Generating random direction in C64 Basic - random

I have run the ‘More Bouncing Balls’ Basic program from chapter 5 of the C64 user’s manual, with the addition from the final page of the chapter. The code is as follows:
10 PRINT CHR$(147):REM SHIFT CLR/HOME
20 POKE 53280,7 : POKE 53281,13
30 X=1:Y=1
40 DX=1:DY=1
50 POKE 1024 + X + 40*Y, 81
60 FOR T=1 TO 10: NEXT T
70 POKE 1024 + X + 40*Y, 32
80 X=X+DX
90 IF X=0 OR X=39 THEN DX=-DX
100 Y=Y+DY
110 IF Y=0 OR Y=24 THEN DY=-DY
120 GOTO 50
To this were added the lines at the end, ɔ:
21 FOR L=1 TO 10
25 POKE 1024+INT(RND(1)*1000),160
27 NEXT L
85 IF PEEK(1024+X+40*Y)=160 THEN DX=-DX:GOTO 80
105 IF PEEK(1024+X+40*Y)=160 THEN DY=-DY:GOTO 100
These lines are not relevant to the question, but I included them for sake of completeness.
I wanted to add randomness to the direction of the ball (chr$(81)), and noticed that by changing DX and DY to other numbers, I would get it to move at angles other than 45°; of course, having both DX and DY set to 1, would have them both ‘push’ the ball in perpendicularly opposite directions, ɔ: halfway between both, equalling 45°.
But when trying to use a random number, I would get truly odd behaviour. I assumed the number had to be between 0 and 1, and so tried (INT(10*RND(1))+1)/10, and changed line 40 to set DX and DY to this random number. What I got instead was some very odd behaviour. The ball would move very fast at a predictable angle, disappearing at the right side and reappearing on the left, moving a few lines down, then disappearing completely, then turning up on top of the screen drawing unmoving balls one after another horizontally, then crash.
When instead setting DX or DY to an integer, i.e. 2, I would still get some strange behaviour, such as the ball disappearing at one end and reappearing at the opposite, and on this occasion the program would end after a few seconds.
What is causing this erratic behaviour? And how can I set the parameters in line 40 to allow the ball to move in different directions (kind of like in Pong) when it hits a wall?
Note 1: When changing DX and DY in lines 80 and 100 instead, I got some interesting jittering movement, but as expected, as though the ball drawn on-screen was an uneven sphere.
Note 2: I am aware one generally should not include tags in titles, but was unsure whether the question would be too unsearchable if I left them out. Feel free to edit the title if need be; I am happy to be educated.

I modified the program in this way:
1-DX is step for X.
2-DY is step for Y.
2-VX is direction of X, -1 left and +1 rigth.
3-XY is direction of Y, -1 up and +1 down.
3-When Bouncing Ball angle changes randomly (subroutine 300)
Calculation of DX and DY is for a right triangle with hypotenuse of 1 (one).
4-When plotting use only integer numbers so the "ball" doesn't have odd moves.
5-Control off limits, so "ball" doesn't disappear.
5 rem 2018-08-24 bouncing balls
6 rem https://stackoverflow.com/questions/51907035
7 rem /generating-random-direction-in-c64-basic
10 print chr$(147);:rem shift+clr/home=clear screen
20 poke 53280,7:poke 53281,13
25 rem random initial position
40 p=rnd(1)*40:x=p
45 q=rnd(1)*25:y=q
50 gosub 300
60 rem vector direction
70 vx=(rnd(1)<0.5):if vx>=0 then vx=1
80 vy=(rnd(1)<0.5):if vy>=0 then vy=1
100 rem plot
110 poke 1024+int(p)+40*int(q),32
120 poke 1024+int(x)+40*int(y),81
130 for t=1 to 30:next t
140 p=x:q=y
150 x=x+dx*vx
160 ca=0:rem change angle
170 if x<=0 or x>=39 then vx=-vx:ca=-1
175 if x<0 then x=0
176 if x>39 then x=39
180 y=y+dy*vy
190 if y<=0 or y>=24 then vy=-vy:ca=-1
195 if y<0 then y=0
196 if y>24 then y=24
200 if ca then gosub 300
210 goto 100
300 rem random angle between 15 and 75 d
egrees
305 rem a=angle in degrees r=radians
310 a=15+rnd(1)*(75-15+1):r=a*{pi}/180
320 dx=cos(r)
330 dy=sin(r)
340 return
On C64 replace {pi} using SHIFT+UP_ARROW.
If line 110 is REM then you can see the walk.

