ZXSimulator

Anything QL Software or Programming Related.
User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

I slightly improved the main loop so it would run a bit faster on a non-accelerated computer. Kind of playable on a ZX81 or simulated on an unexpanded QL. You can see how if INKEY$ is 0 I go straight back to refreshing screen with stars, cross-hairs and enemy. Next will give opponent opportunity to shoot back and destroy me and impact ammo, shields, fuel and energy.

Code: Select all

10 REM ELITE
20 GOSUB 3000
30 GOSUB 3500
400 REM PLAY
410 LET DY=0
420 LET DX=1
430 GOSUB 1500
440 GOTO 460
450 GOSUB 2500
460 GOSUB 1000
470 GOSUB 1100
480 GOSUB 2000
490 LET KEY=CODE INKEY$
500 IF KEY=0 THEN GOTO 460
510 IF KEY=FIRE THEN GOTO 450 
520 GOTO 430
999 STOP
1000 REM LASER SIGHT
1010 PRINT AT 6,14;"\.'"
1020 PRINT AT 6,17;"\'."
1030 PRINT AT 7,14;"\'."
1040 PRINT AT 7,17;"\.'"
1050 RETURN
1100 REM STAR FIELD
1110 IF STARS=0 THEN GOTO 1220
1120 LET S$=" "
1130 GOSUB 1300
1140 IF INT (RND*10)=1 THEN LET SM=SM+1
1150 LET SX=SX+DX
1160 LET SY=SY-DY
1170 LET SM=SM-DY
1180 IF SY+SM>13 THEN GOTO 1230
1190 LET S$="."
1200 GOSUB 1300
1210 RETURN
1220 LET STARS=1
1230 LET SM=0
1240 LET SX=INT (RND*3)+5
1250 LET SY=INT(RND*2)+4
1260 GOTO 1190
1300 REM STAR
1310 IF SY+SM>=0 AND SY+SM<14 AND SX-SM>=0 AND SX-SM<32 THEN PRINT AT SY+SM,SX-SM;S$
1320 IF SY+SM*2-4>=0 AND SY+SM*2-4<14 AND SX+10>=0 AND SX+10<32 THEN PRINT AT SY+SM*2-4,SX+10;S$
1330 IF SY+SM-1>=0 AND SY+SM-1<14 AND SX+SM+20>=0 AND SX+SM+20<32 THEN PRINT AT SY+SM-1,SX+SM+20;S$
1340 RETURN
1500 REM CONTROLS
1510 PRINT AT 18,15;"  "
1520 PRINT AT 19,14;" \ :\:  "
1530 PRINT AT 20,15;"  "
1540 IF DX<>DY THEN LET KEY=0
1550 LET DY=0
1560 LET DX=0
1570 IF KEY=LEFT THEN GOTO 1620
1580 IF KEY=RIGHT THEN GOTO 1650
1590 IF KEY=up THEN GOTO 1680
1600 IF KEY=DOWN THEN GOTO 1710
1610 RETURN
1620 LET DX=DX+1
1630 PRINT AT 19,14;"\ :"
1640 RETURN
1650 LET DX=DX-1
1660 PRINT AT 19,17;"\: "
1670 RETURN
1680 LET DY=DY-1
1690 PRINT AT 18,15;"\ '\' "
1700 RETURN
1710 LET DY=DY+1
1720 PRINT AT 20,15;"\ .\. "
1730 RETURN
2000 REM ENEMY SHIP
2010 IF SHIP=0 AND INT (RND*6)<>1 THEN RETURN
2020 IF SHIP=0 THEN GOTO 2240
2030 IF EY<13 OR EY>43 THEN GOTO 2060
2040 IF EX>=1 AND EX<65 THEN UNPLOT EX-1,EY
2050 IF EX>-2 AND EX<63 THEN UNPLOT EX+1,EY
2060 IF EX<0 OR EX>64 THEN GOTO 2090
2070 IF EY>13 AND EY<45 THEN UNPLOT EX,EY-1
2080 IF EY>11 AND EY<43 THEN UNPLOT EX,EY+1
2090 IF EL=0 THEN GOTO 2700
2100 LET DIR=INT (RND*8)+1
2110 IF DIR=1 AND EY<42 THEN LET EY=EY+1
2120 IF DIR=2 AND EX<62 THEN LET EX=EX+1
2130 IF DIR=3 AND EY>28 THEN LET EY=EY-1
2140 IF DIR=4 AND EX>1 THEN LET EX=EX-1
2150 LET EX=EX+DX
2160 LET EY=EY+DY
2170 IF EY<13 OR EY>43 THEN GOTO 2200
2180 IF EX>=1 AND EX<65 THEN PLOT EX-1,EY
2190 IF EX>-2 AND EX<63 THEN PLOT EX+1,EY
2200 IF EX<0 OR EX>63 THEN GOTO 2230
2210 IF EY>13 AND EY<45 THEN PLOT EX,EY-1
2220 IF EY>11 AND EY<43 THEN PLOT EX,EY+1
2230 RETURN
2240 LET SHIP=1
2250 LET EL=INT (RND*3)+2
2260 LET EX=INT (RND*62)+1
2270 LET EY=INT (RND*10)+33
2280 GOTO 2170
2500 REM FIRE LASER
2510 FOR I=14 TO 7 STEP -1
2520 PRINT AT I,22-I;"\.'"
2530 PRINT AT I,9+I;"\'."
2540 NEXT I
2550 PAUSE 4
2560 FOR I=14 TO 7 STEP -1
2570 PRINT AT I,22-I;" "
2580 PRINT AT I,9+I;" "
2590 NEXT I
2600 IF EY<29 OR EY>30 THEN RETURN
2610 IF EX<30 OR EX>33 THEN RETURN
2620 LET EL=EL-1
2630 RETURN
2700 REM SHIP EXPLODES
2710 LET SHIP=0
2720 FOR I=1 TO 2
2730 PLOT EX,EY
2740 PLOT EX-1,EY
2750 PLOT EX+1,EY
2760 PLOT EX,EY-1
2770 PLOT EX,EY+1
2780 UNPLOT EX,EY
2790 PLOT EX-2,EY-2
2800 PLOT EX+2,EY-2
2810 PLOT EX-2,EY+2
2820 PLOT EX+2,EY+2
2830 UNPLOT EX-1,EY
2840 UNPLOT EX+1,EY
2850 UNPLOT EX,EY-1
2860 UNPLOT EX,EY+1
2870 UNPLOT EX-2,EY-2
2880 UNPLOT EX+2,EY-2
2890 UNPLOT EX-2,EY+2
2900 UNPLOT EX+2,EY+2
2910 NEXT I
2920 RETURN
3000 REM DRAW DISPLAY
3010 FOR I=0 TO 31
3030 PRINT AT 15,I;"\.."
3040 NEXT I
3050 FOR I=16 TO 21
3060 PRINT AT I,7;"\ :"
3070 PRINT AT I,24;"\: "
3080 NEXT I
3090 PRINT AT 17,12;"\ .\..\.'\''\''\'.\..\. "
3100 PRINT AT 18,10;"\..\''\' ","   \ '\''\.."
3110 PRINT AT 19,9;"\.'","      \'."
3120 PRINT AT 20,8;"\ .\' ","      \ '\. "
3130 PRINT AT 21,8;"\ :  E L I T E   \: "
3140 PRINT AT 19,15;"\ :\:  "
3150 PRINT AT 17,0;"FUEL:"
3160 PRINT AT 18,0;"\##\##\##\##\##\##\##"
3170 PRINT AT 20,0;"ENERGY"
3180 PRINT AT 21,0;"\##\##\##\##\##\##\##"
3190 PRINT AT 17,25;"AMMO:"
3200 PRINT AT 18,25;"\##\##\##\##\##\##\##"
3210 PRINT AT 20,25;"SHIELD:"
3220 PRINT AT 21,25;"\##\##\##\##\##\##\##"
3230 RETURN
3500 REM SETTINGS
3510 LET SHIP=0
3520 LET STARS=0
3530 LET FIRE=CODE "F"
3540 LET LEFT=CODE "A"
3550 LET RIGHT=CODE "D"
3560 LET DOWN=CODE "W"
3570 LET UP=CODE "S"
3580 PRINT AT 0,0;"S:TART C:ONFIGURE?",,,"  DEFAULT: F,A,D,W,S"
3590 GOSUB 3810
3600 PRINT AT 0,0;"                  ",,,"                    "
3610 IF KEY=CODE "S" THEN RETURN
3620 PRINT AT 0,0;"PRESS KEY FOR ACTION:"
3630 PRINT AT 2,2;"FIRE?"
3640 GOSUB 3810
3650 LET FIRE=KEY
3660 PRINT AT 2,2;"LEFT?"
3670 GOSUB 3810
3680 LET LEFT=KEY
3690 PRINT AT 2,2;"RIGHT?"
3700 GOSUB 3810
3710 LET RIGHT=KEY
3720 PRINT AT 2,2;"UP?   "
3730 GOSUB 3810
3740 LET UP=KEY
3750 PRINT AT 2,2;"DOWN? "
3760 GOSUB 3810
3770 LET DOWN=KEY
3780 PRINT AT 0,0;"                     "
3790 PRINT AT 2,2;"      "
3800 RETURN
3810 REM GET KEY
3820 LET KEY=CODE INKEY$
3830 IF KEY<>0 THEN RETURN
3840 GOTO 3820
Haven't found any new bugs in ZXSimulator so this was a good exercise. Still lots to do. I'm being sneaky with INKEY$ as it and CODE/CHR$ currently are tied to ASCII. So you'll see me doing lots of IF INKEY$=CODE "K" so that I don't have to worry about actual numeric codes which would make things incompatible with the ZX81 since I haven't tried to create a map to the ZX81 character set.

