Noughts and crosses

The cover of 6502 games, a bitmap style picture of a cowboy being shot.I just inherited a load of books on programming the 6502 processor in assembly language (and a Kim-1 computer, more on that later!). Among them was an intriguing 1980 book by Rodnay Zaks called 6502 Games. Zaks wrote what, for many, is the default text book on programming the 6502, but this book is a bit more playful.

The Games Board for the Sym-1 computer

The games in this book are based around a hardware accessory for the Sym-1 computer. The Sym-1 was very much like a Kim-1, a 6502-based development board. (Intriguingly I read somewhere that it could use an oscilloscope as a VDU, I’d love to know more about that!) The Sym-1 Games Board consists of a bunch of LEDs and a number keypad, and even though I don’t have one of those, nor a Sym-1, the book itself is interesting.

A page from the book where Zaks discussed artificial intelligence

I just noticed that the Games Board seems to be made by Sybex, who published the games book. Maybe this book was just a ruse to sell hardware. Anyway…

The most complex game is in the final chapter: ‘tic tac toe’, or noughts and crosses as we call it in the UK. Artificial intelligence long pre-dates this book, of course, but it’s interesting to see the term used here to describe a computer playing a game. It got me thinking about two approaches to solving this problem, which he discusses:

1) A heuristic approach, where the computer learns from its mistakes. This is, I think, how LLMs work, by training on huge amounts of data. It’s also how the matchbox-based noughts and crosses engine, MENACE, works. Often these systems come up with models that the creators of the tools don’t themselves fully understand. This approach takes time and a lot of memory, something lacking on a 1980 home computer. (By the way, there’s a great video of Matt Parker demonstrating MENACE to Professor Hannah Fry in the 2019 Ri Christmas Lectures).

2) A human-programmed algorithmic approach. This requires much more thinking by a human programmer, who needs a deep knowledge, in this case, of how to play the game and all its possible strategies and outcomes. The human applies the usual skills of computational thinking to solve the problem of how to get a machine to play a game that normally humans play.

So which approach is best? Zaks’ hand was forced down the second path due to lack of computer memory, but it strikes me that – if the problem is simple enough – it’s best to take the human-programmed route. The designer learns more. The algorithm is not opaque, you can challenge it if you think it’s biased. It’s open to inspection, improvement in a way LLMs, for example, seem not to be.

I don’t think I’ve ever coded a noughts and crosses game, so inspired by Rodnay Zaks’ very thorough discussion of approaches to creating algorithms for the game, I thought I’d have a go at writing one in Python.

Broadly speaking, he suggests assigning a numerical value to each potential square depending on the threat from the human opponent and the machine’s chances of winning. Clever.

I know that what I’m doing here below is not original, it’s purely an exercise for relaxation in creating some simple programs to play a game, inspired by reading a chapter in a very old computer book.

Simplest version

I started by writing a version for two human players, just so I could set up a user interface and handle the board, detecting wins and draws. The code is here.

It just uses a list to store the board, with 9 elements. A dash is used to show an empty square, capital O and X for each player’s marks. It scans each row, column and diagonal to counts Os and Xs, and if there are 3 it knows someone has won. It also counts free squares, so if no-one has won and every square is filled, it must be a draw. You make your move by typing in the number of the square:

012
345
678

Shooting fish in a barrel

As a stepping-stone to a clever machine that can beat me, I created a laughably simple version. In this one, the human plays against the machine which always just picks the first available square. As the human always goes first, it’s incredibly easy to beat.

I have created you and now you will destroy me

Then I tried to implement something much cleverer, and closer to Zaks’ algorithm. I don’t doubt there are much more elegant and compact ways of doing this, but I wanted to code something a child (and I) could understand.

Zaks’ algorithm is impressively sophisticated, especially for a small 6502 assembly language program. It incorporates randomness and the machine varies its skill level depending on how well it’s doing, which makes for a much more entertaining opponent. I decided to do something much simpler.

This clever version has a new list called ‘move_weight’ which it uses to score how good a square might be. It scans rows, columns and diagonals. Squares already played get a score of 0, playable squares 1. An additional point is added if the human already has placed a O on that line. If the human has two Os on the line, it gets an extra 5 points, but if the computer has two Xs on the line and can win, it gets 6.

You can also choose who goes first, human or machine. The human always plays O, the machine X.

It’s a pretty boring opponent, always playing the first square suggested by the algorithm if there’s more than one choice, but it’s also pretty good. When I’m being dozy, it can beat me!

