• Please review our updated Terms and Rules here

Applesoft BASIC Pongprogram.

Mister_Alex

Experienced Member
Joined
Sep 1, 2011
Messages
58
I've been doing a little bit on this program every few nights. It's far from a complete package, but for now, what do people think?

Calormen's Applesoft emulator works great!

Also, sorry if including my website is considered SPAM. If it is then I'll edit the post.


10 text : home
20 paddley=8 : x=10 : y=10 : xv=0 : yv=0 :
25 gosub 9000
30 gosub 1000
40 gosub 2000
50 gosub 3000 : gosub 4000
60 for l=0 to 200 : next l : goto 40

1000 gr : color=3
1100 hlin 0,39 at 0
1200 hlin 0,39 at 39
1300 vlin 0,39 at 39
1400 htab(1) : vtab(22) : print "A=UP"
1500 htab(1) : vtab(23) : print "Z=DOWN"
1600 htab(15) : vtab(22) : print "Q=QUIT"
1700 htab(15) : vtab(23) : print "SPACE-LAUNCH BALL"
1999 return

2000 key=peek(49152) : if key<128 then key=128
2010 button$=chr$(key-128)
2020 if button$="q" then text : home :end
2030 if button$="a" then paddley=paddley-1
2040 if button$="z" then paddley=paddley+1
2050 if button$="q" then text : home : end
2050 if key=160 then if (xv=0 and yv=0) then gosub 8000
2060 if paddley<1 then paddley=1
2070 if paddley>32 then paddley=32
2080 if (xv=0 and yv=0) then x=2 : y=paddley+3
2999 return

3000 color=0
3010 if paddley>1 then plot 1,paddley-1
3020 if paddley<32 then plot 1,paddley+7
3030 color=15
3040 vlin paddley,paddley+6 at 1
3999 return

4000 color=0
4010 if x=>0 then plot x,y
4020 if xv<>0 then x=x+xv
4025 if yv<>0 then y=y+yv

4026 if (xv=0 and yv=0) then gosub 7000

4030 color=15
4040 if x=>0 then plot x,y
4050 if x>37 then xv=-1
4060 if (x=2 and xv<>0) then gosub 5000
4070 if x<0 then gosub 6000
4080 if y<2 then yv=1
4090 if y>37 then yv=-1
4999 return

5000 if y=>paddley and y=<paddley+6 then xv=1
5999 return

6000 xv=0 : yv=0
6999 return

7000 color=0
7010 plot x,y-1 : plot x,y+1
7999 return

8000 if y=<20 then yv=1
8010 if y>20 then yv=-1
8020 xv=1
8999 return

9000 htab(17) : vtab(5): print chr$(162)+"PONG"+chr$(162)
9010 htab(4) : vtab(7) : print "Programmed By Alexander G. Tozzi"
9020 htab(4) : vtab(9) : print "www.wumpustales.com"
9030 flash : htab(10) : vtab(12) : print "PRESS ANY KEY TO START"
9040 key=peek(49152) : if key<128 then goto 9040
9050 normal : home : gr
9999 return
 
Just curious but can you beat the computer? One unexpected problem I experienced after coding it my first time was the realization that the computer can't lose, so I'm not really sure what the original game did speed wise to make things beatable.
 
It's not supposed to be beatable. That's why there's a wall at the right. :)
Later versions (who knows when that will be) might have a computer-paddle which can lose, and possibly 'spinners' which will shake things up a bit.
 
Some observations:

Your use of 'single shot' gosub is probably costing you a lot of execution time. unrolling 1000 through 4000 and just letting them run would probably speed it up a lot.

when you detect the start of game and the launch, you aren't flushing the keyboard probe by peeking 49168... this means if you don't move and lose it will auto-relaunch the ball, and if you start the game with space, the ball will launch automatically.

converting key to button$ may be convenient from a code legibility standpoint, but it's a pointless conversion/typecast -- same for the subtracting 128 from the keyboard read. Do the math, don't make the interpreter have to work harder on figuring out fixed values.

Rather than having a separate if statements to move the paddle, make sure the paddle stays in bounds, and redraw the paddle -- you could combine those down to single statements.

