Category Archives: CoCo

Tandy/Radio Shack TRS-80 Color Computer (CoCo)

Recreating the Pac-Man maze in 1993

Many years ago, I played with drawing a 3-D maze under OS-9 on my Radio Shack CoCo 3. That demo is on the NitrOS-9 “Ease of Use” release under the name “semaze“. It lets you wander around a simple line maze:

There is even a map you can bring up with “?”:

As I mentioned years ago on this site, I had played with turning that into an OS-9 version of the classic Phantom Slayer 3-D game on the CoCo 1. I got as far as having my maze with a “phantom” in it that would wander around:

An unfinished CoCo 3 OS-9 3-D maze game inspired by the old “Phantom Slayer” by MED SYSTEMS.

But the oddest version was probably me putting the Pac-Man maze into my 3-D “engine” and then deciding to put dots around it, and make it refresh every half second or so, making it a “real time” game. With a prototype ghost (which appeared just as a large circle) wandering around!

And bringing up the map showed the Pac-Man maze:

In the days before the Internet, the only way I would have been able to recreate this map is if I had access to an accurate home port (I did not), or a picture in a magazine (maybe). I am guessing I based it on some CoCo Pac-Man clone with a fairly accurate maze.

How well did I do? Here is my CoCo version, then the actual arcade game, and the Arduino TV-Out version I was working on a decade ago (very accurate, down to the tiles).

I can see a few errors, like the bottom walls under the power pellets going into the maze an extra tile. And the dots are off. Today, I understand how the Pac-Man maze is laid out with tiles so it would be much easier to recreate my 3-D “DotMaze” game with an accurate map.

Maybe I will.

Color BASIC and octal

Updates:

  • 2025-02-19 – Thanks to a comment from William Astle, the term “decimal” number has replaced my incorrect use of “integer.” And per a comment from James Jones, a clarification that all values you input are still stored internally as the same type of numeric floating point – the parsing converts them all to this floating point representation.

Color BASIC had one type of number you could use: decimal. These are the normal numbers we use every day like 1, 50392 or 42.

A=42
PRINT "A IS";A

When Extended Color BASIC was added, the CoCo accepted the following notations for numeric constants: integer, hexadecimal and octal. (Internally, BASIC converts them all to the same numeric representation of a floating point value.)

Getting Started with Extended Color BASIC describes hex and octal as follows:

Extended Color BASIC lets you use both hexadecimal and octal constants.

Hexadecimal numbers are quantities represented in Base 16 notation, composed of the numerals 0 to 9 and the “numerals” A to F. Hexadecimal constants must be in the range 0 to FFFF, corresponding to the decimal range 0 to 65535.

To indicate that a number is an octal constant, precede it with the symbol &H, as shown here:

&HA010 &HFE &HDl &HC &H4000

Octal numbers are quantities represented in Base 8 notation, composed of the numerals 0 to 7. Octal constants must be in the range 0 to 177777. The computer stores them as two-byte integers that correspond to the decimal range 0 to 65535.

To indicate that a number is an octal constant, precede it with the symbol &0 or &, as shown here:

&070 &044 U1777 &7170 &17 &01234

The use of “hex” and octal constants is convenient in programs that reference memory locations and contents. For further information, read a book on machine-language programming.

– Getting Started With Extended Color BASIC (p. 195, 1984 revision)

I most likely learned hexadecimal when I was learning assembly language. Today, I use hex values often in C programming. But octal? I do not think I have ever used it for anything. Have you?

I do believe I have seen it used “in the real world.” In the late 1980s (possibly early 1990s) I had a Kawai K1 synthesizer keyboard. It organized its instrument settings (called “patches” in reference to early synthesizers using “patch cables” to route signals do different processors) into two groups of Internal (onboard storage, uppercase “I” and lowercase “I”) and two groups of External (memory card, uppercase “E” and lowercase “e”). Each section had eight patches.

My first commercial CoCo program was a MIDI Librarian that could read the patches from the synthesizer and save them to disk, or load patches from disk into the keyboard. The patch screen in question looked like this:

You will see that each area had four banks (A-D) and each of those had eight patches (1-8). Uppercase “I” was A(1-8), B(1-8), C(1-8) and D(1-8), and lowercase “i” was the same. This was also the same for the External banks.