Also, I may write a separate utility program that'll renumber the BASIC code for me. Pain to constantly have to change line numbers to keep things uniform. ZX81 doesn't support renumber feature.


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

This version of elite.bas adds a little game play where you lose ammo if you shoot and don't hit and also shields but that part is still a bit clunky. If you lose all your shields the game ends.

Code: Select all

10 REM ELITE
20 GOSUB 3200
400 REM PLAY
410 GOSUB 1500
420 GOTO 460
430 GOSUB 2400
440 GOSUB 1000
450 GOSUB 1100
460 GOSUB 2000
470 LET KEY=CODE INKEY$
480 IF KEY=0 THEN GOTO 440
490 IF KEY=FIRE THEN GOTO 430 
500 GOTO 410
999 STOP
1000 REM LASER SIGHT
1010 PRINT AT 6,14;"\.'"
1020 PRINT AT 6,17;"\'."
1030 PRINT AT 7,14;"\'."
1040 PRINT AT 7,17;"\.'"
1050 RETURN
1100 REM STAR FIELD
1110 IF STARS=0 THEN GOTO 1220
1120 LET S$=" "
1130 GOSUB 1300
1140 IF INT (RND*10)=1 THEN LET SM=SM+1
1150 LET SX=SX+DX
1160 LET SY=SY-DY
1170 LET SM=SM-DY
1180 IF SY+SM>13 THEN GOTO 1230
1190 LET S$="."
1200 GOSUB 1300
1210 RETURN
1220 LET STARS=1
1230 LET SM=0
1240 LET SX=INT (RND*3)+5
1250 LET SY=INT(RND*2)+4
1260 GOTO 1190
1300 REM STAR
1310 IF SY+SM>=0 AND SY+SM<14 AND SX-SM>=0 AND SX-SM<32 THEN PRINT AT SY+SM,SX-SM;S$
1320 IF SY+SM*2-4>=0 AND SY+SM*2-4<14 AND SX+10>=0 AND SX+10<32 THEN PRINT AT SY+SM*2-4,SX+10;S$
1330 IF SY+SM-1>=0 AND SY+SM-1<14 AND SX+SM+20>=0 AND SX+SM+20<32 THEN PRINT AT SY+SM-1,SX+SM+20;S$
1340 RETURN
1500 REM CONTROLS
1510 PRINT AT 18,15;"  "
1520 PRINT AT 19,14;" \ :\:  "
1530 PRINT AT 20,15;"  "
1540 IF DX<>DY THEN LET KEY=0
1550 LET DY=0
1560 LET DX=0
1570 IF KEY=LEFT THEN GOTO 1620
1580 IF KEY=RIGHT THEN GOTO 1650
1590 IF KEY=up THEN GOTO 1680
1600 IF KEY=DOWN THEN GOTO 1710
1610 RETURN
1620 LET DX=DX+1
1630 PRINT AT 19,14;"\ :"
1640 RETURN
1650 LET DX=DX-1
1660 PRINT AT 19,17;"\: "
1670 RETURN
1680 LET DY=DY-1
1690 PRINT AT 18,15;"\ '\' "
1700 RETURN
1710 LET DY=DY+1
1720 PRINT AT 20,15;"\ .\. "
1730 RETURN
2000 REM ENEMY SHIP
2010 IF SHIP=0 AND INT (RND*6)<>1 THEN RETURN
2020 IF SHIP=0 THEN GOTO 2240
2030 IF EY<13 OR EY>43 THEN GOTO 2060
2040 IF EX>=1 AND EX<65 THEN UNPLOT EX-1,EY
2050 IF EX>-2 AND EX<63 THEN UNPLOT EX+1,EY
2060 IF EX<0 OR EX>64 THEN GOTO 2090
2070 IF EY>13 AND EY<45 THEN UNPLOT EX,EY-1
2080 IF EY>11 AND EY<43 THEN UNPLOT EX,EY+1
2090 IF EL=0 THEN GOTO 2900
2100 LET DIR=INT (RND*8)+1
2110 IF DIR=1 AND EY<42 THEN LET EY=EY+1
2120 IF DIR=2 AND EX<62 THEN LET EX=EX+1
2130 IF DIR=3 AND EY>28 THEN LET EY=EY-1
2140 IF DIR=4 AND EX>1 THEN LET EX=EX-1
2150 LET EX=EX+DX
2160 LET EY=EY+DY
2170 IF EY<13 OR EY>43 THEN GOTO 2200
2180 IF EX>=1 AND EX<65 THEN PLOT EX-1,EY
2190 IF EX>-2 AND EX<63 THEN PLOT EX+1,EY
2200 IF EX<0 OR EX>63 THEN GOTO 2230
2210 IF EY>13 AND EY<45 THEN PLOT EX,EY-1
2220 IF EY>11 AND EY<43 THEN PLOT EX,EY+1
2230 RETURN
2240 LET SHIP=1
2250 LET EL=INT (RND*3)+2
2260 LET EX=INT (RND*62)+1
2270 LET EY=INT (RND*10)+33
2280 GOTO 2170
2400 REM FIRE LASER
2410 IF AMMO=0 THEN GOTO 2510
2420 FOR I=14 TO 7 STEP -1
2430 PRINT AT I,22-I;"\.'"
2440 PRINT AT I,9+I;"\'."
2450 NEXT I
2460 PAUSE 4
2470 FOR I=14 TO 7 STEP -1
2480 PRINT AT I,22-I;" "
2490 PRINT AT I,9+I;" "
2500 NEXT I
2510 IF EY<29 OR EY>30 THEN GOTO 2570
2520 IF EX<30 OR EX>33 THEN GOTO 2570
2530 IF AMMO=0 THEN GOTO 2590
2540 LET EL=EL-1
2550 IF AMMO<7 THEN LET AMMO=AMMO+1
2560 GOTO 2750
2570 IF AMMO>0 THEN LET AMMO=AMMO-1
2580 GOTO 2750
2590 LET SHIELD=SHIELD-1
2600 GOSUB 2800
2610 LET AMMO=AMMO+1
2620 GOTO 2750
2650 REM FUEL
2660 IF FUEL=0 THEN RETURN
2670 LET BAR=FUEL
2680 PRINT AT 18,0;
2690 GOTO 2850
2700 REM ENERGY
2710 LET BAR=ENERGY
2720 PRINT AT 21,0;
2730 IF ENERGY=0 THEN GOTO 4000
2740 GOTO 2850
2750 REM AMMO
2760 LET BAR=AMMO
2770 PRINT AT 18,25;
2780 GOTO 2850
2800 REM SHIELD
2810 LET BAR=SHIELD
2820 PRINT AT 21,25;
2830 IF SHIELD=0 THEN GOTO 4000
2850 FOR I=1 TO 7
2860 IF I<=BAR THEN PRINT "\##";
2870 IF I>BAR THEN PRINT " ";
2880 NEXT I
2890 RETURN
2900 REM SHIP EXPLODES
2910 LET SHIP=0
2920 FOR I=1 TO 2
2930 PLOT EX,EY
2940 PLOT EX-1,EY
2950 PLOT EX+1,EY
2960 PLOT EX,EY-1
2970 PLOT EX,EY+1
2980 UNPLOT EX,EY
2990 PLOT EX-2,EY-2
3000 PLOT EX+2,EY-2
3010 PLOT EX-2,EY+2
3020 PLOT EX+2,EY+2
3030 UNPLOT EX-1,EY
3040 UNPLOT EX+1,EY
3050 UNPLOT EX,EY-1
3060 UNPLOT EX,EY+1
3070 UNPLOT EX-2,EY-2
3080 UNPLOT EX+2,EY-2
3090 UNPLOT EX-2,EY+2
3100 UNPLOT EX+2,EY+2
3110 NEXT I
3120 LET AMMO=7
3130 GOTO 2750
3200 REM SETTINGS
3210 LET SHIP=0
3220 LET STARS=0
3230 LET FUEL=7
3240 LET ENERGY=7
3250 LET AMMO=7
3260 LET SHIELD=7
3270 LET FIRE=CODE "F"
3280 LET LEFT=CODE "A"
3290 LET RIGHT=CODE "D"
3300 LET DOWN=CODE "W"
3310 LET UP=CODE "S"
3320 LET DY=0
3330 LET DX=1
3340 LET EX=0
3350 LET EY=0
3360 LET EL=0
3400 REM DRAW DISPLAY
3410 FOR I=0 TO 31
3420 PRINT AT 15,I;"\.."
3430 NEXT I
3440 FOR I=16 TO 21
3450 PRINT AT I,7;"\ :"
3460 PRINT AT I,24;"\: "
3470 NEXT I
3480 PRINT AT 17,12;"\ .\..\.'\''\''\'.\..\. "
3490 PRINT AT 18,10;"\..\''\' ","   \ '\''\.."
3500 PRINT AT 19,9;"\.'","      \'."
3510 PRINT AT 20,8;"\ .\' ","      \ '\. "
3520 PRINT AT 21,8;"\ :  E L I T E   \: "
3530 PRINT AT 19,15;"\ :\:  "
3540 PRINT AT 17,0;"FUEL:"
3550 GOSUB 2650
3560 PRINT AT 20,0;"ENERGY"
3570 GOSUB 2700
3580 PRINT AT 17,25;"AMMO:"
3590 GOSUB 2750
3600 PRINT AT 20,25;"SHIELD:"
3610 GOSUB 2800
3650 REM CONFIGURE
3660 PRINT AT 0,0;"S:TART C:ONFIGURE?",,,"  DEFAULT: F,A,D,W,S"
3670 GOSUB 3900
3680 PRINT AT 0,0;"                  ",,,"                    "
3690 IF KEY=CODE "S" THEN RETURN
3700 PRINT AT 0,0;"PRESS KEY FOR ACTION:"
3710 PRINT AT 2,2;"FIRE?"
3720 GOSUB 3900
3730 LET FIRE=KEY
3740 PRINT AT 2,2;"LEFT?"
3750 GOSUB 3900
3760 LET LEFT=KEY
3770 PRINT AT 2,2;"RIGHT?"
3780 GOSUB 3900
3790 LET RIGHT=KEY
3800 PRINT AT 2,2;"UP?   "
3810 GOSUB 3900
3820 LET UP=KEY
3830 PRINT AT 2,2;"DOWN? "
3840 GOSUB 3900
3850 LET DOWN=KEY
3860 PRINT AT 0,0;"                     "
3870 PRINT AT 2,2;"      "
3880 RETURN
3900 REM GET KEY
3910 LET KEY=CODE INKEY$
3920 IF KEY<>0 THEN RETURN
3930 GOTO 3910
4000 REM END GAME
4010 PRINT AT 6,14;"    "
4020 PRINT AT 7,14;"    "
4030 GOSUB 2850
4040 FOR I=1 TO 3
4050 PRINT AT 7,11;"GAME OVER!"
4060 PAUSE 4
4070 PRINT AT 7,11;"%G%A%M%E% %O%V%E%R%!"
4080 NEXT I
4090 PRINT AT 7,11;"GAME OVER!"
4100 STOP


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

