Here is the original Tetris program I wrote back in the early 90s. Everything is as it was. Nothing is changed. That's quite generous on my part, owing to the very weird spacing conventions I used. Did someone in COMPUTE! tell me to do that to save valuable bytes? Very weird. I would have to pay a memory inducing quack thousands of dollars to pluck that little shard of memory from my head. Apart from the "out-there" spacing conventions, there are numerous other errors too embarrassing to bring to everyone's attention in bullet point form.
Of particular note is the fact that this isn't ordinary Tetris -- this is Tetris with pieces that are made with 5 bricks instead of the usual humdrum 4 brick pieces. I guess this shouldn't really be called Tetris. Pentris would have been better, but then people would have vandalized the arcade machine cases and made crude remarks with the game's name... so Tetris II is the official name for this one. For a straw-man attack to support this mediocre naming scheme, see the Intel naming scheme for the Pentium chips.
I was able to pluck it from the original disk and into ASCII land by using the XE1451 Extended Cable, the Star Commander Program, and a paper clip. Many thanks to the creators of these products... I don't believe the original disks would have withstood another winter outside in an unheated shed on my parent's farm. The screen shots were obtained from the VICE emulator.
Everything in black. How psychologically interesting. My mother said that even as toddlers, a personality is quite well formed. And look no further than right here -- we've got the POKEs and the Cascading Style Sheets to prove this idiom right.
All these FOR loops created the border for the "next shape" box -- we're POKE'ing in the border lines with FOR loops. The screen display codes give this one away, if you translate them using the proper Commodore cypher -- 12 is space, 74 is a round character in the upper right corner, 75 is the same in the left corner, and 66 is "|".
All of the shapes are loaded into the "s" array. Each indice represents one block of a total shape. The a indice delineates each shape, the b indice determines the shape it becomes for each of the three rotations, and the c indice describes the each individual block of the pieces. There are only 4 because the middle block is always known to exist, so there is no need to store its indice.
GOTOs considered harmful -- what about a GOTO (line 20) into a GOSUB (line 25) to prime three back-to-back FOR loops. Why did my parents never buy me academic journals for Christmas?
The image shown displays the screen as it is being constructed. The circles (character number 81 in Commodore-speak) were actually put into the screen buffer, and then turned black, and therefore invisible. The pieces were made visible by changing the color of the individual circles black.
Line 5000 seems to contain the "a-mazin' subrutine", which 'unfolds' a message on the screen. See the subroutine for more details. The message displayed is identified by the wg variable, which in turn references a particular element of the data array of messages located later on. The c variable holds the screen location of where the message starts.
In line 140, we do a couple of things. One, we draw the shape. Secondly, if fd is 1, then the space bar has been pressed (see line 149), and we can go into the proverbial free-fall mode.
This is particularly stupid. In Commodore-speak, 14 = N, 5 = e, 24 = x, etc. This puts down the words "next shape" during EVERY TURN.
149 ifa$=" "thenfd=1
A string comparison... you know, this could be the root cause of the performance issues.
Ignore this. Very sloppy work here. This is already taken care of in line 1015.
Looks like the sp variable is the rotation variable, and the w variable is the width variable.
We're checking to see if we hit any of the shapes currently placed on the board. We're PEEKing to see what's in that location. And then the tr variable... well, I'll get back to you. When it is 4, that means there are no spaces being taken up by the HYPOTHETICAL next position of the shape, and we can move the shape down one more line.
...and if we do see that we've got something in the way, we leave the shape right there.
This is free fall mode. Straight down!
Erase the shape in the previous space.
This moves the shape down a notch. This is the HYPOTHETICAL position that the shape will take on the next turn. We now check to make sure that it can fit there (i.e. no other shape's in the way).
Tsk tsk. Copied code. Do you think I used the old print-the-lines-out-then-rewrite-the-new-line-numbers-over-top trick? I miss doing that -- vi-like power in a Microsoft product.
If we've hit bottom, then we can check to see if any lines have been made.
The shape is OK, nothing's in the way... let's drop the shape another level.
5000 rem*a-mazin' subrutinÁ
Wouldn't want any side effects, would we? Can't be wrecking that valuable c variable. I am sure that EJD would have smiled at this childhood adherence to acceptable software practices from his place in the sky (well, actually, back then, I guess it would have been Texas).
POKE the text in there, starting from the MIDdle.
The lines are placed above and below the text (one column is 40 characters wide in Commodore-speak).
This code is never entered... Looks like I was testing to see if I could put everything into lowercase.
6000 rem check for 'da lines
Well, now that we're all the way here, I should tell you a little secret. This program never worked. I was so close... but it just wouldn't properly check for any lines. Perhaps the... OH MY GOD! I found the problem. The xx variable is incremented by one for every line we hit. If it hits 16, then we've got a line. BUT, if there was no line it would have been less than 16. And in the incriminating line 6060, we subtract by 16 every time. How heartbreaking. I was THIS close to child freakin' genius of the decade. UPDATE: Nope, that's not it. Not getting any smarter in my old age, I guess. Fairly embarrassing to leave those previous comments there. That said, in the spirit of this code review, I'll not discriminate against stupidity of a more recent vintage. The xx variable simply keeps track of the current screen location that we are checking for the presence of present blocks. Perhaps the wrong value from the peek is being returned in line 6025?
9000 rem gnarly! a line!
Here, we move all the lines down. Laboriously going through all the lines that are above the subtracted lines, we look at what's above, and move it down. Is there any other way?
If ya got a line, I've got a message for ya...
50000 data10,your're a tetris dude,12,keep those lines coming!
Here's the fun part. Is there any better word than gnarly? And dude. And superdude! Of course, I knew when to quit -- I cooled things down with that "regular tetris person" line.
50010 data8,gnarly! a tetris,14,excellent placing of tetrads
50020 data5,game over!,5,pause mode,19,select song by pressing number(1 to 6)
50030 data12,start song again (y-n)?,8,start your game!
50040 data18,maybe candyland would be more your game!
Ooooh. Ya, Candyland... just like my little SISTER plays. Loser.
50050 data17,press (space) or m to choose music
50060 data16,1000 points till your high score,5,high score
50070 data11,regular tetris person,4,oh! oh!,11,superdude! great going
These are interesting... the previously mentioned "regular tetris person" quotation... the orgasmic "oh! oh!"... and the saccharine yet jarring "superdude! great going". All in one line, folks.
50080 data2,wow!,6,high scores!,10,major gnarly player!,5,try again.
50090 data5,excellent!,14,ha! ha! that score is a joke
50100 data14,disgrace to the tetris race!,3,gross!
"Disgrace to the Tetris Race!" I rather like this one. Nice cadence.
50110 data14,tetrisdude. or tetrisdudette,9,been playing alot?,3,cool!!
Even back then, I knew that SEXISM WAS WRONG.
50120 data16,condider yourselve a mentalblock,7,you are a hero,4,you suck