QuakeC puzzles

Discuss programming in the QuakeC language.
Post Reply
OneManClan
Posts: 247
Joined: Sat Feb 28, 2009 2:38 pm
Contact:

QuakeC puzzles

Post by OneManClan »

[EDIT: I originally used 'dremove()' below, which I forgot is specific to CustomTF. I've changed the 'dremove()' to 'remove()' which is essentially the same thing. Sorry for any confusion ('dremove' is just 'remove()' with extra code to check that the entity hasn't already been removed, and isn't a player etc)]

QuakeC Puzzle 1: 'self' issues

Code: Select all

void () Func_1 =
{
	local entity foo;
	foo = spawn();

	foo.think = Func_2;
	foo.nextthink = time + 1;
};

void () Func_2 =
{
remove(self);
	Func_3();
};

void () Func_3 =
{
// Q: who is self?
		
};
=========================================
QuakeC Puzzle 2: 'find'

Code: Select all

void () Func_1 =
{
	local entity foo;
		foo = spawn();
		foo.classname = "puzzle";
		.
		.

};

void () Func_2 =
{
local entity e;
e = find(world, classname, "puzzle");
remove(e); // Q: did we just delete foo?

};
Last edited by OneManClan on Fri Nov 18, 2011 4:44 pm, edited 4 times in total.
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Re: Quake puzzles

Post by ceriux »

puzzle 1 is either no one or foo right? lol cause foo was removed.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: QuakeC puzzles

Post by Spike »

1:
I don't know what's special about dremove, so I can't answer that one fully.
self refers to the entity spawned in Func_1, but either it has been removed, or its think function has been set to cause it to be removed. Either way, you can still assign to its fields... but you really shouldn't do so.

2:
the dremove call removes (I assume, I've not seen the dremove function itself) an entity which was probably spawned inside Func_1. If Func_1 was called multiple times then it'll remove just one of those entities (per time Func_2 is called). If Func_2 is called more than Func_1 was called, the whole thing will break.
I'm careful to not say that "it removes 'foo'" because, technically, it doesn't. Once Func_1 returns, foo leaves scope, and nothing is known as that particuar 'foo' any more.
So no, it doesn't 'remove foo' because 'foo' no longer exists anyway, but the entity that foo refered to does still exist, and its that entity which is removed, rather than simply 'foo'.
Many times you'll see someone refer to it as though Func_2 does remove Func_1, quite simply they're being lazy, and are technically incorrect. However that distinction is not a major one, and is usually not actually relevent as any experienced programmer will know what was actually meant even if what is said is a lie, so its quite common to say it, or even think that way. Just remember that its not actually true when you do have multiple instances of 'foo' entities at the same.
WickedShell
Posts: 24
Joined: Mon Feb 14, 2011 5:16 am

Re: QuakeC puzzles

Post by WickedShell »

This seems like a good chance to clarify. I've been operating on the assumption that spawn() is essentially malloc(sizeof(struct_entity)), and that remove() is essentially free(). Is there anything fundamentally wrong with looking at it this way?
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: QuakeC puzzles

Post by Spike »

aye, spawn as malloc and remove as free is basically how it is. with the 'entity' type being just a pointer to it.

an entity can get reused by spawn() 2 seconds after being remove()d, and it is considered valid to be able to read or even write the fields of an entity that was freed, if only because the engine is to lazy to block it and too much code already does such that the engine couldn't block it and still be used. Memory reuse is a problem in C, too, but one that is more likely to result in page faults, so yeah, there's no real difference.
Qrv
Posts: 45
Joined: Thu Oct 20, 2011 7:43 am
Location: Stuck in a Slipgate.

Re: QuakeC puzzles

Post by Qrv »

Puzzle 1 :

I'd be inclined here to say self = world, as theres no entity.

Puzzle 2 :

It'l remove the entity spawned earlier. Although not known as foo by that point, that entity should be removed.


Although both functions say "local entity", from my own experience, that means nothing in regards to programming terms. I posted code in another thread that uses "local entity" to spawn bubbles to help Nahuel with something, although spawned locally, they seem to exist globally.
I'm looking for a Mapper, Modeller/Animator and a Sound effect/Music person, to work on an exciting project. PM Me here, or catch me on IRC for further info.
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: QuakeC puzzles

Post by frag.machine »

Qrv wrote:Puzzle 1 :

I'd be inclined here to say self = world, as theres no entity.

Puzzle 2 :

It'l remove the entity spawned earlier. Although not known as foo by that point, that entity should be removed.


Although both functions say "local entity", from my own experience, that means nothing in regards to programming terms. I posted code in another thread that uses "local entity" to spawn bubbles to help Nahuel with something, although spawned locally, they seem to exist globally.
That's correct. The local entity means that once outside the function, the entity reference is lost, but not the entity itself.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
necros
Posts: 77
Joined: Thu Dec 16, 2004 10:32 pm

Re: QuakeC puzzles

Post by necros »

1. self is foo
remember, a removed entity's pointer is still locked to the entity for ~2 seconds, afterwhich the entity pointer is freed for use with another entity. if you spawned another entity 3 seconds later, it would probably take this edict slot, and self (if it was called later on) would be this new entity.
also, not all entity fields are cleaned out at remove() time, only obvious ones like .model, .solid, maybe a few others. if you use an engine that displays bboxes, you can watch discarded entities who have bboxes accumulate at the origin (0,0,0).
spawn() is the only point where all fields are cleared.
this is important because if you had something like:
self.owner = someEntity;

and then you removed someEntity and then later did a check:
if (!self.owner)

it would return true.

2. yes
this one is straightforward.
Post Reply