Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-8081-

Game logic

Name: Anonymous 2010-05-16 5:18

How the fuck do they code games so that everything moves smoothly and at a consistent rate regardless of the speed of the machine you run it on, and still have tons of shit interacting with each other somehow?
Maybe I need to find a good open-source candidate to have a look at.

Also, I wish I knew the correct terms to describe what I'm talking about.

Name: Anonymous 2010-05-16 5:20

Logic simulation doesn't usually work with concrete ticks but delta-time.

Name: Anonymous 2010-05-16 5:51

>>2
If the game is running on delta-time at one frame every two seconds wouldn't the physics differ from a computer running one frame every one second? Say the velocity is recalculated every cycle of the game loop based on acceleration- if fps = 2.0, this is calculated twice as often as fps = 1.0- resulting in a desync between the two machines even if the input is identical.

Name: sage 2010-05-16 5:55

>>3 yes, it would. So what?

Name: Anonymous 2010-05-16 6:00

>>4
For say, a multiplayer game- how is this dealt with? And also if the computer is horrendously laggy, (one frame every two minutes)- you still wont be able to composite a video after recording a couple days of frames because every frame will be completely wack, (x += dx * timedelta) would make you fly through walls etc with a timedelta of 120.

Name: Anonymous 2010-05-16 6:07

>>5
Calculate velocity on server.
Send to clients. While no velocity is known(server didn't send it to client yet), client can try to calculate velocity by it, but after receiving use received values.

This is done for example in TeeWorlds. In freeze mod for example - when your tee is frozen, if you press jump client will render jump, but after receiving from server that tee actually never jumped, jump will be reverted.

Name: Anonymous 2010-05-16 6:08

>>5
For large time scales nothing is expected to be in sync. Over larger periods synchrony is maintained however. You're assuming that deltas are cumulative and sequential. This is a mistake.

Name: >>7 2010-05-16 6:10

For large time scales nothing is expected to be in sync.
should read: For small time scales ...

Name: Anonymous 2010-05-16 7:56

>>1
Either using delta time as others have said, or by limiting update speed.

The second method's good for consoles since the hardware's known and there's no real danger of everything going wrong, physics engines will perform a hell of a lot better too.

Using delta time is great for varied hardware though, even if physics engine's don't like it. It can become a problem in some cases though, for example, if delta time ends up getting too high intersection testing will fail with fast moving objects, and you'll need to instead calculate if something would hit at a given time.

Name: Anonymous 2010-05-16 12:06

>>9
if delta time ends up getting too high intersection testing will fail
Most good physics engines should calculate intersections at increasing granularity, preferring vector intersection equations over if x1+vx1 >= x2 as collisions become more likely (e.g. after bounding-box tests, pythagorean distance tests and simple directional vector tests have all returned true).
Even with high deltas, logic should say that if one object ended up on the other side of another after an update, it's pretty likely that they should have collided.

Name: Anonymous 2010-05-16 15:31

>>10
You can even get your 3D hardware to do the test.

Name: Anonymous 2010-05-16 18:41

>>11
But I don't have any drivers for it! D:

Name: Anonymous 2010-05-16 18:53

Fixed tick engines are only optimal for fps=ticks. If the machine is faster, you're wasting power.

If the machine is slower and the programmer had a clue (50% chance, depends on whether the problem was evident enough), you are wasting power calculating ticks that you won't show, and also what you show won't be as smooth as possible because unless your fps divides the tick rate exactly there will be timing jitter.

If the machine is slower and the programmer was retarded, the game speed will actually slow down. As incredible as it seems, some people still have the guts to publish big titles with this problem (see below).

As other people have explained, with variable ticks network replication (and demo playback, same thing) works in a client-server manner where an authoritative server sends absolute (not relative) updates. Usually these updates come at low frequencies (10-30/s is typical), the client buffers two of them and lerps (interpolates) between them to generate smooth results (this adds 1/freq latency). If it doesn't interpolate (by design or due to network issues), it'll try to extrapolate and then correct when a new update arrives. Some single-player games do this too to decrease CPU power, as lerping is cheaper than fully calculating everything (and you only need to lerp stuff that is in the vicinity of the player).

Of course sending full updates is more expensive than sending inputs. Fixed tick engines can get away with sending just input and can support a ton of players since an human can't generate that much data, plus they're unaffected by the number of objects in the game world. However they usually don't support mid-game joining (this requires sending the current state wholly). These characteristics make them ideal for real time strategy games. Note that you can lerp in these engines too and present more frames than ticks (for animations and effects that don't affect the game). This requires programmers who aren't lazy bastards though.