Ok, finished part 1 of the Elite demo. It has full play capabilities and it's actually pretty hard to play. It's part 1 because it doesn't have any of Elite's cool features like planet hopping, station docking and bartering for goods. I do want to add that in. Right now it's blasting pirates and grabbing their fuel, ammo, and anything else they leave floating in space once they've been destroyed.

Game play is:
  • You lose ammo whenever you fire
  • Same goes for shields though it depends on if you are firing at enemy in which case shields may hold up or drain further
  • Fuel gets used up when you maneuver so be cautious of movement
  • You gain energy when you destroy a pirate and you also get to grab ammo and fuel and regenerate your shields
  • If you run out of fuel, ammo, or shields you lose
  • If you destroy all the pirates you end the game (or at least part 1 of it)
Below is the BASIC that you can load into a ZX81 emulator (like EightyOne) after converting it to a .p file (also attached) or you can simply load it into ZXSimulator on the QL (look on previous page for latest zip file). It runs ok on a ZX81 and on ZXSimulator on an unexpanded QL...it's playable. Runs way better when accelerated of course.

Now that part 1 of Elite demo is done, I can start concentrating on improving and finalizing the ZXSimulator. Need to add floating point and all the functions that go with it, all while not slowing it down too much. We will see how it goes.

BASIC for Elite on ZXSimulator/ZX81:

