Apparently smart people are the true idiots.
Chris Katko

This is a 4.4MB C# source file for A Game About A Dragon... which is on Steam.

It's not even the entire game. 107K lines. No loops. The author didn't know about loops and to my absolute horror the update function calls itself in order to "loop". Read that again. In order to loop, it throws another function onto the stack. How it doesn't crash immediately, I have no freaking idea.

You'll also notice a lack of classes, as well as far as I can tell, arrays. Tons of global variables. The "update" function is 95,000 lines long.

Also, apparently the award winning game Undertale has a switch statement that's over 1,728 lines long.

Here we are, wasting all this time trying to learn elegant ways to control code rot in our codebases, and caveman are running around smashing two rocks together and getting on Steam.

On the bright side, I do feel a little better that my code isn't that horrific. But I'm also not making any money off my games.

Mark Oates

Everything you've said is 100% true. The priority of software development is not on code quality, but your ability to ship. Globals, data structures, languages, paradigms, OOP, etc. is important, but if you can't get past holding on to absolute rules then it will hold you back.

I think I'm less productive when I try to write perfect software. Some of the most successful code I've written was before I learned that I was doing it wrong. :P

To offer an alternative to your examples, people were raving about how amazing the original Doom source was when it was released. :)

Bruce Pascoe

It looks like the Update function calls itself at the end of the function block. The C# compiler is probably smart enough to convert it to a tailcall. Basically, it's a lucky accident that it works at all.

But yeah, that's... well, to quote Dave Strider of Homestuck fame:

Quote:

that is horrendous
in the most beautiful way

I can't give the coder too much flak. He at least acknowledges how bad it is. Hell, I wrote code like that when I first started out with QBasic, all those years ago. We were all newbies once.

Reminds me of the VB code my cousin used to write. Then I taught him about object-oriented programming and loops and it got much better.

l j

There's no recursion of any kind in that code. It's calling the super class' update method.

RPG Hacker

