diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.gitmodules b/.gitmodules old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/countBattles.txt b/countBattles.txt old mode 100644 new mode 100755 index faf0797..d081bc1 --- a/countBattles.txt +++ b/countBattles.txt @@ -1 +1 @@ -1448 \ No newline at end of file +1836 \ No newline at end of file diff --git a/html/.htaccess b/html/.htaccess old mode 100644 new mode 100755 diff --git a/html/imgs/Arenes-Nimes.jpg b/html/imgs/Arenes-Nimes.jpg old mode 100644 new mode 100755 diff --git a/html/imgs/Bronze_Medal.svg b/html/imgs/Bronze_Medal.svg old mode 100644 new mode 100755 diff --git a/html/imgs/Emoji_u1f4a9.svg b/html/imgs/Emoji_u1f4a9.svg old mode 100644 new mode 100755 diff --git a/html/imgs/Gold_Medal.svg b/html/imgs/Gold_Medal.svg old mode 100644 new mode 100755 diff --git a/html/imgs/Silver_Medal.svg b/html/imgs/Silver_Medal.svg old mode 100644 new mode 100755 diff --git a/html/index.php b/html/index.php old mode 100644 new mode 100755 diff --git a/html/log.txt b/html/log.txt old mode 100644 new mode 100755 diff --git a/html/principe.gif b/html/principe.gif old mode 100644 new mode 100755 diff --git a/html/style.css b/html/style.css old mode 100644 new mode 100755 diff --git a/html/testBotScripts/connectfour.html b/html/testBotScripts/connectfour.html old mode 100644 new mode 100755 diff --git a/html/testBotScripts/index.html b/html/testBotScripts/index.html old mode 100644 new mode 100755 diff --git a/html/testBotScripts/tictactoe.html b/html/testBotScripts/tictactoe.html old mode 100644 new mode 100755 diff --git a/install.sql b/install.sql old mode 100644 new mode 100755 diff --git a/lang/en.php b/lang/en.php old mode 100644 new mode 100755 diff --git a/lang/fr.php b/lang/fr.php old mode 100644 new mode 100755 diff --git a/src/DUEL.php b/src/DUEL.php new file mode 100644 index 0000000..0b158c5 --- /dev/null +++ b/src/DUEL.php @@ -0,0 +1,80 @@ +rank1 = $r1; + $this->rank2 = $r2; + } + private function get_k($rank){ + if ($rank < 1000) return 80; + if ($rank < 2000) return 50; + if ($rank <= 2400) return 30; + return 20; + } + private function changeScores($score){ + $this->rank1 = $this->rank1 + $this->get_k($this->rank1) * ($score - (1/ (1 + pow(10,(($this->rank2 - $this->rank1) / $this->factor))))); + $this->rank2 = $this->rank2 + $this->get_k($this->rank2) * (1 - $score - (1/ (1 + pow(10,(($this->rank1 - $this->rank2) / $this->factor))))); + } + + public function oneWinsAgainstTwo(){ + $this->changeScores(1); + } + public function twoWinsAgainstOne(){ + $this->changeScores(0); + } + public function drawGame(){ + $this->changeScores(0.5); + } +} + + + + + + + + + + + +class ELO +{ + public $rank = 1500; //default rank + + public function __construct($v=1500) { + $this->rank = $v; + } + + private function ELO_get_new_ranks($elo1,$elo2,$score){ + /* + * return an array containing new ELO scores after a battle + * $score : 0 player 2 won + * 0.5 draws + * 1 player 1 won + */ + + //good luck for understanding it + //(see https://blog.antoine-augusti.fr/2012/06/maths-et-code-le-classement-elo/) + return array( + $elo1 + ELO_get_k($elo1) * ($score - (1/ (1 + pow(10,(($elo2 - $elo1) / 400))))), + $elo2 + ELO_get_k($elo2) * (1 - $score - (1/ (1 + pow(10,(($elo1 - $elo2) / 400))))) + ); + } + + + + public function looseAgainst(ELO $winer){ + + } + public function winAgainst(ELO $looser){ + + } + public function drawAgainst(ELO $drawPlayer){ + + } + +} diff --git a/src/PHPMailer b/src/PHPMailer index 7c8b786..1d85f9e 160000 --- a/src/PHPMailer +++ b/src/PHPMailer @@ -1 +1 @@ -Subproject commit 7c8b786228bb9e1561ff60a2d6f7f6ce91be6fee +Subproject commit 1d85f9ef3ecfc42bbc4f3c70d5e37ca9a65f629a diff --git a/src/about.html b/src/about.html old mode 100644 new mode 100755 diff --git a/src/aboutBot.php b/src/aboutBot.php old mode 100644 new mode 100755 diff --git a/src/act.php b/src/act.php old mode 100644 new mode 100755 diff --git a/src/addBot.php b/src/addBot.php old mode 100644 new mode 100755 diff --git a/src/arenas/Battleship/act.php b/src/arenas/Battleship/act.php old mode 100644 new mode 100755 diff --git a/src/arenas/Battleship/doc-en.html b/src/arenas/Battleship/doc-en.html old mode 100644 new mode 100755 diff --git a/src/arenas/Battleship/doc-fr.html b/src/arenas/Battleship/doc-fr.html old mode 100644 new mode 100755 diff --git a/src/arenas/Battleship/functions.php b/src/arenas/Battleship/functions.php old mode 100644 new mode 100755 diff --git a/src/arenas/Battleship/js.js b/src/arenas/Battleship/js.js old mode 100644 new mode 100755 diff --git a/src/arenas/Battleship/public.php b/src/arenas/Battleship/public.php old mode 100644 new mode 100755 diff --git a/src/arenas/Battleship/style.css b/src/arenas/Battleship/style.css old mode 100644 new mode 100755 diff --git a/src/arenas/Battleship/testBot.html b/src/arenas/Battleship/testBot.html old mode 100644 new mode 100755 diff --git a/src/arenas/connectFour/act.php b/src/arenas/connectFour/act.php old mode 100644 new mode 100755 diff --git a/src/arenas/connectFour/doc-en.html b/src/arenas/connectFour/doc-en.html old mode 100644 new mode 100755 diff --git a/src/arenas/connectFour/doc-fr.html b/src/arenas/connectFour/doc-fr.html old mode 100644 new mode 100755 diff --git a/src/arenas/connectFour/functions.php b/src/arenas/connectFour/functions.php old mode 100644 new mode 100755 diff --git a/src/arenas/connectFour/js.js b/src/arenas/connectFour/js.js old mode 100644 new mode 100755 diff --git a/src/arenas/connectFour/public.php b/src/arenas/connectFour/public.php old mode 100644 new mode 100755 diff --git a/src/arenas/connectFour/style.css b/src/arenas/connectFour/style.css old mode 100644 new mode 100755 diff --git a/src/arenas/tictactoe/act.php b/src/arenas/tictactoe/act.php old mode 100644 new mode 100755 diff --git a/src/arenas/tictactoe/doc-en.html b/src/arenas/tictactoe/doc-en.html old mode 100644 new mode 100755 diff --git a/src/arenas/tictactoe/doc-fr.html b/src/arenas/tictactoe/doc-fr.html old mode 100644 new mode 100755 diff --git a/src/arenas/tictactoe/doc.html b/src/arenas/tictactoe/doc.html old mode 100644 new mode 100755 diff --git a/src/arenas/tictactoe/functions.php b/src/arenas/tictactoe/functions.php old mode 100644 new mode 100755 diff --git a/src/arenas/tictactoe/js.js b/src/arenas/tictactoe/js.js old mode 100644 new mode 100755 diff --git a/src/arenas/tictactoe/public.php b/src/arenas/tictactoe/public.php old mode 100644 new mode 100755 diff --git a/src/arenas/tictactoe/style.css b/src/arenas/tictactoe/style.css old mode 100644 new mode 100755 diff --git a/src/arenas/tictactoe/testBot.html b/src/arenas/tictactoe/testBot.html old mode 100644 new mode 100755 diff --git a/src/arenas/tron/Coords.php b/src/arenas/tron/Coords.php new file mode 100755 index 0000000..9fdb5e4 --- /dev/null +++ b/src/arenas/tron/Coords.php @@ -0,0 +1,33 @@ + Coords::$max) || ($y < Coords::$min) || ($y > Coords::$max)){ + //out of limits + error_log("a bot out of limits"); + return false; + } + + $this->x = $x; + $this->y = $y; + + + } + + public function __toString(){ + return $this->x.",".$this->y; + + } + + public function addDirection(Direction $dir){ + return new Coords( + $this->x + $dir->deltaX, + $this->y + $dir->deltaY + ); + } +} \ No newline at end of file diff --git a/src/arenas/tron/Direction.php b/src/arenas/tron/Direction.php new file mode 100755 index 0000000..69105e2 --- /dev/null +++ b/src/arenas/tron/Direction.php @@ -0,0 +1,95 @@ +value = 0; + } + + private function setValue($value){ + $this->value = $value; + switch ($value){ + case Direction::$bottom: + $this->deltaY = -1; + $this->deltaX = 0; + break; + case Direction::$top: + $this->deltaY = 1; + $this->deltaX = 0; + break; + case Direction::$left: + $this->deltaY = 0; + $this->deltaX = -1; + break; + case Direction::$right: + $this->deltaY = 0; + $this->deltaX = 1; + break; + } + } + + public function __toString(){ + switch ($this->value){ + case Direction::$top: + return "y+"; + break; + case Direction::$bottom: + return "y-"; + break; + case Direction::$left: + return "x-"; + break; + case Direction::$right: + return "x+"; + break; + } + } + + public static function make($str){ + $dir = new Direction(); + switch((string)$str){ + case "x+": + $dir->setValue(Direction::$right); + break; + case "x-": + $dir->setValue(Direction::$left); + break; + case "y+": + $dir->setValue(Direction::$top); + break; + case "y-": + $dir->setValue(Direction::$bottom); + break; + default: + //error_log("expected 'x+', 'x-', 'y+' or 'y-'". (string)$str."received."); + return false; + //throw new InvalidDirectionException("expected 'x+', 'x-', 'y+' or 'y-'". (string)$str."received."); + break; + } + return $dir; + } + public function opposite(){ + $opposites = array( + Direction::$top => Direction::$bottom, + Direction::$bottom => Direction::$top, + Direction::$left => Direction::$right, + Direction::$right => Direction::$left + ); + + $opposite = new Direction(); + $opposite->setValue($opposites[$this->value]); + return $opposite; + } +} \ No newline at end of file diff --git a/src/arenas/tron/ScoreLap.php b/src/arenas/tron/ScoreLap.php new file mode 100644 index 0000000..eb6f7a2 --- /dev/null +++ b/src/arenas/tron/ScoreLap.php @@ -0,0 +1,64 @@ +participants[] = $bot; + } + + public function addLoser(TronPlayer $bot){ + $this->loosers[] = $bot; + } + public function __construct() { + $this->participants= array(); + $this->loosers = array(); + } + + public function getLoosersList(){ + //return losers as a digest array + $arr = array(); + + foreach($this->loosers as $looser){ + $arr[] = array("id" => $looser->id,"order" => $looser->playerIndex); + } + return $arr; + } + + private function ApplyDraws(){ + + //apply draw match to all losers + if(count($this->loosers) < 2) return; + + foreach($this->loosers as $looser1){ + foreach($this->loosers as $looser2){ + if($looser1->playerIndex == $looser2->playerIndex) continue; + save_battle('tron', $looser1->id, $looser2->id, 0, 'id' ); + } + } + } + + + private function ApplyWins(){ + + //need to make losers List. simply array of orders + $loosersIndexArr = array(); + foreach($this->loosers as $looser){ + $loosersIndexArr[] = $looser->playerIndex; + } + 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 new file mode 100755 index 0000000..17604d0 --- /dev/null +++ b/src/arenas/tron/Trail.php @@ -0,0 +1,73 @@ +trail = new SplStack(); + } + + public function last() { + if($this->trail->isEmpty()){ + return false; + } + return $this->trail->top(); + } + + public function emptyTrail(){ + $this->trail = new SplStack(); + } + public function getTrail(){ + return $this->trail; + } + public function mergeWith($trailToMerge){ + if($trailToMerge->getTrail()->isEmpty()) return; + + foreach($trailToMerge->getTrail() as $value) { + $this->trail->push($value); + } + + } + + public function add($value) { + if(!$this->trail->isEmpty()) { + if(Trail::kind($this->trail->bottom()) !== Trail::kind($value)) { + return false; + } + + if($this->contains($value)) { + //throw new AlreadyBeenAddedException( + // 'value has already been added to the trail'.$value.'|'.$this->__toString() + //); + return false; + } + } + + $this->trail->push($value); + } + public function __toString(){ + return json_encode($this->getTrailAsArray()); + } + + public function getTrailAsArray(){ + $arr = array(); + foreach($this->trail as $coord) { + $arr[] = array($coord->x,$coord->y); + } + return $arr; + } + public function contains($searchedValue) { + foreach($this->trail as $value) { + if($value == $searchedValue) return true; + } + + return false; + } + + public static function kind($var) { + $type = gettype($var); + if($type == 'object') $type .= ' ' . get_class($var); + return $type; + } +} diff --git a/src/arenas/tron/TronGame.php b/src/arenas/tron/TronGame.php new file mode 100755 index 0000000..f49905e --- /dev/null +++ b/src/arenas/tron/TronGame.php @@ -0,0 +1,253 @@ + Game ended or not initialised + + private function getAliveBots(){ + $aliveBots = array(); + foreach($this->bots as $bot){ + if($bot->isAlive){ + $aliveBots[] = $bot; + } + } + return $aliveBots; + } + + private function getBotByPlayerIndex($index){ + foreach($this->bots as $bot){ + if($bot->playerIndex == $index){ + return $bot; + } + } + 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; + } + } + + public function get_trails(){ + //return all trails for draw svg + $trailsArr = array(); + foreach($this->bots as $bot){ + $trailsArr[] = $bot->trail->getTrailAsArray(); + } + //error_log("*********".json_encode($trailsArr,true)."********"); + 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(); + foreach($this->bots as $bot){ + $trailsArr[] = $bot->trail->last(); + } + return $trailsArr; + } + public function new_lap(){ + + if($this->get_continue() === false){ + return false; + } + + $scoreObj = $this->initScoring(); + $aliveBots = $this->getAliveBots(); + + //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(); + + + + 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' => $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]); + } + + //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($curlError !== "") { + + //erreur curl, he loses + $scoreObj-> addLoser($currentBot); + $currentBot->loose(); + error_log("no curl response".$playerIndex); //debug + + }elseif(! $arr = json_decode($response,TRUE)){ + + //la reponse n'est pas un json, il a perdu + $scoreObj-> addLoser($currentBot); + $currentBot->loose(); + error_log("la reponse est pas JSON".$playerIndex); //debug + + }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(); + error_log("La reponse ne contient pas une direction".$playerIndex); //debug + + }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(); + error_log("Il joue sur une case deja prise".$playerIndex); //debug + }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); + + } + + $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; + } + } + } + + //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' => $scoreObj->getLoosersList() + ); + } + + + + + + public function init_game(){ + //send init messages to bots + $logs = ""; + $fullLogs = ""; + $nbeBots = count($this->bots); + for ($botCount = 0; $botCount < $nbeBots; $botCount++){ + $messageArr = array( + 'game-id' => "".$this->gameId, + 'action' => 'init', + 'game' => 'tron', + 'board' => '', + 'players' => $nbeBots, + 'player-index' => $botCount + ); + + $resp = get_IA_Response($this->bots[$botCount]->url,$messageArr); + $fullLogs .= 'Arena send to '.$this->bots[$botCount]->name.''.htmlentities($resp['messageSend']).'
+ HTTP status: '.htmlentities($resp['httpStatus']).'
+ Bot anwser: '.htmlentities($resp['response']).'
'; + $logs.="Init message send to ".$this->bots[$botCount]->name."
"; + } + return array($logs,$fullLogs); + } + + public function __construct($botsInfos){ + $this->gameId = get_unique_id(); + $this->bots = array(); + $positions = array(); + $botCount = 0; + $err = ""; + + //print_r($botsInfos); + + foreach($botsInfos as $bot){ + //find a random start position + do{ + $x = rand(1,999); + $y = rand(1,999); + }while(in_array($x.",".$y,$positions)); + + $positions[] = $x.",".$y; + $startCoord = new Coords($x,$y); + + $this->bots[$botCount] = new TronPlayer(); + $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()."
"; + }else{ + $botCount++; + } + } + return $err; + } +} \ No newline at end of file diff --git a/src/arenas/tron/TronPlayer.php b/src/arenas/tron/TronPlayer.php new file mode 100755 index 0000000..8949332 --- /dev/null +++ b/src/arenas/tron/TronPlayer.php @@ -0,0 +1,45 @@ +trail->last()->addDirection($dir); + if($dest === false){ + $this->loose(); + return false; + } + + $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,$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; + } +} \ No newline at end of file diff --git a/src/arenas/tron/act.php b/src/arenas/tron/act.php new file mode 100755 index 0000000..d88e0ee --- /dev/null +++ b/src/arenas/tron/act.php @@ -0,0 +1,91 @@ + $r[0], 'name' => $r[1], 'url' => $r[2]); + } + + + $botsArrayTemp = json_decode($_POST['bots']); + //error_log($_POST['bots']); + $botsInfos = array(); + + foreach($botsArrayTemp as $id){ + //tester si le bot existe dans la bdd + if((isset($botsFullArr[$id])) && ($id > 0)){ + $botsInfos[] = $botsFullArr[$id]; + } + } + + $game = new TronGame($botsInfos); + + + $logs = $game->init_game(); + + echo json_encode(array( + 'status' => $game->get_continue(), + 'logs' => $logs, + 'gameId' => $game->gameId, + 'botsPosition' => $game->get_lasts_trails() + )); + + $_SESSION['game'] = serialize($game); + + + die; + break; + case "play": + $logs = ""; + if(!isset($_SESSION['game'])){ + echo '{"status":"error"}'; + die; + } + + $game = unserialize($_SESSION['game']); + + if($game->gameId <> $_POST['gameId']){ + //sometimes if an ajax callback is applied after init an other game + echo '{"status":"error"}'; + die; + } + $lap = $game->new_lap(); + if($game->get_continue()){ + $continue = 1; + }else{ + $continue = 0; + } + echo json_encode(array( + 'gameId' => $game->gameId, + 'continue' => $continue, + 'lap' => $lap + )); + $_SESSION['game'] = serialize($game); + die; + + break; + default: + break; + +} \ No newline at end of file diff --git a/src/arenas/tron/doc-en.html b/src/arenas/tron/doc-en.html new file mode 100755 index 0000000..f764fef --- /dev/null +++ b/src/arenas/tron/doc-en.html @@ -0,0 +1,175 @@ +

How Tron Fights Works

+

Game's rules (excluding technical specs)

+

Each bot starts from a point randomly selected by the arena.

+

At each turn, bots are asked to grow one square. they can choose the direction.

+

If a bot strikes a cell already taken by its trail or that of another, it loses.

+

It is not turn-based, bots are playinig simultaneously, so they can lose by choosing the same destination cell as another snake.

+

Example:

+ + + + + + + + + + + +
9
8
7
6
5
4oOoO
3
2
1
0123456789
+

If in the same turn the green snake and the red snake decide to go respectively to the left and to the right, they will telescope and both will lose.

+ + + + + + + + + + + +
9
8
7
6
5
4): :(
3
2
1
0123456789
+

When a snake dies, (when a bot loses) its tail is erased and cells taken by it become free for snakes still alive.

+

The game ends when there are less than two snakes left

+

Grid

+ + +

Communications between the arena and the bots

+

The arena does send http (s) requests to the bots.

+ + +

Initialization of the game

+

The arena (this site) sends the following exemple message to your bot:

+
+{"game-id":"1679","action":"init","game":"tron","board":"","players":4,"player-index":2}
+
+ + +

Your bot must respond with an array in json format, like this:

+
+{"name":"botName"}
+
+

+The arena does not currently verify this response, the init step has been inserted to ensure compatibility with Bolosseum. If your bot answers a blank page at this stage (action = init), it will work as part of botsarena. +

+ +

Game's laps

+

Exemple of arena's message send on the first lap:

+ + +

Exemple of arena's message send after some laps:

+
+{"game-id":"1680","action":"play-turn","game":"tron","board":[[[687,110],[687,111],[686,111],[686,110],[686,109],[686,108],[686,107],[685,107],[685,108],[685,109],[684,109],[684,110],[684,111],[684,112],[684,113],[683,113],[682,113],[681,113],[681,114],[681,115],[681,116],[680,116],[680,117],[679,117],[679,116],[679,115],[679,114],[679,113],[679,112],[679,111],[679,110],[679,109],[678,109],[678,108],[677,108],[676,108],[676,107],[676,106],[676,105],[676,104],[676,103],[675,103],[674,103],[674,102],[673,102],[672,102],[672,101],[671,101],[670,101],[669,101],[669,102],[669,103],[669,104],[669,105],[669,106],[669,107],[668,107],[668,108],[668,109],[668,110],[668,111],[668,112],[667,112],[667,111],[667,110],[666,110],[666,109],[666,108],[665,108],[664,108],[664,107],[664,106],[663,106],[663,107],[663,108],[662,108],[661,108],[660,108],[660,107],[659,107],[659,106],[658,106],[657,106],[657,105],[657,104],[656,104],[656,103],[655,103],[655,102],[655,101],[654,101],[654,102],[654,103],[654,104],[653,104],[653,103],[653,102],[653,101],[653,100],[652,100],[651,100],[651,101],[651,102],[651,103],[651,104],[650,104],[650,105],[650,106],[649,106],[649,105],[648,105]],[[100,225],[100,226],[100,227],[100,228],[100,229],[100,230],[100,231],[99,231],[98,231],[98,232],[97,232],[96,232],[96,231],[96,230],[96,229],[96,228],[96,227],[96,226],[96,225],[96,224],[96,223],[95,223],[95,222],[94,222],[94,221],[94,220],[93,220],[92,220],[92,219],[92,218],[92,217],[92,216],[92,215],[91,215],[91,214],[90,214],[89,214],[89,213],[89,212],[88,212],[88,213],[88,214],[87,214],[87,213],[86,213],[86,214],[86,215],[85,215],[85,214],[84,214],[84,215],[83,215],[83,216],[83,217],[82,217],[82,216],[81,216],[81,215],[80,215],[80,216],[79,216],[79,215],[79,214],[78,214],[77,214],[77,213],[77,212],[76,212],[75,212],[75,211],[75,210],[75,209],[74,209],[74,210],[74,211],[73,211],[73,210],[72,210],[72,209],[71,209],[71,210],[70,210],[70,209],[69,209],[68,209],[68,210],[68,211],[67,211],[67,210],[67,209],[67,208],[66,208],[66,207],[66,206],[66,205],[66,204],[66,203],[65,203],[65,204],[64,204],[64,203],[63,203],[63,204],[63,205],[63,206],[62,206],[61,206],[61,207],[60,207],[60,208],[59,208]]],"player-index":0,"players":2}
+
+

Following fields are as in the previous paragraph:

+ +

Not same fields are:

+ +

The map / the board

+

It is contained on "board" field. All the cells taken by each player are writted in.

+ +It is composed of several subarrays / subobjects (depending on your programming language). +the sub-tables haved the following form: +