Code: Select all

10 REM ELITE
20 GOSUB 3200
400 REM PLAY
410 GOSUB 1500
420 GOTO 440
430 GOSUB 2400
440 GOSUB 1000
450 GOSUB 1100
460 GOSUB 2000
470 LET KEY=CODE INKEY$
480 IF KEY=0 THEN GOTO 440
490 IF KEY=FIRE THEN GOTO 430
500 GOTO 410
999 STOP
1000 REM LASER SIGHT
1010 PRINT AT 6,14;"\.'"
1020 PRINT AT 6,17;"\'."
1030 PRINT AT 7,14;"\'."
1040 PRINT AT 7,17;"\.'"
1050 RETURN
1100 REM STAR FIELD
1110 IF STARS=0 THEN GOTO 1220
1120 LET S$=" "
1130 GOSUB 1300
1140 IF INT (RND*10)=1 THEN LET SM=SM+1
1150 LET SX=SX+DX
1160 LET SY=SY-DY
1170 LET SM=SM-DY
1180 IF SY+SM>13 THEN GOTO 1230
1190 LET S$="."
1200 GOSUB 1300
1210 RETURN
1220 LET STARS=1
1230 LET SM=0
1240 LET SX=INT (RND*3)+5
1250 LET SY=INT(RND*2)+4
1260 GOTO 1190
1300 REM STAR
1310 IF SY+SM>=0 AND SY+SM<14 AND SX-SM>=0 AND SX-SM<32 THEN PRINT AT SY+SM,SX-SM;S$
1320 IF SY+SM*2-4>=0 AND SY+SM*2-4<14 AND SX+10>=0 AND SX+10<32 THEN PRINT AT SY+SM*2-4,SX+10;S$
1330 IF SY+SM-1>=0 AND SY+SM-1<14 AND SX+SM+20>=0 AND SX+SM+20<32 THEN PRINT AT SY+SM-1,SX+SM+20;S$
1340 RETURN
1500 REM CONTROLS
1510 PRINT AT 18,15;"  "
1520 PRINT AT 19,14;" \ :\:  "
1530 PRINT AT 20,15;"  "
1540 IF DX<>DY THEN LET KEY=0
1550 LET DY=0
1560 LET DX=0
1570 IF KEY=LEFT THEN GOTO 1620
1580 IF KEY=RIGHT THEN GOTO 1650
1590 IF KEY=up THEN GOTO 1680
1600 IF KEY=DOWN THEN GOTO 1710
1610 RETURN
1620 LET DX=DX+1
1630 PRINT AT 19,14;"\ :"
1640 GOTO 1730
1650 LET DX=DX-1
1660 PRINT AT 19,17;"\: "
1670 GOTO 1730
1680 LET DY=DY-1
1690 PRINT AT 18,15;"\ '\' "
1700 GOTO 1730
1710 LET DY=DY+1
1720 PRINT AT 20,15;"\ .\. "
1730 GOSUB 2650
1740 LET FUEL=FUEL-1
1750 IF FUEL=0 THEN GOTO 4010
1760 RETURN
2000 REM ENEMY SHIP
2010 IF SHIP=0 AND INT (RND*6)<>1 THEN RETURN
2020 IF SHIP=0 THEN GOTO 2240
2030 IF EY<13 OR EY>43 THEN GOTO 2060
2040 IF EX>=1 AND EX<65 THEN UNPLOT EX-1,EY
2050 IF EX>-2 AND EX<63 THEN UNPLOT EX+1,EY
2060 IF EX<0 OR EX>63 THEN GOTO 2090
2070 IF EY>13 AND EY<45 THEN UNPLOT EX,EY-1
2080 IF EY>11 AND EY<43 THEN UNPLOT EX,EY+1
2090 IF EL=0 THEN GOTO 2850
2100 LET DIR=INT (RND*8)+1
2110 IF DIR=1 AND EY<42 THEN LET EY=EY+1
2120 IF DIR=2 AND EX<62 THEN LET EX=EX+1
2130 IF DIR=3 AND EY>28 THEN LET EY=EY-1
2140 IF DIR=4 AND EX>1 THEN LET EX=EX-1
2150 LET EX=EX+DX
2160 LET EY=EY+DY
2170 IF EY<13 OR EY>43 THEN GOTO 2200
2180 IF EX>=1 AND EX<65 THEN PLOT EX-1,EY
2190 IF EX>-2 AND EX<63 THEN PLOT EX+1,EY
2200 IF EX<0 OR EX>63 THEN GOTO 2230
2210 IF EY>13 AND EY<45 THEN PLOT EX,EY-1
2220 IF EY>11 AND EY<43 THEN PLOT EX,EY+1
2230 RETURN
2240 LET SHIP=1
2250 LET EL=INT (RND*3)+2
2260 LET EX=INT (RND*62)+1
2270 LET EY=INT (RND*10)+33
2280 GOTO 2170
2400 REM FIRE LASER
2410 FOR I=14 TO 7 STEP -1
2420 PRINT AT I,22-I;"\.'"
2430 PRINT AT I,9+I;"\'."
2440 NEXT I
2450 PAUSE 4
2460 FOR I=14 TO 7 STEP -1
2470 PRINT AT I,22-I;" "
2480 PRINT AT I,9+I;" "
2490 NEXT I
2500 IF EY<29 OR EY>30 THEN GOTO 2540
2510 IF EX<30 OR EX>33 THEN GOTO 2540
2520 LET EL=EL-1
2530 IF EL=0 THEN RETURN
2540 GOSUB 2750
2550 LET AMMO=AMMO-1
2560 IF AMMO=0 THEN GOTO 4060
2570 GOSUB 2800
2580 LET SHIELD=SHIELD-INT (RND*2)
2590 IF SHIELD=0 THEN GOTO 4090
2650 REM FUEL
2660 LET BAR=INT (FUEL/3)
2670 PRINT AT 18,BAR;G$;
2680 RETURN
2700 REM ENERGY
2710 LET BAR=INT ((ENERGY-1)/2)
2720 PRINT AT 21,BAR;G$
2730 IF ENERGY=13 THEN GOTO 4040
2740 RETURN
2750 REM AMMO
2760 LET BAR=INT (AMMO/2)
2770 PRINT AT 18,25+BAR;G$
2780 RETURN
2800 REM SHIELD
2810 LET BAR=INT (SHIELD/2)
2820 PRINT AT 21,25+BAR;G$
2830 RETURN
2850 REM SHIP EXPLODES
2860 LET SHIP=0
2870 FOR I=1 TO 2
2880 PLOT EX,EY
2890 PLOT EX-1,EY
2900 PLOT EX+1,EY
2910 PLOT EX,EY-1
2920 PLOT EX,EY+1
2930 UNPLOT EX,EY
2940 PLOT EX-2,EY-2
2950 PLOT EX+2,EY-2
2960 PLOT EX-2,EY+2
2970 PLOT EX+2,EY+2
2980 UNPLOT EX-1,EY
2990 UNPLOT EX+1,EY
3000 UNPLOT EX,EY-1
3010 UNPLOT EX,EY+1
3020 UNPLOT EX-2,EY-2
3030 UNPLOT EX+2,EY-2
3040 UNPLOT EX-2,EY+2
3050 UNPLOT EX+2,EY+2
3060 NEXT I
3070 LET G$="\##"
3080 FOR I=RND*2+1 TO 0 STEP -1 
3090 GOSUB 2650
3100 IF I>0 AND FUEL<18 THEN LET FUEL=FUEL+3
3110 GOSUB 2750
3120 IF I>0 AND AMMO<12 THEN LET AMMO=AMMO+2
3130 GOSUB 2800
3140 IF I>0 AND SHIELD<12 THEN LET SHIELD=SHIELD+2
3150 NEXT I
3160 LET ENERGY=ENERGY+1
3170 GOSUB 2700
3180 LET G$=" "
3190 RETURN
3200 REM SETTINGS
3210 LET SHIP=0
3220 LET STARS=0
3230 LET FUEL=20
3240 LET ENERGY=0
3250 LET AMMO=13
3260 LET SHIELD=13
3270 LET FIRE=CODE "F"
3280 LET LEFT=CODE "A"
3290 LET RIGHT=CODE "D"
3300 LET DOWN=CODE "W"
3310 LET UP=CODE "S"
3320 LET DY=0
3330 LET DX=1
3340 LET EX=0
3350 LET EY=0
3360 LET EL=0
3370 LET G$=" "
3400 REM DRAW DISPLAY
3410 FOR I=0 TO 31
3420 PRINT AT 15,I;"\.."
3430 NEXT I
3440 FOR I=16 TO 21
3450 PRINT AT I,7;"\ :"
3460 PRINT AT I,24;"\: "
3470 NEXT I
3480 PRINT AT 17,12;"\ .\..\.'\''\''\'.\..\. "
3490 PRINT AT 18,10;"\..\''\' ","   \ '\''\.."
3500 PRINT AT 19,9;"\.'","      \'."
3510 PRINT AT 20,8;"\ .\' ","      \ '\. "
3520 PRINT AT 21,8;"\ :  E L I T E   \: "
3530 PRINT AT 19,15;"\ :\:  "
3540 PRINT AT 17,0;"FUEL:"
3550 PRINT AT 18,0;"\##\##\##\##\##\##\##"
3560 PRINT AT 20,0;"ENERGY"
3570 PRINT AT 21,0;"\##"
3580 PRINT AT 17,25;"AMMO:"
3590 PRINT AT 18,25;"\##\##\##\##\##\##\##"
3600 PRINT AT 20,25;"SHIELD:"
3610 PRINT AT 21,25;"\##\##\##\##\##\##\##"
3650 REM CONFIGURE
3660 PRINT AT 0,0;"S:TART C:ONFIGURE?",,,"  DEFAULT: F,A,D,W,S"
3670 GOSUB 3900
3680 PRINT AT 0,0;"                  ",,,"                    "
3690 IF KEY=CODE "S" THEN RETURN
3700 PRINT AT 0,0;"PRESS KEY FOR ACTION:"
3710 PRINT AT 2,2;"FIRE?"
3720 GOSUB 3900
3730 LET FIRE=KEY
3740 PRINT AT 2,2;"LEFT?"
3750 GOSUB 3900
3760 LET LEFT=KEY
3770 PRINT AT 2,2;"RIGHT?"
3780 GOSUB 3900
3790 LET RIGHT=KEY
3800 PRINT AT 2,2;"UP?   "
3810 GOSUB 3900
3820 LET UP=KEY
3830 PRINT AT 2,2;"DOWN? "
3840 GOSUB 3900
3850 LET DOWN=KEY
3860 PRINT AT 0,0;"                     "
3870 PRINT AT 2,2;"      "
3880 RETURN
3900 REM GET KEY
3910 LET KEY=CODE INKEY$
3920 IF KEY<>0 THEN RETURN
3930 GOTO 3910
4000 REM GAME END
4010 LET M$="YOU RAN OUT OF FUEL"
4020 GOSUB 2650
4030 GOTO 4100
4040 LET M$="YOU GOT ALL OF THEM"
4050 GOTO 4100
4060 LET M$="YOU RAN OUT OF AMMO"
4070 GOSUB 2750
4080 GOTO 4100
4090 LET M$="YOUR SHIELDS FAILED"
4100 GOSUB 2800
4110 REM MESSAGE
4120 PRINT AT 6,14;"    "
4130 PRINT AT 7,14;"    "
4140 FOR I=1 TO 3
4150 PRINT AT 6,11;"GAME OVER"
4160 PAUSE 20
4170 PRINT AT 6,11;"%G%A%M%E% %O%V%E%R"
4180 PAUSE 20
4190 NEXT I
4200 PRINT AT 6,11;"GAME OVER"
4210 PRINT AT 7,6;M$
4220 STOP
P file:
elite.zip
(2.8 KiB) Downloaded 161 times


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

