Civilisation

Application icon for !Civilisation
!Civilisation

Obsession

Gosh, Civilisation... yes. Civilisation 1 took over a little bit of my life back when I was at school. Starting with just playing it for fun - having got a copy from a friend without any manuals or anything - I began by making a note of the technology tree on paper, so that I could know what was a useful path to pursue. Running on the little laptop I'd borrowed from school it was great - I could keep playing all night, and did... <smile>

As the laptop was more powerful than the machines that the game was originally intended for, I could run a shell around the game and switch between it and other tasks. Importantly for me that meant switching to QuickBASIC to run (or edit) the program I'd written which traversed the technology tree. Given any technology it would produce a description of all the technologies needed to get it, either as a list or a tree. That way I could work out the best route to what I wanted which took me through the useful technologies.

The program to draw the tree is probably lying around somewhere, but I can't find it any more. The game was pretty easy to get to work on the old RM Nimbus systems that they had at school - amusingly bypassing the security by exiting through the BBC Basic implementation. By this time I'd played quite a bit with assembler on the BBC and had found it to be relatively easy to work with once you got the hang of things. I'd previously done simple direct screen access on a few little things, and my other games and projects - whilst simple - were stepping stones along the way.

A BBC version

You might think that I only ever nicked ideas from other places. I couldn't possibly comment <smile>. Seriously, though, a lot of the early things that I did weren't that original, and Civilisation is a typical example. They say that imitation is the sincerest form of flattery, but for me it's also a lack of imagination. I'm happy to admit that. I've come up with enough original things over time that I don't mind that now and then I'm only working from someone else's idea.

To write Civilisation for the BBC I needed to think about things in more clever ways, with more planning and to know what I was aiming for. This wasn't going to be something that ever got sold or anything - it was just for fun so that I could say that I'd done it.

I started out with the map generation. Essentially a program that fills in a wrapping array that maps the world with concentric circles in random locations for a few thousand iterations. Each circle increases the level of the array squares that it covers, and each inner circle increases it by one more level. It's a whole load of blunt cones pushing up into a grid of sliding pegs is how I thought about it. I termed the process 'faulting', although it's not really the same kind of thing.

The 'height' of the cones was controlled by the number of concentric circles, and their radius determined how sharp the cones were. Both factors determined the type of map that came out - whether it was mountainous or flat, consisting of large continents or archipelagos.

Once the iterations were complete, it was just a matter of flooding the land and capping the mountains - which is just a fancy way of saying that anything below a threshold became sea, anything above another threshold became a hill, and anything above a higher threshold became a mountain. I don't believe I had any support for deserts, although I'm not completely certain.

The map could be stored in the sideways RAM, along with much of the code that implemented the game. That way I could retain the use of mode 2 - a 16 colour mode. There were a lot of colours in mode 2, but half of them were flashing and so nearly useless to me. However, my choice was to use mode 1 (or 5) which only had 4 colours, and that just wouldn't give the right look to the game. The downside to mode 2 was that characters were huge - 20 characters across the screen, as each character was 8x8 and the screen is only 160 pixels wide.

The character size problem was countered by implementing my own characters, which were 4 pixels wide (but still 8 pixels high). A character set had been used in other applications which were this big, so it was pretty easy to reuse them. I'd previously implemented a 'mini mode 2' which used these smaller characters by trapping the character plotting vectors and replacing the standard characters with the thinner versions.

This code from that implementation was easy to put into the ROM so that I could use it in the game. Where previously I'd made all text use small fonts, in the game I only wanted them to come out in the font if called through my code. Part of the screen construction code in BASIC had an exciting routine:

DEFPROCSmall(A$,X,Y)
$&900=CHR$31+CHR$X+CHR$Y+A$+CHR$0
!&70=&900:*FX163,4
ENDPROC

Which makes perfect sense if you know that entry point 4 was a 'plot string referenced by &70' call, and that codes 31,x,y would move to those coordinates.

The graphics came next. I'd decided on what terrain I needed - I wasn't going to have anything complex. There would be flatland, hills, mountains, and sea. The 'coast' rendering would be determined by the type of land that bordered the sea.

I worked out all the combinations of the 9 cells and cancelled out the ones that were just duplicates of one another to produce the smallest number of coast types which I needed for the center of the 9 cells. I then reduced that further by removing all the coast shapes which were just inverted copies of others, horizontally, vertically or both. This produced a minimum number of coast graphics (19 in total) and at the same time imposed a requirement on the sprite renderer that it be able to plot any given image inverted horizontally, vertically or both.

