Web Programming

Q War - Shockwave game

Oliver Brown
— This upcoming video may not be available to view yet.

At around the same time that I worked on Supremacy, I worked on another game called “Q War”.

Interacting with this video is done so under the Terms of Service of YouTube
View this video directly on YouTube

Both were inspired by the content of Gary Rosenzweig’s Advanced Lingo for Games book. But where Supremacy was a slight refinement and rebranding of a complete game, Q War takes one behaviour (the implementation of the bullet sprites from both the “Space Invaders” and “Space Rocks” games) and builds a different game, complete with “original” graphics.

I believe I worked on Supremacy first as a learning exercise, and then started Q War. But I made Q War available first. The only hard evidence I have is the remains of the Shocklive! site in 2001:

  • 8th February - Site created! Q War, a two level action shooter is playable
  • 18th February - A Completely re-done Q War has been uploaded!
  • 14th March - Supremacy, a new fun strategy game is now available!

The game has been submitted to the Flashpoint Archive but as of 27 May it is not yet available. It is also sort of playable directly on this site.

Gameplay

Each level puts you in control of a ship that can fly around and shoot, with limited shields that deplete as you take fire. The game supports one or two players working cooperatively.

The game is split into multiple levels, connected by a map screen between each one where you choose your next destination. Starting in the top left, the goal is to reach the bottom right. Levels can be blank, or they can contain obstacles — either an asteroid belt you need to survive for a set time, a powerful enemy station that is shooting at you, or a pair of enemy ships to defeat. Any combination of those can appear in a single level, including all three at once.

Online features

Q War features two online features.

Maps

The map is loaded from the map.txt file along side the game file on the server. An example map.txt file:

[["xxx","a1x","a1x","xxx","xs1","xxx"],
 ["axx","axx","axx","asx","x2x","xxx"],
 ["axx","xxx","xxx","axx","x1x","xxx"],
 ["axx","axx","xxx","xxx","x1x","xs2"]]

Firstly, that format is the default way Lingo serialised an object. That is an array of four elements, each of which is an array of six strings.

I think the game technically predates JSON (Wikipedia says it was first specified in March 2001). It certainly predates JSON being widely used for anything. As such, Director and Lingo do not support JSON and instead use their own format. However, for string arrays, the syntax just happens to be the same.

Each string controls one map cell with the following rules:

  • If it contains an “a”, the level contains asteroids.
  • If it contains an “s”, the level contains a station.
  • If it contains a “1” the level contains one enemy ship.
  • If it contains a “2” the level contains two enemy ships.

It seems the order does not matter.

The map is also absolutely required to be exactly 6×4. It just uses direct indexing and would crash otherwise (I think technically it could be bigger without a problem).

The reason the map is loaded from a file is so I could provide multiple maps. In fact, I had it so the maps were generated by a PHP script:

Complete map script
function createMap() {
    mt_srand(time()^2);

    $rand = mt_rand(1,4);

    if ($rand <= 1) {
        $a = array('x','a','a','x','x','x');
        $b = array('a','a','a','a','x','x');
        $c = array('a','x','x','a','x','x');
        $d = array('a','a','x','x','x','x');
    } elseif ($rand <=2 ) {
        $a = array('x','a','x','x','x','x');
        $b = array('a','a','a','a','a','x');
        $c = array('x','x','a','a','a','a');
        $d = array('x','x','x','x','a','a');
    } elseif ($rand <=3 ) {
        $a = array('x','a','a','x','a','a');
        $b = array('a','a','a','x','a','a');
        $c = array('x','x','a','x','x','a');
        $d = array('x','x','a','a','x','a');
    } elseif ($rand <=4 ) {
        $a = array('x','x','a','a','a','a');
        $b = array('a','x','x','x','a','a');
        $c = array('a','a','a','x','x','x');
        $d = array('a','a','a','a','x','x');
    }

    $file = fopen('map.txt', 'w');
    fwrite($file, '[');

    for ($j=0;$j<4;$j++) {
        fwrite($file, '[');
        for ($i=0;$i<6;$i++) {
            if ($j == 0) {
                $row[$i] = $a[$i];
            } elseif ($j == 1) {
                $row[$i] = $b[$i];
            } elseif ($j == 2) {
                $row[$i] = $c[$i];
            } elseif ($j == 3) {
                $row[$i] = $d[$i];
            }

            $rand = mt_rand(1,24);
            if ($i == 5 and $j == 3) {
                $row[$i] .= 's2';
            } elseif ($i == 0 and $j == 0) {
                $row[$i] .= 'xx';
            } elseif ($rand == 1) {
                $row[$i] .= '1x';
            } elseif ($rand == 2) {
                $row[$i] .= 'sx';
            } elseif ($rand == 3) {
                $row[$i] .= '1x';
            } elseif ($rand == 4) {
                $row[$i] .= '1x';
            } elseif ($rand == 5) {
                $row[$i] .= '2x';
            } elseif ($rand == 6) {
                $row[$i] .= '2x';
            } elseif ($rand == 5) {
                $row[$i] .= '1x';
            } elseif ($rand == 6) {
                $row[$i] .= '2x';
            } elseif ($rand == 7) {
                $row[$i] .= 's1';
            } else {
                $row[$i] .= 'xx';
            }
            fwrite($file, '"'.$row[$i].'"');
            if ($i <> 5) {
                fwrite($file, ',');
            }
        }
        fwrite($file, ']');
        if ($j <> 3) {
            fwrite($file, ',');
        }
    }
    fwrite($file, ']');
    fclose($file);
}

