Information Technology - Computer Programming - Source Code - Homebrew - Open Source - Software - Hardware - 8 bit - 16 bit - 32 bit - 64 bit - x86 - x64 - DOS - Windows - Linux - Arduino - Embedded - Development - Retro - Vintage - Math - Science - History - Hobby - Beginners - Professionals - Experiment - Research - Study - Fun - Games

Express BASIC - an interpreter in C

Anything C/C++ related.
admin
Site Admin
Posts: 127
Joined: Wed Feb 22, 2023 6:51 am

Update!!

Post by admin »

Hexidecimal values may now be denoted in expressions using the &H prefix.

The INP() function and OUT command has been added to the DOS Edition. It makes sense to allow DOS programmers the ability to access ports. This only works on the DOS .Edition and not DPMI, Win32, or Linux. While this allows for incompatible software to exist, the trade-off is worth it. Express BASIC for DOS is a whole new animal now. Especially with the addition of hex notation.

I tried adding Peek/Poke/Def Seg and had some luck, but still can't get it right. When I get that down I will try Varseg and Varptr. Maybe even Call Absolute.. That one looks difficult. For now, we have INP() and OUT for tinkering.

For example, INP(96) is now valid in Express BASIC. You may read keyboard input in real time.

I have updated the documentation. As always, please check it before using to avoid confusion. Please let me know if anyone has questions or wants to suggest something that is missing or incorrect.

More example programs have been added. There's a total of 18 playable games now that are cross platform between Linux, Windows, and DOS.

Here's a few of the new examples:

Code: Select all

1 REM Percentages Quiz
2 REM by Beronica Smothers
5 PRECISION 2
10 CLS: PRINT "*** Percentages Quiz ***": PRINT
20 INPUT "How many questions"; Q
25 LET C = 0
30 FOR I = 0 TO Q - 1
40 CLS
50 LET T = INT(RND * 9) + 1
60 GOSUB T * 1000
70 PRINT: PRINT: INPUT "Enter 0 to continue or 1 to exit. ", Z
80 IF Z = 1 THEN 100
90 NEXT I
100 LET P = C / Q * 100
110 CLS: PRINT: PRINT "You got "; P; "%% of the questions correct!": PRINT
120 IF P >= 90 THEN PRINT "You got an A! Amazing!"
130 IF P >= 80 AND P < 90 THEN PRINT "You got a B! Not bad!"
140 IF P >= 70 AND P < 80 THEN PRINT "You got a C! Could have done better."
150 IF P >= 60 AND P < 70 THEN PRINT "You got a D! Needs improvement!"
160 IF P < 60 THEN PRINT "You got an F! What a catastrophe!"
170 PRINT: PRINT: INPUT "Try again? Yes(1) No(2) ", Z
180 IF Z = 1 THEN 10
190 PRINT: PRINT "Hmm...alright. You better come back!"
200 END
999 REM *** Discount
1000 LET OP = (RND * 100) + ABS(RND - 1)
1010 LET PD = INT(RND * 99) + 1
1020 LET D = OP * (PD * .01)
1030 PRINT "A video game originally costs $"; OP
1040 PRINT "It now has a "; PD;"%% discount."
1050 PRINT: INPUT "What is the discount? $", A: PRINT
1060 IF A = D THEN PRINT "Correct!": LET C = C + 1: RETURN
1070 PRINT "Incorrect! The discount is $"; D: RETURN
1999 REM *** Final price after discount
2000 LET OP = (RND * 100) + ABS(RND - 1)
2010 LET PD = INT(RND * 99) + 1
2020 LET FP = OP - (OP * (PD * .01))
2030 PRINT "A video game originally costs $"; OP
2040 PRINT "It now has a "; PD;"%% discount."
2050 PRINT: INPUT "What is the final price? $", A: PRINT
2060 IF A = FP THEN PRINT "Correct!": LET C = C + 1: RETURN
2070 PRINT "Incorrect! The final price is $"; FP: RETURN
2999 REM *** Percent discount
3000 LET FP = (RND * 100) + ABS(RND - 1)
3010 LET OP = (RND * 100) + ABS(RND - 1): IF OP <= FP THEN 3010
3020 LET PD = (1 - (FP / OP)) * 100
3030 PRINT "A video game now costs $"; FP
3040 PRINT "The original price was $"; OP
3050 PRINT: INPUT "What is the percent discount"; A: PRINT
3060 IF A = PD THEN PRINT "Correct!": LET C = C + 1: RETURN
3070 PRINT "Incorrect! The percent discount is "; PD; "%%": RETURN
3999 REM *** Original price before discount
4000 LET FP = (RND * 100) + ABS(RND - 1)
4010 LET PD = INT(RND * 99) + 1
4020 LET OP = FP / ((100 - PD) * .01)
4030 PRINT "A video game is on sale for "; PD; "%% off."
4040 PRINT "The final price is $"; FP
4050 PRINT: INPUT "What was the original price? $", A: PRINT
4060 IF A = OP THEN PRINT "Correct!": LET C = C + 1: RETURN
4070 PRINT "Incorrect! The original price is $"; OP: RETURN
4999 REM *** Final price after markup
5000 LET OP = (RND * 100) + ABS(RND - 1)
5010 LET PD = INT(RND * 99) + 1
5020 LET FP = OP + (OP * (PD * .01))
5030 PRINT "A game console costs $"; OP; " to make."
5040 PRINT "The store marks it up "; PD; "%% to make profit."
5050 PRINT: INPUT "What is the final price of the game console? $", A: PRINT
5060 IF A = FP THEN PRINT "Correct!": LET C = C + 1: RETURN
5070 PRINT "Incorrect! The final price is $"; FP: RETURN
5999 REM *** Taxes
6000 LET BT = (RND * 100) + ABS(RND - 1)
6010 LET ST = 8
6020 LET TA = BT * (ST * .01)
6030 PRINT "Your total before taxes comes out to $"; BT
6040 PRINT "Your state's sales tax is "; ST; "%%"
6050 PRINT: INPUT "How much will you be paying in taxes? $", A: PRINT
6060 IF A = TA THEN PRINT "Correct!": LET C = C + 1: RETURN
6070 PRINT "Incorrect! The tax amount is $"; TA: RETURN
6999 REM *** Total after taxes
7000 LET BT = (RND * 100) + ABS(RND - 1)
7010 LET ST = 8
7020 LET AT = BT + (BT * (ST * .01))
7030 PRINT "Your total before taxes comes out to $"; BT
7040 PRINT "Your state's sales tax is "; ST; "%%"
7050 PRINT: INPUT "What is your total after taxes? $", A: PRINT
7060 IF A = AT THEN PRINT "Correct!": LET C = C + 1: RETURN
7070 PRINT "Incorrect! Your total after taxes is $"; AT: RETURN
7999 REM *** Total after taxes
8000 LET AT = (RND * 100) + ABS(RND - 1)
8010 LET ST = 8
8020 LET BT = AT / ((100 + ST) * .01)
8030 PRINT "Your total after taxes comes out to $"; AT
8040 PRINT "Your state's sales tax is "; ST; "%%"
8050 PRINT: INPUT "What was your total before taxes? $", A: PRINT
8060 IF A = BT THEN PRINT "Correct!": LET C = C + 1: RETURN
8070 PRINT "Incorrect! Your total before taxes is $"; BT: RETURN
8999 REM *** Percent from ratio
9000 LET R1 = INT(RND * 99) + 1
9010 LET R2 = INT(RND * 100) + 1: IF R2 <= R1 THEN 9010
9020 LET P = R1 / R2 * 100
9030 PRINT "You buy a new video game and take it for a spin!"
9040 PRINT "You shot down "; R1; " out of "; R2; " enemy space ships!"
9050 PRINT: INPUT "What is your percent accuracy"; A: PRINT
9060 IF A = P THEN PRINT "Correct!": LET C = C + 1: RETURN
9070 PRINT "Incorrect! Your percent accuracy is "; P; "%%": RETURN

