open All Channels
seplocked EVE Technology Lab
blankseplocked Needing a little php help
 
This thread is older than 90 days and has been locked due to inactivity.


 
Author Topic

Vistilantus
Caldari
Vitriol Ventures
BLACK-MARK
Posted - 2011.06.16 11:00:00 - [1]
 

Edited by: Vistilantus on 16/06/2011 11:01:38
Hi Guys, been coding in php for the last few months but have came accross a problem i can't solve on my own.

What happens is, there are some SQL queries that run one after the other. The first one is for "defenders" defending against attackers.

There is then a SQL querey to reduce the HP of the attacker

There is then a call to a function to update the variables with the stats

The next one is for "attackers" attacking the defenders.

There is a SQL querey to reduce the HP of the defender.

Battle then ends.

Where the call to the function to update stats, it is acting as though the SQL to reduce HP is not executing, even when i echo $sql; there is nothing. After the attacker attacks, reduces HP of the defender do the stats then get altered.

Any ideas?

e.g if both sides have 100hp and 50att, defender attacks attacker, reduces hp to 50, because of wounds att is reduced to 25, when attacker attacks, he should do 25 damage, but he does the full 50.

After the battle, looking at the DB, both players have 50hp and 25att

Cruthensis
Gallente
Xeno Tech Corp
Self Destruct.
Posted - 2011.06.16 11:02:00 - [2]
 

Code sample would help...

cyclobs
Minmatar
Posted - 2011.06.16 11:28:00 - [3]
 

Edited by: cyclobs on 16/06/2011 11:32:58
right, suggestions i have is (probably wont help) run your SQL querys first and maybe add checks to make sure they can be run in the first place (like health etc etc etc). then update your stats.

and make good use of debugginh

Quote:
sql_query("blah blah blah")
or die("SQL query failed: " . sql_error());



using that little bit of code above has done wonders

TorTorden
Amarr
Posted - 2011.06.16 12:07:00 - [4]
 

Also my 0.02$, using innodb and sql transactions and call a rollback if one of the queries fails or your own verifications fail would help keeping the tables at least somewhat less insane.

Vistilantus
Caldari
Vitriol Ventures
BLACK-MARK
Posted - 2011.06.16 12:15:00 - [5]
 

Edited by: Vistilantus on 16/06/2011 12:29:13
here's the code

CHECK STATS
function checkstats()
{
$defenderhpsql = "SELECT * FROM defender WHERE userid='$_SESSION[defenderid]'";
$defenderhpresult = mysql_query($defenderhpsql) or die(mysql_error());
while($defenderhprow = mysql_fetch_array($defenderhpresult))
{
$_SESSION['defenderhp'][] = $defenderhprow;

}
//THIS IS DECLARED ELSEWHERE
$_SESSION['attackerhp'][] = $attackerhprow;

COMBAT CODE
checkstats();
$hpleft=$_SESSION['attackerhp']-$_SESSION['defenderatt'];
if ($hpleft<0)
{
$hpleft=0;
}
echo " HP Left = ".$hpleft;
//MYSQL QUEREY TO REMOVE HP LOST FROM ATTACKER
$attacksql = "UPDATE attacker SET hp=$hpleft WHERE userid='$_SESSION[attackerid]'";
$attackresult = mysql_query($attacksql)
or die(mysql_error());


//THIS APPEARS TO DO NOTHING
echo $attacksql;


//ATTACKER THEN ATTACKS
checkstats();
$hpleft=$_SESSION['defenderhp']-$_SESSION['attackeratt'];
if ($hpleft<0)
{
$hpleft=0;
}
echo " HP Left = ".$hpleft;

//MYSQL QUEREY TO REMOVE HPLOST FROM DEFENDER
$defendsql = "UPDATE defender SET hp=$hpleft WHERE userid='$_SESSION[defenderid]'";
$defendresult = mysql_query($defendsql)
or die(mysql_error());

END COMBAT
$removequeuesql = "DELETE FROM combatqueue WHERE userid='$_SESSION[attackerid]'";
$removequeueresult = mysql_query($removequeuesql)
or die(mysql_error());

Vistilantus
Caldari
Vitriol Ventures
BLACK-MARK
Posted - 2011.06.16 12:26:00 - [6]
 

Edited by: Vistilantus on 16/06/2011 12:39:38
I have slightly edited the above code so as not to give away too much detail. But the code DOES work. It seems that the combat SQL is not ran untill the very end, just before the code to remove the entry from the queue. Therefore when i run my "atatcker attacking defender" part, the HP and attack that is lost is not reflected when the attacker attacks. It runs as though he has full HP and full ATT stats, even though, when it's all over, he has 50hp and 25att as expected.

Cruthensis
Gallente
Xeno Tech Corp
Self Destruct.
Posted - 2011.06.16 12:40:00 - [7]
 

Quote:
$_SESSION[defenderid]


Is this a verbatim copy? If so, what is 'defenderid'. Looks like a variable, but you're not addressing a variable with that. Needs to be $_SESSION[$defenderid] or, if it's an assoc array key $_SESSION['defenderid']

Vistilantus
Caldari
Vitriol Ventures
BLACK-MARK
Posted - 2011.06.16 12:50:00 - [8]
 

Edited by: Vistilantus on 16/06/2011 12:51:56
$_SESSION['defenderid'] is declared earlier in the code here :

(SQL QUEREY HERE TO GET LOCATION DETAILS OF DEFENDER, INCLUDING DEFENDERID FROM DB)
$_SESSION['defenderid']=$location[0]['userid'];

EDIT : I'm wondering if putting the code for combat into functions would be a better idea?
defence()
{
(defender attacking attacker first)
}
attack()
{
(attacker attacking defender)
}

It just seems that the SQL to reduce the HP doesn't take effect untill everything else is done first....

cyclobs
Minmatar
Posted - 2011.06.16 13:01:00 - [9]
 

one suggestion i can give to do with your $_SESSIONS. since you are using the variable in a query (so using '' would cause utter havoc) instead put the $_SESSIONS into variables

Quote:
$att_id = $_SESSION['attackerit'];


then in your sql you can use
Quote:
"user_id = '" . $att_id . "')");