Thus, octal. I could have used octal in my program — but I do not know if I even realized this was octal at the time. I’d have to think about how I would have even done that. Maybe something like this:

0 'OCTALIN.BAS (2-15-2025)
10 LINE INPUT "BANK (0-7):";B$
20 LINE INPUT "PATCH(0-7):";P$
30 NM=VAL("&O"+B$+P$)
40 PRINT "THAT IS PATCH #";NM

…though I do not recall how the MIDI messages. It could have just been a user interface thing and internally the patches were still 1-whatever.

But I digress.

Juan Castro posted to the Color Computer e-mail list about a bug in the octal routines:

Octal constant (Ex.: &O14 = 12 decimal)

It accepts 8 as a digit. D’oh. Try “PRINT &O18” in a CoCo 1 or CoCo 2.

Without having a CoCo3 at hand to check I’ll wager it patches that bug. All
it has to do is replace a LBHI with a LBHS.

Juan Castro
Enviado do meu Olivetti Programma 101
http://retropolis.com.br

Since an octal value should only be 0-7, a value of 8 is not valid octal.

10 CLS:PRINT"DEC","OCT"
20 FOR A=0 TO 10
30 PRINT A,VAL("&O"+STR$(A))
40 NEXT

This should print 0-7 then error out. Yet…

And is there really no better error than SYNTAX for this type of problem?

And naturally, I had to see what HEX values do. A valid hex digit is 0-9 and A-F, representing 0 to 15. Will it do a syntax error as well if I go past the letter F?

It appears it does not. It seems to bail on the parsing and print them as two variables. Which is a neat trick, since you have to put a space or semicolon between two variables if you want to print them otherwise.

To confirm that is what it is doing, I tried this:

Ah, so it is not treating this as variables “H” and “G”. And I just learned something new (and probably useless).

Something new (and probably useless)…

Integer values are things like 1, 2, or 152032. They are floating point values, so you can also have things like 1.2 or 33.5. Though, not always. Floating point values cannot represent every decimal value accurately, but that’s a story for another article…

Somewhere, someone learned that a decimal (period) by itself would be treated as zero. The fastest way to assign 0 to a variable in Color BASIC is like this:

A=.

Weird, but it works. It seems the parser starts looking for a fractional amount, like “.25” or whatever, so it processes the period and then there is nothing else so the code returns with 0 (the initialization value when the function is called). It is still weird, though.

I found out tonight that the same thing applies to hex. You can do this:

A=&H

…and you get a zero. Try “PRINT &H” to see for yourself.

Of course, I had to try a quick benchmark, sitting in a loop doing something like “Z=.” and another run doing “Z=&H”. 1000 times through with “Z=.” used 140 timer ticks. The “Z=&H” used 154. I guess that is the overhead of parsing two characters instead of one.

But I digress. Again.

I have not looked up what BASIC is doing (see the excellent “BASIC Unravelled” books for the disassembly of the BASIC ROMs), but I suspect the parser starts looking and finds the “&” followed by the “H” and is ready to parse… it then hits an invalid character, so the parsing is over and 0 is there. Then it sees the G, which is not a command so it is treated like a variable.

Using “PRINT” was deceiving. Had I just tried this:

A=&HG

…I would have got what I was expecting:

?SN ERROR

Thanks, Juan, for sharing this. I learned about a bug, and in writing this, discovered another odd thing, which is less odd now that I understand what happened.

Until next time…

Sub-Etha graphical adventures?

Around 93-94, I created a text adventure that featured black and white digitized pictures from the 1992 Atlanta CoCoFest. It was more of a “simulation” than a game — and even called itself a simulation on the splash screen. But, while browsing through the source code, I found there were quite a number of things you could “do” in the game, while the score let you know how much of it you completed.

I also found one from a Chicago CoCoFest, which seems to be complete other than missing the images. Rooms were numbers with the vendor name and description. It was kind of like “playing” one of my old CoCoFest reports. Trippy.

And a weird 3-D first-person Pac-Man game I was working on…