As for delta times getting too high, engines usually impose a maximum delta time to process. This is good practice anyway to avoid other kind of problems.

Now, from memory:

* Doom (Doom2, etc): fixed ticrate 35Hz, no lerp, will run multiple ticks to maintain speed, demos and network only use user input

* Quake: variable ticks (1 tick per rendered frame), lerp for demos and network, sends full updates, client input has latency but camera angle is short-circuited, maximum tick is 100ms (therefore game will slow down below 10fps)

* QuakeWorld: variable ticks, lerp for demos and network, client input is processed on the client immediately and corrected if the server disagrees later

* Quake2: same as quakeworld, but server ticks run at 10Hz always, even on single player. Has noticeable latency when firing weapons for this reason, even when running at 1000fps. Timing changed from doubles to integers representing milliseconds

* Quake3 (and infinite derivates including MoH, CoD and their sequels...): same as Quake2, no limits (server runs at 20Hz by default, 40Hz on Quake Live), maximum tick is 200ms (full speed from 5fps and up), some physics are run at 16fps at a minimum (will run multiple times for tick if it's running slower)

* Doom3: worst of all worlds, 62.5Hz fixed ticrate (16ms/frame) and sends full updates, original plan was not to, but bugs caused the game to desynch

* GoldSrc/Source engine (modern versions, based off Quake1): same as QuakeWorld mostly, but also client-side prediction for some actions such as firing weapons, and lag compensation (server moves stuff to the places it was when the client did the action). Client-side prediction is for cosmetic effect only, server always has the last word. The result is that weapon spray and blood effects will differ between clients and server.

* Unreal Engine (U1, UT, UT2K3, millions of derivatives): Variable ticrate, lerping and prediction; changed a billion times already. Uses float time.

* StarCraft: fixed ticrate, selectable, 23.8Hz at maximum game speed (42ms frames), 15fps at normal speed. Might batch inputs together to lessen the network load (of course mouse pointer and screen scroll are fully client-side and can run faster than game speed).

* Diablo 1 and 2: fixed ticrate, 25Hz. Network code in Diablo1 is a best of its own, in Diablo2 it's just client/server. In Diablo2 the mouse pointer can be drawn as fast as possible between game updates (however it's not a hardware cursor) - same as SC.

* Serious Sam (& Second Encounter): Variable ticrate, uses player input for network synchronization and demos. Does send entire state when a new player connects. Clients are sent updates as fast as the server is rendering, the server framerate sets the ticrate (so a fast server can overwhelm a slow client, because clients have to process all of the updates even if they can't render them). Quite bizarre but runs really well in practice as long as the machines are within a reasonable range of performance. Allows hundreds of monsters on view while using modem bandwidth. Uses floats for time.

* Command & Conquer and sequels: Fixed ticrate with no speed control (slow fps = slow game, on networked games one slow client will slow down everybody). Game speed just means "minimum delay between tics" (just a dumb fps cap). Fastest game speed meant "as fast as your machine can process it". At some point the speed setting was removed and the limit set at 30Hz. Even some of the recent 3D games lacked speed control, so if your graphics card couldn't render them at 30fps, they would slow down. Pretty terrible, I remember moving the camera away to barren zones to make the game progress faster on occasions. No wonder EA bought them, they're made for each other.

* A lot of console games: fixed ticrates at the speed of the corresponding TV system, usually 60 or 30Hz. Lazy PAL releases run 20% slower at 50 or 25Hz. This happens even today.

* Some console games (most Wii games, incl. Super Mario Galaxy and Zelda whatever): same as above, but to keep the same speed on PAL, run two ticks every 5 frames. This causes a noticeable "jump" 5 times a second, looks pretty bad if you're looking for it. Fortunately you can set it to output 60Hz for compatible monitors.

My experience is that a variable ticrate engine (with lerping for clients when networking) is well worth it for smoothness and feels much better compared with a fixed ticrate engine even when rendering at its optimal rate. This might be because timing is pretty sucky on PCs though (console games that are hardlocked to the screen refresh rate are perfectly smooth too). In some games I mentioned the use floats or millisecond-integers for timing. This is important because the difference is actually noticeable (with milliseconds you get about 6% timing jitter at 60fps, and 12% at 120fps). It's not terrible (most people won't notice) but I'd rather have better precision.