So playing Elite on the ZXSimulator and on the EightyOne I found that the controls needed a bit improvement so I made a small change.

The up/down/left/right controls needed two inputs to change state. So basically you would hit left and to go right you'd have to hit that twice, once to get out of left and then to get into right. So basically, the control stick would stay in the last position and a new position change would reset it to zero. This required two control stick (joy stick) movements to change direction.

The improved controls now will change instantly, so you can go from left to right or up to down or left to up, etc... If you want to set the control stick to the center then just repeat the current position (i.e. if you are moving in the up direction, if you move the control stick up it resets to center). So that way you can quickly change directions but still have the ability to set the control stick to neutral.

Much better play and it works on a fast QL emulating the ZXSimulator and just as well on an unexpanded QL running ZXSimulator or the EightyOne emulator running the game. It helps when things are really slow since you have to do less input to get shots off to destroy the pirate...it's why I changed it since I was testing it out on an unexpanded QL and found firing to take a bit of time.

To minimize code additions I utilized the fact that ZX81 BASIC equates true and false to zero and one (like C). So I have a statement to set the "delta X" as follows: LET DX=DX<>1. So if "Delta X" was already 1 it sets it to 0 otherwise to 1.

A really small change is that I made shields fail more easily during game play since it seemed that only ammo and fuel were causing game losses.

P file:
elite.zip
(2.82 KiB) Downloaded 148 times
Source:

Code: Select all

