Intro
Questo è un contest interattivo King of the Hill in cui il controller è completamente contenuto in un frammento di stack nella parte inferiore della domanda. Il controller legge automaticamente le risposte e gioca attraverso i giochi. Chiunque può eseguirlo in qualsiasi momento direttamente nel proprio browser.
Le meccaniche di questo concorso sono molto simili a quelle di Red vs. Blue - Pixel Team Battlebots . Tranne che il gioco che si sta giocando, mentre è ancora basato sulla griglia, è completamente diverso. Ogni partita è 1 contro 1 e non ci sono squadre. Ogni voce è in lotta per se stessa e solo una sarà il campione finale.
Il controller utilizza JavaScript e poiché JavaScript è l'unico linguaggio di scripting lato client supportato dalla maggior parte dei browser, anche tutte le risposte devono essere scritte in JavaScript .
In questa specifica, il testo in corsivo viene utilizzato per indicare il termine formale per un meccanico o una proprietà di gioco. Questi termini sono usati ovunque per aiutare a mantenere un modo chiaro e coerente di riferirsi alle diverse parti del gioco.
gameplay
Nozioni di base
Ogni risposta a questa domanda rappresenta un giocatore . Una partita è una competizione tra due giocatori, P1 e P2 . Ogni giocatore controlla uno stormo di 8 robot , numerati da 0 a 7. I giochi si svolgono nella griglia , un'arena di celle 128 × 64 le cui 8 file inferiori iniziano come muri (i "blocchi") e altre file iniziano come aria . Le celle al di fuori dei limiti della griglia sono considerate aria.
La coordinata x della griglia varia da 0 a sinistra a 127 a destra e y varia da 0 in alto a 63 in basso.
Esempio di griglia iniziale:
I robot rimangono sempre allineati alle celle della griglia e più robot possono occupare la stessa cella. I robot possono occupare solo celle d'aria. I robot di P1 iniziano sempre in una riga 0-7 alla sinistra della riga sopra le pareti e i robot di P2 iniziano sempre in una riga 7-0 all'estrema destra.
I vicini di un robot o cella sono le 8 celle direttamente ortogonali e diagonali ad esso.
Il campo visivo ( FOV ) di un bot è il quadrato di cella 13 × 13 centrato su un bot. Si dice che una cellula o un robot nemico si trovi nel FOV di un giocatore se si trova nel FOV di almeno uno dei robot del giocatore.
Mosse e azioni
Durante una partita, ogni giocatore può muoversi 1000 volte. P1 si sposta prima, poi P2, poi P1 e così via fino a quando non sono state effettuate 2000 mosse totali, a quel punto il gioco termina.
Durante una mossa, ogni giocatore riceve informazioni sullo stato del gioco e sulle celle della griglia e sui robot nemici nel proprio FOV, e lo usa per decidere un'azione da eseguire per ciascuno dei suoi robot.
L'azione predefinita è non fare nulla , in cui il bot non si sposta o interagisce con la griglia.
Le altre azioni sono spostare , afferrare e posizionare :
Un bot può spostarsi in una delle celle adiacenti C se:
- C non è fuori limite,
- C è aria (cioè non un muro),
- e almeno uno dei vicini di C è un muro.
In caso di successo, il bot passerà a C.
Un bot può prendere una delle sue celle vicine C se:
- C non è fuori limite,
- C è un muro,
- e il bot non sta già portando un muro.
In caso di successo, C diventerà aria e il robot ora trasporterà un muro.
Un bot può posizionarsi su una delle sue celle vicine C se:
- C non è fuori limite,
- C è aria,
- nessun robot di entrambi i giocatori occupa C,
- e il robot porta un muro.
In caso di successo, C diventerà un muro e il bot non trasporterà più un muro.
Le azioni non riuscite si traducono in non fare nulla.
Una cella occupata da almeno un robot che trasporta pareti ha un piccolo quadrato colorato a parete disegnato sopra di esso. I robot iniziano senza muri.
Memoria
Durante una mossa, un giocatore può accedere e modificare la propria memoria , una stringa inizialmente vuota che dura per tutto il gioco e può essere utilizzata per memorizzare dati strategici.
Obbiettivo
La cella nel mirino giallo è l' obiettivo , che inizia in una posizione casuale. Ogni giocatore ha un punteggio che inizia da 0. Quando il robot di un giocatore si sposta in porta, il punteggio di quel giocatore aumenta di 1 e l'obiettivo viene riposizionato casualmente prima del turno successivo. Vince il giocatore con il punteggio più alto alla fine di una partita. È un pareggio se i punteggi sono uguali.
Se più robot si muovono verso l'obiettivo durante una mossa, il giocatore ottiene ancora solo un punto.
Se l'obiettivo è stato nello stesso posto per 500 mosse, viene riposizionato di nuovo a caso. Ogni volta che l'obiettivo viene posizionato in modo casuale, è garantito che non venga posizionato su una cella occupata da un bot.
Cosa programmare
Scrivi un corpo per questa funzione:
function myMove(p1, id, eid, move, goal, grid, bots, ebots, getMem, setMem) {
//body goes here
}
Verrà chiamato una volta ogni volta che il tuo giocatore si muove e deve restituire le azioni che vuoi che ciascuno dei tuoi robot effettui durante quella mossa.
È possibile utilizzare il codice di base come punto di partenza.
parametri
p1
è un bool che ètrue
se sei P1 efalse
se sei P2id
è un numero intero che è l'ID di risposta della tua risposta.
- Puoi trovare l'ID di una risposta facendo clic sul link "condividi" sotto di esso e cercando il numero subito dopo
a/
nell'URL.- L'ID della voce di prova è -1.
eid
è un numero intero che è l'ID di risposta della risposta del tuo nemico.move
è un numero intero compreso tra 1 e 1000 che indica la mossa in cui ti trovi.goal
è un oggetto conx
ey
proprietà. Queste sono le coordinate dell'obiettivo. Vengono dati anche se l'obiettivo è fuori dal tuo FOV.grid
è una funzione che accetta argomenti xey, ad esgrid(x,y)
. Restituisce:
-1
per "sconosciuto" se gli argomenti non sono due numeri interi o sex,y
non si trova nel tuo FOV.0
per "aria" sex,y
è fuori limite o se la cellax,y
è in aria.1
per "muro" se la cella inx,y
è un muro.
bots
è un array dei tuoi 8 robot. I suoi elementi sono oggetti con proprietàx
,y
ehasWall
:
x
ey
sono le coordinate del bot.hasWall
ètrue
se il robot trasporta un muro e infalse
caso contrario.
bots
viene sempre ordinato normalmente, l'ennesimo indice corrisponde al numero di bot N.ebots
è un array di oggetti conx
,y
ehasWall
proprietà comebots
. Ci sono solo i robot nemici nel tuo FOVebots
. Quindi avrebbe lunghezza 0 se non ci sono robot nemici nel tuo FOV. Viene ordinato in modo casuale.getMem
è una funzione senza argomenti che restituisce la tua memoria.setMem
è una funzione che accetta un argomento M. Se M è una stringa di 256 caratteri o meno, la memoria viene aggiornata a M, altrimenti non accade nulla.
L' console
oggetto browser è disponibile solo per la voce Test.
Valore di ritorno
La tua funzione deve restituire un array di esattamente 8 numeri interi, ciascuno compreso tra 0 e 24. Il valore all'indice N è l'azione che il numero di bot N intraprenderà.
Tutti i tuoi robot non faranno nulla se la tua funzione:
- Genera un errore di qualsiasi tipo. ( errore )
- Richiede più di 20 millisecondi per l'esecuzione. ( timeout )
- Non restituisce un array di 8 numeri interi compresi tra 0 e 24. (non valido )
Per comodità, il numero di errori, timeout e azioni non valide vengono visualizzati al termine della partita.
Ognuno dei numeri da 0 a 24 corrisponde a una particolare azione bot:
- 0 è per non fare nulla.
- 1-8 sono per lo spostamento.
- 9-16 sono per afferrare.
- 17-24 sono per il posizionamento.
Ognuno degli 8 valori per spostare, afferrare e posizionare corrisponde a una delle celle adiacenti del bot, come mostrato qui:
Quindi, ad esempio, 15
è l'azione per afferrare la cella sotto il bot.
Le azioni del bot vengono gestite nell'ordine da bot 0 a bot 7. Ad esempio, se durante uno spostamento viene detto a bot 0 di posizionare una parete nella stessa cella d'aria a cui è stato detto di spostare 1 bot, la cella d'aria diventerà una parete prima del bot L'azione di 1 viene gestita e il bot 1 non avrà esito positivo.
Le azioni infruttuose non fanno nulla e si dice che abbiano fallito . I segnalini azione falliti vengono visualizzati anche al termine del gioco.
Regole
Potrei squalificare temporaneamente o permanentemente gli utenti o le risposte che non seguono queste regole. Le iscrizioni squalificate non sono idonee a vincere.
Quando si dichiarano variabili o funzioni, è necessario utilizzare la
var
parola chiave.
ad es.var x = 10
ovar sum = function(a, b){ return a + b }
Le cose dichiarate senzavar
diventare globali e potrebbero interferire con il controller. Sono stati fatti dei passi affinché questa interferenza sia impossibile, ma farlo per assicurarsi.Il tuo codice non dovrebbe funzionare lentamente o perdere tempo.
È impossibile interrompere le funzioni JavaScript durante l'esecuzione, quindi il codice di ciascun giocatore viene eseguito fino al completamento. Se l'esecuzione del codice richiede molto tempo, tutti coloro che eseguono il tuo lettore noteranno e saranno infastiditi. Idealmente, le voci funzioneranno sempre bene entro il limite di 20ms.- È necessario utilizzare il codice compatibile con ECMAScript 5 nell'ultima versione di Firefox poiché è qui che lo eseguirò. Non utilizzare le funzionalità di ECMAScript 6 in quanto non è ancora supportato in molti browser.
- Puoi rispondere fino a 3 volte, ma solo se ciascuna delle tue strategie è notevolmente diversa. Puoi modificare le risposte quanto desideri.
- Non puoi tentare di avere alcun tipo di memoria se non attraverso l'uso di
getMem
esetMem
. - Non puoi tentare di accedere o modificare il controller, il codice di altri giocatori o risorse esterne.
- Non puoi tentare di modificare nulla incorporato in JavaScript.
- Le risposte non devono essere deterministiche. Puoi usare
Math.random
.
Formato di risposta
#EntryName
Notes, etc.
<!-- language: lang-js -->
//function body
//probably on multiple lines
More notes, etc.
Il primo blocco di codice multilinea deve contenere il corpo della funzione.
Il nome della voce è limitato a 20 caratteri.
La tua voce apparirà nel controller con il titolo EntryName - Username [answer ID]
, più [DQ]
se è squalificata.
vincente
Quando la domanda è stata sollevata per almeno 3 settimane e una volta che la risposta si è risolta, incoronerò il campione.
Userò la funzione di esecuzione automatica del controller . In un round di esecuzione automatica, ogni giocatore non squalificato gioca due partite l'una con l'altra, una come P1, una come P2 (un doppio round robin).
Eseguirò il maggior numero di colpi possibile nel giro di poche ore. Questo dipenderà da quanti invii ci saranno e da quanto tempo impiegheranno. Ma state tranquilli, mi impegno a ottenere una classifica finale accurata. Il giocatore con più vittorie è il campione e la sua risposta sarà accettata.
Userò Firefox su un laptop con Windows 8.1 a 64 bit, 4 GB di RAM e un processore quad-core da 1,6 GHz.
Premio
Scriverò e pubblicherò una sfida PPCG specificamente dedicata al campione. In qualche modo coinvolgerà il loro nome utente o avatar o qualcosa su di loro. Deciderò privatamente su quale sarà la sfida al termine di questo concorso. Lo scriverò al meglio delle mie possibilità e cercherò di farlo diventare una domanda di rete calda.
controllore
Esegui questo snippet o vai a questo JSFiddle per utilizzare il controller. Si inizia con giocatori casuali selezionati. L'ho provato a fondo solo su Firefox e Chrome.
<style>html *{font-family:Consolas,Arial,sans-serif}canvas{margin:6px}button,input table,select{font-size:100%}textarea{font-family:monospace}input[type=text],textarea{padding:2px}textarea[readonly]{background-color:#eee}select{width:250pt;margin:3px 0}input[type=radio]{vertical-align:-.25em}input[type=checkbox]{vertical-align:-.15em}.c{margin:12px}.h{font-size:125%;font-weight:700}#main td{padding:12px;text-align:left}#main table{margin-left:auto;margin-right:auto}#main{text-align:center}#title{margin:12px;font-size:175%;font-weight:700;color:#333}#delay{text-align:right}#statsTable table{border-collapse:collapse}#statsTable td{border:1px solid gray;padding:3pt;font-family:monospace;text-align:center}#footnotes{margin:18px 0 0;font-size:75%}#arWrapper{border:2px solid red;background-color:#fff4f4}</style><div id=loadStatus>Loading entries...</div><div id=main><div id=title>Block Building Bot Flocks</div><div><span id=p1Title class=p1Color></span> vs. <span id=p2Title class=p2Color></span></div><canvas id=canvas>Canvas unsupported!</canvas><div><span id=p1Score class=p1Color>0</span> | <span id=moveCounter>0</span> | <span id=p2Score class=p2Color>0</span></div><div class=c><button id=runPause type=button onclick=runPause()>Run</button> <button id=moveOnce type=button onclick=moveOnce()>Move Once</button> <button type=button onclick=newGame()>New Game</button></div><div class=c><input id=delay size=4 value=20> ms delay <input id=showNumbers type=checkbox onclick=toggleNumbers()><label for=showNumbers>Show bot numbers</label> <input id=showLOS type=checkbox onclick=toggleLOS()><label for=showLOS>Show field of view</label></div><table><tr><td><div id=p1Header class="p1Color h">Player 1</div><div><select id=p1Select onchange=changeSelect(!0)></select></div><div><a id=p1Link href=javascript:;>Answer Link</a></div><td><div id=p2Header class="p2Color h">Player 2</div><div><select id=p2Select onchange=changeSelect(!1)></select></div><div><a id=p2Link href=javascript:;>Answer Link</a></div></table><div>Test Entry</div><div><textarea id=testEntry rows=8 cols=64>return [0,0,0,0,0,0,0,0]</textarea></div><div class=c><button type=button onclick=autorun()>Autorun N Rounds</button> N = <input id=N size=4 value=1> <input id=arTestEntry type=checkbox><label for=arTestEntry>Include Test Entry</label></div><div id=footnotes><input id=debug type=checkbox onclick=toggleDebug()><label for=debug>Console debug messages</label> | Scale: <input id=sc1 type=radio name=sc value=1><label for=sc1>Micro</label><input id=sc3 type=radio name=sc value=3><label for=sc3>Small</label><input id=sc6 type=radio name=sc value=6 checked><label for=sc6>Normal</label><input id=sc9 type=radio name=sc value=9><label for=sc9>Large</label> | Colors: <input id=normalCo type=radio name=co value=normal checked><label for=normalCo>Normal</label><input id=pastelCo type=radio name=co value=pastel><label for=pastelCo>Pastels</label><input id=neonCo type=radio name=co value=neon><label for=neonCo>Neon</label> <button type=button onclick=reload()>Reload</button><div id=invalidWrapper><br>No entry name/code found: <span id=invalid></span></div></div></div><div id=arWrapper><div id=arInfo class=c>Autorun in progress. Running game <span id=arProgress></span>.</div><div id=arResults><div class="c h">Autorun Results</div><div class=c>Players: <span id=arPlayers></span><br>Rounds: <span id=arRounds></span><br>Games per round: <span id=arGpR></span><br>Total games: <span id=arTotal></span><br></div><div class=c><strong>Leaderboard:</strong></div><div id=leaderboard class=c></div><div class=c>(W = wins, T = ties, L = losses, G = total goals, E = errors, I = timeouts, M = malformed actions, F = failed actions)</div><div class=c><strong>Player vs. Player Statistics:</strong></div><div id=statsTable class=c></div><div class=c>The top row has the ID's of P1.<br>The left column has the ID's of P2.<br>Every other cell not on the diagonal has the form "[P1 win count] [tie count] [P2 win count]".</div><div class=c><button type=button onclick=closeAutorun()>Close</button></div></div></div><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><script>function setGlobals(e){G={},G.QID=50690,G.SITE="codegolf",G.DQ_ANSWERS=[],G.DQ_USERS=[],G.DEBUG=Q("#debug").is(":checked"),G.SHOW_NUMBERS=Q("#showNumbers").is(":checked"),G.SHOW_LOS=Q("#showLOS").is(":checked"),G.BOTS=8,G.LOS=6,G.W=128,G.H=64,G.SCALE=e?6:parseInt(Q('input[name="sc"]:checked').val()),G.CW=G.SCALE*G.W,G.CH=G.SCALE*G.H,G.TOTAL_MOVES=2e3,G.GOAL_LIFESPAN=500,G.MEM_MAX_LENGTH=256,G.TIME_LIMIT=20;var t=Q('input[name="co"]:checked').val();e||"normal"===t?G.COLORS={AIR:"#ccc",WALL:"#888",GOAL:"rgba(255,255,0,0.6)",BG:"#f7f7f7",P1:"#00f",P1_TEXT:"#008",P1_LOS:"rgba(0,0,255,0.1)",P2:"#f00",P2_TEXT:"#800",P2_LOS:"rgba(255,0,0,0.1)"}:"pastel"===t?G.COLORS={AIR:"#cef0ff",WALL:"#66cc66",GOAL:"rgba(0,0,0,0.3)",BG:"#fdfde6",P1:"#f4a034",P1_TEXT:"#a35f00",P1_LOS:"rgba(255,179,71,0.2)",P2:"#f67cf6",P2_TEXT:"#b408b4",P2_LOS:"rgba(249,128,249,0.2)"}:"neon"===t&&(G.COLORS={AIR:"#000",WALL:"#444",GOAL:"rgba(255,255,0,0.9)",BG:"#999",P1:"#0f0",P1_TEXT:"#5f5",P1_LOS:"rgba(255,128,0,0.15)",P2:"#f0f",P2_TEXT:"#f5f",P2_LOS:"rgba(0,255,255,0.15)"}),G.SCOREBOARD={P1SCORE:void 0,MOVE:void 0,P2SCORE:void 0},G.CTX=void 0,G.PLAYERS=void 0,G.GAME=void 0,G.TIMER=void 0,G.RUNNING=!1}function reload(){var e="undefined"==typeof G;e||stopTimer(),setGlobals(e);var t=Q("#canvas");t.width(G.CW).height(G.CH).prop({width:G.CW,height:G.CH}),G.CTX=t[0].getContext("2d"),G.CTX.font=(2*G.SCALE).toString()+"px Courier New",G.SCOREBOARD.P1SCORE=Q("#p1Score"),G.SCOREBOARD.MOVE=Q("#moveCounter"),G.SCOREBOARD.P2SCORE=Q("#p2Score"),Q("body").css("background-color",G.COLORS.BG),Q(".p1Color").css("color",G.COLORS.P1),Q(".p2Color").css("color",G.COLORS.P2),Q("#invalidWrapper").hide(),Q("#arWrapper").hide(),loadAnswers(G.SITE,G.QID,function(e){Q.isArray(e)?(Q("#loadStatus").remove(),loadPlayers(e),newGame()):Q("#loadStatus").text("Error loading entries - "+e)})}function maskedEval(e,t){var r={};for(i in this)r[i]=void 0;for(i in t)t.hasOwnProperty(i)&&(r[i]=t[i]);return new Function("with(this) { "+e+";}").call(r)}function toKey(e,t){return G.W*t+e}function fromKey(e){return{x:e%G.W,y:Math.floor(e/G.W)}}function outOfBounds(e,t){return 0>e||e>=G.W||0>t||t>=G.H}function rnd(e){return Math.floor(Math.random()*e)}function isInt(e){return"number"==typeof e&&e%1===0}function isString(e){return"string"==typeof e||e instanceof String}function decode(e){return Q("<textarea>").html(e).text()}function shuffle(e){for(var t,r,o=e.length;o;t=rnd(o),r=e[--o],e[o]=e[t],e[t]=r);}function makeTable(e){for(var t=Q("<table>"),r=0;r<e.length;r++){for(var o=Q("<tr>"),a=0;a<e[r].length;a++)o.append(Q("<td>").text(e[r][a]));t.append(o)}return t}function toggleDebug(){G.DEBUG=Q("#debug").is(":checked")}function toggleNumbers(){G.SHOW_NUMBERS=Q("#showNumbers").is(":checked"),drawGame(G.GAME)}function toggleLOS(){G.SHOW_LOS=Q("#showLOS").is(":checked"),drawGame(G.GAME)}function closeAutorun(){Q("#arWrapper").hide(),Q("#main").show()}function changeSelect(e){var t=Q(e?"#p1Select":"#p2Select").val(),r=Q(e?"#p1Link":"#p2Link");null===t&&0>t?r.attr("href","javascript:;"):r.attr("href",G.PLAYERS[t].link)}function stopTimer(){"undefined"!=typeof G.TIMER&&clearInterval(G.TIMER)}function moveOnce(){gameOver(G.GAME)||(moveGame(G.GAME),drawGame(G.GAME),gameOver(G.GAME)&&(stopTimer(),Q("#runPause").text("Run").prop("disabled",!0),Q("#moveOnce").prop("disabled",!0),G.DEBUG&&console.log("======== GAME OVER: "+G.GAME.p1.score+" TO "+G.GAME.p2.score+" ========"),alert(gameOverMessage(G.GAME))))}function runPause(){if(G.RUNNING)stopTimer(),Q("#runPause").text("Run"),Q("#moveOnce").prop("disabled",!1);else{var e=parseInt(Q("#delay").val());if(isNaN(e)||0>e)return void alert("Delay must be a non-negative integer.");Q("#runPause").text("Pause"),Q("#moveOnce").prop("disabled",!0),G.TIMER=setInterval(moveOnce,e)}G.RUNNING=!G.RUNNING}function newGame(){stopTimer();var e=G.PLAYERS[Q("#p1Select").val()],t=G.PLAYERS[Q("#p2Select").val()];G.RUNNING=!1,Q("#runPause").text("Run").prop("disabled",!1),Q("#moveOnce").prop("disabled",!1),Q("#p1Title").text(e.title),Q("#p2Title").text(t.title),G.GAME=createGame(e,t),drawGame(G.GAME)}function tryParse(e,t){var r=parseInt(Q(e).val());return!isNaN(r)&&r>=0?r:void alert(t+" must be a non-negative integer.")}function autorun(){function e(){for(var e=new Array(a.length),t={},r=["wins","goals","errors","timeouts","malformed","invalid"],n=0;n<e.length;n++){t.wins=t.ties=t.losses=t.goals=t.errors=t.timeouts=t.malformed=t.invalid=0;for(var l=0;l<e.length;l++)n!==l&&(t.ties+=s[n][l].ties+s[l][n].ties,t.losses+=s[n][l].p2.wins+s[l][n].p1.wins,r.forEach(function(e){t[e]+=s[n][l].p1[e]+s[l][n].p2[e]}));e[n]={wins:t.wins,text:a[n].title+" : "+t.wins+"W, "+t.ties+"T, "+t.losses+"L, "+t.goals+"G, "+t.errors+"E, "+t.timeouts+"I, "+t.malformed+"M, "+t.invalid+"F"}}e=e.sort(function(e,t){return t.wins-e.wins}).map(function(t,r){return r+1+". "+t.text+(r<e.length-1?"<br>":"")});for(var i=new Array(s.length+1),G=0;G<i.length;G++){i[G]=new Array(s.length+1);for(var c=0;c<i.length;c++){var f;i[G][c]=0===c&&0===G?"P2\\P1":0===c?a[G-1].id:0===G?a[c-1].id:(f=s[c-1][G-1])?f.p1.wins+" "+f.ties+" "+f.p2.wins:"-"}}Q("#arPlayers").text(a.length),Q("#arRounds").text(o),Q("#arGpR").text(S/o),Q("#arTotal").text(S),Q("#leaderboard").empty().append(e),Q("#statsTable").empty().append(makeTable(i)),Q("#arInfo").hide(),Q("#arResults").show()}function t(e,t){for(var r=createGame(a[e],a[t]);!gameOver(r);)moveGame(r);r.p1.score>r.p2.score?s[e][t].p1.wins++:r.p1.score<r.p2.score?s[e][t].p2.wins++:s[e][t].ties++,["p1","p2"].forEach(function(o){s[e][t][o].goals+=r[o].score,s[e][t][o].errors+=r[o].stats.errors,s[e][t][o].timeouts+=r[o].stats.timeouts,s[e][t][o].malformed+=r[o].stats.malformed,s[e][t][o].invalid+=r[o].stats.invalid.reduce(function(e,t){return e+t},0)})}function r(){if(c!==f&&(t(c,f),++p<=S&&Q("#arProgress").text(p+"/"+S)),f+1<a.length)f++;else if(f=0,c+1<a.length)c++;else{if(c=0,!(o>i+1))return void e();i++}setTimeout(r,0)}var o=parseInt(Q("#N").val());if(isNaN(o)||1>o)return void alert("N must be a positive integer.");var a=[];Q("#arTestEntry").is(":checked")&&a.push(G.PLAYERS[0]);for(var n=1;n<G.PLAYERS.length;n++)G.PLAYERS[n].dq||a.push(G.PLAYERS[n]);for(var s=new Array(a.length),n=0;n<a.length;n++){s[n]=new Array(a.length);for(var l=0;l<a.length;l++)n!==l&&(s[n][l]={ties:0,p1:{wins:0,goals:0,errors:0,timeouts:0,malformed:0,invalid:0},p2:{wins:0,goals:0,errors:0,timeouts:0,malformed:0,invalid:0}})}var i=0,c=0,f=0,p=1,S=o*a.length*(a.length-1);Q("#arProgress").text("1/"+S),Q("#main").hide(),Q("#arInfo").show(),Q("#arResults").hide(),Q("#arWrapper").show(),setTimeout(r,0)}function gameOver(e){return e.move>=G.TOTAL_MOVES}function gameOverMessage(e){function t(e,t){return"P"+(t?1:2)+": "+e.entry.title+"\nScore: "+e.score+"\nErrors: "+e.stats.errors+"\nTimeouts: "+e.stats.timeouts+"\nMalformed actions: "+e.stats.malformed+"\nFailed actions: ["+e.stats.invalid.toString().replace(/,/g,", ")+"]"}var r="GAME OVER - ";return r+=e.p1.score>e.p2.score?"PLAYER 1 WINS":e.p1.score<e.p2.score?"PLAYER 2 WINS":"TIE GAME",r+="\n\n"+t(e.p1,!0)+"\n\n"+t(e.p2,!1)}function createGame(e,t){function r(e){return{entry:e,bots:new Array(G.BOTS),mem:"",score:0,stats:{errors:0,timeouts:0,malformed:0,invalid:Array.apply(null,new Array(G.BOTS)).map(Number.prototype.valueOf,0)}}}var o={},a=Math.floor(.875*G.H)-1;o.move=0,o.walls=new Array(G.H);for(var n=0;n<G.H;n++){o.walls[n]=new Array(G.W);for(var s=0;s<G.W;s++)o.walls[n][s]=n>a}o.p1=r(e),o.p2=r(t);for(var l=0;l<G.BOTS;l++)o.p1.bots[l]={x:l,y:a,hasWall:!1},o.p2.bots[l]={x:G.W-1-l,y:a,hasWall:!1};if(-1===o.p1.entry.id||-1===o.p2.entry.id){var i=decode(Q("#testEntry").val());-1===o.p1.entry.id&&(o.p1.entry.code=i),-1===o.p2.entry.id&&(o.p2.entry.code=i)}return resetGoal(o),G.DEBUG&&console.log("======== NEW GAME: "+o.p1.entry.title+" VS "+o.p2.entry.title+" ========"),o}function moveGame(e){movePlayer(e,++e.move%2===1),++e.goal.age>=G.GOAL_LIFESPAN&&resetGoal(e)}function setupParams(e,t){function r(e,t){var r=toKey(e,t);if(!n.hasOwnProperty(r)){n[r]=!1;for(var a=0;a<G.BOTS;a++)if(Math.abs(o.bots[a].x-e)<=G.LOS&&Math.abs(o.bots[a].y-t)<=G.LOS){n[r]=!0;break}}return n[r]}var o=t?e.p1:e.p2,a=t?e.p2:e.p1,n={},s={};s.p1=t,s.id=o.entry.id,s.eid=a.entry.id,s.score=o.score,s.escore=a.score,s.move=Math.floor((e.move+1)/2),s.goal={x:e.goal.x,y:e.goal.y},s.getMem=function(){return o.mem},s.setMem=function(e){isString(e)&&e.length<=G.MEM_MAX_LENGTH&&(o.mem=e)},s.grid=function(t,o){return isInt(t)&&isInt(o)&&r(t,o)?outOfBounds(t,o)?0:e.walls[o][t]?1:0:-1},s.bots=new Array(G.BOTS),s.ebots=[];for(var l=0;l<G.BOTS;l++)s.bots[l]={x:o.bots[l].x,y:o.bots[l].y,hasWall:o.bots[l].hasWall},r(a.bots[l].x,a.bots[l].y)&&s.ebots.push({x:a.bots[l].x,y:a.bots[l].y,hasWall:a.bots[l].hasWall});return shuffle(s.ebots),-1===o.entry.id&&(s.console=console),s}function movePlayer(e,t){var r,o,a=t?e.p1:e.p2,n=t?e.p2:e.p1,s=setupParams(e,t);G.DEBUG&&(console.log("######## MOVE "+e.move+" - P"+(t?1:2)+" ########"),console.log("PARAMETERS:"),console.log(s)),o=performance.now();try{r=maskedEval(a.entry.code,s)}catch(n){return a.stats.errors++,void(G.DEBUG&&(console.log("!!!! ERRORED !!!!"),console.log(n)))}if(o=performance.now()-o,G.DEBUG&&console.log("TIME TAKEN: "+o+"ms"),o>G.TIME_LIMIT)return a.stats.timeouts++,void(G.DEBUG&&console.log("!!!! TIMED OUT !!!!"));if(G.DEBUG&&(console.log("ACTIONS:"),console.log(r)),!Array.isArray(r)||r.length!==G.BOTS)return a.stats.malformed++,void(G.DEBUG&&console.log("!!!! MALFORMED ACTIONS !!!!"));for(var l=0;l<G.BOTS;l++)if(!isInt(r[l])||r[l]<0||r[l]>24)return a.stats.malformed++,void(G.DEBUG&&console.log("!!!! MALFORMED ACTIONS !!!!"));performActions(e,a,r)}function performActions(e,t,r){function o(e){t.stats.invalid[e]++,G.DEBUG&&console.log("!! BOT"+e+" ACTION FAILED !!")}function a(e){return e.x!==i||e.y!==c}for(var n=!1,s=0;s<G.BOTS;s++){var l=r[s];if(l){var i,c;switch((l-1)%8){case 0:i=-1,c=-1;break;case 1:i=0,c=-1;break;case 2:i=1,c=-1;break;case 3:i=-1,c=0;break;case 4:i=1,c=0;break;case 5:i=-1,c=1;break;case 6:i=0,c=1;break;case 7:i=1,c=1}if(i+=t.bots[s].x,c+=t.bots[s].y,outOfBounds(i,c))o(s);else switch(Math.floor((l-1)/8)){case 0:!e.walls[c][i]&&(i>0&&c>0&&e.walls[c-1][i-1]||c>0&&e.walls[c-1][i]||i<G.W-1&&c>0&&e.walls[c-1][i+1]||i>0&&e.walls[c][i-1]||i<G.W-1&&e.walls[c][i+1]||i>0&&c<G.H-1&&e.walls[c+1][i-1]||c<G.H-1&&e.walls[c+1][i]||i<G.W-1&&c<G.H-1&&e.walls[c+1][i+1])?(t.bots[s].x=i,t.bots[s].y=c,i!==e.goal.x||c!==e.goal.y||n||(n=!0,G.DEBUG&&console.log("** BOT"+s+" REACHED GOAL **"))):o(s);break;case 1:e.walls[c][i]&&!t.bots[s].hasWall?(e.walls[c][i]=!1,t.bots[s].hasWall=!0):o(s);break;case 2:!e.walls[c][i]&&t.bots[s].hasWall&&e.p1.bots.every(a)&&e.p2.bots.every(a)?(e.walls[c][i]=!0,t.bots[s].hasWall=!1):o(s)}}}n&&(t.score++,resetGoal(e)),G.DEBUG&&(console.log("FINAL PLAYER STATE:"),console.log(t))}function resetGoal(e){for(var t={},r=[],o=0;o<G.BOTS;o++)t[toKey(e.p1.bots[o].x,e.p1.bots[o].y)]=!0,t[toKey(e.p2.bots[o].x,e.p2.bots[o].y)]=!0;for(var a=0;a<G.H;a++)for(var n=0;n<G.W;n++){var s=toKey(n,a);t.hasOwnProperty(s)||r.push(s)}var l=fromKey(r[rnd(r.length)]);e.goal={age:0,x:l.x,y:l.y}}function drawGame(e){function t(e,t){G.CTX.fillRect(e*G.SCALE,t*G.SCALE,G.SCALE,G.SCALE)}function r(e,t){G.CTX.fillRect(e*G.SCALE+1,t*G.SCALE+1,G.SCALE-2,G.SCALE-2)}G.CTX.fillStyle=G.COLORS.AIR,G.CTX.fillRect(0,0,G.CW,G.CH),G.CTX.fillStyle=G.COLORS.WALL;for(var o=0;o<G.H;o++)for(var a=0;a<G.W;a++)e.walls[o][a]&&t(a,o);if(G.SHOW_LOS){var n=(2*G.LOS+1)*G.SCALE;G.CTX.fillStyle=G.COLORS.P1_LOS;for(var s=0;s<G.BOTS;s++)G.CTX.fillRect((e.p1.bots[s].x-G.LOS)*G.SCALE,(e.p1.bots[s].y-G.LOS)*G.SCALE,n,n);G.CTX.fillStyle=G.COLORS.P2_LOS;for(var s=0;s<G.BOTS;s++)G.CTX.fillRect((e.p2.bots[s].x-G.LOS)*G.SCALE,(e.p2.bots[s].y-G.LOS)*G.SCALE,n,n)}G.CTX.fillStyle=G.COLORS.P1;for(var s=0;s<G.BOTS;s++)t(e.p1.bots[s].x,e.p1.bots[s].y);G.CTX.fillStyle=G.COLORS.P2;for(var s=0;s<G.BOTS;s++)t(e.p2.bots[s].x,e.p2.bots[s].y);G.CTX.fillStyle=G.COLORS.WALL;for(var s=0;s<G.BOTS;s++)e.p1.bots[s].hasWall&&r(e.p1.bots[s].x,e.p1.bots[s].y),e.p2.bots[s].hasWall&&r(e.p2.bots[s].x,e.p2.bots[s].y);if(G.SHOW_NUMBERS){var l=-.1,i=2.75;G.CTX.fillStyle=G.COLORS.P1_TEXT;for(var s=0;s<G.BOTS;s++)G.CTX.fillText(s.toString(),(e.p1.bots[s].x+l)*G.SCALE,(e.p1.bots[s].y+i)*G.SCALE);G.CTX.fillStyle=G.COLORS.P2_TEXT;for(var s=0;s<G.BOTS;s++)G.CTX.fillText(s.toString(),(e.p2.bots[s].x+l)*G.SCALE,(e.p2.bots[s].y+i)*G.SCALE)}G.CTX.fillStyle=G.COLORS.GOAL,t(e.goal.x+1,e.goal.y),t(e.goal.x-1,e.goal.y),t(e.goal.x,e.goal.y+1),t(e.goal.x,e.goal.y-1),G.SCOREBOARD.P1SCORE.text(e.p1.score),G.SCOREBOARD.MOVE.text(e.move),G.SCOREBOARD.P2SCORE.text(e.p2.score)}function loadPlayers(e){var t=/<pre\b[^>]*><code\b[^>]*>([\s\S]*?)<\/code><\/pre>/,r=/<h1\b[^>]*>(.*?)<\/h1>/;G.PLAYERS=[];var o={id:-1,dq:!1,code:void 0,link:"javascript:;",title:"TEST ENTRY [-1]"};G.PLAYERS.push(o);var a=[];e.forEach(function(e){var o=decode(e.owner.display_name),n=t.exec(e.body),s=r.exec(e.body);if(null===n||n.length<=1||null===s||s.length<=1)return a.push(" "),void a.push(Q("<a>").text(o).attr("href",e.link));var l={};l.id=e.answer_id,l.dq=G.DQ_ANSWERS.indexOf(e.answer_id)>-1||G.DQ_USERS.indexOf(e.owner.user_id)>-1,l.code=decode(n[1]),l.link=e.link,l.title=s[1].substring(0,20)+" - "+o+" ["+l.id.toString()+"]",l.dq&&(l.title+="[DQ]"),G.PLAYERS.push(l)}),a.length>0&&(Q("#invalid").empty().append(a),Q("#invalidWrapper").show());for(var n=new Array(G.PLAYERS.length),s=new Array(G.PLAYERS.length),l=0;l<G.PLAYERS.length;l++)n[l]=Q("<option>").text(G.PLAYERS[l].title).val(l),s[l]=Q("<option>").text(G.PLAYERS[l].title).val(l);Q("#p1Select").empty().append(n).val(rnd(G.PLAYERS.length)),changeSelect(!0),Q("#p2Select").empty().append(s).val(rnd(G.PLAYERS.length)),changeSelect(!1)}function loadAnswers(e,t,r){function o(){Q.get("https://api.stackexchange.com/2.2/questions/"+t.toString()+"/answers?page="+(s++).toString()+"&pagesize=100&order=asc&sort=creation&site="+e+"&filter=!YOKGPOBC5Yad4mOOn8Z4WcAE6q",a)}function a(e){e.hasOwnProperty("error_id")?r(e.error_id.toString()):(n=n.concat(e.items),e.hasMore?o():r(n))}var n=[],s=1;o(s,a)}Q=jQuery,Q(reload);</script>
Questa domanda ha una sua chatroom. Pubblicherò le classifiche lì ogni pochi giorni.