BBC BASIC for Windows
Programming >> BBC BASIC language >> Re: HELP! Lots of different errors?
http://bb4w.conforums.com/index.cgi?board=language&action=display&num=1366740319

Re: HELP! Lots of different errors?
Post by admin on Apr 23rd, 2013, 9:38pm

on Apr 23rd, 2013, 6:05pm, coolguy wrote:
the error is "Not in a Procedure"

I would advise adding an END statement before the DEF PROC because as your code stands there's nothing to prevent execution 'falling through' from the main program into the procedure:

Code:
      ENDIF
      END

      DEF PROC_s
      ..... 

If execution does 'fall through' you will receive a 'Not in a procedure' error when it reaches the ENDPROC, so that's the likely explanation.

Richard.
Re: HELP! Lots of different errors?
Post by DDRM on Apr 24th, 2013, 08:26am

Indeed, The REPEAT...UNTIL loop wraps around the outside of the procedure definition.

I suggest you put an END after the UNTIL..., as Richard suggested.

Then you should move the procedure definition to AFTER the END statement. When you call a procedure, BB4W goes off and finds the procedure code and executes it, returning to where it started from when it reaches the ENDPROC, so procedure (and function) definitions should be OUTSIDE the main program loop, where they will never get executed "by mistake", leading to the error you report.

There also appear to be a couple of redundant ENDIF statements: these are only needed when you have a block-structured IF (i.e. if the THEN section is on (a) separate line(s) (also any ELSE statements).

It's not an error, but where you have a set of IF statements relating to essentially the same comparison you might find it clearer to use the CASE statement. In particular, the "cunning use of the CASE statement" Richard describes in the manual, using

CASE TRUE OF:

might work well here.

Best wishes,

David
Re: HELP! Lots of different errors?
Post by coolguy on Apr 24th, 2013, 5:41pm

Thank you very much Richard and David but if i input the values "Strength of player 1 as 50, the strength of player 2 as 2 and the same for the skill values and when the 2 dice are rolled, and player 2 has a higher dice score than player 1, then it still prints that player 2 is dead?? why is this still happening, also when i put the "end ", in, it still says "not in a procedure" and what did you mean by using Case TRUE OF, could you explain?

Regards
A
Re: HELP! Lots of different errors?
Post by admin on Apr 24th, 2013, 9:35pm

on Apr 24th, 2013, 5:41pm, coolguy wrote:
when i put the "end ", in, it still says "not in a procedure"

Strange. You shouldn't get that error if you've made sure execution can't fall through into the procedure. Check that you haven't inadvertently put the END inside a conditional clause such as an IF...ENDIF.

You might want to consider changing the procedure into a function, because that's a nicer way to return the option$ value than using a global variable. Ideally globals should be used only for genuinely 'global' values, not as a way of getting data from a procedure:

Code:
DEF FN_s
LOCAL g, option2$
PRINT "Press R to Restart or D to Draw the game"
REPEAT
  g=GET
UNTIL g=68 OR g=100 OR g=82 OR g=114
IF g=68 OR g=100 THEN
  option2$="Draw"
ELSE
  option2$="Restart"
ENDIF
= option2$ 

With that change, the main REPEAT...UNTIL loop can be terminated using something like:

Code:
UNTIL FN_s = "Draw" 

Richard.

Re: HELP! Lots of different errors?
Post by DDRM on Apr 25th, 2013, 10:17am

Hi Coolguy,

There are a number of problems with your code which you could find by following through with your starting numbers, and thinking EXACTLY what you are doing.

For example, you test who won the fight by testing which die roll was higher,then you print what happens to the strength, skill and score, but you never actually change them!

You then lower both player's strength and skill, regardless of the outcome of the fight, which probably isn't what you mean to do - or is they idea that they gradually get tired out fighting?

Since player 2 is starting with a strength of 2, not getting any boost for winning the fight, and then having lowerstrength2 defined as INT((50-2)/5)=9 subtracted from their strength, they naturally come up as dead.

Incidentally, I note that you define the damage done by losing the fight in terms of the difference between the two players' strength - and that applies to both fighters. Is that actually what you want to do?

You could make the code tidier and easier to follow if you defined C as INT(ABS((strength2%-strength%)/5)) directly: then you wouldn't need to correct it each time you use it. That assumes you are never going to want the non-integer, signed version anywhere in your program.

As I understand it, your program adds extra strength and skill to the winning player, then removes it from both: the net consequence is that the loser goes down and the winner remains constant. That seems a bit convoluted - why not cut out the "middle man"?

Assuming that, and the simplification of C and D, look at this:

Code:
CASE TRUE OF
WHEN x%=y%: REM tie - do nothing
WHEN x%>y%:
REM player 1 has scored a hit: lower scores for player 2
Strength2%-=C
Skill2%-=D
PRINT "Strength and skill for player 2 are now ";Strength2%;" and ";Skill2%; "respectively"
IF Strength2%<=0 THEN PRINT "Player 2 is now dead!":END:REM You might prefer to set a flag here, and not end the program directly
WHEN x%<y%:
REM player 2 has scored a hit: lower scores for player 1
Strength%-=C
Skill%-=D
PRINT "Strength and skill for player 1 are now ";Strength%;" and ";Skill%; "respectively"
IF Strength%<=0 THEN PRINT "Player 1 is now dead!":END
ENDCASE
 


Note that I haven't tested this code, and it may have typos in - but it should be enough for you to get the idea of how using a CASE statement would work. I've also used unary operators, i.e.

Code:
a+=b
REM is equivalent to 
a=a+b
 


If you are still getting a "not in a procedure" error, you must still be falling through into the procedure code. Follow your code through to find out how. I suspect you think you are in a block structured IF statement, but there aren't any in your whole program as it stands in your earlier post, so each line will be executed sequentially from the initial REPEAT to the final UNTIL. If your procedure definition is anywhere in here it will get executed, and crash and burn when you get to the ENDPROC. You need to move it outside the main program loop.

best wishes,

D
Re: HELP! Lots of different errors?
Post by coolguy on Apr 26th, 2013, 5:31pm

Hi, thanks for the suggestions, Richard and D. Richard, when i try to use a Function instead of the Procedure, it comes up with a syntax error, e.g i write THEN FN_s instead of THEN PROC_s... a syntax error appears. Also, i wanted to ask you what code would i use to only allow the user to input a positive number and ask the user to input another number if a negative number is entered. e.g strength value entered is -20 then i imagined the code would be something like:

IF Strength% OR Strength2%<=0 THEN PRINT "Negative strength entered!."

But i'm, not 100% sure abt it.

D, Thank you for spotting errors in my code, so i am able to eradicate them. I have understood the CASE TRUE OF and have figured out another way of solving the problem i had been having smiley. But Thank you very much.

Regards

A
Re: HELP! Lots of different errors?
Post by admin on Apr 26th, 2013, 9:42pm

on Apr 26th, 2013, 5:31pm, coolguy wrote:
when i try to use a Function instead of the Procedure, it comes up with a syntax error

You can't simply replace a procedure call with a function call because they are syntactically quite different. I listed in my previous reply an example of how to call the function; if you had used that it would have worked!

Quote:
IF Strength% OR Strength2%<=0 THEN PRINT "Negative strength entered!."

That's valid syntax, but is it really what you want to do? As shown the message will be printed whenever Strength% is non-zero (even if it's positive).

I think you would benefit from working through the Beginners' Tutorial (you can access it from the Help menu) to boost your level of understanding of the BASIC language.

Richard.