First the layout of asteroids was chosen from four possible layouts. Then each cell had a random chance of also gaining ships and a station. Finally, the first cell is always blank, and the last cell has a station and two ships.

And astute readers may not the $rand == 5 and $rand == 6 cases duplicated. I only noticed this while writing this post.

High score table

The reason why the maps were variable is because it also had an online high score table.

You could enter your name, and it would keep track of the high scores for the current map, including keeping solo and coop separate.

There were two different implementations of the high score server script, and considering the two shows some of my developing understanding of how to design systems (if not really any serious consideration of security).

Highscore server script version 1
<?php
include('../connect.php');

if (!$mode) {
        $mode = "Single";
}
if (!$player) {
        $player = "<i>No Name Entered</i>";
}
if (!$score) {
        $score = 120;
}

if ($score < 1000) {
        $score = "0$score";
}

connect();

$sql = "SELECT * FROM qwar ORDER BY number DESC";
$result = mysql_query($sql);
$row = mysql_fetch_object($result);

$num = $row->number;

$sql = "INSERT INTO qwar_".$mode."_".$num." VALUES('$player', $score)";
$result = mysql_query($sql);

print "Done\n";

function check() {
    connect();
    $sql = "SELECT * FROM qwar ORDER BY number DESC";
    $result = mysql_query($sql);
    $row = mysql_fetch_object($result);

    $time = $row->time;
    $num = $row->number+1;

    if ($time < time()) {
        $time = $time + 604800;
        $sql = "INSERT INTO qwar VALUES($time, $num)";
        $result = mysql_query($sql);
        $sql = "CREATE TABLE qwar_Coop_$num (name varchar(30) DEFAULT 'No name given', score smallint(5) unsigned DEFAULT '0')";
        $result = mysql_query($sql);
        $sql = "CREATE TABLE qwar_Single_$num (name varchar(30) DEFAULT 'No name given', score smallint(5) unsigned DEFAULT '0')";
        $result = mysql_query($sql);
        createMap();
    }
}

?>

In the first version I hadn’t really got database design at all.

The check function was called periodically to check if a new map should be generated (probably as part of some other page load).

If 7 days (604,800 seconds) had passed I generated a new map and I created a new table for the new high scores (actually two tables; one for single and for coop) I also stored the number that was part of the name for the tables so I knew which tables to store scores in.

Other than that, I just stored the name and score into the relevant table. It relied on the amazing feature PHP had back then called register_globals which just dumped GET and POST values into variables with the same name.

This obviously meant you could just craft a very easy GET request to post whatever score you wanted. Oddly enough, I don’t think anyone actually did.

Highscore server script version 2
<?php
include('../connect.php');

if (!$mode) {
    $mode = "Single";
}
if (!$player) {
    $player = "<i>No Name Entered</i>";
}
if (!$score) {
    $score = 120;
}

connect();

$time = time();
if ($score < 12000 and $HTTP_SERVER_VARS["REMOTE_ADDR"] <> '80.137.161.246' ) {
    $sql = "INSERT INTO qwar VALUES(NULL, '$player', $score, '$mode', '$time')";
    $result = mysql_query($sql);
}
print "Done\n";

?>

For version two, some things are better. Firstly, the high scores are now in a single table with extra columns of mode and time.

And… that was it. Everything else was the same.

Except for some reason I was blocking high scores from one specific IP address. I cannot remember why. Maybe someone actually did try cheating?