Code: Select all

10 PRINT TAB(33); "SPLAT"
20 PRINT TAB(15); "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
40 PRINT: PRINT: PRINT
95 PRINT "WELCOME TO 'SPLAT' -- THE GAME THAT SIMULATES A PARACHUTE"
96 PRINT "JUMP. TRY TO OPEN YOUR CHUTE AT THE LAST POSSIBLE"
97 PRINT "MOMEMT WITHOUT GOING SPLAT."
118 PRINT: PRINT: LET D1 = 0: LET V = 0: LET A = 0: LET N = 0: LET M = 0: LET D1 = INT(9001 * RND + 1000)
119 PRINT " SELECT YOUR OWN TERMINAL VELOCITY (YES(1) NO(2))";: INPUT Z
120 IF Z = 2 THEN GOTO 128
121 IF Z <> 1 THEN PRINT "YES(1) OR NO(2)";: INPUT Z: GOTO 120
123 PRINT "WHAT TERMINAL VELOCITY (MI/HR)";:INPUT V1
125 LET V1 = V1 * (52800 / 3600): LET V = V1 + ((V1 * RND) / 20) - ((V1 * RND) / 20): GOTO 135
128 LET V1 = INT(1000 * RND)
130 PRINT "OK. TERMINAL VELOCITY = "; V1; " MI/HR"
131 LET V1 = V1 * (52800 / 3600): LET V = V1 + ((V1 * RND) / 20) - ((V1 * RND) / 20)
135 PRINT "WANT TO SELECT ACCERLERATION DUE TO GRAVITY (YES(1) OR NO(2))";
136 INPUT Z
140 IF Z = 2 THEN 150
141 IF Z <> 1 THEN PRINT "YES(1) OR NO(2)";: INPUT Z: GOTO 140
143 PRINT "WHAT ACCELERATION (FT/SEC/SEC)";: INPUT A2
145 LET A = A2 + ((A2 * RND) / 20) - ((A2 * RND) / 20): GOTO 205
150 LET Z = INT(1 + (10 * RND))
151 IF Z = 1 THEN PRINT "FINE. YOU'RE ON MERCURY. ACCELERATION=12.2FT/SEC/SEC":GOTO 161
152 IF Z = 2 THEN PRINT "ALRIGHT. YOU'RE ON VENUS. ACCELERATION=28.3FT/SEC/SEC":GOTO 162
153 IF Z = 3 THEN PRINT "THEN YOU'RE ON EARTH. ACCELERATION=32.16FT/SEC/SEC":GOTO 163
154 IF Z = 4 THEN PRINT "FINE. YOU'RE ON THE MOON. ACCELERATION=5.15FT/SEC/SEC":GOTO 164
155 IF Z = 5 THEN PRINT "ALRIGHT. YOU'RE ON MARS. ACCELERATION=12.5FT/SEC/SEC":GOTO 165
156 IF Z = 6 THEN PRINT "THEN YOU'RE ON JUPITER. ACCELERATION=85.2FT/SEC/SEC":GOTO 166
157 IF Z = 7 THEN PRINT "FINE. YOU'RE ON SATURN. ACCELERATION=37.6FT/SEC/SEC":GOTO 167
158 IF Z = 8 THEN PRINT "ALRIGHT. YOU'RE ON URANUS. ACCELERATION=33.8FT/SEC/SEC":GOTO 168
159 IF Z = 9 THEN PRINT "THEN YOU'RE ON NEPTUNE. ACCELERATION=39.6FT/SEC/SEC":GOTO 169
160 IF Z = 10 THEN PRINT "FINE. YOU'RE ON THE SUN. ACCELERATION=896FT/SEC/SEC":GOTO 170
161 LET A2 = 12.2: GOTO 145
162 LET A2 = 28.3: GOTO 145
163 LET A2 = 32.16: GOTO 145
164 LET A2 = 5.15: GOTO 145
165 LET A2 = 12.5: GOTO 145
166 LET A2 = 85.2: GOTO 145
167 LET A2 = 37.6: GOTO 145
168 LET A2 = 33.8: GOTO 145
169 LET A2 = 39.6: GOTO 145
170 LET A2 = 896: GOTO 145
205 PRINT
206 PRINT "	ALTITUDE	= "; D1; " FT"
207 PRINT "	TERM.VELOCITY	= "; V1; " FT/SEC =  +-5 %"
208 PRINT "	ACCELERATION	= "; A2; " FT/SEC/SEC = -5 %"
210 PRINT "SET THE TIMER FOR YOUR FREEFALL."
211 PRINT "HOW MANY SECONDS";: INPUT T
215 PRINT "HERE WE GO."
217 PRINT
218 PRINT "TIME (SEC)", "DIST TO FALL (FT)"
219 PRINT "==========", "================="
300 FOR I = 0 TO T STEP (T/8)
310 IF I > V / A THEN GOTO 400
320 LET D = D1 - ((A / 2) * I ^ 2)
330 IF D <= 0 THEN GOTO 900
240 PRINT I, TAB(8), D
350 NEXT I
360 GOTO 500
400 PRINT "TERMINAL VELOCITY REACHED AT T PLUS "; V / A; " SECONDS"
405 FOR I = I TO T STEP (T / 8)
410 LET D = D1 - ((V ^ 2 / (2 * A)) + (V * (I - (V / A))))
420 IF D <= 0  THEN GOTO 1010
430 PRINT I, TAB(8), D
440 NEXT I
500 PRINT "CHUTE OPEN"
510 LET K = 0: LET K1 = 0
550 FOR J = 0 TO 42
555 IF @(J) = 0 THEN GOTO 620
560 LET K = K + 1
570 IF D >= @(J) THEN GOTO 600
580 LET K1 = K1 + 1
600 NEXT J
610 GOTO 540
620 LET @(J) = D
630 IF J > 2 THEN 650
635 PRINT "AMAZING!!! NOT BAD FOR YOUR ";
636 IF J = 0 THEN PRINT "1ST ";
637 IF J = 1 THEN PRINT "2ND ";
638 IF J = 2 THEN PRINT "3RD ";
639 PRINT "SUCCESSFUL JUMP!!!": GOTO 2000
650 IF K - K1 <= .1 * K THEN GOTO 700
660 IF K - K1 <= .25 * K THEN GOTO 710
670 IF K - K1 <= .5 * K HEN GOTO 720
680 IF K - K1 <= .75 * K THEN GOTO 730
690 IF K - K1 <= .9 * K THEN GOTO 740
695 GOTO 750
700 PRINT "WOW! THAT'S SOME JUMPING. OF THE "; K; " SUCCESFUL JUMPS"
701 PRINT "BEFORE YOURS, ONLY "; K - K1; " OPENED THEIR CHUTE LOWER THAN"
702 PRINT "YOU DID."
703 GOTO 2000
710 PRINT "PRETTY GOOD! "; K; " SUCCESSFUL JUMPS PRECEDED YOURS AND ONLY"
711 PRINT K - K1; " OF THEM GOT LOWER THAN YOU DID BEFORE THEIR CHUTES"
712 PRINT "OPENED.": GOTO 2000
720 PRINT "NOT BAD. THERE HAVE BEEN "; K; " SUCCESSFUL JUMPS BEFORE YOURS."
721 PRINT "YOU WERE BEATEN OUT BY "; K - K1; " OF THEM.": GOTO 2000
730 PRINT "CONSERVATIVE AREN'T YOU? YOU RANKED ONLY "; K - K1; " IN THE"
731 PRINT K; " SUCCESSFUL JUMPS BEFORE YOURS.": GOTO 2000
740 PRINT "HUMPH! DON'T YOU HAVE ANY SPORTING BLOOD? THERE WERE"
741 PRINT K; " SUCCESSFUL JUMPS BEFORE YOURS AND YOU CAME IN "; K1; " JUMPS"
742 PRINT "BETTER THAN THE WORST. SHAPE UP!!!": GOTO 2000
750 PRINT "HEY! YOU PULLED THE RIP CORD MUCH TOO SOON. "; K; " SUCCESSFUL"
751 PRINT "JUMPS BEFORE YOURS AND YOU CAME IN NUMBER "; K- K1; "! GET WITH IT!"
752 GOTO 2000
800 PRINT "REQUIESCAT IN PEACE.": GOTO 1950
801 PRINT "MAY THE ANGEL OF HEAVEN LEAD YOU INTO PARADISE": GOTO 1950
802 PRINT "REST IN PEACE": GOTO 1950
803 PRINT "SON-OF-A-GUN": GOTO 1950
804 PRINT "#$%&&%!$": GOTO 1950
805 PRINT "A KICK IN THE PANTS IS A BOOST IF YOU'RE HEADED RIGHT": GOTO 1950
806 PRINT "HMMM. SHOULD HAVE PICKED A SHORTER TIME.": GOTO 1950
807 PRINT "MUTTER. MUTTER. MUTTER": GOTO 1950
808 PRINT "PUSHING UP DAISIES.": GOTO 1950
809 PRINT "EASY COME, EASY GO.": GOTO 1950
900 PRINT SQR(2 * D1 / A), "SPLAT"
1000 LET Z = INT(1 + (10 * RND)): IF Z = 1 THEN 800
1001 IF Z = 2 THEN 801
1002 IF Z = 3 THEN 802
1003 IF Z = 4 THEN 803
1004 IF Z = 5 THEN 804
1005 IF Z = 6 THEN 805
1006 IF Z = 7 THEN 806
1007 IF Z = 8 THEN 807
1008 IF Z = 9 THEN 808
1009 IF Z = 10 THEN 809
1010 PRINT (V / A) + ((D1 - (V ^ 2 / (2 * A))) / V), "SPLAT"
1020 GOTO 1000
1950 PRINT "I'LL GIVE YOU ANOTHER CHANCE." GOTO 2000
2000 PRINT "DO YOU WANT TO PLAY AGAIN YES(1) OR NO(2)";: INPUT Z
2001 IF Z = 1 THEN GOTO 118
2002 IF Z = 2 THEN GOTO 2005
2003 PRINT "YES(1) OR NO(2)": GOTO 2000
2005 PRINT "PLEASE";: INPUT Z: IF Z = 1 THEN 118
2006 IF Z <> 2 THEN PRINT "YES(1) OR NO(2)";: GOTO 2005
2007 PRINT "SSSSSSSSSS.": GOTO 2046
2046 END

