The signs were there plain and clear from the very beginning, as they always are. Signs of trouble, of curse. Of what else could signs ever be? It really is only insanity, misery and ineptitude that scar the fabric of the world so much as to leave signs at all, after all. Sanity, happiness and competence work basically all too well *with* reality for one to notice – or to otherwise need to notice – much at all.
The signs started in this case with the dubious names linked to significant parts of the project1 The magic numbers scattered all through the code like so many stinky droppings. The inexistent design documents. The outdated and incomplete documentation overall. The crashes. The total lack of automated tests despite the huge code base. The 20-or-more-levels deep errors thrown occasionally at the unsuspecting user. The arbitrary and abusive limits imposed on users – thou shall not have more than 100 inventory slots or thou shall not store containers inside containers. The sheer size of it to start with – the unjustified and unjustifiable2 tons of lines of code piled deep and piled high in a tangle that actively resists sanity already. Such as this tiny bit of mess, part of a whole larger mess of the same kind:
Still, I naively thought it to be more or less what it claimed to be – a piece of *working* code written perhaps by monkeys as the best of humans are anyway, but at least by knowledgeable monkeys as it were. Still written through pushing keys and pressing buttons of course, but with movements directed by some actual thought and inner workings of a brain that has grasped the more abstract concept of a banana and that of fruit even, as more powerful tools than the mere image of any given banana in front of one’s eyes. After all, it IS a working game, isn’t it? And if it’s working, it means – or so I thought in my happy world of sane code and educated programmers – that there is clarity at its core, there is thoughtful planning in its design and there is structure to its code. Alas, in the wider world of open sores it turns out that “working” code is in fact nothing more than a total mess of bits and pieces glued together with mud and thrown at one another haphazardly, propped up with random things pompously called supports and then those supports further propped up in turn and then again until the whole thing is but a pile of hardened idiocy and nonsense that just keeps growing. And the more it grows, the more it eats up not only the time of those involved but also all light and beauty and good in the world for no such things can ever be grown out of such cursed soil.
Still, being of a rather inexplicably happy disposition, I could not quite imagine the full extent of the horror that “working” code can be. With happy and naive thoughts that there still is something sane at the core of the whole thing, I took the plunge. Since documentation was missing and useless, since the code itself was too tangled to provide any means to get the bigger picture first, I went straight into the code, as one would go into the unknown jungle – slowly and carefully, looking 10 times first and making a tiny step only afterwards. And tiny steps worked for a while. They worked for fixing small things – an unintended truncated result of division due to using int operands here, a lack of checks on pointers here and there, a missed case at an “if” crossroads or an incorrect sorting of an array.
Such tiny fixes worked for a while, but they soon became harder and harder to perform. For they were essentially the code equivalent of draining a swamp that was not merely a little puddle somewhere on the outskirts of the project, but rather the very soil on which the whole code had grown – as twisted and foul as it had grown, of course. And the swamp – like any swamp – effectively hindered any and all attempts at building something solid, high and dry and safe: the tangle ensured that no bit of code *could* actually be tested on its own because there was no way to isolate it even for testing purpose; the magic-number droppings meant that changing even one single thing required changes through all the code base without really knowing the consequences; the sheer size of the code meant that others had been lost in it before and giving in to it they had simply copy/pasted code again and again and again until there was the same thing done in five places and slightly different ways for slightly different cases with very similar results; there were pointers anywhere and everywhere, for reasons long forgotten if they even existed in the first place; there were weird calculations with the magic numbers – one can be forgiven for hating magic alltogether after seeing this source of it; there were identifiers, but not only IDs as one might expect – oh no, there were instead pIDs and eIDs and uIDs and in some cases they all referred in fact to the same thing, while in other cases they referred to entirely different things; there were items and there were containers and sometimes items were containers while containers were actionLocations while at other times items were items but containers were items*100 and the containerID could refer at the same time to a container, to a location or to the number of horns on the latest devil incarnation for magic-number purposes.
Despite the above and many more adventures of the same type3, I kept going on. I kept thinking that all of that nonsense is in fact just the accumulated rot of countless eager contributions that the unsuspecting and unprotected open
sourcesores project might encounter in its unhappy life in the wild. I kept basically entertaining the delusion that there still was – if there ever was – something that can be used as it is, once all the rot has been cleared away. And I held on to this illusion until that vomit-inducing moment when one significant piece of the mess became very, very clear: the whole thing, the server and the client and the feeble attempts at logic on both sides were made *starting* from and ending with… graphics. In other words, those monkeys pushing the keys knew indeed nothing of the abstract concept of a banana, they were totally innocent in fact of any notion of abstraction. Their world really was nothing more than what met the eyes – what met *their* eyes even.
In one of the most horrible exhibits of this innocence, the server effectively searches through a list of graphical representations (meshes) to find a wanted object; in another, both server and client identify objects not by their id or even by their type+name or any other such key essentially related to the object itself, but by their… place in the world. And if that was not enough, this place in the world is not even always the same thing, for it can change in puzzling ways: to give but an example, containers in the world have places inside them from 0 to 15 but same container taken in somebody’s inventory has places (of a kind as they are “simulated” for added points of idiocy) from 1 to 16 all of a sudden. Moreover, containers in inventory are not even containers anymore (fancy that!) – they are instead “simulated.” Simulated how? Well, in a very, very simple way, like all horrible solutions: by multiplying the container’s slot with 100 and then adding to that 1 to 16 for the container’s slots themselves. So that first slot in container on slot 15 in inventory becomes 100*15+1 = 151, isn’t that neat? And doesn’t that make it impossible to change the number of slots in inventory alltogether beyond the magic number of 100? And doesn’t it mean that all server and client code keeps going back and forth with div 100 and mod 100 and * 100 and fuck 100 and oh, no, we forgot 100 for ever and ever and in all places?
Still, I guess it shows that some of them knew at least about mod and div and 100. Well done, have a banana!
No, there is no possible sane justification for more than half a million lines of code for a computer game that is overall barely noticeable in terms of game play. ↩
They each deserve a detailed story I guess, but I’m still quite in the thick of it, quite raw in places from it, quite busy with the rest of it. ↩