I modified the program so:
- Start position X and Y are random
- Direction DX and DY are random, values -1 or +1
10 PRINT CHR$(147):REM SHIFT CLR/HOME
20 POKE 53280,7:POKE 53281,13
25 REM RANDOM INITIAL POSITION
30 X=INT(RND(1)*39)+1:Y=INT(RND(1)*24)+1
35 REM RANDOM DIRECTION
40 DX=(RND(1)<0.5):IF DX>=0 THEN DX=1
45 DY=(RND(1)<0.5):IF DY>=0 THEN DY=1
50 POKE 1024+X+40*Y,81
60 FOR T=1 TO 30:NEXT T
70 POKE 1024+X+40*Y,32
80 X=X+DX
90 IF X<=0 OR X>=39 THEN DX=-DX
100 Y=Y+DY
110 IF Y<=0 OR Y>=24 THEN DY=-DY
120 GOTO 50

Related

Issue with Lua Random Number Generation in Loops

I have a script for a rock-paper-scissors (RPS) game I am making, and I am trying to generate a random number to determine a series of RPS moves. The logic is as follows:
moves = {}
table.insert(moves, 'rock')
table.insert(moves, 'paper')
table.insert(moves, 'scissors')
currentMoves = {}
math.randomseed(playdate.getSecondsSinceEpoch()) -- game SDK library function that returns seconds since midnight January 1 2000 UTC to initialize new random sequence
math.random(); math.random(); math.random();
-- generates a list of rps moves to display on the screen
function generateMoves(maxMovesLength) -- i set maxMovesLength to 3
currentMoves = {}
for i = 1, maxMovesLength, 1 do
randomNumber = math.random(1, 3)
otherRandomNumber = math.random(1,99) -- even with this, based on the presumption 1~33 is rock, 34~66 is paper, 67~99 is scissors, I get a suspicious number of 3 of the same move)
print(otherRandomNumber)
table.insert(currentMoves, moves[randomNumber])
end
return currentMoves
end
However, I noticed that using the Lua math.random() function, I seem to be getting a statistically unlikely number of series of 3 of the same RPS move. The likelihood of getting 3 of the same move (rock rock rock, paper paper paper, or scissors scissors scissors) should be about 11%, but I am getting sets of 3 much more often.
For example, here is what I got when I set maxMovesLength to 15:
36 -paper
41 -paper
60 -paper
22 -rock
1 -rock
2 -rock
91 -scissors
36 -paper
69 -scissors
76 -scissors
35 -paper
18 -rock
22 -rock
22 -rock
92 -scissors
From this sample, it seems that sets of 3 of a kind are happening much more often than they should be. There are 13 series of 3 moves in this list of 15 moves, and among those 3/13 are three of a kind which would be a probability of about 23%, higher than the expected statistical probability of 11%.
Is this just a flaw in the Lua math library?
It seems that when setting maxMovesLength to a very high number this issue doesn't exist, so I will just call math.random() a bunch of times before I actually use it in my game (more than the 3 times I currently do under randomseed().

Slideshow Algorithm

I need to design an algorithm for a photo slideshow that is constantly receiving new images, so that the oldest pictures appear less in the presentation, until a balance between the old photos and those that have appeared.
I have thought that every image could have a counter of the number of times they have been shown and prioritize those pictures with the lowest value in that variable.
Any other ideas or solutions would be well received.
You can achieve an overall near-uniform distribution (each image appears about the same number of times for the long run), but I wouldn't recommend doing it. Images that were available early would appear very very rarely later on. A better user experience would be to simply choose a random image from all the available images at each step.
If you still want near-uniform distribution for the long run, you should set the probability for any image based on the number of times it appeared so far. For example:
p(i) = 1 - count(i) / (max_count() + epsilon)
Here is a simple R code that simulates such process. 37 random images are selected before a new image becomes available. This process is repeated 3000 times:
h <- 3000 # total images
eps <- 0.001
t <- integer(length=h) # t[i]: no. of instances of value i in r
r <- c() # proceded vector of indexes of images
m <- 0 # highest number of appearances for an image
for (i in 1:h)
for (j in 1:37) # select 37 random images in range 1..i
{
v <- sample(1:i, 1, prob=1-t[1:i]/(m+eps)) # select image i with weight 1-t[i]/(m+eps)
r <- c(r, v) # add to output vector
t[v] <- t[v]+1 # update appearances count
m <- max(m, t[v]) # update highest number of appearances
}
plot(table(r))
The output plot shows the number of times each image appeared:
epsilon = 0.001:
epsilon = 0.0001:
If we look, for example at the indexes in the output vector in which, say, image #3 was selected:
> which(r==3)
[1] 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
[21] 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 1189 34767 39377
[41] 70259
Note that if epsilon is very small, the sequence will seem less random (newer images are much preferred). For the long run however, any epsilon will do.
Instead of a view counter, you could also try basing your algorithm on the timestamp that images were uploaded.