Cruthensis
Gallente
Xeno Tech Corp
Self Destruct.
Posted - 2011.06.16 13:03:00 - [10]
 

span style= font-size:7pt i Edited by: Cruthensis on 16/06/2011 13:12:04 /i /span br Quotes in your query string are fine - PHP is not going to parse them if you do it right. br br $sql = SELECT FROM defender WHERE userid= {$_SESSION[ defenderid}'";

...is just fine, but yes, if you're using it a few times maybe stick it in a plain variable for ease of referencing.

Overall, I'd suggest you look into a bit of OOP and using (suggested names): Combatant, Defender, Attacker, with the latter two inheriting from the first.

Get your SQL into functions within the objects. Call the functions with parameters.

If you really want to abstract what's going on and model things efficiently: http://framework.zend.com/manual/en/zend.db.html

but there are plenty of other tools and frameworks around.

(Forum has spazzed out about something ^^^ ?!)

Vistilantus
Caldari
Vitriol Ventures
BLACK-MARK
Posted - 2011.06.16 13:05:00 - [11]
 

Ahh, makes sense. I had been doing " blah blah '$_SESSION[stuff]' " so far. Suggestion noted and will change it when i refine my code. Thank you :)

cyclobs
Minmatar
Posted - 2011.06.16 13:06:00 - [12]
 

yes i only picked it up my self since i've been building my own search engine which requires a lot of SQL handling

Vistilantus
Caldari
Vitriol Ventures
BLACK-MARK
Posted - 2011.06.16 13:15:00 - [13]
 

But can you see any reason why the sql query isn't executing to reduce the attackers HP BEFORE i call the checkstats function the 2nd time AND running the attacker's attack phase?

cyclobs
Minmatar
Posted - 2011.06.16 13:30:00 - [14]
 