Code: Select all

10 PRINT TAB(32); "REVERSE"
20 PRINT TAB(15); "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
30 PRINT: PRINT: PRINT
100 PRINT "REVERSE -- A GAME OF SKILL": PRINT
140 REM *** N = NUMBER OF NUMBERS
150 LET N = 9
160 PRINT "DO YOU WANT THE RULES YES(1) NO(2)";
170 INPUT A
180 IF A = 2 THEN 210
190 GOSUB 710
200 REM *** MAKE A RANDOM LIST A(1) TO A(N)
210 LET @(1) = INT((N - 1) * RND + 2)
220 FOR K = 2 TO N
230 LET @(K) = INT(N * RND + 1)
240 FOR J = 1 TO K - 1
250 IF @(K) = @(J) THEN 230
260 NEXT J
261 NEXT K
280 REM *** PRINT ORIGINAL LIST AND START GAME
290 PRINT: PRINT "HERE WE GO ... THE LIST IS:"
310 LET T = 0
320 GOSUB 610
330 PRINT "HOW MANY SHALL I REVERSE";
340 INPUT R
350 IF R = 0 THEN 520
360 IF R <= N THEN 390
370 PRINT "OOPS!     TOO MANY!    I CAN REVERSE AT MOST"; N: GOTO 330
390 LET T = T + 1
400 REM *** REVERSE R NUMBERS AND PRINT NEW LIST
410 FOR K = 1 TO INT(R / 2)
420 LET Z = @(K)
430 LET @(K) = @(R - K + 1)
440 LET @(R - K + 1) = Z
450 NEXT K
460 GOSUB 610
470 REM *** CHECK FOR A WIN
480 FOR K = 1 TO N
490 IF @(K) <> K THEN 330
500 NEXT K
510 PRINT "YOU WON IT IN "; T; " MOVES!!!": PRINT
520 PRINT
530 PRINT "TRY AGAIN (YES(1) NO(2))";
540 INPUT A
550 IF A = 1 THEN 210
560 PRINT: PRINT "O.K. HOPE YOU HAD FUN!!": GOTO 999
600 REM *** SUBROUTINE TO PRINT LIST
610 PRINT
611 FOR K = 1 TO N
612 PRINT @(K);
613 NEXT K
650 PRINT: PRINT: RETURN
700 REM *** SUBROUTINE TO PRINT THE RULES
710 PRINT: PRINT "THIS IS THE GAME OF 'REVERSE'. TO WIN, ALL YOU HAVE"
720 PRINT "TO DO IS ARRANGE A LIST OF NUMBERS (1 THROUGH ";N; ")"
730 PRINT "IN NUMERICAL ORDER FROM LEFT TO RIGHT. TO MOVE, YOU"
740 PRINT "TELL ME HOW MANY NUMBERS (COUNTING FROM THE LEFT) TO"
750 PRINT "REVERSE. FOR EXAMPLE, IF THE CURRENT LIST IS:"
760 PRINT: PRINT "2 3 4 5 1 6 7 8 9"
770 PRINT: PRINT "NOW IF YOU REVERSE 5, YOU WIN!"
800 PRINT: PRINT "1 2 3 4 5 6 7 8 9": PRINT
810 PRINT "NO DOUBT YOU WILL LIKE THIS GAME, BUT"
820 PRINT "IF YOU WANT TO QUIT, REVERSE 0 (ZERO).": PRINT: RETURN
999 END
admin
Site Admin
Posts: 127
Joined: Wed Feb 22, 2023 6:51 am

