Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Sign in to follow this  
entryway

strange spawning cube

Recommended Posts

Graf Zahl said:

... which will only work in ports that don't fix such bugs.

And don't provide compatibility options for things they "fix".

Share this post


Link to post

Compatibilty options are for things that got changed but break some real world maps.

All this would break would be some joke effects so why add more baggage?

Share this post


Link to post

why not? zdoom breaks backwards compat more and more every day, but going in the opposite direction and (ab)using features and glitches it no longer supports needs to be heavily frowned upon?

Share this post


Link to post

What *is* the definitive cause of this problem, anyway? I've never seen an explanation for it and haven't dug far enough into the code to realize the ultimate cause for it.

Share this post


Link to post
Quasar said:

What *is* the definitive cause of this problem, anyway?

Yeah, Gez should add explanation on wiki :)

Share this post


Link to post
dew said:

why not? zdoom breaks backwards compat more and more every day,



Bullshit.

The most broken ZDoom versions were 1.23 which are 10 years old now. If somebody reports a serious compatibility issue it will get addressed.

But if someone reports a glitch that at best can be abused as some oddball effect I'm sorry, I don't care. I find it more important that the engine works like a sane person would expect it to behave (i.e. spawn a monster at the destination in this case.)

dew said:

but going in the opposite direction and (ab)using features and glitches it no longer supports needs to be heavily frowned upon?



If people feel the need to abuse every bug they encounter they do not deserve any support in my opinion. You have to draw the line somewhere and for me it's at the point where somebody says 'Gee, I found a bug in Doom. I have to exploit it in my next map.'

Share this post


Link to post
entryway said:

Yeah, Gez should add explanation on wiki :)


Thanks for volunteering me.

Anyway:

