Alright, guys, I suppose I owe you an apology. I’ve been quiet these last few weeks because my ability to concentrate on one thing for more than 10 minutes at a time has been vanishing recently. This has lead to development work actually stopping for the first time in a few years.
I blame a cabal of reality TV stars, climate denialists, space nazi’s, meddling kids and the reptile people from the earth’s core who currently control the Australian government.
I’m trying to work through this, and I will get back to consistant development on Species as soon as I stop being useless and/or lazy and/or my mindspace is properly aligned with the non-euclidian geometry of the outerworlds, allowing my mind to serve as an anchor for MORGAZULOTH THE CONSUMER. As you can see I’m unable to even finish a sentence sensibly right now, but I think I’m past the worst of it.
In the mean time, here’s what I managed before Tony Abbot started seeding my breakfast cereal with mind control spores.
Fences are now established as a complete game feature, useful for splitting populations, only requiring UI integration and some cleanup to stop creatures and AI-controlled rovers from endlessly attempting to move through them. Also, you can make race courses with them, which serves to remind us just how hilariously impossible the rovers are to drive. Oh, and the fence collision doesn’t extend above the fence, so yes, you can jump them.
Physics work is accellerating a little: I’m attempting to visualise the forces at work in the skelington. It’s costing a moderate percentage of my sanity points to match the forces locations up with the creature’s actual body plan (not as simple as one might expect, thanks to code that was poorly written the first time through), but I’m getting some clean-up done while I’m in there.
Although the debug elements are starting to clutter the screen a little…
The fences look a bit like fences now.
Started adding basic creature-to-fence collision code, and the creatures seem to be deliberately helping me test it. They love fences! And they seem to have this trick where they ram themselves up against the wire and then birth a creature on the other side.
I think that’s the plot of Jurassic Park 5 (co-directed by Ridley Scott and Michael Bay).
This time it wasn’t entirely unexpected: our old webhosting provider went out of business. I was planning to have a smooth transition to a new provider in the next week, but apparently someone shut the server down early. So much for that plan.
I’m going over the backups: I have a local copy of the site files themselves, but it looks like the forum databases are out of date. This is frustrating because I went to a lot of effort to set up daily backups, but it looks like the code on my local machine hasn’t been running properly. Lesson learned: test everything twice!
Will try to keep everyone updated here on the blog.
(Edit) Good news! The hosting company got the data center to agree to unlock the server, so no data will be lost. I’m arranging a new hosting provider now.
I forgot to charge my laptop yesterday so used the forced break to practice my sketching, but I’m back in it today and development continues.
The Mutation Map tool now has the ability to view and edit both the overall map and the individual stats of each head. It can also do the same for Feet, and I’m working on getting the remaining mutation maps (Limbs, Coverings, Colour Patterns, Feature Models and Feature Textures) into the tool. Hope to be done by the end of the week and moving on to other things, though that may be a bit optimistic.
Also took some time to begin taking my Stat encapsulation to the next level. Currently we have 6 types of Stat:
- GeneticStats encapsulate a mutation rate, plus mutate, randomise and blank routines, for every gene.
- FloatingGeneticStat: A hereditable decimal number, like “torsoWidth” or “headSize”. Encapsulates an upper limit and lower limit in addition to the mutation rate.
- DiscreetGeneticStat: A hereditable integer number, like “numberOfFeatures”. Just encapsulates the mutation rate.
- BooleanGeneticStat: A hereditable yes/no value, like “hasTail” or “hasNeck”. Just the mutation rate again.
- MappedGeneticStat: A stat with a mutation map, like “headType” or “bodyCovering”. Encapsulates the entire mutation map structure.
- BasalStat: a non-hereditable stat which is imported from an external file, linked to a MappedGeneticStat. Like how HeadType determines Diet, or how LimbTipType determines BaseLimbDamage. These stats are rarely used directly: usually, they feed into formulas to determine other stats. (diet is an exception)
- UpdatableAttribute: a type of Stat I have encapsulated but haven’t derived from IStat yet: these are things like Health, Energy and Biomass, which change over the course of a creature’s life. Encapsulates a list of “Deltas”, making it possible to track the source of changes to these stats (you can see these deltas listed out on the energy page in creature details).
There’s only one major type of stat still missing, at least on a per-creature level:
- DerivedStat: Any stat which calculates itself from other stats. For instance, Speed takes into account LimbSize, LimbBaseSpeed, TorsoWidth, TorsoRotation, LimbTipBaseSpeed, and so on. DerivedStat will encapsulate all these stats, plus the formula used to combine them.
The method I’m using to encapsulate the formula uses something I haven’t spent much time with in the past: delegates. I’m storing it the entire formula as a delegate inside the DerivedStat instance. This means I get to define the formula in StatData, but still use the built-in accessors of the objects, so I get the same intellisense benefits and high performance as if I was defining the calculation over in Phenotype.
The result looks like this:
"Mass", //Printable Name
"Determines how much stuff there is in the thing", //Printable Description
delegate(Genome genome, BodyPlan bodyPlan, Phenotype phenotype) //boring code stuff
return bodyplan.Volume * genome.Skin.Density; //Formula
The relevant bit is the second-last line: that’s the only place that formula needs to be defined. All I have to do later is call Initialise, and the DerivedStat takes care of calculating itself on behalf of it’s parent creature, pulling other stats in and combining them, as well as throwing errors if stats haven’t been correctly initialised.
Yes yes, making with the boring and the code and the words and the stuff, so what? Why do we care?
Here’s why we care: every calculation, limit and mutation rate from the raw genes to attributes like speed and stamina is now stored in StatData. This one file is becoming the spinal column of a lot of the simulation’s behaviour, so tweaking mutation rates, adding limits, changing names and descriptions, and now adjusting stat formula will all be possible simply by changing the input data here.
And I intend to expose that input data to modding.
Cue the maniacal laughter,
I really should have done this sooner.
It’s a graphical representation of the head type mutation map. Took me half a week to make, and it’s already showing me a number of interesting defects in the map. There’s one in the screenshot above: see if you can spot it.
If you’re wondering where that particular head should be, you can see it’s originally intended location here:
The reason for these defects is simple: so far I’ve had to build this entire map textually, with nothing to go on but the names. That’s the “Gen3C”, “Gen4CaA” and “Gen5CcAAA”. The abstract naming scheme was designed to make it easier to connect them up without being able to see them, and without making mistakes. Guess it didn’t work as well as I’d hoped.
This tool should fix that little problem by allowing me to see what I’m doing. In fact, I’m considering taking it a step further and allowing me to edit the map directly from this window.
Also, I know 0.6.1 had a smaller Content to Time-Spent ratio than previous updates. This was because I spent half my time on cleanup, rather than new features. I justified this by telling myself it would make development faster in the long run. Turns out I was right! This simple tool would have taken at least a few weeks without being able to reuse the DrawableHead class, and the fancy MutationMap classes I made for the Mod Maker all the way back in 0.4.1.