Bug Reports · Legacy archive

Code help

Started by Strolen Feb 25, 2003 16 posts Locked

  1. Code help

    #1
    Trying to figure out how to randomize the encounter tables. Figured there are a couple coders in this group and maybe you can help out.

    aside::I actually have some better randomize functions then rand(), from what I learned, rand() is only partially random, not that it matters. My difficulty arrives from trying to get the array to the point where I can randomize it and then limit it to a certain amount.

    Here is where I am pseudocode with many comments.

    limit of encounters I want displayed = LIMIT

    FULL_LIST = Grab from mysql all the encounters (non sequential numbers. ie 1,3,5,7,9,)
    FULL_LIST_COUNT = total number of results from previous

    FULL_LIST is now an array loaded with my non sequential numbers.

    Now the randomizer functions I have can't radomize this array, they can randomize a number range so I need to make FULL_LIST sequential yet still maintain their original numbers so I can pull 'valid' encounters using the non sequential numbers. Meaning if the randomize functions calls for a 2, if it isn't mapped to a FULL_LIST number then it will return an blank.

    So I have to load FULL_LIST into an array with some kind of loop.
    SEQUENT 1 => FULL_LIST 1
    SEQUENT 2 => FULL_LIST 3
    SEQUENT 3 => FULL_LIST 5

    (I don't know how to mess with arrays or load them, somebody needs to teach me or show me how to code that. Language doesn't matter, I can figure it out from any example)

    Now I have a sequential list of numbers called SEQUENT

    RANDOMIZE (SEQUENT) from 1 to FULL_LIST_COUNT

    Now we should have a random sequence of numbers. What I need to do now is trim the number of random numbers to the LIMIT we defined. I don't know how to do this either. The can come from anywhere, either the first LIMIT or last LIMIT or whatever. This is more messing with arrays that I don't understand below

    WHILE (SEQUENT < LIMIT)
    {
    LIMIT_SEQUENT is the new array with only the LIMIT amount of encounters
    }

    Once I am here I can just access the array until it is empty but I need to know how to get to the FULL_LIST number that is the second number in the array. Can't just call LIMIT_SEQUENT because it is random and it can be any number.

    I just don't understand the manipulations of arrays so I am sort of lost. I am actually taking C++ and arrays are in the next couple of chapters we are doing, but I just don't know enough about them to get it to work. I know what I want, just not how to do it.

    Any help would be great!!
  2. Code help

    #2
    Examples may be taken from
    http://www.php.net/manual/en/language.types.array.php

    ******************** Note: ************************
    http://www.php.net/manual/en/function.rand.php

    rand
    (PHP 3, PHP 4 )
    rand -- Generate a random value
    Description
    int rand ( [int min, int max])
    If called without the optional min, max arguments rand() returns a pseudo-random value between 0 and RAND_MAX. If you want a random number between 5 and 15 (inclusive), for example, use rand (5, 15).
    In older versions of PHP, you had to seed the random number generator before use with srand(). Since 4.2.0 this is no longer necessary.
    So RAND() shoud be sufficiently random, with out seeding the random number generator.

    **************************************************
    **************************************************
    But you can always get truly random numbers here (see below)
    http://www.php.net/manual/en/function.rand.php

    nospam at hotmail dot com
    08-Apr-2002 12:29

    If you need true random numbers (as computer generated ones, such as those returned by rand(), are not truly random) then consider those generated by radioactive decays. One place you can get these online is:

    http://www.fourmilab.ch/hotbits/generate.html

    Isn't the internet handy?
    - Patrick

    **************************************************

    Preface
    I do not know how to code in php, so this is a guess and I have not debugged any of this so bear with me

    You want random encounters from a database where the indexes are non-sequential but the table is full (no blank records)

    array( [key =>] value
    , ...
    )
    // key is either string or nonnegative integer
    // value can be anything


    $index = integer
    FULL_LIST = Grab from mysql all the encounters (non sequential numbers. ie 1,3,5,7,9,)
    FULL_LIST_COUNT = total number of results from previous

    for($index =0;$index
  3. Code help

    #3
    The actual randomizing is not the problem, and unfortunately, the select by rand() in the mysql statement was most definately not random. I tried it for awhile and almost everytime the exact same encounter came up first and last, that is why I dumped that idea and went with the way I wrote. I should have mentioned that, my fault.

    I did read through most of the array stuff, and some other, better array tutorials. I can fill the first array, I can't quite wrap my head around filling the second array, and I don't know how to limit the second array to only LIMIT amount of inputs. That is where my trouble lies.

    Here is my embarassing code as it sits right up to the while loop to write to the browser


    $limit = 2;
    $resultsenc = mysql_query("SELECT COUNT(enc_id) FROM $table");
    list($countenc) = mysql_fetch_row($resultsenc);
    //WHERE enc_id LIKE '$enc_id'

    while($enc_number = mysql_fetch_array($resultsenc))
    {

    $encounters[$counterit] = $enc_number["enc_id"];
    //I forget if you can use ++ to increment
    $counterit = $counterit + 1;
    }


    while(count($rands_k) < $countenc)
    {
    $n = rand(1,$countenc); // now set much higher
    if(!isset($rands_k[$n]))
    {
    $rands_k[$n] = 1;
    $numbers[] = $n;
    }
    //else
    // error_log("$n Repeats"); // These are the repeating value errors

    }

    while (array($numbers) < $limit)
    {
    $number[] = $numbers;
    }



    print 'RollEncounter';

    $n1 = 1;

    foreach ($numbers as $number1)
    //$data = mysql_fetch_array($results
    {

    $results = mysql_query("SELECT * FROM $table WHERE enc_id LIKE '$number1'");
    while ($data = mysql_fetch_array($results))
    {


    Here is the result http://www.strolen.com/random/encounter/
  4. Code help

    #4
    Did you try SRAND() to seed the random number generator? I did not mention it because the PHP page said it was not required anymore.

    I will give your example some thought.
  5. Code help

    #5
    LOL. Doc. I know how to randomize. That was never the issue. Help me with the arrays man, help me with the arrays. LOL
  6. Code help

    #6
    I think I got it sort of working, although I am not sure I can manipulate it the way I want to yet, but this is what I have.


  7. Code help

    #7
    PHP claims to have a shuffle() function, that shuffles an array. May or may not be of use.
  8. Code help

    #8
    "claim" is the working word. It seems that all the built in randomizing functions in PHP are a little flawed. Forums are full of threads like "Random is not so random" and "Shuffle returning same values" even on php.net they have work arounds to the functions. Shuffle doesn't seem to work very well either unfortunately. Heck, if random() worked I could use it in the mysql call and be done with it in one line.

    That is why there is so much trouble with this, because there has to be a home made solution to something the program already supplies.

    Oh well. It seems to be doing something fairly random now so I am happy.
  9. Code help

    #9
    Might I suggest just using a function to check if the entry is valid or is that going to take too much processing time.
  10. Code help

    #10
    That is actually how we do the random generator on the homepage, and for all the 'ideas' at the bottom of the main pages.

    I have no idea about efficiency, and possibly that is another solution. In my own personal thoughts (I am a self taught coder so do what is easiest for the most part) I was thinking it would be easier to have valid numbers to start with and skip the part to check for a valid number.

    The encounters potentially will have dozens of checks per page and to double check all those values seemed a little much vs filling an array with good numbers. Each check would require a database call which would add to the overhead as well. Array managing is pretty quick overall I believe.

    I plan on cannibalizing this code for all the other random sets we are going to have so I need to keep it as efficient as possible.

    If there is a problem with it and you can point it out or if there is a different way to do the validity check that makes more sense then what I have...I am all ears and would love to hear the improvements.
  11. Code help

    #11
    Why don't you use the rand() function and multiply it by the microsecond to product a much more random number?

    That way the time it is when the view loads it will be random. Or you could divide by the microsecond and use the first two digits right of the decimal place to produce a random number. Then since they can potentially be 00 to 99, you only need to multiply by the quantity of the high number minus the low number end quantity add the low number
    e.g.
    To generate a random real number between a and b, use:
    RAND()*(b-a)+a

    Or take the microsecond then use the random function to calculate the decimal place of the number to use. Do this twice then concatenate the numbers and do like I described above to set the number between 1 and 20.

    Example:
    $microsecond = microsecond // 465678634, I have no idea what the number would look like but I bet it is a long

    $DecimalPlace = rand()*(Len($microsecond)-1)+1 // say it equals '3'

    $MyRand = $DecimalPlace // this will be '5'

    $DecimalPlace = rand()*(Len($microsecond)-1)+1 // say this equals '8'

    // it might be necessary to coerse this variables to strings to concatenate them
    $MyRand = $MyRand & $DecimalPlace // this will be '5' + '3'

    Now $MyRand = 53, if we coerce it to a integer then we have a random number. Even if Rand starts out predictably (which shouldn't happen if we send the random number generator) then we still get a pseudo random number based on the difficulty in predicting when a link gets clicked.


    With this added randomizing then you should be able to make that MySql call.

    I hope that make since
  12. Code help

    #12
    My above comment was take from this post by 'Anonymous' on php.net
    http://www.php.net/manual/en/function.rand.php

    14-Nov-2002 10:58

    This seems quite randomized to me, and useful.

    //
    //Function - Psuedo-Random ASCII generator for hashing etc
    //

    srand((double)microtime()*1234567);
    function rand_ascii($num) {
    for ($i=0;$i
  13. Code help

    #13
    Once I discovered shuffle() or at least the fixes they found it, I figure it is easier to shuffle the array, vs. loading it into a sequential array, which I am pretty sure any rand() function is going to need since it is a range, and then having to parse a two level array which I don't know how to do.

    What you suggest is to come up with a random number first, and use that as the mysql call right? That would create a new database call for every random number, not to mention the error correcting for when the query doesn't return a result which would amount to basically what i have already, you would also have to build another array of all the previous 'good' numbers you already got so you would be comparing every new random number to the database for a good number, comparing it to a accumulating array of past numbers, once it passes it would be loaded in the accumulating array so the next random number can go through the process.

    Right now I have one mysql query, one array build, and shuffle algorithm.

    Your way I would have two or three (depending on 1-100 or 1-1000) random number generations, a mysql database call, an error check for NULL, another check against an array of previous random numbers, and a way to put the ok'd number into the checking array. And this is for every random number.

    Mysql queries aren't too expensive, but if you can get it all in one pull, that is what should be done. Compared to sorting or shuffling an array, a querie is going to take more time. I don't like the idea of having to query the database for every random number found and tried to get away from that from the start, not to mention all the other stuff it has to go through....

    Am I off or did I misunderstand you. It is an interesting thing you propose and I no doubt think it will work, but is it very efficient?
  14. Code help

    #14
    Ok then make one sql call, loading all the encounters into one array.

    Generate the random number (see above), check to see if that number is in the second array.

    If yes repeat the loop.

    else store that number into the second array.

    repeat loop 20 times

    Build php page loading the index for the first array that are stored in the second array
  15. Code help

    #15
    Make one sql call.

    Generate random number. (which is actuall two random calls and will have to be three as soon as we break 100 so must be planned for)

    (added) Check if it is a valid number in the original query array

    (added) Do Random again if fails.

    Check if it is in second array.

    Do Random again if fails.

    Store in array.

    Repeat LIMIT amount of itmes. User defined limit. Could be 100

    Build.
    =======
    VS.
    =======
    Mysql call randomized.

    Load array.

    Shuffle array.

    Build with limit that takes no extra calls.

    =======

    Do you see the difference in complexity or is it just me...or are you just being a black knight? :wink: :lol:

    Granted the shuffle algorithm in mine is probably the biggest thing since it has to take all the encounters in the database and mix them up, but still not convinced that it is less efficient then all the loops and double checks. Do you think?

    Mine it just mixes it up by stepping through it and randomizing with guaranteed good numbers. This one steps through one array, checks, steps through another array, checks then does it over and over again for each new number.

    I like the simplicity of the current one and I think it is overall more efficient?
  16. Code help

    #16
    Of course I like mine the best. Hell I even think mine is simpler. But ultimately you are going to be the one building it, so you should go with what you feel comfortable with. I imagine there is more than one way to make what you describe work, so go for it with any way that works.

    What will the available options be?
    - You can define limit (how many encounters returned)
    - User can pre-select encounters to be randomly encountered (maybe the user has a theme and only likes 50 out of 250 for that theme, and only needs 15 out of those 50 potentials returned)
    - User can select "allow duplicates," the user may want truly random encounters where some encounters may happen more than once (e.g. attacked by pack of wolves, invaded by garden slugs, harassed by gnomes, etc)
    - Maybe users decides difficulty level of encounter (e.g. easy = encounter hungry wild dogs, medium = encounter = mother cave bear and her cubs (surprise them), hard = encounter hunting party of adult male ogre-magi, death wish/extreme = unbeknownst to the party they are spotted by hungry/angry ancient dragon)

Bug Reports · All categories · Guildhall