how do i set a global random?

Discuss programming in the QuakeC language.
Post Reply
hondobondo
Posts: 207
Joined: Tue Sep 26, 2006 2:48 am
Contact:

how do i set a global random?

Post by hondobondo »

say i wanted to set a random global to be used in StartFrame();
where would i call it? main();?

i have this in main but it's causing weirdness

Code: Select all

	local float n;
	n = ceil(random()*6);
	if (n == 1) {MSWAVES = TRUE; bprint("waves\n");}
	else if (n == 2) {MSRANDOM = TRUE; bprint("random\n");}
	else if (n == 3) {MSMELEE = TRUE; bprint("melee\n");}
	else if (n == 4) {MSDUKE = TRUE; bprint("duke\n");}
	else if (n == 5) {MSTROOP = TRUE; bprint("troopeux\n");}
	else {MSVQUAKE = TRUE; bprint("vanilla quake\n");}
this is happening, but its completely random. at least i don't understand it at all. sometimes it crashes to the console sometimes it runs.

Code: Select all

EQ_F       484(MSTROOP)  0.0    200(TRUE)  1.0       3109(?]              
IFNOT      3109(?]              branch 3
CALL0      4565(monsterspawner_troop)monsterspawner_troop() 
GOTO       branch 5
IFNOT      482(MSMELEE)  0.0    branch 3
CALL0      4566(monsterspawner_melee)monsterspawner_melee() 
GOTO       branch 2
CALL0      4562(monsterspawner)() 
    world.qc : StartFrame : statement 22
PR_ExecuteProgram2: NULL function
Host_Error: Program error
this is the call in StartFrame();

Code: Select all

	if (MSRANDOM == TRUE) monsterspawner_random();
	else if (MSDUKE == TRUE) monsterspawner_duke();
	else if (MSTROOP == TRUE) monsterspawner_troop();
	else if (MSMELEE) monsterspawner_melee();
	else monsterspawner ();
any clues?
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: how do i set a global random?

Post by frag.machine »

I don't see any reason to blame this part of the code. :S
Try dprinting n to confirm if it is actually tied to the crashes.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: how do i set a global random?

Post by Spike »

what is monsterspawner, and where is it defined?

older versions of fteqcc had a bug that allowed it to 'successfully' compile code with uninitialised (non-var) functions.
or in other words, if you have void()monsterspawner; somewhere without void()monsterspawnwer={}; somewhere then you get a null function error when you call it, because you never actually set it to anything.

so yeah, find where the code for that function is, and if you can't find it then there's your answer.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: how do i set a global random?

Post by Spike »

side note: when using random() it is generally better to use floor instead of ceil, but the reason for this is engine-specific.

fte/dp: random returns a value between 0 <= val < 1
vanilla: random returns a value between 0 <= val <= 1

note the equals. random can and WILL return 0 sometimes, but it will NEVER return 1 in fte/dp.
the fact that it can return 0 means that ceil will sometimes bug out with a 0 value, while floor will only bug out in vanilla engines.
this means you will pretty much always need an else statement... but else doesn't really make sense when it comes to array offsets, in which case you're screwed, but you're at least more likely to be using one of the advanced engines if you're using such functionality, so its all okay, right?
well, meh, maybe not. but either way its a good practise to get into.
anyway, just saying.


the statements that the engine prints out on a qc crash are only losely related to the statement that was executing at the time. specifically it doesn't understand branches so they're not all even related to the issue. the exception is of course the last statement that it displays, in this case a CALL0 to the global at 4562 (aka: monsterspawner).
thus monsterspawner is the variable that is null. if it were a variable then the previous statements might have given a hint at how its initialised, but in this case only the last one is interesting. so yeah, see my post about fteqcc, yeah, double posts, evil. I just thought I'd explain things in a little more detail. what can I say, ceil(random()*foo) irks me.


and yeah, as frag.machine points out, bprint can have a delay to it, which means the message may not appear until AFTER the server has already crashed, which makes it painful for debugging.
so yeah, developer 1 combined with dprint is more reliable for print-based debugging, especially when hunting down host_errors.
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: how do i set a global random?

Post by frag.machine »

