1 week to go

Still on schedule to release on Friday the 24th of April. Playtesting has been going well: I’m mostly fixing minor bugs and making tweaks at this point.

It’ll be good to get this new version out there: the new AI really makes a difference to the feel and quality of the game.

… and I don’t really have anything else to say at this point. Here, have a silly image macro:

gravitynope

Leave a comment

Revenge of the Cliff Zombies

Things are going well. We’re well ahead of schedule as far as playtesting goes (despite a few bugs, this has easily been one of the most stable releases so far, making it somewhat ironic that I put aside more time for playtesting this one than I have previously).

And on top of that, a last-minute feature has managed to sneak in!

Cliffs!

Cliffs!

Well, I say “new”: species 0.4.0 had cliffs, as you can see below. But they got removed for 0.5.0 as a result of rejiggering the biome system. And by “rejiggering” I mean creating.

Cliffs in 0.4.0! Disregard the giant rubber corpses.

Cliffs in 0.4.0. Disregard the giant rubber corpses.

The new cliffs are actually made from scratch, by abusing the biome system somewhat. I couldn’t resurrect the old normal-based cliffs. Sadly, necromancy is not real, and is also fake. Magical zombies are impossible to create.

Quite unlike scientific zombies, which we seem to accidentally create every few weeks! That’s actually why I’m having May post this from inside the barricaded control center of the Orbital EMP Cannon while my minions fight off the ravenous corpses of their former colleagues outside. If you listen carefully you can hear the fight in the background.

“Die you bastards, die!”
“Oh god, is that Dave?”
[BLAM]
“Not anymore it isn’t.”

I won’t go into the detail. It’s a long story. Suffice it to say, it’s totally not my fault.

“This is totally the bosses fault!”

Anyway, they’re not perfect. The cliffs that is, not the zombies. They don’t affect what tree’s grow in that location, creature’s can still graze on the biome beneath them, and they don’t actually affect creature’s movement in any way, buuuuut…

Well, they look cool. Isn’t that enough reason?

130731233025176099

 

Cheers from zombie-infested space!
Qu

“Remind me again how lucky we are to work in a space station! I KEEP FORGETTING!”

1 Comment

Another Bug Post

I was originally going to post this as a forum post, because it’s basically just an enormous wall-o-text, but I decided what the hell you only live once. And then you die. Like everyone else. So before you die, you might as well waste a few minutes you can never get back reading this wall-o-text.

Playtesting 0.8.0 has revealed some bugs: thankfully not major, crash-inducing ones. They’re mostly problems with longer-term simulations.

I tried tracking down the two major ones this morning (over-reliance on carnivory and species-count becoming desynchonised from the creatures) and failed miserably. Couldn’t reproduce the latter at all, and the former is just plain odd.

It doesn’t seem to be an energy leak bug: creature’s can’t survive if you kill *all* the plant matter, which is a good sign. But they *can* survive extraordinarily well on a very small amount of food.

I think I’ve got an idea, though: I’m starting to think this might be a recycling issue related to the way biomass is handled.

When a creature eats a plant, the amount of energy it consumes is constant, but then other factors kick in (the creature’s diet, the plants efficiency, global efficiency if it worked properly, etc) to reduce the amount of usable energy that is actually added to the energy bar.

The unusable energy is added to the creature’s biomass value, which is little more than a storage space, keeping track of the energy that the creature has consumed during it’s lifetime. When it dies, biomass (along with any leftover health or energy) becomes delicious meat.

Meat is a more efficient food source. You might be able to see where I’m going with this.

Whether a herbivore or a carnivore eats the plant, the same amount of energy is introduced to the population. Even a near-carnivore will eat plants in an emergency, and even though the individual might not be able to make use of the biomass it picks up, it’s pure-carnivore siblings can when it dies. So the population ends up relying on these omnivorous mutants to bring energy into the system. And of course, unlike a herbivorous population, when each of these carnivores dies they can be fed on in turn by their siblings, resulting in an incredibly efficient survival strategy that requires far less energy input overall. It’s quite elegant, actually.

Alright, that’s enough admiring the enemy, what can we do about it (assuming that huge steaming pile of extrapolation was at all accurate)?