This was useful, because it meant that the irrigation pattern - a set of blue lines to indicate water over the land could be flipped alternately horizontally and vertically, which meant that all the lines would join up. I had already decided that one 'colour' of the 16 was the mask colour and would allow me to overlay graphics. The roads and railroads followed a similar pattern, with just 3 forms of each being required - a 'middle to right' road, a 'middle to bottom right' road and a 'middle to bottom road'. All the other road forms were just flipped versions of those.

The coast itself had waves. I had all these extra colours that were doing nothing because they would otherwise just be flashing, and I had no need for them. So instead I assigned 5 colours (I believe it was 5 - I can't remember and can't find the code right now) to be the wave front. These would be palette cycled sinusoidally in the background. Once enabled, the ROM would sit on the VSync event and update the palette so that the waves kept moving whatever the rest of the game was doing.

All the sprites I was going to use I designed myself using a few templates that I'd thrown together in a simple custom editor written for just this job. All the sprites were saved in individual files named after their purpose, and these were then joined together into a data block to include in the ROM.

The Civilisation ROM was where all the code that did the work was stored. Everything was made modular so that sections could be assembled into the ROM as I needed them - it reduced building time - but they were always available through a few special calls. The *FX calls (on ByteV) had a couple of calls set aside for user operations (SWI OS_Byte 163), and the ROM processed these, which allowed me to call each of the routines individually if I needed to as part of tests. Most code relied on more than a couple of variables, so extra parameters were passed in values in zero page (addresses &70-&7F I think).

So to plot a sprite you'd write the coordinates and the sprite number to the zero page locations and then call the 'plot sprite' call, and the sprite would appear. I had a BASIC program as the harness for this, but essentially the 'game' part of it (the non-test) was a small loop with 'plot map', 'get input' calls in it.

The designs for the game and the layout of the calls and register maps were all written down on A4 sheets collected together into a little book that I kept by the computer.

I'd found and extracted all the technology and unit data from the original game and these were stored in individual files on the disc. A small section of the ROM code was devoted to loading the data from a file and displaying it in a window on the screen, so that when called upon, the 'Civilopedia' was available.

The ROM itself was built from a number of separate files, each of which constructed its little bit of the code and imported any data necessary. It was all written in BASIC assembler, and as it was assembled it wrote out a file containing exported addresses, and another file containing the places where the addresses were used. At the end of the assembly, the control program would be invoked and it would read the exports and apply them at the locations specified in the use file, effectively linking all the parts together.

The main game screen was designed in a small BASIC program that would call the ROM to plot icons and draw boxes, etc. At the same time it would write out a compressed version of the operations which it used. This way I could test out different layouts and when I was happy write out the results to a file. The file was then built into the ROM and the 'plot game area' call would expand and execute all the operations needed to draw the game screen.

The ROM copyright string tells me that this was last updated in 1993. It amuses me that that's now 19 years ago. There's a small test suite of programs that check the behaviour of the application is as expected, and each program has a little comment at the top of the BASIC which explains what it's trying to test.

When the 'game' was running, the small loop that handled the input also showed a little pointer on the screen that could be controlled by the joystick, and the player could press 'fire' over any of the movement or action buttons. The keyboard also worked as well, and supported keypad style movement on the number keys (despite the BBC not having a numeric keypad). The whole input system was handled by a single call, and returned the operation that had been performed by the user in a register. It made the main game loop a lot simpler!

There's some great gems in the assembler, such as the following that had me scratching my head in the game screen plot code:

570 .Jxlmpltdt:JMP xlmpltdt

It took me a minute, but I pieced it together...

  • J = long jump
  • x = exit
  • lm = little map
  • plt = plot
  • dt = dot

It's part of the little map renderer to jump to the exit code so that it can clean up. You've got to love the condensed variable naming. I learnt that I could use proper names when I moved to RISC OS and have never stopped since - it amuses me when I come across people using such obscure names for things these days.

But there's more fun stuff - you forget how exciting it is to only have 8 bit registers when you've been spoilt by ARM! <laugh>

ASL xl:ROL xh:ASL xl:ROL xh
ASL xl:ROL xh
LDA xl:CLC:ADC #32:STA xl
LDA xh:ADC #0:STA xh

Obvious, isn't it ? A 16 bit calculation on X (in xl and xh), multiplying it by 8 and adding 32. The Y calculation is even better:

