Readit News logoReadit News
dietrichepp · 2 years ago
Quake II was my first experience writing C.

The code is clear, coherent, and straightforward. I’m not going to say it’s the best source code I’ve ever read, but it set a high bar. I’ve read source code to games since then, and I’ve seen all sorts of weird stuff… I’ve seen functions with nesting levels that go past the right side of the screen, I’ve seen functions a mile long that do a million things, you know. It was an early lesson that you could do cool things with simple code.

We used Quake and Quake II to teach a VR class to kids in the late 1990s and early 2000s. You got a VR headset, you got a half-dozen PCs with Q.E.D. or Qoole, and you taught a room of 12-14 or 14-18 year-old students how to make their own virtual reality game.

“Make your own virtual reality game” was, essentially, making your own Quake or Quake II level, without any monsters or guns in it. The story for the game could be told through on-screen messages triggered in the level. Students made all sorts of levels. One group made a level with slime you had to cross, and a button that turned on pumps to drain the slime (very much like what you would see in a standard Quake II level). Another group made a 3D maze out of water that you had to swim through, floating in space. I still have some of these student-made levels on my hard drive, after all these years, although I have trouble getting some of them to work.

For the class, I made a mod that gave the players a flaregun instead of the blaster. Basically, it was still the blaster, but with a different sound effect and no weapon model. I modified the blaster bolt to be affected by gravity, bounce off of things, and go out after a certain amount of time.

(If you were in that class—you may not have gotten the headset. We couldn’t always get it to work.)

trilinearnz · 2 years ago
Certainly id's code is clean and well-structured, however I always had a tough time trying to grok it as a layperson. Comments (those within the functions) are relatively sparse, and the code often contains quite cryptic expressions that are somewhat bewildering to those without an high understanding of 3D graphics.

This, of course, makes perfect sense as an output from an industry leader in the field (Carmack). However it definitely requires a lot of foreknowledge and, dare I say it, a mathematical bent to follow with confidence.

NovaDudely · 2 years ago
"I’ve read source code to games since then, and I’ve seen all sorts of weird stuff… I’ve seen functions with nesting levels that go past the right side of the screen, I’ve seen functions a mile long that do a million things, you know. It was an early lesson that you could do cool things with simple code."

Guilty as charged!

I used to chronically write macaroni code. So you would have like 25 lines of code that ended up being the back bone of like a dozen things that would have another dozen things stacked on top of each. Would execute super fast BUT would amount technical debt quickly and eventually said functions would become untouchable because you would risk breaking a lot of stuff build on top of stuff.

Comments would try to clear it up, but communication skills where not the best. Explain function but not workings. Things like - "Does SINE table". "Table Defrag". "Binary resolve" etc.

Get a lot of people going "What the F*K is this shit?! But... it does the job damn fast". If it was any field other that video games, I would not have lasted long and neither would the product...

pydave · 2 years ago
Appreciation for that id code means you may appreciate "John Carmack on Inlined Code (2014)": https://news.ycombinator.com/item?id=12120752
pengaru · 2 years ago
I never scrutinized the id software source, but man have I seen some horrifying game source. The bar is extremely low.

What's surprised me is that successful, fun to play, and stable enough games have been shipped with such absolute unmitigated disasters behind the curtain.

It makes me question sometimes all the effort(and time) I put into preventing the chaos, when such carelessly bodged together garbage can be perfectly profitable.

djmips · 2 years ago
It's nice when you can have both but I have yet to see a game review that mentions how clean the source code is!
flohofwoe · 2 years ago
That's usually because the high level gameplay code needs to be incrementally tweaked over months or years based on very subjective feedback like "this doesn't feel quite right, can you maybe try...".

You can start with a great plan, but no plan survives gameplay- and balance-tweaking for very long.

Ideally the lower layers are much more structured though, usually those need to be maintained over a longer time and across games.