Now that I have Xroar running the current Ease of Use NitrOS-9 build, and have my CoCoSDC “real CoCo” hard drive image mounted as the second drive, I may finally be able to dig through all this stuff and see what else I have.

Like finding I made a Towel V1.05” — after I moved to Iowa! I have no recollection of that. Lots of stuff to get archived and posted online.

Should be fun.

MAZE.BAS for the CoCo

While looking for something completely unrelated, I ended up going through some of my old BBS disks. In addition to my *ALLRAM* tape-based BBS, I worked on several other BBSes that were never completed.

One one of those disks was something called MAZE.BAS. But why would a maze game be on a BBS disk?

Running it showed me this…

The player “P” can move around the maze while the enemy “*” tries to get to you. It uses “A-S” for left and right, and “W-Z” for up and down.

Ah, now I remember. I had learned about VIDTEXT/VIDEOTEXT/whatever having control codes to move the cursor around the screen, so I was going to write a maze game to run online in the BBS. If you had a compatible terminal program, you could play an actual “action” game rather than just some text adventure or simulation.

The numbers at the bottom were diagnostics messages. X/Y and movement direction for Up/Down and Left/Right.

Interesting.

Here is the listing…

0 'PALETTE12,63:PALETTE13,0
9 CLS
10 PRINT" #####
11 PRINT" ########## ##########
12 PRINT" # # #
13 PRINT" ### ###### ####### ###### ###
14 PRINT" # # # #
15 PRINT" # ### ################# ### #
16 PRINT" # # # #
17 PRINT" ####### #### #### #######
18 PRINT" # #
19 PRINT" # ###### # # ###### #
20 PRINT" # # ### # #
21 PRINT" # #### #### #
22 PRINT" ### ####### ###
23 PRINT" #### ####
24 PRINT" ###########
25 MX=15:MY=1:PX=15:PY=13
30 POKE1024+(PY*32+PX),80:POKE1024+(MY*32+MX),96
31 PRINT@512-32,PX;PY;XP;YP,MX;MY;X;Y;
35 X=SGN(PX-MX):Y=SGN(PY-MY):Z=(1024+(MY*32+MX))
36 IFPEEK(Z+(Y*32))=96 THENMY=MY+Y ELSEIFPEEK(Z+Y*32+X)=96 THENMX=MX+X:GOTO39
37 IFPEEK(Z+X)=96 THENMX=MX+X:GOTO39
39 POKE1024+(MY*32+MX),42
40 A$=INKEY$:IFA$=""THEN55
45 IFA$="W"THENYP=-1:XP=0 ELSEIFA$="Z"THENYP=+1:XP=0
50 IFA$="A"THENXP=-1:YP=0 ELSEIFA$="S"THENXP=+1:YP=0
55 IFPEEK(1024+(PY*32+PX)+(32*YP)+XP)=96 THENPOKE(1024+PY*32+PX),96:PX=PX+XP:PY=PY+YP
60 GOTO30
999 GOTO999

Using what I know about BASIC today, I would tackle this in quite a different manner.

Maybe I will, as a benchmark exercise.

Until then…

Our magazine ads, before they were typeset…

While going through some random disk images, I found some text files that seem to be the Sub-Etha Software ads, before we took them to the printshop to have them typeset by a professional.

First, this looks like the first ad we planned to run in Rainbow magazine, before we got a deal to do a quarter page inside. Note the company name was going to be Forty-Two Technology and the phone # listed was before I had a dedicated line.

Multi-Basic-- Ever wonder why, with 128K or 512K, you cannot use even 32K under RS-Dos?  Well now there's MultiBasic, making possible, without adding ANY commands, the use of ALL of your CoCo3's memory by basic.  Have several programs loaded in memory at once, able to call subroutines from each other, move between each other, even load other programs from disk, all without variable loss or interruption of program flow.

Shadow BBS-- Finally, a CoCo3 RS-Dos BBS with power, speed, and flair. Uses RS232 Pak or serial port. Features include full ANSI, X/Y Modem, 28 line 40/80 column support, 240 byte onscreen status window, software clock, up to 255 independently numbered message areas, borderlines, one-liner discussions, surveys, auto-messages, doors to external programs, user profiles, full sysop utilities, much, much more! See for yourself, call ShadowBBS HQ at (409)63-REALM. Order thru BBS or thru: Forty-Two Technology, PO Box 4242, Lufkin, TX 75901. (409)637-7604.

