
More Dirty Coding Tricks from Game Developers (2010) - maccard
http://www.gamasutra.com/view/news/249475/More_dirty_coding_tricks_from_game_developers.php
======
ketralnis
A couple of those are cited like this:

> \- Anonymous (sourced from Reddit replies to the original 2009 Dirty Coding
> Tricks article)

So not anonymous at all then. reddit comments have usernames attached to them,
URLs that can be linked to, and even an on-site messaging system that can can
be used to ask the author for permission to use the content. Heck, every
comment has an "embed" link below it to conveniently embed the properly cited
comment right on your page.

Is this a thing that's okay to do? Take someone else's content from someone
else's website, copy-paste it into your article, and claim it was "anonymous"?

Would this author be okay with it if I copy-pasted their articles to my blog?
What about if I stole all of the comments posted to their articles to make my
site look more active?

~~~
rjbwork
No, it's not okay. The media, especially gaming publications, have been doing
this stuff for years now, and it's ridiculous. Some publications have wised
up, but many haven't.

It's greatly amusing when someone just gives up all pretense and just scrapes
a subreddit, then SEO blog spams every single post - because then the members
will upvote stories about how terrible the website is. I unfortunately can't
find anything specific at the moment, but 2 of the big ones I remember was
/r/makeupaddiction and /r/gaming.