Re: Express BASIC - an interpreter in C

Post by admin »

Here's a simple demo of sending output to the parallel port in DOS.

Code: Select all

10 FOR i = 1 TO 255
20 PRINT CHR$(i),: OUT &H378, i
30 LET t = TIMER
40 IF TIMER < t + 1 THEN 40
50 NEXT i
The output is viewable with a rs232 quick tester like this:
AD-D25QT__00914.jpg
AD-D25QT__00914.jpg (40.44 KiB) Viewed 8937 times
admin
Site Admin
Posts: 127
Joined: Wed Feb 22, 2023 6:51 am

Re: Express BASIC - an interpreter in C

Post by admin »

This week brings a big update.

Handling of negation has been improved. For example, -(10 +1) returns -11 as it should. As opposed to -9. I had never accounted for negating outside of parenthesis. Only in front of a variable or literal value. The solution for now is to swap the - with a _1* and later swap the _ back to a - while processing the infix.

A bug with GOSUB was fixed. We're working on making the subs and for loops work with the colons. For now, just the subs.

There's three new examples.

This particular example wasn't working correctly until I fixed the negation handling. I think it shows the progress that we're making.

Code: Select all

1 REM PLOT A NORMAL DISTRIBUTION CURVE
2 REM PORTED TO EXPRESS BASIC
3 REM FROM THE DTSS EMULATOR MANUAL "A BASIC OUTLINE"
10 FOR X = -2 TO 2 STEP .1
20 PRINT TAB(INT(100 * (EXP(-(X ^ 2 / 2)) / SQR(2 * PI)))); "*"
30 NEXT X
admin
Site Admin
Posts: 127
Joined: Wed Feb 22, 2023 6:51 am