Next up is the prototype for the ad we did run, featuring MultiBASIC and SHADOW BBS by Terry Todd. We didn’t have a dedicated phone number yet, so the 632-4200 was just a made up one for the mockup.

 _____________________________________________________________
| |
| |
| |
| |
| |
| |
| MULTIBASIC - Use all 128K/512K of your CoCo 3 without |
| learning ANY new commands! Have several programs loaded |
| at once sharing subroutines and variables! Load programs |
| without losing variables, and more! INTRO. PRICE: $24.95 |
| |
| SHADOW BBS - An RS-Dos BBS with Power, Speed, and Flair! |
| ANSI, X/Y Modem, Clock, Surveys, AutoMessage, Up to 255 |
| Msg Areas, User Profiles, Doors, Borderlines, Full SysOp |
| Utilities, and Much, Much More! Runs on 128K CoCo 3 with |
| Disk Drive(s), Serial Port OR RS232 pak! Call and see |
| for yourself! (409) 63-REALM INTRO. PRICE: $34.95 |
| |
| Sub-Etha Software Call or write for information! |
| P.O. Box 152442 Add $2.00 S&H and $3.00 C.O.D. |
| Lufkin, TX 75901 Texas residents add 8.25% tax. |
| (409) 632-4200 "Don't Panic!" |
|___________________________________________________________|