My first inclination is to reduce the meat efficiency. But that doesn’t actually stop the energy from being introduced to the population: it just means it has to go through more creatures to be usable. Plus it makes carnivory less likely. The problem isn’t carnivory so much as so efficiently recycling the incoming energy.

The large total plant energy is what caused the problem in the first place, so I could reduce that. I’d need to increase the efficiency of herbivory to compensate: the end result would be that eating plants would add substantially less biomass.

Or efficiency could actually influence the total amount of energy that’s added: rather than having a constant increase and divvying it up between biomass and energy. But functionally, that’s pretty much the same as reducing planet energy content as mentioned above, since they’re the things with the low efficiency.

Or… well, I could finally accept the fact that the biomass value isn’t hammerspace and rework it somewhat.

Honestly, I’ve been treating biomass wrong for a long time. It was originally a way to ensure the conservation of energy, but a potential storage of infinite meat on every creature is quite frankly rediculous and unrealistic.

So, how to fix?

In real life, edible biomass *isn’t* simply unused energy: that only applies to fat stores, and those are just a tiny fraction of the creature’s edible meatiness. It’s structural: muscles, flesh, etc. It’s correlated with mass. And unused or unusable food isn’t stored forever as fat stores, either: it’s expelled.

So, the sensible way to fix this might actually be a deliberately introduced energy leak. Sort of like Decay, only happening while creatures are alive. It’d work something like this:

Creatures gain biomass normally up to a set point (perhaps their childhoodCost (to represent structural biomass) plus a percentage of their mass (fat stores)), after which it leaks out over time (possibly even providing a minor energy boost as it does so). It would have to leak exponentially faster the higher it went, to prevent a creature capable of rapid consumption from outpacing the energy leak indefinately simply by gathering food.

This would put a limit on the amount of meat a single creature could provide, meaning that carnivores eating a particularly bountiful meat pile would get a much smaller meal: enough to produce one or two children, rather than dozens.

Hopefully, that should put a spanner in the works of the current dominant survival strategy.

We’ll see…

Qu

3 Comments

Happy Easter: Let the playtesting commence!

It’s the most occult time of year again!

Religious leaders rise from the grave! Otherwise kind parents force their children to hunt in the grass for their food! Small mammals in the family Leporidae give birth to sterile brown eggs for occult reasons!

And evil game developers laugh manically while unleashing swarms of horrifying bugs on innocent playtesters!

Okay, that’s not a tradition, but maybe it should be? I dunno.

Anyway, if you wish to be consumed by my genetically modified insects and/or playtest the latest (unstable and full of bugs) version of Species, come join us in the forums where 0.8.0 has just entered the community playtesting stage prior to the release date on the 24th April!

That’s only 3 weeks away!

Prior warning: you may have to brave the dark, malevolent aura that drives the strongest willed men to gibbering madness and actually join the forums to see the playtesting board. Don’t worry though, despite the aura it’s not actual madness. It’s more like substitute madness. “I Can’t Believe It’s Not Madness”.

1 Comment

Mouse Lag

In 0.7.0, the game draws the custom mouse cursor. The mechanism it does this by is very simple: every frame, retrieve mouse position and draw the cursor sprite.

This is the simplest possible way to draw a mouse cursor in a game environment, and it has two problems (well, technically two aspects of the same problem, but I’m separating them for this post):

 • Latency: you don’t see where the cursor is, but rather where it *was* when the last frame was drawn. When the game’s running at it’s standard 30fps, this can cause the mouse to feel a little bit sluggish, but not so much you can consciously notice it (it’s only consciously noticeable if you turn the windows mouse cursor on, at which point you’ll notice that the cursor doesn’t quite keep up).

If we were making a twitch game this sluggishness might be a problem, but for a slow-paced game like Species it’s nothing major.

 • Lag. It means the mouse is susceptible to low frame rates. When there’s thousands of creatures wandering about and “every frame” means twice every few seconds, this causes it to become very difficult to control the game cursor. Factor in the latency on top of not being able to see where you’ve moved the mouse, and the game becomes practically unplayable with mouse control.

 

Artist's Rendition

Artist’s Rendition

 

This is far more a problem: Species is a game that needs to push the boundaries of what the computer running it is capable of. Having a lag-sensitive mouse is a big issue.

There’s actually an easy solution to this: use the windows cursor. It’s drawn by the operating system, not the game, so is immune to the game’s lag.