I did actually make one extra addition a few years later. Another parameter that identified what website you were on so it was possible to host the game in different places with unique high score tables. I even blogged about it:

Random trivia

The name

This game predates Galaxia, and as such it predates my online name “GalaxiaGuy”. Back then I used the name “Admiral Q”, a reference to the STCCG card Military Privilege which includes the quote: “Starfleet Admiral Q at your service!”

As such, I naturally named everything with a “Q”.

There are a few old posts on this blog mentioning Q War. Notably, my 2004 references spell it “QWar” rather than “Q War”. This is obviously wrong since the title screen clearly renders it as two words, but apparently past me was less bothered about such consistency.

Graphics

Unlike Supremacy, the graphics are “original”. And by original, I mean I didn’t just get them from the Lingo book and conceived of them myself. In reality they are lovingly based on existing Star Trek material.

Player ships

Player 1
Player 2

The player ship is the Bajoran Raider from Star Trek: Deep Space Nine. Weirdly, the original has a pair of struts connecting to the wings, but I’ve filled in the gap in the middle essentially making the wings wider.

I also added a tint to the ship which is blue and green for player one, and red and yellow for player two.

I would later reuse the ship graphic for Gravitas.

Enemy ships

Working this out took some time.

As a small aside I would like to call attention to the excellent Star Trek website Ex Astris Scientia by Bernard Schneider. In this case his Starship Gallery was an invaluable resource without which I would not have found the source of this ship.

The enemy ships are Vidiian ships, specifically the “Vidiian ship 3” from that link.

Possibly to introduce a bit more colour to the game, or maybe just to hide the source, I drastically changed the colour from the original brick red to the weird lilac cyan combo.

Enemy station

The space station is the Renegade Borg Ship from the Star Trek: The Next Generation episode Descent (the one with Lore and Hugh).

The only change I made was to make it green.

And honestly, I’ve always thought this shape makes much more sense as a station than a ship.

Asteroids

The asteroids actually are completely original creations I made in Paint Shop Pro 5, and for whatever reason I remember exactly how I made them.

  • Generate some random noise.
  • Apply Gaussian blur.
  • “Cut out” an asteroid outline.
  • Apply a circular gradient to add shadow.
  • Colourise.

Fonts

The main title and menu font is Trek Generation 1, which continues my theme of using Star Trek fonts in Shockwave games.

In this specific case, it was a surprise to me. For as long as I can remember I thought I’d used Copperplate Goth Bold (which does look similar) but when I actually explored the original source, I was wrong.

The longer text is Abadi MT Condensed Light.

Galaxia branding

Like Supremacy, some time after the initial release, I added the message “Brought to you by Galaxia”. Galaxia being another game I developed.

The future

Once DirPlayer has better support for my games, one of my goals is to recreate the Shocklive! site complete with both Supremacy and Q War. This would include a new, safer high score system to replace the original.

Screenshots

Supremacy - Shockwave game

Oliver Brown
— This upcoming video may not be available to view yet.

I started programming from a young age. One of the earliest programming projects I worked on that I was pleased with was a version of Risk called “Supremacy”.

Interacting with this video is done so under the Terms of Service of YouTube
View this video directly on YouTube

Shockwave was a technology created by Macromedia as a sort of companion/competitor/successor to the then ubiquitous Flash1.

Back in late 2000, I managed to get access to Macromedia Director1, the authoring software, and started playing around with it.

This was back when I was learning much of my programming from books (there was less available on the internet then). So I bought “Advanced Lingo for Games” by Gary Rosenzweig (Lingo being a bespoke programming language created just for Director).

Both Director and Advanced Lingo for Games are available on the Internet Archive now.

Supremacy is heavily based on the “Strategy Game” code sample included with that book. So much so, that the “Copyright © 2001 Oliver Brown” with no attribution makes me cringe a little now. So now is as good a time as any to thank Gary Rosenzweig for writing the book (and the code). I did eventually take it further, but that is for another post.

I made the game available on a website called “Shocklive!” on March 14, 2001 (and apparently released an update on March 18 with “no known bugs and better AI”).

Shocklive! as of May 17, 2001.

Today, the game has been submitted to the Flashpoint Archive and should be available soon.

Random trivia

Since it has been almost 25 years since I worked on the game, my memory has gaps. But I do still have the source code, so here are some things I can either remember or have worked out.

The name

Early in development I called it “Domination”, which is why the main file for the game is called dom.dcr.

Risk mechanics

It really is a bare bones version of Risk (mostly because it was designed as a programming tutorial and at best as a jumping off point to do more).