Next, another prototype… Much closer to what ended up being typeset and published – and even has the real phone number. These blank spots at the top where were the logo was going to go. I did these ASCII ones to show them exactly what we wanted.

 _____________________________________________________________
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Ever wonder why, with a 128K or 512K CoCo 3 you cannot |
| even use 32K under RS-Dos? Well, now there's MultiBasic, |
| making possible without adding ANY commands the use of |
| your CoCo 3's "hidden" memory by Basic. Have several |
| programs loaded in memory at once able to call |
| subroutines from each other. Move between programs and |
| load other programs from disk without variable loss or |
| interruption of program flow. A "must-have" utility for |
| Basic programmers! |
| |
| INTRODUCTORY PRICE ............................... $24.95 |
| |
| |
| /) Shadow BBS (\ |
| Complete RS-Dos BBS with Low Hardware Requirements! |
| |
| Finally, an RS-Dos CoCo 3 BBS with power, speed, and |
| flair! Uses RS232 Pak OR serial port! Features include |
| ANSI, X/Y Modem file transfers, 28 line 40/80 column |
| support, 240 byte on-screen status window, software |
| clock, up to 255 independently numbered message areas, |
| borderlines, one-liner discussions, surveys, automessage, |
| doors to external programs, user profiles, full SysOp |
| utilities, and much, much more! And unlike most BBSs |
| you've seen, no hard drive, RS232 Pak, or memory upgrade |
| is required! Shadow BBS will run on a 128K CoCo 3 with |
| one disk drive and a modem, yet it is capable of taking |
| advantage of all the hardware your system includes. A |
| full appreciation of Shadow BBS comes not, however, from |
| it's many features or it's low hardware requirements, but |
| from the flair and smoothness of the program itself. We |
| want you to see what this incredible BBS can do. Call |
| The Shadow's Realm, the official Shadow BBS HQ system, at |
| (409) 63-REALM (300/1200 Baud, 24 Hrs.) and see for |
| yourself! |
| |
| INTRODUCTORY PRICE ............................... $34.95 |
| |
| |
| Sub-Etha Software Call or Write for Information! |
| P.O. Box 142442 Add $2.00 S&H and $2.50 C.O.D. |
| Lufkin, Texas 75915 Texas residents add 8.25% tax. |
| (409) 639-ETHA [3842] "Don't Panic!" |
|___________________________________________________________|

And this one, AD4.txt, is another variation:

_____________________________________________________________
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|___________________________________________________________|
|| ||
|| *: MultiBasic :* ||
|| More Memory for Basic without Learning New Commands! ||
|| ||
|| Ever wonder why, with a 128K or 512K CoCo 3 you cannot ||
|| even use 32K under RS-Dos? Well, now there's ||
|| MultiBasic, making possible without adding ANY commands ||
|| the use of your CoCo 3's "hidden" memory by Basic. ||
|| Have several programs loaded in memory at once able to ||
|| call subroutines from each other. Move between ||
|| programs and load other programs from disk without ||
|| variable loss or interruption of program flow. A ||
|| "must-have" utility for Basic programmers! ||
|| ||
|| INTRODUCTORY PRICE ............................. $24.95 ||
|| ||
|| ||
|| *: Shadow BBS :* ||
|| Complete RS-Dos BBS with Low Hardware Requirements! ||
|| ||
|| Finally, an RS-Dos CoCo 3 BBS with power, speed, and ||
|| flair! Uses RS232 Pak OR serial port! Features include ||
|| ANSI, X/Y Modem file transfers, 28 line 40/80 column ||
|| support, 240 byte on-screen status window, software ||
|| clock, up to 255 independently numbered message areas, ||
|| borderlines (quotes), one-liner discussions, surveys, ||
|| automessage, doors to external programs, user profiles, ||
|| full SysOp utilities, and much, much more! And unlike ||
|| most BBSs you've seen, no hard drive, RS232 Pak, or ||
|| memory upgrade is required! Shadow BBS will run on a ||
|| 128K CoCo 3 with one disk drive and a modem, yet it is ||
|| capable of taking advantage of all the hardware your ||
|| system includes. A full appreciation of Shadow BBS ||
|| comes not, however, from it's many features or it's low ||
|| hardware requirements, but from the flair and ||
|| smoothness of the program itself. We want you to see ||
|| what this incredible BBS can do. Call The Shadow's ||
|| Realm, the official Shadow BBS HQ system, at (409) ||
|| 63-REALM (300/1200 Baud, 24 Hrs.) and see for yourself! ||
|| ||
|| INTRODUCTORY PRICE ............................. $34.95 ||
||_________________________________________________________||
| |
| Sub-Etha Software Call or Write for Information! |
| P.O. Box 152442 Add $2.50 S&H and $3.50 C.O.D. |
| Lufkin, Texas 75915 Texas residents add 8.25% tax. |
| (409) 639-ETHA [3842] "Don't Panic -- We Ship Fast!" |
|___________________________________________________________|

I guess by this next one we trusted the typesetting person, since it was just the raw text:

Happy Holidays From...

SUB-ETHA SOFTWARE

"In Support of the CoCo"

Thanks to those who stopped by our booth at the CoCo Fest!

*: MiniBanners :*
Multiple Line Banners on ANY Printer!

NEW! Create single or multiple line banners with adjustable heights and
widths. Up to 16 lines of text with independently sized characters. Even
works with daisy wheel and non-graphic printers! Includes over 30 fonts!

INTRODUCTORY PRICE ................................................ $14.95

*: MultiBasic :*
More Memory for Basic without Learning New Commands!

PRETTY NEW! Tired of being limited to 22K for Basic? We were too, so we
created MultiBasic, a utility which allows you to use the "hidden" memory of
your CoCo 3 without learning ANY new commands. Load multiple programs, disk
chain, share subroutines and variables, all without interrupting program flow.

HOLIDAY PRICE ..................................................... $24.95

*: Shadow BBS :*
Complete RS-Dos BBS with Low Hardware Requirements!

ALSO PRETTY NEW! Finally, an RS-Dos BBS with power, speed, and flair. Uses
RS232 Pak OR serial port. Does not require a hard drive or memory upgrade!
Features: SysOp Utilities, Up to 255 Msg Areas, X/Y Modem, ANSI, Status
Window, Clock, AutoMessage, User Surveys and Profiles, and too much more to
mention here! A full appreciation of Shadow BBS comes not, however, from it's
many features or low hardware requirements, but from the flair and smoothness
of the program itself. We want you to see what this BBS can do. Call the
Shadow's Realm, the official Shadow BBS HQ, at (409) 63-REALM (300-2400 Baud,
24 Hrs.) and see for yourself!

HOLIDAY PRICE ..................................................... $34.95

