My 2nd eBook is going to be a bit like the first one- first it teaches C but it is oriented towards Raspberry Pis. Then it shows how to program Asteroids (like the first book) followed by a Match three game and finally a Rogue type dungeon explorer game.
Now some rogue-likes stay true to the originals which were text based. Like this above from an article on Wikipedia. Now that’s ok, but I fancy something a bit more colourful so I’m going to use 16 x 16 pixel graphics.
I did a bit of searching and found these dungeon graphics on itch.io. I’ll use those to start with but may change. The view is not quite top down but top down with a bit of isometric in it. It looks better than pure top down.
So I figure the game has to have these elements.
(1) Generate a dungeon with multiple rooms and levels and stairs between,
(2) Fill the dungeon with monsters and treasures.
(3) Move the player’s character through the dungeon fighting monsters, picking up things including keys and maintaining a small inventory.
(4) Add some side quests like needing to find keys to open a chest with a magical item.
(5) I’ll also need to devise a simple combat system with magic.
Do monsters move- you’d hope so. How are rooms connected, in fact how are dungeons generated? I created a dungeon generator for the postal game Quest 30 years ago and can remember how I did it so there’ll will be that to implement in C.
I’m also going to leave out things like needing food and water.
So there it is now. Now to start writing the software. I’ll update this with progress reports.
I spent several years in the 1980s programming games.
I have a memory of 26 year old me sat hunched over a computer late at night back in 1985. I was working a 60-70 hour week as a partner in a games company. My current game was an American Civil War tactical wargame called Johnny Reb II. I was struggling with some ‘artificial intelligence’ code for the attackers (Confederate troops) to cross a bridge over a river. On the other side the defenders (Union) were trying to defend the bridge.
Artificial Intelligence in games is a completely different thing from ML and Data Science nowadays. Back then it was just a control algorithm for troops reacting to the presence of enemy troops and working out the best routes, targets to attack, whether to retreat and so on.
What made it worse was that the whole thing was written in 6502 assembly language (and later converted to Z80). Back then you had two choices: Basic which was to be honest slow and clunky for writing games or assembly language. If I was doing it now, without a moments hesitation I’d program it in C. But C compilers for 6502 didn’t exist back then.
The Problem with assembly language
The problem with assembly language is (a) it’s slow to write. You can write 10 lines of C in the same time as ten lines of assembly code. Those ten lines of C will do far more than ten lines of assembly code. In 6502 all you are doing is moving values between registers or register <> memory. Maybe add a number or increment one of the three available registers A, X or Y. These were all 8-bit registers so you couldn’t even index easily through 64-bit memory. To do 16-bit indexing you stored the 16-bit address in two successive page-0 locations (addresses 0-255) and then used Y as an 8-bit index. You could do the same in page 0- memory with the X register.
(b). It takes a lot of code to do anything in assembly language. You want floating point arithmetic in 6502? Take a look. I think Steve Wozniak wrote those for the Apple I/II. What we take for granted in languages like C# or Java or JavaScript is code for high level data structures like dictionaries. I’m sure it could be done but it takes a fair bit of programming. You don’t have those in assembly language; all you have to use is simple and not very long arrays.
In C# I wrote a program to read a 46 MB text file and produce a sorted count of all words in the file. It used a Dictionary, took me 30 minutes to write and it ran in 5 seconds. It would take weeks to do the same in assembler.
6502 Page 0 locations were valuable because they made your code both shorter and faster.
I wrote a cross-assembler for 6502 in Z80 as a way to learn Z80. Assemblers use labels (L20, L30, L31 etc. in the screenshot) and I needed a way to hold them efficiently in memory. I ended up with a 26 x 26 index table of 2 byte pointers. If you had a label ‘ROUTE’ then there would be a pointer to a chain at the location for [‘R’][‘O’]. Each entry in the chain was like this
1 byte length of rest of label (i.e. 3 for ‘UTE’) – 0 marks the end of the chain.
3 bytes to hold ‘UTE’.
2 byte address value
No need to hold the whole word as you know the first two letters. It also makes comparing a label against one in the table was faster because it only needed to match against len(label)-2 characters.
So the next value in the chain would start after that or be a 0 for the end of the chain. Yes most of the index table might be empty (all 26x26x2= 1352 bytes) but every label in a chain used 2 bytes less than the full label text. So with more than 676 labels you saved memory. Searching for a label was just a matter of walking a chain. Labels were just addresses; so a location could hold a value like a count. You’d identify it with a label and use that label in 6502 instructions. No variables in assembler; it’s all addresses…
With 6502 you need to do two passes to generate code. If you have a label in the first page of memory (0-255) then instructions are only two bytes long and are faster to execute than the three byte instructions. So on the first pass you don’t know if a LDA label will be 2 or 3 bytes long. After the first pass through though you do know now, so on the 2nd pass it can output the correct size instructions.
Programming in assembler means you have to write a lot of code and in the early days before I had a development machine that meant I had to save the source code to tape and compile it using a cartridge assembler. The CBM-64 could take cartridges and one of them stored assembly language in RAM just like Basic. If the game did something wrong then the CBM-64 would reset and you’d lose your source and have to reload it from the slow tape. Let’s hope you didn’t forget to save changes before you ran it. I spent a few hours gnashing my teeth over a persistent crash. I was calling a CLR routine when it should have been CLS! d’oh…
So a game back then might be 5,000 lines of code or longer. That’s quite a bit to hold in memory, given that you need space for the game machine code, sprites, graphics etc. as well. Plus it’s wasteful having to recompile the same code over and over again. My cross-assembler did 250 lines per second but divide that by two for the two passes.
So I split up long files into smaller ones and created a jump table at the start. There was no linker so the code was loaded into RAM at fixed addresses. If you had five subroutines in one file then there’d be five jumps at the start to the actual function. And the files that called those functions just had a block of five calls at the start.
That way you didn’t have to worry exactly where the function was located in RAM so long as that file was always loaded at the same address.
Switching to Development Machines
It got easier when we switched to development machines. The CBM-64 had a parallel port as did the development machine (Tatung Einstein-a CP/M computer) so a little bit of handler code in the CBM-64 set up the CIA chip to wait for data sent down the parallel cable and put the code directly in RAM. It took no time to load the handler from tape after a crash and then send down the whole file.
Modern CPUs do all sort of optimizing tricks and that’s even before you use vectorization. Compiler writers know how to generate code that uses these tricks but it would take quite a while to learn them so you could use them in hand-written assembly.
Conclusion
Writing in assembler in the 80s was easy to learn. Nowadays I wouldn’t know where to start- the Intel and AMD CPUs have a lot of different chips in their families so there are variations in what instructions are available. Oh and don’t forget there’s ARM CPUs as well.
Writing in C (or even C++) is a lot easier to get into and I very much doubt if you’d get any better performance in writing things in assembly. Also, it would take a lot longer.
Something had gone wrong and I couldn’t change the DNS because it was showing up in somebody else’s account. After I proved ownership of the domain by adding a TXT record they fixed it and I added the hosting name servers in.
Within a few minutes the domain was hitting the server and after I edited the A record to get rid of the parking, it correctly picked up my dummy place holder index.html.
Interestingly I could only add TXT/SPF records at 123-reg.co.uk and Google’s online dig tool (shown) couldn’t pick them up.
Hiding the VPS
I decided that I’d let the main web domain take the strain from hackers trying to access the VPS. So the web game will save orders into gamedomain.org/n/orders and get results from gamedomain.org/n/results for game n. (Not the real game domain!) But behind the scenes the VPS that runs the game processing code will pull orders from that orders folder. The VPS is located elsewhere, not even in the same hosting and after processing, it will copy the results back to the relevant results folder.
This solves a couple of problems.
Getting the orders in (and results out) requires a web interface. Because the game is based on the postal model, it’s quite feasible to keep the web interface and the processing separate.
Increased security. If you don’t know where the VPS is located, it’s somewhat harder to hack it!
I’m also experimenting with having a web command interface. Commands get picked up pulled to the VPS and executed. For example creating a new game, pulling in game processing logs and so on.
There are plenty of other programming languages that would do. Programming languages are just tools but C# comes with several advantages.
I know it pretty well, having been using it since 2005.
With .NET 6 (and 5), it’s easy to create applications that run on Linux. This lowers the cost for hosting. I’m setting the game on a low cost VPS.
Also on Linux, ASP.NET works pretty well for both Websites and Web Apis.
I like some of the recent changes in C#. And Visual Studio 2022 Community Edition is pretty good. For instance the JSON handling has got better and better.
Do you know what Hello World in C# looks like now? Here it is in its entirety.
Console.WriteLine("Hello, World!");
That’s a console application. One line! Follow the link for more details about the C# templates. Note, there’s no usings there either. That’s because applications now start with a default set in C# 10 and .NET 6 (you get both if you install VS 2022). And if you want a particular namespace that you’ve written to be available to all source code in a project, you can just add this:
global using xyz;
And it becomes available everywhere without needing any more usings.
Back in August I mentioned WikidPad which I had been using for ideas, design notes etc.
Recently though while waiting to get my Windows PC sorted, I’ve been doing nearly everything on an old laptop that I’ve repurposed by installing Ubuntu. All blogs since March 6th have been done on this laptop.
Today I came across Dendron which is a markdown editor (on steroids!) that runs in VS Code. Anyone who reads this blog knows that I’m a big fan of VS Code so it’s a no-brainer to combine the two.
Markdown is a way of annotating text for example *this phrase* will appear in italics. Dendron lets your have a split view so you type in the markdown text on the left and the page appears on the right.
The idea is that you create your document out of lots of pages, that are hyper linked. Dendron makes it easy to create pages and link them. Markdown is used to add formatting. WikidPad used a similar scheme but it was a Windows application holding pages in a SQLite database not an extension to VS Code as Dendron is that holds pages as individual text files.
Dendron appears a lot more powerful so I will be getting to grips with it. It’s a handy way of designing and documenting a design.
This is another post in the Inselkampf series. Having spent much of my career creating “desktop” application, web always feels a bit different. If it’s a website then HTML/CSS/PHP + MySql is a reasonable way of working. But when its a web application like a browser game that uses a SQL database, then there’s a bit of architecting involved.
I’m using Blazor because it lets me write C# that runs in the browser. I’ve never been a JavaScript fan though I realise many people are. I also have to use database. As I’ve said before Blazor gives you two choices- The WebAssembly version that runs completely in the browser and the Server version that talks to a server using a protocol called SignalR.
I’m trying to be clever by using the WebAssembly version but having the C# talk to a restful interface. Restful just means it has a bunch of http calls to do things like update, fetch data, login etc. On the server runs a ASP.NET program implementing this. It’s headless, as in its not outputting any webpages to the browser but just returns data in JSON (or maybe MessagePack).
This avoids having a SignalR connection for every user logged into the site which is one way to bring a server to its knees. When you create a Blazor Server application, it has a few disadvantages. As Microsoft says: when you use Blazor server.
Higher latency usually exists. Every user interaction involves a network hop.
There’s no offline support. If the client connection fails, the app stops working.
Scalability is challenging for apps with many users. The server must manage multiple client connections and handle client state.
An ASP.NET Core server is required to serve the app. Serverless deployment scenarios aren’t possible, such as serving the app from a Content Delivery Network (CDN).
I’m also not using the Microsoft authentication but rolling my own. Yes it’s possibly not perfect but I’ve done it before. This way I get to generate recovery numbers. (Both GitHub and Gmail offer these). A bunch of one off codes that are used to authenticate you, if you’ve lost your password or messed up your email then you login with your account number and an authentication code. This is the only way you get to change email and/or password. You just have to keep the codes safe.
Rolling my own Interface
So things like logging in, getting current status, updating game play are all done by making a call to an HTTPS routine. This is all behind the scenes so players see nothing. Values are sent as POST parameters and also include a nonce. This word (that unfortunately means sex offender in UK English!) , refers to a special code that has to be supplied with each call to the server to authenticate it. Successful logging in returns a nonce that has to be added as a parameter with every call to the server.
The program on the server that serves the restful calls is a simple ASP.NET Razor pages application (Well maybe Razor, I’m not sure if I need them). Behind the scenes I’m using MySQL which was installed as part of VirtualMin (the excellent software I use to setup the VPS).
I’ve talked about Inselkampf in a previous post. it was an example of a PBBG (Persistent Browser Based Game). Currently if you want to write a web application that updates part of a page without refreshing itself, you have to do it via a JavaScript toolkit. People have been doing this going back about 15 years or so initially using a technology called AJAX.
Refreshing an entire web page takes a few seconds- some of the pages have got really big what with trackers and other things that bloat them up. So being able to update just part is a massive time saver plus it looks good. Browser games couldn’t work without it.
Blazor takes things further by letting you update parts of pages, controls but in C#. There are two types of Blazor. WebAssembly (the machine code of the web) which does everything in the browser. It’s how the trains program works. The other type uses a server and does everything server side (controls and data) then sends it to the browser to be rendered.
For my purposes, the WebAssembly one is better. If you have a lot of people connected to a server then the Blazor server can use a fair whack of server resources. Th Blazor WebAssembly will also connect to the server but just to fetch or update data. So I’ve bought a Udemy course and am soaking up Blazor.
There’s still all sorts of questions. For example keeping the tick in synch. PBBG games often have a clock where new resources, building construction happen after a few seconds or longer. If you do this on the server then it’s not so difficult if the browser gets disconnected. In the browser though, it has to update the server or come up with some scheme so the browser and server don’t drift part. These are all part of the fun designing and programming such games. But I definitely think Blazor offers a lot of potential here.
Having just published Slay Tutorial three, making the Onslaught game play well as a computer opponent(well up to 8 of them) has been weighing on my mind. I have played the original Slay perhaps a couple of thousand times, so I’m reasonably familiar with strategy.
There’s almost 500 games on the Slay game chooser screen shown with four different sizes of islands; the four boxes. Usually by the time I’ve played through all games here (probably taking 18 months to two years) , I can start again and have forgotten what it was like. Plus I think it randomises the starting positions so you get a lot of replay value.
In the first Slay Tutorial I published a map of the tutorials and so far am sticking to it. Tutorial seven is the one for the game AI and its on my mind. I play all the Slay games at the same top intelligence level and even it sometimes makes stupid mistakes like leaving an area vulnerable to splitting and losing all units due to starvation.
The main aim of any player is to expand their territory at the expense of other players. Joining territories can be one tactic as its lets you support the bigger units. The 2 point unit is a Peasant then there’s Spearmen (6 points) , Knights (18 point) and Baron (54 points). Getting a Knight early on gives you a big advantage as it can defeat castles and too often I’ve seen a territory with one or two spearmen get trapped by castles and destroyed in a few turns.
Likewise putting a castle down early on can secure a territory for a while. Or if you have a larger area, a couple of castles can shield your flanks so you can focus yoyr troops against one enemy and not worry about other players moving in.
Self Playing
In Slay once you are eliminated the games plays through until one player beats everyone else. But self-playing can also be a useful way to have computer players learn. One possibility is to try and implement a “matchbox” AI. This was done with Tic-Tac-Toe (noughts and crosses for us Brits) with Menace, Now it may be that Onslaught is too complex to implement that but there’s a lot of RAM available, so if I can limit the number of setups that it recognises then maybe?
Anyway there’s a fair bit of time and Tutorials 4-6 to do before I get to Tutorial seven.
PS
If you move the mouse over the About Me, you’ll see a link to a page that has short cut links to all blog posts along with the title of each. It’s a quicker way of navigating.
In an earlier post on web games, I mentioned an old multi-player web game that I used to play and which was discontinued in 2014. I have a rough design for this and am busy learning Blazor as I believe that would be the best technology to use. It lets you run C# programs in the browser, no JavaScript needed. This simplifies input with verification and also updating the web page without having to do lots of messy Ajax stuff.
But being a web game there is a web server involved and the big question is what sort of data architecture to use? The most obvious one is probably using a relational database behind the scenes. That way each game (with up to 1,000 players) is held in a single database in about 12 tables. I’ll probably use MariaDB.
I did consider doing everything in RAM but its a terrible abuse of a web server and rather restricts it to running one or two games. Pulling stuff out of a database is much less strain on the system than having a few hundred MB of RAM tied up per game. A web server can support multiple games which helps keep the costs down.
Also with a web game, it raises the possibility of caching certain static files on disk to improve throughput. This blog uses WordPress but has a cache so when you view a page, it’s almost certainly been pre-generated rather than built on the fly.
An example of a web game that I admire is Torn.com.
Here’s my answer. “Think about how you might make it work as a roleplaying game. You’d have a set of characteristics- age, cuteness, physical attraction, charisma, boldness etc. Have your characters roll 3 6 sided dice to get these. Then you can work out an easy scoring system by comparing similar characteristics.
So once you have a basic matching algorithm, your game has to let the player find potential dates. In the gym, supermarket, dating site, college etc. Perhaps you get an initial idea about someone you meet and then you get multiple dialogs where you try and figure out how to ask them out. Choose the wrong phrase (e.g. “Do you spit or swallow?” ) and you won’t see them for dust. Maybe if the person you are asking out has a large personality they’ll laugh at your humour and say yes.
Then you have to decide what wins the game. Getting to first base, 2nd, breakfast? Or you get a low score when they tell you they’ve decided to become a nun because of you…
How you implement it is entirely up to you? Things like renpy, or maybe you’ll do the whole thing. For the possible target market I think you might have to make it graphical. Perhaps a comic-book type approach? That way you don’t need too many drawn backgrounds.”
This is the kind of thing you might use Renpy for. What is Ren’py? Ren’Py is a visual novel engine used by thousands of creators around the world that helps you use words, images, and sounds to tell interactive stories on computers and mobile devices. These can be both visual novels and life simulation games.
I got the screenshot from Wikipedia. Talk about breaking the fourth wall! And yes Ren’py has an irritating apostrophe in the middle!