Quitting game when player fails
Johan Halmén

My game will end when player fails to complete one level. So I thought of making one function that plays the level and returns true if player succeeds and false otherwise. Each level will be harder than the previous and at some point the levels are impossible, so I might not need a final "Congrats, end of game jadajada" thing. So I thought of this: [edit] I lined up the columns

if (play_level(1,  60,  120) &&
    play_level(2,  70,  125) &&
    play_level(3,  80,  130) &&
    play_level(4,  90,  135) &&
    play_level(5, 100,  140) &&
    play_level(6, 110,  140))
        my_alert("Congrats, end of game jadajada");

// do stuff with the score...

The parameters of the function call are level number, number of items to collect, available time (I might extend the parameter list). But my question is, will this work. The play_level calls are supposed to happen consecutively, until one of them returns false, and after that the following lines are not executed.

Some compiler settings might force all calls to be executed, no matter whether true or false. But is it possible that some compilers will force all calls in any case? And can I rely on that every compiler makes the functions to be called in that exact order?

Matthew Leverton
if (0 && foo()) {}

foo() is guaranteed to never be called. Anything else would be a tragedy.

Audric

&& : The C standard guarantees order of evaluation from left to right, and no evaluation of the right part if the left part evaluated to 0.

ixilom

Why not use a for loop?

bool playmore = true;
int level = 1;
int numitems[6] = { 60,70,80,90,100,110 };
int timeavail[6] = { 120,125,130,135,140,140 };

for( ; level<6 && playmore; i++)
{
  playmore = play_level(level,numitems[level],timeavail[level]);
}

myalert("GZ, you made it to level &d",level);
// do stuff with the score

Slartibartfast

Hehe, reminds me of a bug I read about in one game, where they had what basically amounts to
if (Random() + modifiers > Random() + other_modifiers) {do stuff;}
And on some OSs the left Random() would be called first, and on some the right would be called first.
This meant that recreating the same results by using the same seed failed between different OSs.

Indeterminatus
Quote:

And on some OSs the left Random() would be called first, and on some the right would be called first.

That's because the order of evaluation is not defined here. In case of operators &&, || and ?: it is, though, as already stated. For all other operators, it's best not to rely on the order of execution. If you need the guarantee, extract those bits to local variables.

That said, what you're trying to achieve works with all ISO C compliant compilers, Mr. Halmén.

OICW
Quote:

That said, what you're trying to achieve works with all ISO C compliant compilers, Mr. Halmén.

However I would prefer a loop method, since the above idea looks uncomfortable to me. At least the loop will save you some typing.

Indeterminatus
OICW said:

However I would prefer a loop method, since the above idea looks uncomfortable to me.

Seconded, albeit that was not the question ;)

Johan Halmén

I don't count copy+paste as typing. I don't care whether I have 20 or 50 lines of those play_level calls. I like it when the parameters get in columns. I might write:
play_level(00, 060, 120) &&
Then I copy, then I paste 50 times. Then I quickly number the levels (the two zeros), right hand pushes on down arrow and backspace, left hand runs over keys 0-9 repeatedly - yes, that's typing, but simple, systematic and fast. Then I change the other parameters to whatever I want. The lines and columns in my code tell me more about the levels than the separate int arrays in ixilom's example. Of course one can line up the values in the arrays with spaces or tabs, but fifty ints on one line of code won't work. Especially if you want to make them match with an array on the next line.

tobing

Just take care, in source 060 ist not exactly what you might expect...

Thomas Fjellstrom
Quote:

Then I change the other parameters to whatever I want. The lines and columns in my code tell me more about the levels than the separate int arrays in ixilom's example.

You can easily merge the two arrays you know.

int levels[6][2] = {
  /* num, time */
   { 60,  120 },
   { 70,  125 },
   { 80,  130 },
   { 90,  135 },
   { 100, 140 },
   { 110, 140 },
};

for( ; level<6 && playmore; i++)
{
        playmore = play_level(level,levels[level][0],levels[level][1]);
}

Or somesuch.

ixilom

Just to nitpick some. I wouldn't hardcode those values at all :P

Thomas Fjellstrom
Quote:

Just to nitpick some. I wouldn't hardcode those values at all :P

Neither would I...

Indeterminatus
ixilom said:

Just to nitpick some. I wouldn't hardcode those values at all :P

KISS. :) There's nothing wrong with Johan's way, it gets the job done, and only requires very little development time in doing so. Everything else (loading those parameters from [external, ed.] data, for instance) can be added later on, should it be needed at all.

Johan Halmén

TF's array works exactly as well as my calls!

And I will hardcode them. The alternative would be to have some script system, like cfg files, and that would require error checking and stuff to be as reliable as hardcoding.

Audric

I have only one observation, it's that this single C statement from "if" to ";" handles many things at once:
which level is first,
which level follows which one,
detect when player loses,
detect when player quits,
detect when player wins and launch endgame sequence.

In most games, the sequence of events varies, especially if you start adding cheat keys to warp to any level (It makes it way easier to test the game).
It's one of the rare cases where I'd recommend a very loose program structure:

  • A while(true) loop, so you can repeat the level-init and level-play parts as many times as there is a "level" to play.

  • After level-play: individual if() blocks that identify if the level was won, lost, aborted, etc, and what you want to happen in each case.In these blocks you can use return to exit the current function, "break" to stop the loop (execution will resume at the instruction after "while() {}" ), or "continue" to go back to the beginning of the loop, where a new level will start.

Thread #596518. Printed from Allegro.cc