Kinda reminds me of Amazing Tetris, my first completed game written in Free Pascal. It probably wasn't THIS bad, but I didn't know about OOP back then, so no classes or inheritance in the entire code (which, to be fair, probably isn't even that much of a problem in a Tetris game, which barely benefits from inheritance in the first place). Also had a ridiculously long main.pas file, where like 90% of my game update code were, including the complete options menu (and pretty much any other menu). Honestly, I still somewhat have the habbit of making really long source files and functions. I only ever split code into multiple functions when I'm actually reusing it somewhere. In a Tron-like racing game I programmed at Games Academy, almost all of the update code of my main player class was just a single lage update() function with almost no functions.

Regarding the time argument, yeah, that's a huge factor. There are major differences between code I write at work with limited time, code I write at home for fun and code I write at home for "serious" stuff and plan to reuse later. For the first category of code, functionality usually is the most important thing and there just isn't always enough time to put in the effort of making the code prettier, cleaner and more readable. For the second category, there is enough time, but no real necessity for write good and reusable code, so "everything goes". For the third category, there IS a necessity for writing good code, as well as enough time, so here I usually write the best kind of code, which means often going back to old code to making it prettier and better. Of course this also means slow progress, but that's worth it, since those are kind of my "dream projects". The real problem here is rather how often I completely restart a project because I decide that the current project in the current state just doesn't suit my needs anymore. Happened all too many times. With my current project, I'm on a good course, though.

Kris Asick

Making a game does not indicate someone's level of intelligence. I would think the library of stuff here on Allegro.cc would be a good indication of this, as it all ranges from really awesome to "how in the world did anyone think this was a good idea?" :P

Besides, there's tons of people out there who are stronger designers than coders... There's actually a couple indie games I have on Steam which look neat but which I can't actually play because of game-breaking issues which only affect certain people and not most people, thus the authors aren't completely sure how to go about fixing them... even after I've tried making suggestions on how.

(Side Note: If you don't have a product published on Steam and you try to give programming advice to someone publically in a non-programmers internet environment, there will ALWAYS be f___twats who try to call you out for not knowing what you're talking about, even though they themselves don't have a clue what they're saying. I've had this happen to me a few times now and it doesn't even have to happen on Steam itself. Some people forget that there was once a time when indie game devs had to sell their software in ways other than Steam... :-/)

Bruce Pascoe

Regarding what RPG Hacker says: That's why I wouldn't ever want to do programming professionally. I like to take the time and put some care into my code so that I can still understand it a year down the road. My JS game engine, minisphere, has some of the nicest C code you'll see anywhere (not to say I didn't make some questionable decisions along the way, but I'm slowly working on rectifying them, me being a refactoring fiend), but that's only because I'm not running up against a deadline--so I can take my time and do releases only when they're ready.

RPG Hacker

I get your point, but on the other hand: Many of the needs of my private "home" engine only exist BECAUSE or experiences I've made at work (either things I've learned at work or problems I've encountered with code at work). So it's kinda like "I have to write shit code at work before I can write really good code at home" (in a metaphorical sence, my code at work isn't "shit", just less polished). In fact: A lot of the code I considered "good code" a few years back, before I even did Programming for a living, I now consider bad or even horrible code. A lot of code-related problems just never arise unless you're working on a really big project (and especially a team project), so work is actually what teaches me the things I want (or absolutely don't want) in my private engine.

bamccaig

At the end of the day, game software is basically the same program with a bunch of hard-coded logic thrown into specific places. It's hard to really improve upon that anyway. Generally the game state is one big blob. Interactions happen in ways differently than business software. At least doing everything at once avoids the usual gotchas that people naturally attempt to do with gaming OOP: mario.draw() or mario.check_collision(block). That's probably worse than just hard-coding everything into the main file because you'll probably end up having to hack around your abuse of objects and inevitably it will lead to bugs.

Of course, game software is typically not maintained. You write it once, ship it, and that's that. You'll never maintain it. You'll never go back to fix anything. Hell, if it shipped on a console you can't. At best you'll port it to other platforms and you'll do it as quick 'n dirty as you can. :P That's the difference.

If this guy were to go back to this game in 6 months and try to figure out what was happening he might curse his past self. That said, it looks like the XNA or equivalent framework was used to make it and he probably has that structuring to thank for making it as straightforward as it is. He doesn't have any of the framework stuff that we'd have in Allegro to sort through. If he had to write that too he might not have ever made a game at all, let alone one that could reach Steam. That's the downfall of Allegro...

He could probably reduce the size of the code quite a lot with a smarter design, but the size probably isn't a huge hindrance and it works so fuck it. :P The biggest pain is probably just making a change X times. But a good editor, which he probably wasn't using, can automate that... A determined and ignorant programmer won't mind those tedious changes though.

jmasterx
bamccaig said:

Of course, game software is typically not maintained. You write it once, ship it, and that's that. You'll never maintain it. You'll never go back to fix anything. Hell, if it shipped on a console you can't. At best you'll port it to other platforms and you'll do it as quick 'n dirty as you can. :P That's the difference.

That might have been true in say the 6th gen console days or earlier, but these days mandatory updates are the norm. They include new features, bug fixes, DLC, etc. So maintenance is now very much part of the game SDLC.

RPG Hacker

Kinda, yeah. But typically only for a few weeks after release. Even then, this is only the case because, thanks to the power of patching, games are now released earlier than they used to (usually before they're fully ready and/or without having gone through the same kind of thorough QA that games on past consoles necessarily had to go through before release). I think what bamccaig meant was actually maintaining software for years to come. Like, for example, Windows. Microsoft doesn't release a version of Windows and then, a few weeks later, just abandons it and moves on to the next project, just to get back to the old Windows a few years later and do a quick and dirty port of it. No, after they release a new Windows version, they provide that version of Windows with updates for years to come, and even when a new Windows version is eventually made, it reuses a majority of the code of the old version.

In that regard, I actually have to disagree with bamccaig a little. Sure, games are usually programmed for one-time use and are rarely touched upon after release. However, this doesn't go for game engines. Game engines are usually written for reuse, especially in professional environments, so even as a professional programmer, you want to put at least SOME care into maintaining your code. This doesn't necessarily apply to hobby programmers, of course.

Chris Katko

I heard John Carmack talking about advanced, expensive code quality analysis companies / services (5 figure expensive!). They told him his Doom 3 engine (601K lines of code) was one of the most well-put-together codebases they had ever seen. Other people apparently agree:

http://kotaku.com/5975610/the-exceptional-beauty-of-doom-3s-source-code

Now that doesn't really mean $$$, or good reviews. But it's still impressive from an artisan standpoint. Doom 3 was produced on a schedule, and was a commercial endeavor.

One note though, I disagree about the articles "code shouldn't have comments." That's silly. Code for "how," comments for "why."

[edit] Check out the comments! John Carmack himself chimes in!

Quote:

Thanks!

A few comments:

In some ways, I still think the Quake 3 code is cleaner, as a final evolution of my C style, rather than the first iteration of my C++ style, but it may be more of a factor of the smaller total line count, or the fact that I haven’t really looked at it in a decade. I do think “good C++” is better than “good C” from a readability standpoint, all other things being equal.

I sort of meandered into C++ with Doom 3 – I was an experienced C programmer with OOP background from NeXT’s Objective-C, so I just started writing C++ without any proper study of usage and idiom. In retrospect, I very much wish I had read Effective C++ and some other material. A couple of the other programmers had prior C++ experience, but they mostly followed the stylistic choices I set.

I mistrusted templates for many years, and still use them with restraint, but I eventually decided I liked strong typing more than I disliked weird code in headers. The debate on STL is still ongoing here at Id, and gets a little spirited. Back when Doom 3 was started, using STL was almost certainly not a good call, but reasonable arguments can be made for it today, even in games.

I am a full const nazi nowadays, and I chide any programmer that doesn’t const every variable and parameter that can be.

The major evolution that is still going on for me is towards a more functional programming style, which involves unlearning a lot of old habits, and backing away from some OOP directions.

http://www.altdevblogaday.com/2012/04/26/functional-programming-in-c/

[edit] Archived version:
https://web.archive.org/web/20140719080947/http://www.altdev.co/2012/04/26/functional-programming-in-c/

John Carmack

bamccaig
jmasterx said:

That might have been true in say the 6th gen console days or earlier, but these days mandatory updates are the norm. They include new features, bug fixes, DLC, etc. So maintenance is now very much part of the game SDLC.

The only updates that they'll push are generally going to be abuses of the platform. Probably severe bugs that prevent the game from being played if you're lucky, but I recall PS3 games that were never patched and you just had to pray as you went through certain levels that you didn't get stuck.

Some games they might try to fix if they released before it was really ready to meet a deadline, but it'll just be the end of the development cycle overlapping with release/deployment. It's not maintenance mode. It's still development mode.

Most updates are probably superficial, like removing controversial content, adding or tweaking tracking/DRM/intrusions, advertising, etc. Updates are usually pretty rare after the first few months of release even on platforms where it's technically possible. Unless it is hurting sales there's no point for the game studio to spend any extra resources on making changes. They move on.

The exception is long-term online games, like GTA: Online or MMOs or whatever else. Those will get content updates to keep them relevant.

Ariesnl

Apparently C# eats your brain :-D

Kris Asick
Ariesnl said:

Apparently C# eats your brain :-D

While D just makes your ears bleed. ;D

amarillion

I think I'm less productive when I try to write perfect software.

That should be the TINS tagline

l j

Perfectionism is a curse. I've never been proud of anything I've made so far and always rewrite over and over again. I've stopped the rewriting games part generally now, because I ended up writing a script language, scrapped it and am now busy building a compiler for a language that I'll probably end up throwing away at some point.

RPG Hacker
Quote:

I am a full const nazi nowadays, and I chide any programmer that doesn’t const every variable and parameter that can be.

He got me there! ;D

I usually DO use const with functions whereever it's necessary (either on pointer/reference arguments or on the functions themselves), except for things I pass by value (like native types or small structs), because I don't feel the need there. For actual code, I almost never use const, though, unless I absolutely have to (like when you pull an element from a vector of const objects, for example). I don't know if compilers even benefit from local variables being const (and I'm not talking about something like "const int = 1;" here, where I do see the point, but rather about something like "const int = arg + 1;", where arg is an argument and the whole expression therefore can't be a compile-time constant, anyways - I don't know if the const actually makes any difference here except for giving the programmer a usage hint).

l j

Const is 'pure', immutable values are easy to reason about. The majority of variables don't need to mutate in most programs. Optimizers are more free to make assumptions about immutable values. Accidentally mutating a const will result in a compile-time error.

Bruce Perry

Look on the bright side: the poor guy has now trained himself never to suffer a copy and paste error in his entire life :)

I actually remember balking at what I would have to do to achieve certain things when I didn't know arrays yet. I think it may have been pixels or something. All 640x256 of them.

bamccaig

Look on the bright side: the poor guy has now trained himself never to suffer a copy and paste error in his entire life :)

How so? Quite the opposite, he has trained himself to suffer countless copy and paste errors. He needs to start on the path to untraining it.

Johan Halmén

Allegro code is to top selling game code what poetry is to pop song lyrics.

RPG Hacker

All this talk about copy & paste kinda reminds me of Limbo of the Lost! ;D

Mark Oates

poetry is to pop song lyrics.

Pop music having a much higher market value. ;D

Bruce Perry
bamccaig said:

How so? Quite the opposite, he has trained himself to suffer countless copy and paste errors. He needs to start on the path to untraining it.

I understand a copy and paste error to be where you legitimately copy and paste something but forget to change everything you wanted to change. Since he has done so much copying and pasting, he will be an expert and not forgetting to change things. You're right that he needs to train himself not to copy and paste so much, of course - but once he's done that, at least he'll still copy and paste reliably when he does need to :)

bamccaig

All this talk about copy & paste kinda reminds me of Limbo of the Lost! ;D

It has given me a game idea. One where you have to solve code puzzles using only copy and paste. You'd start out each puzzle with a single text of code and have to modify it to do something else, but your only method of transformation would be copy and paste (and maybe cut). ;D

I suppose a more accessible game would be one where you just had to modify text, not code, but perhaps that's where difficulty levels would come in. :)

Seems like a reasonable idea for a mobile game...

I understand a copy and paste error to be where you legitimately copy and paste something but forget to change everything you wanted to change. Since he has done so much copying and pasting, he will be an expert and not forgetting to change things. You're right that he needs to train himself not to copy and paste so much, of course - but once he's done that, at least he'll still copy and paste reliably when he does need to :)

Doing a tedious and painful operation countless times does not make you more reliable at it. We're humans. Meat sacks. We are forever bad at these kinds of tasks.

People don't screw it up because they don't know better. Experienced programmers with 10 years of experience will screw up copy-paste operations if they're doing them repeatedly. Particularly if they're lazy and don't review their patches. :P

OICW

Everything you've said is 100% true. The priority of software development is not on code quality, but your ability to ship.

Well yes, but on the other hand you have to ask yourself a question whether you can just forget about what you've written after you shipped it. In the previous work our client wanted us to change some functionality in the application that was under constant development. There were some crunches to meet some release deadlines for milestone versions (trying to mix agile development with clients expecting waterfall because you can plan your spending... but that's for another debate).