ASL yl:ROL yh:ASL yl:ROL yh
ASL yl:ROL yh
LDA #940 MOD 256:SEC:SBC yl:STA yl
LDA #940 DVI 256:SBC yh:STA yh

which you might otherwise express as '940-y*8'. Both could probably have been done through a lookup table, but I don't think this is much less complex.

A RISC OS version

The family got an A5000, and so I was moving on up from the simple BBC version of Civilisation and started on a RISC OS version. It was nice to write code in ARM, and a more advanced BASIC interpreter. Oh, and a whole lot more memory!

Most of the code that I'd already written - the 6502 assembler - was completely useless on the A5000. Things like the map generator and the processors for text and the like were all reusable though. The sprites were usable, but they were a little smaller than I wanted. The sprites were originally 8x8, but with the RISC OS version I could do more. The new version had sprites that were 32x32, and I scaled up all the BBC sprites to the new size. For the coastline I rounded off the edges so that they were smoothed out nicely, and I started redrawing the units so that they weren't quite so blocky.

In the BBC version, the units had a one pixel border which would be the colour of the player, so that you could distinguish them. In the RISC OS version this became 4 pixels around the outside after the scale up, so all the graphics had more space as well.

Although the assembler needed rewriting, it wasn't too hard to get a lot of the code converted. Instead of writing direct screen access myself, though, I chickened out and used the standard SWI OS_SpriteOp calls. I say chickened out, but really I weighed up the hassle of writing a whole load of plotting functions for all the different screen modes that the desktop could run in (as I'd decided to do the whole thing in the desktop), and chose to use the OS routines that were provide for the purpose.

However, the basics of how the plotting worked remained the same - sprites could still be plotted flipped in both directions and the individual images would be plotted over the top in the same way as before. Because I'd already gone through testing things in the BBC version, and I knew exactly how everything worked in that version, it was just a matter of reimplementing the calls and then the tests. Knowing exactly what needed doing made things a lot easier!

Part way through I decided to use the game as my final A-Level project. It was going to be the biggest thing I'd done, and I knew a lot about it, so it should be easy to make a project out of it. As usual, that wasn't quite the case. Whilst it's easy to know what you can do, actually writing it up in a way that is useful for the course is harder. I've had a read through my project report and it's not all that great. There's a lot of very bad writing in there - very informal and not well thought out (and you thought this was bad! <smile>).

On the other hand, the report seems to contain the right things. There's an introduction that talks about what I'm doing and why. A section that talks about the background so that the reader knows what's being done and why (about the machines, processors, assembler, and reasons for choosing them). It describes the process of steps I went through to build up from plain sprites, and the landscape generation to getting things on to the screen. There's detail included on how the masks were selected for the coastlines so that the patterns give a smooth and pleasing outline.

There's an explanation of the tests, timing results for doing things different ways, and graphs of derived data to show that the calculations I was using would scale properly over the course of a game. There's a conclusion (which obviously says it is incomplete, but talks about what worked and what should have been done differently), and some discussion of future direction and work. Throughout there were tables and screenshots to illustrate what was being discussed.

At the end there's an appendix detailing some of the topics skimmed over in the report, a glossary explaining some of the terms, and a section giving attributions and thanks to people who had helped. And finally there was an index.

It may not have been a great read, but I think it hit all the right points. If there's anywhere it was let down is was in the completion - it just wasn't finished. But it did look pretty neat for what it did.

There's not really much more to say about the RISC OS version - it redid many of the things that the BBC one did, but used the RISC OS interfaces where possible. The different things that would have been in other areas of the screen in the BBC version - the main map, little map, buttons, achievements, city view (which was never completed) and so on - were in separate windows. The game happily handled multiple units, and would switch between them at the ends of turns - although it wouldn't jump to make the active unit the centre of the display, which made things a little irritating. That wouldn't be too hard to do though.

The RISC OS version did have cities, though, and could even label them using a selection of fonts. The idea was that an 'old' style font would be used early on, and as technology improved the fonts used in the map would update in line with them.

According to the documentation in my report, fights between units were nearly working. What it looks like is that the inner implementation for units being created, attacking, the random results, and the unit destruction exists, but beyond that there's nothing else - so no visible component yet.

The RISC OS version did have a slightly more impressive (I said 'slightly') landscape generator, which showed you what it was doing as it applied the landscape generation algorithm. I'm not sure that I would have exposed this if it was finished, but as part of the testing it helped quite a bit.