Except, of course, I want to use my custom cursor.

Don’t give me that look, the custom cursor is important. It is my right, nay duty as a game developer to hijack your mouse and make it into some ridiculously over-sized and self-indulgent custom sprite.

 

hoogeCursorMenu

(totally to scale)

 

So to achieve that, I had to redesign the cursor display function.

Describing that would be a big pile of steaming boring, so I’ll just skip to the end: rather than hiding the cursor and drawing my own, Species now instructs the windows cursor to display as a custom *.png sprite, using a similar (if slightly more complex) system to the one other programs use to display the wait cursor.

The practical upshot of this? Mouse lag immunity! The mouse now runs smoothly and without latency even when the game is drawing at slideshow speeds.

It’s not a complete fix: the UI itself is still linked to game performance, so buttons remain fairly unresponsive. I do have some idea’s on that front, and for a game like Species they might be worth exploring at a later date (I believe it should be possible, theoretically at least, to get the UI buttons and controls drawing at a consistent 30fps even if the 3d world is lagging).

But regardless of what we may or may not do in the future, 0.8.0’s mouse control is a boatload smoother and more responsive than what we had previously. Which is, by my standards, a Win.

Cheers,
Qu

,

1 Comment

Anatomy of a bug – Loading Death

Hello minions,

Time for another “Anatomy of a bug” post. I’ll try not to get the lymph all over the place, but no promises. Vivisection is a messy business!

A recent bug fix involved a save/load problem: when you load a game, about 10-20% of the creatures would die, but *only* if the game had been running for a few minutes. This was something I hadn’t previously noticed: I didn’t really pay attention to the number of creatures, and they just looked like ordinary corpses after the load, so there was nothing to raise my suspicion.

With the new red-mist effect when creatures die, however, it was quite obvious that a large number of creatures were dying at the exact moment the game was loaded. Nothing quite says “you have a problem” like a couple dozen perfectly-synchronised bloodsplosions.

Liberties may have been taken.

Liberties may have been taken with this rendition of the event.

My first assumption was that this was somehow related to the AI changes: I’d implemented other potential culprits since 0.7.0, things like changes to how growth cost is evaluated and how temperature damage is applied, but since I’d just come off of implementing save/load functions for the creatures new brain, I assumed it was that the AI was being initialised badly. That would also fit the symptoms: 10-20% of creatures would be roughly the amount doing specific, low priority actions (the vast majority of them spend their time feeding), and they always start the game by seeking food which would explain why it took a few minutes to manifest.

But after adding a variety of reset and revaluate functions to completely refersh the behaviour tree, creatures were still dying during load. At that point I had to admit that the AI probably wasn’t the cause.

The next thing to check was that the Save/Load function itself wasn’t broken. That seemed unlikely: typo’s in the save/load routine usually either crash the game or result in *very* noticable problems. Still, maybe I was loading energy as health or something, so it needed to be tested.

I did that by saving the game with exactly 500 creatures, then loading it. Sure enough, when it comes in, there are 428 creatures.

Except… with the power of code, I can put a breakpoint in and study the game’s state at the *exact* moment it leaves the load routine. And at that moment, there are 500 creature’s. The killing blow isn’t actually being delivered until after the game is loaded, in the single update frame between when Loading finishes and the game is actually drawn to the screen.

And that thought, thinking of it as a “killing blow”, caused me to notice something something interesting. After the load, a large number of creatures were Fleeing Randomly. They’d noticed something.

Flee Randomly is actually a very specific behavior: it only occurs when Fear increases with no discernable source. Since fear is only raised under very specific circumstances, we can narrow it down further: they can’t have recieved a threatening ping (since that would give them a source), so they must have taken a significant amount of damage in a single frame.

They weren’t just fleeing in terror from some nebulous threat. They’d been attacked. Eeeenteresting.


Wait, did I say interesting? I meant terrifying. Something is in my game, causing pain and death in the single-frame of darkness between loading and playing, and I don’t know what it is.

After checking that the 8 seals on [REDACTED] were indeed still intact, I started looking for other sources of pain, misery and death in the Species universe. The first was prompted by a strangely beautiful observation: a few particles of snow falling in the desert.