EDIT: For the curious, here's the mod post about the /r/makeupaddiction
incident
[https://www.reddit.com/r/MakeupAddiction/comments/39o74y/mod...](https://www.reddit.com/r/MakeupAddiction/comments/39o74y/mod_notice_your_pictures_are_being_used_without/)
I'm unable to find the others at the moment, though there is a list under the
top comment on the thread I've linked.

------
Negitivefrags
I have a story kind of similar to the one called "...Or is it over here!?"

A friend of mine was having crashes with a program. When debugging it he found
that a bunch of his local variables had weird values. He suspected that there
might be a buffer overflow elsewhere that was trampling over the memory.

The fix? Just add "char buffer[ 1000 ];" to the function to absorb the damage.
It fixed the crash and it shipped like that.

~~~
shoo
This reminds me of an older "dirty trick" where a buffer was sacrificed,
instead of added, at the end of the project in order to ship.

See "The Programming Antihero"[1].

[1].
[http://www.gamasutra.com/view/feature/132500/dirty_coding_tr...](http://www.gamasutra.com/view/feature/132500/dirty_coding_tricks.php?page=4)

~~~
tfigment
I've done something like this on a production data base server before. Maybe
not the same thing but I allocated a really big file because mysql would
occasionally grow its ibdata file to full the disk before we could handle the
alert. Deleting this file allowed room to maneuver after restarting the
database and dealing with this run away journal file.

The other similar urban legend is the enterprise teams which have for(int
i=0;i<10000000;++i); loops in code which they can remove a zero when
performance boost is needed and they can quickly provide a fix.

------
curryhoward
> Here is a horror story from the good old days when men were men and used
> DirectX 7.

Ugh.

> Personally, I hate CONST with a passion, so I like this trick.

Ugh.

> PhysicalObjects could take damage. The air strikes did enough damage in a
> large enough radius that they were quite literally "killing" the camera. I
> did fix the bug by ensuring that cameras couldn't take damage, but just to
> be sure, I boosted their armor and hit points to ridiculous levels. I
> believe I can safely say we had the toughest camera in any game.

Awesome.

~~~
shoo
Regarding the camera with hitpoints, is there a name for that class of bug?
Poorly thought out code reuse? Overly specific inheritance?

A similar seeming bug is the old "kangaroos with rocket launchers" story (from
military simulations, not games) [1].

[1] [http://www.petting-
zoo.net/~deadbeef/archive/4488.html](http://www.petting-
zoo.net/~deadbeef/archive/4488.html)

~~~
tinco
It's inherent to common game architecture. Far out the most flexible way of
dealing with the multitude of complex entities in a game is to not work with
inheritance but rather with 'components'. Ideally this means that an entity is
nothing more than a UUID for which data is stored in component tables (a la
relational databases).

Unfortunately that approach is rather cumbersome to reason about and brings
with it unhandy syntax requisites. Given an entity UUID, how do you get a
value for some property? It would be component_table_get(health_components,
entity_id)->hitpoints. Or something similar. (note: what happens if you
accidentily call that function on a entity_id for which no health_components
entry exists?)

The alternative which is really fine for smaller games and which often leaks
into the codebase of larger games, sometimes for performance reasons is to
make the entity a struct which has some members common to all entities. Now
you can do entity->hitpoints, but the downside is that every entity, including
abstract game components such as the camera also have hitpoints.

If you're curious why games don't do inheritance (anymore) look up articles
about Component Entity Systems, they usually do a good idea of explaining why
games are too complex for inheritance.

~~~
golergka
> Unfortunately that approach is rather cumbersome to reason about and brings
> with it unhandy syntax requisites. Given an entity UUID, how do you get a
> value for some property? It would be component_table_get(health_components,
> entity_id)->hitpoints. Or something similar. (note: what happens if you
> accidentily call that function on a entity_id for which no health_components
> entry exists?)

I work with Unity engine (which uses exactly that model), and in good code
these problems don't arise — or, rather, these checks are meaningful and
actually represent the logic, rather then being "unhandy syntax requisite".

Imagine that you have a lava object with a trigger collider (that means that
it doesn't influence the physics) and a Lava custom component (MonoBehaviour)
on it. In `OnTriggerEnter` method of Lava you run `var health =
GetComponent<Health>()` method on GameObject that entered lava and determine
if that thing is something that can be damaged — because, quite possibly, it
is a camera (as in that example) and the method will return null. And then, if
it is something that you can damage, then you can use the `health.Damage(5 /*
random dice roll */)` on it.

------
airza
> we'd inexplicably get a crash in printf [..] The client in debug would print
> out the hashes of every content package the server told it to load, and
> apparently one of them (on this build) had a % in the hash. We couldn't
> figure out a reasonable fix for it, but #ifndef PS3 worked just fine until
> the next data build

Friends don't let friends printf(str).

~~~
Kenji
I didn't really understand that problem. They couldn't fix this?? Like, they
didn't know how to escape/replace percent signs or print differently? Maybe I
am missing something but it does not look like a particularly elusive problem.

~~~
pandaman
How I understand is that they had printf(x) somewhere and some values of x
included the '%' character. If this has been inside the UE and the x itself
was a hash value then both replacing with printf("%s",x) and changing the x's
value could be problematic.

------
golergka
I want to do something very violent to that person who "hates const with a
passion". No wonder he didn't provide his name.

~~~
bitwize
'const' in C and C++ is broken. Not only is it like a Chinese word that varies
wildly in meaning depending on where you use it and how it is inflected, but
in C-family languages, 'const' modifies _type_ , making objects that benefit
from the compiler hints 'const' implies type-incompatible with objects that do
not. This results in the problem of some know-it-all deciding that a core API
needs to be const-correct, and checks in changes making it so, only to find
that the entire fucking code base is now broken.

Note that I'm not saying "don't use 'const'" with the above (and I'm CERTAINLY
not saying "using '#define const' in your code base is a good idea"); only
that 'const' in C-family languages has significant drawbacks which may affect
the engineering tradeoffs you make when you decide whether to use it.

By contrast, languages such as Ada have explicit and implicit constantness
restrictions ('in' parameters, for instance, cannot be modified), but these do
not modify the type of the object, allowing objects with these restrictions to
be type-compatible with objects without them.

~~~
CountSessine
I don't really understand what you're saying.

 _' const' in C and C++ is broken. Not only is it like a Chinese word that
varies wildly in meaning depending on where you use it and how it is
inflected, but in C-family languages, 'const' modifies type, making objects
that benefit from the compiler hints 'const' implies type-incompatible with
objects that do not._

They're not type-incompatible in any way that doesn't violate those compiler
hints in the first place - C and C++ fully support sensible coercion between
const and non-const types. What more do you want?

 _This results in the problem of some know-it-all deciding that a core API
needs to be const-correct, and checks in changes making it so, only to find
that the entire fucking code base is now broken_

Would you rather it compiled and silently broke? If some dingus breaks the
build by changing an API without checking in the corresponding code using the
API, how is that C/C++'s fault?

 _By contrast, languages such as Ada have explicit and implicit constantness
restrictions ( 'in' parameters, for instance, cannot be modified), but these
do not modify the type of the object, allowing objects with these restrictions
to be type-compatible with objects without them._

This is bizarre. Can you take that 'in' parameter and then pass it on to
another function as an 'in/out' parameter? If so, then either

1\. Ada just made you a copy silently (bad)

2\. Ada is broken and 'in' means nothing (worse).

If neither of those are true and an 'in' can't be transitively passed on as an
'in/out', then _that 's a type_ \- however you want to refer to it, 'in' is
then a type with all of the 'broken' type restrictions you're railing against
in C/C++.

~~~
thisisnotatest
const is type-incompatible like this:

Suppose you want to write a function that returns all the nodes in a tree that
satisfy some property. In C++ you have to define two different versions (or
use templates to make the compiler clone it for you):

    
    
      vector<Node*> GetGoodNodes(Node* root);
      vector<const Node*> GetGoodNodes(const Node* root);
    

If more than one type is involved in the operation, there can be a
combinatorial explosion.

~~~
golergka
I don't feel that I understand purpose of this function yet.

Does this function return data point that it creates itself, or does it
retrieve these nodes from somewhere else? If it's the first option, who's in
charge of deleting them? If it's a second option, who's in charge of counting
references to these objects? Also, if it's a second option, and this data
points are retrieved from a certain storage, are you absolutely sure that
whoever gets this data should be able to modify them?

~~~
SamReidHughes
> Does this function return data point that it creates itself, or does it
> retrieve these nodes from somewhere else?

It returns pointers to the nodes in the tree. You know this because the caller
isn't supposed to (or allowed to) delete them, because if the caller was
responsible for that, they'd be wrapped in smart pointers.

> If it's a second option, who's in charge of counting references to these
> objects?

The pointers in the return value are valid as long as their particular
descendant of the function parameter isn't deleted. There's no need for
reference counts, and if they're present at all, they aren't updated by this
function, since the caller isn't responsible for decrementing them. If the
caller was responsible, the return value would be a vector of smart pointers.

> Also, if it's a second option, and this data points are retrieved from a
> certain storage, are you absolutely sure that whoever gets this data should
> be able to modify them?

If they have a const node *, they shouldn't. If they don't, they should.

~~~
golergka
Thanks! Your first two answers would be obvious if we assume that we're
working with modern codebase written by adequate developers, but that's a very
strong assumption to make, so I wanted to be specific.

And your final answer is, well, exactly the point I was trying to steer the
conversation to. In other words, if you declare both methods, it means that
you're doing something wrong: you're giving away data mutably and immutably at
the same time, and it just doesn't make sense.

~~~
SamReidHughes
You aren't.

If you have a non-const node, you can access its children non-constly _or_
constly (which you could do anyway, since you could make your reference to the
node be const at any time). If you have a const node, you can only access its
children constly.

This makes perfect sense.

~~~
golergka
My bad: didn't read the code carefully, thought that these were methods.

------
wh-uws
The battery backup initialization hack from NBA JAM TE is random and hilarious

[http://www.ign.com/cheats/games/nba-jam-tournament-
edition-g...](http://www.ign.com/cheats/games/nba-jam-tournament-edition-
gen-6289)

~~~
daodedickinson
Is there an explanation for this somewhere?

~~~
barbs
I was also looking for more info on this. Sounds like a good idea for a blog
post if anyone can shed light on how/why this works.

~~~
icelancer
Agreed. My limited Google searching turned up nothing.

------
busterarm
Pretty sure Nicholas Vining was referring to the LithTech engine and the game
would be Die Hard: Nakatomi Plaza

~~~
avesanen
Yep, this is the comic he was referring to: [http://www.penny-
arcade.com/comic/2002/02/11](http://www.penny-arcade.com/comic/2002/02/11)

~~~
Sniffnoy
This is actually not the first mention of that character -- that would be this
comic[0] -- but seeing as that comic doesn't mention an engine and the rest
doesn't really fit either, presumably the one you link is the one he actually
meant.

[0] [http://www.penny-arcade.com/comic/2001/07/11](http://www.penny-
arcade.com/comic/2001/07/11)

~~~
spoondan
Nicholas Vining was referring to the first ever _appearance_ of the character,
not its first _mention_. The Lithtech comic is the first appearance, and the
one you've linked is its first mention.

~~~
mikeash
Interesting. Does it not count as an appearance even though its box is there,
with the item inside?

------
shoo
The earlier articles[1][2] are also pretty good.

I'm utterly horrified by the "(s)elf-exploitation" story. Ugh. Clever.

[1]
[http://www.gamasutra.com/view/feature/194772/dirty_game_deve...](http://www.gamasutra.com/view/feature/194772/dirty_game_development_tricks.php)

[2]
[http://www.gamasutra.com/view/feature/132500/dirty_coding_tr...](http://www.gamasutra.com/view/feature/132500/dirty_coding_tricks.php?page=4)

------
e28eta
I wonder if these anecdotes would be a good litmus test for developers. They
make me cringe, but I work on business software, not games.

I really don't like the idea of papering over the bugs so that your testers
can't find them anymore, I'd much rather find the underlying issue. On the
other hand, the described changes were often very practical, solved a customer
need, and were manageable to implement. So that sounds like a win!

~~~
gambiting
Few things contribute to it. Mostly it's lack of time, and the fact that we
don't really have to support code for long periods of time. If the input code
works then it works, when a game is released its code it's mothballed on a
server and I don't even see it again unless there's some urgent patches(and 6
months after release the chance of that happening reduces to zero), and then I
have to request IT to give me access to that code again.

------
Turbo_hedgehog
What happened to altdevblogaday.com anyway? It had content similar to this.

~~~
daodedickinson
Isn't it awful when such resources vanish?

When Megaupload was destroyed, it was like losing the Library of Alexandria to
me. The ATF can't just destroy the entire nation's set of self-storage units
because they found drugs or pirate DVDs in some of the units. But that's what
happened with Megaupload. Some people lost family photos, some people lost
backups of theses... Why couldn't the authorities have taken it over,
eliminated illegal content, and turned it over to some sort of Vichy CEO?
There need to be protections for data storage customers in a FDIC sort of way,
I feel.

~~~
ivanca
Police (and the like) are paid for capturing criminals, not for doing what is
morally right (some hope they are the same thing, but many times it isn't)

~~~
agumonkey
Capturing people doing wrong things by doing wrong things. Strangely
consistent.

~~~
Drakim
This actually not as strange as you'd think:

[https://en.wikipedia.org/wiki/Monopoly_on_violence](https://en.wikipedia.org/wiki/Monopoly_on_violence)

~~~
agumonkey
Interesting view, very interesting view.

------
bananaboy
I've read that Wing Commander anecdote before, and it still doesn't make any
sense to me (also I don't remember that original message "Thank you for
playing Wing Commander" message and every abandonware version I found had a
different message - "You step out of the airlock and into.."). It doesn't make
sense because EMM386 is the expanded memory manager that came with DOS. It's
not something you ship with your game and can hex edit at will. Now if it was
a 3rd party library that USED EMM386, and which they didn't have the source
for, then that might make sense..

~~~
IvyMike
There were third party memory managers that you could use in DOS; for example,
QEMM and 386max. I assume Wing Commander was licensing and shipping one of
those rather than relying on the stock memory manager. In fact in 1993 MS
licensed some technology for later versions of EMM386 from Helix's third party
memory manager[0].

[0]
[https://en.wikipedia.org/wiki/Helix_Software_Company](https://en.wikipedia.org/wiki/Helix_Software_Company)

~~~
bananaboy
Yeah I used to run QEMM. I don't think anyone would have shipped QEMM or
386max with their game, since they were commercial products for end users. It
sounds like, as someone else said, the story was mangled over time.

------
bnastic
Ah, debugging games... It screams desperation when you see code that is
sprinkled with "int 3" 'cos no one knows where or why it's crashing.

~~~
CountSessine
There's a whole lot of desperation in the air when you're final-ing and your
development director is standing over your shoulder at 1 in the morning. :-)

------
plq
> I then remembered that when you put the window in the notification area or
> in the start-menu bar, Windows immediately reclaims unused/freed memory.

Wow. Is this a horrible hack or a wonder of the tight integration between the
GUI and the kernel in an operating system designed to be used in a desktop?
I'm torn :)

~~~
dfox
I think that this is some kind of oversimplification of what actually
happened.

AFAIK there is not even an operation like "put window into notification area"
as part of WinAPI as the icons are mostly orthogonal to windows (and are not
even intended to represent "more-minimized" windows).

The icon has to reference some window, but only because it generates window
messages that have to be consumed somewhere. Fun fact: at least on 2k and XP,
when the window goes away, the icon stays visible unless it is explicitly
deleted by user code and is removed only when some message would be sent to
now non-existent window (ie. when users mouses over the icon).