Quote:
if ($hpleft<0) {


concider changing that to <= 0 or even "0" (depends how it's handled)

< 0 means it has to be in negitives, <= means if it is 0 or less (a little bug that might catch you later on)

Quote:
$attacksql = "UPDATE attacker SET hp=$hpleft WHERE userid='$_SESSION[attackerid]'";


i dunno how effective this is but i like to do it like thi

Quote:
$attacksql = "UPDATE attacker SET hp = '" . $hpleft . "' WHERE userid = '" . $_SESSION['attackerid'] . '"";


but there could also be a
Quote:
"UPDATE attacker SET hp VALUE = ('" . $var . "')


but i could be wrong with that last bit. i'm unsure so really just throwing it out there

InUrJita CheckinUrPrice
Posted - 2011.06.16 13:48:00 - [15]
 

I can't imagine a language less suited to creating a game than PHP. Unless you tie it to SQL, and then it just goes cray cray.

Have you considered whether any other language might be appropriate? Flash maybe? Python? Java?

It's like using a hammer to create a cake. You might end up with something, but it's not gonna be all that delicious.

Vistilantus
Caldari
Vitriol Ventures
BLACK-MARK
Posted - 2011.06.16 15:17:00 - [16]
 

I'm using php because it's the only language i know reasonably well enough to do a browser based game on. When i have this completed i can then look at using other technologies to enchance it, like actionscript or whatever :)

Going to re-write the combat code tonight and over the weekend, just incase i've done something silly.

Vistilantus
Caldari
Vitriol Ventures
BLACK-MARK
Posted - 2011.06.16 18:55:00 - [17]
 

I've changed it so that the stat checks are done outside of a function but i had to change the variables to attackerhp1, attackerattack1, defenderhp1, defenderattack1 THEN change the 2nd lot to attackerhp2, attackerattack2, defenderhp2, defenderattack2

I don't know why, but for some reason, it didn't appear to update the values properly when they were called from a function, even calling the function AFTER changing the DB didn't seem to change teh values of the stored variables. Maybe because i was using sessions and it was treating the variables as an array?

I'm not sure why it didn't work, but the workaround i have might work....for now..... much more testing is required on a larger scale...

Tonto Auri
Vhero' Multipurpose Corp
Posted - 2011.06.16 19:21:00 - [18]
 

I'll start down-top and rant at you for using deprecated and extensively blamed MySQL extension instead of MySQLi or PDO_MySQL.
Second, your string embed syntax is ambiguous. Use clarified {} syntax or PDO_MySQL.
Third, the way you explain it makes your design favoring attackers to the level, where defending anything is just pointless.
And lastly, you are using your database as your playground, which to me looks extremely strange.
But for your specific reason... Enable statement logging in the server and see what is really happening on that end. Make sure your database is not used for anything else, though. As that kind of logging could easily overwhelm moderately loaded database through rapid growth of log files.
I suspect a silly mistake in variable assignment somewhere in your code.

Vistilantus
Caldari
Vitriol Ventures
BLACK-MARK
Posted - 2011.06.16 20:21:00 - [19]
 

Thanks for the reply.
I'll check out MySQLi and PDO_MySQL - i'm self taught (and it shows) so most of what i've coded so far is trial and error + lots of googling.
Not sure on point number 2, but will google both suggestions.
3rd - I'm not sure how you come to that conclusion, The defenders attack first as they have time to prepare, get into tactical positions, etc. The way it should work is that the defenders inflict damage first, then the attackers (using remaining numbers) launch their attack.
The DB is the playground because it's supposed to be a multiplayer browser combat game, i know that so far the database is probably going to get wtfpwned by the number of calls being made all the time, but i don't know how to do it any better. I run all the code on a local development server so i can afford to overload it with the statement logging.

If you're willing to give me some helpful pointers, i will send you a copy of the full, unmodified source. please evemail me an email address and i'll be in touch.

Many thanks!

Vist

Tonto Auri
Vhero' Multipurpose Corp
Posted - 2011.06.16 21:11:00 - [20]
 

Originally by: Vistilantus
Thanks for the reply.
I'll check out MySQLi and PDO_MySQL - i'm self taught (and it shows) so most of what i've coded so far is trial and error + lots of googling.
Not sure on point number 2, but will google both suggestions.

I didn't mean any harm, just rantin' :)
Here's a quick roundtrip about PDO_MySQL, which I highly suggest for use, as it's the proposed standard way to operate with databases in PHP. It also contains the answer to your second question (confusion?) - look for DSN assignment line.
function error_message($msg, $exit = 0)
{
printf('example-PDO: %s'.chr(0x0A), $msg);
if($exit)
{
die($exit);
}
}

$oldErrorHandler = set_error_handler(create_function('$errno, $errstr, $errfile, $errline',
'throw new ErrorException($errstr, $errno, $errno, $errfile, $errline);'),
(E_ALL | E_STRICT) &~ (E_NOTICE | E_USER_NOTICE));

if('cli' == php_sapi_name())
{
$isCli = true;
}

$s = array (
'SQL' => 'mysql',
'SQLUSER' => 'ulog',
'SQLPWD' => 'ulog',
'SQLHOST' => '127.0.0.1',
'SQLPORT' => '3306',
'SQLDB' => 'ulog',
);

$DSN = "{$s['SQL']}:host={$s['SQLHOST']};port={$s['SQLPORT']};dbname={$s['SQLDB']}";

try
{
$db = new PDO($DSN, $s['SQLUSER'], $s['SQLPWD'], array(
// Driver-specific options
// Set error modes to "exception" - the best to track down errors.
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
// Set fetch mode to "associative array" - since i never used indexed arrays so far
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
// Optional. If you realy want to use it and know what that means
// PDO::ATTR_PERSISTENT => true,
// Finishing
));
unset($s);
}
catch(Exception $e)
{
error_message('Unable to connect to database. (' . $e->getMessage() . ')', $isCli ? 0 : 1);
}

// Straight statement execution example
try
{
$_result = $db->exec("CREATE TABLE IF NOT EXISTS `ip_alias` (
`lanAddr` VARCHAR(45) COLLATE utf8_general_ci NOT NULL DEFAULT '0.0.0.0',
`addrName` VARCHAR(45) COLLATE utf8_general_ci NOT NULL DEFAULT '0.0.0.0',
PRIMARY KEY `index` (`lanAddr`)
) Engine=MyISAM COLLATE utf8_general_ci;");
}
catch(Exception $e)
{
error_message('Something happened: ' . $e->getMessage(), 1);
}