eddyfromtheblok · 2 years ago
That garbage code brought about the speed run culture, highlighted by charity events like Awesome Games Done Quick. The speed runner and their crew on stage will explain the latest level skips, wall clipping to avoid tedious areas, enemy weaknesses and exploits, and frame perfect input strings needed to accomplish those. And some will perform speed runs blindfolded with only the audio cues to work with.
audunw · 2 years ago
The id software source code gets increasingly cleaner for each game I think. I've read the Doom source code and Quake II's. I remember Quake II being very clean and elegant. Doom is not quite there. It's fairly well organized, the functions are generally short and concise, but it's a mess of global variables.
metadat · 2 years ago
Can you share any screenshots of the results of this course? It sounds amazing!
majestic5762 · 2 years ago
Whoa, I still remember watching a show about VR on the Discovery Channel around 1999 when I was a kid. They used Quake 2 as a demo, and it blew my mind. I was playing Quake 2 on my PC also, but the concept of VR was revolutionary to me at the time. It's stuck in my head to this day. To now learn that using Quake 2 was a common practice for teaching VR. Maybe it was you in that documentary!
augustk · 2 years ago
Talking about clear and coherent, does anyone know if there is a deeper reason for using `break' and `continue' instead of pure structured programming? The snippet

  i = ent->client->chase_target - g_edicts;
  do {
     i++;
     if (i > maxclients->value)
        i = 1;
     e = g_edicts + i;
     if (!e->inuse)
        continue;
     if (!e->client->resp.spectator)
        break;
  } while (e != ent->client->chase_target);
for instance, from the function ChaseNext in the file original/rogue/g_chase.c can be reduced to

  i = ent->client->chase_target - g_edicts;
  do {
     i = i % maxclients->value + 1;
     e = g_edicts + i;
  } while ((! e->inuse || e->client->resp.spectator) && (e != ent->client->chase_target));
which in my opinion is clearer since the exit condition for the loop is in one place.

notbeuller · 2 years ago
I find the latter - with all the conditions much less clear. I have to pause and reason about each condition and it’s relation to the others, the order of the comparisons and the effect of short circuits.

The first example makes it very clear that condition A means do it again and condition B means exit this loop while condition C establishes the boundaries of the loop.

andybak · 2 years ago
I think it's debateable which is clearer. Your while condition requires some mental parsing of the booleans whereas the original can be analysed one at a time.

I'd say I prefer the original.

_flux · 2 years ago
Using % vs comparison and reset was probably more efficient with the compilers of the time; might still be.

Also I doubt everyone would agree that the one exit condition is more clear. For example, if I know that if e->inuse is 0 it will continue with the next round. Arguably it's more difficult to understand that from the single combined expression—because it isn't so: if !e->inuse but e == ent->client->chase_target, the original will loop but yours will exit.

Though I'm guessing ent->client->chase_target->inuse is probably never 0.

nsteel · 2 years ago
Pretty sure your line 3 and the original lines 3-5 are not equivalent. Check it with `i` entering the loop with value `maxclients->value`.

The best reason not to re-write for style reasons is you break it.

flohofwoe · 2 years ago
Break, continue, return (and arguably even C's goto before variables could be declared in the middle of a scope block) are all entirely normal tools in the structured programming toolbox. How those are used is just personal taste.

Deleted Comment

ycom13__ · 2 years ago
I had to laugh at this https://github.com/ESWAT/john-carmack-plan-archive/blob/mast...

----------------------------------------- John Carmack's .plan for Jan 31, 1997 -----------------------------------------

I went down to the ferrari dealership today with Ann and American with the intention of buying a new f355 as a "sensible" car (in contrast to my other twin turbo monstrosities).

There was an F40 sitting out front.

Umm. Sensible car. F40. Sensible car. F40. Hmmmm.

American played the evil conscience and Ann played the good conscience. For a while. Then Ann got infected by the Dark Side. :-) I bought the F40.

Ok, I now have too many ferraris. I have a plan to fix that. This hasn't gone through all the legal crap necessary yet, but it is my intention to give away my first ferrari as the grand prize of a Quake tournement.

Yes, I am serious.

DO NOT SEND ME ANY MAIL ABOUT THIS! When we have more to say about it, we will make a formal announcement. This would be a good time to start a heated debate in the newsgroups about what the fairest tourney rules would be, though.

The specs:

1987 328 GTS with turbocharged engine. Feature in the january, 1994 issue of Turbo magazine. Made 360 HP at the rear wheels on a chassis dyno. New engine (I melted the first one...), new paint. The interior could use a little work.

I plan to also include enough cash to cover tax and insurance.

spamtarget · 2 years ago
A prospective buyer is coming, you say? Hmm, let's park the F40 exactly next to the gate accidentally.
wantoncl · 2 years ago
As I recall, when Seymour Cray would buy a new car, he'd pick the first car on the left as he entered the dealership.

After 2 or 3 purchases, the dealer habitually put the most expensive car in that spot.

