<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="author" content="Gnieark" /> <title>ConnectFour's Ludus</title> <style type="text/css"> body{width:100%; font-size:100%; line-height:140%; word-wrap:break-word; text-rendering:optimizelegibility; margin:0 auto; font-family : "lucida grande", "gill sans", arial, sans-serif; left:auto;} header{ background-color:#A60800; width: 100%; overflow: hidden; height: auto;} header h1{display: block; font-size:300%; color:#FFF;float: left; margin-left: 5%;} header nav{display: block; width: 45%; color:#FFF; float: right;} #menus{ margin-left: 50px; width:100%; display: table;} #menus a{color: #fff; display: table-cell; text-decoration: none;text-align: center;border-radius: 15px 15px 0px 0px;} #menus a.selected{color:#202020; background-color:#fff;} footer{height: 70px; display: block; color: #343638; font-size: 11pt; line-height: 15pt; margin: 0; padding-top: 15pt; overflow-x: hidden; box-sizing: border-box; background-image: -webkit-linear-gradient(top, #f5f5f5,#e9e9e9); border-top: 1px solid #bebebe; color: #999; font-size: 12px; line-height: 1.5em; text-align: center;width: 100%;} footer a {margin:0px 15px 0px 15px; color: #666;text-decoration: none; font-weight: normal;} #languages{float: right; text-align: right;} section{margin: 0 auto; width: 90%;} article{float: right; width:70%;} aside{float:left; width: 28%; border-right: 1px dashed green;} aside table {width: 90%;} aside table tr td{width: 33%;} aside table tr td input, aside table tr td select {width: 100%;} .center{text-align: center;} aside p img{ width: 100%; max-width:342px;} form textarea, form input, form select {width:100%;} form input[type=checkbox], form input[type=radio] { width:15px; } form label {float:left; width:40%; margin-right:0.5em; padding-top:0.2em; text-align:right;} pre{ font-style: normal;font-size: 16px; margin-left: 32px;font-family: Consolas, "Times New Roman", Verdana; border-left: 4px solid #CCC; padding-left: 8px;} .battleGrid{display:table-cell; padding-left:10px; border-collapse:collapse; margin: 20px 20px 20px 20px;} .battleGrid tr{} .battleGrid td{border: 1px dashed green; text-align: center; font-weight: bold;width:2em; height: 2em; vertical-align: middle;} .winCase{background-color:red;} .hidden{display: none;} #logs{font-size: 70%;} </style> <script> var board=[["","","","","","",""], ["","","","","","",""], ["","","","","","",""], ["","","","","","",""], ["","","","","","",""], ["","","","","","",""]]; var currentPlayer=1; var gameId="0"; function wins(player){ addLog('player ' + player + ' wins'); } function createElem(type,attributes){ var elem=document.createElement(type); for (var i in attributes) {elem.setAttribute(i,attributes[i]);} return elem; } function addLog(message){ var p=createElem('p'); p.innerHTML=message; document.getElementById('logs').appendChild(p); } function changePlayerType(player,newValue){ if(newValue == "bot"){ document.getElementById('url' + player).disabled=""; }else{ document.getElementById('url' + player).disabled="disabled"; } } function playingAT(col){ //hide buttons document.getElementById("playerButtons").setAttribute("class", "hidden"); if(currentPlayer == 1){ var symbol= "X"; }else{ var symbol="O"; } if(board[5][col]!== ""){ addLog('Player ' + currentPlayer + ', symbol ' + symbol + ' wants to play on column ' + col + ' but that column is already full. He loses.'); return; } //find the first line empty var i=0; for(i = 0; i < 6 , board[i][col] !== ""; i++){ //nothing juste a counter } board[i][col]=symbol; document.getElementById('td' + col + '_' + i).innerHTML = symbol; addLog('player ' + currentPlayer + ', symbol ' + symbol + ' played col ' + col); //does he win? var x=col; var y=i; var searchValue=""; for (var k=0; k < 4; k++){ searchValue +=symbol; } //horizontaly var line=""; for (var k=0; k < 7; k++){ if(board[y][k] == ""){ line += " "; }else{ line += board[y][k]; } } if (line.indexOf(searchValue) > -1){ wins(currentPlayer); return; } //verticaly var line=""; for (var k=0; k < 6; k++){ if(board[k][x] == ""){ line += " "; }else{ line += board[k][x]; } } if (line.indexOf(searchValue) > -1){ wins(currentPlayer); return; } //diagonal \ /* * diagonal is an affin function: * y=-x+b */ //find b var b = parseInt(y + x); if (b < 6){ //first point of the diagonal has x=0; var kx = 0; var ky = b; //:aga: }else{ //first point of the diagonal has y=5 var kx = b - 5; var ky = 5; } var line=""; var lx , ly; for (lx = kx, ly = ky; (lx < 7) && (ly > -1); lx++ , ly-- ){ if( board[ly][lx] == ""){ line += " "; }else{ line += board[ly][lx]; } } if (line.indexOf(searchValue) > -1){ wins(currentPlayer); return; } //diagonal / affin function like y=x+b b = parseInt(y - x); if( b > -1){ //first point has x=0 kx = 0; ky = b }else{ //first point has y=0 ky = 0; kx = -b; } var line=""; var lx , ly; for (lx = kx , ly = ky ; (lx < 7) && (ly < 6) ; lx++ , ly++){ if( board[ly][lx] == ""){ line += " "; }else{ line += board[ly][lx]; } } if (line.indexOf(searchValue) > -1){ wins(currentPlayer); return; } //if it was the last cell var full=true; for (var i = 0; i < 7; i ++){ if( board[5][i] == "" ){ full = false; } } if (full){ addLog('match nul'); return; } //change player if(currentPlayer == 1){ play(2); }else{ play(1); } } function play(player){ currentPlayer=player; if(document.getElementById("player" + player + "Type").value == "bot"){ //call bot url if(currentPlayer == 1){ var symbol= "X"; }else{ var symbol="O"; } var arrToSend= { "game-id": "" + gameId, "action" : "play-turn", "game" : "connectFour", "players" : 2, "board" : board, "you" : symbol, "player-index" : player-1 }; var xhr = new XMLHttpRequest(); xhr.open("POST", document.getElementById('url' + player).value, false); xhr.setRequestHeader("Content-Type", "application/json"); xhr.send(JSON.stringify(arrToSend) ); addLog('Message send to player ' + player + ': ' +JSON.stringify(arrToSend) ); if(xhr.status == 200) { try{ var reponse = JSON.parse(xhr.responseText); var colTarget= reponse['play']; }catch(e){ addLog('player ' + player + ' made a non confom response: ' + xhr.responseText); return; } var t = new RegExp('^[0-6]$'); if (t.test(colTarget)){ addLog('His rsponse is:' + xhr.responseText); playingAT(colTarget); }else{ addLog ('bot response must be a digit betwin 0 and 7, witch indicate the conumn number where he wants play. His response his: "' + colTarget + '"' ); } }else{ alert ('Bot ' + player + ' replied with an error code: ' + xhr.status + ' ' + xhr.responseText); addLog('Bot ' + player + ' replied with an error code: ' + xhr.status + ' ' + xhr.responseText); return; } }else{ //wait for human response, show buttons document.getElementById("playerButtons").setAttribute("class", ""); } } function startGame(){ //empty div while (document.getElementById("fightResult").firstChild) { document.getElementById("fightResult").removeChild(document.getElementById("fightResult").firstChild); } //create board var table=createElem('table',{'class':'battleGrid', 'id': 'board'}); for (var i=5; i > -1; i--){ var tr=createElem('tr'); for (var j=0;j<7; j++){ var td=createElem('td',{'id': 'td' + j + '_' + i}); tr.appendChild (td); } table.appendChild(tr); } document.getElementById('fightResult').appendChild(table); var divLogs=createElem("div",{"id":"logs"}); document.getElementById('fightResult').appendChild(divLogs); var newTr=createElem('tr',{'id':'playerButtons','class':'hidden'}); for(var i = 0; i < 7; i++){ var newTd=createElem('td'); var button=createElem('input',{'type':'button','value': i, 'onclick': "playingAT('" + i + "');"}); newTd.appendChild(button); newTr.appendChild(newTd); } document.getElementById('board').appendChild(newTr); board=[["","","","","","",""], ["","","","","","",""], ["","","","","","",""], ["","","","","","",""], ["","","","","","",""], ["","","","","","",""]]; gameId=Math.floor((Math.random() * 10000) + 1); //send init messages for (var p = 1; p < 3 ; p++){ if(document.getElementById("player" + p + "Type").value == "bot"){ var xhr = new XMLHttpRequest(); xhr.open("POST", document.getElementById('url' + p).value, false); xhr.setRequestHeader("Content-Type", "application/json"); xhr.send(' {"game-id":"' + gameId + '","action":"init","game":"connectFour","players":2,"board":"","player-index":' + (p - 1) +'}'); if(xhr.status == 200) { addLog('Message d\'init envoyé au bot player ' + p + ' {"game-id":"' + gameId + '","action":"init","game":"connectFour","players":2,"board":"","player-index":' + (p - 1) +'} <br/> il a répondu ' + xhr.responseText ); }else{ addLog('player ' + p + ' n est pas joignable ' + xhr.status); return; } } } play(1); } </script> </head> <body> <header> <h1>ConnectFour's Ludus</h1> </header> <section> <p>Here you can test and fix your bot, against himself, against human or against any other bot if you know the URL. <br/>No scoring here, it's a Ludus (gladiators training center).</p> <aside> <h2>Configure the test</h2> <table> <tr> <td>Player 1</td> <td><select id="player1Type" name="player1Type" onchange="changePlayerType(1,this.value);"> <option value="bot">bot</option> <option value="human">human</option> </select> </td> </tr> <tr> <td colspan="2"> <input id="url1" type="text" name="player1URL" placeholder="url du bot http://localhost" value="https://ias.tinad.fr/StupidIAconnectFour.php"/> </td> </tr> <tr> <td>Player 2</td> <td> <select id="player2Type" name="player2Type" onchange="changePlayerType(2,this.value);"> <option value="human">human</option> <option value="bot">bot</option> </select> </td> </tr> <tr> <td colspan="2"> <input id="url2" type="text" name="player2URL" placeholder="url du bot http://localhost" disabled value="https://ias.tinad.fr/StupidIAconnectFour.php"/> </td> </tr> </table> <p><input type="button" onclick="startGame()" value="Fight"/></p> </aside> <article id="fightResult"> </article> </section> <footer> <a href="/p/About">About</a><a href="https://github.com/gnieark/botsArena">Bots'Arena source code</a><a href="/p/legals">Mentions légales</a> </footer> </body> </html>