@Spike in a unrelated question: does FTE QCVM has any extra debugging features ?

I know that's one area in engine development not exactly considered "sexy", but better runtime entity inspection and maybe even *gasp* BREAKPOINTS would be great.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: how do i set a global random?

Post by Spike »

<offtopic>
@frag.machine, in answer to your unrelated question:
use fteqccgui, set up the debugger to target fteglqw or whatever. compile your code and then run it, and it'll run with the debugger enabled.
f9 to set a breakpoint, f11 to single-step, f10 to step over function calls, etc.
mouse-over variables to view them or use the watch window thing.
you can set a single watchpoint via the engine's console - 'watchpoint_ssqc someglobal' or 'watchpoint_csqc 5.model' or whatever.
f7 will recompile (and reload the map+qc modules)
while frozen for debugging, the engine window will display the console and a stack trace.
any qc faults will also kick you back into the gui rather than dumping you onto the console with an indecipherable stack trace.

debugging will probably still shed 'remote' clients due to timeouts though, and the symbol lookups are entirely engine based so it doesn't really understand classes/structs/etc, but it should normally cope fine with vanilla qc stuff so long as you don't have any optimisations enabled beyond default.

if you want to debug both ssqc and csqc at the same time, you'll need to use '#pragma sourcefile' to include both modules within the same fteqccgui instance. otherwise it gets a bit messy.

it'd be nice if other engines implemented the same interface etc, but I kinda doubt they will on account of all the machinary that it needs in the engine.
</offtopic>
hondobondo
Posts: 207
Joined: Tue Sep 26, 2006 2:48 am
Contact:

Re: how do i set a global random?

Post by hondobondo »

well i am 100% sure this stuff is the problem since its the only change i made before getting these errors. they seem to have disappeared when i created all the monsterspawner functions and referenced them. what was weird is that i would have calls to set the global var (MSMELEE) but didn't even use it in a conditional statement and a null function error occurred. all of the monsterspawner functions i referenced existed, but the problem didnt go away until i made conditionals with all of the globals i created AND monsterspawner functions. anyway, it hasn't happened since. ugh. but maybe i didn't create the functions before referencing them....
hondobondo
Posts: 207
Joined: Tue Sep 26, 2006 2:48 am
Contact:

Re: how do i set a global random?

Post by hondobondo »

actually i did create all the functions, because sometimes they worked fine and sometimes they didn't. i'm not that sloppy before coming here for help
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: how do i set a global random?

Post by frag.machine »

@Spike: great, I definitely will check it out. dprint-based debugging is too painful. :P
@hondobondo: that's weird. While is good to know things are working as expected now, I know very well this feeling of not being sure what happened or why didn't work before much less why is working now... :)
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: how do i set a global random?

Post by Spike »

temporarily hardcode it with this line change:
n = 1;//ceil(random()*6);
see if its now crashing every single time or not.

random can be useful, but it does make debugging specific pathways more awkward.
hondobondo
Posts: 207
Joined: Tue Sep 26, 2006 2:48 am
Contact:

Re: how do i set a global random?

Post by hondobondo »

Spike wrote:what is monsterspawner, and where is it defined?

older versions of fteqcc had a bug that allowed it to 'successfully' compile code with uninitialised (non-var) functions.
or in other words, if you have void()monsterspawner; somewhere without void()monsterspawnwer={}; somewhere then you get a null function error when you call it, because you never actually set it to anything.

so yeah, find where the code for that function is, and if you can't find it then there's your answer.
heh heh this is exactly what i did. god bless FTEQCC. i just started using it since i installed win 10 and yeah...it compiles with missing functions. i used to use proqcc and this never happened. thanks Spike and everyone else. i'm gonna get the proqcc code and compile it for win10 i'm thinking. what i did was change the name of monsterspawner in dmsp.qc but not in world where i called it.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: how do i set a global random?

Post by Spike »

proqcc is woefully outdated

http://triptohell.info/moodles/win32/fteqccgui.exe is what you should be using. :)
(remember that I did say 'older versions'. unfortunately its easy to not realise that there are bugs when your own code doesn't trip up on them)
Post Reply