hyperion2010 · 2 years ago
I'll drop my Quake II anecdote here. Quake II was the first FPS I ever beat (at least I think I beat it). I did it over a week in the summer when visiting a friend out of state (never would have been allowed otherwise).

When I started, I had only ever played the original DOOM, so I used those controls, and lo and behold they worked, and I thought nothing of it. At some point as I was playing along, my view suddenly became locked to the ceiling and I was thoroughly confused and stuck. Turns out I had bumped the mouse, and managed to figure out that mouse look was a thing after extended fiddling with the system to try to determine the cause and get back to killing badguys. Needless to say, the game got quite a bit easier after that.

There wasn't internet, neither I nor my friend knew what mouse-look was, we had never seen anyone play a true 3d fps. It is hard to imagine how obscure and alien the interfaces for games are because of how pervasive the knowledge has become.

Glad to see the source code released!

Zambyte · 2 years ago
> Glad to see the source code released!

In case you were unaware, this is actually the source code of the rerelease of Quake II. The source code for the original Quake II has been released for many years[0], along with many of the id Software classics[1].

[0]: https://github.com/id-Software/Quake-2

[1]: https://github.com/id-Software

kibibu · 2 years ago
It's also only the code for the game.dll, which is important for modding but doesn't include the new engine.

If it's anything like the Quake re-release, it's not actually using idTech 2 at all.

ramranch · 2 years ago
In case you were unaware, the source code of the original is included along with the re-release in this repository, as stated in the first sentence of the readme.
epolanski · 2 years ago
You reminded me of the first time I saw a lan full of people playing an fps.

I was at a ComicCon in Rome, Italy, circa 1999, anyway Half Life just hit gold production and released multiplayer demos there were at least 20 people all playing on lan multiplayer half life, with mouses too! Crazy.

I went to many many lan parties since then up to 2005, then online match making killed quakenet and socializing.

mmh0000 · 2 years ago
Oh man! Memories.

Back in 1999, Quake II was the game I played (like, literally the only one). I sunk so much time in QII and I wrote my very first code building a Mod.

I think it's fair to say, Quake II turned me from a computer user into a computer programmer. And set the course for my entire adult life and career.

From my original mod, I learned how to calculate vectors, learn an existing code base, integrate autobuilds for rapid testing.

I also dabbeled in making maps, learning 3rd art, but, quickly realized I am no artist or designer.

Sadly, my version control and backup policies at the time were non-existant and I've lost all my original code.

The next game that really got my attention in the same way was Tribes 2, the scriptings and modding you could do there was truly amazing.

mmh0000 · 2 years ago
In my endless files, I just found the binary of my mod.

https://xn0.co/Xeno-Mod_1.9_Setup.exe

Because I'm sure everyone on HN just downloads execs from a random internet source and runs them!

But if you have the OG QII, are curious, it is safe to run.

koolba · 2 years ago
No way I’m running that unless you publish it on NPM.

Then you could even do: npx run quake-2-xeno-mod@1.9

mulmen · 2 years ago
> Because I'm sure everyone on HN just downloads execs from a random internet source and runs them!

Not true, some of us have JavaScript disabled.

giantrobot · 2 years ago
> Because I'm sure everyone on HN just downloads execs from a random internet source and runs them!

...should I not?

klipklop · 2 years ago
What does your mod do?
mentos · 2 years ago
Tribes 2 was my first taste of modding, the game holds a super special place in my heart too. Then came Ultima Online emulators Sphere and RunUO that turned me from a gamer into a programmer too.
n4te · 2 years ago
I had a lot of fun making the HaVoC Tribes 1 mod. It was really cool seeing there was 1000 people online playing my mod at once.
mcronce · 2 years ago
Rune was mine. A buddy and I got into level design, and I got into modding along with it
ljm · 2 years ago
Tribes 2 and Unreal Tourney were childhood faves.. when I played something other than CS 1.6
anotherhue · 2 years ago
Discovering the drop down console was a revelation.

An homage: http://guake-project.org/

bee_rider · 2 years ago
I wish I could find a use for that, it is a funny idea. Unfortunately in a world where all of you stuff is in terminals, having one special drop down one is less useful.
AdmiralAsshat · 2 years ago
The Windows terminal now has a quake-style dropdown mode by default.
karim79 · 2 years ago
Incredible and just sent me way back to the nineties. To be fair, I'm talking about the first Quake game here. I had a PC rig on my bedroom floor which as I recall was a Pentium 166MMX, and my friend came over with a similar machine which was a bit faster (a 233) perhaps. No LAN cards insight.