Let the water under the sky be gathered to one place, and let dry ground appear.
The land generation programs apply lots of 'faults' repeatedly until a threshold is met. (Animated version (7998K))
God called the dry ground 'land', and the gathered waters he called 'seas'.
The distribution of the heights generated by the faults determined the land mass distribution and the number of hills and mountains.
Below the blue line will be water, below the green plains, below the white hills, and the rest are mountains.

The final game in the desktop looked pretty reasonable - it needed a lot of work and the sprites would need updating, but it was certainly getting somewhere.

RISC OS civilisation, not quite finished
My earliest attempt at a game - replicating Sid Meier's Civilization. (Animated version (936K))

I'm really quite pleased with Civilisation, and it was mostly put on one side as I started to play with other things after I went to University. Being able to do things in a more powerful way with C, rather than assembler was a big influence. But also - and more importantly - I got to learn more about writing things for the Internet...

UMoria

I'm not sure where we found it, but we had a copy of Edouard Poor's port of UMoria to RISC OS. We'd not really played any role playing games before, so it was a little bit interesting. I can't imagine playing such things in person, without a computer, but it was great fun at the time. And, seemingly, still is a good distraction as I seem to have lost most of Saturday that I wasn't asleep to a game of it.

I've also checked out the Windows port of Moria which was a contemporary at the time. It's not that impressive - aside from crashing, the colouring is very poor compared to Edouard's port. Modern versions of Angband use prettier tiles, but I'm still fond of the simple ASCII graphics - albeit with colour.

Anyhow, I didn't like the fact that you only played until you died. If you died you couldn't restore your character, only the 'monster memory' that it had attained. So I put together a simple wrapper in its !Run file so that we could retain older files without losing them. I guess that goes against the spirit of the game, but I wasn't at all fussed about that - if it's not fun, then it's not much of a game.

Remembering which spell book particular spells (or prayers, if you were of a religious persuasion) was hard for me, so I knocked up some simple applications which presented the spells as little buttons. When you clicked the buttons, the relevant keys were sent to !UMoria to cast the spell. They weren't very complicated as programs - and I had one program for each of the spell books - but they did the job. Another thing that I wanted to get past was the lack of any RISC OS interface. It was all keyboard based, with no control panel at all.

I started a simple !Controls application which had little buttons to do the moving around the map. It gained other features such as being able to search in directions, or open and close doors. Since these weren't particularly complicated as key controls, I ended up using the keyboard most of the time anyhow, but I still wanted to be able to do more things than the game offered.

Initially this was for bartering. In the shops you were expected to barter, and the prices on offer were usually quite a way from the price you could get the items for. This was invariably tedious, and although the system learnt that you were good at bartering and offered you fixed prices if you'd done well in the past, it was still frustrating when you needed gear. Together with the !Zap 'read memory' feature, and some suitably convoluted operations, I located where in the application's memory the current display was stored and used that to be automate the bartering.

The !Controls application could read out from the display anything that was being shown and used that to determine what to do next. If the offer was accepted it would stop, but if the shop keeper wanted more for something, it would adjust its offer and supply this to the game. This was all tied to the ctrl-B shortcut. So whenever you wanted to buy things you only had to make a first offer and then press ctrl-B and you'd get a good deal.

Selling items came a little later, when I found I could return to the town and sell off the things that I'd found in the mines. The algorithm is exactly the same, except the price offered decreases rather than increasing.

A few more little features were added, which weren't that interesting. Things like automatic Wimp button generation for menus were quite nice though. If you wanted to read a scroll (for example) the application would spot that this was what you were doing and force the list of scrolls to be shown. These appeared as a list on the right of the screen, normally, but the application would read this list and present some Wimp buttons in a window appropriately labelled and ready to be clicked (which would trigger the right action).

The goodies were the automatic run around the map and mining that came later. Sometimes you didn't really want to do everything yourself <smile>. The automatic run made things a lot easier by just running around the map until it reached a monster of something that might be interesting.

Automatic run around the map follows the edge of the wall
The automatic run along the edge of the walls in !UMoria. (Animated version (85K))

The example above shows the automatic run, which stops when it encounters a Killer beetle, so that it can be killed manually. Then I can continue the automatic run, which continues down the tunnel until it reaches the next monster - a floating eye.

The automatic run kept even if it reaches a door - it tries a few times to open the doors before giving up and turning around. If it reaches a dead end it will search a few times, which normally finds any hidden doors, which it can then try to open. The runner followed a clockwise edge of the wall, and you could at any time stop the running by pressing the 'Shift' key. Additionally you could press the 'Ctrl' key to reverse the direction of travel - which was useful if it set off in the wrong direction down a corridor.