10 REM ELITE
20 GOSUB 3200
400 REM PLAY
410 GOSUB 1500
420 GOTO 440
430 GOSUB 2400
440 GOSUB 1000
450 GOSUB 1100
460 GOSUB 2000
470 LET KEY=CODE INKEY$
480 IF KEY=0 THEN GOTO 440
490 IF KEY=FIRE THEN GOTO 430
500 GOTO 410
999 STOP
1000 REM LASER SIGHT
1010 PRINT AT 6,14;"\.'"
1020 PRINT AT 6,17;"\'."
1030 PRINT AT 7,14;"\'."
1040 PRINT AT 7,17;"\.'"
1050 RETURN
1100 REM STAR FIELD
1110 IF STARS=0 THEN GOTO 1220
1120 LET S$=" "
1130 GOSUB 1300
1140 IF INT (RND*10)=1 THEN LET SM=SM+1
1150 LET SX=SX+DX
1160 LET SY=SY-DY
1170 LET SM=SM-DY
1180 IF SY+SM>13 THEN GOTO 1230
1190 LET S$="."
1200 GOSUB 1300
1210 RETURN
1220 LET STARS=1
1230 LET SM=0
1240 LET SX=INT (RND*3)+5
1250 LET SY=INT(RND*2)+4
1260 GOTO 1190
1300 REM STAR
1310 IF SY+SM>=0 AND SY+SM<14 AND SX-SM>=0 AND SX-SM<32 THEN PRINT AT SY+SM,SX-SM;S$
1320 IF SY+SM*2-4>=0 AND SY+SM*2-4<14 AND SX+10>=0 AND SX+10<32 THEN PRINT AT SY+SM*2-4,SX+10;S$
1330 IF SY+SM-1>=0 AND SY+SM-1<14 AND SX+SM+20>=0 AND SX+SM+20<32 THEN PRINT AT SY+SM-1,SX+SM+20;S$
1340 RETURN
1500 REM CONTROLS
1510 PRINT AT 18,15;"  "
1520 PRINT AT 19,14;" \ :\:  "
1530 PRINT AT 20,15;"  "
1540 IF KEY=LEFT THEN GOTO 1590
1550 IF KEY=RIGHT THEN GOTO 1640
1560 IF KEY=up THEN GOTO 1690
1570 IF KEY=DOWN THEN GOTO 1740
1580 RETURN
1590 LET DX=DX<>1
1600 LET DY=0
1610 IF DX=0 THEN RETURN
1620 PRINT AT 19,14;"\ :"
1630 GOTO 1780
1640 LET DX=-(DX<>-1)
1650 LET DY=0
1660 IF DX=0 THEN RETURN
1670 PRINT AT 19,17;"\: "
1680 GOTO 1780
1690 LET DX=0
1700 LET DY=-(DY<>-1)
1710 IF DY=0 THEN RETURN
1720 PRINT AT 18,15;"\ '\' "
1730 GOTO 1780
1740 LET DX=0
1750 LET DY=DY<>1
1760 IF DY=0 THEN RETURN
1770 PRINT AT 20,15;"\ .\. "
1780 GOSUB 2650
1790 LET FUEL=FUEL-1
1800 IF FUEL=0 THEN GOTO 4010
1810 RETURN
2000 REM ENEMY SHIP
2010 IF SHIP=0 AND INT (RND*6)<>1 THEN RETURN
2020 IF SHIP=0 THEN GOTO 2240
2030 IF EY<13 OR EY>43 THEN GOTO 2060
2040 IF EX>=1 AND EX<65 THEN UNPLOT EX-1,EY
2050 IF EX>-2 AND EX<63 THEN UNPLOT EX+1,EY
2060 IF EX<0 OR EX>63 THEN GOTO 2090
2070 IF EY>13 AND EY<45 THEN UNPLOT EX,EY-1
2080 IF EY>11 AND EY<43 THEN UNPLOT EX,EY+1
2090 IF EL=0 THEN GOTO 2850
2100 LET DIR=INT (RND*8)+1
2110 IF DIR=1 AND EY<42 THEN LET EY=EY+1
2120 IF DIR=2 AND EX<62 THEN LET EX=EX+1
2130 IF DIR=3 AND EY>28 THEN LET EY=EY-1
2140 IF DIR=4 AND EX>1 THEN LET EX=EX-1
2150 LET EX=EX+DX
2160 LET EY=EY+DY
2170 IF EY<13 OR EY>43 THEN GOTO 2200
2180 IF EX>=1 AND EX<65 THEN PLOT EX-1,EY
2190 IF EX>-2 AND EX<63 THEN PLOT EX+1,EY
2200 IF EX<0 OR EX>63 THEN RETURN
2210 IF EY>13 AND EY<45 THEN PLOT EX,EY-1
2220 IF EY>11 AND EY<43 THEN PLOT EX,EY+1
2230 RETURN
2240 LET SHIP=1
2250 LET EL=INT (RND*3)+2
2260 LET EX=INT (RND*62)+1
2270 LET EY=INT (RND*10)+33
2280 GOTO 2170
2400 REM FIRE LASER
2410 FOR I=14 TO 7 STEP -1
2420 PRINT AT I,22-I;"\.'"
2430 PRINT AT I,9+I;"\'."
2440 NEXT I
2450 PAUSE 4
2460 FOR I=14 TO 7 STEP -1
2470 PRINT AT I,22-I;" "
2480 PRINT AT I,9+I;" "
2490 NEXT I
2500 IF EY<29 OR EY>30 THEN GOTO 2570
2510 IF EX<30 OR EX>33 THEN GOTO 2570
2520 LET EL=EL-1
2530 IF EL=0 THEN RETURN
2540 GOSUB 2800
2550 LET SHIELD=SHIELD-INT (RND*3)
2560 IF SHIELD=0 THEN GOTO 4090
2570 GOSUB 2750
2580 LET AMMO=AMMO-1
2590 IF AMMO=0 THEN GOTO 4060
2600 RETURN
2650 REM FUEL
2660 LET BAR=INT (FUEL/3)
2670 PRINT AT 18,BAR;G$;
2680 RETURN
2700 REM ENERGY
2710 LET BAR=INT ((ENERGY-1)/2)
2720 PRINT AT 21,BAR;G$
2730 IF ENERGY=13 THEN GOTO 4040
2740 RETURN
2750 REM AMMO
2760 LET BAR=INT (AMMO/2)
2770 PRINT AT 18,25+BAR;G$
2780 RETURN
2800 REM SHIELD
2810 LET BAR=INT (SHIELD/2)
2820 PRINT AT 21,25+BAR;G$
2830 RETURN
2850 REM SHIP EXPLODES
2860 LET SHIP=0
2870 FOR I=1 TO 2
2880 PLOT EX,EY
2890 PLOT EX-1,EY
2900 PLOT EX+1,EY
2910 PLOT EX,EY-1
2920 PLOT EX,EY+1
2930 UNPLOT EX,EY
2940 PLOT EX-2,EY-2
2950 PLOT EX+2,EY-2
2960 PLOT EX-2,EY+2
2970 PLOT EX+2,EY+2
2980 UNPLOT EX-1,EY
2990 UNPLOT EX+1,EY
3000 UNPLOT EX,EY-1
3010 UNPLOT EX,EY+1
3020 UNPLOT EX-2,EY-2
3030 UNPLOT EX+2,EY-2
3040 UNPLOT EX-2,EY+2
3050 UNPLOT EX+2,EY+2
3060 NEXT I
3070 LET G$="\##"
3080 FOR I=RND*2+1 TO 0 STEP -1 
3090 GOSUB 2650
3100 IF I>0 AND FUEL<18 THEN LET FUEL=FUEL+3
3110 GOSUB 2750
3120 IF I>0 AND AMMO<12 THEN LET AMMO=AMMO+2
3130 GOSUB 2800
3140 IF I>0 AND SHIELD<12 THEN LET SHIELD=SHIELD+1
3150 NEXT I
3160 LET ENERGY=ENERGY+1
3170 GOSUB 2700
3180 LET G$=" "
3190 RETURN
3200 REM SETTINGS
3210 LET SHIP=0
3220 LET STARS=0
3230 LET FUEL=20
3240 LET ENERGY=0
3250 LET AMMO=13
3260 LET SHIELD=13
3270 LET FIRE=CODE "F"
3280 LET LEFT=CODE "A"
3290 LET RIGHT=CODE "D"
3300 LET DOWN=CODE "W"
3310 LET UP=CODE "S"
3320 LET DY=0
3330 LET DX=0
3340 LET EX=0
3350 LET EY=0
3360 LET EL=0
3370 LET G$=" "
3400 REM DRAW DISPLAY
3410 FOR I=0 TO 31
3420 PRINT AT 15,I;"\.."
3430 NEXT I
3440 FOR I=16 TO 21
3450 PRINT AT I,7;"\ :"
3460 PRINT AT I,24;"\: "
3470 NEXT I
3480 PRINT AT 17,12;"\ .\..\.'\''\''\'.\..\. "
3490 PRINT AT 18,10;"\..\''\' ","   \ '\''\.."
3500 PRINT AT 19,9;"\.'","      \'."
3510 PRINT AT 20,8;"\ .\' ","      \ '\. "
3520 PRINT AT 21,8;"\ :  E L I T E   \: "
3530 PRINT AT 19,15;"\ :\:  "
3540 PRINT AT 17,0;"FUEL:"
3550 PRINT AT 18,0;"\##\##\##\##\##\##\##"
3560 PRINT AT 20,0;"ENERGY"
3570 PRINT AT 17,25;"AMMO:"
3580 PRINT AT 18,25;"\##\##\##\##\##\##\##"
3590 PRINT AT 20,25;"SHIELD:"
3600 PRINT AT 21,25;"\##\##\##\##\##\##\##"
3650 REM CONFIGURE
3660 PRINT AT 0,0;"S:TART C:ONFIGURE?",,,"  DEFAULT: F,A,D,W,S"
3670 GOSUB 3900
3680 PRINT AT 0,0;"                  ",,,"                    "
3690 IF KEY=CODE "S" THEN RETURN
3700 PRINT AT 0,0;"PRESS KEY FOR ACTION:"
3710 PRINT AT 2,2;"FIRE?"
3720 GOSUB 3900
3730 LET FIRE=KEY
3740 PRINT AT 2,2;"LEFT?"
3750 GOSUB 3900
3760 LET LEFT=KEY
3770 PRINT AT 2,2;"RIGHT?"
3780 GOSUB 3900
3790 LET RIGHT=KEY
3800 PRINT AT 2,2;"UP?   "
3810 GOSUB 3900
3820 LET UP=KEY
3830 PRINT AT 2,2;"DOWN? "
3840 GOSUB 3900
3850 LET DOWN=KEY
3860 PRINT AT 0,0;"                     "
3870 PRINT AT 2,2;"      "
3880 LET KEY=0
3890 RETURN
3900 REM GET KEY
3910 LET KEY=CODE INKEY$
3920 IF KEY<>0 THEN RETURN
3930 GOTO 3910
4000 REM GAME END
4010 LET M$="YOU RAN OUT OF FUEL"
4020 GOSUB 2650
4030 GOTO 4100
4040 LET M$="YOU GOT ALL OF THEM"
4050 GOTO 4100
4060 LET M$="YOU RAN OUT OF AMMO"
4070 GOSUB 2750
4080 GOTO 4100
4090 LET M$="YOUR SHIELDS FAILED"
4100 GOSUB 2800
4110 REM MESSAGE
4120 PRINT AT 6,14;"    "
4130 PRINT AT 7,14;"    "
4140 FOR I=1 TO 3
4150 PRINT AT 6,11;"GAME OVER"
4160 PAUSE 20
4170 PRINT AT 6,11;"%G%A%M%E% %O%V%E%R"
4180 PAUSE 20
4190 NEXT I
4200 PRINT AT 6,11;"GAME OVER"
4210 PRINT AT 7,6;M$
4220 STOP


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