Using one of my dad's ancient parallel cables and fooling Windows into thinking it was a LAN connection, which worked well enough, we played for days, until it got kind of tedious. So we then got into the whole modding scene - not creating anything, but downloading and testing the things which were out there. I will never, ever forget Girobot and KQP (Killer Quake Patch).

The Girobot bots were a force to be reckoned with when they didn't get stuck in the terrain. It was KQP which added all kinds of crazy mods/weapons/bot systems to the game that was the real gold. The Vampire Gun left us in stitches every time someone was hit by it, because it basically guaranteed a slow but not too slow death in which the hit player would crumble into little chunks of flesh. I miss the nineties very, very much.

jasonb05 · 2 years ago
"Girobot", do you mean the "Gyrobot" by "Gyro Gearloose" [1]?

Also, I believe KQP had ZeusBots included (for reference).

[1] https://github.com/Jason2Brownlee/QuakeBotArchive

samplatt · 2 years ago
ZeusBots were where it was at, for me.

First few computers were too slow to run Quake effectively, but then I had a Duron 900 (they ran slow AND hot!), bought a 'PC Powerplay' magazine that came with a CD full of quake mods, and a map with 20-40 of ZeusBots worked just fine!

karim79 · 2 years ago
Thank you for the correction, sorry, it has been forever. The link is fantastic, thank you for that as well.
hypercube33 · 2 years ago
I had 8gb of downloaded-over-modem and sometimes T1 mods, maps, skins for quake 2 multiplayer. I miss the mods so much.
autoexec · 2 years ago
The endless amounts of user created mods, maps, and skins many of us enjoyed in early days were killed off so that game publishers could make a fortune charging us for a small selection of sanctioned DLC. In the process they killed off an entire ecosystem that grew up around user created content. Forums, review sites, file hosting, and generations of new talent who found their love of programing by creating mods all lost due to greed and a desire for control.
dmclamb · 2 years ago
my dad's ancient parallel cables

With a null modem? I had same setup with my college roommate in our apartment. This was mid 90s, so it was Doom 2 and other FPS from that time.

Great memories.

karim79 · 2 years ago
Indeed. My brother and I played starcraft using the same trick. When the fight started to escalate and there were hundreds of units fighting, the lag got really really bad, but it worked well enough that we kept coming back to it. That and Warcraft 2, Heretic, Hexen, all the rest. The best days in gaming IMO.
johnwalkr · 2 years ago
Quake 1 (original DOS version only) supported null modem, but Quake 2 didn't -you had to use a null modem with Windows 95 dial-up networking, which was a bit more tricky to setup.
jandrese · 2 years ago
I saw grumbling elsewhere about how the re-release doesn't include a Linux version, but here they are with the source and it claims to be tested with clang. Big props to iD for sticking to their principles.
generichuman · 2 years ago
I wonder why they released the source code for this one. Is it purely because of the principles, or did they have a legal requirement since the old one is also GPL licensed?

I'm assuming they don't have legal requirements since they owned the old code anyway.

hadlock · 2 years ago
John Carmack has been fairly vocal about releasing the source code for his games, particularly the Quake/Doom series for as long as I can remember, going back to at least Quakecon 2004 during one of his keynotes there. I think at the keynote when they announced Doom 3, he even talked at length about eventually releasing that engine as open source, I think in 7 years (which eventually did happen). He is not the flag carrier for open source games, but he may be one of the most consistent at following through on open sourcing their base engine over the last 20 years. Before leaving Meta as CTO he was speaking about making sure the GO and Quest 1 were usable in offline mode with sideload capability when they become EOL'd. In my view this release of code is not at all surprising in the least.
tekchip · 2 years ago
ID has traditionally release code for their games when they reach...I forget, 10 years, or end of official support or something. This is just continuing the tradition of giving their games the longest of tale by opening them up. Check it out. https://github.com/id-Software
fineIllregister · 2 years ago
I remember in one if Carmack's last Quakecon keynotes, after the acquisition, he was talking about future source code releases. He didn't say anything definitive, but he did tell a story where he spoke with a Zenimax lawyer, and they told him how important the GPL releases were.
kibibu · 2 years ago
This is not the engine code, this is the game code that was released even prior to Quake 2 being GPLd.

    -----------------------------------------
    John Carmack's .plan for Dec 11, 1997
    -----------------------------------------

    The Quake 2 public code release is up at:

    ftp://ftp.idsoftware.com/idstuff/quake2/source/q2source_12_11.zip

    This source code distribution is only for hard-core people that are
    going to spend a lot of time pouring over it. This is NOT a
    how-to-make-levels-for-q2 type dsitribution!

    This should keep a bunch of you busy for a while. :)