Automatic mining picks up gold, over multiple pages
The automatic mining clears everything in the veins in !UMoria. (Animated version (1542K))

The example of the mining is similar - all the vein of quartz, or darker rock (the '%' symbols) is mined until something unexpected is found, like a monster. The mining is recursive, and so remembers its path, unwinding when it completes, all the way back to the starting point. As with the automatic running, the code happily tracks the player even when they move between screens. It's quite a neat little bit of code, and because you can rapidly clear a large amount of rock, I added in a little extra label - "The JCB from hell!!!". At the end, if it actually collected any gold or gems it includes a small message telling you how much was picked up.

The automatic mining meant that it was significantly easier to get money which you could then use to upgrade your weapons and armour. Of course, if you were any good at the game you quickly outstripped what the shops could offer by finding better items in the mines. But being able to clear a lot of rock quickly was neat, especially when you used the staff of destruction (which fills a large area with rock, usually killing anything in its path)

There were other little things as well. One of the cheat interfaces was based on the features from other cheating tools such as special cartridges on consoles through to Doggysoft's Desktop Hacker - you could ask the !Controls application to search the application's memory for a particular value. It would list all the memory locations that the value appeared in. You could then edit it to replace the value with something else - for example increasing your health.

Of course, sometimes the values displayed are not the ones that are stored in memory, so there was a separate part to the cheat tool which let you store the whole of memory to a file at one point, and then compared it to the memory at another point. This would allow you to see which locations changed between the stored and current version.

It might not have been the best application, but it was a whole lot of fun with the game - not just for me, but for Julian and Simon as well. I couldn't find any of my characters in the old archives, so I used one of Simon's old characters for the examples above.

NetOXO

Application icon for !NetOXO
!NetOXO

I had written a few Internet applications, both services and clients, and I wanted to do something with a little more appeal to people in general. Games generally have more appeal than just simple applications for 'doing stuff'. Even more than chatting, games tend to be the things that get people involved, and games where you play against other people are far more fun than those against a dumb machine (albeit those machines are more clever than people most of the time!)

There really weren't many network games for RISC OS, so I decided to write a simple game - Noughts and Crosses is about the simplest you can get, so that was my initial attempt. The idea was that I write the game, and then I make it networked. It worked out quite well, but I found myself working with the network libraries quite a bit.

The main thing that it impressed upon me was that writing the game wasn't all that hard (for a simple game), but making it use the network was fiddly and ought to be a lot simpler.

The simplest of games
Noughts and Crosses is the simplest game to write, although it's not all that taxing to play. (Animated version (159K))

NetGames

Application icon for !NetGames
!NetGames

Having learnt from !NetOXO what needed to be done to make a network game, I believed that there was scope for some library to make it easier to write turn based games. I shouldn't have been as hard as I had found writing the !NetOXO to be, but now that I'd met the challenges there, I should really capture the results into a library so that I (or others) didn't have to do it again.

There are lots of turn based games, and they don't have to be as simple as Noughts and Crosses. The !NetGames library was intended to make it easier to write network games. It didn't solve all the problems, but the idea was to make it simple to write the basic games that might get people interested in writing some more complex (and more fun) games.

The library was based on my !JFShared libraries which I'd used for !NetOXO and most of my other applications, and which was pretty well tested. The main functions that were performed by the networking code were taken out and placed in a library to make them able to be used elsewhere.

The NetGame library itself wasn't all that clever. It only handled a single client connected at a time - and would reject any subsequent connections. It did, however, handle all the connection processing and validation that the connection was for the right game. Because it only handled a single connection, it was limited to 2 player games. This was a design decision to make it simple to write the library and reduce the complexity for anyone writing games. Well, that and the fact that that's what was needed for !NetOXO so it was all I started with <smile>.

The library could be directed to connect to a remote host and would call functions in the main application to report when it connected. If a connection was received from another application, it would call the function in a similar way, but reporting that that we were not originating the connection. In the games that I wrote to demonstrate the library, this was used to determine which player went first.

All of the messages from the other application were sent as simple strings, so were limited in size. My demonstrations used the first character of the string to indicate the type of data - an 'M' prefix indicated that the user had entered a message to send to the other player, a 'C' prefix to request that the board be cleared, or a position to indicate where they had placed their piece.