It also prints out the ‘move_weight’ list, so you can see how it made its choice and it also prints out when it thinks it’s in danger of losing or spots a winning square. A typical bit of game play might look like this:

0 1 2    - - -
3 4 5    - - -
6 7 8    - - -

Player O go:
0
0 1 2    O - -
3 4 5    - - -
6 7 8    - - -

Computer thinking...
[0, 1, 2, 1, 1, 1, 2, 1, 2]
0 1 2    O - X
3 4 5    - - -
6 7 8    - - -

Player O go:
4
0 1 2    O - X
3 4 5    - O -
6 7 8    - - -

Computer thinking...
danger at 8
[0, 1, 0, 1, 0, 2, 2, 2, 6]
0 1 2    O - X
3 4 5    - O -
6 7 8    - - X

Player O go:
6
0 1 2    O - X
3 4 5    - O -
6 7 8    O - X

Computer thinking...
danger at 3
winning move at 5
[0, 1, 0, 6, 0, 8, 0, 2, 0]
0 1 2    O - X
3 4 5    - O X
6 7 8    O - X

Game over!
Winner is X

micro:bit version

Using IDLE for the first time in ages made me miss the micro:bit Python Editor, so I made a version for the BBC micro:bit. It uses the serial console for entering moves and it even works in the simulator, as well as showing the board on the micro:bit’s LED display. Bright LEDs are the human’s Os, and dim LEDs are the computer’s Xs. I may see if I can create a version you can just play on the micro:bit itself with no computer attached, and maybe add a bit of randomness to make the computer a more interesting opponent. There’s also clearly scope to use functions to shorten some repetitive bits of code.

Self-contained micro:bit version

I also made a self-contained version that you can play just using a micro:bit V2, with no serial console or computer needed.

It works best with a headphones or speaker attached so you can clearly hear the speech instructions and who wins.

This version only works on a micro:bit V2 with built-in speaker which has more memory.

Press A to go first, B for micro:bit to go first.

Press B to step through possible play squares which blink.

Press A to choose a square to play.

Press reset button on back of the micro:bit to play a new game.

In conclusion

All in all, a nice, relaxing coding activity prompted by a 1980 book on programming the 6502!

Posted in computers, microbit | Tagged , , , , , , | Leave a comment

Raspberry Pi video art installation

My daughter makes video art and needed a simple solution for showing one of her pieces continually in a loop.

I used an old Raspberry Pi model B for this. I just realised that the only place I had documented this was on my now-deleted Twitter account, and I can’t recall where I learned about this method, so I just had a quick look at the machine in question to try and work out what I did to make it. I’m recording it here in case it’s useful to anyone else or, more likely, me.

The Pi has Raspbian Buster on it, no GUI/desktop, just the command line stuff. It needs omxplayer, which I think was installed by default.

I put the source video MP4 file in the default pi user’s home directory. (I may have transferred the file from a USB stick using fdisk to identify and

sudo mount /dev/sda1 /media/usb-drive/

to mount the drive, but you could also probably transfer the file using SFTP, FTP over SSH).

I also doubtless used raspi-config to force the audio to either HDMI or the 3.5mm audio jack, and maybe alsamixer to set the volume level.

The magic happened by editing rc.local:

sudo nano /etc/rc.local

Then I added some lines so it looked a bit like this:

# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi
omxplayer -o local --loop /home/pi/video-art.mp4 &
exit 0

Now when the Pi reboots, after quite a lot of boot-up text scrolling, the video plays and loops automatically. Connect to your monitor or projector and install in your art gallery!

Posted in Raspberry Pi | Tagged , , | Leave a comment

Why did 1973 matter to Classic Mac OS?

So I was clearing off an old 350MHz graphite Apple Macintosh G4 Server which had OS 10.4.9 on it, and decided to put Mac OS 9.2 on it for the lolz.

This was a mistake, as I had been intending to sell it, but now I am discovering old software, games and artwork I made many many years ago.

One thing that intrigued me was this dialogue box that popped up:

Mac OS 9 error message that the clock is set to a date before 1973

The motherboard’s battery long since died and I removed it, so the system clock goes back to its default setting. But why does Mac OS care if the clock is set to a date before 1973? Why 1973 specifically?

1970 is a significant date in computing – midnight UTC on 1 January 1970 is ‘the UNIX epoch‘ base. Time in Unix is measured from this point.

But 1970 is not 1973, and OS 9 is not Unix. (Its successor Mac OS X was, of course, built on Unix.)