Re: Express BASIC - an interpreter in C

Post by admin »

Been working out a TON of bugs. Hopefully I will get to post an update today or tomorrow.

Including issues with GOSUB and FOR. Trying to make the code wotk right with colons.
Also, other random typos and issues.

Thia is why EB is still alpha. Many things to test and improve or fix.
admin
Site Admin
Posts: 127
Joined: Wed Feb 22, 2023 6:51 am

Re: Express BASIC - an interpreter in C

Post by admin »

No update has been released yet. Still working on a ton of issues.

Things were looking okay. I developed a new example game. It works on EB compiled with Watcom and DJGPP, but not Turbo C 1. It compiles in Turbo, but has a serious glitch. Doesn't compile at all in TC2. Compiles for DOS in Watcom, but has the same issue.

So...

Fixed several potential memory leaks.
Increased string memory size by a little.
Also found that line numbers over 32767 don't work on EB for DOS. (had to mod the game as it had nums over 40000)
Will probably need to figure out later on why line nums in DOS are being limited as an INT (probably some more mistakes)

At this point the game is working under EB for DOS compiled with Open Watcom. Except programs with Watcom do not compile correctly for the 8088. It just hangs.

After some research I found that Watcom wasn't properly tested on the 8088 and requires a fix. This fix is supposedly now implemented in the Watcom 2 fork.

And now of course it is time for me to return to my day job. Time is limited. Problems are many.

As things are, we may consider all editions of EB to be broken until I'm able to get the update out. Sorry about that!

Here's a peek of the game that is pushing development. It won't yet run with the current releases. The next update will include this game with all the editions. Hopefully that won't take more than a few days..

Code: Select all