https://github.com/ESWAT/john-carmack-plan-archive/blob/mast...

jsheard · 2 years ago
They shipped this version on all of the major platforms, and I'm reasonably sure that Nintendo and Sony both use Clang/LLVM for their SDK toolchains nowadays. Maybe Linux was on their mind but getting it to build for modern consoles will have been the main motivation.
fretn · 2 years ago
This is only the game code and not the engine source code, or am I missing something ?
aaptel · 2 years ago
Yes it seems to be missing the rendering code. game.h defines a generic list of imported function pointers which have no implementation in the repo.

Deleted Comment

wg0 · 2 years ago
There are so many games that aren't being sold anymore and aren't playable on modern software/hardware stack.

I wish there were a law that if you don't release a patch for your software for 20 years to make it workable for newer platforms, you've to release it as open source from the perspective of cultural significance.

hoten · 2 years ago
What are people's thoughts on using "_t" as a suffix for types in C/C++, as this source does? My understanding is that it is technically reserved for language defined types, but I haven't come across a reasonable alternative (and having no suffix makes for odd code, for example a custom type for a "viewport" is better imo as "viewport_t viewport;" than "viewport viewport;")
uxp100 · 2 years ago
I don’t believe that’s a c language thing, but a posix thing. anyway, in my own code for myself I do it, but it is frequently forbidden in coding standards I’ve worked under (even in a non posix environment) and it doesn’t rise to the level of pushing back on it usually, I’ll name types however the style guide wants, even if it’s worse. t prefix, worse. The whole word typedef, worse.
LexiMax · 2 years ago
From what I understand, it's POSIX that reserves the _t suffix, not C.

That being said, I picked up the _s/_t habit from working on idtech codebases, and decided that I'm fine with my own C codebases forever having a "not POSIX compliant" stamp on it, whatever that means in practice. For C++ I just use InitialCamelCase.

genocidicbunny · 2 years ago
Probably not everyone's cup of tea, but I tend to use CamelCase for types, and under_scores for variables. It does result in constructs like 'Viewport viewport;' but at least it's easy enough to tell that Viewport is the type.
cpeterso · 2 years ago
Mixing CamelCase type names and snake_case variable names feels chaotic to me, but it’s the standard coding style for Python, Ruby, Rust, and Google’s C++ code. I wonder who used it before Python.
bentcorner · 2 years ago
It's useful when you have an IDE that doesn't help you very much and you need to know what a thing is just from what code is in front of you.
OnACoffeeBreak · 2 years ago
Where I work the style guidelines for C specify to use "_type". Interestingly enough, the huge code base for embedded products with a custom OS does not rely on <stdint.h> types for fixed-width integer types: "uint32_t", for example. Instead, a company-wide header defines "uint32" etc. without the "_t" suffix. I don't know what guided that decision.
flohofwoe · 2 years ago
For a very long time the fixed-width types in stdint.h were not universally available, or in other headers, especially Visual Studio trailed behind. I guess this problem has stuck even after all C compilers caught up with C99.
flohofwoe · 2 years ago
It's totally fine and legal. Only POSIX reserves the _t for types, but POSIX is not the C standard (but even when writing code for POSIX, it's not like POSIX changes much these days, so unexpected type collisions because of POSIX updates will be very unlikely).
badsectoracula · 2 years ago
I've being using it for a long time and the only time i had a problem was when i ported an old 3d game engine of mine to Mac OS X and i had a type "key_t" which conflicted with some Mac header.

I just used the preprocessor to #define key_t mykey_t (or something like that) after the Mac-specific headers in the couple of files where the conflict was and never thought about it again.

cxr · 2 years ago
Recently I was musing to myself about adopting the convention `func_r`, to denote "the thing that the function `func` returns".

Why spend the energy trying to think up two names (one for the function you're writing and one for what you should call the type of its result)? It's also amenable to preprocessor macros, if you're so inclined.

andrewmcwatters · 2 years ago
You're not supposed to do it, but anyone who works with the Quake family of engines is used to it, so when in Rome...
djbusby · 2 years ago
I've seen that suffix on loads of C stuff from ages ago. All stuff that circa 90s codes (some older)
snvzz · 2 years ago
I use and prefer capitalization for typedefs.

Cube instead of cube_t.