Hi Jim,
This upgrade contains several improvements:
Source: http://basic256.blogspot.ro/2014/03/minimalist-version-of-flappy-bird-work.html
Author: Manuel Santos
Please, run the game below. Loose one life. Then finish level.
# Minimalist version of flappy bird, Work in progress # Click to jump graphsize 600,400 fastgraphics Dim obstaclehight(10) lifes=3 for level = 1 to 5 # Generate obstacles for n = 0 to 9 obstaclehight[n] = 150+ int(rand*(10+40*level))-20*level next n # restart point after losing a life start: birdy=200 dy=-1 # End game code if lifes = 0 then color black font "arial",50,50 text 50,50,"End" refresh end end if pause 1 # Running code for x = 1 to 2200 step 1 color yellow rect 0,0,600,400 color black font "arial",50,50 text 50-x,50,"Level:"+(level) if level < 5 then text 2200-x,50,"Level:"+(level+1) if level = 5 then text 2200-x,50,"End" # Drawing columns for n = 0 to 9 color darkgreen rect 300+n*200-x,0,50,400 color yellow rect 300+n*200-x,obstaclehight[n],50,100 # Ball death if 300+n*200-x=50 or 300+n*200-x=0 then if birdy < obstaclehight[n] or birdy > obstaclehight[n]+100 then lifes=lifes-1 goto start end if end if next n # Ball draw color red circle 50,birdy,10 color white circle 52,birdy-2,3 color black circle 53,birdy-2,2 rect 56,birdy+2,5,3 color black font "arial",20,100 text 10,10,"Lifes"+lifes # Movement birdy=birdy+dy dy=dy+.015 if clickx>0 then dy=-1 clickclear refresh #wait to make playable pause .01 next x next level end
C'mon, run the game above. Loose one life. Then finish level.
Youl will get this error: ERROR on line 69: Variable in NEXT does not match FOR.
If we strip the program we get:
for level = 1 to 5 start: # Running code for x = 1 to 2200 step 1 # Drawing columns for n = 0 to 9 # Ball death if ..... then goto start end if next n # Ball draw next x next level end
The problem appear when progam execute the # Ball death
part.
In this moment BASIC256 has in ForNext stack: FOR level, FOR x, FOR n.
goto start
makes BASIC256 to jump atstart:
and to run from there... it is quite ok this.
BASIC256 encouter FOR x and add it to the stack...
The ForNext stack looks like: FOR level, FOR x, FOR n, FOR x
And so on...
At the end of level, BASIC256 has been deleted all finished FOR/NEXT and execute next level
.
But wait... in the stack there are multiple unfinished FOR/NEXT...
It expects a FOR level in stack but it get another unfinished FOR/NEXT.
BASIC256 as any BASIC language is a wonderful language that allows spagetti code.
And so it must remain.
However...
The FOR/NEXT implementation in BASIC256 is not like the old BASIC language.
10 FOR A = 1 TO 10 20 IF INKEY$ = "A" THEN NEXT A .... 50 NEXT A
It is more closed to all others loops/statements like WHILE, UNTIL, IF... that are using blocks.
FOR A = 1 TO 10 ... NEXT A
NEXT A
is in fact the end of block and cannot be used like old style (see line 20 in first example).
It is ok like this. The programming style is consistent and unitary.
So, NEXT A
will allways match FOR A
. At compiling time even the variable used in both cases is checked to match.
So, a NEXT
will refer to an unique FOR
from the program.
To avoid situations like one from Flappy Ball
, BASIC256 should add a FOR
in ForNext stack ONLY if this unique FOR
do not already exist into stack.
Also, any NEXT
should not expect to find its pair FOR
to be always the last one into ForNext stack.
If is not last it sould serch if there is in stack.
FIXED
Also drop the ERROR_NEXTWRONGFOR ("Variable in NEXT does not match FOR") error message because it is verify at compiling time.
Make also ERROR_NEXTWRONGFOR to be trapable ("Next without FOR" - when FOR is removed from stack and user jumps to its NEXT)
Check for errors in multiple situations FOR/NEXT.
Also change the text that asking user to input the number -3.14 in testsuitearrayinclude by usinng the correct localized decimal point.
Create this file to be INCLUDEd:
mystuff.kbs
subroutine divide(a, b) #rem next line will generate an error print a/b end subroutine
Now, run the main program:
include "mystuff.kbs" call divide(0, 0)
Before (error message): ERROR on line 3: Division by zero. (because calling subroutine skips OP_INCLUDEFILE)
After (error message): ERROR in included file 'mystuff.kbs' on line 3: Division by zero.
1) included file is now encoded in line number as an id.
2) opcode currentline is compound and includes file number (the ID of included file, not depth level of INCLUDE) and line number
3) drop OP_INCLUDEFILE
4) add max number of included files (100) and the error message at compiling time: "Maximum number of INCLUDE files"
Run multiple times any program that use directive INCLUDE. Just keep pressing F5.
include "mystuff.kbs"
After a while you will get error: COMPILE ERROR on line 2: Unable to open INCLUDE file. because the files are not closed.
FIXED
INCLUDE (Statement)
INCLUDE is not a realy statement, it is in fact a directive (wikipedia).
When the compiler finds an INCLUDE directive it replaces this line by the entire content of the specified file.
The external source file is loaded into the program at compile time (when the RUN button is pressed), just before the program actually starts. It is as if the contents of the specified file were written directly into the program insead of INCLUDE line.
The argument to the INCLUDE statement must be a string constant.
Before, INCLUDE can be used anywhere in program. This behaviour (to replace it with specified file) anywhere, even in the middle of a line, it was wrong, leading to a lot of possible errors.
Example
main program:
include "mystuff.kbs" 12345
"mystuff.kbs" contains only one line, without enter at end
If you run this program it will work. It is equivalent to print 12345 because include "mystuff.kbs" from the main program it is replaced with content of "mystuff.kbs" which is print
First, program should not accept a wrong syntax as the one above.
This is a light example, but (in real world) it can generate errors that are very hard to debug because the file can be inserted in the middle of a line and the rest of line is actually concatenate to the end of included file.
Other accepted (wrong) syntax
print include "mystuff.kbs" if(true) then include "mystuff.kbs"
FIX: INCLUDE directive syntax accept only this directive to exists in line.
Add error message "INCLUDE must be placed in a separate line" at compiling time.
There are accepted only remarks (REM, #) in this line (for the convenience of the user) and those are eated by compiler before to include file.
Example
main program:
include "mystuff.kbs"
"mystuff.kbs" contains only one line, which obviously will generate an error
1234
Before: COMPILE ERROR in included file mystuff.kbs on line 1: Syntax error around character 11.
After: COMPILE ERROR in included file 'mystuff.kbs' on line 1: Syntax error around character 4.
Example
run this program:
include
You will get no error. Ok...
Now run this:
bla bla bla This is a BASIC program a===10 + 15 hhohoho
You will get no error because the compiler is locked into INCLUDE state.
FIXED Add error message at compiling time: "No file specified for INCLUDE"
wavplay "jim_saying_numbers.mp3" #not playing... it need to start mediaplayer with WAVPLAY wavwait
FIXED
Run this (this should be not working)
input integeregereger a
FIXED
printer cancel printer[tab]cancel #no syntax highlighting
FIXED
This is done to correctly measure time elapsed by running program (benchmarks).
Respectfully,
Florin Oprea