1 REM Zombie Bug-out by Gemino Smothers
2 REM Lucid Apogee 2024 www.lucidapogee.com
3 REM Run with Express BASIC
10 CLS: GOSUB 10000: GOSUB 20000: GOSUB 100: GOTO 10
100 IF NOT(die) THEN CLS: GOSUB 1000: GOSUB 2000: GOSUB 3000: GOTO 100
110 LET die = 0: LET lvl = 0: LET s = 0: LET t = 0: RETURN
1000 IF die THEN RETURN
1010 IF NOT(g) THEN PRINT "Area cleared."; CHR$(10): GOSUB 10000
1020 PRINT "Level: "; lvl; " Score: "; s; " Thirst: "; t; "/"; 16 + lvl; CHR$(10)
1030 PRINT TAB(15); "N"; CHR$(10); TAB(14); "W E"; CHR$(10); TAB(15); "S"; CHR$(10): GOSUB 4000 
1040 PRINT "  (1) Go North (2) Go East"; CHR$(10); "  (3) Go South (4) Go West"
1050 PRINT "  (5) Wait (6) Shoot Gun"; CHR$(10); "  (0) Give Up"; CHR$(10)
1060 INPUT "   What is your decision"; a: PRINT: RETURN
2000 IF a = 1 AND py > 1 THEN PRINT "You move North."; CHR$(10): LET py = py - 1
2010 IF a = 2 AND px < mx THEN PRINT "You move East."; CHR$(10): LET px = px + 1
2020 IF a = 3 AND py < my THEN PRINT "You move South."; CHR$(10): LET py = py + 1
2030 IF a = 4 AND px > 1 THEN PRINT "You move West."; CHR$(10): LET px = px - 1
2040 IF a = 5 THEN PRINT "Waiting..."; CHR$(10)
2050 IF a = 6 THEN GOSUB 5000
2060 IF a <> 0 THEN 2090
2070 CLS: PRINT "Final Score: "; s; CHR$(10): LET fs = 0: LET die = 1
2080 INPUT "Enter any number to continue:", a
2090 LET t = t + 1: IF px = wx AND py = wy THEN LET t = 0
2100 IF NOT(t = 16 + lvl) THEN 2130
2110 CLS: PRINT "You are too thirsty to go on..."; CHR$(10); CHR$(10); "Final Score: "; s; CHR$(10)
2120 LET fs = 0: LET die = 1: INPUT "Enter any number to continue:", a
2130 RETURN
3000 IF sk THEN LET sk = sk - 1: RETURN
3010 LET ch = INT(RND * 2): FOR i = 0 TO (zcnt * 2) - 1 STEP 2
3020 IF NOT(@(i)) AND NOT(@(i + 1)) THEN 3100
3030 IF ch AND @(i + 1) > py THEN LET @(i + 1) = @(i + 1) - 1: GOTO 3100
3040 IF ch AND @(i) < px THEN LET @(i) = @(i) + 1: GOTO 3100
3050 IF ch AND @(i + 1) < py THEN LET @(i + 1) = @(i + 1) + 1: GOTO 3100
3060 IF ch AND @(i) > px THEN LET @(i) = @(i) - 1
3070 IF NOT(@(i) = px AND @(i + 1) = py) THEN 3100
3080 CLS: PRINT "A zombie has eliminated you..."; CHR$(10); "Final Score: "; s; CHR$(10)
3090 INPUT "Enter any number to continue:", a: LET fs = 0: LET die = 1: BREAK i
3100 NEXT i: RETURN
4000 FOR dy = py - 2 TO py + 2: PRINT TAB(13);: FOR dx = px - 2 TO px + 2: LET f = 0
4010 IF dx < 1 OR dx > mx OR dy < 1 OR dy > my THEN LET f = 1: PRINT "#";: GOTO 4060
4020 IF dx = px AND dy = py THEN LET f = 1: PRINT "+";: GOTO 4060
4030 FOR i = 0 TO (zcnt * 2) - 1 STEP 2
4040 IF dx = @(i) AND dy = @(i + 1) THEN LET f = 1: PRINT "!";: BREAK i
4050 NEXT i
4060 IF NOT(f) AND dx = wx AND dy = wy AND wf THEN LET f = 1: PRINT "~";
4070 IF NOT(f) THEN PRINT ".";
4080 NEXT dx: PRINT: NEXT dy: PRINT: RETURN
5000 PRINT "  (1) Shoot North (2) Shoot East"
5005 PRINT "  (3) Shoot South (4) Shoot West"; CHR$(10)
5010 INPUT "   What is your decision"; a: PRINT
5020 IF a = 1 THEN LET sx = px: LET sy = py - 1
5030 IF a = 2 THEN LET sx = px + 1: LET sy = py
5040 IF a = 3 THEN LET sx = px: LET sy = py + 1
5050 IF a = 4 THEN LET sx = px - 1: LET sy = py
5060 FOR i = 0 TO (zcnt * 2) - 1 STEP 2
5070 IF NOT(sx = @(i) AND sy = @(i + 1)) THEN GOTO 5110
5080 LET g = g - 1: LET @(i) = 0: LET @(i + 1) = 0: LET s = s + 1
5090 GOSUB 40000: PRINT "You have eliminated a zombie!"; CHR$(10)
5100 INPUT "Enter any number to continue:", a: BREAK i
5110 NEXT i: RETURN
10000 IF fs THEN PRINT "Looking for zombies...";
10010 LET lvl = lvl + 1: LET zcnt = INT(RND * (lvl * 2)) + 1: LET g = zcnt
10020 LET mx = INT(RND * 8) + 4 + lvl: LET my = INT(RND * 8) + 4 + lvl
10030 FOR i = 0 TO (zcnt * 2) - 1 STEP 2: PRINT "...";
10040 LET @(i) = INT(RND * mx) + 1: LET @(i + 1) = INT(RND * my) + 1
10050 NEXT i: LET px = INT(RND * mx) + 1: LET py = INT(RND * my) + 1
10060 LET wx = INT(RND * mx) + 1: LET wy = INT(RND * my) + 1: LET wf = 1
10070 PRINT: PRINT: IF NOT(fs) THEN 10090
10080 PRINT "Zombies found."; CHR$(10): INPUT "Enter any number to continue:", a
10090 LET fs = 1: LET sk = 2: CLS: RETURN
20000 CLS: PRINT TAB(10); "Zombie Bug-out"; CHR$(10)
20010 PRINT " (1) Bug-out (2) Help (0) Give Up"; CHR$(10)
20020 INPUT "     What is your decision"; a: CLS
20030 IF a = 0 THEN END
20040 IF a = 1 THEN RETURN
20050 IF a = 2 THEN GOSUB 30000
20060 GOTO 20000
30000 PRINT "Objective: Survive the zombie invasion."; CHR$(10)
30010 PRINT "You're represented by a + while the zombies are a ! symbol."; CHR$(10)
30020 PRINT "Tiles with the ~ symbol are water sources."
30030 PRINT "Tiles with the # symbol are trees representing the map edge."
30040 PRINT "Tiles with the . symbol represent a blank space on the map."; CHR$(10)
30050 PRINT "You may either move, wait, or attack."
30060 PRINT "Waiting allows you to pass a turn without moving."; CHR$(10)
30070 PRINT "To eliminate a zombie, you must attack while adjacent to it."
30080 PRINT "Multiple zombies may occupy a single tile at a time."
30090 PRINT "Zombies will eliminate you if they move to the same map tile you're on."; CHR$(10)
30100 PRINT "If you get too thirsy, you will be unable to continue."; CHR$(10)
30110 PRINT "[+] Hunter [!] Zombie [#] Tree"; CHR$(10)
30120 INPUT "Enter any number to continue:", a: CLS: RETURN
40000 FOR b = 1 TO 61: CLS
40010 PRINT "  /=============="; TAB(b); "-"; TAB(79 - b - 17); "!"
40020 PRINT " / ____/"
40030 PRINT "/_/  `"
40040 NEXT b: RETURN
admin
Site Admin
Posts: 127
Joined: Wed Feb 22, 2023 6:51 am

