Jump to content

Photo

RND function question


35 replies to this topic

#26 Zerosquare OFFLINE  

Zerosquare

    River Patroller

  • 2,728 posts
  • Location:France

Posted Mon Aug 6, 2018 1:36 PM

Mersenne twisters have a better randomness indeed, but they're slower. I don't think it's worth it for games :)

#27 Christos ONLINE  

Christos

    Stargunner

  • 1,020 posts
  • Location:Thessaloniki, Greece

Posted Mon Aug 6, 2018 4:35 PM

It depends on the game though. On a turn based rpg it wouldnt matter

#28 Clint Thompson ONLINE  

Clint Thompson

    River Patroller

  • 4,368 posts
  • Kiss Reality Goodbye.
  • Location:Indianapolis, Indiana

Posted Tue Aug 7, 2018 12:04 AM

I now have it pulling from the numbers stored into the array from the (not actually random) random generator (I'll worry about that later) with a counter assigned so that each time it passes (I depress a key, it allows the playback to cycle plus 1), it increases by one and will go up to 8, 16, 32 and displays accordingly on-screen to match the corresponding colors. That's just swell...

 

However, I still don't know how to read from the Jaguar port as an INPUT and wait for user input to check against what is stored in the array. Normally it would be INPUT A$ whatnot and in this case I can't replace that with the jagpad_1 BAND whatever because it obviously doesn't work. Or am I supposed to only look at this system as a constant input and build around that only?

 

Probably overtired and overthinking it as if it should be in a separate subroutine, but maybe not?

 

Also, is there a trick to negative counters? I was trying to have the program display 1, 2, 3 sequence from memory but deduct from a separate counter so that as long as it matched 1 from the main counter for seq1 and was 1 for the input counter, it would display. The main counter is working just fine. I've tried a dozen things with the negative counter but can't seem to get it to work in conjunction with. More or less I'm asking to make sure there's no known issues or bugs going into a negative as it cycles, may it be from sub routines or user inputs?

 

 



#29 ggn OFFLINE  

ggn

    Stargunner

  • 1,399 posts
  • Location:Athens, Greece

Posted Tue Aug 7, 2018 2:33 AM

However, I still don't know how to read from the Jaguar port as an INPUT and wait for user input to check against what is stored in the array. Normally it would be INPUT A$ whatnot and in this case I can't replace that with the jagpad_1 BAND whatever because it obviously doesn't work. Or am I supposed to only look at this system as a constant input and build around that only?
 
Probably overtired and overthinking it as if it should be in a separate subroutine, but maybe not?


So when you type INPUT A$ in common basic dialects, what they actually do is freeze the main program and wait for user input before giving control back. So let's just do that here:
 
dim pad as LONG
ZEROPAD()
pad=zero_left_pad
do until (pad band 0xffbefbf)<>0
    ZEROPAD()
    pad=zero_left_pad
loop
So what this does is: a) do an initial read of the pad values, b) go into an infinite loop checking if any button was pressed, and only then break the loop.