void A_SpawnFly (mobj_t* mo)
{
    mobj_t*	newmobj;
    mobj_t*	fog;
    mobj_t*	targ;
    int		r;
    mobjtype_t	type;
	
    if (--mo->reactiontime)
	return;	// still flying
Oooh, it's entirely relying on reactiontime reaching 0 to know when it's over. So... How does it compute reactiontime?
    // spawn brain missile
    newmobj = P_SpawnMissile (mo, targ, MT_SPAWNSHOT);
    newmobj->target = targ;
    newmobj->reactiontime =
	((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics;
Ah yeah. What if targ->y == mo->y ? Then we got (0 / newmobj->momy) / newmobj->state->tics, so 0 divided by some irrelevant value twice, which makes it 0.

Given that they use --var and not var--, it's turned into -1 on the first time, and then you've got to cycle through all the negative numbers before it overflows to positive and starts counting down to zero. Since reactiontime is an int, in a 32-bit codebase, that means it'll take over four billion tics to reach 0. Only about 1420 days if I'm not fat-fingering calc.exe too badly.

Wait, that's not tics. That's calls to A_SpawnFly. It's called every three tics. So, just under 12 years to wait.

Share this post


Link to post

Wow that IS pretty screwed up. Why does it work in the general case? It seems to me it ought to be based on a proper Euclidean distance measurement and not just the y coordinate >_>

Share this post


Link to post

It works in the general case because P_SpawnMissile has scaled its momy accordingly to the Y distance to run.

Which means if I'm not mistaken that in this particular case, reactiontime is equal to 0 / 0 / 3. We're lucky C is super lazy and goes all "oh, it's a zero, I don't have to look at the divisor to know the result" in that first division. (At least, I assume that's what happens. I'm not looking into how the C compiler works.)

Share this post


Link to post
Quasar said:

Wow that IS pretty screwed up. Why does it work in the general case? It seems to me it ought to be based on a proper Euclidean distance measurement and not just the y coordinate >_>

I guess that's because of performance concerns back when Doom was developped. Or maybe to avoid having to implement a square root function on fixed_t. Probably same reason why P_AproxDistance is named as such and doesn't calculate the correct distance. Is fixed_t (instead of floating-point) still required in Doom for performance? I hate it otherwise, along with all those trigonometric tables, especially tantoangle.

Share this post


Link to post
Gez said:

We're lucky we do not crash because momy will also be zero, logically enough, and we're dividing by it. Oops!

Probably that's because doom crashes if spawned cube is blocked and not able to move immediately after spawning (I checked, but I do not remember). I had a headache because of this crash at least with two Eternal's projects.

Share this post


Link to post
printz said:

I guess that's because of performance concerns back when Doom was developped.

No. It's part of A_BrainSpit, so it's not a time-critical part. It's just something that's called once every few tics in a single map in the game. P_SpawnMissile makes heavier computations a lot more often.

printz said:

Or maybe to avoid having to implement a square root function on fixed_t.

Didn't stop P_SpawnMissile.

printz said:

Probably same reason why P_AproxDistance is named as such

No, it's named as such because they can't spell and they don't know there are two 'P' in "approximate".

Share this post


Link to post
entryway said:

Probably that's because doom crashes if spawned cube is blocked and not able to move immediately after spawning (I checked, but I do not remember). I had a headache because of this crash at least with two Eternal's projects.

Heh, I do not remember, but looks like I added a few checks to prboom-plus in 2009 :)

  // spawn brain missile
  newmobj = P_SpawnMissile(mo, targ, MT_SPAWNSHOT);
  
  // e6y: do not crash with 'incorrect' DEHs
  if (!newmobj || !newmobj->state || newmobj->momy == 0 || newmobj->state->tics == 0)
    I_Error("A_BrainSpit: can't spawn brain missile (incorrect DEH)");

  P_SetTarget(&newmobj->target, targ);
  newmobj->reactiontime = (short)(((targ->y-mo->y)/newmobj->momy)/newmobj->state->tics);

Share this post


Link to post

So, and I don't think it surprises anyone that this entire mess of calculations was entirely dumped in ZDoom and replaced by something sane that doesn't break when someone shouts 'boo', because it made it nearly impossible to use the spawn cube code for anything else than just the spawn cubes (littered with some compatibility code, of course so that Dehacked trickery doesn't break.)

Share this post


Link to post
Gez said:

Which means if I'm not mistaken that in this particular case, reactiontime is equal to 0 / 0 / 3. We're lucky C is super lazy and goes all "oh, it's a zero, I don't have to look at the divisor to know the result" in that first division. (At least, I assume that's what happens. I'm not looking into how the C compiler works.)

Shouldn't that expression either:

1. crash the software (that's what seems to happen under Dev-C++ compiles which I just used to test this).

2. result in #IND or #NaN (I'm not sure, but 0/0 is indeterminate)?

In any case, testing printf("%d\n", 0/0); or any variation thereof resulted in a crash in Dev-C++, with a compiler warning before that.

EDIT: that's just dumb, #IND or #INF only happens with floating point... which vanilla Doom naturally doesn't have. Otherwise it's a crash.

Accepting 0/0 = 0 is mathematically incorrect.

Share this post


Link to post

If you want mathematical correctness, go buy Mathematica or something. The plain old C standard out of the box is not what you want.

Did you know that integers can't be expressed past a given range? That floating point values lack precision? That dividing by zero shouldn't result in a crash? (I mean, equations on paper do not crash; and neither do brains when they think about it.)

Specialized software uses a lot of code to be more correct, or at least more precise.

Share this post


Link to post
Gez said:

If you want mathematical correctness, go buy Mathematica or something. The plain old C standard out of the box is not what you want.

Did you know that integers can't be expressed past a given range? That floating point values lack precision?

I wasn't talking about size limitations, but about operator semantics. C is mostly accurate. It avoids having the power operator too, thus averting any power-of inconsistencies (even then, they can make it right-to-left). For arbitrarily large or detailed numbers, "double" is acceptable. If that fails, some implementations might allow even longer doubles.

That dividing by zero shouldn't result in a crash? (I mean, equations on paper do not crash; and neither do brains when they think about it.)

Well, in floating point at least, dividing by zero doesn't crash the application and results in "infinite" or "indetermined" which is exactly like in paper mathematics (though I'm not sure if you can do further operations on those symbols, but who knows?). Other indeterminate operations might return NaN instead. So I really find C accurate. Even the "and" / "or" operator precedence is correct ("and" first) because it works like the "+" notation for "or" and "*" (dot) notation for "and".

Also arrays in C begin with 0. In MATLAB they always begin with 1. On paper, I've often found it more practical to start discrete signals with index 0, not 1 like in MATLAB.

Share this post


Link to post

Heh, so A_SpawnFly doesn't even use P_ApproxDistance but more like P_CowHorseAndCamerLuverDistance() ? :-p

Share this post


Link to post
Maes said:

P_CowHorseAndCamerLuverDistance() ? :-p

Missing operand there.

Share this post


Link to post
printz said:

Missing operand there.


Not that it would matter much.

Share this post


Link to post
Gez said:

No, it's named as such because they can't spell and they don't know there are two 'P' in "approximate".

Redundant extra letter is redundant.

Share this post


Link to post

Not at all. It changes the way the A is pronounced. "Aproximate" would sound like "ape roximate". "Approximate" sounds like "App roximate".

Share this post


Link to post
Gez said:

Not at all. It changes the way the A is pronounced. "Aproximate" would sound like "ape roximate". "Approximate" sounds like "App roximate".

Oh come on, English words don't play by pronunciation rules.

Share this post


Link to post

Most programmers just have terrible spelling.

A few of Carmack's other SNAFUs:

  • defered
  • consistancy

Share this post


Link to post
Maes said:

Ghoti, anyone?

"Ghoti" blissfully ignores some of the pronunciation rules that actually exist in English. -gh can only be silent if it is the ending of a word; -ti- will only be 'sh' if it is part of the -tion/tian suffix (that's pretty much an import from the French rule about -tion/-tien, but there the t gets pronounced like an s instead of the ti pronounced like an sh).

Quasar said:

Most programmers just have terrible spelling.

A few of Carmack's other SNAFUs:

  • defered
  • consistancy


I guess it was for consistancy that Randy called his implementation of the Hexen ACS store "defered scripts". ;)

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
×