Aha! The temperature map is being initialised one frame too late, hence the snow!

That would mean that for a single frame creatures are subjected to absolute-zero temperature. Or, y’know, -17 degrees Celsius, which is absolute zero in the species universe (FOR REASONS!). That would do some damage: not much, but enough to knock off some of the near-death creatures and scare the rest. Problem solved, and as a bonus we don’t have some wrathful eldritch abomination loose in the game’s universe.

So I went ahead and fixed the temperature map issue.

It didn’t work. The creatures still died.


Welp I guess it really is an elder god. Time to bury your computer, hide in your weird survivalist neighbours anti-zombie bomb shelter and await death or insanity, whichever comes first.

Or we could keep looking for a rational explanation, but where’s the fun in that?

The current UpdatableAttribute system has a neat feature where it records the cause of all changes to an attribute, called “delta’s”. So you can, in theory at least, see what type of health change the delta was: Attack Damage, Temperature, Healing, Pregnancy: you get the idea.

Of course nothing is ever so simple: there are 20-something delta’s split across 4 updatable attributes for 500+ creatures 30 times a second. Getting *specific* information out of it is difficult. Luckily, we know we’re dealing with something unusual here: a large negative spike across many creatures in a single frame. Those are rare, especially now that pregnancy happens over time.

So, some conditional breakpoints and a few false positives later, and we had a culprit:

Aha!

Aha!

ChildhoodGrowth! They’re being attacked by the cost they pay as children to grow to adulthood.

But why?


An answer gives way to more questions. Simply knowing it’s ChildhoodGrowth that is damaging them doesn’t really help: we need to know *why* ChildhoodGrowth is damaging them. What’s wrong with it’s calculation that conflicts with the loading routine?

Here’s the entirety of the code for calculating this amount of growth cost that needs to be paid this from:

if(isChild) 
{
    //Calculate energy cost for growth during childhood
    float energythatShouldHaveBeenSpent = phenotype.childhoodCost.Value * (age / (phenotype.childhoodLength));
    float thisFrameCost = energythatShouldHaveBeenSpent - energySpentOnChildHood;

    energySpentOnChildHood += thisFrameCost;
    health.QueueChange(HealthDeltaType.ChildhoodGrowth, -thisFrameCost);
}

As you can see, it calculates the total amount that needs to be spent (childhoodCost), multiplies it by the ratio between age and childhoodLength, subtracts any energy that has been spent previously, and then applies the result.

Can you see the bug?

No? I couldn’t either, so I created a number of debug variables, to test what the values of everything were before and after saving. The results were as follows:

savedChildhoodCost = 28                 : ChildhoodCost = 28
savedAge = 166                          : age = 166
savedChildHoodLength = 72               : ChildhoodLength = 72
savedEnergythatShouldHaveBeenSpent = 52 : energythatShouldHaveBeenSpent = 28    : BZZZZZT!

Ah! So the difference between what was saved before the load, and what was spent after, lies in energythatShouldHaveBeenSpent, which is…

… calculated from the other three variables. Which are the same before and after the load. So the values should be exactly the same.

What.

Can you see the bug now?

if(isChild) 
{
    //Calculate energy cost for growth during childhood
    float energythatShouldHaveBeenSpent = phenotype.childhoodCost.Value * (age / (phenotype.childhoodLength));
    float thisFrameCost = energythatShouldHaveBeenSpent - energySpentOnChildHood;

    savedEnergythatShouldHaveBeenSpent = energythatShouldHaveBeenSpent; 
            //Note: savedChildhoodCost, savedAge, and savedChildhoodLength
            //are all saved from their actual values at the moment of save.
            //energythatShouldHaveBeenSpent is a local variable, so it has 
            //to be saved here.

energySpentOnChildHood += thisFrameCost;
health.QueueChange(HealthDeltaType.ChildhoodGrowth, -thisFrameCost);
}

The same 3 values being combined in the same way can’t result in a different value. It doesn’t work that way. I must be
missing something. That saved value must have been generated at a different point in time or something…

… wait a sec.

Back up for a bit. I missed something important back here.

savedChildhoodCost = 28                 : childhoodCost = 28
savedAge = 166                          : age = 166
savedChildhoodLength = 72               : childhoodLength = 72
savedEnergythatShouldHaveBeenSpent = 52 : energythatShouldHaveBeenSpent = 28    : BZZZZZT!