Important Update for Express BASIC

Post by admin »

After weeks of painful research and debugging, we have finally released the next update. We're still going to remain in alpha version. You never know if and when a new problem may surface.

The Watcom debugger was helpful in finding leaks and other problems.
The issue of line numbers being limited in DOS was fixed (also with the help of Watcom).

It seems that many problems we were having were due to DOS memory limits and having to find a balance. Now things appear to be "stable" again... until I figure out another line of code that breaks the interpreter... hopefully not! :cry:

The Zombie Hunter game from the post above this one is now included. It appears to work on DOS, Windows, Linux, and DPMI exactly the same. Not factoring speed and differences between consoles.

A few things are still in need of attention. One is that if you use colons to combine two FOR loops in one line with the same index variable, it will not work. Two different indexes will work, but not the same. There's a fix for this and should be added to the next update in the coming week. The other known issue is that the = operator may not be used in the expression of an array pointer for assignment. For example LET @(1=1)=1+2. The parsing overlooks the =. It is a simple, but tedious fix. The fix is also planned for the next update. I doubt anyone uses = in a pointer expression for assignment, but you never know and I would rather support all possibilities.
admin
Site Admin
Posts: 127
Joined: Wed Feb 22, 2023 6:51 am

Re: Express BASIC - an interpreter in C

Post by admin »

We're still working towards the next update.

I encountered another problem. A FOR loop combined after an IF statement doesn't work correctly.

This became apparent with the following example where line 40 and 50 should have been doable with one line.

Code: Select all

1 REM https://rosettacode.org/wiki/Sieve_of_Eratosthenes
10 LET l = 120: FOR n = 2 TO l: LET @(n) = 1: NEXT n
20 PRINT "prime numbers less than or equal to "; l; " are:"
30 FOR n = 2 TO SQR(l)
40 IF NOT(@(n) = 1) THEN 60
50 FOR i = n * n TO l STEP n: LET @(i) = 0: NEXT i
60 NEXT n
70 FOR n = 1 TO l
80 IF @(n) = 1 THEN PRINT n,
90 NEXT n
We're looking into this issue as well as the ones mentioned in the previous post.

It may take a long time to iron out these issues. :geek:
admin
Site Admin
Posts: 127
Joined: Wed Feb 22, 2023 6:51 am

The next update is out

Post by admin »

With this next update, we have included more examples and have fixed the issues mentioned previously about not being able to have multiple FOR loops on the same line with the same index variable. Also, the issue with not being able to execute a for loop on the same line as an if statement. These things are now possible. Of course there may be other problems. Hopefully not.

New examples include:

Code: Select all

1 REM https://rosettacode.org/wiki/Sieve_of_Eratosthenes
10 LET l = 120: FOR n = 2 TO l: LET @(n) = 1: NEXT n
20 PRINT "prime numbers less than or equal to "; l; " are:"
30 FOR n = 2 TO SQR(l)
40 IF @(n) = 1 THEN FOR i = n * n TO l STEP n: LET @(i) = 0: NEXT i
50 NEXT n
60 FOR n = 1 TO l
70 IF @(n) = 1 THEN PRINT n,
80 NEXT n

Code: Select all