I wonder what else I will find as I go through these things…

What are the odds?

Back in the early 1980s, a friend of mine had TRS-80 Model III in their house. His mother was a writer, and had gotten it to use for writing books.

I believe it was this TRS-80 where I saw a version of Monopoly that taught me a strategy I had never learned as a kid:

The computer bought EVERYTHING it landed on, even if it had to mortgage properties to do so.

This simple strategy was a gamble, since you could end up with too many mortgaged properties and no source of income from rent. But. by doing this, the computer would end up owning so many random pieces it made it difficult to own a monopoly yourself.

And since then, that is how I played Monopoly. When it worked, it created some awfully long games (if no one had a monopoly to quickly drive other players bankrupt when they landed on their hotels).

In more modern times, I have watched YouTube videos concerning Monopoly strategies. They will break down the statistical odds of landing on any particular piece of property. For example, you know a pair of dice can produce values from 2 to 12. If truly random, the odds of getting a “1 and 1” should be the same as getting a “3 and 5.” Rather than focus on dice rolls, the strategies take into consideration things that alter locations: Go To Jail, Advance to Go, Take a Ride on Reading, etc.

These cards existing means there are more chances for a player to end up on Go, Reading Railroad, Jail, etc. This means the property squares after those spots have more chances of being landed on.

Board with board games. Move along…

But I digress… As Internet Rabbit Holes do, this led me to watch other videos about statistics in things like card games. In a randomly shuffled deck, there should be as much chance for the first card to be Ace of Spaces as there is for it to be Three of Clubs. It is random, after all.

For that first card drawn, that is a 1 out of 52 chance to be any card in the deck. (52 cards in the deck.)

But as a game plays on, there are fewer cards, so the odds of getting any of the remaining cards increases. For the second card drawn, you now know there is a 0% chance of getting whatever the first card is, and a 1 in 51 chance of getting any of the rest.

And so it continues…

For games like Blackjack or 21, you do not really care if it is a Ten of Diamonds or a King of Hearts or a Queen of Clubs or a Jack of Spades. They all have the value of 10 in the game. Thus, the likelihood of drawing a ten card is much higher than any other card in the deck.

You have four suits (clubs, spades, hearts, diamonds) so there are four of each card – Aces, Two through Ten, Jacks, Queens, and Kings. This means there are 16 cards in the deck that could be a value of 10 in the game. When you draw the first card, you should have a 16 in 52 chance of it being a ten card. That is about a 33% chance!

If you pay attention to what cards have been seen (either by you having it, or seeing it face up with another player), you can eliminate those cards from the possibilities — changing the odds of what you will get.

This is basically what I understand card counting to be. If you play a game, and you know you’ve seen three Kings so far (either in your hand, or played by others), you now know instead of four chances to draw a King, you only have one.

Math is hard. Make the computer do it.

I know this has been done before, and quite possible even on a Radio Shack Color Computer, but I thought it might be fun to create a program that displays the percentage likelihood of drawing a particular card from a deck. I suppose it could have the Blackjack/21 rule, where it treads 10, Jack, Queen and King the same, versus a “whole deck” rule where each card is unique (where you really need an 8 of Clubs to complete some run in poker or whatever game that does that; I barely know blackjack, and have never played poker).

I plan to play with this when I get time, but I decided to post this now in case others might want to work on it as well.

I envision a program that displays all the cards on the screen with a percentage below it. As cards are randomly drawn, that card’s percentage goes to 0% and all the others are adjusted.

It might be fun to visualize.

More to come, when time allows…

Counting characters in a string in Color BASIC

And so it begins…

I want to visualize some playing card statistics, and the easiest way I could think of to do this was to write a program in BASIC. Of course.

There are many approaches I can take, so as I put figure it out I will “show my work” and experiments that help me figure out which one will work best.

For my task, I will greatly simplify a deck of cards by ignoring suits (I just care if it’s an Ace, a Five, a King or whatever). I figure I can store it as a 52-character string representing each card:

A123456789JQKA123456789JQKA123456789JQKA123456789JQK

I could “shuffle” this “deck” and end up with a string in “random” order. I believe I have touched on randomizing a list in the past, and had some great suggestions in comments on how to do it better. Forgetting all of that, let’s just say I end up with as string that gets randomized.