There it is. There’s the bug. Can you see it? Look closely.

age = 166
childhoodLength = 72

This creature is not a child.

Why is an adult creature paying the childhood growth cost?


Suddenly everything begins to fall into place.

Immediately after a load, all creatures are initialised with isChild set to true. Their saved age will cause them to *become* adults next frame, but for that first frame, they will pay the outstanding childhood growth cost.

And that outstanding cost is calculated by multiplying the amount it takes to grow out of childhood by their *age*. So if they’ve lived as an adult for any amount of time, that’s quite a lot of growth cost they haven’t had to pay (by virtue of being fully grown), that they suddenly have to pay all at once in a single frame.

And they would have gotten away with dying horribly too, if it wasn’t for us meddling kids.

Thankfully, after all that, it’s an easy solution: just make sure “IsChild” is saved and loaded, right?

Well, not quite. Creature’s are initialised as children, they need to call the GrowToAdulthood method, or they’ll suffer permanent dwarfism. I could call this method manually, but it’s clumsy and inelegant. Plus it doesn’t really address the GrowthCost debt, which keeps accumulating in the background and only takes one wrong line of code to show up and wreck things.

So, a slightly more sideways solution is to make sure EnergythatShouldHaveBeenSpent maxes out at ChildhoodCost. No more excess childhood growth debt, and I can keep initialising creatures with high age values and letting their normal methods take care of growing them to adulthood.

if(isChild) 
{
    //Calculate energy cost for growth during childhood
    float energythatShouldHaveBeenSpent = phenotype.childhoodCost.Value * MathHelper.Min((age / (phenotype.childhoodLength), 1.0));
    float thisFrameCost = energythatShouldHaveBeenSpent - energySpentOnChildHood;

    energySpentOnChildHood += thisFrameCost;
    health.QueueChange(HealthDeltaType.ChildhoodGrowth, -thisFrameCost);
}

Cheers,
Bugkiller Qu.

7 Comments

0.8.0 Release Date

On the 27th of May 2011, I started this blog and detonated an antimatter bomb in the core of the planet. Nobody particularly noticed or cared on either front, but I totally did those things. Both of them.

Over the course of the next year, I somehow picked up a few minions. I mean readers. Okay no I mean minions. Perhaps they were entertained by my weird shenanigans, or interested in the slowly developing Species, (which at the time looked something like this):

Horrible! And pink. So very pink…

To my dear minions: thank you. I wouldn’t be where I am today without you. You are the ones who released bio-engineered photosynthetic parasites into the upper atmosphere to reflect infrared light. You are the ones who convinced the Australian government the great barrier reef was the maw of a planet consuming abomination that needs to be destroyed. You are the one’s who built me an orbital weapons platform on which to lounge arrogantly while ordering you to do tedious evil things in the name of the greater good of tedious evil things I want to do! I know some people will say you did it just to get me off the planet, but I know better! That space station? That is your achievement! And I will forever treasure the memory of all the brave minions I had to throw out the airlock because they pissed me off.

So anyway, one year after I started the blog, on the 27th of May 2012, I released Species ALRE 0.4.0.

It was terrible. No seriously, it was a godawful alpha release. I actually feel kinda sorry for everyone who played it. I should probably apologies for that. You’re welcome! You lucky, lucky bastards.

And then a couple of years went by and I didn’t do anything special for the 27th of May 2013/2014 because the vagaries of time have no sway over a being such as myself. Also I forgot. But mainly the vagaries thing.

But we released Dynamic Biomes in 0.5.0, Rovers in 0.6.0, and Body Physics in 0.7.0 in the meantime, so I guess it wasn’t a total loss.

And then, as we once again approach the prophesied date of 27 May, 2015, Quasar looked upon the Artificial Intelligence in 0.8.0 he had wrought…

130709607552385870

… and spake unto the nearest minion…

“That’s like 2 months away! I’m not waiting that friggin’ long! Something something vagaries!”


And so it was decided that 0.8.0 would be released on the 24th April, 2015.


Well this was a weird post. Feels good to write something ridiculous again. I think I’ll do more of these…

10 Comments

Follow

Get every new post delivered to your Inbox.

Join 485 other followers