Jump to content
Sign in to follow this  
TXG/MNX

RND function question

Recommended Posts

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?

 

 

Share this post


Link to post
Share on other sites

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
  • Like 3

Share this post


Link to post
Share on other sites

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.

  • Like 2

Share this post


Link to post
Share on other sites

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!)

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites

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.

  • Like 1

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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
  • Like 3

Share this post


Link to post
Share on other sites

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 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.

  • Like 3

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

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

Loading...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...