diff --git a/countBattles.txt b/countBattles.txt index 44fb745..e6d1b72 100755 --- a/countBattles.txt +++ b/countBattles.txt @@ -1 +1 @@ -1726 \ No newline at end of file +1747 \ No newline at end of file diff --git a/src/arenas/tron/Coords.php b/src/arenas/tron/Coords.php index fe760e2..9fdb5e4 100755 --- a/src/arenas/tron/Coords.php +++ b/src/arenas/tron/Coords.php @@ -1,14 +1,15 @@ min) || ($x > $this->max) || ($y < $this->min) || ($y > $this->max)){ + if (($x < Coords::$min) || ($x > Coords::$max) || ($y < Coords::$min) || ($y > Coords::$max)){ //out of limits + error_log("a bot out of limits"); return false; } diff --git a/src/arenas/tron/ScoreLap.php b/src/arenas/tron/ScoreLap.php index ddd0a91..a529252 100644 --- a/src/arenas/tron/ScoreLap.php +++ b/src/arenas/tron/ScoreLap.php @@ -2,71 +2,57 @@ class ScoreLap { - private $playersIdsByOrder; //array containing id's of alive players at the beginning of the match, Put only alive bots in! - private $looserList; //idem but only loosers - public function addBotOnLap($order,$id){ - $this->playersIdsByOrder[$order] = $id; + private $participants; //array containing bots objects + private $loosers; //those who losed + + + public function addBotOnLap(TronPlayer $bot){ + $this->participants[] = $bot; } - public function addLoser($order,$id){ - $this->looserList[$order] = $order; + public function addLoser(TronPlayer $bot){ + $this->loosers[] = $bot; } public function __construct() { - $this->playersIdsByOrder = array(); - $this->looserList = array(); + $this->participants= array(); + $this->loosers = array(); } public function getLoosersList(){ - return $this->looserList; + return $this->$loosers; } - - //NO! - // public function make($botsList){ - // //$botsList must be like array[{botOrder:BotId},{botOrder:BotId}] - // $this->looserList = $botsList; - // } + + private function ApplyDraws(){ - private function ApplyDraws(){ //apply draw match to all losers - if(count($this->looserList) > 1){ //no draw if only 0 or one user at this lap - foreach($looserList as $order1 => $looser1){ - foreach($looserList as $order2 => $looser2){ - if($order1 <> $order2){ - save_battle('tron', - $this->playersIdsByOrder[$looser1], - $this->playersIdsByOrder[$looser2], - 0, - 'id'); - } - } + if(count($this->looserList) < 2) return; + + foreach($loosers as $$looser1){ + foreach($loosers as $looser2){ + if($looser1->playerIndex == $looser2->playerIndex) continue; + save_battle('tron', $looser1->id, $looser2->id, 0, 'id' ); } - } + } } - private function ApplyWins(){ + + + private function ApplyWins(){ //need to make losers List. simply array of orders - $loosersOrdersArr = array(); - foreach($this->looserList as $order => $looser){ - $loosersOrdersArr[] = $order; + $loosersIndexArr = array(); + foreach($this->looserList as $looser){ + $loosersIndexArr[] = $looser->playerIndex; } - - foreach($this->looserList as $looserOrder => $looserId){ - foreach($playersIdsByOrder as $order=>$player){ - if(!in_array($order,$this->looserList)){ - save_battle('tron', - $this->playersIdsByOrder[$looser], - $player, - 2, - 'id'); - } + foreach($this->loosers as $looser){ + foreach($this->participants as $participant){ + if(in_array($participant->playerIndex,$loosersIndexArr)) continue; + save_battle('tron', $looser->id, $participant->id, 2, 'id'); } } - } public function ApplyScores(){ $this-> ApplyDraws(); $this-> ApplyWins(); - } } \ No newline at end of file diff --git a/src/arenas/tron/Trail.php b/src/arenas/tron/Trail.php index 7361574..9740d18 100755 --- a/src/arenas/tron/Trail.php +++ b/src/arenas/tron/Trail.php @@ -18,15 +18,14 @@ class Trail { public function emptyTrail(){ $this->trail = new SplStack(); } - + public function mergeWith($trailToMerge){ + foreach($trailToMerge as $value) { + $this->trail->add($value); + } + } public function add($value) { if(!$this->trail->isEmpty()) { if(Trail::kind($this->trail->bottom()) !== Trail::kind($value)) { - - // - // throw new TypeError( - // 'items added to a trail must be of the same kind' - // ); return false; } @@ -43,7 +42,7 @@ class Trail { public function __toString(){ return json_encode($this->getTrailAsArray()); } - + public function getTrailAsArray(){ $arr = array(); foreach($this->trail as $coord) { diff --git a/src/arenas/tron/TronGame.php b/src/arenas/tron/TronGame.php index 00edf86..0d55fb6 100755 --- a/src/arenas/tron/TronGame.php +++ b/src/arenas/tron/TronGame.php @@ -4,16 +4,38 @@ class TronGame private $bots; //array of bots public $gameId; private $status; //false => Game ended or not initialised + + private function getAliveBots(){ + $aliveBots = array(); + foreach($this->bots as $bot){ + if($bot->isAlive){ + $aliveBots[] = $bot; + } + } + return $aliveBots; + } - public function get_continue(){ - //count bots alive. if less than 1, game is ended - $count = 0; + private function getBotByPlayerIndex($index){ foreach($this->bots as $bot){ - if( $bot->isAlive == true){ - $count++; + if($bot->playerIndex == $index){ + return $bot; } } - if($count > 1){ + return false; + } + private function initScoring(){ + /* + *Add all alive bots on a ScoreLap object and return it + */ + $scoring = new ScoreLap(); + foreach($this->getAliveBots()as $bot){ + $scoring->addBotOnLap($bot); + } + return $scoring; + } + public function get_continue(){ + //count bots alive. if less than 1, game is ended + if(count($this->getAliveBots()) > 1){ return true; }else{ return false; @@ -28,6 +50,14 @@ class TronGame } return $trailsArr; } + private function get_map_as_an_unique_trail(){ + $trail = new Trail; + foreach($this->bots as $bot){ + $trail->mergeWith($bot->trail); + } + return trail; + + } public function get_lasts_trails(){ //return only the lasts coords for each tail $trailsArr = array(); @@ -37,83 +67,126 @@ class TronGame return $trailsArr; } public function new_lap(){ - // for all alive bots - $logs = ""; - $nbeBots = count($this->bots); - $urls = array(); - $paramToSend = array(); - $board = $this->get_trails(); - //$board = $this->get_lasts_trails(); - $lastsCells = array(); + + if($this->get_continue() === false){ + return false; + } + + $scoreObj = $this->initScoring(); + $aliveBots = $this->getAliveBots(); - $scoring = new ScoreLap(); + //fixed Query parameters + $nbeBots = count($this->bots); + $board = $this->get_trails(); //same for each bot + $initialMapAsATrail = $this->get_map_as_an_unique_trail(); + //Open curl multi + $cmh = curl_multi_init(); + $ch = array(); - for ($botCount = 0; $botCount < $nbeBots; $botCount++){ - if ($this->bots[$botCount]->isAlive){ - - $scoring->addBotOnLap($botCount,$this->bots[$botCount]->id); - $urls[$botCount] = $this->bots[$botCount]->url; - - $paramsToSend[$botCount] = array( + + + foreach($aliveBots as $bot){ + $i = $bot->playerIndex; //because $i is shorter + + $bodyRequestArr[$i] = array( 'game-id' => "".$this->gameId, 'action' => 'play-turn', 'game' => 'tron', 'board' => $board, - 'player-index' => $botCount, // To do: verifier que ça restera le même à chaque tour + 'player-index' => $i, 'players' => $nbeBots ); - } + $data_string = json_encode($bodyRequestArr[$i]); + $ch[$i] = curl_init($bot->url); + curl_setopt($ch[$i], CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($ch[$i], CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($ch[$i], CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch[$i], CURLOPT_POSTFIELDS, $data_string); + curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch[$i], CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json', + 'Content-Length: ' . strlen($data_string)) + ); + curl_multi_add_handle($cmh,$ch[$i]); } - - $responses = $this->get_multi_IAS_Responses($urls,$paramsToSend); - //grow bots'tails - for ($botCount = 0; $botCount < $nbeBots; $botCount++){ - if ($this->bots[$botCount]->isAlive){ + //send the requests + do { + $returnVal = curl_multi_exec($cmh, $runningHandles); + }while($runningHandles > 0); + + //get results + foreach($ch as $playerIndex=>$cr){ + $currentBot = $this->getBotByPlayerIndex($playerIndex); + + // Check for errors + $curlError = curl_error($cr); + $response = curl_multi_getcontent($cr); - if(!$dir = Direction::make($responses[$botCount]['responseArr']['play'])){ - //he loses , non conform response - $scoring-> addLoser($botCount,$this->bots[$botCount]->id); - $this->bots[$botCount]->loose(); - }else{ + if($curlError !== "") { + //erreur curl, he loses + $scoreObj-> addLoser($currentBot); + $currentBot->loose(); + + }elseif(! $arr = json_decode($response,TRUE)){ + //la reponse n'est pas un json, il a perdu + $scoreObj-> addLoser($currentBot); + $currentBot->loose(); - $lastsCells[$botCount] = $this->bots[$botCount]->grow($dir); - - if($lastsCells[$botCount] === false){ - //$loosers[] = $botCount; - $scoring-> addLoser($botCount,$this->bots[$botCount]->id); - $this->bots[$botCount]->loose(); - } - - } + }elseif(Direction::make($arr['play']) === false){ + //tester ici la réponse + //he loose il utilise probablement une de ses propres cases + $scoreObj-> addLoser($currentBot); + $currentBot->loose(); + }elseif($initialMapAsATrail->contains($currentBot->trail->last()->addDirection(Direction::make($arr['play'])))){ //ounch + //le bot tente d'aller sur une case qui était prise au début du round + $scoreObj-> addLoser($currentBot); + $currentBot->loose(); + }else{ + //mettre de coté la direction du bot + $currentBot->nextDir = Direction::make($arr['play']); } + //close curl + curl_multi_remove_handle($cmh, $cr); + curl_close($cr); + } - //test if loose - for ($botCount = 0; $botCount < $nbeBots; $botCount++){ - if ($this->bots[$botCount]->isAlive){ - - //tester si collusion avec les cases actuelles - for( $botCount2 = 0; $botCount2 < $nbeBots; $botCount2++){ - if(($botCount <> $botCount2) - && ($this->bots[$botCount2]->trail->contains($lastsCells[$botCount])) - ){ - - $scoring-> addLoser($botCount,$this->bots[$botCount]->id); - $this->bots[$botCount]->loose(); - break; - } + + $aliveBots = $this->getAliveBots(); + //pour tous les bots encore vivants, on teste si deux d'entre eux ne cibleraient pas la même case + foreach ($aliveBots as $bot1){ + foreach ($aliveBots as $bot2){ + if($bot1-> $playerIndex == $bot2-> $playerIndex) continue; + if($bot1->trail->last()->addDirection($bot1->nextDir) == $bot2->trail->last()->addDirection($bot2->nextDir)){ + //he loose + $scoreObj-> addLoser($bot1); + $bot1->loose(); + break; } } } - //$this->apply_looses($loosersList); + //ok, faire grossir les bots qui restent + foreach($this->getAliveBots() as $bot){ + $bot-> applyNextDir(); + } + + //apply scores: + $scoreObj-> ApplyScores(); + return array( 'last_points' => $this->get_lasts_trails(), - 'loosers' => $scoring->getLoosersList() + 'loosers' => $scoreObj->getLoosersList() ); } + + + private function get_multi_IAS_Responses($iasUrls, $postParams){ + //bug here le resultat retourné ne prend pas les bots ayant déjà perdus + + //same as the get_IAS_Responses function // but more than one bot requested parallely @@ -158,7 +231,7 @@ class TronGame } $res[$i] = array( 'messageSend' => json_encode($postParams[$i]), - 'response' => $response, + 'response' => $response, 'httpStatus' => curl_getinfo($ch[$i])['http_code'], 'responseArr' => $arr ); @@ -222,7 +295,7 @@ class TronGame $startCoord = new Coords($x,$y); $this->bots[$botCount] = new TronPlayer(); - $this->bots[$botCount]->make($bot['id'],$startCoord,$bot['name'],$bot['url']); + $this->bots[$botCount]->make($bot['id'],$startCoord,$bot['name'],$bot['url'],$botCount); if ($this->bots[$botCount]->isAlive === false){ $err .= "Something went wrong for ".$this->bots[$botCount]->getName()."
"; diff --git a/src/arenas/tron/TronPlayer.php b/src/arenas/tron/TronPlayer.php index de123e1..8949332 100755 --- a/src/arenas/tron/TronPlayer.php +++ b/src/arenas/tron/TronPlayer.php @@ -4,12 +4,14 @@ class TronPlayer{ public $id; public $name; public $trail; - private $direction; public $isAlive = true; + public $playerIndex = -1; //if unset is -1 + public $looseCause = ""; + public $nextDir; public function grow(Direction $dir){ $dest = $this->trail->last()->addDirection($dir); - if($dest == false){ + if($dest === false){ $this->loose(); return false; } @@ -17,19 +19,25 @@ class TronPlayer{ $this->trail->add($this->trail->last()->addDirection($dir)); return $this->trail->last(); } + + public function applyNextDir(){ + $this-> grow($this->nextDir); + } + public function loose(){ $this->isAlive = false; $this->trail->emptyTrail(); //error_log($this->name." a perdu"); return false; } - public function make($botId, Coords $initialsCoords,$name,$url){ + public function make($botId, Coords $initialsCoords,$name,$url,$playerIndex = -1){ $this->id = $botId; $this->trail = new Trail; $this->trail->add($initialsCoords); $this->name = $name; $this->url = $url; $this->state = true; + $this->playerIndex = $playerIndex; } public function __construct(){ $this->state = false; diff --git a/src/arenas/tron/functions.php b/src/arenas/tron/functions.php index 0705b1d..b3d9bbc 100755 --- a/src/arenas/tron/functions.php +++ b/src/arenas/tron/functions.php @@ -1,5 +1 @@