// Parametrised insertion example
define('SQL_ADD_ALIAS', 'INSERT INTO `ip_alias` (`lanAddr`, `addrName`) VALUES (?, ?);');
// Yup, I like to define my SQL statements as constants, so no tricky hands could alter them.
// In fact, they are defined in the external file, so no easy way to trick them at the time of execution.
$host = '192.168.1.2';
$alias = 'adsl';
try
{
$insert = $db->prepare(SQL_ADD_ALIAS);
$insert->execute(array($host, $alias));
}
catch(Exception $e)
{
error_message('Unable to insert an alias. (' . $e->getMessage() . ')', 2);
}


I'm not providing an example parametrized query, as my query where I'm using this table span over five lines of code and use two nested SELECTs.
But i'll post the template just to give you an insight into the database power:
Quote:
SELECT FROM_UNIXTIME(`snapDate`, '%Y-%m-%d %H:%i') `date`, `name`, SUM(`input`) `input`, SUM(`output`) `output`
FROM (SELECT `snapDate`, IFNULL(`addrName`, `lanAddr`) `name`, `input`, `output`
FROM `stat_hourly`
LEFT JOIN `ip_alias` USING (`lanAddr`)
WHERE `snapDate` > ? AND `snapDate` <= ? AND ? IN (`addrName`, `lanAddr`)) t1 GROUP BY `date`, `name` ORDER BY `date`, `name`;


Quote:
3rd - I'm not sure how you come to that conclusion, The defenders attack first [...], then the attackers (using remaining numbers) launch their attack.

The "remaining numbers" is the issue. You basically provoking blobbing. If whichever side were able to obliterate opponents in their first turn, they don't get a single hit back.
Retrieve both sides from the database, calculate the round, then insert outcome back and display the result.

Vistilantus
Caldari
Vitriol Ventures
BLACK-MARK
Posted - 2011.06.16 21:21:00 - [21]
 

No Worries mate, constructive criticism is always welcome :)

I think i solved the problem, changed a variable to use the proper array instead of a session variable
$_SESSION['attackerfrigateatt']=($attackership[0][1]*$_SESSION['ships'][0][4]);
rather than
$_SESSION['attackerfrigateatt']=($_SESSION['$attackership'][0][1]*$_SESSION['ships'][0][4]);

When you say calculate the round, then just display the result, you would think it better to just throw the numbers in as though (in simple terms) each ship has a single shot and all ships fire at the exact same time kinda thing? so rather than a defender attacking first....everyone attacks at the same time?

Many thanks for your feedback, im going to look over the example you posted above

Tonto Auri
Vhero' Multipurpose Corp
Posted - 2011.06.16 21:44:00 - [22]
 

Originally by: Vistilantus
When you say calculate the round, then just display the result, you would think it better to just throw the numbers in as though (in simple terms) each ship has a single shot and all ships fire at the exact same time kinda thing? so rather than a defender attacking first....everyone attacks at the same time?

You missed the "record outcome" step. :) Display comes last, as the result of recording.
Basically, yes, if you don't want to dive into realistical simulation part, and each turn consist of single round of fire, it's (IMHO) best to give both parties a turn at the same time.
Alternatively, if your whole turn span for a prolonged period of time (say, a day or even month), you could adopt Atlantis way of doing things. Where firepower is relatively low, but fight start on equal terms (unless one of the sides have TACT'ical advantage, then that side have initial free round), last until one of the sides reach half of their numbers, then begin to retreat and the winner get the last free round of attack before the fight cease completely.

One note about prepared statements.
I'll show a code sample without comments, but it should give you an idea about your last step (recording).
    $_query = $_pdo->prepare('INSERT INTO `index_list`
(`pageId`, `itemOrder`, `itemName`, `itemId`, `sectionId`)
VALUES (0, 1, ?, ?, ?);');
foreach($_ta as $_rc)
{
$_query->execute(array(trim($_rc['title']), $_rc['id'], $_rc['sid']));
}

comparing "time php -f script.php" to the
    foreach($_ta as $_rc)
{
mysql_query(vsprintf('INSERT INTO `index_list`
(`pageId`, `itemOrder`, `itemName`, `itemId`, `sectionId`)
VALUES (0, 1, \'%s\', %d, %d);', mysql_real_escape_string(trim($_rc['title'])),
(int)$_rc['id'], (int)$_rc['sid']));
}


I've been consistently saving approximately 5% of execution time with prepared statement on a local database. For approximately 2k rows inserted.


 

This thread is older than 90 days and has been locked due to inactivity.


 


The new forums are live

Please adjust your bookmarks to https://forums.eveonline.com

These forums are archived and read-only