The idea was to use simple messages for all of the operations, and for the communications to not worry about data structures, timing or anything more complicated. It would have been possible to transmit larger amounts of data but I never really tried that - and it might have had issues if the socket buffer filled up. The game library would detect if the user quit abnormally (either because they crashed, routing problems, or whatever) and report this to the application. If they disconnected 'properly' (usually by quitting or pressing some button), this would be communicated with a different reason code.

This allowed the application to differentiate between clients who quit and those that just had other problems. It was quite important to me as I'd often played games where people quit when they were losing, or seemed to quit when they were losing but actually just had network issues.

After writing the network libraries, a couple of people spoke to me about writing a better framework for games so that writing games for the STBs could be made a lot easier. I remember chatting to someone from Acorn about it at one of the shows and then exchanging a number of emails before their interest dried up. I think that partly I wasn't really ready for writing anything more than toy things at that time, and partly they liked the idea but couldn't see a good way to justify the work in a commercial sense.

At least that's what I remember about it - thinking back, there may also have been some reticence in working with someone who was still writing BASIC applications, and hadn't had any commercial experience. In my defence, I wrote the BASIC applications because a) it was well supported and worked for what I was doing, and (more importantly) b) that's where I saw the benefit in having a simple network library - the people playing around, writing little BASIC programs were exactly the sort of people who could find this sort of thing useful and be spurred to write something more clever.

As with all of my !JFShared libraries, a !StrongHelp manual was supplied, and as with those libraries, it was very poorly explained what it did. The !Help file didn't really give a lot of guidance and there was no tutorial. As with the !JFShared library, it bothered me at the time that people didn't use it much. I never thought beyond the fact that what I'd supplied was good enough for me, but other people needed more information and guidance. It is no good explaining what the library functions do if you've got no idea what it is that it is trying to achieve or how it fits together. An overview of how it worked, and a simple tutorial - maybe showing how you might build the !NetOXO game using the library - would have helped a little there.

SiteEdit

Application icon for !SiteEdit
!SiteEdit

The sites editor is a perfect example of a useful thing that was completely unexplained in the 'documentation'. The principle was simple. For most of the network games you need to supply a target host and port to connect to. You want to have these bookmarked, so that you don't have to enter them by hand each time. The NetGame library provided functions to read a simple 'Sites' file which contained such bookmarks, but editing it was more complex and it would be foolish to include that code in every game application.

That's where the !SiteEdit application came in - it provided a way to edit these Sites files in a simple and (relatively) friendly way. The application could even be replaced by something else if there was a better editor written - I could have easily replaced it with an application that listed the sites in a window or provided a set of icons for the configured sites in the future. Essentially it became a shared tool for all the network games.

But this wasn't at all explained in the documentation, and not helped by the fact that !NetOXO didn't support it - because I had never updated it to use the new library. <sigh>

Amazingly, though, someone did actually use my library to create a game - and quite a nice one it is, too. Robert Hampton used my library, together with a single player game by Phil Norman, to create a network version, called !NetReact. I loved it, not only because someone was actually using my stuff to create something fun, but because it was a version of the 'chain reaction' game that I'd written previously as 'Explode' (see the prior ramble).

NetC4

Application icon for !NetC4
!NetC4

From the notes I've got here, !NetC4 was written after I'd sent the !NetOXO application to Acorn User and they suggested that something better like Battleships might be more fun. There's one thing I can say quite definitely, and that is that it's not Battleships. Which is odd because I look back and think 'well, duh, yes that would have been far better a game to write'.

However, I didn't. I guess because it was more complex and I wanted to show off the !NetGame library. I really think I made a mistake there and Battleships really would have shown off that you could write a decent game using the library. Connect 4 is... well, it's still a bit simple. But it is a pretty good demonstration of how you can make a network game. It has simple animation (counters dropping), messaging between the users, and a more complex board to play on, whilst still only using simple input.

A lesson in playing with yourself
Playing against yourself isn't half as fun, but it shows the game is playable. (Animated version (428K))

If I wanted to think of other games that might have been good follow ups, something like Dominoes, Othello, Go, Draughts, or even more obscure things like Nine Men's Morris could have worked well with the system, and that's before you move into other games that don't strictly have to be turn based. There's no reason why you couldn't have race solitaire or similar games implemented with the same library. The main restriction you'd have would be that you couldn't have reliable timings in the games - it wasn't that kind of synchronised library, although I had considered a variant that was, using some of the things that I had learnt from working with Doom's network code.