Name: Anonymous 2010-05-16 19:09

>>12
Then download some.

Name: Anonymous 2010-05-16 19:19

>>14
There aren't any GNU/free ones. :<

Name: Anonymous 2010-05-16 19:28

>>13
Your post was coherent, helpful and interesting.

Name: Anonymous 2010-05-16 19:28

>>15
1. Quit being a faggot.
2. Download some drivers.

Name: Anonymous 2010-05-16 20:32

>>15
Are you one of those lobotomized Mac switchers who don't understand the GNU/Linux scene? Stop being a worthless bitch and write your own drivers.

Name: Anonymous 2010-05-16 20:34

>>18
DRIVE MY ANUS

Name: OP 2010-05-16 20:38

>>13
Whew, thanks for writing all that up for me.

I still need to think about it a lot to wrap my brain around how to write a working example of a game (or just a small system) that does this kind of thing properly.

Any recommended reading would be appreciated.

Name: Anonymous 2010-05-16 20:41

>>13! I LOVE YOU! I LOVE YOUR POST! I BOOKMARKED IT FOR FUTURE REFERENCE! KEEP POSTING!

Name: Anonymous 2010-05-16 21:09

Name: Anonymous 2010-05-16 21:29

>>22
These are 3d rendering engines. For physics, check out bullet(http://www.ohloh.net/p/bulletphysics), newton(http://newtondynamics.com/forum/newton.php), and google(http://www.google.com/search?q=physic%20engine)

Name: Anonymous 2010-05-16 21:50

>>23
Yes, that's true. However most of these include physics and more importantly serve as examples of complete engines which handle the problem in OP. It's funny that the physics engines you list are used by engines I have deliberately omitted.

Name: Anonymous 2010-05-17 1:28

>>13
Someone enshrine this post.

Name: Anonymous 2010-05-17 1:45

>>25

┌──────────┐
│◎◎◎◎◎◎◎◎◎◎│
│◎※◆◇◆◇◆◇※◎│
│◎◆┌────┐◆◎│
│◎◇│┏━━┓│◇◎│
│◎◆│┃>>13┃│◆◎│
│◎◇│┗━━┛│◇◎│
│◎◆└────┘◆◎│
│◎※◆◇◆◇◆◇※◎│
│◎◎◎◎◎◎◎◎◎◎│
├──────────┤
│  SHRINE OF >>13  │
└──────────┘

Name: Anonymous 2010-05-17 2:12


┌──────────────┐
│◎◎◎◎◎◎◎◎◎◎◎◎◎◎│
│◎※◆◇◆◇◆◇◆◇◆※◎│
│◎◆┌────────┐◆◎│
│◎◇│┏━━━━━━┓│◇◎│
│◎◆│┃ >>13 ┃│◆◎│
│◎◇│┗━━━━━━┛│◇◎│
│◎◆└────────┘◆◎│
│◎※◆◇◆◇◆◇◆◇◆※◎│
│◎◎◎◎◎◎◎◎◎◎◎◎◎◎│
├──────────────┤
│SHRINE OF >>13
└──────────────┘

Name: Anonymous 2010-05-17 3:15

>>1
Set int 08 to appropriate frame rate.

Name: Anonymous 2010-05-17 5:02

* A lot of console games: fixed ticrates at the speed of the corresponding TV system, usually 60 or 30Hz. Lazy PAL releases run 20% slower at 50 or 25Hz. This happens even today.

Yeah mario kart dd records page has different charts for 50 vs 60hz

Name: Anonymous 2010-05-17 7:04

>>24
Why did you deliberately omit them?

Name: Anonymous 2010-05-17 8:57

>>30
Nothing to do with the physics engines themselves, but the engines using them which came to mind would make truly poor examples, eg.: blender game engine (w/ bullet) wouldn't answer the question at all.

Name: Anonymous 2010-05-17 10:56

The trick is to use fixed ticks and if the system is fast enough to render more frames you interpolate between the ticks.

Name: Anonymous 2010-05-17 12:16

>>32
You also can (and in fact, should) interpolate if the system is slower.

T = game tick; R = rendered frame

T    T    T    T    T    T
R      R      R      R


Here the ticrate is 30Hz and the rendering is ~20fps for example. If you pick up the nearest (well, previous) tick instead of interpolating, it won't look very good.

However this adds latency, so please make it variable tick (parametric) instead. It's not that hard. For continuous stuff you just multiply velocity by time. For periodic stuff (weapon firing), you have an accumulator where you add the time every frame. If the accumulator's value is larger than the period, you subtract as many whole periods as possible and perform the action that many times, keeping the remaining time in the accumulator.

There are some other fine details but on the whole I don't see how not being parametric would save a lot of work.

Also, read http://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization for an example of a decent design for network replication that doesn't use fixed tics anywhere, presents perfectly smooth motion at any framerate, gives the illusion of no latency, and hides network imperfections (packet loss, timing jitter) rather effectively.

Name: Anonymous 2010-05-17 16:09

>>33
Thank you again, sir.

I'm going to have a look through Ogre3D (or one of the other 2 suggestions) today.

Name: Anonymous 2010-05-18 15:52

>>13,33
Does the final part of this page ("Constant Game Speed independent of Variable FPS") do things the best way ???
http://dewitters.koonsolo.com/gameloop.html

Name: Anonymous 2010-05-18 16:10

>>35
Looks like he re-published it here but I don't think he modified the article in any way: http://dev.koonsolo.com/7/dewitters-gameloop/

Anyways... Looks like he doesn't lerp or anything like that in the game logic.  He only interpolates in the display_game() code ???

Name: Anonymous 2010-05-18 16:19

Anyways... Looks like he doesn't lerp
He does derp though

Name: Anonymous 2010-05-18 18:41

>>35
That's the cheapo way: fixed tic rate, render with time interpolation. It's reasonable, the problem is that it adds latency and the only advantage is that the logic can be a bit simpler (however you lose other desirable features such as the ability to do slow-motion properly).

He says the problem with the right solution ("Game Speed dependent on Variable FPS") is numerical instability. Well, so suck it up and design it correctly so huge errors don't pile up on a reasonable range of speeds, and limit times to that. That's what most properly designed games do. For example most recent Valve Source games are limited to 300fps by default. Most iD Tech 3 games come limited to 85fps, most Unreal Tech 3 are limited to 60 (that's a bit too low, but can be increased and increasing it doesn't cause any problems). Practical experimentation suggest that mathematical precision isn't an issue at all in practice.

Of course badly chosen units + shitty timing functions that have low precision and will return 0 regularly (like the GetTickCount() he suggests) = trouble. Big news.

Name: Anonymous 2010-05-18 20:38

>>38
Ah, so "Game Speed dependent on Variable FPS" demonstrates the right solution?  I've read about the problems with GetTickCount() and some other methods of getting the time (ie. GetSystemTimeAsFileTime and QueryPerformanceCounter in Windows) but I don't recall the article saying which method is actually good to use.  Anything you can tell me about that?  If not then I'll see what Ogre3D or one of the other engines does about timing.

Name: Anonymous 2010-05-18 20:47

>>39
You also forgot rdtsc, but that's not exactly a timer.

Name: Anonymous 2010-05-19 1:45

>>39
QueryPerformanceCounter is probably your best bet. No method is perfect though. rdtsc is a terrible idea that won't work at all: modern CPUs have variable clocks, and on top of that each core might have its own desynchronized counter. A lot of rdtsc-based stuff (mostly games) broke in recent years because of this.

Now, this is something that no soul should ever have to see, but behold: https://hg.mozilla.org/mozilla-central/file/f8a47845a0b8/js/src/prmjtime.cpp

Please see bug 363258 for why the win32 timing code is so complex.
 
     calibration mutex : Win32CriticalSection(spincount=0)
     data mutex : Win32CriticalSection(spincount=4096)
    
     def NowInit():
       init mutexes
       PRMJ_NowCalibration()
    
     def NowCalibration():
       expensive up-to-15ms call
    
     def PRMJ_Now():
       returnedTime = 0
       needCalibration = False
       cachedOffset = 0.0
       calibrated = False
       PR_CallOnce(PRMJ_NowInit)
       do
         if not global.calibrated or needCalibration:
           acquire calibration mutex
             acquire data mutex
    
               // Only recalibrate if someone didn't already
               if cachedOffset == calibration.offset:
                 // Have all waiting threads immediately wait
                 set data mutex spin count = 0
                 PRMJ_NowCalibrate()
                 calibrated = 1
    
                 set data mutex spin count = default
             release data mutex
           release calibration mutex
    
         calculate lowres time
    
         if highres timer available:
           acquire data mutex
             calculate highres time
             cachedOffset = calibration.offset
             highres time = calibration.last = max(highres time, calibration.last)
           release data mutex
    
           get kernel tick interval
    
           if abs(highres - lowres) < kernel tick:
             returnedTime = highres time
             needCalibration = False
           else:
             if calibrated:
               returnedTime = lowres
               needCalibration = False
             else:
               needCalibration = True
         else:
           returnedTime = lowres
       while needCalibration
    

Name: Anonymous 2010-05-19 5:51

>>41
Well, that is complicated and hideous.  I'll just stick with QueryPerformanceCounter for now I guess. I hear it has a few problems, such as "If there's heavy bus traffic, on many, common chip sets, [...] this timer may suddenly jump between one and four seconds forward in time" but it is probably the least shitty solution for now.

And now that I know "Game Speed dependent on Variable FPS" is the correct solution I can work on my little test game to help me get all this sorted out.  Thanks again!

Name: Anonymous 2010-05-19 5:56

>>42
Already found something to help with the random jumps:
http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q274323&;
Programs should watch for an unexpected jump by comparing the change in time as determined by successive calls to QueryPerformanceCounter  with the change in time as determined by successive calls to the GetTickCount  function. If there is a significant jump that is based on QueryPerformanceCounter(), but no similar increase that is based on GetTickCount, then it can be assumed that the performance counter just jumped forward. The code sample at the end of this article demonstrates how to do this.


So I can use GTC to make sure that QPC is in check, which is also simpler than having 3 separate kinds of timers to all have a vote (which is an idea I found on gamedev.net)

Name: Anonymous 2010-05-19 10:14

>>43
Here's a 77-line solution to this large problem we don't want to fix.
-- microsoft.com support

Name: Anonymous 2010-05-20 1:54

programmeur expert

Name: Anonymous 2010-05-20 2:30

>>46
I saw it on /f/, its was really hard.

Name: Anonymous 2010-05-20 18:52

What the hell happened to this thread?

Name: Anonymous 2010-05-20 20:02

>>50
(Some of) the spam was deleted.

Name: Anonymous 2010-05-20 21:39

>>51
Along with half of /prog/'s legitimate posters.

Name: Anonymous 2010-05-20 22:30

>>52
/prog/ has no legitimate posters. But some are more illegitimater than others.

Name: Anonymous 2010-05-20 22:35

>>52
3 posts were destroyed. They probably referred to one of two spam URLs. Was anything legitimate actually destroyed?

Name: Anonymous 2010-05-20 22:52

>>54
I scraped two of them before they got deleted, and they were both linkspam, so probably not. A lot of innocent people seem to have been banned, though:

http://twitter.com/progsnake/status/14389226548
http://twitter.com/Cairnarvon/status/14391272965

A bunch of people are complaining in the IRC channels too. It's all MrVacBob-tan's fault:

http://twitter.com/mrvacbob/status/14389759557

Name: Anonymous 2010-05-20 23:04

>>55
And he still hasn't fixed it

Name: Anonymous 2010-05-20 23:34

Name: Anonymous 2010-05-21 0:47

>>55
Anyone that would post about /prog/ on Twitter has no legitimate cause for being here. Case dismissed, move along.

Name: Anonymous 2010-05-21 1:18

>>55
Oh dear. This is the best example of "two problems" I've seen yet.

Name: Anonymous 2010-05-21 1:23

>>58
Twitter is just a very slow IRC with a saner protocol. And /prog/ without Xarn is no /prog/ at all.

Name: Anonymous 2010-05-21 1:48

>>60
How is it saner? IRC is more compact, more flexible, more secure, easier to scale, considerably more featureful and so on. The only thing twitter has on IRC is being http-based, and that can be interpreted as both good and bad.

Name: Anonymous 2010-05-21 1:50

>>61
Freenode tried to bridge the gap to being HTTP based by not rejecting HTTP connections.

Name: Anonymous 2010-05-21 1:58

>>62
I've seen some really nice IRCDs which when greeted with a HTTP request kindly issue a temporary kline to the user doing the request.

Name: Anonymous 2010-05-21 2:02

>>61
more compact, more flexible, more secure, easier to scale
I don't think you've ever actually looked at the IRC protocol.

Name: Anonymous 2010-05-21 2:05

>>64
I've read the IRC RFC's and various server-specific extensions.

Twitter is most certainly not a suitable IRC.

Name: Anonymous 2010-05-21 2:09

>>65
That's a different question altogether. Stop dodging the issue.

Name: Anonymous 2010-05-21 4:18

>>58
What's wrong with Twitter? It's just a slightly more verbose picoup (pre-fuckup).

Name: Anonymous 2010-05-21 4:25

Shitdang, looks like the framerate will need to be capped somewhere to avoid using 100% CPU.  That's ok though, just need to find a good method of doing that which hopefully keeps the framerate steadier than it is right now.

Name: Anonymous 2010-05-21 4:41

>>13,33
Does this not succumb to rounding error at some point or other? Or do periodic server corrections account for this? Seems like this would only be good for FPS games, where RTS games for instance have way more entities that can't constantly be corrected so a fixed tickrate would be better.

Name: Anonymous 2010-05-21 4:54

>>68
Have you tried using any of the methods described in this thread?

Name: Anonymous 2010-05-21 4:56

>>68
Looks like this is fucking impossible under Windows :|  Guess I'll check how other games/engines go about it

Name: Anonymous 2010-05-21 5:08

>>70
Of capping the framerate? I was mostly reading about the proper way of handling the game loop, which involved not capping anything. In any case, I think I've got it.

Name: Anonymous 2010-05-21 5:45

>>71
Sleep(...)

Name: Anonymous 2010-05-21 6:17

>>73
Yeah, I somehow got the idea into my head that Sleep()'s resolution was not enough.  Then when I was looking for a solution I realized that it would be fine.

Name: Anonymous 2010-05-21 12:43

>>74
sceDisplayWaitVblankStart; VBlankIntrWait

Name: Anonymous 2010-05-22 18:44

>>69
Any answer?

Name: Anonymous 2010-05-22 20:29

>>13
Pretty terrible, I remember moving the camera away to barren zones to make the game progress faster on occasions. No wonder EA bought them, they're made for each other.

I LOVE YOU! I LOVE YOUR POST! I READ IT 5 TIMES! KEEP POSTING!

Name: Anonymous 2010-05-22 21:46

>>76
Try it, let us know. I'm pretty sure you're overestimating the resolution capacity of the human mind.

Name: Anonymous 2010-05-25 8:59

Name: Anonymous 2010-05-30 18:08

"Anus" is a colloquial term for the codan receptacle, an orifice which is necessary for proper development of programmer ability. The anus is very sensitive to suboptimal conditions, meaning you must be careful to take proper care of it to prevent sudden data corruption, or the destruction of the anus altogether. This procedure requires the treatment fluid described in the attached attached document, form hatch sign 42016.† If you are not able to procure sufficient quantities of the ingredients necessary, please unintelligible a supervisor.

To assemble a codan, we generally use the sharp jagged edge of a bottle broken off at the neck coated in several layers of pages from SICP. This gives the codan structural integrity while also allowing it to absorb a surplus of embalming fluid for use in the procedure. Diagram 14 will indicate appropriate settings on the fellatio burner for applying this type of coating

Since even the smallest amount of contamination can result in the codan sparking, spitting, or pulling out, you'll want to wear your safety goggles at all times. Naturally you should do this anyway, but a disappointingly sizeable minority of people feel like they don't have to adhere to the safety protocols that every one of you signed on your first day here. Keep in mind that the deceptive statistical unlikelihood of a life-threatening accident is just that--deceptive. The original formulation of Murphy's Law should be in chapter 2 of your field manuals, and you're expected to memorize it.

After completing all other pre-anusry setup, but before inserting the codan, take care to ensure that the proglodyte is in a stable and comfortable position, so as to avoid such disastrous consequences as having it pass out from exertion. Place your free hand gently on the buttock to help spread it open. The anus will react initially with a slight tensing, followed by relaxation as the codan eases in. An unusual response at this stage should be taken as a sign of insufficient ink application, and the procedure should be aborted. Otherwise, proceed with complete insertion up to the secondary fill line etched into the codan's surface. At this point the proglodyte should experience an intense yet pleasurable stinging sensation as the liquid epoxy literally melts the flesh of the anus and permanently destroys all the nerve endings in the most painful way imaginable.

Once insertion is complete, proceed with vendor lock-in by depressing lever B of the codan, thus allowing it to rotate about a quarter turn clockwise. When the anus looks sufficiently puckered, pull the codan back out until the fastener catches on the tender and vomit-inducing inside lip of the anus. The tertiary fill line (if present) should once again be visible. Allow lever B to return to its neutral position, securing the codan in place, and depress lever A momentarily to initiate satori transfer. For the duration of the transfer, the proglodyte's increases in programming ability will be indicated by an extra set of shark mouth tattoos appearing spontaneously around the nipples, as well as multiple sets of glowing red eyes on the ends of stalks sprouting out of the nose in place of nose hairs. Completion of the transfer is indicated by the proglodyte swallowing its own feet and entering an infinite loop. As a courtesy to others, please immediately disconnect the codan to avoid turning into Heath Ledger with dyed spiceberry facial hair.

____________________
† Ingredients: One liter topical isopropyl, distilled. Four liters Home Depot brand extra strength paint remover. Two liters unionized helium-3. Lilac nectar up to 25ml. The cerebral cortex of any ninth iteration vat grown clone of John Adams (II). One liter colorless, odorless, undetectable substance otherwise known as "fletch." One liter orange juice. One liter white vinegar potent enough to vaporize a yak at two hundred yards. Three liters Stonehenge.
Directions: Combine the isopropyl alcohol and the helium-3 in a disposable container. Defrost the cerebral cortex of John Adams (II) with a hair dryer. NB. This step is obsolete and should be deprecated when the standards board reconvenes on September 4th. Please refer to the attarL Rotate the hair dryer 180 degrees in mid air. Rotate the colorless, odorless, undetectable substance. Combine the orange juice and paint remover. Barbecue the vinegar. Discard the vinegar. Discard the cerebral cortex. Burn down the Stonehenge. Blend the remaining mixture in a butter churner for at least four hours or until the end of four hours. Store in  25cc test tube while rotating counterclockwise.

Name: Anonymous 2010-05-30 18:21

What a colossal waste of time.

Name: Anonymous 2010-05-30 19:29

>>81
What?  I found >>80 to be a delightful exercise in creative writing!

Name: Anonymous 2010-05-30 19:49

Draw/Paint();

Update/Cycle();

Name: Anonymous 2010-05-30 20:55

One word, indirect threaded code, thread over.

Name: Anonymous 2010-11-15 1:30

Name: Anonymous 2011-02-04 9:03

I need to stop procrastinating

Name: Anonymous 2011-02-04 10:07

>>86
PROCRASTINATE MY ANUS

Name: Anonymous 2011-02-04 10:32

hax my dubs

Name: Anonymous 2011-02-04 11:21

>>88
HAX MY ANUS!

Name: Anonymous 2011-02-04 11:55

ANTICRASTINATION

Name: Anonymous 2011-02-04 12:11

ANUSCRASTINATION

Name: Anonymous 2011-02-04 14:09

ramuda karukurusu

Name: Anonymous 2011-02-04 14:59

Let us have a minute's silence for >>13's contribution to /prog/.

Name: Anonymous 2011-02-04 15:54

>>92
ラムダ·クダークルス。

Name: Anonymous 2011-02-04 16:46

Doom and Quake engines are GPL'd.

Name: Anonymous 2011-02-04 16:50

>>95
He said open-source

Name: Anonymous 2011-08-16 22:16

Awesome code. Great size. Looks concise. Efficient. Elegant. Keep us all posted on your continued progress

with any new code factoring or compiler optimization. Show us what you got man. Wanna see how freakin'

expressive, efficient, concise and elegant you can get. Thanks for the motivation.

Don't change these.
Name: Email:
Entire Thread Thread List