It has the original 42 countries from Risk, and uses the base rule: reinforcements equal to a third of your country count. It does not have continent bonuses however. This makes it much harder to snowball and as a result games tend to take longer (see the video).

It also does not use dice - every battle just gives attackers and defenders an even chance to win. This, combined with the fact that it also has no cards further lengthens games.

The computer player names

The default computer players are named after famous fictional AIs:

  • Deep Thought - The super computer from the Hitchhiker’s Guide to the Galaxy that determined the Answer to The Ultimate Question of Life, the Universe, and Everything was 42, and which went on to design an even more powerful computer, the Earth.
  • Orac - A sophisticated artificial intelligence from the British sci-fi TV series Blake’s 7.
  • Ziggy - The super hybrid computer from the sci-fi TV show Quantum Leap that runs Project Quantum Leap.
  • Zen - The master control computer of the Liberator, also from Blake’s 7.
  • Hal - The artificial intelligence and main antagonist in 2001: A Space Odyssey.
  • K-9 - The robot dog that was a companion in Doctor Who.

Title background

The background image is a Vietnamese girl holding an AK-47. I believe I sourced it from somewhere implying the girl was undergoing training to be part of some militia or military.

I still have the original copy and when I did a reverse image search I found it, with the description:

a Vietnamese high school girl practises taking aim with an AK-47 assault rifle during military training for students in Hanoi September 8 2000 high school and university students in communist ruled Vietnam take part in such training every year as part of a national defence programme"

Fonts

The main title font is Romulan Eagle. It sounds Star Trek based (which definitely makes sense with my interests at the time) but I honestly cannot remember anything about it. I have no idea where I found it. Possibly from the internet, possibly from a CD (CDs full of fonts were popular then).

The body font is Tahoma a standard Microsoft font which was apparently the standard screen font for Windows XP.

Also included in the project for some reason is Monaco, a font by Apple that was standard on Macs at the time. Which is a bit odd since I was using Windows at home and Acorn Computers at school.

Galaxia branding

Some time after the initial release, I added the message “Brought to you by Galaxia”. Galaxia is another game I developed (from which I got the online name I’ve been using ever since - GalaxiaGuy). I was working on a new version of Galaxia (which I tried a few times) when I first started this blog. The old Galaxia posts are still available.

Life on this blog

In fact, the game was available for a while directly on this blog. Sadly, this is no longer the case.

Screenshots

Some in game screenshots:

Opening in the project in Macromedia Director on a Windows XP VM:


  1. All the links say “Adobe”. It was Macromedia at the time. It shall live forever in my heart as “Macromedia”. ↩︎ ↩︎

Flashpoint Archive

Oliver Brown
— This upcoming video may not be available to view yet.

I’ve just found out about Flashpoint Archive, an application for playing old content created using Flash, as well as other obsolete browser technologies.

Interacting with this video is done so under the Terms of Service of YouTube
View this video directly on YouTube

The core functionality is provided by sandboxed versions of the plugins that run the content, a proxy server for games that need to believe they are run over the internet, and a launcher allowing you to browse and launch content - all wrapped up in a neat package.

And for the true archivists, there is a version that embeds all the content for download that, at the time of writing, is 2.28TB.

I’m interested in this for a couple of reasons.

Firstly, the preservation of history. I would like everything we create as a culture to remain available in some way (which is why I also support the Wayback Machine and the Internet Archive). I’m also of the right age that much of this was some of the most popular content available on the internet when I started using it.

But also, I myself have some stuff I’ve produced that is hard to access in modern browsers. Specifically, some Shockwave and Silverlight games.

So, for the near future I’m going to do what I can to get my games added to the archive.

Migrated another site from WordPress to Hugo and Azure Static Web Apps

Oliver Brown
— This upcoming video may not be available to view yet.

Some time ago I migrated my blog from WordPress (hosted on WordPress.com) to Hugo (hosted on Azure Static Web Apps). Over the past week I did the same for my wife’s blog.

The process went well. The Hugo site has pretty good docs for migrating to Hugo from various other platforms. The exact steps I took were:

  1. Export content from Wordpress.
  2. Generate Hugo content from the export using blog2md.
  3. Upload to GitHub.
  4. Create an Azure Static Web app (which as detailed before creates a build pipeline and deploys to an autogenerated Azure domain).
  5. Browse the site and fix any broken content.
  6. Add any custom functionality desired to the theme files.
  7. Update the domain to point at the Azure instance.

The new blog is available at www.luliriisi.me.uk (the original is still available at luliriisi.wordpress.com).