And what happened during these crunches was that some functionality was hacked in. Not to mention that there was a really diverse bunch of programmers. After some time the client, naturally, wanted to change something in the previously hacked part of the code. The hacks have bitten us in the ass quite hard several times. I can tell you, the code debt you introduce into your codebase stacks until one day the project just crubmles under its own weight.

bamccaig said:

At the end of the day, game software is basically the same program with a bunch of hard-coded logic thrown into specific places. It's hard to really improve upon that anyway. Generally the game state is one big blob. Interactions happen in ways differently than business software.

Hm, I don't think so, you can write a game engine elegantly, just like id Software did with most of their engines. It depends on whether you plan just one title game or you plan to use your engine for more products. Right now I work at a company where we are using one such engine in ways unimaginable. It contains some really old legacy code and the whole thing is nightmare to maintain, debug and, heaven forbid, extend.

Not to mention that there are some really nasty hardcoded things, the whole codebase uses macro hell for enabling/disabling particular functionality, hot fixes or whole products. The main game loop is a long piece of disgusting code interleaved with conditionally compiled blocks of code everywhere. Just the worst spaghetti bowl you've ever seen :-X

So, no games are not ad-hoc pieces of code flicked together. Do not treat them like it, they are first class citizens amongst other codebases. They are no different.