This has definitely been addictive. So I smoothed out graphics for both stars and pirates by getting rid of redundant checks and not refreshing the stars when nothing moved. It's a bit faster now. Fixed shields so that they get updated correctly. I keep losing by running out of AMMO or FUEL but get pretty close to running out of SHIELD strength as well.

I added a new feature that has the pirate go to hyperspace after some time and that has made the game harder. Say you shot the pirate 3 times or 4 times and you are ready for the final shot to destroy them (usually between 3 and 5) and boom, they are gone. You banked on grabbing their ammunition, fuel and shield power to regenerate but nope, gone. Next pirate you see is at full power and you are not.

Starting to play better on ZX81 and ZXSimulator on an unexpanded QL. Still takes a bit for the pirate to move into scope when they are way off to the side on the slower machines but once they get close things become interesting. I suppose you need to look at it as a high speed chase/battle in space where the pirate (bogey) is flying fast enough that you can't make quick maneuvers to get them into sights. On an accelerated QL running ZXSimulator the game flows much more arcade-like and the speed improvements have smoothed out graphics.

Future improvements need some work on the ZXsimulator itself. I have variables hardcoded at 32 and I think I have about 30 or so. Also, I didn't realize the TAB command existed, that would make the laser sight more efficient being shown with 2 PRINT statements vs 4. Funny how I spent all this time optimizing the interpreter and now I spent the last week optimizing the game running in the simulator. Life is optimization when you try and work with limited resources and it's kind of fun. In machine code on the ZX81 the game would play like on an accelerated QL running the interpreter and re-implemented on the QL in SuperBASIC would be speed -- any takers???

For fun I won't include the BASIC source this time directly, just the .p file. Below is a link to zxtool.exe and all you need to do is run in a command shell:

zxtool.exe elite.p > elite_bas

...and out comes the BASIC listing. So from a binary representation for the EightyOne emulator (is that the actual internal binary repesentaton for a ZX81?) to BASIC for the ZXSimulator just to show that compatiilty goes both ways.

P file:
elite.zip
(2.81 KiB) Downloaded 155 times
Link to zxtool.exe:

https://www.sinclairzxworld.com/downloa ... php?id=860

BTW, this was the only difference in going from text-to-p and then back to p-to-text. I used "% " for an inverse space and it mapped it to "\::" instead...ZXSimulator supports both.

< 4170 PRINT AT 6,11;"%G%A%M%E% %O%V%E%R"
---
> 4170 PRINT AT 6,11;"%G%A%M%E\::%O%V%E%R"


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

Forgot that space is black so I fixed it. Use zxtool.exe (link above) if you want the BASIC file to load into ZXSimulator.

P file:
elite.zip
(2.87 KiB) Downloaded 136 times
elite.png
elite.png (11.62 KiB) Viewed 3687 times


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

BTW, to get any of my BASIC listings to work or when using zxtool.exe on a .p file, the files need to be converted from DOS to QL (also UNIX) format. A good set of tools for that is found in the link below. You can just drag and drop them in Windows and voila the line-feed/carriage returns are fixed to line-feeds. The ZXSimulator barfs on carriage returns after the first line for those that tried the listings (I may fix that in the future so it just ignores them on read-in). When I include the BASIC demo programs in my zx_zip files they have been converted properly.

http://dos2unix.sourceforge.net/


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

Newest version of ZXSimulator. Not done yet but improves.
zx.zip
(28.1 KiB) Downloaded 137 times
Here's what's been added:
  • DIM statement added
  • CHR$ and CODE now use proper values (mostly, if unknown it will print ? and above 291 is reserved for QL)
  • STR$ and VAL implemented
  • NEW now wipes all variables and loops (and so does LOAD) and CLEAR was added to clear variables
  • speaking of LOAD, it now ignores '/r' so no need to convert to unix anymore
  • nesting of subroutines is now dynamic (variables still static in amount it can handle)
  • sped up by about 15%, last baseline was 98 seconds, slowed down to 104 seconds w/features...now at 86 seconds (compared to 57 for PAL ZX81)
  • string handling improved (concatenation now works and so does string equalities)
  • Elite.bas is now on the zip along with Banner.bas & Ball.bas. The game is complete in part 1. Next part will be planet hopping. Improved in speed.