But I digress…

The next question will be: “How many Kings are left in the deck?”

Some of you will already see I am heading down a poor path for doing this, but let’s start there anyway.

One way of counting a specific character in a string is to loop through it and use MID$ to pull out an individual character. Something like this:

FOR A=1 TO LEN(A$)
IF MID$(A$,A,1)="S" THEN C=C+1
NEXT

That would count all the “S” characters that appear in the string. Since every time MID$ is used it has to build a new string representing that portion of the original string, this should be our slowest way to do this. On a system with tons of strings in use, string manipulation gets real slow. For such a simple program, this might be fast enough.

Another approach, which was originally shown to me during a word wrap article as a submission, would be to use VARPTR to get the memory location of the 5-byte string ID memory, and then go to the memory where the string bytes are stored and use PEEK to look for them. You can find details in my earlier article on VARTPR.

The memory location that VARPTR returns will have the length of string as the first byte (byte 0), then an empty byte (byte 1, always 0), then the next two bytes will be the address where the string is stored (bytes 2 and 3) followed by a zero (byte 4). Knowing this, something like this would do the same thing as MID$:

A=VARPTR(A$)
SL=PEEK(A)
SS=PEEK(A+2)*256+PEEK(A+3)
FOR A=SS TO SS+SL-1
IF PEEK(A)=ASC("S") THEN C=C+1
NEXT

And do it faster.

VARPTR is a legal BASIC function, but it still seems nasty to reach in to string memory to do this. Thus, I came up with the idea of using INSTR. This function returns the start location of a matching string in another string, or 0 if not found:

PRINT INSTR("ABCDEFG","D")

That should print 4, since a “D” is located at the 4th position in the string.

You can also add an additional parameter which is where in the string to start searching. Doing this:

PRINT INSTR(5,"ABCDEFG","D")

…would print 0, because it starts scanning at the 5th character (just past the D) of the string, and then won’t find anymore.

I could start using INSTR with a position of 1 (first character), and if it comes back with a value other than 0, I found one. That value will be the position of the found character. I could then loop back and use that position + 1 to scan again at the character after the match. Repeat until a 0 (no more found) is returned. That lets the scan for characters be done by the assembly code of the BASIC ROM and is even faster. It looks like this:

F=0
xxx F=INSTR(F+1,A$,T$):IF F>0 THEN C=C+1:GOTO xxx

And we put them all together in a benchmark test program…

10 ' COUNTSTR.BAS
20 A$="THIS IS A STRING I AM GOING TO USE FOR TESTING. I WANT IT TO BE VERY LONG SO IT TAKES A LONG TIME TO PARSE."
30 T$="S":T=ASC(T$)
40 '
50 ' MID$
60 '
70 PRINT "MID$:";TAB(9);
80 TIMER=0:C=0
90 FOR A=1 TO LEN(A$)
100 IF MID$(A$,A,1)=T$ THEN C=C+1
110 NEXT
120 PRINT C,TIMER

130 '
140 ' VARPTR
150 '
160 PRINT "VARPTR:";TAB(9);
170 TIMER=0:C=0
180 A=VARPTR(A$)
190 SL=PEEK(A)
200 SS=PEEK(A+2)*256+PEEK(A+3)
210 FOR A=SS TO SS+SL-1
220 IF PEEK(A)=T THEN C=C+1
230 NEXT
240 PRINT C,TIMER

250 '
260 ' INSTR
270 '
280 PRINT "INSTR:";TAB(9);
290 TIMER=0:C=0:F=0
300 F=INSTR(F+1,A$,T$):IF F>0 THEN C=C+1:GOTO 300
310 PRINT C,TIMER

And running prints:

Wow, using INSTR is six times faster than MID$? And four times faster than VARPTR. Nice.

Now you know a bit about what I need to do. I need to represent cards in a deck (and be able to “draw” cards from that deck) and calculate how many of a specific card remain in the deck.

Since I do not need to track or show the suits (hearts, spaced, clubs, diamonds), I figure I could use one byte in a string.

To be continued … but in the meantime, do you have a better approach? Comment away!