News:

11 March 2016 - Forum Rules

Main Menu

Organized Battle System.

Started by InfamousKnight, November 11, 2012, 01:12:18 PM

Previous topic - Next topic

InfamousKnight

I've created a battle system with some pretty ugly code so I updated it breaking the good parts into sections.

Here's my new code:
http://pastebin.com/tYTA9bcr
Somebody suggested that I make a damage calculation function but I couldn't bother. Sorry about all the constant text in the comments. I just like yelling at the people trying to learn lol.. no.

henke37

There is a major problem here: you forgot to account for the game needing to run the rest of the game engine.

You need code to wait for animations, manage the ui, run the music engine and what not.

Further more you have outright bugs in your randomness. You can't constantly seed the generator like that and expect random numbers to work.

Another issue is the overuse of strings where enums or pointers to structures should be used instead.

And finally, the design just isn't complicated enough to deal with things like different numbers of enemies, equipment as well as enemies having non trivial AI. Have you seen the AI of some games? There are turing complete AI scripting languages out there.

InfamousKnight

Quote from: henke37 on November 12, 2012, 01:45:40 AM
Further more you have outright bugs in your randomness. You can't constantly seed the generator like that and expect random numbers to work.

I really didn't know what I was doing when seeding a random number. I thought you had to reestablish it to make it randomize when doing the next cycle?

Pyriel

For the most part, seeding is initializing the random number generator's state.  Depending on the algorithm, seeding every time you generate a number can mean you just get the same number every time.  Even if that's not the case, there's no reason to keep seeding like that.

henke37

No, it is not "depending on the algorithm", it is guaranteed (by the c and c++ standards even) that the same seed will always result in the same sequence.

Ryusui

Here's the idea.

Computers don't do random numbers. What they do is pseudorandom numbers - they may look random to a human eye, but they are in fact predetermined based on 1. the seed value and 2. the precise implementation of the "random" number generator. If you seed the RNG with, say, "150," then it will produce the exact same sequence of "random" numbers every time. In fact, if you keep seeding it with the same number, odds are you will simply get the same single "random" number each time.

A programmer who actually knows what the hell he's doing will instead seed the RNG with a value that is unlikely to be the same twice - the current time, for example.
In the event of a firestorm, the salad bar will remain open.

Pyriel

Quote from: henke37 on November 13, 2012, 02:53:33 AM
No, it is not "depending on the algorithm", it is guaranteed (by the c and c++ standards even) that the same seed will always result in the same sequence.
I didn't intend to speak only for C/C++, and their standard algorithms.  I probably should have, though.

InfamousKnight

I honestly don't even know what seeding a random number is.. I just put 150 because thats just what popped in my mind.. What happens when you seed a random number?

tryphon

When you ask for a random number without seed, compiler uses a default seed.

So if you seed your generator with a random number x, since you didn't give a seed for x, compiler uses the default seed and x is always the same.

So it's the same than when you seed with a constant number.

As already said, use time for seed, it's generally sufficient.

Bregalad

The random number generation algorithm is just an opperation that takes a number, and create another number from it.
The seed is the initial number of the series.

This is a very good system as, as for the same SeeD, you get the same sequence, which can sometimes turn is a very useful property. Then you get "controllable" random numbers.

A very good example of this is the game Fire Emblem. During battles, it is determined randomly if you land a critical hit, or if you miss your attack.
Also you are allowed (in fact forced) to save the game on all your moves. If something bad happens (for example you miss an enemy and then he lands a critical hit on you, killing your unit), you can turn the console off, and restart from your saved game which is just before the fight.
However Nintendo were not stupid, and when saving your game they also saved the state of the random number generator. That way when you resume your save, the exact same random sequence will happen again, and you will again miss the enemy, and he will again land a critical hit, again killing you.

If the numbers would have been actually random, this could not have been possible - that is all players could cheat by restoring their saves and never being killed. I've tried this on my first FE play though of course ^^

For a normal utilisation of a RNG (you want actual random numbers) it's standard practice to seed the RNG once at startup and then never seed again. If you want the numbers to be different on every run of your program it's common practice to use the system time, on the other side if you want the random sequence to be the same no matter who runs your program, you should seed with a numeric constant, such as 150. It's also possible to rely on user input to make up for the randomness : Video game systems does not have a system's time, but it's common practice to seed with 1 (or any constant) and to call the random() function on each frame at title screen, that way the time spent on the title screen (which is random) "seeds" the generator.

