im learning PHP because i made only designs and templates, and i came to an big problem, at least for me. I am making simple "army battle script" where each player has some troops with attack, defense, hp stats, and they battle against each other. Ive made attack player vs player but i am struggling about many entity fight and how to code it.
First im calling all my units sended to attack, run it trought the loop and get in array every row/unit
Then i made that with enemy units, and in the end, i have a simple simulation script that makes the fight. But the fight isnt working. It doesnt select random unit from the array, it doesnt switch between attacker x defender turns and whats the worse, it only runs with one unit, when that units dies, the script ends and thats it... Can you guys please give me some answer, or way to handle this? I will be so thankfull because i am solving this for few days and i have no clue. Thanks. (i know that the code is ugly, but its just concept...)
//EDIT
Ok, i turned on the error reports and change a bit the simulation code, but the results are bad. I get error Fatal error: Maximum execution time of 30 seconds exceeded in or Warning: Division by zero in php in line
$hit = ($attacker['attack']/$defender['defense']) + rand(1, 2);
Heres the full code, ive tried rand(0,count($unit_attacker_def)-1); but i think its without changes. Also i added selecting new random array with unit, if there is 0 health and unset. And its still running trought one unit, not all in attacker array, and all, or left units in defender array. I somehow came to phase where the script calls the next unit, but it havent any variables in it loaded.
case 'battle_wizard_execute';
?>
<table>
<tr><td><h3>Utok</h3></td></tr>
<?
$query_street = mysql_query("SELECT * FROM game_army_attacks WHERE attack_id = '".$_GET['id']."' ");
$row_street = mysql_fetch_assoc($query_street);
$query_loc_info = mysql_query("SELECT * FROM game_location_street WHERE street_id = '".$row_street['attack_attacker']."' ");
$row_loc_info = mysql_fetch_assoc($query_loc_info);
$tilee_info = mysql_num_rows($query_street);
if ($tilee_info > 0){
$query_units_info = mysql_query("SELECT * FROM game_army_units_attacking WHERE army_attack = '".$_GET['id']."' ");
while (($unitsinfo = mysql_fetch_assoc($query_units_info)) != NULL) {
$query_unit_info = mysql_query("SELECT * FROM game_army_class WHERE army_class_id = '".$unitsinfo['army_class_id']."' ");
$unit = mysql_fetch_assoc($query_unit_info);
$unit_attacker = array();
$unit_attacker[] = array(
'name' => $unit['army_class_name'],
'power' => $unitsinfo['army_power'],
'attack' => $unitsinfo['army_att'],
'defense' => $unitsinfo['army_def']
);
///// Kolko jednotiek máš tolko krat sa vypise
$x = 1;
while($x <= $unitsinfo['army_population']) {
foreach($unit_attacker as $index => $record){
///// Tato cast pusti kod pre kazdu jednu jednotku ktora je v poli
echo "<tr><td>Jednotka: {$record['name']} ID: {$record['power']} ParentID: {$record['attack']} Title: {$record['defense']}</td></tr>";
$x++;
}
}
}
}
?>
</table>
<table>
<tr><td><h3>Utok protivnik</h3></td></tr>
<?
$query_street_def = mysql_query("SELECT * FROM game_army_units WHERE army_street = '".$row_street['attack_defender']."' ");
$tilee_info_def = mysql_num_rows($query_street_def);
if ($tilee_info_def > 0){
$query_units_info_def = mysql_query("SELECT * FROM game_army_units WHERE army_street = '".$row_street['attack_defender']."' ");
while (($unitsinfo_def = mysql_fetch_assoc($query_units_info_def)) != NULL) {
$query_unit_info_def = mysql_query("SELECT * FROM game_army_class WHERE army_class_id = '".$unitsinfo_def['army_class_id']."' ");
$unit_def = mysql_fetch_assoc($query_unit_info_def);
$unit_attacker_def = array();
$unit_attacker_def[] = array(
'name' => $unit_def['army_class_name'],
'power' => $unitsinfo_def['army_power'],
'attack' => $unitsinfo_def['army_att'],
'defense' => $unitsinfo_def['army_def']
);
///// Kolko jednotiek máš tolko krat sa vypise
$y = 1;
while($y <= $unitsinfo_def['army_population']) {
foreach($unit_attacker_def as $index => $record_def){
///// Tato cast pusti kod pre kazdu jednu jednotku ktora je v poli
echo "<tr><td>Jednotka: {$record_def['name']} ID: {$record_def['power']} ParentID: {$record_def['attack']} Title: {$record_def['defense']}</td></tr>";
$y++;
}
}
}
}
Simulation:
$count = 0;
while ((count($unit_attacker_def) > 0) && (count($unit_attacker) > 0)){
$count++;
$attacker_key = rand(0,count($unit_attacker_def)-1);
$attacker =& $unit_attacker[$attacker_key];
$defender_key = rand(0,count($unit_defender)-1);
$defender =& $unit_attacker_def[$defender_key];
while (($defender['power'] >= 0) && ($defender['power'] >= 0)){
$hit = ($attacker['attack']/$defender['defense']) + rand(1, 2);
echo "<tr><td>{$count}.xx {$attacker_key} xJednotka {$defender['name']} ({$defender['power']} hp) bola zranená a dostala {$hit} zranenia jednotkou {$attacker['name']} ({$attacker['power']} hp)</td></tr>";
$defender['power'] = $defender['power'] - $hit;
$attacker['power'] = $attacker['power'] - $hit;
if ($defender['power'] <= 0) {
echo "<tr>Jednotka {$defender['name']} umrela, jednotka {$attacker['name']} vyhrala!</tr>";
unset($defender[$defender_key]);
$defender_key = rand(0,count($unit_defender)-1);
$defender =& $unit_attacker_def[$defender_key];
}
if ($attacker['power'] <= 0) {
echo "<tr>Jednotka {$attacker['name']} umrela, jednotka {$defender['name']} vyhrala!</tr>";
unset($attacker[$attacker_key]);
$attacker_key = rand(0,count($unit_attacker_def)-1);
$attacker =& $unit_attacker[$attacker_key];
}
}
}
?>
</table>
<?
break;
Well you use array_rand() it selects one element from the array and when u use $array[$key] where $key = 1 because of array to var conversion it returns second element of your array atackers and second element of defenders. Use rand(0,count($unit_attacker)-1) to generate random key. But it still will be bugy because you can generate the same key )).
First of all, make sure you have turned on error reporting:
<?php
// Turn off error reporting
error_reporting(0);
// Report runtime errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
// Report all errors
error_reporting(E_ALL);
// Same as error_reporting(E_ALL);
ini_set("error_reporting", E_ALL);
// Report all errors except E_NOTICE
error_reporting(E_ALL & ~E_NOTICE);
?>
With simple debugging you will find out where is an error. Just var_dump() every important variable and check its state. Nobody can debug for you because we don't know what is the data in your mysql table.
Try to use mysqli_* functions, because mysql are deprecated.
Try to use classes to describe everything in your game and make it more readable and maintainable. For example:
<?php
abstract class Unit{
protected $hp;
protected $damage;
protected $defense;
// Force Extending class to define this method
abstract protected function applyDamage($damage);
}
class GroundUnit extends Unit{
//GroundUnit inherits everything from Unit
//define methods specific for GroundUnits
}
class FlyingUnit extends Unit{
//FlyingUnit inherits everything from Unit
//define methods specific for GroundUnits
}
When you find where is an error, and if you are still stuck, update your question with relevant data.
Note that your code is vulnerable to SQL injection
$query_street = mysql_query("SELECT * FROM game_army_attacks WHERE attack_id = '".$_GET['id']."' ");//don't put $_GET['id'] directly into query because that is security hole
Simple steps(related to your example) to improve your protection from sql injection would be :
//assume that $_GET['id'] should hold an integer value
$id = isset($_GET['id']? trim($_GET['id']) ? 0);
$id = (int)$id;
Now let's pretend that there is a $_GET['some_key'] also and it should hold string value. Now checks would be little different:
$some_string_value = isset($_GET['some_key']? trim($_GET['some_key']) ? '');
$some_string_value = trim($some_string_value);//triming whitespace
$some_string_value = mysql_real_escape_string($some_string_value);//escaping troublesome quotes(')
Also you can use prepared statements which is in my opinion a preferred way.
Related
I have a conundrum I'm struggling to crack.
I have a database with 719 entries that I'm running a script on, these entries are Characters in a game and is what they will be referenced as.
However my while loop stops at 360 every time...
See below:
$query = mysqli_query($con,"SELECT * FROM users ORDER BY entryID;");
// Start loopy loop
$runCount = 0;
$CharNum = 0;
echo "NumRows = ".mysqli_num_rows($query)."<br/>"; // Outputs: NumRows = 719
while ($row = mysqli_fetch_array($query)) {
echo "Character#: ".++$CharNum."<br/>"; // Outputs: Counter stops at 360??
$entryID = $row["entryID"];
$CharacterID = $row["characterID"];
$blue = $row["blue"];
$tsDatabaseID = $row["tsDatabaseID"];
$tsUniqueID = $row["tsUniqueID"];
$tsName = $row["tsName"];
if (...[tonnes of code here]
}
echo "Runcount = ".++$runCount."<br/>"; // Outputs: Another counter stops at 360??
}
echo [some report summary]
I have no idea how or why it is stopping, but it isn't crashing as the report summary is showing after the while finishes but it is too perfect to be 360 every time??
So fun story,
if (!mysqli_fetch_array($query)) {
Doesn't sanity check it like I thought to see if it's valid, but performs the fetch in a way it screws everything up. Perhaps someone can explain this who is better than I. But this was inside my if.
I am currently giving a score of one or more people and choosing to draw more than one person based on the score. However, there is still a runtime error and is not being resolved. Please let me know how to this problem solve.
this is my code:
$selectChildrens = array();
for($i=0;$i<$recuTotal;$i++){
$random = rand(0,sizeof($childSelectArray)-1);
$selectChild = $childSelectArray[$random];
$sameCheck = 0;
if(sizeof($selectChildrens) == 0){
array_push($selectChildrens,$selectChild);
while(($key = array_search($selectChild,$childSelectArray)) != NULL){
unset($childSelectArray[$key]);
}
$recuTotal—;
$i=0;
}else{
array_push($selectChildrens,$selectChild);
while(($key2 = array_search($selectChild,$childSelectArray)) != NULL){
unset($childSelectArray[$key2]);
}
$recuTotal—;
$i=0;
}
}
I see that your attempt to decrement $recuTotal is not using correct syntax.
Use this line instead: $recuTotal--
You are using a long dash, but need two hyphens.
As for your array_search() lines, I always use: !==false though I'm not sure it matters.
Lastly, you can use !sizeof($selectChildrens) as a shorter if statement.
Though I'll admit I didn't fully comb your code to see what it is doing, this is a DRYer code block that will perform the same way:
$selectChildrens = array();
for($i=0;$i<$recuTotal;$i++){
$random = rand(0,sizeof($childSelectArray)-1);
$selectChild = $childSelectArray[$random];
$sameCheck = 0;
array_push($selectChildrens,$selectChild);
while(($key=array_search($selectChild,$childSelectArray))!==false){
unset($childSelectArray[$key]);
}
$recuTotal--;
$i=0;
}
I am trying to solve a mysteries code that writing a number in a choice I will get all opposite of that number
I did almost done with that the only problem with it I might have the opposite recalled as he does have another recorded in another course
In more word my PHP about courses when I do ask MY PHP course it well give me all people how did not take course 1 but some people were recalled as they have other courses
The Problem when I choose For Example Course X I do get All Who Did not Take Course X But Some where Called From The same Table cause They Do Have Taken Other Courses In the same table
I did resolve The first Problem Using the following code
if(isset($_GET['course_guid']) && $_GET['course_guid']!="" )
$f.=" AND s.course_guid != '".$_GET['course_guid']."'";
And I Did Create Another page Select.php To Omit All Identified People from Orig.php using The Following Code
<?php
if(isset($_GET['id']))
foreach($_GET as $key => $post)
$_GET[$key]=m($post);
$ff="";
if(isset($_GET['id']) && $_GET['id']!="")
$ff.=" AND cs.id = '".$_GET['id']."' ";
$prns =(isset($_GET['prn'])? $_GET['prn']:'');
if(isset($prns) && $prns!="")
$ff.=" AND cs.prn = '".$prns."' ";
$course_guids =(isset($_GET['course_guid'])? $_GET['course_guid']:'');
if(isset($course_guids) && $course_guids!="")
$ff.=" AND cs.course_guid = '".$course_guids."' ";
$from_time=system_time();
$date_from= date("d",$from_time)."-".date("m",$from_time)."-".date("Y",$from_time);
$date_to=date("d",system_time())."-".date("m",system_time())."-".date("Y",system_time());
if(isset($_GET['alldates']) && $_GET['alldates']=="on") {
$t_f=mktime(0,0,0,6,1,2011);
$t_t=system_time();
} else {
$t_f=mktime(0,0,0,substr($date_from,3,2),substr($date_from,0,2),substr($date_from,6,4));
$t_t=mktime(23,59,59,substr($date_to,3,2),substr($date_to,0,2),substr($date_to,6,4));
}
$query="SELECT cs.id,cs.prn,cs.course_guid FROM courses_attend cs
WHERE cs.time BETWEEN $t_f AND $t_t
$ff
";
//echo "$prns";
$rs22 = mysql_query($query) or die(mysql_error());
// $total22 = mysql_num_rows($rs22);
/*
while($row22=mysql_fetch_assoc($rs22))
{
$prnss =(isset($row22['prn'])? $row22['prn']:'');
print($prnss);
}
*/
?>
print($prnss); // this should be the code needed to be recalled In Orig.php
and It should Be Called Inside a loop mysql_fetch_array which is cannot be Used In orig.php Cause I do already Have a structure and Another Loop In that page Cause real Output Interface is there
as far as I do know I do think function callback() would be a solve on the other hand I do not know how to create one
// Answer
for ($i= 0; $i < mysql_num_rows($rs22);$i++) {
$row22 = mysql_fetch_assoc($rs22);
$prnss = $row22['prn'];
// echo "$prnss"; // return print all Omitted data
// echo "<br />\n";
$f.=" AND s.prn != '".$prnss."' ";
}
Solved By Adding This In Orig.php
On the other hand and after testing Select.php DATA can be added TO the Orig.php
Best regards
I have a question that I have been stuck on for several hours now. I have played around with numerous types of for() and while() loops. I put them in different locations with different variables and ran different things, nothing worked..
My question:
Why is my program giving all users below the first one the same level? You can clearly see in the picture that Nicolas has much more XP. (5,000 xp is level 20, and if "Nic5" was first in the database then it would change the "Skill Level" to 20.
I know that the returned variable $lvl isn't changing for each player that loads and this is why each player is getting the first player's level.
Can anybody help me with this please?
Notes:
0 = a column that holds experience for a players skill level.
class calculatelevel:
class calculatelevel {
function level($skillnum)
{
$host = "*";
$user = "*";
$pass = "*";
$db = "*";
$con = new mysqli($host, $user, $pass, $db) or die($con->error);
$res = $con->query("SELECT `0` FROM hiscores");
$max = 99;
while($row = $res->fetch_assoc()) {
$xp = $row['0'];
// Find the appropriate level
for ($lvl = 1; $lvl < $max; $lvl++) //this for loop runs 99 times
{
if ($xp < $this->experience($lvl))//if players xp in skill is less than experience(level 1-99)
{
// Level found
$lvl -= 1;
break;
}
}
}
return $lvl;
}
public function experience($lvl)
{
$xp = 0;
for($x = 1; $x < $lvl; $x++)
{
$xp += floor($x + 300 * pow(2, ($x / 7)));
}
return floor($xp / 4);
}
}
Method that writes database information to page.
if($res->num_rows > 0) {
echo "<table>
<tr>
<td>Rank</td>
<td>Username</td>
<td>Skill Level</td>
<td>Total Exp</td> </tr>";
while($row = $res->fetch_assoc()) {
echo 'ran';
$calc = new calculatelevel();
$level = $calc->level(0);
echo '<tr>
<td>'.($count+1).'</td>
<td>'. htmlspecialchars($row['username']) .'</td>
<td>'.number_format($level).'</td>
<td>'.number_format($row['0']).'</td>
</tr>';
$count++;
}
}
Your while loop and for loop are structured incorrectly. You are looking at only the first row and returning the level for that row every time. You break the for loop when you find the level for that row's player, then immediately return that level. Result: it looks like everyone has the same level.
EDIT: Okay, here are a few more thoughts.
First, a column named 0 is asking for trouble, as Mike W pointed out. You say 0 is a table, but if that's the case, your SELECT statement doesn't make sense. The first thing I would try is changing the column name to something that isn't a number, like xp.
Second, you really should make only one database connection and use it throughout the entire request, if possible. Opening a new connection each time a particular function runs will tie up a server quickly.
Third, the obvious problem in your current code is this:
function level($skillnum) {
// other code here....
// Okay, you load a row's data into $row, with the idea that you will repeat this.
while($row = $res->fetch_assoc()) {
// $xp is set to the experience points for the user you just loaded
$xp = $row['0'];
// You now look at each level, starting at 1, to see if the
// user's xp is greater than the cutoff for that level
for ($lvl = 1; $lvl < $max; $lvl++) //this for loop runs 99 times
{
// If the user's xp is less than the cutoff...
if ($xp < $this->experience($lvl))//if players xp in skill is less than experience(level 1-99)
{
// ... then you go back down one level...
// Level found
$lvl -= 1;
// ... and quit the for loop!
break;
}
}
// okay, you're out of the for loop, so you go back to the while loop...
// a new row is loaded...
// and $xp and $lvl are both overwritten with that user's values
}
// So, the while loop has run once for each player...
// ... but you are only returning one player's level!
return $lvl;
}
Also, you have defined calculatelevel::level to require a parameter $skillnum, but you never use it in the code posted here.
I suspect there is another glitch in your real code causing it to return the first player's level, rather than the last player's level. It could be a problem with the 0 column name; that really should change.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
Does anyone know the facemash algorithm that Mark Zuckerberg implemented in his facemash site?
http://www.thecrimson.com/article/2003/11/19/facemash-creator-survives-ad-board-the/
Preferably in PHP & MySQL.
UPDATE:
As I said in the comments, I've added this algerithm to my new website. At first it seemed to work perfectly. But after some weird inputs some strange result began to form.
While debugging I figured out what I was doing wrong. When getting the score for a "direct relationship" (used in the indirect relationship too) between 2 nodes I added the scores together. This was wrong, the score of a direct relationship should be expressed in -1 to +1, where:
-1 = lost everything
+1 = won everything
So if A won 8 times to B, and B won 2 times to A the score should be:
(A wins) 8 + (B wins) 2 = (total matches)10
(delta of -1 and +1 =) 2 / (total matches)10 = (points per win) 0.2
Score of A vs B = (points per win) 0.2 * (wins) 8 - 1 = 0.6
Score of B vs A = (points per win) 0.2 * (wins) 2 - 1 = -0.4
Also I didn't mention this in the original explanation but it is all about triangles. So when we look at the indirect score, you don't need to go any further than 1 hop.
I don't know what algorithm was actually used for the real-world site, but what they write on the window in the movie is based on the Elo rating system, which originated in the chess world and is now also used in many other games.
I recreated it aswell check it out.
Not sure about php but the C# class is
http://lukedurrant.com/2010/11/c-elo-rating-class-used-on-facemash-as-seen-in-the-social-network-movie/
I used it on my
Facemash
Key press code is
$(document).keydown(function(event) {
if (event.keyCode == 37) {
//Voted Face 1
Rate("face1", false);
}
if(event.keyCode == 39) {
//Voted Face 2
Rate("face2", false);
}
});
<?php
//This page is responsible to return a JSON object
//code starts after the functions for those who might get confused xD
header('content-type: application/json; charset=utf-8');
global $responseData;
function AdjustRate($Ra, $Ea, $Sa)
{
//i used my own rules here 32 points for less than 500
if($Ra < 500)
$k = 32;
elseif ($Ra < 1000)//24 points for anything between 500 and 1000
$k = 24;
else
$k = 16;//16 for anything more than 1000
return $Ra + ($k*($Sa - $Ea));
}
function GetExpectedChance($rA, $rB) // the ELO formula taken from http://en.wikipedia.org/wiki/Elo_rating_system
{
return (1/(1+pow(10,(($rB-$rA)/400))));
}
function setNewRates($lastCall) // function I used to update my database tables
{
global $responseData;
$A = $lastCall->p1;
$B = $lastCall->p2;
$C = $lastCall->c;
$A->E = GetExpectedChance($A->rate, $B->rate);
$B->E = GetExpectedChance($B->rate, $A->rate);
// decide who won and who lost
if($A->id == $C){
$winner = $A;
$looser = $B;
}
elseif ($B->id == $C) {
$winner = $B;
$looser = $A;
}
// 3 cases, in all of them winner will get his rate/hits increased by 1
//Case #1: normal case we just update rate/hits for the winner, this applies all the time
$winner->rate += 1;
$winner->hits += 1;
//Case #2 / #3 : here we should adjust the rate after applying case #1
// if he won while he is expected to lose OR if he lost while expected to win
// there should be minimum rate different of 40 between the two
$diff = abs($winner->rate - $looser->rate);
if($diff >= 40 && ($winner->E < 0.5 || $looser->E >= 0.5)) {
$winner->rate = AdjustRate($winner->rate, $winner->E, 1);
$looser->rate = AdjustRate($looser->rate, $looser->E, 0);
}
// update the db to update rates, hits for both winner and looser
$updateQuery = 'UPDATE user SET rate='.$winner->rate.',hits='.$winner->hits.' WHERE id=' . $winner->id;
mysql_query($updateQuery);
$updateQuery = 'UPDATE user SET rate='.$looser->rate.' WHERE id=' . $looser->id;
mysql_query($updateQuery);
// Save to responsedate
$responseData->winner = $winner;
$responseData->looser = $looser;
}
//CODE STARTS HERE :)
// Setup the mysql connection
include 'db.php';
// Part 1: calculate the rate and save to db, if we have a lastcall
// GET the last call data object, it has p1, p2, c, these are the items i recieved from my javascript ajax call
$lastCall = json_decode((string)$_GET['lastCall']); // it was a JSON object so i need to decode it first
// Save last call data, will be sent with the respond as well
$responseData->lastCall = $lastCall;
// if there is a json object, means that there was a rating process and I have to set the new rates
if($lastCall->c != NULL)
{
setNewRates($responseData->lastCall);
}
// Part 3: Select new persons and addthem to our responseData
$q = Array();
$q[0] = 'SELECT id, name, sex, rate, hits FROM user WHERE fm_status=1 AND sex="female" ORDER BY RAND() LIMIT 2';
$q[1] = 'SELECT id, name, sex, rate, hits FROM user WHERE fm_status=1 AND sex="male" ORDER BY RAND() LIMIT 2';
// girls or boys ?
srand(mktime());
$query = $q[array_rand($q)];
$result1 = QueryIntoArray($query);
$responseData->user = $result1;
// Part 4: encode to JSON/JSONP string then respond to the call
$json = json_encode($responseData);
$json = isset($_GET['callback'])? "{$_GET['callback']}($json)" : $json;
echo $json;
mysql_close();
// by Noor Syron :)
//I used this in my www.mimm.me
?>
`I have designed the code in Perl all from google searching and it works.
Here's It
use strict;
use warnings;
use WWW::Mechanize;
use LWP::Simple;
sub images()
{
my $mech = WWW::Mechanize->new();
my ($site,$count,$file,$dir);
print "\t\t\tDesigned By NUMWARZ GAMING\n\n";
print "Enter the name of the site you want to search for images\t:\n";
$site = <STDIN>;
print "Enter the folder where you want to save this\t:\n";
$dir = <STDIN>;
open my $doc, ">" , $dir."sitelist.txt";
$mech->get( $site);
my #links = $mech->images();
$count = 0;
for my $link ( #links )
{
$file = $dir.$count.".jpg";
mirror($link->url,$file);
print $file," : "$link->url,"\n";
print $doc $link->url." ".$file."\n";
$count+=1;
}
close $doc;
exit;
}
images();
No not here not anywhere on the web. The Facemash source code has never been released to the public. The only one, who might still have a copy is Mark Zuckerberg himself.
here is a clone of facemash available http://www.facemash.99k.org
I've recreated it as well, but in a WordPress plugin
http://pofornot.com/
http://codecanyon.net/item/pics-mash-image-rating-tool/3256459?ref=mikemayhem3030