Instead of redrawing the entire paddle, just erase and draw the ends -- 2 pixels is probably faster than a line AND a pixel.

Think about this:
4020 if xv<>0 then x=x+xv
4025 if yv<>0 then y=y+yv

If they are zero, adding them won't change them, and as a rule of thumb doing a flat addition is going to be FASTER than an IF statement, even when false.

Longer variable names also take longer for Applesoft basic to parse on the real hardware.... The book says to stick to one, I've found the difference between one or two is negligible.

Oh, and in Applesoft using line numbers greater than 999 is slower, don't know why, but it is.'

Between local emulation and my IIe Platinum, I did a quick rewrite:

Code:
10 s=-16336 : py=8 : goto 50

30 z=peek(s)+peek(s)-peek(s)+peek(s)-peek(s)+peek(s)-peek(s)
40 return

50 gosub 800
60 flash : htab(10) : vtab(16) : print "PRESS ANY KEY TO START"
70 k=peek(49152) : if k<128 goto 70
80 z=peek(49168)

100 normal : gr : color=3
110 hlin 0,39 at 0
120 hlin 0,39 at 39
130 vlin 0,39 at 39
140 vtab(22) : htab(3)  : print "A = UP"
150 htab(3) : print "Z = DOWN"
160 vtab(22) : htab(24) :  print "Q = QUIT"
170 htab(20) : print "SPACE = LAUNCH BALL"

200 x=2 : y=py+3 : oy=1 : ox=0 : dx=0 : dy=0
210 color=15 : vlin py,py+6 at 1

250 k=peek(49152) : if k=209 goto 900

300 if (k<>193 or py=1) goto 350
310 color=0 : plot 1,py+6
320 py=py-1
330 color=15 : plot 1,py
340 goto 400

350 if (k<>218 or py=32) goto 400
360 color=0 : plot 1,py
370 py=py+1
380 color=15 : plot 1,py+6

400 if (dx<>0) goto 500
410 y=py+3
420 if k<>160 then goto 600
430 z=peek(49168)
440 dx=1 : dy=1
450 if y>20 then dy=-1

500 x=x+dx : y=y+dy
510 if x<0 goto 700
520 if x=38 then dx=-1 : gosub 30
530 if (y<=1 or y>=38) then dy=-dy : gosub 30
540 if (dx<0 and x=2 and y>=py and y<=py+6) then dx=1 : gosub 30

600 if (oy=y and ox=x) goto 690
610 color=0 : plot ox,oy : color=15 : plot x,y
620 ox=x : oy=y

690 for l=0 to 200 : next : goto 250

700 for t=0 to 60 step 2 : gosub 30
710 for n=0 to t : next : next
720 color=0 : plot ox,oy
730 goto 200

800 text : home
810 vtab(5) : htab(17) : print chr$(162)+"PONG"+chr$(162)
820 vtab(8) : htab(5) : print "Originally By Alexander G. Tozzi"
830 htab(8) : print "http://www.wumpustales.com"
840 print : htab(7) : print "Rewritten By Jason M. Knight"
850 htab(8) : print "http://www.deathshadow.com"
860 return

900 gosub 800
910 print : htab(12) : print "Thanks for playing." : print

To break it down:

I renamed everything to one or two letter vars using a consistent naming convention. Helps to list your vars in basic thanks to the cryptic names -- I always try to maintain such a list.

Code:
[b]Variables:[/b]

   dx == direction of ball on x axis
   dy == direction of ball on y axis
    k == keyboard input
   ox == last ball x position
   oy == last ball y position
   py == paddle location
    s == speaker address
t,n,i == counters
    x == ball x position
    y == ball y position
    z == discard (used for speaker and key strobe clear)


Lines:

10 -- The memory location -16336 is the speaker 'toggle'; I added sound effects and putting this in a variable lets us 'peek' that location faster getting us a bit higher a pitch. Set the paddle to the starting position, then the goto skips over the speaker function.