You might wonder what's that dark arts "pad band 0xffbefbf" about? Normally to check if anything was pressed we'd simply have to do something like (pad<>0) since no button press would mean zero, right? Well, it turns out that there are some "hidden" buttons on each jagpad (which IIRC have to do with teamtaps) that are set at all times. Our condition then has to be rewritten to "(pad band -Input_Pad_C1<>0) band (pad band -Input_Pad_C2<>0) band (pad band -Input_Pad_C3<>0)" or something like that (haven't tested this!), which is a bit long! So instead using boolean math we can convert this to "pad band -(Input_Pad_C1 bor Input_Pad_C2 bor Input_Path_C3)". In turn this boils down to the magic value of 0xffbefbf.
 

Also, is there a trick to negative counters? I was trying to have the program display 1, 2, 3 sequence from memory but deduct from a separate counter so that as long as it matched 1 from the main counter for seq1 and was 1 for the input counter, it would display. The main counter is working just fine. I've tried a dozen things with the negative counter but can't seem to get it to work in conjunction with. More or less I'm asking to make sure there's no known issues or bugs going into a negative as it cycles, may it be from sub routines or user inputs?


There are a couple of ways to count down negatively. If I understand you correctly you want to do a for/next counting down? Then you can use any of these

for i=10 to 0 step -1
 ...
next i
for i=0 to 10
 counter=10-i   'use this variable, not i!
 ...
next i


#30 Zerosquare OFFLINE  

Zerosquare

    River Patroller

  • 2,728 posts
  • Location:France

Posted Tue Aug 7, 2018 2:38 AM

Careful, that minus sign in your expression should be a NOT. In other words, to mask out bits, you need one's complement, not two's complement.

#31 ggn OFFLINE  

ggn

    Stargunner

  • 1,399 posts
  • Location:Athens, Greece

Posted Tue Aug 7, 2018 6:04 AM

Careful, that minus sign in your expression should be a NOT. In other words, to mask out bits, you need one's complement, not two's complement.


(haven't tested this!)



#32 Clint Thompson ONLINE  

Clint Thompson

    River Patroller

  • 4,368 posts
  • Kiss Reality Goodbye.
  • Location:Indianapolis, Indiana

Posted Tue Aug 7, 2018 8:01 AM

dim pad as LONG
ZEROPAD()
pad=zero_left_pad
do until (pad band 0xffbefbf)<>0
    ZEROPAD()
    pad=zero_left_pad
loop

 

Awesome, thanks.

 

So two questions with this (you answer one then I ask two, sorry)

 

1. This loop can be in its own sub routine and loop endlessly within itself...

 

2. ...loop until counter condition = x number then jump back to main game OR if x value = xx THEN go gameover (I'm wording this very loosely I know)

 

I'm realizing there's multiple ways to go about this now and don't really care which is longer or harder just as long as I can do it.

 

So, it would probably just be easier to set it up all as counter based instead of waiting for input?

 

As in - pull random numbers from array, each cycle have it deduct or add to that specific color, have computer check to see if value has been met with that each subsequent depress otherwise gameover. I feel like reading the joystick and writing it into its own array in sequence then reading back and checking it against random generated array may be more difficult than just doing counters in any given direction based on the 4 colors.

 

I'll mess around some more over this next week and see if I can't get it. Thanks again for the help!



#33 sh3-rg OFFLINE  

sh3-rg

    River Patroller

  • 3,396 posts
  • doge + tie = dothemath
  • Location:BOLTON, England

Posted Tue Aug 7, 2018 9:33 AM

You'd normally have a game loop and call the pad reading once per screen update, rather than having it sit and wait for some kind of input, as usually there's more going on than all stop and idling until someone presses B or whatever.

#34 Clint Thompson ONLINE  

Clint Thompson

    River Patroller

  • 4,368 posts
  • Kiss Reality Goodbye.
  • Location:Indianapolis, Indiana

Posted Sun Aug 12, 2018 4:42 AM

I've spent the night on a dead end and I just don't get it. While this is very obviously the hardest way to do it (subjectively so, if it works it works) and obviously it doesn't because I'm here again haha... but, how come this doesn't work or what do I have to do to make this work:

SUB CHECKSIM

	ZEROPAD()
	pad=zero_left_pad
	do until (pad band 0xffbefbf)<>0
		
					
IF simonvalues[1]=1 AND pad band Input_Pad_Right THEN
CALL RIGHT
ENDIF

IF simonvalues[1]=1 AND pad band Input_Pad_Down THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=1 AND pad band Input_Pad_Up THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=1 AND pad band Input_Pad_Left THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=2 AND pad band Input_Pad_Right THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=2 AND pad band Input_Pad_Down THEN
CALL DOWN
ENDIF

IF simonvalues[1]=2 AND pad band Input_Pad_Up THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=2 AND pad band Input_Pad_Left THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=3 AND pad band Input_Pad_Right THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=3 AND pad band Input_Pad_Down THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=3 AND pad band Input_Pad_Up THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=3 AND pad band Input_Pad_Left THEN
CALL LEFT
ENDIF

IF simonvalues[1]=4 AND pad band Input_Pad_Right THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=4 AND pad band Input_Pad_Down THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=4 AND pad band Input_Pad_Up THEN
CALL UP
ENDIF

IF simonvalues[1]=4 AND pad band Input_Pad_Left THEN
CALL GAMELOSE
ENDIF


IF FRCOUNT=2 THEN 
CALL gamestart
ENDIF

**here I would repeat the top portion pulling from simonvalues 2 - 8+ and continue to increase the FRCOUNT variable by +1 (which is added each time the game plays back an array loop)
so it'll match that of the playback on-screen. and then, if FRCOUNT=8 goes to winscreen (which I would later change with X DIM variable so that it can increase to 16, 32, etc.)**

IF FRCOUNT=8
CALL GAMEWIN
ENDIF

loop


#35 ggn OFFLINE  

ggn

    Stargunner

  • 1,399 posts
  • Location:Athens, Greece

Posted Sun Aug 12, 2018 2:53 PM


dim correctmask[4] as long
correctmask[1]=Input_Pad_Right
correctmask[2]=Input_Pad_Down
correctmask[3]=Input_Pad_Left
correctmask[4]=Input_Pad_Up


if pad band correctmask[simon[1]] then
  call direction_dispatch(pad)
else
  call gamelose
endif
 
 
function direction_dispatch(direction as int)
 
    select case (direction band (Input_Pad_Right bor Input_Pad_Left bor Input_Pad_Down bor Input_Pad_Up))
 
    case Input_Pad_Right
       
    case Input_Pad_Left
 
    case Input_Pad_Down
 
    case Input_Pad_Up
 
    end select
   
end function
 
This should work!

(I'm on vacation so I'll refrain from posting lengthy explanations for now)

Edited by ggn, Sun Aug 12, 2018 2:54 PM.


#36 ggn OFFLINE  

ggn

    Stargunner

  • 1,399 posts
  • Location:Athens, Greece

Posted Mon Aug 27, 2018 4:09 AM

Ok, so here's the bit more elaborate explanation for the source above:

What I essentially tried to do was to convert that huge block of if/call statements you had in the code you posted into something more compact. So let's examine a small part of your code:
 
IF simonvalues[1]=1 AND pad band Input_Pad_Right THEN
CALL RIGHT
ENDIF

IF simonvalues[1]=1 AND pad band Input_Pad_Down THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=1 AND pad band Input_Pad_Up THEN
CALL GAMELOSE
ENDIF

IF simonvalues[1]=1 AND pad band Input_Pad_Left THEN
CALL GAMELOSE
ENDIF
So this essentially calls RIGHT if and only if simonvalues[1]=1 and pad has Input_Pad_Right, else it calls GAMELOSE. Right? So we can rewrite this code as:
 
IF simonvalues[1]=1 then
  IF pad band Input_Pad_Right THEN
    CALL RIGHT
  ELSE
    CALL GAMELOSE
  ENDIF
ENDIF
Have another read at it, as it should be directly equivalent to the code above. The second 'if' executes only when simonvalues[1]=1. So then we only have to check if pad contains the Input_Pad_Right bitmask. Otherwise it doesn't so the player loses.

This way we can compress all 4 blocks of your code in 4 times my block of code above.
 
IF simonvalues[1]=1 then
  IF pad band Input_Pad_Right THEN
    CALL RIGHT
  ELSE
    CALL GAMELOSE
  ENDIF
ENDIF
IF simonvalues[1]=2 then
  IF pad band Input_Pad_Down THEN
    CALL RIGHT
  ELSE
    CALL GAMELOSE
  ENDIF
ENDIF
IF simonvalues[1]=3 then
  IF pad band Input_Pad_Left THEN
    CALL RIGHT
  ELSE
    CALL GAMELOSE
  ENDIF
ENDIF
IF simonvalues[1]=4 then
  IF pad band Input_Pad_Up THEN
    CALL RIGHT
  ELSE
    CALL GAMELOSE
  ENDIF
ENDIF
But still that's a lot of code!

So, we notice that the 4 if/endif blocks are nearly the same. The only thing that changes is simonvalues[1], the Pad_Input____ value and which subroutine to call (RIGHT/DOWN/LEFT/UP). That's where correctmask table comes in.
 
dim correctmask[4] as long
correctmask[1]=Input_Pad_Right
correctmask[2]=Input_Pad_Down
correctmask[3]=Input_Pad_Left
correctmask[4]=Input_Pad_Up


if pad band correctmask[simonvalues[1]] then
  call direction_dispatch(pad)
else
  call gamelose
endif
 
Let's step through the revised if block, from innermost compexity to outermost. First of all, we assume simonvalues[i] will evaluate to 1,2,3 or 4. This will be used as an index to correctmask table, which will give us the value Input_Pad_Right/Down/Left/Up. Then we band it with pad and call direction_dispatch if it's true (non-zero). Why does is this equivalent to the above code?

Each of the 4 rewritten if blocks above only has one shot at not calling GAMELOSE. If simonvalues[1]=1 then the only mask to band and would yield a correct result is Input_Pad_Right. And this is the value correctmask[simonvalues[1]] will give us in this case! So we cut down on the checks this way.

Finally, when we reach direction_dispatch we know that we have a correct answer so we simply check the pad value and call the appropriate subroutine depending on input.



Hopefully this explanation makes things more clear!

Explaining the code here made me realise I made a few oopsies:

a) dim correctmask[4] should be dim correctmask[5] - dim is 0 indexed so it counts as an index. We use 1-4 but 0 is unused but still takes up memory!
b) I don't check if simonvalues[1] is between 1 and 4 inclusive. That could also lead to problems if it's (for example) 5!
c) If the player hits any other button than up/down/left/right (for example the C button) this code will also call gamelose. Not sure if you want this behaviour or not.
d) Diagonal movement can also lead to correct guess (for example if the correct answer is up and the player does up-left on the d-pad)


Hopefully all this makes sense now.



Reply to this topic



  


0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users