Also it's imporant to always use less bits than what the internal state of the RNG is made of. Why ?
Because the random generator will always generate the same sequence for the same numbers. If you want for example a 8 bit random number, and use a 8 bit RNG, you will NEVER have a sequence like this :
... -> 152 -> 3 -> 89 -> 204 -> .... -> 152 -> 4 -> ...

Because if a '152' is followed by a '3', then it means ALL '152's will be followed by '3's.
To fix this problem, you can use for example a 16 or 32 bit RNG, and use only the upper (or lower) 8 bits.

henke37

To be specific, the c and c++ standards actually define the default seed. I think it's one.

InfamousKnight

I'm guessing I don't have to reestablish rand()? I think I might have to reestablish srand()..

Ryusui

You're fine if you call srand() only once, but you should seed it with a decently unpredictable environment value - say, the system time, as noted above. There's nothing technically wrong with just seeding it with a fixed value like 150, like you've already done - it just won't do what you want it to do. A fixed seed means the RNG will pull out the exact same sequence of random numbers, every time. If you want random numbers, you need a random(ish) seed.

Have you ever played Minecraft or Dwarf Fortress? Part of the appeal of these games is that their worlds are randomly generated, but you can reproduce any world in either game perfectly as long as you have the seed value that was used to generate it. That's how predictable pseudorandom numbers are: the same seed in the same RNG will always produce the same sequence. If you want different sequences, you need to find some way of making your seed different each time the program runs, as I've explained before.
In the event of a firestorm, the salad bar will remain open.

BRPXQZME

Time is a popular choice but there are other seed sources you can consider, because sometimes you don't want the player to have any (reasonably easy) influence over the seed.

I don't know what you mean by "reestablish", but srand() just seeds the generator, and rand() keeps getting new numbers from the generator. Pretty much just set it and forget it.
we are in a horrible and deadly danger

InfamousKnight

#14
Hey guys, there seems to be an issue with these lines: if(players[i].ally == "enemy") {
                        while(true) {
                        if(players[etarget].dead || players[etarget].ally == "enemy") {
                        if(ac <= 0) break;
                                              srand(150);
                                              etarget = rand() % 4;                         
                        }
                        if(!players[etarget].dead || players[etarget].ally == "ally") break;
                        }
                        checkabi(players, i, etarget, eability);
                                              players[i].ct = 0;
                                              srand(150);
                                              etarget = rand() % 4;
                                              srand(150);
                                              eability = rand() % 1;
                                              }
                        }


For some reason, the enemies attack themselves and people that are already dead.. Do you see why I say "reestablish srand() or rand()?"? If you notice in the while loop, it checks if the etarget is equal to someone already dead or is an enemy too so then I reestablish rand and srand to get another number until it finds someone thats not dead and is an ally.

Could someone help?

BRPXQZME


[20:13:02] brp@eva:~$ cat test.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    srand(150);
    printf("%d ", rand());
    srand(150);
    printf("%d ", rand());
    srand(150);
    printf("%d\n", rand());
    srand(150);
    printf("%d ", rand());
    printf("%d ", rand());
    printf("%d\n", rand());
}
[20:13:09] brp@eva:~$ cc -o test test.c
[20:13:13] brp@eva:~$ ./test
2521050 2521050 2521050
2521050 1569098057 731858839
[20:13:15] brp@eva:~$

Please. Only seed once!
we are in a horrible and deadly danger

InfamousKnight

You mean like this:
                        if(players[i].ally == "enemy") {
                        while(true) {
                        if(players[etarget].dead || players[etarget].ally == "enemy") {
                        if(ac <= 0) break;
                                              srand(150);                   
                        }
                        if(!players[etarget].dead || players[etarget].ally == "ally") break;
                        }
checkabi(players, i, etarget, eability);
                                              players[i].ct = 0;
                                              srand(150);
                                              }
                        }


That apparently only attacks the same person over and over again..

BRPXQZME

This is how a typical program should use srand():

<start program>
srand(time(0));
<rest of program with rand()s in it; never calls srand again>
<end program>

Every call to rand() will return a random number this way.
we are in a horrible and deadly danger

InfamousKnight

Thanks! Fixed. A little buggy but doesn't matter to me for now. I'll update the OP.

InfamousKnight