Chris Katko

I read up about the Limbo of the Lost. Wow, that was quite the rollercoaster of insanity.

Also, intelligent design, both preliminary, and as the design evolves, is going to control how much additional complexity is from accidental complexity.

I've been reading some interesting stuff lately. There are two kinds of complexity. Accidental and essential. Essential is what's actually going on. The actual problem is X complex. The accidental complexity is what we, in our lack of omniscience to see the problem for what it is and where we're going, is the complexity we add on top of it. Anti-patterns. Doing things that aren't in our best interest because we fail to understand the problem, or the implications of our design choices.

Proper design is about reducing accidental complexity, not essential. The C++ community (and others) has brainwashed itself into thinking essential complexity can be removed with hierachies and abstraction but it's actually the opposite. Encapsulation and abstraction actually increase overall complexity, but allows us to organize the complexity into manageable chunks to keep similar issues lumped together. A programmer can only keep so many ideas in his head at a time, and the more you have, the more likely he or she will fail to notice one or more of the requirements and write a bug, or reduce the rate at which code can be written. We've all been there: Looking at a piece of code and taking the smallest baby-step changes because we're afraid of breaking something we don't quite understand because it's so massive and difficult to reason about.

Also, shrinking functions as small as they can go can actually increase complexity. You're reducing the amount of function calls per function, but at the same time increasing the vertical depth of your program. So you could be going from a "complex" 1-page function, to a couple of one-liners, but now you've got to track 8 different functions across different source files and it becomes very hard to visualize the call graph.