Finally, a first, I got someone elses's program, Minesweeper.bas, to work on the ZXSimulator. Big step in development because I want it to be fully compatible.

Minesweeper.bas I found here:

http://www.zx81.de/english/soft_e.htm

If you open it up you'll see it starts like this:

Code: Select all

    0 REM  [3978 bytes]
    2 REM  [3969 bytes]     3 REM        %M%C%O%D%E%R\::%I%I         COPYRIGHT 1983   D C THRELFALL COMPILER AT 17300 PROG AT 20500
   10 REM  MINESWEEPER
Just delete line "0" and then ZXsimulator will read it in and run just fine. I think this was a dual (compiled and BASIC) version. There is this MCODE compiler for the ZX81 made in 1982 that does some sort of partial compilation. In any case, this is the whole BASIC program and it will load and run in ZXSimulator. It does some funky stuff with recursion/nesting so it needs all the memory space so you can't run it presently on an unexpanded QL but it's also very slow. So under QLAY with speed 1000 on the ZXSimulator it runs decently.

Give it a try. It's the first foreign program I've run on the ZXSImulator so it's pretty compatible already (even if it's still missing floating point).


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

Newest version:
zx.zip
(28.46 KiB) Downloaded 126 times
Fixed a bug that caused the Minesweeper program not to work on an unexpanded QL under ZXSimulator. It's good to try and run existing ZX81 BASIC programs as that stress tests the ZXSimulator. Lots of strange coding techniques I need to catch. I also wasn't doing TAB's correctly which I found out when running someone else's maze craze program (fixed now).

But the main bug crashing on Minsweeper was caused when I forgot to allocate memory for a DIM'ed variable when fetching an indexed entry value causing things to freeze up. Another error was introduced after having added the CLEAR command where I forgot to pass an argument into one of the clear-out functions which wasn't caught by the compiler but crashed the program in low memory. Also added the ability to DIM a string array which, to be honest, I don't see the purpose for. I suppose it bounds the size of a string variable until you do a CLEAR or NEW:

DIM A$(3)
LET A$="HELLO"
PRINT A$

this prints "HEL"

It also conforms string arrays a bit better to ZX81 so you can't do out-of-bounds indecies (my original BASIC just truncated to the range of the string bounds) without getting an error.

You can now play Minesweeper on an unexpanded QL if you have a lot of time. It is really slow. It's best run on QLAY with speed set to 100000 and delay set to 0. It's a pretty neat program written for the ZX81 but awfully slow. I'm guessing it's a dynamic programming implementation so it has to go through lots of recursion to figure out the neighborhood of all the mines. So it's not really playable unless you don't mind waiting minutes when you clear out a large portion of the screen.

Someone ought to convert that version to the QL in SuperBASIC since it really doesn't use much graphics and mostly relies on a single DIMension statement and oodles of FOR loops and GOSUB calls. The two version for the QL that I've found online both require an expanded QL and one needs the pointer environment. Any Minesweepers that run decently on an unexpanded QL?
Last edited by bwinkel67 on Wed May 06, 2020 9:32 am, edited 1 time in total.


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

So I've been working with Minesweeper and have spent some time optimizing the BASIC code for the ZX81. Some of the slowdowns had to do with excessive use of IF/THEN. One section was trying to create a blinking cursor, basically printing a black square and then replacing it with what's on the screen. It did this:

Code: Select all

  300 GOSUB 4000
  310 IF K$="5" AND X>1 THEN LET X=X-1
  320 IF K$="8" AND X<32 THEN LET X=X+1
  330 IF K$="6" AND Y<21 THEN LET Y=Y+1
  340 IF K$="7" AND Y>1 THEN LET Y=Y-1
  350 IF K$="O" THEN GOSUB 5000
  360 IF K$="M" THEN GOSUB 6000
  370 IF BM=1 THEN GOTO 7700
  400 IF N<>0 THEN GOTO 300
  ...
 3000 REM  DISPLAY SINGLE FIELD
 3005 LET E=21*(X-1)+Y
 3010 LET C$=CHR$ F(E)
 3020 IF C$="0" THEN PRINT " ";
 3030 IF C$>="1" AND C$<="8" THEN PRINT C$;
 3040 IF C$="9" THEN PRINT "%*";
 3050 IF C$>="A" AND C$<="J" THEN PRINT "\##";
 3060 IF C$>="K" AND C$<="T" THEN PRINT "%£";
 3070 IF C$>="U" THEN PRINT "%?";
 3990 RETURN 
 4000 REM  DISPLAY STAT, GET KEY
 4010 PRINT AT 0,0;N,AT 0,26;T
 4020 LET T=T+1
 4100 PRINT AT Y,X-1;"\::";
 4110 LET K$=INKEY$
 4120 PRINT AT Y,X-1;
 4130 GOSUB 3000
 4140 IF K$="" THEN GOTO 4100
 4990 RETURN 
The code in the 3000's is especially inefficient. So I replaced all those lines with this:

Code: Select all

  10 LET F$=" 12345678%*\##\##\##\##\##\##\##\##\##\##%#%#%#%#%#%#%#%#%#%#%?%?%?%?%?%?%?%?%?%?%?"
 ...
 120 PRINT AT 0,26;T
 130 LET T=T+1
 140 PRINT AT Y,X-1;"\::"
 150 LET KEY=CODE INKEY$
 160 PRINT AT Y,X-1;F$(F(21*(X-1)+Y)+1);
 170 IF KEY=0 THEN GOTO 140 
 180 IF KEY=LEFT AND X>1 THEN LET X=X-1
 190 IF KEY=RIGHT AND X<32 THEN LET X=X+1
 200 IF KEY=DOWN AND Y<21 THEN LET Y=Y+1
 210 IF KEY=UP AND Y>1 THEN LET Y=Y-1
 220 IF KEY=OPEN THEN GOSUB 1000
 230 IF KEY=MARK THEN GOSUB 2000
 240 IF N<>0 THEN GOTO 120

Basically all 10 lines form 3000 to 3999 are replaced by line 160 (which does a string array lookup). Much more efficient.

Another inefficiency was that the original code was storing CODE values for characters in the integer DIM'ed array. So for storing 0 through 9 it stored 28 through 37 and then printing the CHR$ of that on the screen. It would check if it was greater than 9 by doing a string-compare for being greater or equal to the "A" character. Not only was that slow but initializing the 672 entries of the DIM'ed array took a while (31x22). So I just have the array now hold integer values which is initizlied to 0 by default on the ZX81 (a big time saver). So 0 for "0" and 1 for "1" and so on, and then 10 for "A" etc... and then I can use my F$ string array to get the actual characters to print to the screen. All that sped it up nicely for a ZX81 and is pretty playable.

Now on the ZXSimulator after all those fixes, it was still running about 50% slower. I realized it was due to the inefficient linear search I use for GOTO/GOSUB. I still need to turn that into a binary search. So I reorganized the Minesweeper code and now it runs on par with the ZX81 and is actually playable. I basically moved code that was using excessive GOSUB's (the empty-space-clear-out routine that shows empty spaces) to the top. Eventually, when I fix the GOTO/GOSUB code, that should not matter.
Last edited by bwinkel67 on Tue May 05, 2020 10:26 am, edited 4 times in total.


Post Reply