30-40 -- Since the speaker function is going to be called a lot and gosubs are faster when at the start of the code in applesoft basic, we really want that front and center. Quickly reading this memory location toggles a flip-flop connected to the speaker. Toggling it back to back gives a roughly 110khz chirp in Basic (yes, applesoft basic is that slow) -- so 7 toggles gives us roughly a fifteenth of a second chirp. Decent for when the ball strikes a surface. I alternate between + and - there so that the result is more likely to stay within byte-bounds -- as toggling an overflow on a 8 bit cpu can slow down how fast we can call those peeks.

50-80 -- First I call the credits. I left this as a function so credits could be called a second time when exiting the program. Drawing the flashing press any key is no different, nor is the keyboard peek/loop -- what is different is that I then peek 49168 after the check to 'flush' the value so that if you hit space to start, the ball doesn't automatically launch.

100-170 -- no real changes apart from my omitting some of the vtab's as unneccessary. Print automatically goes to the next line, so why waste time saying to go where it already is?

200-210 -- Sets up our game start values and draws the paddle in it's starting spot. I also call this later on to reset the ball position when you 'miss'.

250 -- keyboard handler and abort on q.

300-340 -- "a" handler. As mentioned checking by numeric value, and if the paddle y position is where we even allow it to move. If neither is true we just goto to skip this section. If py isn't 1, we can move it, so first we erase the bottom pixel, move it, then draw the bottom pixel. Cleaner/simpler than erasing a pixel then drawing the whole line. The goto skips over our check for 'z' since obviously if it reaches that point, we don't need to do that.

350-380 -- 'z' handler, same basic check, just we flip the redraw.

400-450 -- since dy and dx are both either non-zero or zero, there's no reason to ever check both! So if dx (and by extension dy) isn't zero, the ball is launched so skip this section. Otherwise we set the ball to the center of the paddle, check for the launch key... if it's not the launch key skip past all the game logic to the redraw... otherwise flush the keyboard strobe (so if you lose without moving it doesn't auto-launch again!), set it in motion. Notice I set dy to one and then run an if statement. This is simpler/faster than playing with multiple if statements or playing with goto/gosub.

500-540 -- move it, check for loss and goto to the loss handler. Otherwise check for our bounces, and if it is bouncing not only flip direction but play our little 'bounce' sound.

600 to 620 -- if the ball didn't move, don't erase and redraw it. Otherwise erase it's old location and draw the new one. Little bit of extra variables needed, but has the advantage of no flickering of the ball when it's not moving. It also reduces the delay between erasing it and drawing it so the overall movement effect seems smoother too.

690 -- same delay you had.. though it runs a bit faster since I'm not saying which variable to next. By default next will work with whatever flow operation is at the top of the stack, so not saying the variable makes for/next loops faster in Applesoft basic... Then of course it loops back to the keyboard check.

700-730 -- "Loss" routine. Plays a "beyooo" noise, then erases the ball, then does a GOTO back to our game reset/startup.

800-860 -- the Credits. Notice once again I skip using vtab anywhere near as much and let print do most of the work.

900 -- Our exit handler. Show the credits again, show 'thanks for playing', done.

... and that's it! About 200 bytes less code, runs anywhere from 10-15% faster so you may want to play with the 'delay' loop. Often wish the apple had an actual system timer you could trap for things like this, but thankfully Apple milked the same piss poor clock speed for a decade and a half so unlike the PC side of things you don't have to worry about every machine that can run it native being anywhere from 4.77mhz to 4ghz...

Hope this helps, or at least gets you thinking on different ways of handling things.

Mein gott, to think it's been almost twenty-five years since I did any real coding in Applesoft Basic... but this at least gave me something to play with now that I've dragged my IIE platinum out of storage... made me remember a lot of the oddball quirks and headaches the language had -- like the lack of an ELSE statement.
 
Any possibility of getting this to play against itself? Trying to get this to run as a "demo loop" as a prop for a tv show.
 
I'm not strictly an Apple ][ person myself even though I've being playing around with Joshua Bell's Applesoft BASIC, though I thought what you posted @deathshadow was quite good. :D

Sorry I didn't realise it was posted back in 2012! :eek: Still, works well in Applesoft BASIC. :D
 
Last edited:
Back
Top