1 REM https://rosettacode.org/wiki/Semiprime
10 FOR i = 2 TO 100
20 LET n = ABS(i)
30 LET c = 0
40 IF n < 3 THEN 100
50 LET f = 2
60 LET m = n MOD f = 0
70 IF m THEN LET c = c + 1: LET n = n / f
80 IF NOT(m) THEN LET f = f + 1
90 IF n > 1 THEN 60
100 IF c = 2 THEN PRINT i,
110 NEXT i

Code: Select all

1 REM https://rosettacode.org/wiki/Blum_integer
10 PRINT "The first 50 blum integers are:": PRINT
20 LET n = 3: LET b = 0
30 LET n = n + 2
40 GOSUB 1000
50 IF r = 0 THEN 30
60 IF prime1 MOD 4 <> 3 THEN 30
70 LET prime2 = n / prime1
80 IF (prime2 <> prime1) and (prime2 MOD 4 = 3) THEN LET b = b + 1
90 IF b <= 50 THEN PRINT n;" "; 
100 IF b >= 26828 THEN PRINT "The 26828th Blum integer is: "; n: END
110 GOTO 30
120 END
1000 LET x = 3: LET y = 0: LET z = n
1010 IF x * x > z THEN 1080
1020 IF z MOD x <> 0 THEN 1060
1030 IF y = 2 THEN LET r = 0: RETURN
1040 LET z  = z / x: LET y = y + 1
1050 GOTO 1020
1060 LET x = x + 2
1070 GOTO 1010
1080 LET prime1 = z: LET r = y = 1
1090 RETURN

Code: Select all

1 REM https://rosettacode.org/wiki/Statistics/Basic
5 CLS: PRECISION 8
10 LET n = 100: GOSUB 100
20 LET n = 1000: GOSUB 100
30 LET n = 10000: GOSUB 100
40 END
100 LET sum = 0: LET sumsq = 0
110 FOR i = 1 TO n: LET @(i) = RND: LET sum = sum + @(i): LET sumsq = sumsq + @(i) ^ 2: NEXT i
120 LET mean = sum / n
130 PRINT "Sample size "; n: PRINT
140 PRINT " Mean = "; mean
150 PRINT " Std dev = "; (sumsq / n - mean ^ 2) ^ .5
160 LET scal = 10
170 FOR i = 1 TO n: LET z = INT(scal * @(i)): LET @(z + n) = @(z + n) + 1: NEXT i
180 FOR b = 0 TO scal - 1: PRINT " "; b; " : ";
190 FOR j = 1 TO INT(scal * @(b + n)) / n * 70: PRINT "*";: NEXT j
200 PRINT: NEXT b: PRINT: RETURN

Code: Select all

1 REM https://rosettacode.org/wiki/Cullen_and_Woodall_numbers
10 PRINT "The first 20 Cullen numbers are:": PRINT
20 FOR n = 1 to 20: PRINT INT(n * (2 ^ n) + 1); " ";: NEXT n
30 PRINT: PRINT: PRINT "The first 20 Woodall numbers are:": PRINT
40 FOR n = 1 to 20: PRINT INT(n * (2 ^ n) - 1); " ";: NEXT n

Code: Select all

1 REM https://rosettacode.org/wiki/Ethiopian_multiplication
10 LET x = 17: LET y = 34: LET s = 0
20 IF x < 1 THEN 100
30 IF s = 1 THEN PRINT x
40 IF s = 0 THEN LET s = 1
50 LET a = x: LET e = a MOD 2: LET e = 1 - e
60 IF e = 0 THEN LET t = t + y: PRINT x, y
70 LET a = x: LET a = INT(a / 2): LET x = a
80 LET a = y: LET a = 2 * a: LET y = a
90 IF x >= 1 THEN 20
100 PRINT "=": PRINT t

Code: Select all

1 REM https://rosettacode.org/wiki/Casting_out_nines
10 LET b = 10
20 FOR k = 1 TO (b ^ 2) - 1: LET c1 = c1 + 1
30 IF k MOD (b - 1) = (k * k) MOD (b - 1) THEN LET c2 = c2 + 1: PRINT k,
40 NEXT k: PRINT
50 PRINT "trying "; c2; " numbers instead of "; c1; " numbers saves "; 100 - (100 * c2 / c1); "%%"
admin
Site Admin
Posts: 127
Joined: Wed Feb 22, 2023 6:51 am

Re: Express BASIC - an interpreter in C

Post by admin »

There has been two more major updates.
Read about them here
viewtopic.php?t=110
and here
viewtopic.php?t=111

Plans for the next update:
INKEY$
File i/o
more functions
etc...
admin
Site Admin
Posts: 127
Joined: Wed Feb 22, 2023 6:51 am

Re: Express BASIC - an interpreter in C

Post by admin »

Update!

Some issues with file and string handling are fixed.
A string array called $() similarly to @() has been added.
There's more error handling and messages.

For example:
"String parsing operation out of bounds"
"Attempted input past end of file"

Usually BASIC languages will only return the available characters when LEFT$(), RIGHT$(), and MID$() go out of bounds. Express BASIC will return the available characters without going out of bounds, but will also provide an error. This unique feature should help to write better code. You could take any string code and find leaks by porting to Express BASIC.

New examples include:

Tiny Basic Example
HTM Parser
Madlibs
Capital Quiz
Hangman
Post Reply