Mike Acton, of Insomniac Games (Rachet and Clank) really struck a chord with me when he did his talk at C++Con about "the software isn't the platform. The hardware is the platform." It was such a different mindset, everyone was either appalled or confused. He said, as an engineer, you have to be able understand how the code you write will be run on the CPU and cache-level. They kept saying "That's complex. We prefer to abstract away the underlying hardware." and he said, [all paraphrased] "That doesn't matter. If the problem is complex, then you deal with the complexity. What you're suggesting is not solving the problem. The problem of the hardware is still there and you're just ignoring it and hoping it doesn't screw you." He basically suggested that if you're not dealing with the entire problem (relying on encapsulation like quick-and-easy STL containers) then you're not an engineer--you're more akin to a mechanic/industrial tech who knows how to use tools but not why they work and how to break out equations and solve them when something "odd" happens outside their experience.

http://www.johnnybigert.se/blog/2012/02/sustainable-software-development-managing-complexity/

Quote:

Last words from McConnell’s “Keep it simple” article: “Neither hierarchies nor abstractions reduce the total number of details in a program — they might actually increase the total number. Their benefit arises from organizing details in such a way that fewer details have to be considered at any particular time.”

This needs to be my new sig.

bamccaig
OICW said:

Hm, I don't think so, you can write a game engine elegantly, just like id Software did with most of their engines. It depends on whether you plan just one title game or you plan to use your engine for more products. Right now I work at a company where we are using one such engine in ways unimaginable. It contains some really old legacy code and the whole thing is nightmare to maintain, debug and, heaven forbid, extend.

Not to mention that there are some really nasty hardcoded things, the whole codebase uses macro hell for enabling/disabling particular functionality, hot fixes or whole products. The main game loop is a long piece of disgusting code interleaved with conditionally compiled blocks of code everywhere. Just the worst spaghetti bowl you've ever seen :-X

So, no games are not ad-hoc pieces of code flicked together. Do not treat them like it, they are first class citizens amongst other codebases. They are no different.

I'm not sure if you countered my argument or supported it. :o I'm generally an idealist and perfectionist in the sense that I believe that software can always be written ideally and "correctly". That said, I haven't figured out yet how to make a profit doing it so I'm open to criticism. I don't particularly subscribe to the notion of Capitalism either since we've seen where that gets us, but I'm not sure the alternatives have proven themselves any more robust. My point is basically that I said that begrudgingly. I haven't actually accomplished writing a complete "game" before, and it seems that most that have assert the need for "bad practices" to get the job done. I'm glad to see somebody opposing that, but again your anecdotal evidence seems to by contradictory to your point. :P

Bruce Perry

I just had a copy and paste error in my TINS entry :)

    event.mouse.x = (event.mouse.x - pillar) * screenWidth / (displayWidth-2*pillar);
    event.mouse.y = (event.mouse.y - pillar) * screenHeight / (displayHeight-2*letter);

RPG Hacker

Is it the "pillar" in the second line?

Bruce Perry

Yep :)

RPG Hacker

Now that kind of error just too well! ;D

Thread #616249. Printed from Allegro.cc