we have to make a web game for a school project.
but im currently stuck at one point. its a mafia styled web game, you probably know one of these. When your charachter goes to the hospital to get his wounds fixed up he needs to pay a certain amount of money. this is calculated by the following code
$maxHeal = 100 - $health;
$costs =round(pow($maxHeal,1.8));
health is a number between 0 and 100 and the costs are based on exponential growth. but if the player can only afford 50 but types in 100, how do I make sure he only getw 50, and how do I make sure it are the first 50 health points, the most expensive ones and not the cheap ones, this will cause player to just type in 1 press enter to get some cheap health.
I hope my porblem is clear, if you have any questions about other parts of the codes please ask
thanks in advance
edit: to give some extra clearance,
when I am at 10 health(hp) and I want to go back to 100hp I need to get a 90 extra. there is a form where I can type how much hp I want to cure, so I type in 90 and the system requests to ad 90 to my life so it makes 100. to do this I need to check if the players can afford to pay for those 90 points. if I can not pay for 90 but can pay for 50 I want those 50 to be added anyways. but if I count from 1 to 50 and to one form 40(the remaining I need to heal another timer) it wil cost less than counting from 1 to 90 because of the exponential growth.
so I need 2 checks. I have to cure al I can afford, so if I can afford just 50 of the 90 hp I need, I will only get 50 points and pay for 50, but as this wil be cheaper how can I make sure that I pay for the 50 like I woulld pay for 90. so 50 and 40 need to be equal to one times 90
Based on your question (which is not totally clear to me, but hey, I'm in a good mood), I built the following example:
//total amount of health points
$points = 20000;
//health left
$health = 10;
//how many health do we miss? 100 = maximal
$maxHeal = 100 - $health;
//counter
$i = 0;
while($points > $cost = round(pow($maxHeal-$i,1.8))) {
//check if the user has enough points
if ($points - $cost > 0) {
$health++;
echo "Healt +1 point, total: " . $health . " (points " . $points . " - cost " . $cost . " = " . ($points - $cost) . " left)" . "\n";
} else {
echo "Can't heal anymore, not enough points left (" . $points . ")" . "\n";
}
$points -= $cost;
$i++;
}
echo "\n";
echo "Remaining points: " . $points . ", needs points for next repair: " . $cost;
With the following output:
Health now: 10
Healt +1 point, total: 11 (points 20000 - cost 3293 = 16707 left)
Healt +1 point, total: 12 (points 16707 - cost 3228 = 13479 left)
Healt +1 point, total: 13 (points 13479 - cost 3163 = 10316 left)
Healt +1 point, total: 14 (points 10316 - cost 3098 = 7218 left)
Healt +1 point, total: 15 (points 7218 - cost 3035 = 4183 left)
Healt +1 point, total: 16 (points 4183 - cost 2971 = 1212 left)
Remaining points: 1212, needs points for next repair: 2909
I hope this gets you going :)
Related
i have database list for users and user's coupons and i want to add +1 ticket per coupon if bigger than two between numbers.
For example:
100 between 200 = 1 ticket
200 between 300 = 2 ticket
300 between 400 = 3 ticket
.......
.......
1200 between 1300 = 12 ticket
i put photo for example:
My Code is :
$q=$db->query("SELECT DISTINCT client_id FROM kuponlar ORDER BY client_id LIMIT 20");
foreach($q as $cat){
echo '<li id="'.$cat['client_id'].'" class="files">';
echo 'User ID: '.$cat['client_id'].'';
echo '<ul class="sub-menu">';
$linkq=$db->query("SELECT * FROM kuponlar WHERE client_id='" . $cat['client_id'] . "'");
foreach($linkq as $link){
echo '<li>Coupon ID: '.$link['kuponid'].' - Coupon Price: '.$link['yatirimi'].' ₺ / Won Ticket: '.substr($link['yatirimi'], 0, 1).' </li>';
}
echo '</ul></li>';
}
As discussed in the comments;
So if the number is 12 000, you want 120 as a result? Basically divide by 100? – Qirel
Yes #Qirel this is perfect comment. i mean like this. (...) – Ismail Altunören
So put simply, you want to divide the number by 100. You must then floor it, to get a full integer and get rid of any decimal points.
floor($link['yatirimi']/100);
You would replace that with your substr(), making the full line
echo '<li>Coupon ID: '.$link['kuponid'].' - Coupon Price: '.$link['yatirimi'].' ₺ / Won Ticket: '.floor($link['yatirimi']/100).' </li>';
floor() docs
You can do this using floor():
http://php.net/manual/en/function.floor.php
floor — Round fractions down
So this should do the trick: floor($link['yatirimi'] / 100)
Use that in place of your substr.
you can user this: $wonTicketsCount = round(($link['yatirimi'] / 100 ) - 0.5); instead substr($link['yatirimi'], 0, 1).
Refering to your comments if you only use hundreds steps :
Modify this line :
substr($link['yatirimi'], 0, 1)
This line will always take the first number.
By : this one
This will take all numbers excepts the two lasts.
substr($link['yatirimi'],0,-2);
By keeping the substr, it will not work for number between 0-100,
It's better to use #Qirel's Anwser.
I would like to calculate the spending factor in a rule where we spend Nth time the previous payment done
Here is an example of spending.
firstPaymentAmount=10
SpendingFactor=5
PaymentCount=4
payment1: 10
payment2: 50 (= 10 x 5)
payment3: 250 (= 50 x 5)
payment4: 1250 (= 250 x 5)
At the end we get the sum of all payment made and we have :
10 + 50 + 250 + 1250 = 1560
I would like to know the formula that let me retrieve the spending factor (=5 here) by only knowing these parameters:
paymentCount = 4
initalPayment = 10
totalPaid = 1560
By knowing the formula to calculate the spendingFactor, I will then be able to know the amount and detail of each payment.
I've came with a solution. It gets an approximation of the spending factor because there is no direct formula.
Getting the exact spending factor is too CPU intensive. So, I'm calculating a near approximation first. This value will always be above the solution. I then decrease that number until I'm getting below the total paid amount.
Here is a PHP sample of what I've done.
$paymentCount = 4;
$initialPayment = 10;
$totalPaid = 1560;
//----- precalculate the factor based on total payment for faster computation
//----- this predefined factor will always be above our final factor
$estimatedSpendingFactor = exp(log($totalPaid) / $paymentCount);
//----- find the estimated spending factor
do
{
$estimatedSpendingFactor -= 0.0001;
$y = $initialPayment * (pow($estimatedSpendingFactor, $paymentCount) - 1)
/ ($estimatedSpendingFactor-1);
}
while ($y > $totalPaid);
//-----
printf("The spending factor is %f\n", $estimatedSpendingFactor);
the output will be :
The spending factor is : 5.000000
I am currently building a system that requires ranking based on an internal actions/score. The score itself can range from anywhere within 0 to 20000.
I need the function I create to rank users to return a value between 1-100. If this is impossible it would be fine to return any result sets over 100 as just 100. I am currently having difficulties ensuring creating a logarithmic algorithm for determining scores.
I have tried the following function:
echo 1 + sqrt(500 + 2000 * $score) / 50;
However the results this return do not vary enough for lower values and increase exponentially for higher ones.
Example input scores at low/average end of the scale are:
0.15
1
7
12
Example input at high end of the scale
236.4
1211
17899.70
Any help would be greatly appreciated. Been stuck on this for a few days now. The above function is the best attempt I have so far however as advised there is not enough disparity between the low/medium results and too much between higher ones.
Thanks,
Daniel
This is an open-ended question and there is no clear answer with different tradeoffs.. I'm not a PHP programmer, but something like the following should work.
# THESE PARAMETERS CONTROL THE RANKING ALGORITHM.
$rescale = 0;
$spread = 1;
function rescore ($n) {
return log($n) + $rescale;
}
function rank ($scores) {
return 100 / (1 + exp(- $spread * array_sum(array_map("rescore", $scores))));
}
You should choose $rescale so that the average score rescores to something close to 0. And play around with $spread until you're happy with how much your scores spread out.
The idea is that log turns a wide range of scores into numbers in a comparable range that can be positive or negative. Add a bunch of rescored scores together and you get an arbitrary real number. Then throw that into a logistic function (see https://en.wikipedia.org/wiki/Logistic_function for details) to turn that into a number in your desired range.
Attempting to closely follow a definition in Wikepedia where "each mark on the [logarithmic] scale is the previous mark multiplied by a value," we set value^100 = 20000 and arrive at value = 1.104104805. Could this logarithmic scale then be implemented with a function akin to the following?
function rank($score){
return log($score,1.104104805);
}
Output:
$scores = [0.15,1,7,12,236.4,1211,17899.70];
foreach ($scores as $score){
echo "Score: " . $score . ", Rank: " . rank($score) . "\n";
}
/*
Score: 0.15, Rank: -19.156079885479
Score: 1, Rank: 0
Score: 7, Rank: 19.648736275112
Score: 12, Rank: 25.091228109202
Score: 236.4, Rank: 55.187884698844
Score: 1211, Rank: 71.683855953272
Score: 17899.7, Rank: 98.879704658993
*/
thanks for the help. Here is what I ended up with (thanks to the help of Jake L Price)
The score varied slightly after the initial question (with 120,000 being the top end of the scale) however the logic for the algorithm needed to remain the same. As you can see below we used log * 10 to get a comprehensible low number. We then multiply this again by a number which ensures 120,000 has the top level of 100.
echo $this->rank($score);
public function rank($score)
{
//-- log reg time
// 7.143963378055477 being the numberic multiplier to ensure 120,000 has the score of 100.
$res = 7.143963378055477 * log($score * 10);
return $res;
}
This is now returning
$scores = [0.15,1,7,12,236.4,1211,17899.70, 120000];
foreach ($scores as $score){
echo "Score: " . $score . ", Rank: " . $this->rank($score) . "</br>";
}
Output:
Score: 0.15, Rank: 2.896627883404
Score: 1, Rank: 16.449583579206
Score: 7, Rank: 30.351094421044
Score: 12, Rank: 34.201665683178
Score: 236.4, Rank: 55.495096060882
Score: 1211, Rank: 67.166020848577
Score: 17899.7, Rank: 86.407125230156
Score: 120000, Rank: 100
Im making a browser based PHP game and in my database for the players it has a record of that players total EXP or experience.
What i need is a formula to translate that exp into a level or rank, out of 100.
So they start off at level 1, and when they hit say, 50 exp, go to level 2, then when they hit maybe 125/150, level 2.
Basically a formula that steadily makes each level longer (more exp)
Can anyone help? I'm not very good at maths :P
Many formulas may suit your needs, depending on how fast you want the required exp to go up.
In fact, you really should make this configurable (or at least easily changed in one central location), so that you can balance the game later. In most games these (and other) formulas are determined only after playtesting and trying out several options.
Here's one formula: First level-up happens at 50 exp; second at 150exp; third at 300 exp; fourth at 500 exp; etc. In other words, first you have to gather 50 exp, then 100 exp, then 150exp, etc. It's an Arithmetic Progression.
For levelup X then you need 25*X*(1+X) exp.
Added: To get it the other way round you just use basic math. Like this:
y=25*X*(1+X)
0=25*X*X+25*X-y
That's a standard Quadratic equation, and you can solve for X with:
X = (-25±sqrt(625+100y))/50
Now, since we want both X and Y to be greater than 0, we can drop one of the answers and are left with:
X = (sqrt(625+100y)-25)/50
So, for example, if we have 300 exp, we see that:
(sqrt(625+100*300)-25)/50 = (sqrt(30625)-25)/50 = (175-25)/50 = 150/50 = 3
Now, this is the 3rd levelup, so that means level 4.
If you wanted the following:
Level 1 # 0 points
Level 2 # 50 points
Level 3 # 150 points
Level 4 # 300 points
Level 5 # 500 points etc.
An equation relating experience (X) with level (L) is:
X = 25 * L * L - 25 * L
To calculate the level for a given experience use the quadratic equation to get:
L = (25 + sqrt(25 * 25 - 4 * 25 * (-X) ))/ (2 * 25)
This simplifies to:
L = (25 + sqrt(625 + 100 * X)) / 50
Then round down using the floor function to get your final formula:
L = floor(25 + sqrt(625 + 100 * X)) / 50
Where L is the level, and X is the experience points
It really depends on how you want the exp to scale for each level.
Let's say
LvL1 : 50 Xp
Lvl2: LvL1*2=100Xp
LvL3: LvL2*2=200Xp
Lvl4: LvL3*2=400Xp
This means you have a geometric progression
The Xp required to complete level n would be
`XPn=base*Q^(n-1)`
In my example base is the inital 50 xp and Q is 2 (ratio).
Provided a player starts at lvl1 with no xp:
when he dings lvl2 he would have 50 total Xp
at lvl3 150xp
at lvl4 350xp
and so forth
The total xp a player has when he gets a new level up would be:
base*(Q^n-1)/(Q-1)
In your case you already know how much xp the player has. For a ratio of 2 the formula gets simpler:
base * (2^n-1)=total xp at level n
to find out the level for a given xp amount all you need to do is apply a simple formula
$playerLevel=floor(log($playerXp/50+1,2));
But with a geometric progression it will get harder and harder and harder for players to level.
To display the XP required for next level you can just calculate total XP for next level.
$totalXpNextLevel=50*(pow(2,$playerLevel+1)-1);
$reqXp=$totalXpNextLevel - $playerXp;
Check start of the post:
to get from lvl1 -> lvl2 you need 50 xp
lvl2 ->lvl3 100xp
to get from lvl x to lvl(x+1)
you would need
$totalXprequired=50*pow(2,$playerLevel-1);
Google gave me this:
function experience($L) {
$a=0;
for($x=1; $x<$L; $x++) {
$a += floor($x+300*pow(2, ($x/7)));
}
return floor($a/4);
}
for($L=1;$L<100;$L++) {
echo 'Level '.$L.': '.experience($L).'<br />';
}
It is supposed the be the formula that RuneScape uses, you might me able to modify it to your needs.
Example output:
Level 1: 0
Level 2: 55
Level 3: 116
Level 4: 184
Level 5: 259
Level 6: 343
Level 7: 435
Level 8: 536
Level 9: 649
Level 10: 773
Here is a fast solution I used for a similar problem. You will likely wanna change the math of course, but it will give you the level from a summed xp.
$n = -1;
$L = 0;
while($n < $xp){
$n += pow(($L+1),3)+30*pow(($L+1),2)+30*($L+1)-50;
$L++;
}
echo("Current XP: " .$xp);
echo("Current Level: ".$L);
echo("Next Level: " .$n);
I take it what you're looking for is the amount of experience to decide what level they are on? Such as:
Level 1: 50exp
Level 2: 100exp
Level 3: 150exp ?
if that's the case you could use a loop something like:
$currentExp = x;
$currentLevel;
$i; // initialLevel
for($i=1; $i < 100; $i *= 3)
{
if( ($i*50 > $currentExp) && ($i < ($i+1)*$currentExp)){
$currentLevel = $i/3;
break;
}
}
This is as simple as I can make an algorithm for levels, I haven't tested it so there could be errors.
Let me know if you do use this, cool to think an algorithm I wrote could be in a game!
The original was based upon a base of 50, thus the 25 scattered across the equation.
This is the answer as a real equation. Just supply your multiplier (base) and your in business.
$_level = floor( floor( ($_multipliter/2)
+ sqrt( ($_multipliter^2) + ( ($_multipliter*2) * $_score) )
)
/ $_multipliter
) ;
So I have a members website written in PHP and MYSQL.
Say for a second I want to let my users level up as a reward system and they get XP from doing certain things on the site like posting and what not. Giving the XP is the easy bit, the bit I am kinda stuck on is how the levelling will actually work.
When someone joins it will auto be at lv 1. Now say it lv x 2 for XP to level up per time;
lv1 = 2 xp
lv2 = 4 xp
lv3 = 6xp
lv4 = 8xp
How do I factor this into a formula, so when the XP is reached it will for the certain LV it will level the user up and double the amount of XP needed?
If we start at level 0, and require 2*level xp to get from level-1 to level (ie: 2 xp gets you to level 1, 2+4 total gets you to level 2, 2+4+6 total for level 3, etc), then we have an arithmetic sequence, and the sum is equal to (level/2) * (2 + (2*level))
Simplifying further:
$total_xp_required = $level * (1 + $level);
Now, if we use the quadratic formula to solve level^2 + level + -xp = 0 for level, we get level = (-1 ± sqrt(1 - 4*(-xp))) / 2.
The positive root will always be the one we want, so of the +/-, we only care about the +. Also, non-integer levels don't make sense, so turn it into an int. The only catch is, floats are kinda flaky -- numbers could come up to like 1.99999999998 or something rather than 2.0. We can add a tiny fudge factor to the number before truncating it.
$level = int((sqrt(1 + ($xp*4)) - 1) / 2 + .000000005);
Now, if you want to double the xp required each time, it gets even easier. Say level 1 requires 2 xp, level 2 takes 4, level 3 takes 8, etc. Then your total xp required for a given level is 2 ^ level.
Powers of 2 being a special case in binary, 2^x can be represented by 1 << x.
$total_xp_required = 1 << $level;
And to calculate the level, there are a number of tricks. Mathematically, the level is the log2 of the score.
$level = intval(log($xp) / log(2) + .000000005);
Or stringwise, we can just count the number of digits in the number's base-2 representation. No fudge factor needed here, since floats never come into the picture.
$level = strlen(sprintf("%b", $xp)) - 1;
Either way, at this point, since we can calculate level from xp and vice versa, you don't really need to store the level at all -- just calculate it when you need it.
formulas:
your sample:
//level => required XP to reach it 1 => 0; 2=>2; 3=>6; 4=>8....
$xpForNextLevel = ($currentLevel)*2;
Double required xp after each level
//level => required XP to reach it 1 => 0; 2=>2; 3=>4; 4=>8; 5=>16; 6=>32....
$xpForNextLevel = pow(2,$currentLevel);
EDIT:
Where $xpForNextLevel is the total amount of xp required to reach the next level, NOT the difference betwean this level and the next.
$expRequired = 2^$level;
or
$expRequired = 2*$level;
I did my leveling and EXP system like this, but mine's more advanced with skill points..
<?php
$level_up = ($level + 1);
if ($exp >= $max_exp)
{
$sql = "UPDATE users SET level=(level + 1) , max_exp=(exp + 300) , skill_points=(skill_points + 3) WHERE id='".$id."' LIMIT 1";
$res = mysql_query($sql);
echo '<div class="Leveled">' . 'You sucessfully leveled up to ' . $level_up . '!' . ' As a reward you were given 3 skill points!' . '</div>';
}
else
{
}
?>