Part 25: Mission Control
The Legend Of Avalon.I used to play a Dungeons And Dragons type game with Andrew Braybrook and some of his friends. I think it was based on Runequest with a few rules added by our dungeon master. We invented a character for my son Mark, called Maroc although he was too young to play. We used to play for hours just to get to a dungeon. This gave me the idea of trying to create a computer game that had the same sort of puzzles to solve plus lots of fighting action. I asked the dungeon master to write me an outline for the plot as if he were working out a dungeon for us to play. I then started to think about how I would get the feeling of exploring a dungeon into a Spectrum game. I had just finished Lunattack which had a landscape built out of sprites. I thought I would use the same technique to build rooms. The idea was to give the illusion of a whole room by drawing important bits like the doors and corners, then sketching a few features to complete the illusion. To give a 3d feel I added some arbitrary features at the front of the room to scroll at a faster rate in parallax. I decided on a completely novel presentation which I called a virtual theatre. I noticed that most films and TV programs show a view where the players are in a scene. When someone goes through a door the scene just switches to a new view. I realised with a combination of scrolling and flicking to a new view I could make several rooms appear as a continuous building complex.
I had to compress the data as much as possible to fit a huge scenario into the Spectrum. I studied sketches of rooms and decided on a binary system, which was wall section or door. The walls for a room were specified in left right order 8 sections of wall crammed in a byte. The colour ,wall detail, front detail all came from extracting bytes from the Spectrum ROM. I also had a door list detailing which door connected to which room and stored bits to say if it was locked, open closed etc.
I devised an event system to run the adventure sequences. The idea was each object could have several states. Each state could be changed to a following state by a certain trigger event. Object issued trigger events depending on their states. This simple system allowed me to chain together series of actions needed to complete the adventure. An object could effect several other objects but could only be affected by one trigger. So I made some triggers general, representing say a degree of force or magic. It as a bit of a restriction that an object had to change to the next state rather than a specified state and it took a bit of thinking for me to get used to how to chain and merge sequences like the roots of tree leading up to the trunk of the main adventure. My friend did not come up with a plot so I read some books about Avalon and Arthurian mythology and did it myself. I was a fan of Tolkien and loved the way he made Middle Earth real by inventing a history and glimpses of a prehistory. So I followed his example and made up the story of what had happened wrote the poem to give some background then proceeded to invent the main items for the adventure. I worked backwards from the main trunk. I wanted a handful of key items that were needed to complete the final encounter. These would be hidden in different sections to make it necessary to visit each main part of the dungeon. Then I worked out groups of subordinate tasks needed to get those main objects. Finally I devised individual streams of actions.
I had played a few text adventures ands started by testing my system by encoding a few sequences I was familiar with. They were easy to encode so I started thinking about how I could push it further by using the arcade nature of the game. This was unique, it had not been done before but I knew the reward would be a game that would have superb potential. I put some simple spells in the game and realised that it took time to select and fire a spell, or take the correct object to use. So by putting a danger that the player had to counter I could combine arcade action and adventure. I could slow the generation and approach and hit value of any danger to balance the game. I added some meanies and adjusted them so they were not too fast. They followed the player from room to room but got lost if you could get two rooms ahead. Suddenly the fact that it took time to fire a spell came into its own. I could feel a panic as a meanie plodded toward my player and a satisfaction if I managed to fire a spell in time. That is what you need for a compelling game; risk with reward for success, penalty for failure. I used similar timing for dangers protecting objects that needed collecting or transforming before collection.
I started off with very simple sequences and mechanics. As I got better at designing sequences I realised that the player would have the same learning curve. As long as I put simple stuff at the beginning I could ramp up the complexity as I got deeper into the game.
I put in a few twists such as the undead being able to see you when you were invisible but having to sniff you out when you are visible. This was inspired by the Ring Wraiths when Frodo puts on the ring. I tried to make each character class act differently . The Warriors Of Chaos for example were fearless at first, slow but they always headed straight for you. The goblins were faster, weaker and more indecisive and easy to scare. I kept a room fear count that went up if you killed enemies then gradually dissipated. The enemies were tested against it and could retreat or panic. I had never seen any of these things in a game. Even today enemies don't react too much to what is going on.
I can remember taking up the first experimental prototype to Hewson's. You had to use a bit of imagination as I only had a wizard graphic in it. Spells objects and enemies were all wizards. They could see I was on to something and were increasingly impressed by each version as the game matured. It is important to get positive feed back when you are taking risks. I had no game to compare mine with, I just had to make it work from scratch. I was really pleased with the result the game surpassed what I had expected to achieve.
Deepest Blue Progress.
It has been a long slog but I feel I am gradually getting there. Sometime coding goes really quickly. Then I am suspicious and wonder where the bugs are that I have not found. Sometimes progress seems to crawl. You track down a bug, find you need to change more than you would really want to. That upsets something else like trying to get the final side of a Rubix cube in place. Hopefully I am past that. This month I have been working on a few of the AI sequences and the matching player code.
Ages ago I was testing the boot sequence of factions populating the scenario. This needed nearly every aspect of the game to work. Two important parts were AI players to explore space sectors find warp points then navigate down them to find more warp points along with resources. I needed this to happen automatically but in a way that the player could interact with. Many months ago I penned a mission system where a player could look and choose a suitable mission. This months task was to get all these elements working together.
I had bases generating AI ships and a routine to allocate them a mission. I had a system of posting missions as features were found. For example if a warp point was found a pioneer mission was created. After a few crashes I realised I needed a more systematic way of testing all this code so I could see what was happening. I had limited the number of AI ships to 1 and attached the camera so it would follow the one AI ship so I could adjust its behaviour. I then realised that I could not follow the AI ships down warp holes, that code was player specific so I set about generalizing it. This would allow me to let the player watch his ships and take over if they wanted to as well as aiding debugging.
I thought I had the warp holes stitching together months ago but now and then a ship exited a warp hole into oblivion. The data is all generated on the fly instead of carefully prepared by hand so it was time to retrace the build routines to see what I had missed.
The next step was to get the player mission assignment working and integrate HUD displays to help the player navigate to a mission location and carry out the mission. All the parts were written nut needed to be tied together. I added a mission message text area so I could feed instructions to the player. I made sure the player mission data and AI data and procedures are identical, the idea being that you can switch a ship from player to automatic control or vice versa.
I coded the action routine so AI ships can collect raw materials from asteroid fields. Raw materials are mixed together and need purifying so I added a type of factory process to sort out the raw mixed resource. Now a ship can deliver mixed resource and the base sorts the wheat from the chaff. Precious stuff like gold will be imported to Earth in return for funds and other resources.
So what is left to do? I still need to debug the process of creating and improving bases. I have bases building base parts to be towed into position, I need to create the AI and player routines to position and join base parts. The other big action routine I need along with its player counterparts is for fleet actions. I have a squad formation process already but want to join multiple squads. I need HUD guidance for the player showing them formation position. After that most of the game code will be there and I can start thinking about sound and graphics. I am really looking forward to that. I have been experimenting in Reaper with various synthesizers to see if they can create in sci fi sound effects I want. At some point I need to update Direct X so I can use better shaders.
Programming Tips.One of the things about getting older is that it gets more difficult to remember things. However the experience of a lifetimes programming more than makes up for this. The key is to be systematic in the way you do things. I will organise each of my programs in exactly the same way. Then I know where to find things. I like to keep system code intended for more than one project in a separate library. I split this into a number of sub libraries each with a meaningful name that describes the content. Each library as made up of source modules that cover one area of functionality. Although I do not program in C++ for flexibility and speed each of these modules can be thought of as roughly dealing with one object. For example my network routines will be in a module called network.c , the main object pointer will always be called pNetwork and all the routines named NetworkSomething where something is usually a verb describing the action of the routine. I use the same names for general actions for example NetworkInit for initialisation , NetworkTerm for termination. I use standard shorthand on long names to save typing and increase readability. The idea is that I can deduce all the routine names rather than have to remember them.
I will sometimes have more than one object in a module if they are so closely related the depend on each other. For example my Node object is part of a network so it make sense for the code to be close. Then fewer modules open when I trace and the code is more likely to be in the same cache when called. When you have an object like Network that represents a collection of child objects you often need functions that can be thought of as belonging to either such as NetworkNodeAdd. With a good naming convention and choice of words the routines purpose should be obvious. I have seen people recommending you write an essay for each name, its much harder remembering more words. Imagine the extra typing and ways I could get the name wrong if I called it "AddABrandNewNodeToAnExistingNetwork". One simple reason for ordering the words the way I do is that the various dropdowns in Visual C display things in alphabetic order. If you have the main word first the routines are displayed in a much more organised fashion.
Working in patterns is really important in programming. Over the years you get used to the various ways a piece of code can catch you out. The more complex a piece of code is the more I want it exactly as I have done it before. Indeed I will cut and paste and then change a few names here and there to minimise bugs.
In some ways the whole of my program is one big pattern and will look like any other program I have written. I find the best way to write a new program is to start off with a copy of the last one.
Over the years I have generally dropped Hungarian and camel notations as the intellisense reveals all about a variable. I still like to clarify the strength of a C pointer with a pName for a pointer , ppName for a pointer to a pointer etc. The only time I use prefixes such as f for float is if I need multiple variables representing different types of the same value.