Sharing themes

That “custom functionality” is of course optional, and a potential rabbit hole depending on your exact needs. In the case of my wife’s blog, because she is a hand-knitting pattern designer I added some templating for sharing her patterns easily.

And, because the core theme is shared with this blog (and Games with Gravitas), that functionality is also available here - which is why I can easily add one of her patterns to this post.

Blazor Numbers Game

Oliver Brown
— This upcoming video may not be available to view yet.

Over the weekend I was playing around with Blazor and created a little number game based on part of a popular British TV show.

In the future this may expand in functionality as part of my exploration into Blazor.

You can try the number game full screen.

Blazor custom elements

Oliver Brown
— This upcoming video may not be available to view yet.

There is now a preview package for Blazor that allows creating custom elements.

Custom elements are part of the Web Components standards and are intended to be a way of defining tags that can be consumed in HTML and interoperate with each other.

The docs mostly focus on using them with Angular or React, but that isn’t why they are interesting to me.

The site for Tic-tac-toe Collection includes pages that show some information about specific game mode (for example four-player Tic-tac-toe misère rumble).

That content is rendered as a custom element (in this case <ttt-settings short-code="T_D4_S6x6_W3_T0_P0_M1_O1_F0"></ttt-settings>). Since the site is statically generated with no frontend framework, I wrote the element in vanilla JavaScript. Blazor support for custom elements means I could rewrite that component in C#.

Clarifying my position on ASP.net

Oliver Brown
— This upcoming video may not be available to view yet.

One of my most read (and most commented on) posts was the one claiming “ASP.NET sucks”, which only goes to show being a little offensive goes disappointingly far on the internet. Since it has now been five years since I posted that, I thought a quick follow-up was in order.

I stand by most of what I said my initial post, but with a little specificity. It’s not ASP.net that’s the problem but Webforms. Unfortunately at the time Webforms was all you ever saw. There are alternatives around today (and may have been back then but none were especially high profile and none were by Microsoft). These days of course Webforms are very much out of fashion. Following on from the success of Rails Microsoft realised that Webforms weren’t an idea that could keep up with modern web development. A quick glance at the ASP.net home page today shows four out of five articles talking solely about ASP.net MVC and one article talking about both MVC and Webforms (of course that will vary by day I but I doubt the result will be very different).

So taking into account a minor title change (ASP.net Webforms suck!) I’d say my original point stands.

Moved to Amazon EC2

Oliver Brown
— This upcoming video may not be available to view yet.

I’ve just moved the blog over to Amazon EC2 and so far everything seems to be going well. I’d been considering the move for a while and a new feature (well I’m not sure how new it is but I only just noticed it) is a new smaller instance type.

The virtual servers Amazon offer used to come in three sizes, small medium and large starting at $0.10*. Pretty quickly they added some bigger sizes (going all the way up to $2.00 per hour for quadruple extra large) as well as some more specialized types like GPU clusters. But it still meant the minimum price per month for a server always on was about $74/month which is expensive for simple web hosting. Now however, their new micro instances are available at a pretty cool $0.02/hour (about $15 a month). For the performance you’re likely to get it’s still probably not the most cost effective solution for plain web hosting, but for having complete access to a server with high availability (and the extra features hosting on Amazon’s infrastructure provides like being able to clone a whole server with one click) it’s pretty good. One final note is to remember that these numbers are not the final costs you’ll have to pay. You still pay for storage and data transfer which in my case look like they’ll be about an extra 10% extra.

Since then the price of the small instance has come down to $0.085/hour or about $63/month.

Open Graph protocol seems pretty cool

Oliver Brown
— This upcoming video may not be available to view yet.

A few days ago Facebook announced their new Open Graph Protocol.

It’s basically a way for people to interact with pages on the internet (in theory pages representing real world items, but it will be hard to moderate) in basically the same way as they do with existing Facebook pages. For a page to be eligible all you need to do is add a few meta tags to it specifying its  name and type (film, book, actor, product, game etc.). To actually do anything useful, you then add a Facebook “like” button. Once some people have liked it, it appears in their Facebook news feed like any other item (with the data you added in the meta tags).

One of the optional meta tags you can add specifies user IDs of Facebook users who can administrate the page. If you do, you can get access to the same sort of admin page you get with any traditional Facebook page. Conveniently I just developed a use for this sort of thing so I added support to my blog. A few edits to the theme and cunning use of Wordpress’s custom fields and now any page or post on my site can support Open Graph.

Currently the only support is on the Gravitas page.