IAS/connectfour.php

404 lines
13 KiB
PHP
Raw Normal View History

2016-06-13 10:02:22 +02:00
<?php
2016-06-15 01:09:21 +02:00
/*
Bot for connectfour https://botsarena.tinad.fr/connectFour
by Gnieark https://blog-du-grouik.tinad.fr/ june 2016
GNU GPL License
+--+--+--+--+--+--+--+
5 | | | | | | | |
+--+--+--+--+--+--+--+
4 | | | | | | | |
+--+--+--+--+--+--+--+
3 | | | | | | | |
+--+--+--+--+--+--+--+
2 | | | | | | | |
+--+--+--+--+--+--+--+
1 | | | | | | | |
+--+--+--+--+--+--+--+
0 | | | | | | | |
+--+--+--+--+--+--+--+
0 1 2 3 4 5 6
*/
2016-06-13 10:02:22 +02:00
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
2016-06-17 00:59:25 +02:00
function can_win($line,$myChar,$depth=0){
2016-06-15 01:09:21 +02:00
//retourne la position du caractere a remplacer dans la ligne pour gagner
2016-06-17 00:59:25 +02:00
$arr=array();
if($depth == 0){
if (strpos($line,"+".$myChar.$myChar.$myChar) !== false ){
$arr[] = strpos($line,"+".$myChar.$myChar.$myChar);
}
if (strpos($line,$myChar."+".$myChar.$myChar) !== false ){
$arr[] = strpos($line,$myChar."+".$myChar.$myChar) + 1;
}
if (strpos($line,$myChar.$myChar."+".$myChar) !== false ){
$arr[] = strpos($line,$myChar.$myChar."+".$myChar) + 2;
}
if (strpos($line,$myChar.$myChar.$myChar."+") !== false ){
$arr[] = strpos($line,$myChar.$myChar.$myChar."+") + 3;
}
}else{
if (strpos($line,"+".$myChar.$myChar."+") !== false ){
$arr[] = strpos($line,"+".$myChar.$myChar."+");
$arr[] = strpos($line,"+".$myChar.$myChar."+") + 3;
}
if (strpos($line,"+".$myChar."+".$myChar) !== false ){
$arr[] = strpos($line,"+".$myChar."+".$myChar);
$arr[] = strpos($line,"+".$myChar."+".$myChar) + 2;
}
if (strpos($line,$myChar."+".$myChar."+") !== false ){
$arr[] = strpos($line,$myChar."+".$myChar."+") + 1;
$arr[] = strpos($line,$myChar."+".$myChar."+") + 3;
}
2016-06-13 22:13:07 +02:00
}
2016-06-17 00:59:25 +02:00
return $arr;
2016-06-13 21:52:45 +02:00
}
2016-06-15 19:21:57 +02:00
function can_loose($line,$hisChar,$depth=0){
2016-06-17 00:59:25 +02:00
//je pourrai perdre aux 2 prochains tours de jeu
// retourne la place du caractere à remplacer pour éviter ça
$arr=array();
2016-06-15 19:19:27 +02:00
if ($depth == 0){
2016-06-17 00:59:25 +02:00
2016-06-15 19:19:27 +02:00
if (strpos($line,"+".$hisChar.$hisChar.$hisChar) !== false ){
2016-06-17 00:59:25 +02:00
$arr[] = strpos($line,"+".$hisChar.$hisChar.$hisChar);
2016-06-15 19:19:27 +02:00
}
if (strpos($line,$hisChar."+".$hisChar.$hisChar) !== false ){
2016-06-17 00:59:25 +02:00
$arr[] = strpos($line,$hisChar."+".$hisChar.$hisChar) + 1;
2016-06-15 19:19:27 +02:00
}
if (strpos($line,$hisChar.$hisChar."+".$hisChar) !== false ){
2016-06-17 00:59:25 +02:00
$arr[] = strpos($line,$hisChar.$hisChar."+".$hisChar) + 2;
2016-06-15 19:19:27 +02:00
}
if (strpos($line,$hisChar.$hisChar.$hisChar."+") !== false ){
2016-06-17 00:59:25 +02:00
$arr[] = strpos($line,$hisChar.$hisChar.$hisChar."+") + 3;
2016-06-15 19:19:27 +02:00
}
2016-06-17 00:59:25 +02:00
2016-06-15 19:19:27 +02:00
}else{
if (strpos($line,"+".$hisChar.$hisChar."+") !== false ){
2016-06-17 00:59:25 +02:00
$arr[] = strpos($line,"+".$hisChar.$hisChar."+");
$arr[] = strpos($line,"+".$hisChar.$hisChar."+") +3;
2016-06-15 19:19:27 +02:00
}
2016-06-16 20:38:31 +02:00
if(strpos($line,"+".$hisChar."+".$hisChar."+") !== false ){
2016-06-17 00:59:25 +02:00
$arr[] = strpos($line,"+".$hisChar."+".$hisChar."+");
$arr[] = strpos($line,"+".$hisChar."+".$hisChar."+") + 2;
$arr[] = strpos($line,"+".$hisChar."+".$hisChar."+") + 4;
2016-06-16 20:38:31 +02:00
}
2016-06-15 01:09:21 +02:00
}
2016-06-17 00:59:25 +02:00
return $arr;
2016-06-15 01:09:21 +02:00
2016-06-15 17:22:23 +02:00
}
2016-06-17 00:59:25 +02:00
function array_merge_and_increment_rigth ($arr1,$arr2,$incr){
foreach($arr2 as $v){
$arr1[] = $v + $incr;
}
return $arr1;
}
function analize($line,$me,$opponent,$isVertical,$decalageX){
/*
* Etudie les lignes fournies
* Joue si une case est gagnante
* Sinon, "peuple" des variables
* qui permettront de prendre une décision
*/
static $colForNoLose = array();
static $colForNoLose1 = array();
static $canWinDepth1 = array();
if(count(can_win($line,$me,0)) > 0){
if($isVertical){
echo '{"play":'.$decalageX.'}';
}else{
echo '{"play":'.(can_win($line,$me,0)[0] + $decalageX).'}';
}
die;
}
if (count(can_loose($line,$opponent,0)) > 0){
if($isVertical){
$colForNoLose[] = $decalageX;
}else{
$colForNoLose = array_merge_and_increment_rigth($colForNoLose ,can_loose($line,$opponent,0),$decalageX);
}
}
if (count(can_loose($line,$opponent,1)) > 0 ){
if($isVertical){
$colForNoLose1[] = $decalageX;
}else{
$colForNoLose1 = array_merge_and_increment_rigth($colForNoLose1 ,can_loose($line,$opponent,1),$decalageX);
}
}
if(count(can_win($line,$opponent,1)) > 0){
if($isVertical){
$canWinDepth1[] = $decalageX;
}else{
$canWinDepth1= array_merge_and_increment_rigth($canWinDepth1, can_win($line,$me,1), $decalageX);
}
}
return array(
'colForNoLose' => $colForNoLose,
'colForNoLose1' => $colForNoLose1,
'canWinDepth1' => $canWinDepth1
);
}
2016-06-15 17:22:23 +02:00
function should_opponent_win_if_i_play_at($map,$me,$opponent,$colToPlay){
//j'ouvre l'a possibilité à l'adversaire de jouer au dessus de mon pion
// est-ce une connerie?
if(($map[4][$colToPlay] == $me) OR ($map[4][$colToPlay] == $opponent)){
//top of the grid
return false;
}
2016-06-15 19:23:38 +02:00
for($y = 0; (($map[$y][$colToPlay] <> "+") && ($map[$y][$colToPlay] <> "-")); $y++){
2016-06-15 17:22:23 +02:00
}
$map[$y][$colToPlay] = $me;
2016-06-15 19:19:27 +02:00
$map[$y +1][$colToPlay] = "$opponent";
$y++;
if(isset($map[$y +1][$colToPlay])){
$map[$y +1][$colToPlay] = "+";
}
2016-06-15 17:22:23 +02:00
//tester les lignes qui passent pas $y+1,$colToPlay
2016-06-15 19:19:27 +02:00
$loseStr = $opponent.$opponent.$opponent.$opponent;
//horizontale
$line="";
for($x=0; $x < 7; $x++){
$line.=$map[$y][$x];
}
if(strpos($line,$loseStr) !== false){
return true;
}
//diagonal /
$line="";
if($colToPlay > $y){
$kx=$colToPlay - $y;
$ky = 0;
}else{
$kx = 0;
$ky = $y - $colToPlay;
}
while(isset($map[$ky][$kx])){
$line.=$map[$ky][$kx];
$kx++;
$ky++;
}
if(strpos($line,$loseStr) !== false){
return true;
}
//diagional \
$line = "";
$kx = $colToPlay;
$ky = $y;
2016-06-17 00:59:25 +02:00
while(isset($map[$ky -1][$kx +1])){
2016-06-15 19:19:27 +02:00
$kx++;
$ky--;
}
2016-06-17 00:59:25 +02:00
2016-06-15 19:19:27 +02:00
while(isset($map[$ky][$kx])){
$line.=$map[$ky][$kx];
$kx--;
2016-06-17 00:59:25 +02:00
$ky++;
2016-06-15 19:19:27 +02:00
}
if(strpos($line,$loseStr) !== false){
return true;
}
return false;
2016-06-13 11:17:52 +02:00
}
2016-06-15 19:19:27 +02:00
2016-06-13 16:12:08 +02:00
//replace "" by " ", it will simplify my code.
2016-06-15 09:54:01 +02:00
$in=str_replace('""','"-"',file_get_contents('php://input'));
2016-06-13 13:53:28 +02:00
2016-06-13 10:02:22 +02:00
$params=json_decode($in, TRUE);
switch($params['action']){
case "init":
echo '{"name":"Gnieark"}';
break;
case "play-turn":
2016-06-15 01:09:21 +02:00
//find $opponent and clean grid
2016-06-13 16:12:08 +02:00
for($x = 0; $x < 7 ; $x++){
for($y = 0; $y < 6 ; $y++){
2016-06-15 01:09:21 +02:00
//find opponent
2016-06-15 09:54:01 +02:00
if(($params['board'][$y][$x] <> "-" ) && ($params['board'][$y][$x] <> $params['you'] )){
2016-06-13 16:12:08 +02:00
$opponent= $params['board'][$y][$x];
}
2016-06-15 01:09:21 +02:00
//tester si la case est jouable (s'il y a un support en dessous)
2016-06-15 09:54:01 +02:00
if ($params['board'][$y][$x] == "-" ){
//AND (($y==0) OR ($params['board'][$y - 1][$x] !== "-"))
//){
2016-06-15 01:09:21 +02:00
//la case est jouable, je la marque par un "+"
2016-06-15 09:54:01 +02:00
if($y == 0){
$params['board'][$y][$x] = "+";
}elseif(($params['board'][$y -1 ][$x] !== "-") AND ($params['board'][$y -1 ][$x] !== "+")){
$params['board'][$y][$x] = "+";
}else{}
2016-06-15 01:09:21 +02:00
}
2016-06-13 16:12:08 +02:00
}
}
if((!isset($opponent)) && ($params['you'] == "X")){
$opponent="O";
}elseif(!isset($opponent)){
$opponent="X";
}
2016-06-13 17:46:54 +02:00
2016-06-15 01:09:21 +02:00
//transformer la grille en lignes horizontales, verticales et diagonales
//verticales
for($x = 0; $x <7; $x ++){
$colStr="";
for($y = 0; $y <6; $y ++){
$colStr.= $params['board'][$y][$x];
}
2016-06-17 00:59:25 +02:00
$choice = analize($colStr,$params['you'],$opponent,true,$x);
2016-06-15 01:09:21 +02:00
}
//horizontales
for($y = 0; $y <6; $y ++){
$lnStr="";
for($x = 0; $x <7; $x ++){
$lnStr.= $params['board'][$y][$x];
}
2016-06-17 00:59:25 +02:00
$choice = analize($lnStr,$params['you'],$opponent,false,0);
2016-06-15 01:09:21 +02:00
}
//tester seulement les diagonales >= 4 cases
for ($k = 0; $k < 4; $k ++){
//diagonale /
$diagStr="";
for($x=$k , $y=0; isset($params['board'][$y][$x]); $x++, $y++){
$diagStr.=$params['board'][$y][$x];
}
2016-06-17 00:59:25 +02:00
$choice = analize($diagStr,$params['you'],$opponent,false,$k);
2016-06-15 01:09:21 +02:00
//diagonale \
$diagStr="";
for($x=$k , $y=5; isset($params['board'][$y][$x]); $x++, $y--){
$diagStr.=$params['board'][$y][$x];
}
2016-06-17 00:59:25 +02:00
$choice = analize($diagStr,$params['you'],$opponent,false,$k);
2016-06-15 01:09:21 +02:00
}
for ($k = 0; $k < 3; $k ++){
//diagonale /
$diagStr="";
for($x = 0, $y = $k ; isset($params['board'][$y][$x]); $x++, $y++){
$diagStr.=$params['board'][$y][$x];
}
2016-06-17 00:59:25 +02:00
$choice = analize($diagStr,$params['you'],$opponent,false,0);
2016-06-15 01:09:21 +02:00
}
for ($k = 3 ; $k < 6 ; $k++){
//diagonales \
$diagStr="";
for($x=0 , $y=$k; isset($params['board'][$y][$x]); $x++, $y--){
$diagStr.=$params['board'][$y][$x];
}
2016-06-17 00:59:25 +02:00
$choice = analize($diagStr,$params['you'],$opponent,false,0);
2016-06-15 01:09:21 +02:00
}
2016-06-17 00:59:25 +02:00
//print_r($choice);
2016-06-15 01:09:21 +02:00
//si j'arrive là, je ne gagne pas à ce tour
2016-06-17 00:59:25 +02:00
//liste des cases possible moins celles à éviter
$colAvailable=array();
2016-06-15 01:09:21 +02:00
for($i=0;$i<7;$i++){
2016-06-15 19:19:27 +02:00
if((($params['board'][5][$i] == "+") OR ($params['board'][5][$i] == "-"))
AND (!should_opponent_win_if_i_play_at($params['board'],$params['you'],$opponent,$i)))
{
2016-06-15 01:09:21 +02:00
$colAvailable[]=$i;
}
}
2016-06-17 00:59:25 +02:00
if(count($colAvailable) == 0){
//on risque de perdre au prochain tour
for($i=0;$i<7;$i++){
if(($params['board'][5][$i] == "+") OR ($params['board'][5][$i] == "-")){
2016-06-15 19:19:27 +02:00
$colAvailable[]=$i;
}
}
2016-06-17 00:59:25 +02:00
}
2016-06-15 19:19:27 +02:00
2016-06-17 00:59:25 +02:00
if(count($choice['colForNoLose']) > 0){
//intersection entre $choice['colForNoLose'] et $colAvailable
$intersection = array_intersect($choice['colForNoLose'],$colAvailable);
if(count($intersection) > 0){
shuffle($intersection);
echo '{"play":'.$intersection[0].'}';
die;
}else{
//on pourra perdre au prochain tour, tant pis
shuffle($choice['colForNoLose']);
echo '{"play":'.$choice['colForNoLose'][0].'}';
die;
}
}
$colForNoLose1 = array_unique($choice['colForNoLose1']);
$canWinDepth1 = array_unique($choice['canWinDepth1']);
$intersection = array_intersect($colForNoLose1,$colAvailable,$canWinDepth1);
if(count($intersection) > 0){
shuffle($intersection);
echo '{"play":'.$intersection[0].'}';
die;
}
$intersection = array_intersect($colForNoLose1,$colAvailable);
if(count($intersection) > 0){
shuffle($intersection);
echo '{"play":'.$intersection[0].'}';
die;
}
$intersection = array_intersect($colForNoLose1,$canWinDepth1);
if(count($intersection) > 0){
shuffle($intersection);
echo '{"play":'.$intersection[0].'}';
die;
}
//still there? random
2016-06-15 01:09:21 +02:00
shuffle($colAvailable);
echo '{"play":'.$colAvailable[0].'}';
2016-06-13 10:02:22 +02:00
break;
default:
break;
2016-06-13 17:46:54 +02:00
}
2016-06-17 00:59:25 +02:00