Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 6 of 6

Thread: Battle System

  1. #1
    Regular Coder Zangeel's Avatar
    Join Date
    Oct 2007
    Location
    public_html/
    Posts
    638
    Thanks
    17
    Thanked 79 Times in 79 Posts

    Battle System

    So I'm developing an interesting little game and I'm just puzzled as how to go about the next step of userA battling userB

    My initial idea was to use a loop

    while( <userA or userB has health > )

    then let them hit eachother until one has 0 hp. But the problem I'm having is hits are based on three stats, ATTACK POWER (how hard a hit will be), DEFENSE power (ability to withstand attack) and SPEED (who hits first and how many times)

    im specifically having trouble factoring the last part. Lets give some fake stats

    UserA has... 1000 ATK, 5000 DEF, 10000 SPD with 1000HP
    UserB has... 1000 ATK, 5000 DEF, 1000 SPD with 1000HP

    Since userB has significantly less speed, uesrA would hit him 10 times before UserB even has a shot at UserA, so you can understand the model im trying to use for speed, x2 speed = 2 hits, x3 speed has 3 hits and so on.

    But how can I get my php code to follow this?

    shoookran
    PHP Code:
    $aString is_string((string)array()) ? true false// true :D 
    [/CENTER]

  • #2
    Regular Coder Zangeel's Avatar
    Join Date
    Oct 2007
    Location
    public_html/
    Posts
    638
    Thanks
    17
    Thanked 79 Times in 79 Posts
    Bump?

    Maybe i can put it simpler. I neeed to tell my code to do A x amount of times and B x amount of times REPEATED until a variable hits 0.
    PHP Code:
    $aString is_string((string)array()) ? true false// true :D 
    [/CENTER]

  • #3
    Senior Coder Rowsdower!'s Avatar
    Join Date
    Oct 2008
    Location
    Some say it's everything.
    Posts
    2,027
    Thanks
    5
    Thanked 397 Times in 390 Posts
    I'm envisioning something like this:

    PHP Code:
    $user_a=array(
        
    'ATK' => 1000,
        
    'DEF' => 5000,
        
    'SPD' => 10000,
        
    'HP' => 1000
    );
    $user_b=array(
        
    'ATK' => 1000,
        
    'DEF' => 5000,
        
    'SPD' => 1000,
        
    'HP' => 1000
    );


    function 
    resolve_battle($user_a,$user_b){
        
    $in_progress=true;
        
    $time_increment_reached=0;
        
    $user_a_rof=1000/round($user_a['SPD']/1000);
        
    $user_b_rof=1000/round($user_b['SPD']/1000);
        print 
    "<h1>User A RoF: $user_a_rof</h1>\n<h1>User B RoF: $user_b_rof</h1>\n";
        while(
    $in_progress==true){
            
    //as long as the battle is in progress, we loop through the process
            
    $time_increment_reached++;
            if(
    $time_increment_reached%$user_a_rof==0){
                
    //if $user_a gets to make an attack in this milisecond, we process the attack...
                #whatever attack calculations you have go here...
                
    print "<p>User A attacks User B at $time_increment_reached, User B HP goes from ".$user_b['HP'];
                
    $user_b['HP']=round($user_b['HP']-$user_a['ATK']/($user_b['DEF']/20),2);
                print 
    " to ".$user_b['HP']."<p>\n";
                if(
    $user_b['HP']<=0){
                    
    //if this attack has brought the HP for $user_b to zero (or less) then the battle will have ended after this round...
                    
    $in_progress=false;
                    print 
    "<p style=\"font-weight:bold;color:#c00;\">User B has fallen in this round...</p>\n";
                }
            }
            if(
    $time_increment_reached%$user_b_rof==0){
                
    //if $user_b gets to make an attack in this milisecond, we process the attack...
                #whatever attack calculations you have go here...
                
    print "<p style=\"color:#579;font-weight:bold;\">User B attacks User A at $time_increment_reached, User A HP goes from ".$user_a['HP'];
                
    $user_a['HP']=round($user_a['HP']-$user_b['ATK']/($user_a['DEF']/20),2);
                print 
    " to ".$user_a['HP']."<p>\n";
                if(
    $user_a['HP']<=0){
                    
    //if this attack has brought the HP for $user_a to zero (or less) then the battle will have ended after this round...
                    
    $in_progress=false;
                    print 
    "<p style=\"font-weight:bold;color:#c00;\">User A has fallen in this round...</p>\n";
                }
            }
        }
        
    //return the users as they are after the battle has ended...
        
    return array($user_a,$user_b);
    }

    $result=resolve_battle($user_a,$user_b);

    print 
    "<pre>";print_r($result);print "</pre>"
    Apart from the actual battle damage calculations, is that about what you're looking for? Attack and defense stats could be degraded as HP declines and the beginning status of each combatant at the start of each loop could be cached for the current round so that damage could be dealt simultaneously so that the first fighter in the code won't win a match be that merit alone.
    Last edited by Rowsdower!; 04-23-2012 at 01:52 PM.
    The object of opening the mind, as of opening the mouth, is to shut it again on something solid. G.K. Chesterton
    See Mediocrity in its Infancy
    It's usually a good idea to start out with this at the VERY TOP of your CSS: * {border:0;margin:0;padding:0;}
    Seek and you shall find... basically:
    validate your markup | view your page cross-browser/cross-platform | free web tutorials | free hosting

  • Users who have thanked Rowsdower! for this post:

    Zangeel (04-23-2012)

  • #4
    Regular Coder Zangeel's Avatar
    Join Date
    Oct 2007
    Location
    public_html/
    Posts
    638
    Thanks
    17
    Thanked 79 Times in 79 Posts
    Thanks! I really appreciate all of that, it gave me some great ideas.

    it's exactly what I was looking for
    PHP Code:
    $aString is_string((string)array()) ? true false// true :D 
    [/CENTER]

  • #5
    Regular Coder Zangeel's Avatar
    Join Date
    Oct 2007
    Location
    public_html/
    Posts
    638
    Thanks
    17
    Thanked 79 Times in 79 Posts
    Just a friendly BUMP

    I'm going to show my poor math skills now.. the integers used in the above code for the userspeed are fine, but what if just as an example we have one user with the speed of 50, and another with 50000000, it doesn't quite work then im guessing since the number the user speed is divided by is staticly at 1000

    PHP Code:
        $user_a_rof=1000/round($user_a['SPD']/1000); 
    how can we adjust this just so it doesn't matter what the speed of the two user is, whether 1 or 1 trillion?
    PHP Code:
    $aString is_string((string)array()) ? true false// true :D 
    [/CENTER]

  • #6
    Senior Coder Rowsdower!'s Avatar
    Join Date
    Oct 2008
    Location
    Some say it's everything.
    Posts
    2,027
    Thanks
    5
    Thanked 397 Times in 390 Posts
    My earlier suggestion was something that essentially divided the battle into milliseconds/milliminutes/milli-whatever and calculated the combat occurring in each milli-period (since the example speeds you gave were in units of 1,000). This would have limitations (as you are finding with large numbers). In order to support a wider range of numbers you could simply increase the base 1000 up to a million, trillion or whatever you like. But that would still put an arbitrary cap on the speed ratings and larger caps will still mean a lot of extra iterations through the loop.

    So you could do the first approach below, which is extremely inefficient and will take a looooooong time to run with big numbers. but which will present no arbitrary cap at all (allowing any speed rating you wish):

    PHP Code:
    <?php

    $user_a
    =array(
        
    'ATK' => 1000,
        
    'DEF' => 5000,
        
    'SPD' => 10000,
        
    'HP' => 1000
    );
    $user_b=array(
        
    'ATK' => 1000,
        
    'DEF' => 5000,
        
    'SPD' => 1000,
        
    'HP' => 1000
    );


    function 
    resolve_battle($user_a,$user_b){
        
    $in_progress=true;
        
    $time_increment_reached=0;
        
    $user_a_rof=$user_b['SPD'];
        
    $user_b_rof=$user_a['SPD'];
        print 
    "<h1>User A RoF: $user_a_rof</h1>\n<h1>User B RoF: $user_b_rof</h1>\n";
        while(
    $in_progress==true){
            
    //as long as the battle is in progress, we loop through the process
            
    $time_increment_reached++;
            if(
    $time_increment_reached%$user_a_rof==0){
                
    //if $user_a gets to make an attack in this milisecond, we process the attack...
                #whatever attack calculations you have go here...
                
    print "<p>User A attacks User B at $time_increment_reached, User B HP goes from ".$user_b['HP'];
                
    $user_b['HP']=round($user_b['HP']-$user_a['ATK']/($user_b['DEF']/20),2);
                print 
    " to ".$user_b['HP']."<p>\n";
                if(
    $user_b['HP']<=0){
                    
    //if this attack has brought the HP for $user_b to zero (or less) then the battle will have ended after this round...
                    
    $in_progress=false;
                    print 
    "<p style=\"font-weight:bold;color:#c00;\">User B has fallen in this round...</p>\n";
                }
            }
            if(
    $time_increment_reached%$user_b_rof==0){
                
    //if $user_b gets to make an attack in this milisecond, we process the attack...
                #whatever attack calculations you have go here...
                
    print "<p style=\"color:#579;font-weight:bold;\">User B attacks User A at $time_increment_reached, User A HP goes from ".$user_a['HP'];
                
    $user_a['HP']=round($user_a['HP']-$user_b['ATK']/($user_a['DEF']/20),2);
                print 
    " to ".$user_a['HP']."<p>\n";
                if(
    $user_a['HP']<=0){
                    
    //if this attack has brought the HP for $user_a to zero (or less) then the battle will have ended after this round...
                    
    $in_progress=false;
                    print 
    "<p style=\"font-weight:bold;color:#c00;\">User A has fallen in this round...</p>\n";
                }
            }
        }
        
    //return the users as they are after the battle has ended...
        
    return array($user_a,$user_b);


    $result=resolve_battle($user_a,$user_b); 

    print 
    "<pre>";print_r($result);print "</pre>";

    ?>
    That's maximum accuracy for timing. But like I said, it's also extremely terrible performance.

    Now, I'm no math wiz myself, but another alternative I have come up with is that you could set things up more modestly with a speed ratio (using speed "b" / speed "a" for user "a" and speed "a" / speed "b" for user "b") and round these to the nearest "x" level of accuracy (whole unit, 10th, 100th, 1000th place, however deep you care to go for the sake of accuracy), then simply run the battle calcuation with the relative attack frequencies. That might look like this:
    PHP Code:
    <?php
    $user_a
    =array(
        
    'ATK' => 1000,
        
    'DEF' => 5000,
        
    'SPD' => 49587,
        
    'HP' => 1000
    );
    $user_b=array(
        
    'ATK' => 1000,
        
    'DEF' => 5000,
        
    'SPD' => 2384,
        
    'HP' => 1000
    );


    function 
    resolve_battle($user_a,$user_b){
        
    $depth=3//change this to set the decimal point depth of the comparison for RoF
        
    $in_progress=true;
        
    $time_increment_reached=0;
        
    $user_a_rof=round($user_b['SPD']/$user_a['SPD'],5);
        
    $user_b_rof=round($user_a['SPD']/$user_b['SPD'],5);
        
    $user_a_attacks=0;
        
    $user_b_attacks=0;
        
    $dominant_user = (max($user_a_rof,$user_b_rof) == $user_a_rof) ? "b" "a";
        if(
    $dominant_user == "a"){
            
    //"round" to desired decimal place (really just multiply by 10^x where x is the desired decimal place) and then round the result to an integer...
            //the "dominant" user will always have a RoF of 1x10^x, since theirs is the base by which all speed activities are calculated
            
    $user_a_rof=1*pow(10,$depth);
            
    $user_b_rof=round($user_b_rof*pow(10,$depth));
        }
        else{
            
    $user_b_rof=1*pow(10,$depth);
            
    $user_a_rof=round($user_a_rof*pow(10,$depth));
        }
        
    //see if we can reduce the fraction (reduce uneventful combat cycles and speed up the process) so we'll try all of the prime numbers between 1 and 20 (arbitrarily...feel free to add more prime numbers to the list and create a helper function to run it all) to try to slim things down a bit...
        
    while( fmod($user_a_rof,2)==&& fmod($user_b_rof,2)==){
            
    $user_a_rof/=2;
            
    $user_b_rof/=2;
        }
        while( 
    fmod($user_a_rof,3)==&& fmod($user_b_rof,3)==){
            
    $user_a_rof/=3;
            
    $user_b_rof/=3;
        }
        while( 
    fmod($user_a_rof,5)==&& fmod($user_b_rof,5)==){
            
    $user_a_rof/=5;
            
    $user_b_rof/=5;
        }
        while( 
    fmod($user_a_rof,7)==&& fmod($user_b_rof,7)==){
            
    $user_a_rof/=7;
            
    $user_b_rof/=7;
        }
        while( 
    fmod($user_a_rof,11)==&& fmod($user_b_rof,11)==){
            
    $user_a_rof/=11;
            
    $user_b_rof/=11;
        }
        while( 
    fmod($user_a_rof,13)==&& fmod($user_b_rof,13)==){
            
    $user_a_rof/=13;
            
    $user_b_rof/=13;
        }
        while( 
    fmod($user_a_rof,17)==&& fmod($user_b_rof,17)==){
            
    $user_a_rof/=17;
            
    $user_b_rof/=17;
        }
        while( 
    fmod($user_a_rof,19)==&& fmod($user_b_rof,19)==){
            
    $user_a_rof/=19;
            
    $user_b_rof/=19;
        }
        
    //now we should be reasonably reduced, so we go ahead with the battle calculations...
        
    print "<style>*{padding:0;margin:0;}</style><h1 style=\"font-size:24px;\">User A attack frequency (in time units): $user_a_rof</h1>\n<h1 style=\"font-size:24px;\">User B attack frequency (in time units): $user_b_rof</h1>\n<div style=\"width:600px;margin-left:40px;\">\n";
        while(
    $in_progress==true){
            
    //as long as the battle is in progress, we loop through the process
            
    $time_increment_reached++;
            if(
    $time_increment_reached%$user_a_rof==0){
                
    //if $user_a gets to make an attack in this round, we process the attack...
                #whatever attack calculations you have go here...
                
    $user_a_attacks++;
                print 
    "<p style=\"color:#fff;font-weight:bold;background-color:#555;margin:0;padding:2px 5px;\">[$user_a_attacks] User A attacks User B at $time_increment_reached, User B HP goes from ".$user_b['HP'];
                
    $user_b['HP']=round($user_b['HP']-$user_a['ATK']/($user_b['DEF']/20),2);
                print 
    " to ".$user_b['HP']."</p>\n";
                if(
    $user_b['HP']<=0){
                    
    //if this attack has brought the HP for $user_b to zero (or less) then the battle will have ended after this round...
                    
    $in_progress=false;
                    print 
    "<p style=\"font-weight:bold;background-color:#c00;color:#fff;padding:2px 5px;text-align:center;\">User B has fallen in this round...</p>\n";
                }
            }
            if(
    $time_increment_reached%$user_b_rof==0){
                
    //if $user_b gets to make an attack in this round, we process the attack...
                #whatever attack calculations you have go here...
                
    $user_b_attacks++;
                print 
    "<p style=\"color:#444;font-weight:bold;background-color:#ffc;margin:0;padding:2px 5px;\">[$user_b_attacks] User B attacks User A at $time_increment_reached, User A HP goes from ".$user_a['HP'];
                
    $user_a['HP']=round($user_a['HP']-$user_b['ATK']/($user_a['DEF']/20),2);
                print 
    " to ".$user_a['HP']."</p>\n";
                if(
    $user_a['HP']<=0){
                    
    //if this attack has brought the HP for $user_a to zero (or less) then the battle will have ended after this round...
                    
    $in_progress=false;
                    print 
    "<p style=\"font-weight:bold;background-color:#c00;color:#fff;padding:2px 5px;text-align:center;\">User A has fallen in this round...</p>\n";
                }
            }
        }
        
    //return the users as they are after the battle has ended...
        
    return array($user_a,$user_b);


    $result=resolve_battle($user_a,$user_b); 

    print 
    "</div>\n<pre style=\"background-color:#fff;position:fixed;right:20px;top:20px;height:330px;width:260px;padding:20px;border:1px solid #000;\"><h1 style=\"margin:0px 0px 20px 0px;font-size:20px;font-weight:bold;font-family:'verdana';\">Final:</h1>";print_r($result);print "</pre>";
    ?>
    You sacrifice a bit of accuracy in the timing (because you are rounding, after all), but you can control how much of a sacrifice you make and still keep a reasonable handle on performance.

    Like I said, I'm no mathematician so in all likelihood there is a better/cleaner way of doing this (as in "using a formula" rather than actually running iterations). But this is what my muddled thoughts could pull together on short notice.
    Last edited by Rowsdower!; 05-23-2012 at 02:21 PM.
    The object of opening the mind, as of opening the mouth, is to shut it again on something solid. G.K. Chesterton
    See Mediocrity in its Infancy
    It's usually a good idea to start out with this at the VERY TOP of your CSS: * {border:0;margin:0;padding:0;}
    Seek and you shall find... basically:
    validate your markup | view your page cross-browser/cross-platform | free web tutorials | free hosting


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •