Part 19 How to get from Here To Eternity.
Graftgold Memories.I read on Twitter that Gary Foreman signed a letter to convert Ranarama to the C64 30 years ago. Gary worked from home at first just contracted for the one conversion. The results impressed Andrew and I so when Graftgold had the opportunity to expand Gary was offered an in house job. Financed by Telecomsoft, Graftgold moved to its first office in Witham. It was a couple of rooms above a greengrocers, now a flower shop opposite the George public house. The rooms had exposed oak beams and with a bit of paint and a new carpet it was quite cosy. The entrance was via a rear metal set of stairs , we had fun trying to get to Iron Man arcade game up the stairs. We had to dismantle it as much as possible. Later on we moved to a larger room at the other end of the building and the office by the stairs was converted into a vegetable store that we had to pass through to get to our office. The floor of the building was sloped in places where the oak frame had distorted and the front of the building was lower than the back. There was a burger shop downstairs and the aroma of burger and chips used to float through the open window in summer making us feel very hungry.
|\\The original team outside the old office.: Daivid OConnor,Gary Foreman,Dominic Robinson,me,John Cummings and Andrew Braybrook,|
It was great fun setting up the new office. I ordered new L shaped desks for everyone and PC compatibles with twin floppies and Hercules monitors. Hard drives were small and expensive, our first one was on a big Atari used for 16 bit development. We ordered a PDS development system for each programmer but its floppy disk routines did not work. They gave us updated software after a while. We had agreed to finish a Flying Shark Spectrum version in 6 weeks so we were really up against it for a while. It was a relief when we could finally save our work using PDS. It was a step forward having a proper development system that could assemble then down load and debug from PC to Spectrum. We eventually put the Spectrum/C64 PDS boot software on a cartridge to eliminate tape loading.
Deepest Blue Progress.
Long range scan.
When players explore a new sector I needed a way to help them find things rather than just roaming around at random. I decided to add a long range scanner that looked a bit like a submarine sonor or old fashioned radar. I decided to put it as a head up display sweeping the space in a cone in front of the players ship. As the scan goes round blips can be representing features a long way ahead of the players ship. This allows players to locate things without knowing what they are until they get closer.
Semi Transparent Graphics
I needed a semi transparent graphic and realised I needed an easy way of generating an alpha channel from the rgb values in my graphics utility. This meant I could simply make darker areas of a sprite more transparent. I then drew a rough test sprite for the scan that was like a line from the centre of the scanner that faded out as if it was leaving a glow on the screen. I could use the same principle to make some of the other HUD displays semi transparent. I have radar marker lines that were meant to fade at the ends and now these worked a treat.
I use a lot of lines to generate HUD displays . Their colour is defined by texture coordinates, which allows me to make textured or animated of faded lines. I imported a RGB square graphic so I had lots of fades to choose from. My HUD was just using random textures and this simple change immediately looked a lot better.
Last month I was deeply embroiled in rethinking the design so I could code the AI routines to control the game world. I made slow headway and slowly came to realise I needed to refactor some of the main game code to simplify the relationships between structures. This came to a head when I started adding AI path finding routines. I wanted the routes in the game to be discoverable by players and shared by members of an alliance. That meant that each alliance needed its own view of the game world. Its ships could only used paths that it new about.
This affected my core network routines that had no facility to hide and reveal parts of the network.
As space is so big I had a 3 tiered network with system jumps, sector jumps and local paths. Nodes in each of the networks were attached to matching objects representing a star system, a sector within a system and a feature within a sector. This was all rather complicated.
"I then had a brainwave"
I was working on a method of marking routes between nodes by recording the best node to get to from A to B and the distance. It was like one of those triangular mileage charts. I then had a brainwave. Instead of having a complicated Network organisation with nodes linked to each other via link objects I could just have the route triangle. Nodes directly connected just list each other as the next best node. It meant I could dispense with a whole load of structures. Effectively the system /sector or Feature object became the node instead of having to have a pointer to a node structure.
I sketched out the new organisation and finally took the plunge. It was quite a far reaching change with a large impact on the existing code. I wrote the new network routines first trying to keep them compatible but eventually decided I may as well simplify the interface as some functions became redundant. Its not a good idea to change interfaces with existing code unless you have a really good reason. Working by myself meant that the impact was minimised but would need a big bang approach to implement in the game. It took over a week to code and clean compile, but code was significantly simplified leaving me with a good feeling that I had made the right choice.
Multiple linked lists and pointer lists
While I was in the mood for change I decided to simplify my organisation between main game structures. My save and load of data catered for networks, pointer lists and heirachies of linked lists.
It could only have one linked list and pointer list in any one structure. If an object needed more lists it had to have a pointer to an external list object. This added an extra level of addressing. So I added the facility of having multiple linked lists and pointer lists, a tricky change. Each list needed to know which sort of sub object it contained so it could automatically find them and add them to the correct list.
So the next step is to get all this debugged so I can see the game running again. Then I can debug my boot code for the star systems population. I put in five home factions representing power blocs on Earth and a few alien nations. They each should have a home base and a space ship factory. I have coded a crate pioneer routine which is the first part of the AI. The pioneers will find warp gates and explore new sectors, claiming resources for their alliances. When this is working I will code the base creation process so the alliances can mine and process resources.
I have given some tips about debugging before but here are some more ideas.
I like to get to the debugging stage. I have done so much in my programming career that I can almost do it on remote so its like a downhill stage in development of new code.
Debugging actually starts way before I pen any code. I like to consider how I am going to get a new routine working especially if its complicated.
I like to include identification data in each structure such as a short name so it is easy to identify the data when looking at it with the debugger. I sometimes will put an if debug around this data so it is eliminated in a final build, if it is in a memory sensitive structure. It is really useful to be able to see which object you are dealing with when you have hundreds of similar objects.
For objects that are complicated such as my networks I like to write a simple test bed that can try each routine in a controlled and systematic manner. For my network for example I would create a network, add some nodes connect some, find the best routes navigate between them, add more connections, recalculate the best routes, tear the system down. As well as check the things that should work I like to test the things that shouldn't. For example trying to navigate between unconnected nodes or trying to remove a node twice. Routines should fail in a desired manner. Then when other things go wrong your routines do not compound problems and just tell you something is wrong.
I like to trace all code, it forces you to read it in the sequence the computer executes the code. I often spot things that are not quite right while doing that before they cause a problem. Its faster to find an issue early on rather than responding to a crash. I look for dangerous code that has a chance of failing catastrophically if there is bad data or a bug. I add safety checks or change method to increase the safety. Simple things like Nulling out a freed pointer can prevent future errors
I try to catch errors at the start of each routine by checking the input values to be sensible. These checks would be removed in the live version.
I like to keep each routine as standalone as possible so it is a separate entity that can be tested on its own or with minimal code support. Then I can call them at the start of the program to quickly get to the code under test.
For complex sets of structures I will write a Check routine that will write a report listing all the objects and important fields and the relationships between them.
As a last resort while debugging I add lines to write values to a report. It is useful to pen a DEBUG macro that can easily write a line to a file if in debug node.
I like to use the memory display to display a dump of a structure especially an iteration of structures, then watch as the memory changes as I trace. Any memory copying or changing operation is best looked at in this way to check limits and content.