I did a bit of digging into dates in HFS+, the Macintosh file system widely in use around the time this machine was made, around the turn of the millennium. Or Y2K if you prefer.

HFS Plus stores dates in several data structures, including the volume header and catalog records. These dates are stored in unsigned 32-bit integers (UInt32) containing the number of seconds since midnight, January 1, 1904, GMT. This is slightly different from HFS, where the value represents local time.

The maximum representable date is February 6, 2040 at 06:28:15 GMT.

The date values do not account for leap seconds. They do include a leap day in every year that is evenly divisible by four. This is sufficient given that the range of representable dates does not contain 1900 or 2100, neither of which have leap days.

So its timestamps start in 1904. And end in 2040. So, some more dates – but neither of them is 1973!

I tried searching the internet for anything about Mac OS and 1973, about the text of the dialogue box and found almost nothing. I did find a TikTok about an old clamshell iBook and this poem by Jeffrey Joe Nelson:

System Note

Your Macintosh’s clock is set to a year before 1973.

This may cause certain of your pomes to behave erratically.

So then I asked around at work, and after kicking around a few ideas, a colleague has, I think, probably solved it.

Look at the wording of that dialogue box very carefully…

Network time error

Your Macintosh’s clock is set to a year before 1973. This may cause certain applications to behave erratically.

[my bold]

Now my colleague reasoned thus:

Counting seconds in a 32 bit number gives you 136 years’ worth of counting.

If the classic Apple Mac OS epoch (zero time) is indeed 1904,  then 1973 would be precisely half way through that range.

If for reasons of temporary insanity, say, a third party developer held that as a signed 32 bit number, anything before 1973 would look negative. Negative time sounds like a dangerous concept. Certainly one that could cause applications to behave erratically.

No-one inside Apple would be so foolish.

But the developer of certain applications might!

I think he’s cracked it! What do you think?

David Tennant in Doctor Who saying wibbly wobbly timey wimey stuff

Updates!

@prozacchiwawa@functional.cafe on Mastodon adds this intriguing comment:

If an app cheaply checked whether subtracting two dates yielded a positive or negative result in signed space, moving the two dates farther apart than half the unsigned space could fool it. I’m wondering if that’s what they had in mind.

For example, 2023 (0xdfeb9580) – 1941 (0x4599a080) yields 0x9a51f500, which might mean to some apps that 2023 is before 1941.

 

 

Posted in Apple, lowendmac, operating systems | Tagged , , , | Leave a comment

This link may be unsafe

Or: The Straw That Broke This Camel’s Back

Screenshot showing how an https link to my Mastadon page was changed to http by Twitter, triggering a security alert

Elon Musk changed Twitter bio links to Mastadon to http instead of https – or blocked them.

He is a free speech absolutist free marketeer who doesn’t believe in free speech he doesn’t like, nor does he believe in free market competition.

Effectively he changed users’ profiles to make it look like they are scammers.

An insane way to treat users, aside from the many other, probably more important, reasons to quit Twitter.

Anyway, I’ve deleted my Twitter account now.

I know there are reasons to keep your account live, but, if you’re a journalist, I ask you especially to consider ceasing to post on Twitter and only use it for passive research, out of solidarity with your colleagues on The New York Times, Washington Post, CNN, Voice of America and other outlets who had their accounts suspended by Elon Musk for reporting on him.

  • Your DMs are not secure and may be used against you, just as he has used internal private messages against people
  • Your account could be suspended at any time and you won’t be told why
  • Posting on Twitter is providing free content on a toxic platform whose owner is using it to suppress journalism and spread disinformation, for example about COVID

twitter is over if you want it

Posted in internet | Tagged , , | Leave a comment

A Christmas Ghost Story: The Tedious Case of Room 623

The Tedious Case of Room 623 cover art

Had an idea for a story while walking the dog. I was going to abandon it, or at the very least change the narrator’s preposterous name, when I discovered that Agatha Christie wrote over a dozen stories about a man called Quin, Harley Quin and I thought, well I won’t let the stupid name put me off.

I probably should have let the rest of the story being poor put me off, but hey I didn’t. I just wrote this for my own amusement while avoiding writing a novel, and to see where it goes, if anywhere.

Ironically, given the narrator’s views, my original idea for this was as a podcast, or just some audio posted on Mastodon. I might still do that, but it would probably force me to reveal something about the narrator I’d rather leave ambiguous for now.

Download the story as a free PDF here.

Bonus marks will be awarded for spotting any of the popular culture references used in the story.

Merry Spookmas!

Posted in fiction | Tagged , , | Leave a comment