Detecting axis for Sphero Collisions

I am having real troubles trying to figure out which axis was impacted using the collision detection and the MAC SDK. I can't seem to get any data that makes sense. I have integrated the sample keydrive with collision detection to try and make sense of the collision data that is returned. It seems to be able to detect the collisions ok but the return power values for the x and y axis don't seem to be consistent. Using this little bit of code in my async method:
if ([asyncData isKindOfClass:[RKCollisionDetectedAsyncData class]]) {
RKCollisionDetectedAsyncData *collisionData = (RKCollisionDetectedAsyncData *)asyncData;
xPower = collisionData.impactPower.x;
yPower = collisionData.impactPower.y;
NSLog(#"X Power: %u",collisionData.impactPower.x);
NSLog(#"Y Power: %u",collisionData.impactPower.y);
[RKRollCommand sendStop];
}
I have an output for y collisions of:
2014-01-17 17:16:43.734 KeyDrive[16537:303] X Power: 15
2014-01-17 17:16:43.734 KeyDrive[16537:303] Y Power: 113
2014-01-17 17:16:47.360 KeyDrive[16537:303] X Power: 11
2014-01-17 17:16:47.360 KeyDrive[16537:303] Y Power: 130
and for x collisions:
2014-01-17 17:17:36.921 KeyDrive[16542:303] X Power: 25
2014-01-17 17:17:36.922 KeyDrive[16542:303] Y Power: 130
2014-01-17 17:17:39.862 KeyDrive[16542:303] X Power: 18
2014-01-17 17:17:39.868 KeyDrive[16542:303] Y Power: 116
then I have all my thresholds currently set at:
uint8_t xThreshold = 100;
uint8_t yThreshold = 100;
uint8_t xSpeedThreshold = 100;
uint8_t ySpeedThreshold = 100;
float deadZone = 1.0f;
but I have used many different variations to get some sort of consistency with no luck. Anyone have any advice?
EDIT:
So i tried out the new solution. My test environment was dumbed down to try and solidify my findings. I kept the sphero in place not moving and struck it on the different axes. Although the results were a bit more hopeful, they are still not too reliable. see my results below. I did multiple strikes on every axis with differing results specifically on the y axis. Maybe my y axis accelerometer is a dud?
X+
**Impact** **Accel**
X Y X Y
34 8 0.88208 0.218262
55 3 1.381592 0.092529
33 1 0.861572 -0.046875
58 3 1.376953 0.035645
68 3 1.380371 0.094238
X-
**Impact** **Accel**
X Y X Y
57 3 -1.351074 0.026123
38 2 -0.91748 0.050781
57 0 -1.228271 0.025391
59 5 -1.395264 0.178711
40 2 -0.910156 0.005615
Y+
**Impact** **Accel**
X Y X Y
5 31 0.436523 0.638672
6 31 -0.13623 0.390869
18 40 0.39502 0.661621
26 35 0.647461 0.538818
14 46 0.154297 0.770508
Y-
**Impact** **Accel**
X Y X Y
6 32 0.549805 -0.579834
21 30 0.692383 -0.614014
5 31 0.149414 -0.508301
24 30 0.449463 -0.413574
9 31 0.68457 -0.682861
I think that the reason you are seeing these numbers is due to the example you are using. I read that you are using the key drive example, with modifications to create these results. The problem with that is, that when you press a key, the ball TURNS then goes in the indicated direction. Therefore the ball, with respect to its accelerometer, is always being hit in the same direction, causing those kinds of results up there. Now if you wanted to see the different axes you would need to develop a way to cause an impact on the side of the ball perpendicular to where the tail light is, which usually is not something achievable while it's moving (unless you hit it from the side while it's driving).

Contour Lines Algorithm

This could very well be a duplicate, but I could not seem to find something specific to my problem.
I have a xy grid in a picture box. Each grid cell has a specific mass. I would like to create contour lines on this xy grid based on the mass.
Does anyone have any ideas to a good algorithm to perform this task? I am trying to get this done in VB6 but any algorithm would do.
Edit
Contour Grid
I have a grid. I want to display contour lines based on mass (IE, the cells with more than one point in them will be heavier in mass)
This question's a bit stale, but so's my experience: I did something like this almost 30 years ago.
This produces simple contours on a bitmap:
Calculate the field-strength at each point in the grid (I'm assuming you're trying to plot something like gravitational field contours based on the masses of the points).
Colour the alternate spaces between contour lines (which you haven't got yet) in two alternate colours. e.g. if the contour lines should be 100 units (of field-strength) apart then choose the colour of each pixel based on ToInt(pixel_field_strength / 100) % 2.
Trace the edges of the colour boundaries to produce contours. For example, if your two colours are white and black, then only retain white pixels adjacent to a black pixel.
If you're just interested in the results, use a library as suggested in the comments.
Purely for nostalgia's sake, I found my original BBC BASIC code. It still runs on modelb (a BBC Micro emulator).
10 REM THIS COMES WITH NO WARRANTY!
20
30 REM Gravity field
40
50 MODE 1
60 PROCsetup
70 FOR Y%=300 TO 900 STEP 4
80 FOR X%=200 TO 800 STEP 4
90 R=LOG(FNforce(X%,Y%))
100 GCOL0,((R*10) MOD 2)+1
110 PLOT69,X%,Y%
120 NEXT
130 NEXT
140 PROCcontour
150 VDU19,1,0,0,0,0
160 VDU19,2,0,0,0,0
170 END
180 DEFPROCsetup
190 N%=5
200 DIM X%(N%),Y%(N%),M%(N%)
210 FOR P%=1 TO N%
220 READ X%(P%),Y%(P%),M%(P%)
230 NEXT
240 ENDPROC
250 DATA 625,625,1000000
260 DATA 425,725,1000000
270 DATA 475,425,1000000
280 DATA 375,575,1000000
290 DATA 725,525,1000000
300 DEFFNforce(X,Y)
310 P=0
320 FOR P%=1 TO N%
330 DX=X%(P%)-X:DY=Y%(P%)-Y
340 R=SQR(DX*DX+DY*DY)
350 P=P+M%(P%)/R
360 NEXT
370 =P
380 DEFPROCcontour
390 GCOL0,3
400 FOR Y%=300 TO 900 STEP 4
410 FOR X%=200 TO 800 STEP 4
420 IF POINT(X%,Y%)=1 AND (POINT(X%+4,Y%)=2 OR POINT(X%-4,Y%)=2 OR POINT(X%,Y%+4)=2 OR POINT(X%,Y%-4)=2) THEN PLOT69,X%,Y%
430 NEXT
440 NEXT
450 ENDPROC

How to optimize the layout of rectangles

I have a dynamic number of equally proportioned and sized rectangular objects that I want to optimally display on the screen. I can resize the objects but need to maintain proportion.
I know what the screen dimensions are.
How can I calculate the optimal number of rows and columns that I will need to divide the screen in to and what size I will need to scale the objects to?
Thanks,
Jamie.
Assuming that all rectangles have the same dimensions and orientation and that such should not be changed.
Let's play!
// Proportion of the screen
// w,h width and height of your rectangles
// W,H width and height of the screen
// N number of your rectangles that you would like to fit in
// ratio
r = (w*H) / (h*W)
// This ratio is important since we can define the following relationship
// nbRows and nbColumns are what you are looking for
// nbColumns = nbRows * r (there will be problems of integers)
// we are looking for the minimum values of nbRows and nbColumns such that
// N <= nbRows * nbColumns = (nbRows ^ 2) * r
nbRows = ceil ( sqrt ( N / r ) ) // r is positive...
nbColumns = ceil ( N / nbRows )
I hope I got my maths right, but that cannot be far from what you are looking for ;)
EDIT:
there is not much difference between having a ratio and the width and height...
// If ratio = w/h
r = ratio * (H/W)
// If ratio = h/w
r = H / (W * ratio)
And then you're back using 'r' to find out how much rows and columns use.
Jamie, I interpreted "optimal number of rows and columns" to mean "how many rows and columns will provide the largest rectangles, consistent with the required proportions and screen size". Here's a simple approach for that interpretation.
Each possible choice (number of rows and columns of rectangles) results in a maximum possible size of rectangle for the specified proportions. Looping over the possible choices and computing the resulting size implements a simple linear search over the space of possible solutions. Here's a bit of code that does that, using an example screen of 480 x 640 and rectangles in a 3 x 5 proportion.
def min (a, b)
a < b ? a : b
end
screenh, screenw = 480, 640
recth, rectw = 3.0, 5.0
ratio = recth / rectw
puts ratio
nrect = 14
(1..nrect).each do |nhigh|
nwide = ((nrect + nhigh - 1) / nhigh).truncate
maxh, maxw = (screenh / nhigh).truncate, (screenw / nwide).truncate
relh, relw = (maxw * ratio).truncate, (maxh / ratio).truncate
acth, actw = min(maxh, relh), min(maxw, relw)
area = acth * actw
puts ([nhigh, nwide, maxh, maxw, relh, relw, acth, actw, area].join("\t"))
end
Running that code provides the following trace:
1 14 480 45 27 800 27 45 1215
2 7 240 91 54 400 54 91 4914
3 5 160 128 76 266 76 128 9728
4 4 120 160 96 200 96 160 15360
5 3 96 213 127 160 96 160 15360
6 3 80 213 127 133 80 133 10640
7 2 68 320 192 113 68 113 7684
8 2 60 320 192 100 60 100 6000
9 2 53 320 192 88 53 88 4664
10 2 48 320 192 80 48 80 3840
11 2 43 320 192 71 43 71 3053
12 2 40 320 192 66 40 66 2640
13 2 36 320 192 60 36 60 2160
14 1 34 640 384 56 34 56 1904
From this, it's clear that either a 4x4 or 5x3 layout will produce the largest rectangles. It's also clear that the rectangle size (as a function of row count) is worst (smallest) at the extremes and best (largest) at an intermediate point. Assuming that the number of rectangles is modest, you could simply code the calculation above in your language of choice, but bail out as soon as the resulting area starts to decrease after rising to a maximum.
That's a quick and dirty (but, I hope, fairly obvious) solution. If the number of rectangles became large enough to bother, you could tweak for performance in a variety of ways:
use a more sophisticated search algorithm (partition the space and recursively search the best segment),
if the number of rectangles is growing during the program, keep the previous result and only search nearby solutions,
apply a bit of calculus to get a faster, precise, but less obvious formula.
This is almost exactly like kenneth's question here on SO. He also wrote it up on his blog.
If you scale the proportions in one dimension so that you are packing squares, it becomes the same problem.
One way I like to do that is to use the square root of the area:
Let
r = number of rectangles
w = width of display
h = height of display
Then,
A = (w * h) / r is the area per rectangle
and
L = sqrt(A) is the base length of each rectangle.
If they are not square, then just multiply accordingly to keep the same ratio.
Another way to do a similar thing is to just take the square root of the number of rectangles. That'll give you one dimension of your grid (i.e. the number of columns):
C = sqrt(n) is the number of columns in your grid
and
R = n / C is the number of rows.
Note that one of these will have to ceiling and the other floor otherwise you will truncate numbers and might miss a row.
Your mention of rows and columns suggests that you envisaged arranging the rectangles in a grid, possibly with a few spaces (e.g. some of the bottom row) unfilled. Assuming this is the case:
Suppose you scale the objects such that (an as-yet unknown number) n of them fit across the screen. Then
objectScale=screenWidth/(n*objectWidth)
Now suppose there are N objects, so there will be
nRows = ceil(N/n)
rows of objects (where ceil is the Ceiling function), which will take up
nRows*objectScale*objectHeight
of vertical height. We need to find n, and want to choose the smallest n such that this distance is smaller than screenHeight.
A simple mathematical expression for n is made trickier by the presence of the ceiling function. If the number of columns is going to be fairly small, probably the easiest way to find n is just to loop through increasing n until the inequality is satisfied.
Edit: We can start the loop with the upper bound of
floor(sqrt(N*objectHeight*screenWidth/(screenHeight*objectWidth)))
for n, and work down: the solution is then found in O(sqrt(N)). An O(1) solution is to assume that
nRows = N/n + 1
or to take
n=ceil(sqrt(N*objectHeight*screenWidth/(screenHeight*objectWidth)))
(the solution of Matthieu M.) but these have the disadvantage that the value of n may not be optimal.
Border cases occur when N=0, and when N=1 and the aspect ratio of the objects is such that objectHeight/objectWidth > screenHeight/screenWidth - both of these are easy to deal with.

Resources