Rouge contre Bleu - Battlebots de l'équipe Pixel


133

Ce concours est officiellement terminé. L'équipe bleue a gagné!

J'autoran deux séries de 50 batailles et étonnamment, Blue en a remporté 100. En regardant les statistiques, il est clair que les entrées coopératives de PhiNotPi et Sp3000 étaient les vrais héros. Bravo à vous deux! En fait, si vous disqualifiez tous les autres membres de l’équipe bleue , les Sphibots s’affronteront quand même très bien . Certains membres de la Red Team envisageaient de vaincre les Sphibots, mais leurs efforts semblaient se résorber. Désolé équipe rouge.

Le concours est officiellement terminé, mais cela ne signifie pas que vous ne pouvez plus répondre, cela signifie simplement que je ne redéclarerai jamais le gagnant officiel. Les deux équipes sont invitées à continuer de soumettre des robots, juste pour le plaisir. Le contrôleur restera actif et restera fonctionnel aussi longtemps qu'aucune autre entrée ne le divisera.


C'est un roi-de-la-colline concours, mais au lieu de tous ceux qui luttent les uns contre les autres, il y aura deux équipes qui sont en concurrence: rouge et bleu. Un seul sera le gagnant.

L’équipe sur laquelle vous travaillez dépend de votre numéro d’identifiant PPCG . Pour le trouver, cliquez sur votre avatar en haut de l'écran (vous devez être connecté) et regardez l'url de la page qui s'ouvre. Le numéro après users/est votre numéro d'identification:

https://codegolf.stackexchange.com/users/[id number]/[display name]

Par exemple, mon numéro d’identifiant PPCG est 26997:

https://codegolf.stackexchange.com/users/26997/calvins-hobbies

Notez que ce nombre est différent pour différents sites Stack Exchange.

Si votre identifiant est un nombre pair , alors vous faites partie de l' équipe rouge .
Si votre identifiant est un nombre impair , alors vous êtes dans l' équipe bleue .
Il n'y a pas moyen de changer d'équipe.

Vous devez travailler avec votre équipe pour essayer de vaincre l’autre équipe dans une sorte de bataille royale où chaque utilisateur contrôle un "pixel" de la couleur de son équipe sur la grille 128 × 128 située sur le champ de bataille. Les pixels peuvent se déplacer, communiquer avec leurs coéquipiers et supprimer les pixels de l’autre équipe. Si quelqu'un pouvait créer un nombre quelconque de pixels, il serait incontrôlable que chaque utilisateur ne puisse soumettre qu'une seule réponse à cette question.

Cet extrait de pile (une version simplifiée de ce violon [ plein écran ]) est le contrôleur pour tout le concours. Il lit automatiquement les soumissions, s'assure de leur validité et organise des batailles entre les équipes. Il fait ce droit dans votre navigateur à tout moment, en utilisant JavaScript . Comme JavaScript est le seul langage de script côté client que la plupart des navigateurs prennent en charge, toutes les soumissions doivent également être écrites en JavaScript.

function toggleDebug(){debug=$("#debug").is(":checked")}function rnd(e){return Math.floor(Math.random()*e)}function shuffle(e){for(var t,a,r=e.length;r;t=rnd(r),a=e[--r],e[r]=e[t],e[t]=a);return e}function maskedEval(e,t){var a={};for(i in this)a[i]=void 0;for(i in t)t.hasOwnProperty(i)&&(a[i]=t[i]);return new Function("with(this) { "+e+";}").call(a)}function createBattle(e,t,a,r){function n(){var e=rnd(i.length),t=i[e];return i.splice(e,1),t}var l={};l.width=l.height=128,l.totalMoves=2048,l.radius=16,l.msgMaxLength=64,l.timeLimit=15,l.move=0,l.redToMove=a,l.animated=r,l.running=!1,l.over=!1;for(var o=0,i=new Array(l.width*l.height),d=0;d<l.height;d++)for(var s=0;s<l.width;s++)i[o++]={x:s,y:d};l.redTeam=shuffle(e.slice()),l.redMsgs={},l.redKills={};for(var o=0;o<l.redTeam.length;o++){var u=n();l.redTeam[o].x=u.x,l.redTeam[o].y=u.y,l.redMsgs[l.redTeam[o].id]="",l.redKills[l.redTeam[o].id]=0}l.blueTeam=shuffle(t.slice()),l.blueMsgs={},l.blueKills={};for(var o=0;o<l.blueTeam.length;o++){var u=n();l.blueTeam[o].x=u.x,l.blueTeam[o].y=u.y,l.blueMsgs[l.blueTeam[o].id]="",l.blueKills[l.blueTeam[o].id]=0}return l}function drawBattle(e){function t(e){var t=3*e.x,a=3*e.y;ctx.fillRect(t,a,3,3),showNames.is(":checked")&&ctx.fillText(e.title,t+5,a+12)}function a(t){ctx.beginPath(),ctx.arc(3*t.x,3*t.y,3*e.radius,0,2*Math.PI),ctx.closePath(),ctx.fill()}e.animated&&(ctx.clearRect(0,0,canvas.width,canvas.height),showCircles.is(":checked")&&(ctx.fillStyle="rgba(255, 0, 0, 0.1)",e.redTeam.forEach(a),ctx.fillStyle="rgba(0, 0, 255, 0.1)",e.blueTeam.forEach(a)),ctx.fillStyle="red",e.redTeam.forEach(t),ctx.fillStyle="blue",e.blueTeam.forEach(t),moveCounter.text((e.move+1).toString()))}function movePlayer(e,t,a,r,n,l,o,i){function d(a){t.id!==a.id&&Math.sqrt(Math.pow(t.x-a.x,2)+Math.pow(t.y-a.y,2))<e.radius&&(u.push({x:a.x,y:a.y,id:a.id}),debug&&console.log(a.title+" is near"))}debug&&(console.log("--- Moving "+t.title+" ---"),console.log("position before move = ("+t.x.toString()+", "+t.y.toString()+")"));var s={};s.move=a,s.x=t.x,s.y=t.y,s.tCount=r.length,s.eCount=n.length,s.setMsg=function(a){"string"==typeof a&&(l[t.id]=a.length>e.msgMaxLength?a.substring(0,e.msgMaxLength):a,debug&&console.log('set message to "'+l[t.id]+'"'))},s.getMsg=function(e){var t=l.hasOwnProperty(e)?l[e]:void 0;return debug&&console.log('got message "'+t+'" from player with id '+e.toString()),t};var u=[];r.forEach(d),s.tNear=u,u=[],n.forEach(d),s.eNear=u,-1===t.id&&(s.console=console);var c=0,g=performance.now();try{c=maskedEval(t.code,s)}catch(v){c=0,debug&&(console.log("encountered error:"),console.log(v))}g=performance.now()-g,debug&&console.log("time taken = "+g.toString()+"ms"),g>e.timeLimit&&(c=0,debug&&console.log("went over the time limit of "+e.timeLimit+"ms"));var m=t.x,h=t.y;switch(c){case 1:e.redToMove?++m:++h;break;case 2:e.redToMove?--m:--h;break;case 3:++m,--h;break;case 4:--m,--h;break;case 5:--m,++h;break;case 6:++m,++h}m>=0&&m<e.width&&h>=0&&h<e.height&&(t.x=m,t.y=h),debug&&console.log("move direction = "+c);for(var f=0;f<n.length;f++)t.x===n[f].x&&t.y===n[f].y&&(debug&&console.log("took out "+n[f].title),++i[t.id],o[n[f].id]="X",n.splice(f--,1))}function advanceBattle(e){debug&&console.log("====== "+(e.redToMove?"Red ":"Blue ")+e.move.toString()+" ======");var t,a,r,n,l;e.redToMove?(t=e.redTeam,a=e.blueTeam,r=e.redMsgs,n=e.blueMsgs,l=e.redKills):(t=e.blueTeam,a=e.redTeam,r=e.blueMsgs,n=e.redMsgs,l=e.blueKills),t.forEach(function(o){movePlayer(e,o,Math.floor(e.move/2)+1,t,a,r,n,l)}),drawBattle(e);var o;return 0===a.length?(o=e.redToMove?1:-1,e.over=!0):++e.move>=e.totalMoves&&(o=e.redTeam.length>e.blueTeam.length?1:e.redTeam.length<e.blueTeam.length?-1:0,e.over=!0),e.redToMove=!e.redToMove,debug&&"undefined"!=typeof o&&console.log("win status = "+o.toString()),o}function newBattle(){if(0===redTeam.length||0===blueTeam.length)return void alert("Each team must have at least one player.");"undefined"!=typeof interval&&clearInterval(interval);var e=parseInt($("#delay").val());return isNaN(e)||0>e?void alert("Delay must be a non-negative integer."):(debug&&console.log("Created new battle with delay "+e.toString()),battle=createBattle(redTeam,blueTeam,$("#redMovesFirst").is(":checked"),!0),drawBattle(battle),void moveCounter.text("0").css("color","black"))}function reportKills(e,t){for(var a="Red Kills:\n",r=0;r<redTeam.length;r++)a+=e[redTeam[r].id].toString()+" by "+redTeam[r].title+"\n";a+="\nBlue Kills:\n";for(var r=0;r<blueTeam.length;r++)a+=t[blueTeam[r].id].toString()+" by "+blueTeam[r].title+"\n";return a}function intervalCallback(){var e=advanceBattle(battle);"undefined"!=typeof e&&(clearInterval(interval),battle.running=!1,alert([0===e?"Tie!":e>0?"Red Wins!":"Blue Wins!","Red remaining: "+battle.redTeam.length,"Blue remaining: "+battle.blueTeam.length,"\n"].join("\n")+reportKills(battle.redKills,battle.blueKills)))}function run(){if("undefined"!=typeof battle&&!battle.running&&!battle.over){battle.running=!0;var e=parseInt($("#delay").val());if(isNaN(e)||0>e)return void alert("Delay must be a non-negative integer.");interval=setInterval(intervalCallback,e)}}function pause(){"undefined"!=typeof battle&&(battle.running=!1),"undefined"!=typeof interval&&clearInterval(interval)}function step(){"undefined"==typeof battle||battle.running||battle.over||intervalCallback()}function autorunBattles(){function e(e){for(var t,i=createBattle(redTeam,blueTeam,e,!1);!i.over;)if(t=advanceBattle(i),"undefined"!=typeof t){i.over=!0,1===t?++a:-1===t?++n:++r;for(var d in i.redKills)i.redKills.hasOwnProperty(d)&&(l[d]+=i.redKills[d]);for(var d in i.blueKills)i.blueKills.hasOwnProperty(d)&&(o[d]+=i.blueKills[d])}}if(pause(),battle=void 0,0===redTeam.length||0===blueTeam.length)return void alert("Each team must have at least one player.");var t=parseInt($("#N").val());if(isNaN(t)||0>t)return void alert("N must be a non-negative integer.");console.log("Autorunning "+t.toString()+" battles");for(var a=0,r=0,n=0,l={},o={},i=0;i<redTeam.length;i++)l[redTeam[i].id]=0;for(var i=0;i<blueTeam.length;i++)o[blueTeam[i].id]=0;for(var i=0;t>i;i++)console.log("Battle "+i.toString()),e(i%2===0);alert([a===n?"Tie overall!":a>n?"Red wins overall!":"Blue wins overall!","Red wins: "+a.toString(),"Blue wins: "+n.toString(),"Ties: "+r.toString(),"\n"].join("\n")+reportKills(l,o))}function changeSelect(e){var t=e?redTeam:blueTeam,a=$(e?"#redSelect":"#blueSelect").val(),r=$(e?"#redCode":"#blueCode"),n=$(e?"#redLink":"#blueLink");null!==a&&a>-1?(r.text(t[a].code),n.attr("href",t[a].link)):(r.text(""),n.attr("href","javascript:;"))}function loadEntries(){function e(e,t){url="https://api.stackexchange.com/2.2/questions/"+qid.toString()+"/answers?page="+e.toString()+"&pagesize=100&order=asc&sort=creation&site=codegolf&filter=!JDuPcYJfXobC6I9Y-*EgYWAe3jP_HxmEee",$.get(url,t)}function t(d){d.items.forEach(function(e){function t(e,t){t.append(" ").append($("<a>").text(e.owner.display_name).attr("href",e.link))}function n(e){return $("<textarea>").html(e).text()}var d=e.owner.user_id%2===0,s=d?redTeam:blueTeam;if(e.owner.display_name=n(e.owner.display_name),e.hasOwnProperty("last_edit_date")&&e.last_edit_date-e.creation_date>r||dq.indexOf(e.owner.user_id)>-1||l.indexOf(e.owner.user_id)>-1)return void t(e,o);l.push(e.owner.user_id);var u=a.exec(e.body);if(null===u||u.length<=1)return void t(e,i);var c={};c.id=e.owner.user_id,c.title=e.owner.display_name+" ["+e.owner.user_id.toString()+"]",c.code=n(u[1]),c.link=e.link;var g=$(d?"#redSelect":"#blueSelect");g.append($("<option>").text(c.title).val(s.length)),s.push(c)}),d.has_more?e(++n,t):($("#loadStatus").hide(),$("#redCount").text(redTeam.length.toString()),$("#blueCount").text(blueTeam.length.toString()),0===o.html().length&&o.html(" none"),0===i.html().length&&i.html(" none"))}var a=/<pre><code>((?:\n|.)*?)\n<\/code><\/pre>/,r=28800,n=1,l=[],o=$("#disqualified"),i=$("#invalid");pause(),battle=void 0,redTeam=[],blueTeam=[],$("#loadStatus").show(),$("#redSelect").empty(),$("#redCode").empty(),$("#redLink").attr("href","javascript:;"),$("#blueSelect").empty(),$("#blueCode").empty(),$("#blueLink").attr("href","javascript:;");var d=$("#testbot").val();if(d.length>0){debug&&console.log("Using test entry");var s={id:-1,title:"TEST ENTRY [-1]",link:"javascript:;",code:d};$("#testbotIsRed").is(":checked")?(redTeam.push(s),$("#redSelect").append($("<option>").text(s.title).val(0))):(blueTeam.push(s),$("#blueSelect").append($("<option>").text(s.title).val(0)))}e(1,t)}var qid=48353,dq=[],ctx,moveCounter,showNames,showCircles,debug=!1,battle,redTeam,blueTeam,interval;$(document).ready(function(){ctx=$("#canvas")[0].getContext("2d"),moveCounter=$("#moveCounter"),showNames=$("#showNames"),showCircles=$("#showCircles"),loadEntries()});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><style>html *{font-family: Consolas, Arial, sans-serif;}select{width: 100%; margin: 12px 0 0 0;}button, select, input{font-size: 100%;}input{text-align: right;}textarea{font-family: "Courier New", monospace;}textarea[readonly]{background-color: #eee; width: 100%;}canvas{margin: 12px 0 0 0; border: 2px solid gray;}.redWrapper, .blueWrapper{width: 30%;}.redWrapper{float: left;}.blueWrapper{float: right;}.arenaWrapper{width: 40%; display: inline-block;}.redTeam, .blueTeam, .arena{padding: 12px;}.arena{text-align: center;}.redTeam, .blueTeam{border-style: solid; border-width: medium;}.redTeam{border-color: red; background-color: #fee;}.blueTeam{border-color: blue; background-color: #eef;}.redTitle, .blueTitle, .arenaTitle{text-align: center; font-size: 200%;}.redTitle, .blueTitle{font-weight: bold;}.redTitle{color: red;}.blueTitle{color: blue;}.control{margin: 12px 0 0 0;}.count{font-size: 75%; margin: 0 0 12px 0;}.footnotes{font-size: 75%; clear: both; padding: 12px;}</style><div id='loadStatus'> Loading entries...</div><div> <div class='redWrapper'> <div class='redTeam'> <div class='redTitle'> Red Team </div><select id='redSelect' size='20' onchange='changeSelect(true)'> </select> <div class='count'> <span id='redCount'></span> players </div>Code: <br><textarea id='redCode' rows='12' readonly></textarea> <br><a id='redLink' href='javascript:;'> Answer Link </a> </div></div><div class='arenaWrapper'> <div class='arena'> <div class='arenaTitle'> Battlefield </div><canvas id='canvas' width='384' height='384'> Your browser does not support the canvas tag. </canvas> <div>Move <span id='moveCounter'>0</span></div><br><div> <div class='control'> <input id='showNames' type='checkbox'>show names <input id='showCircles' type='checkbox'>show circles </div><div class='control'> <input id='redMovesFirst' type='checkbox'>red moves first </div><div class='control'> <input id='delay' type='text' size='4' value='20'> millisecond delay </div><div class='control'> <button type='button' onclick='newBattle()'> New Battle </button> <button type='button' onclick='run()'> Run </button> <button type='button' onclick='pause()'> Pause </button> <button type='button' onclick='step()'> Step </button> </div><hr class='control'> <div class='control'> <button type='button' onclick='autorunBattles()'> Autorun N Battles </button> N&nbsp;=&nbsp;<input id='N' type='text' size='4' value='16'> </div><div class='footnotes'> Autoruns may hang browser tab until complete. </div></div></div></div><div class='blueWrapper'> <div class='blueTeam'> <div class='blueTitle'> Blue Team </div><select id='blueSelect' size='20' onchange='changeSelect(false)'> </select> <div class='count'> <span id='blueCount'></span> players </div>Code: <br><textarea id='blueCode' rows='12' readonly></textarea> <br><a id='blueLink' href='javascript:;'> Answer Link </a> </div></div></div><div class='footnotes'> Test Entry: (id&nbsp;=&nbsp;-1) <input id='testbotIsRed' type='checkbox'>On Red Team <br><textarea id='testbot' rows='1' cols='32'></textarea> <br><button type='button' onclick='loadEntries()'> Reload with test entry </button> <br><br>This was designed and tested in Google Chrome. It might not work in other browsers. <br>Disqualified entries:<span id='disqualified'></span> <br>Could not find code block:<span id='invalid'></span> <br><input id='debug' type='checkbox' onclick='toggleDebug()'>Debug messages <br></div>

Pour plus de visibilité, le champ de bataille de l'extrait de code est divisé par 3, il s'agit donc de 384 × 384 pixels réels et les "pixels" sont 3 × 3.

Pixel Team Battlebots - Présentation

Joueurs

Chaque réponse valide à cette question représente un joueur . (Pour plus de détails sur la validité, voir "Règles et éliminations" .) Chaque joueur a le contrôle d'une seule cellule 1 × 1 (pixel) sur le champ de bataille de 128 × 128 cellules . Les joueurs de l'équipe rouge ont des pixels rouges et les joueurs de l'équipe bleue ont des pixels bleus.

Batailles

Une bataille est un combat opposant tous les joueurs des deux équipes, même si les équipes n’ont pas le même nombre de joueurs. Une bataille commence avec chaque joueur placé à une position aléatoire sur le champ de bataille, c'est-à-dire toute coordonnée entière comprise entre (0,0) en haut à gauche et (127,127) en bas à droite. Il est garanti qu'aucun joueur ne partira dans la même position.

Se déplace

Chaque bataille est divisée en 2048 coups . Une seule équipe peut réellement déplacer ses joueurs à chaque coup. Cette équipe alternant du rouge au bleu, chaque équipe effectue 1024 coups au total (à moins que la partie se termine tôt).

L’équipe qui se déplace en premier est une option que vous devez définir dans le contrôleur.
Lorsque les batailles sont autorun, l'équipe qui se déplace en premier alterne à chaque bataille.

Le joueur bouge

Quand une équipe se déplace, tous les joueurs de cette équipe sont invités à se déplacer eux-mêmes. Ces appels sont effectués dans un ordre complètement aléatoire pour chaque mouvement. Lorsqu’il est appelé, chaque joueur reçoit des données sur l’état de la bataille pour qu’il puisse décider du chemin à suivre.

Tous les mouvements ne sont éloignés que d’un pixel. Les cercles noirs dans ces diagrammes indiquent les positions de chaque joueur coloré (les carrés) peuvent être déplacés vers:

Diagramme des déplacements de l'équipe rouge Diagramme de déplacement de l'équipe bleue

Les deux couleurs peuvent se déplacer en diagonale dans n'importe quelle direction ou rester immobiles, mais seuls les joueurs rouges peuvent se déplacer de droite à gauche et seuls les joueurs bleus peuvent se déplacer de haut en bas. Merci Phi et les autres.

Si un joueur essaie de sortir des limites du champ de bataille, ou prend trop de temps à décider de la direction dans laquelle se déplacer, ou s'il a une sorte d'erreur, il restera automatiquement immobile.

En plus de se déplacer, un joueur peut, pendant un tour, lire les messages écrits par leurs coéquipiers et écrire des messages qui peuvent à leur tour être lus. Cela permet une forme brute de communication en équipe.

Le code que vous soumettez en tant que réponse est la logique qui détermine le moyen de déplacer votre lecteur et les messages à lire et à écrire (voir "Comment répondre" ).

Retrait des joueurs ennemis

Lorsqu'un joueur entre dans la même cellule qu'un joueur de l'équipe adverse, ce joueur est immédiatement retiré du combat. Le joueur qui vient de déménager continue normalement. C'est le seul mécanisme qui élimine les joueurs de la bataille et sa maîtrise est la clé pour gagner!

S'il y a plusieurs joueurs ennemis dans la cellule sur laquelle un joueur vient d'être transféré, tous les joueurs ennemis sont supprimés. Rien ne se passe si deux joueurs de la même équipe occupent la même cellule.

Gagner une bataille

Une bataille se termine une fois que tous les 2048 mouvements ont été effectués ou qu’une équipe n’a plus de joueurs. L'équipe avec le plus grand nombre de joueurs survivants gagne. Il y a égalité si les deux équipes ont un nombre égal de joueurs survivants.

Comment répondre

Dans votre réponse, vous devez fournir le code JavaScript qui décide de la manière dont votre pixel se déplacera lorsqu'il sera appelé à le faire.

Dans le premier exemple de code en retrait de votre réponse (ceux précédés de 4 espaces), écrivez un corps pour cette fonction:

function moveMe(move, x, y, tCount, eCount, tNear, eNear, setMsg, getMsg) {
    //the body goes here
}

Il n'est pas nécessaire de jouer au golf avec votre code.

Quoi retourner

La valeur de retour de la fonction détermine le sens de déplacement de votre pixel:

0rester immobile pour rester
1à droite pour l'équipe rouge, pour que l'équipe bleue
2se déplacer à gauche pour l'équipe rouge, pour que l'équipe bleue
3se déplacer en diagonale et à droite
4pour se déplacer en diagonale et à gauche
5pour se déplacer en diagonale et à gauche
6pour se déplacer en diagonale bas et à droite

Sous forme de diagramme:

déplacer le diagramme des valeurs de retour

Votre pixel restera immobile par défaut si votre code fait l’une de ces choses:

  • Renvoie autre chose qu'un entier compris entre 0 et 6.
  • Tente de déplacer le pixel hors des limites du champ de bataille.
  • Prend plus de 15 millisecondes à exécuter.
  • Lance toute sorte d'exception.

Votre entrée n'a pas besoin d'être déterministe; utiliser Math.randomc'est bien.

Les paramètres

Les 7 premiers paramètres de fonction de moveMedonnent des informations sur l'état de la bataille:

  • move est un entier qui commence à 1 et s'incrémente après chaque coup jusqu'à ce qu'il soit 1024 au dernier coup de votre équipe.
  • x est votre position x actuelle, un entier compris entre 0 (le plus à gauche) et 127 (le plus à droite).
  • y est votre position y actuelle, un entier compris entre 0 (le plus élevé) et 127 (le plus bas).
  • tCount est le nombre total actuel de joueurs survivants de votre équipe.
  • eCount est le nombre total actuel de joueurs survivants de l'équipe ennemie.
  • tNearest une liste des joueurs survivants de votre équipe qui se trouvent à moins de 16 pixels (distance euclidienne). Chaque élément tNearest un objet x, yet des idpropriétés:
    • x est la position x de l'autre joueur
    • y est la position y de l'autre joueur
    • id est le numéro d'utilisateur PPCG de l'autre joueur (sous forme d'entier)
  • eNearest exactement comme tNearsauf que c'est une liste de joueurs ennemis proches, pas de coéquipiers.

Les cercles dans l'extrait sont ceux de chaque joueur tNearet de leur eNearportée.

messages

Les 2 derniers paramètres, setMsget getMsg, ont des objectifs légèrement différents.

Tout au long d'une bataille, chaque joueur dispose d'une chaîne de 64 caractères maximum qu'il peut manipuler à chaque déplacement pour stocker des données et potentiellement communiquer avec ses coéquipiers. La chaîne de chaque joueur commence par la chaîne vide. Lorsqu'un joueur est retiré de la bataille, sa chaîne est définie sur "X".

  • setMsg est une fonction à un argument qui définit votre chaîne sur la chaîne transmise.
    • Si la valeur transmise n'est pas une chaîne, votre chaîne ne change pas.
    • Si la valeur est une chaîne de plus de 64 caractères, seuls les 64 premiers sont conservés.
  • getMsg est une fonction à un argument qui prend le numéro d'identification de l'utilisateur PPCG (sous la forme d'un entier) de quelqu'un de votre équipe et renvoie sa chaîne.
    • Ce joueur peut être n'importe où dans la grille. Ils n'ont pas besoin d'être dans votre rayon de 16 pixels.
    • undefined est retourné si l'ID donné n'est pas trouvé.

Exemple de soumission

Ce joueur se déplace vers le haut et à droite s'il y a un ennemi à gauche, ou bien vers le bas et à gauche si son coéquipier avec ID 123 dit à, mais reste immobile:

for (var i = 0; i < eNear.length; i++) {
    if (eNear[i].x === x - 1)
        return 3
}
if (getMsg(123) === 'move down and left')
    return 5
return 0

Notez que ce bloc de code est tout ce qui est requis. La définition de la fonction et les crochets ne doivent pas être présents.

Règles et Disqualifications

Si un utilisateur ne respecte pas les règles énumérées ci-dessous, je peux le marquer comme étant disqualifié et le contrôleur ignorera automatiquement ses réponses. J'espère que la plupart des utilisateurs ne vont pas intentionnellement enfreindre les règles et qu'il n'y aura que quelques exclusions temporaires pour cause accidentelle.

Règles importantes

  1. Vous ne pouvez modifier votre réponse que pendant la fenêtre de 8 heures immédiatement après l'avoir postée.
    Les réponses éditées 8 heures après leur publication seront automatiquement disqualifiées par le contrôleur. Cette règle vise à empêcher les réponses initiales d’optimiser continuellement leur approche, voire de voler des idées à des réponses ultérieures. Votre équipe doit se débrouiller avec les réponses avec lesquelles elle a commencé.

    Vous ne pouvez pas supprimer et republier votre réponse sans autorisation spéciale. Je donnerai ceci si quelqu'un modifie par inadvertance votre message après 8 heures ou quelque chose du genre, mais pas seulement parce que vous avez trouvé un bogue.

    Si vous supprimez votre message et choisissez de le supprimer, la règle de modification s'applique toujours. (Le contrôleur ne peut pas voir les réponses supprimées.)

  2. Lors de la déclaration d'une nouvelle variable JavaScript, vous devez utiliser le varmot clé.
    En effet, une variable déclarée sans vardevient globale plutôt que locale, il serait donc facile de jouer accidentellement (ou intentionnellement) avec le contrôleur ou de communiquer librement avec les autres joueurs. Il doit être clair que vous n'essayez pas de tricher.

    Lors de la déclaration de fonctions, il est également préférable d’utiliser le varmot - clé. c'est-à-dire utiliser var f = function(...) {...}au lieu de function f(...) {...}. Je ne sais pas trop pourquoi, mais parfois, cela semble faire la différence.

  3. Votre code ne doit pas être utilisé trop longtemps.
    Si votre code prend plus de 15 millisecondes à exécuter, votre pixel ne bougera pas du tout. Cependant, comme il est difficile en JavaScript d’arrêter les fonctions en cours d’exécution, tous les scripts du lecteur sont exécutés à la fin de chaque mouvement, puis la durée est vérifiée par la suite. Cela signifie que si votre code prend beaucoup de temps, toute personne utilisant le contrôleur le remarquera et en sera contrariée.

Disqualifications automatiques

Le contrôleur a automatiquement disqualifié les entrées pour les raisons suivantes:

  • L'utilisateur a déjà répondu.
  • Les modifications ont été effectuées plus de 8 heures après la création.
  • L'utilisateur est spécifiquement marqué comme disqualifié.

Autres règles

Dans votre code, vous ne pouvez pas ...

  • tenter d'accéder ou de modifier le code du contrôleur ou d'un autre joueur.
  • tenter de modifier quoi que ce soit construit en JavaScript.
  • essayer de communiquer avec les autres joueurs sauf en utilisant getMsget setMsg.
  • faire des requêtes Web.
  • faire des choses autrement malveillantes.

Je garderai un œil sur les autres comportements antisportifs, tels que voler le code mot à mot d'autres réponses ou utiliser des marionnettes à chaussettes pour déconner avec l'autre équipe.

Vous êtes invités à collaborer et à organiser avec votre équipe, mais gardez le concours amical et éthique.

Si vous pensez que quelqu'un doit être disqualifié ou si vous pensez avoir corrigé la raison de votre disqualification, laissez un commentaire ici pour moi ou dans la discussion en question . Je ne participe pas au concours.

Format de réponse suggéré

#[team color] Team - [entry title]

    //function body
    //probably on multiple lines

Explanations, notes, etc.

Le titre de l'entrée est un nom facultatif que vous pouvez donner si vous le souhaitez. Le contrôleur ne fait rien avec elle.

Notation

Ce concours sera officiellement terminé le 19 avril 2015. Ce jour-là (vers 23 h UTC), j'autoriserai au moins 100 batailles (probablement beaucoup plus, en fonction de la durée des batailles). L'équipe qui gagne le plus sera le vainqueur général. Si c'est à égalité ou si serré, je mènerai plus de batailles jusqu'à ce qu'il soit clair qu'une équipe a l'avantage.

(Vous pouvez répondre après la décision du gagnant, mais je ne changerai pas le résultat officiel.)

Je les utiliserai dans la dernière version de Google Chrome sur un ordinateur portable doté de Windows 8.1 64 bits, de 4 Go de RAM et d'un processeur quad-core à 1,6 GHz. Assurez-vous que votre JavaScript fonctionne dans Chrome.

La victoire concerne principalement la gloire de l’équipe, mais j’accepterai la réponse la plus votée de l’équipe gagnante.

Tout au long du concours, gardez à l'esprit que l'aspect basé sur l'équipe et le fait qu'il soit entièrement exécuté dans un extrait de pile sont très expérimentaux. J'ai de grands espoirs, mais je ne peux pas dire avec certitude à quel point les choses vont fonctionner.

Conseils:

  • Vous pouvez tester les entrées avant de répondre. Éditez la zone de texte "Entrée de test" vers le bas de l'extrait de pile et cliquez sur "Recharger avec l'entrée de test". S'il n'est pas vide, il devient un joueur de l'équipe spécifiée.
  • Les réponses sont exécutées dans une portée masquée, ainsi les choses comme alertet console.logne fonctionneront pas. L' consoleobjet ne peut être utilisé que dans l'entrée de test.
  • Vérifiez "Messages de débogage" au bas de l'extrait de pile et regardez dans la console de votre navigateur (F12). De nombreuses informations utiles sont imprimées lorsque des batailles sont en cours.
  • Vous pouvez utiliser le message Meta Sandbox comme une sorte de zone de transit. Les réponses sont bien évidemment différentes de celles d’ici, et le contrôleur peut devenir obsolète.
  • Comme il ne s’agit pas d’une application officielle de pile , le contrôleur peut arrêter de charger les réponses si vous la relancez plus de 300 fois par jour.

La "suite" de ce défi: Block Building Bot Flocks!

Liens rapides

Fiddle Controller    Fullscreen    General Chat       ( Discussion générale générale ) Discussion rouge (discussion en ligne?)    SandboxPost


51
Vous avez fait un travail vraiment génial en mettant tout cela ensemble.
Alex A.

6
Tout le monde, s'il vous plaît utiliser le chat pour les commentaires non cruciaux.
Les passe-temps de Calvin le

4
L'équipe rouge se coordonne dans ce forum: chat.stackexchange.com/rooms/22548/…
Adam Davis le

5
Aidez-moi, je suis absolument amoureux de ça. S'il vous plaît, passez le mot à tous les développeurs que vous connaissez.
Hylianpuffball

3
@ HelkaHomba Hiya! Je voulais juste vous faire savoir que certaines modifications apportées par la communauté les ont disqualifiées.
Stephen

Réponses:


52

Blue Team - SphiNotPi3000

// Char 0: top or bottom ("T" or "B")
// Char 1, 2: x/y coords
// Char 3, move polarity
// Char 4: offset (as codepoint - 128)

var twin = 21487;
var myself = 2867;
var formpos = "T";

var tochar = String.fromCharCode;
var movestat = (move % 2).toString();

var inbox = getMsg(twin);

// Spoofing the message of a deceased partner
if (inbox == "X"){
    inbox = "B" + tochar(x) + tochar(y+1) + ((move + 1) % 2).toString() + tochar(0);
}

var selfsafe = [9,10,10,10,10,10,10];

// Remove useless edge moves
if (x == 0){
    selfsafe[4] = 0;
    selfsafe[5] = 0;
}
if (x == 127){
    selfsafe[3] = 0;
    selfsafe[6] = 0;
}
if (y == 0){
    selfsafe[2] = 0;
    selfsafe[3] = 0;
    selfsafe[4] = 0;
}
if (y == 127){
    selfsafe[1] = 0;
    selfsafe[6] = 0;
    selfsafe[5] = 0;
}

var selfdisp = [[0,0],[0,1],[0,-1],[1,-1],[-1,-1],[-1,1],[1,1]];

if (inbox == "") {
    // First move, pick anywhere safe

    for (j = 0; j < 7; j++) {
        for (var i = 0; i < eNear.length; i++){
            var enemy = eNear[i];
            var dx = enemy.x - x - selfdisp[j][0];
            var dy = enemy.y - y - selfdisp[j][1];

            if (dx * dx == 1 && dy >= -1 && dy <= 1) {
                selfsafe[j] = 0;
            }
        }

        if (selfsafe[j]) {
            var strpos = tochar(x + selfdisp[j][0]) + tochar(y + selfdisp[j][0]);
            var offset = tochar(Math.floor(Math.random() * 256));
            setMsg(formpos + strpos + movestat + offset);
            return j;
        }
    }

} else {
    var twinformpos = inbox.charAt(0);
    var twinx = inbox.charAt(1).charCodeAt();
    var twiny = inbox.charAt(2).charCodeAt();
    var twinmovestat = inbox.charAt(3);
    var offset = inbox.charAt(4);

    formpos = twinformpos == "T" ? "B" : "T";
    var targetx = twinx;
    var targety = formpos == "T" ? (twiny - 1) : (twiny + 1);

    // If true, then this bot is either the second one to move or is not in position.  Move into position.
    if (twinmovestat == movestat || x != targetx || y != targety) {
        var bestmove = 0;

        for (var j = 0; j < 7; j++) {
            for (var i = 0; i < eNear.length; i++){
                var enemy = eNear[i];
                var dx = enemy.x - x - selfdisp[j][0];
                var dy = enemy.y - y - selfdisp[j][1];

                if (dx * dx == 1 && dy >= -1 && dy <= 1) {
                    selfsafe[j] = 0;
                }
                if (dx == 0 && dy == 0){
                    selfsafe[j] *= 2;
                }
            }

            selfsafe[j] -= Math.abs(x + selfdisp[j][0] - targetx) + Math.abs(y + selfdisp[j][1] - targety);

            if (selfsafe[j] > selfsafe[bestmove]) {
                bestmove = j;
            }
        }

        var strpos = tochar(x + selfdisp[bestmove][0]) + tochar(y + selfdisp[bestmove][1]);
        setMsg(formpos + strpos + movestat + offset);
        return bestmove;

    } else {
        // In formation, and is the leader this turn

        var topy = formpos == "T" ? y : (y - 1);
        var topx = x;
        var safe = [1,1,1,1,1,1,1,1,1];
        var disp = [[0,0],[0,1],[0,-1],[1,-1],[-1,-1],[-1,1],[1,1],[1,0],[-1,0]];
        var otherpos = formpos == "T" ? "B" : "T";

        // Avoid dangerous squares and always kill if safe to do so
        for (var j = 0; j < 9; j++){
            var ntopx = topx + disp[j][0];
            var ntopy = topy + disp[j][1];

            if (ntopx < 0 || ntopx > 127 || ntopy < 0 || ntopy > 126){
                safe[j] = 0;
                continue;
            }

            for (var i = 0; i < eNear.length; i++){
                var enemy = eNear[i];
                var dx = enemy.x - ntopx;
                var dy = enemy.y - ntopy;

                if(dx * dx == 1 && dy >= -1 && dy <= 2){
                    safe[j] = 0;
                    continue;
                }

                if(dx == 0 && dy >= 0 && dy <= 1){
                    // Kill!
                    var strpos = tochar(x + disp[j][0]) + tochar(y + disp[j][1]);

                    if (j > 6) {
                        setMsg(otherpos + strpos + movestat + offset);
                        if (formpos == "T"){return 13 - j;}
                        return j - 4;
                    }

                    setMsg(formpos + strpos + movestat + offset);
                    return j;
                }
            }
        }

        var pref = [];

        for (var i = 0; i < eNear.length; i++){
            var enemy = eNear[i];
            var dy = enemy.y - topy;
            var dx = enemy.x - topx;

            if (dy < 0 && dx == 0){ pref=[2,4,3,8,7,1,5,6,0]; }
            if (dy > 0 && dx == 0){ pref=[1,5,6,7,8,2,4,3,0]; }
            if (dy == 0 && dx > 0){ pref=[7,6,3,1,2,5,4,8,0]; }
            if (dy == 0 && dx < 0){ pref=[8,5,4,1,2,6,3,7,0]; }
            if (dy < 0 && dx < 0){ pref=[4,8,5,1,0,2,6,7,3]; }
            if (dy > 0 && dx < 0){ pref=[5,8,4,2,0,1,3,7,6]; }
            if (dy < 0 && dx > 0){ pref=[3,7,6,1,0,2,5,8,4]; }
            if (dy > 0 && dx > 0){ pref=[6,7,3,2,0,1,4,8,5]; }

            for (var k = 0; k < pref.length; k++)
            {
                if (safe[pref[k]]){
                    var strpos = tochar(x + disp[pref[k]][0]) + tochar(y + disp[pref[k]][1]);

                    if (pref[k] > 6) {
                        setMsg(otherpos + strpos + movestat + offset);
                        if(formpos == "T"){return 13 - pref[k];}
                        return pref[k] - 4;
                    }

                    setMsg(formpos + strpos + movestat + offset);
                    return pref[k];
                }
            }
        }

        var offsetint = offset.charCodeAt();
        var offsetmove = move - 128 + offsetint;

        if (offsetmove % 900 < 30) {
            var targetx = 64 - (offsetmove % 30);
            var targety = 64 - (offsetmove % 30);
        } else if (offsetmove % 900 < 90) {
            var targetx = 34 + ((offsetmove - 30) % 60);
            var targety = 34;
        } else if (offsetmove % 900 < 150) {
            var targetx = 94;
            var targety = 34 + ((offsetmove - 30) % 60);
        } else if (offsetmove % 900 < 210) {
            var targetx = 94 - ((offsetmove - 30) % 60);
            var targety = 94;
        } else if (offsetmove % 900 < 270) {
            var targetx = 34;
            var targety = 94 - ((offsetmove - 30) % 60);
        } else if (offsetmove % 900 < 300) {
            var targetx = 34 + (offsetmove % 30);
            var targety = 34 + (offsetmove % 30);
        } else if (offsetmove % 900 < 360) {
            var targetx = 64 + (offsetmove % 60);
            var targety = 64 - (offsetmove % 60);
        } else if (offsetmove % 900 < 480) {
            var targetx = 124;
            var targety = 4 + (offsetmove % 120);
        } else if (offsetmove % 900 < 600) {
            var targetx = 124 - (offsetmove % 120);
            var targety = 124;
        } else if (offsetmove % 900 < 720) {
            var targetx = 4;
            var targety = 124 - (offsetmove % 120);
        } else if (offsetmove % 900 < 840) {
            var targetx = 4 + (offsetmove % 120);
            var targety = 4;
        } else {
            var targetx = 124 - (offsetmove % 60);
            var targety = 4 + (offsetmove % 60);
        }

        if (offsetint % 4 == 1) {
            var temp = targetx;
            var targetx = 127 - targety;
            var targety = temp;
        } else if (offsetint % 4 == 2) {
            var targetx = 127 - targetx;
            var targety = 127 - targety;
        } else if (offsetint % 4 == 3) {
            var temp = targetx;
            var targetx = targety;
            var targety = 127 - temp;
        }

        if ((offsetint >> 3) % 2) {
            var targetx = 127 - targetx;
        }

        var bestmove = 0;

        for (var j = 0; j < 9; j++) {
            safe[j] -= Math.abs(topx + disp[j][0] - targetx) + Math.abs(topy + disp[j][1] - targety);

            if (safe[j] > safe[bestmove]) {
                bestmove = j;
            }
        }

        var strpos = tochar(x + disp[bestmove][0]) + tochar(y + disp[bestmove][1]);

        if (bestmove > 6) {
            setMsg(otherpos + strpos + movestat + offset);
            if (formpos == "T"){return 13 - bestmove;}
            return bestmove - 4;
        }

        setMsg(formpos + strpos + movestat + offset);
        return bestmove;
    }
}

Ce bot forme une paire avec le bot de Sp3000 .

L'idée de base est que deux robots, placés l'un à côté de l'autre, aident à couvrir les faiblesses de l'autre, de sorte qu'aucun des deux robots ne possède un côté exposé. Cela permet de se protéger des menaces et de limiter les options d’échappement de la cible.

Au début du jeu, ils se dirigent l'un vers l'autre et forment une paire. Cette paire se déplace alors comme une seule unité, avec un bot en tête de l’autre. Les deux robots ont un code presque identique, leur permettant d’échanger des positions et des rôles si nécessaire.

Au repos, les robots se déplacent sur le tableau à la recherche d'ennemis. Une fois qu'ils ont repéré un ennemi, ils se sont soigneusement positionnés pour attaquer. Une caractéristique très intéressante est la capacité de la formation à se déplacer droit horizontalement, obtenue en faisant alterner les bots.


9
Oh cher! Dès qu'ils forment une paire, c'est une perte automatique pour le rouge.
Minos

@Minos Assez, oui :)
theonlygusti

Je pensais écrire un bot similaire pour Red, mais je n'y avais jamais pensé auparavant. Maintenant, je dois proposer une stratégie qui puisse battre le duo.
Nit

Pour mémoire, j'ai vu qu'il y a un endroit où il varn'est pas utilisé dans cet article et celui de Sp3000. Ils affectent jimmédiatement à 0 et cela n'interfère pas du tout avec le contrôleur, ce n'est donc heureusement pas un problème dans ce cas.
Les passe-temps de Calvin

47

Blue Team - SphiNotPi3000

// Char 0: top or bottom ("T" or "B")
// Char 1, 2: x/y coords
// Char 3, move polarity
// Char 4: offset (as codepoint - 128)

var myself = 21487;
var twin = 2867;
var formpos = "B";

var tochar = String.fromCharCode;
var movestat = (move % 2).toString();

var inbox = getMsg(twin);

// Spoofing the message of a deceased partner
if (inbox == "X"){
    inbox = "B" + tochar(x) + tochar(y+1) + ((move + 1) % 2).toString() + tochar(0);
}

var selfsafe = [9,10,10,10,10,10,10];

// Remove useless edge moves
if (x == 0){
    selfsafe[4] = 0;
    selfsafe[5] = 0;
}
if (x == 127){
    selfsafe[3] = 0;
    selfsafe[6] = 0;
}
if (y == 0){
    selfsafe[2] = 0;
    selfsafe[3] = 0;
    selfsafe[4] = 0;
}
if (y == 127){
    selfsafe[1] = 0;
    selfsafe[6] = 0;
    selfsafe[5] = 0;
}

var selfdisp = [[0,0],[0,1],[0,-1],[1,-1],[-1,-1],[-1,1],[1,1]];

if (inbox == "") {
    // First move, pick anywhere safe

    for (j = 0; j < 7; j++) {
        for (var i = 0; i < eNear.length; i++){
            var enemy = eNear[i];
            var dx = enemy.x - x - selfdisp[j][0];
            var dy = enemy.y - y - selfdisp[j][1];

            if (dx * dx == 1 && dy >= -1 && dy <= 1) {
                selfsafe[j] = 0;
            }
        }

        if (selfsafe[j]) {
            var strpos = tochar(x + selfdisp[j][0]) + tochar(y + selfdisp[j][0]);
            var offset = tochar(Math.floor(Math.random() * 256));
            setMsg(formpos + strpos + movestat + offset);
            return j;
        }
    }

} else {
    var twinformpos = inbox.charAt(0);
    var twinx = inbox.charAt(1).charCodeAt();
    var twiny = inbox.charAt(2).charCodeAt();
    var twinmovestat = inbox.charAt(3);
    var offset = inbox.charAt(4);

    formpos = twinformpos == "T" ? "B" : "T";
    var targetx = twinx;
    var targety = formpos == "T" ? (twiny - 1) : (twiny + 1);

    // If true, then this bot is either the second one to move or is not in position.  Move into position.
    if (twinmovestat == movestat || x != targetx || y != targety) {
        var bestmove = 0;

        for (var j = 0; j < 7; j++) {
            for (var i = 0; i < eNear.length; i++){
                var enemy = eNear[i];
                var dx = enemy.x - x - selfdisp[j][0];
                var dy = enemy.y - y - selfdisp[j][1];

                if (dx * dx == 1 && dy >= -1 && dy <= 1) {
                    selfsafe[j] = 0;
                }
                if (dx == 0 && dy == 0){
                    selfsafe[j] *= 2;
                }
            }

            selfsafe[j] -= Math.abs(x + selfdisp[j][0] - targetx) + Math.abs(y + selfdisp[j][1] - targety);

            if (selfsafe[j] > selfsafe[bestmove]) {
                bestmove = j;
            }
        }

        var strpos = tochar(x + selfdisp[bestmove][0]) + tochar(y + selfdisp[bestmove][1]);
        setMsg(formpos + strpos + movestat + offset);
        return bestmove;

    } else {
        // In formation, and is the leader this turn

        var topy = formpos == "T" ? y : (y - 1);
        var topx = x;
        var safe = [1,1,1,1,1,1,1,1,1];
        var disp = [[0,0],[0,1],[0,-1],[1,-1],[-1,-1],[-1,1],[1,1],[1,0],[-1,0]];
        var otherpos = formpos == "T" ? "B" : "T";

        // Avoid dangerous squares and always kill if safe to do so
        for (var j = 0; j < 9; j++){
            var ntopx = topx + disp[j][0];
            var ntopy = topy + disp[j][1];

            if (ntopx < 0 || ntopx > 127 || ntopy < 0 || ntopy > 126){
                safe[j] = 0;
                continue;
            }

            for (var i = 0; i < eNear.length; i++){
                var enemy = eNear[i];
                var dx = enemy.x - ntopx;
                var dy = enemy.y - ntopy;

                if(dx * dx == 1 && dy >= -1 && dy <= 2){
                    safe[j] = 0;
                    continue;
                }

                if(dx == 0 && dy >= 0 && dy <= 1){
                    // Kill!
                    var strpos = tochar(x + disp[j][0]) + tochar(y + disp[j][1]);

                    if (j > 6) {
                        setMsg(otherpos + strpos + movestat + offset);
                        if (formpos == "T"){return 13 - j;}
                        return j - 4;
                    }

                    setMsg(formpos + strpos + movestat + offset);
                    return j;
                }
            }
        }

        var pref = [];

        for (var i = 0; i < eNear.length; i++){
            var enemy = eNear[i];
            var dy = enemy.y - topy;
            var dx = enemy.x - topx;

            if (dy < 0 && dx == 0){ pref=[2,4,3,8,7,1,5,6,0]; }
            if (dy > 0 && dx == 0){ pref=[1,5,6,7,8,2,4,3,0]; }
            if (dy == 0 && dx > 0){ pref=[7,6,3,1,2,5,4,8,0]; }
            if (dy == 0 && dx < 0){ pref=[8,5,4,1,2,6,3,7,0]; }
            if (dy < 0 && dx < 0){ pref=[4,8,5,1,0,2,6,7,3]; }
            if (dy > 0 && dx < 0){ pref=[5,8,4,2,0,1,3,7,6]; }
            if (dy < 0 && dx > 0){ pref=[3,7,6,1,0,2,5,8,4]; }
            if (dy > 0 && dx > 0){ pref=[6,7,3,2,0,1,4,8,5]; }

            for (var k = 0; k < pref.length; k++)
            {
                if (safe[pref[k]]){
                    var strpos = tochar(x + disp[pref[k]][0]) + tochar(y + disp[pref[k]][1]);

                    if (pref[k] > 6) {
                        setMsg(otherpos + strpos + movestat + offset);
                        if(formpos == "T"){return 13 - pref[k];}
                        return pref[k] - 4;
                    }

                    setMsg(formpos + strpos + movestat + offset);
                    return pref[k];
                }
            }
        }

        var offsetint = offset.charCodeAt();
        var offsetmove = move - 128 + offsetint;

        if (offsetmove % 900 < 30) {
            var targetx = 64 - (offsetmove % 30);
            var targety = 64 - (offsetmove % 30);
        } else if (offsetmove % 900 < 90) {
            var targetx = 34 + ((offsetmove - 30) % 60);
            var targety = 34;
        } else if (offsetmove % 900 < 150) {
            var targetx = 94;
            var targety = 34 + ((offsetmove - 30) % 60);
        } else if (offsetmove % 900 < 210) {
            var targetx = 94 - ((offsetmove - 30) % 60);
            var targety = 94;
        } else if (offsetmove % 900 < 270) {
            var targetx = 34;
            var targety = 94 - ((offsetmove - 30) % 60);
        } else if (offsetmove % 900 < 300) {
            var targetx = 34 + (offsetmove % 30);
            var targety = 34 + (offsetmove % 30);
        } else if (offsetmove % 900 < 360) {
            var targetx = 64 + (offsetmove % 60);
            var targety = 64 - (offsetmove % 60);
        } else if (offsetmove % 900 < 480) {
            var targetx = 124;
            var targety = 4 + (offsetmove % 120);
        } else if (offsetmove % 900 < 600) {
            var targetx = 124 - (offsetmove % 120);
            var targety = 124;
        } else if (offsetmove % 900 < 720) {
            var targetx = 4;
            var targety = 124 - (offsetmove % 120);
        } else if (offsetmove % 900 < 840) {
            var targetx = 4 + (offsetmove % 120);
            var targety = 4;
        } else {
            var targetx = 124 - (offsetmove % 60);
            var targety = 4 + (offsetmove % 60);
        }

        if (offsetint % 4 == 1) {
            var temp = targetx;
            var targetx = 127 - targety;
            var targety = temp;
        } else if (offsetint % 4 == 2) {
            var targetx = 127 - targetx;
            var targety = 127 - targety;
        } else if (offsetint % 4 == 3) {
            var temp = targetx;
            var targetx = targety;
            var targety = 127 - temp;
        }

        if ((offsetint >> 3) % 2) {
            var targetx = 127 - targetx;
        }

        var bestmove = 0;

        for (var j = 0; j < 9; j++) {
            safe[j] -= Math.abs(topx + disp[j][0] - targetx) + Math.abs(topy + disp[j][1] - targety);

            if (safe[j] > safe[bestmove]) {
                bestmove = j;
            }
        }

        var strpos = tochar(x + disp[bestmove][0]) + tochar(y + disp[bestmove][1]);

        if (bestmove > 6) {
            setMsg(otherpos + strpos + movestat + offset);
            if (formpos == "T"){return 13 - bestmove;}
            return bestmove - 4;
        }

        setMsg(formpos + strpos + movestat + offset);
        return bestmove;
    }
}

Ce bot forme une paire avec le bot de PhiNotPi . Voir le post de Phi pour une brève explication de notre stratégie.


Aie! Bon un ..
DoubleDouble

21

Équipe Rouge - SeekerBot

var myself = 38926;
var messages = getMsg(myself).split(';');
var minimalDistanceToFriend = 2;
var chosenMove = null;
var newDistanceToFriend = null;
var minimalVerticalDistanceToEnemy = null, minimalHorizontalDistanceToEnemy = null;
var closestFriend = null;
var closestEnemy = null;
var possibleVictims = [];
var possibleMoves = [
    {newX: x, newY: y},
    {newX: x + 1, newY: y},
    {newX: x - 1, newY: y},
    {newX: x + 1, newY: y - 1},
    {newX: x - 1, newY: y - 1},
    {newX: x - 1, newY: y + 1},
    {newX: x + 1, newY: y + 1}
];

var calculateDistance = function(x1, y1, x2, y2) {
    return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
};

var iAmInDanger = function(meX, meY, himX, himY) {
    return (Math.abs(meY - himY) === 1 && Math.abs(meX - himX) <= 1);
};

var iCanKillHim = function(meX, meY, himX, himY) {
    return (Math.abs(meX - himX) === 1 && Math.abs(meY - himY) <= 1);
};

var setMessage = function() {
    messages[0] = ("000" + x).substr(-3, 3);
    messages[1] = ("000" + y).substr(-3, 3);
    setMsg(messages.join(';'));
}

for (i = 0; i < possibleMoves.length; i++) {
    if (possibleMoves[i].newX < 0 || possibleMoves[i].newY < 0 || possibleMoves[i].newX > 127 || possibleMoves[i].newY > 127) {
        possibleMoves[i] = null;
    }
}

for (var i = 0; i < eNear.length; i++) {
    if (closestEnemy === null || calculateDistance(x, y, closestEnemy.x, closestEnemy.y) > calculateDistance(x, y, eNear[i].x, eNear[i].y)) {
        closestEnemy = eNear[i];
    }
    if (Math.abs(x - eNear[i].x) <= 2 && Math.abs(y - eNear[i].y) <= 2) {
        possibleVictims.push(eNear[i]);
    }
}

for (i = 0; i < tNear.length; i++) {
    if (closestFriend === null || calculateDistance(x, y, closestFriend.x, closestFriend.y) > calculateDistance(x, y, tNear[i].x, tNear[i].y)) {
        closestFriend = tNear[i];
    }
}    

for (i = 0; i < possibleMoves.length; i++) {
    for (var j = 0; j < possibleVictims.length; j++) {
        if (possibleMoves[i] !== null && iAmInDanger(possibleMoves[i].newX, possibleMoves[i].newY, possibleVictims[j].x, possibleVictims[j].y)) {
            possibleMoves[i] = null;
        }
    }
}

for (i = 0; i < possibleMoves.length; i++) {
    for (j = 0; j < possibleVictims.length; j++) {
        if (possibleMoves[i] !== null && possibleMoves[i].newX === possibleVictims[j].x && possibleMoves[i].newY === possibleVictims[j].y) {
            messages[2] = 0;
            setMessage();
            return i;
        }
    }
}

if (possibleVictims.length > 0) {
    if (iAmInDanger(x, y, possibleVictims[0].x, possibleVictims[0].y)) {
        if (closestFriend !== null) {
            for (i = 0; i < possibleMoves.length; i++) {
                if (possibleMoves[i] !== null) {
                    var distance = calculateDistance(possibleMoves[i].newX, possibleMoves[i].newY, closestFriend.x, closestFriend.y);
                    if (newDistanceToFriend === null || (distance < newDistanceToFriend && distance >= minimalDistanceToFriend)) {
                        newDistanceToFriend = distance;
                        chosenMove = i;
                    }
                }
            }
            messages[2] = 0;
            setMessage();
            return chosenMove;
        }
        else {
            var aggressiveMoves = [];
            var randomMoves = [];

            for (i = 0; i < possibleMoves.length; i++) {
                if (possibleMoves[i] !== null) {
                    if (iCanKillHim(possibleMoves[i].newX, possibleMoves[i].newY, possibleVictims[0].x, possibleVictims[0].y)) {
                        aggressiveMoves.push(i);
                    }
                    randomMoves.push(i);
                }
            }
            var approachCount = messages[2] || 0;
            if (approachCount < 5 && aggressiveMoves.length > 0) {
                messages[2] = approachCount + 1;
                chosenMove = aggressiveMoves[Math.floor(Math.random() * aggressiveMoves.length)];
                setMessage();
                return chosenMove;
            } 
            else {
                chosenMove = randomMoves[Math.floor(Math.random() * randomMoves.length)];
                setMessage();
                return chosenMove;
            }
        }
    }
}

if (closestEnemy != null) {
    for (i = 1; i < possibleMoves.length; i++) {
        if (possibleMoves[i] !== null) {
            var verticalDistance = Math.abs(possibleMoves[i].newY - closestEnemy.y);
            var horizontalDistance = Math.abs(possibleMoves[i].newX - closestEnemy.x);
            if (minimalVerticalDistanceToEnemy === null || verticalDistance <= minimalVerticalDistanceToEnemy) {
                if (minimalVerticalDistanceToEnemy !== null && verticalDistance === minimalVerticalDistanceToEnemy) {
                    if (minimalHorizontalDistanceToEnemy === null || horizontalDistance <= minimalHorizontalDistanceToEnemy) {
                        minimalHorizontalDistanceToEnemy = horizontalDistance;
                        chosenMove = i;
                    }
                }
                else {
                    minimalVerticalDistanceToEnemy = verticalDistance;
                    minimalHorizontalDistanceToEnemy = horizontalDistance;
                    chosenMove = i;
                }                                        
            }
        }            
    }
    messages[2] = 0;
    setMessage();
    return chosenMove;
}

var seekStatus = messages[3] || 0;
var seekCount = messages[4] || 0;
seekStatus = parseInt(seekStatus, 10);
seekCount = parseInt(seekCount, 10);

switch (seekStatus) {
    case 0:
        if (x < 16) {
            seekCount = 0;
            if (y > 111) {
                seekStatus = 4;
            }
            else {
                seekStatus = 1;
            }                
        }
        else {
            chosenMove = 2;
        }
        break;
    case 1:
        seekCount++;
        if (y > 111 || seekCount > 31) {
            seekStatus = 2;
        }            
        else {
            if (seekCount % 2 === 0) {
                chosenMove = 5;
            }
            else {
                chosenMove = 6;
            }
        }
        break;
    case 2:
        if (x > 111) {
            seekCount = 0;
            if (y > 111) {
                seekStatus = 4;
            }
            else {
                seekStatus = 3;
            }                   
        }
        else {
            chosenMove = 1;
        }
        break;
    case 3:
        seekCount++;
        if (y > 111 || seekCount > 31) {
            seekStatus = 0;
        }
        else {
            if (seekCount % 2 === 0) {
                chosenMove = 5;
            }
            else {
                chosenMove = 6;
            }
        }
        break;
    case 4:
        seekCount++;
        if (y < 16) {
            if (x > 63) {
                seekStatus = 0;
            }
            else {
                seekStatus = 2;
            }
        }
        else {
            if (seekCount % 2 === 0) {
                chosenMove = 3;
            }
            else {
                chosenMove = 4;
            }
        }
        break;
}

messages[2] = 0;
messages[3] = seekStatus;
messages[4] = seekCount;    

setMessage();
return chosenMove;

La priorité absolue de SeekerBot est la survie. Par conséquent, il ne considérera que les mouvements qui ne le mettront pas en danger d'être tué au prochain tour (tant que de tels mouvements existent).

Quand aucun adversaire n'est en vue, il se déplacera de manière régulière sur le champ de bataille, ce qui garantira que la plus grande partie du sol sera régulièrement à distance de vue.

Si SeekerBot repère un ennemi, il se déplacera vers lui. S'il peut tuer un ennemi, il le fera tant que le mouvement est enregistré.

S'il ne peut pas tuer un ennemi mais que celui-ci est en mesure de le tuer lors de son prochain tour, SeekerBot tentera d'attirer l'ennemi vers un ami (le cas échéant). Si aucun membre de l'équipe n'est en vue, il essaiera de se déplacer dans une position où il pourra tuer l'ennemi lors du prochain tour. Si cela ne fonctionne pas 5 fois de suite, il changera de tactique et commencera à se déplacer de manière aléatoire, se rapprochant éventuellement de l'ennemi lors du prochain tour.

Pour ce que ça vaut, il utilisera les 7 premiers caractères du message pour crier sa propre position dans le format "x; y" (où x et y sont remplis de zéro).

Ce n'est certainement pas le code le plus propre, mais il semble en faire ce que j'attendais de lui.



2
Vous avez amené l'équipe rouge à gagner chaque fois que je l'ai couru. Sera intéressant de voir ce que les deux nouveaux robots bleus font une fois qu’ils se sont ligués.
Adam Davis

C'est très amusant de regarder ce massacre le blues :)
TheNumberOne

@AdamDavis La coordination de ces deux robots bleus est insensée. chaque match que j'ai regardé jusqu'à présent, ils ont battu!
theonlygusti

12

Équipe Rouge - Groomba

// v009
// I exist, therefore I am identifiable and have motivation
var myself = 1686;
var motive = [ 4,4, 4,-1, 4,3, 3,-1, 
               3,3, 3,1, 1,1, 6,1,
               6,6, 6,-2, 6,5, 5,-2,
               5,5, 5,2, 2,2, 4,2]; 
var killzone = [4,2,5, 3,1,6];

// Default move is to not move.  Then we consider each task in lowest
// to highest priority.  Each task only modifies the move if it needs to.
var move = 0;
var vector = 0;
var step = 0;

// Restore internal state from message
var selfMessage;
selfMessage = getMsg(myself);
if(selfMessage === undefined || selfMessage.length > 2) // first run or bigger than 99, let's make some defaults!
{
   // vector, step - let the default above stand
}
else
{
   vector = Math.floor(parseInt(selfMessage)/2) % 16;
   step = parseInt(selfMessage) % 2;
}

// 1) Move according to motivation
move = motive[vector*2 + step];
step = (step + 1) % 2;

if(move == -1)
{
   move = Math.floor(Math.random() * 2) + 3;
}

if(move == -2)
{
   move = Math.floor(Math.random() * 2) + 5;
}

// 2) When interacting with a wall, rebound but alter the angle 
//    slightly so as to prevent trivial counterattack strategies
// If we are close to a wall and headed towards that wall, randomly
// choose another vector to follow.
if((y < 8 && (vector > 14 || vector < 6)) ||
   (y > 120 && (vector > 6 && vector < 14)) ||
   (x < 8 && (vector > 10 || vector < 2)) ||
   (x > 120 && (vector > 2 && vector < 10)))
{
   vector = Math.floor(Math.random() * 16);
}

// When an enemy is within view, move beside them

if(eNear.length > 0) // I only look at the first enemy in the array.
{
    enemy = eNear[0];
    if(enemy.x == x) // Don't want to be directly on top or below
    {
       if(enemy.y > y) // If they are below move angular down
       {
           move = (x > 63) ? 5 : 6;
       }
       else
       {
           move = (x > 63) ? 4 : 3;
       }
       move = 1;
    }
    else if(enemy.y > y)
    {
       if(enemy.x > x)
       {
           move = 6;
       }
       else
       {
           move = 5;
       }
       vector = 10;
    }
    else if(enemy.y != y)
    {
       if(enemy.x > x)
       {
           move = 3;
       }
       else
       {
           move = 4;
       }
        vector = 2;
    }
    else
    {
        if(enemy.x > x)
        {
            move = 1;
            vector = 6
        }
        else
        {
            move = 2;
            vector = 14;
        }
    }
}

// 3) When an enemy is one space away, act or react.
//    A) If it can be consumed, consume
//    B) If it can consume us next turn, evade
//    C) If we can reposition ourselves to consume next turn, reposition

var enemy;
var difx;
var dify;

// Evade
for(var i=0; i<eNear.length; i++) {
    enemy = eNear[i];
    if(enemy.x == x && enemy.y == y + 1)
    {
       if(x>63)
       {
           move = 5;
       }
       else
       {
           move = 6;
       }
    }
    if(enemy.x == x && enemy.y == y - 1)
    {
       if(x>63)
       {
           move = 4;
       }
       else
       {
           move = 3;
       }
    }
}

// Kill
for(var i=0; i<eNear.length; i++) {
    enemy = eNear[i];
    difx = enemy.x - x + 1;
    dify = enemy.y - y + 1;
    if((difx == 0 || difx == 2) && (dify > -1 && dify < 3))
    {
       move = killzone[Math.floor(difx/2) * 3 + dify];
    }
}

// 4) Encode the current surroundings and internal state
var value = vector*2+step
var message = value.toString();
setMsg(message);

// Return move
return move;

Notes dans les commentaires.


3
Ne pas utiliser self. Cette variable est réservée à pointer window.self. Utilisez I(capital i) à la place. Ou me. Ou même myself.
Ismael Miguel le

11

Red Team - Slayer Slayer

var moves={
    '-1':{'-1':4,'0':0,'1':3},
    '0':{'-1':2,'0':0,'1':1},
    '1':{'-1':5,'0':0,'1':6}
},$id=14732,to,enemies='';

for(var k in eNear)
{
    enemies+=String.fromCharCode(eNear[k].x+32)+String.fromCharCode(eNear[k].y+32);
}

enemies=enemies.replace('"','\\"');

for(var k in eNear)
{
    to=undefined;
    switch( eNear[k].x - x )
    {
        case -1:
        case 1:
            to=moves[eNear[k].y - y][eNear[k].x - x];
            break;
        case 0:
            to=moves[-(eNear[k].y - y)][0];
            break;
    }
    if(to!==undefined)
    {
        setMsg('"a":1,"o":['+x+','+y+'],"m":'+(to||0)+',"e":"'+enemies+'"');
        return to;
    }
}

var msg;

for(var k in tNear)
{
    if(msg = getMsg(tNear[k].id))
    {
        try
        {
            var m=JSON.parse('{'+msg+'}');
            if(m && m[$id])
            {
                if(m[$id].a === 1)
                {
                    if(!m[$id].x || !m[$id].y)
                    {
                        setMsg('"a":1,"o":['+x+','+y+'],"m":'+m[$id].m+',"id":'+m[$id].id+'}');
                        return m[$id].m;
                    }
                    else
                    {
                        setMsg('"a":1,"o":['+x+','+y+'],"m":{"x":'+m[$id].x+',"y":'+m[$id].y+'},"id":'+m[$id].id+',"e":"'+enemies+'"');
                        return moves[m[$id].x][m[$id].y];
                    }
                }
                else if(m[$id].a === 0)
                {
                    setMsg('"a":0,"o":['+x+','+y+'],"m":0,"id":'+m[$id].id+',"e":"'+enemies+'"');
                    return moves[m[$id].x||0][m[$id].y||0];
                }
            }
        }
        catch(e){}
    }
}

setMsg('"a":0,"o":['+x+','+y+'],"m":0,"e":"'+enemies+'"');
return 0;

C'est le plus fondamental, je pourrais l'obtenir. Ce n'est plus 100% de base.

Il ne se déplace que si nécessaire .

Si un utilisateur envoie un message avec 2 chiffres entre -1et1 (par exemple:) '1,0', séparés par une virgule, il s'y déplacera. Il fait totalement confiance à ses coéquipiers.

Cela communique maintenant via JSON. Il a une structure très basique:

  • getMsg:
    • a: détermine l'action:
      • 0: arrêter
      • 1: bouger
    • m: le mouvement à envoyer
      • {x: n, y: n}: objet avec x et y, compris entre -1 et 1
      • valeur brute à renvoyer avec le nombre représenté dans la grille.
  • setMsg:
    • a: indique si elle s'est déplacée ou si elle s'est arrêtée;
    • o: un tableau avec mon ancienne position;
    • m: le mouvement brut retourné par le code;
    • id: si un ordre a été respecté, cela aura l'identifiant du coupable;
    • e: liste avec toutes les positions ennemies. Chaque position est polarisée de 32 pour éviter les caractères non imprimables. Utilisez string.charCodeAt (i) -32 pour obtenir la position ennemie. Ce sera une chaîne de même longueur. Chaque ennemi aura 2 personnages.

Un exemple de message pour le contrôler:

"14732":{"a":1,"m":3}

Qui enverra:

"a":1,"o":[x,y],"m":3,"id":id,"e":""

Il est aussi un peu égoïste et ne vous aidera pas et maintenant il est utile en tant que balise fixe.

Si ce message est incorrect (le format n'est pas correct), essayez d'ajouter à la "}place de }.


Cette édition a été modifiée après la limite de 6 heures et après avoir été étendue à 8 heures.

Il n'est plus cassé et restera comme la version finale.


2
En tant que membre de l'équipe rouge, je pense qu'une chose cruciale que nous devrions inclure est toujours de définir un message avec votre état actuel et de l'entourer sous une forme convenue d'objet (cela doit inclure le mouvement sur lequel cette action a été définie, sinon les bots sont gagnés » t savoir quel état est obsolète). Cela permettra à d’autres bots, plus tard, d’être conscients de plus que leur propre environnement, peut-être de tout le conseil, et de prendre de meilleures décisions.
Nit le

@Nit Je suis d'accord avec vous et c'est pourquoi j'ai choisi d'utiliser JSON pour communiquer. J'ai 5 heures et 22m pour faire des changements. d'autres idées?
Ismael Miguel

1
Je pense que les premiers doivent être des scanners. Nous n'avons besoin que de quatre balayer d'un côté à l'autre pour recouvrir la totalité du tableau (32 largeurs de balayage effectives couvrant 1/4 du tableau). Déplacez-vous d'un côté à l'autre, définissez les N méchants les plus proches à l'aide d'une chaîne binaire ou comprimée et évitez-les, ou cherchez et tuez les méchants en suivant une stratégie raisonnable pour éviter d'être tués (ne les laissez jamais entrer dans votre coin, ni plus ni moins toi?).
Adam Davis

1
@IsmaelMiguel Nope. J'espère pouvoir en soumettre un prochain également, mais ne sachant pas que le Javascript me ralentit.
Adam Davis

3
S'il n'est pas cassé, supprimez les anciens commentaires obsolètes pour réduire l'encombrement.
Nit le

10

Red Team - Le lâche

var bounds = 128;
var movements = [[0,0], [-1,-1],[1,-1],[-1,0],[1,0],[-1,1],[1,1]];

var distanceTo = function(x, y, pixel)
{
    var a = x - pixel.x;
    var b = y - pixel.y;
    return Math.sqrt( a*a + b*b );
}

var isDiagonallyAdjacent = function(x, y, pixel)
{
    return (Math.abs(pixel.x - x) == 1 && Math.abs(pixel.y - y) == 1);
}

var canAttackMe = function(x, y, pixel)
{
    if(x == pixel.x && Math.abs(pixel.y - y) == 1)
    {
        return true;
    }
    else
    {
        return isDiagonallyAdjacent(x, y, pixel);
    }
}

var canIAttack = function(x, y, pixel)
{
    if(y == pixel.y && Math.abs(pixel.x - x) == 1)
    {
        return true;
    }
    else
    {
        return isDiagonallyAdjacent(x, y, pixel);
    }
}

var isPositionSafe = function(x2, y2, enemies)
{
    var safe = true;
    for(var i in enemies)
    {
        if(canAttackMe(x2, y2, enemies[i]))
        {
            safe = false;
            break;
        }
    }
    return safe;
}

var moveTo = function(x, y, x2, y2)
{
    if(x2 < x)
    {
        if(y2 < y) return 4;
        else if(y2 > y) return 5;
        else return 2;
    }
    else if(x2 > x)
    {
        if(y2 < y) return 3;
        else if(y2 > y) return 6;
        else return 1;
    }
    else
    {
        if(y2 < y)
        {
            if(x2 < bounds)
            {
                return 3;
            }
            return 4;
        }
        else if(y2 > y)
        {
            if(x2 >= 0)
            {
                return 5;
            }
            return 6;
        }
    }
    return 0;
}

var getMovement = function(i)
{
    var m = [[0, 0], [1, 0], [-1, 0], [1, -1], [-1, -1], [-1, 1], [1, 1]];
    return m[i];
}

if(eNear.length == 0)
{
    // Move at random
    //return Math.floor((Math.random() * 6) + 1);
    return 0;
}
else 
{
    var safePositions = [];
    var isSafePosition = function(x2, y2)
    {
        for(var i in safePositions)
        {
            if(safePositions[i][0]==x2 && safePositions[i][0]==y2)
            {
                return true;
            }
        }
        return false;
    }

    for(var i in movements)
    {
        var x2 = x + movements[i][0];
        var y2 = y + movements[i][1];
        if(x2 >= 0 && x2 < bounds && y2 >= 0 && y2 < bounds
            && isPositionSafe(x2, y2, eNear))
        {
            safePositions.push([x + movements[i][0], y + movements[i][1]]);
        }
    }

    var dangerousPixels = [];
    var attackablePixels = [];
    var kamikazePixels = [];

    for(var ei in eNear)
    {
        var e = eNear[ei];
        var attackable = canIAttack(x, y, e);
        var dangerous = canAttackMe(x, y, e);
        if( attackable )
        {
            if(isSafePosition(e.x, e.y))
            {
                attackablePixels.push(e);
            }
            else
            {
                kamikazePixels.push(e);
            }
        }
        else if(dangerous)
        {
            dangerousPixels.push(e);
        }
    }
    if(attackablePixels.length == eNear.length)
    {
        return moveTo(attackablePixels[0].x, attackablePixels[0].y);
    }
    if(attackablePixels.length > 0 && tNear.length >= eNear.length)
    {
        // Attack only if we have greater numbers
        // Attack one of them at random
        var i = Math.floor(Math.random() * attackablePixels.length);
        return moveTo(x, y, attackablePixels[i].x, attackablePixels[i].y);
    }
    else if(dangerousPixels.length > 0 && safePositions.length > 0)
    {
        // Flee
        var i = Math.floor(Math.random() * safePositions.length);
        return moveTo(x, y, safePositions[i][0], safePositions[i][1]);

    }
    else if(dangerousPixels.length > 0 && safePositions.length == 0 && kamikazePixels.length > 0)
    {
        var i = Math.floor(Math.random() * kamikazePixels.length);
        return moveTo(x, y, kamikazePixels[i].x, kamikazePixels[i].y);
    }
    else 
    {
        var nearest = null;
        var nearestDist = Infinity;
        for(var ei in eNear)
        {
            var e = eNear[ei];
            var d = distanceTo(x, y, e);
            if(nearest === null || d < nearestDist)
            {
                nearestDist = d;
                nearest = e;
            }
        }

        if(tNear.length >= eNear.length)
        {
            // Attack the nearest
            return moveTo(x, y, nearest.x, nearest.y);
        }
        else
        {
            // Get Away from the nearest
            var n = moveTo(x, y, nearest.x, nearest.y);
            var m = getMovement(n);
            var x2 = x-m[0];
            var y2 = y-m[1];
            if(x2 < 0 || x2 >= bounds) x2 = x + m[0];
            if(y2 < 0 || y2 >= bounds) y2 = y + m[1];
            return moveTo(x, y, x2, y2);
        }
    }
}

Ce bot reste toujours pour éviter d'être détecté autant que possible. Lorsqu'un ou plusieurs ennemis sont en vue, plusieurs choses peuvent se produire:

  • S'il y a plus d'ennemis que le bot et ses alliés en vue, il tente de s'éloigner de l'ennemi le plus proche.
  • S'il y a plus d'amis en vue que d'ennemis, la supériorité numérique donne du courage au bot et tente d'aller de l'avant et d'attaquer l'ennemi.
  • S'il peut tuer un ennemi à côté de lui, il essaiera, quel que soit le nombre de robots amis et ennemis, de toujours essayer de se retrouver dans une cellule qui ne peut pas être attaquée par un autre bot.
  • Si tous les ennemis sont protégés par d'autres ennemis, tente de fuir.
  • S'il ne peut pas aller n'importe où parce que toutes les positions peuvent être attaquées, entre en mode kamikaze et essaie au moins d'amener quelqu'un avec lui dans la tombe.

Ne communique avec personne, au cas où quelqu'un pourrait l'entendre et le poursuivre.

Ce n'est peut-être pas le bot le plus utile pour l'équipe, mais c'était amusant de le regarder essayer de s'éloigner de tout le monde.


Ok, j'aime ton bot. Le mien est un peu à l'opposé (il cherche des ennemis et se dirige ensuite vers le centre), il a donc une interaction fantastique où le mien pourrait essayer de taquiner le tien du coin et de le traîner vers le milieu, mais si ton voisin voit quelqu'un, il aura peur. et retourne au coin, tandis que le mien le poursuit.
Hylianpuffball

Merci! Je trouve ça drôle de le voir interagir avec les autres. Mais j’ai trouvé quelques bugs au sujet des limites et de la façon dont elles rebondissaient, mais il était trop tard pour les réparer ... Donc, ce n’est pas aussi bon que je le souhaiterais.
rorlork

9

Blue team - Eagle

var move_valid = function(x, y, move){
    var move_x = {0:0, 1:0, 2:0, 3:1, 4:-1, 5:-1, 6:1};
    var move_y = {0:0, 1:1, 2:-1, 3:-1, 4:-1, 5:1, 6:1};
    var xx = x + move_x[move];
    var yy = y + move_y[move];
    return (1 <= xx && xx <= 125 && 1 <= yy && yy <= 125);
}
var sign = function(x){
    if (x === 0) return 0;
    else if (x > 0) return 1;
    else return -1;
}

if (eNear.length === 0) {
    if (getMsg(29577).length > 0) {
        var last_move = parseInt(getMsg(29577).charAt(0))
        if (last_move !== 0 && 
            move_valid(x, y, last_move) &&
            Math.random() > 0.03) return last_move;
    }

    var moves = [1, 2, 3, 4, 5, 6];
    var valid_moves = [];
    for (var move of moves){if (move_valid(x, y, move)) valid_moves.push(move);}
    if (valid_moves.length === 0) valid_moves.push(0);
    var move = moves[Math.floor(Math.random()*moves.length)];
    setMsg(move.toString());
    return move;
} else {
    var enemy = eNear[0];
    var dist = Math.max(Math.abs(x- enemy.x), Math.abs(y - enemy.y))
    var dir_x = sign(enemy.x - x);
    var dir_y = sign(enemy.y - y);
    var dir_to_move = {1: {1: 6, 0: -1, "-1": 3}, 0: {1: 1, 0: 1, "-1": 2}, "-1": {1: 5, 0: -1, "-1": 4}};
    var move = dir_to_move[dir_x][dir_y];
    var fight_count = 0;
    if (getMsg(29577).length > 1) {
        fight_count = parseInt(getMsg(29577).substring(1));
    }
    fight_count += 1;
    if (fight_count > 100){
        if (fight_count > 110) fight_count = 0;
        move = dir_to_move[-dir_x][dir_x !== 0 ? -dir_y : (Math.random() > 0.5 ? 1 : -1)];
        setMsg(move.toString() + fight_count.toString());
        return move;
    } else {
        if (dist > 2) {
            // Move towards enemy
            if (move === -1) move = dir_to_move[dir_x][Math.random() > 0.5 ? 1 : -1]
            setMsg(move.toString() + fight_count.toString());
            return move;
        } else if (dist === 2) {
            if (Math.abs(x - enemy.x) < 2) {
                // go one down if === 0
                // go diagonal, if ===1
                // move is already correct  
            } else if (Math.abs(y - enemy.y) === 2) {
                // dist_x == dist_y
                move = dir_to_move[0][dir_y];
            } else if (Math.abs(y - enemy.y) === 1) {
                move = dir_to_move[dir_x][-dir_y];
            } else {
                // dist_y == 0, dist_x == 2
                move = dir_to_move[0][Math.random() > 0.5 ? 1 : -1]
            }
            setMsg(move.toString() + fight_count.toString());
            return move;
        } else if (dist === 1) {
            if (move !== -1) {
                // Kill
                setMsg(move.toString() + fight_count.toString());
                return move;
            } else {
                // Run away
                var move = dir_to_move[-dir_x][Math.random() > 0.5 ? 1 : -1]
                setMsg(move.toString() + fight_count.toString());
                return move;
            }
        }
    }
    return 0;
}

Je suis assez content de mon bot pour le moment. Il a la tactique suivante:

  • S'il n'y a pas d'ennemi, avancez dans une direction aléatoire. Si je frappe un mur ou après environ 33 mouvements, je change de direction.
  • Si je vois un ennemi, je me dirige vers lui. (Attention à ne pas aller sur un terrain où l'ennemi peut me tuer). Une fois que j'en approche, approchez-vous du haut ou du bas et tuez-le.

7

Équipe bleue - Enemyeater

for (var i = 0; i < eNear.length; i++) {
    var enemy = eNear[i];
    var rx = enemy.x - x;
    var ry = enemy.y - y;
    if (rx == -1) {
        if (ry == 1) {
            return 4;
        }
        return 5;
    }
    if (rx == 0) {
        if (ry == 1) {
            return 2;
        }
        return 1;
    }
    if (rx == 1) {
        if (ry == 1) {
            return 3;
        }
        return 6;
    }
}
return Math.floor(Math.random() * 7);

Ce petit pixel cherche des échantillons autour de lui et essaie de le manger. S'il n'y a pas de pixel, il se déplace dans une direction aléatoire. J'ai hâte de voir ce que les autres peuples proposeront.


Désolé, la dernière fois que j'ai codé javascript, c'était il y a 2 ans.
Loovjo le

2
Math.floornon Math.float!
Jakube

1
@ Jakube Ou (Math.random() * 6) & 6ou (Math.random() * 6) << 0ou (Math.random() * 6) >> 0 (utile pour codegolf).
Ismael Miguel

Tu n'as pas besoin de faire Math.random() * 7? J'ai essayé quelques essais et il semble que votre bot ne va pas en bas à droite. L'IIRC Math.random()est 0 inclusif et 1 exclusif, ce qui signifie qu'il * 6n'est jamais 6.
Destrictor

1
Désolé tout le monde, je suis nul en JavaScript.
Loovjo le

7

Équipe Rouge - Chargeur Rouge Jittery

var direction = 3;
if (getMsg(14314) === ''){
    setMsg('3');
}
if (getMsg(14314) === '3'){
    direction = 6;
    setMsg('6');
}
else if (getMsg(14314) === '4'){
    direction = 5;
    setMsg('5');
}
else if (getMsg(14314) === '5'){
    direction = 4;
    setMsg('4');
}
else if (getMsg(14314) === '6'){
    direction = 3;
    setMsg('3');
}
if(x === 0){
    setMsg('3');
}
else if(x === 127){
    setMsg('5');
}
return direction;

Red Charger ne se déplace que de gauche à droite, dans l'espoir d'exploiter l'incapacité de la Blue Team de se déplacer dans ces directions. Après avoir atteint un mur, il se retourne et charge dans la direction opposée, dans l’espoir de détruire aveuglément les robots sur son passage.

EDIT: Red Charger vient de prendre un gallon de boisson énergisante et ne peut plus arrêter de trembler, il espère pouvoir en tirer parti. Il est trop caféiné pour écouter ses coéquipiers, mais il crie chacun de ses mouvements.


6

Blue team - LazySoldier

try {
    var state = getMsg(38671);
    if(state == null) {
       state = {direction:x==0?1:-1};
    } else {
       state = JSON.parse(state);
    }

    var choice = 0;    

    var escape=function(dx,dy) {
    if(dx==-1) {
       return y>0?4:5;
    } else if (dx==1) {
       return y>0?3:6;
    } else return 0;
    };

    var eat=function(dx,dy) {
       var b={'-1,-1':4, '0,-1':2,'1,-1':3,'-1,1':5,'0,1':1,'1,1':6};
       k=dx+','+dy;
       if(b[k]) {
       return b[k];
       } else return 0;
    };

    for(var i=0;i<eNear.length;i++) {
        var enemy = eNear[i];
        var dx=enemy.x-x;
        var dy=enemy.y-y;
        if(dy==0 && (dx==-1||dx==1)) {
            choice = escape(dx,dy);
            break;
        } else if(dy==-1 || dy==1) {
            choice = eat(dx,dy);
            break;
        }
    }

    if(x==0 || x==127) {
        state.direction=-state.direction;
    }

    if(choice == 0) {
       choice=state.direction==-1?2:1;
    }

    setMsg(JSON.stringify(state));
    return choice;

} catch(e) {
    if(console && console.error) {
        console.error(e);
    }
    return 0;
}

Savez-vous que le message JSON est long de combien d'octets? Seuls les 64 premiers caractères du message peuvent être enregistrés.
PhiNotPi

.. J'ai oublié cette limitation :(
dieter

Je suppose que cela dépend du nombre d’adversaires, car la chaîne json comprend les positions des eminems proches
dieter

Je change le format en ce moment
Dieter

1
Vous devez mettre cela JSON.parsedans un bloc try / catch ou quelque chose comme ça ... ça cause beaucoup trop d'erreurs.
12

6

Blue Team - Mass Killer

var i, j, enemies = [];
var DIRECTIONS = [4, 2, 3, 5, 1, 6];

// initialize 5x5 surroundings
for (i = 0; i < 5; i++) { 
    enemies[i] = [];
    for (j = 0; j < 5; j++) {
        enemies[i][j] = 0;
    }
}

// get amounts of enemies there
for (i = 0; i < eNear.length; i++) {
    var xOff = eNear[i].x - x + 2;
    var yOff = eNear[i].y - y + 2;
    if (xOff >= 0 && xOff <= 4 && yOff >= 0 && yOff <= 4) {
        enemies[yOff][xOff]++;
    }
}

// get maximum amount of direct neighbours, where I can move
var max = 0, index = -1;
// check the triple above
for (i = 0; i < 3; i++) { 
    if (enemies[1][i+1] > max) {
        max = enemies[1][i+1];
        index = i;
    }
}
// check the triple below
for (i = 0; i < 3; i++) { 
    if (enemies[3][i+1] > max) {
        max = enemies[3][i+1];
        index = i + 3;
    }
}

// if there is any reachable enemy, stomp on where the biggest amount of them is 
if (max > 0) {
    return DIRECTIONS[index];
}

// otherwise, if enemy is near (though unreachable), try to move that I am above or below him
var unreachable = [];
unreachable[4] = enemies[0][1] + enemies[2][1]; // NW (north west)
unreachable[3] = enemies[0][3] + enemies[2][3]; // NE
unreachable[5] = enemies[4][1] + enemies[2][1]; // SW
unreachable[6] = enemies[4][3] + enemies[2][3]; // SE
unreachable[2] = enemies[0][2];                 // N
unreachable[1] = enemies[4][2];                 // S

max = 0, index = 0;
for (i = 1; i <= 6; i++) {
    if (unreachable[i] > max) {
        max = unreachable[i];
        index = i;
    }
}

if (max > 0) {
    return index;
}

// if no one is near, let's move randomly
return Math.round(Math.random() * 6);

Je suppose que la tactique est assez simple. Je compte les ennemis directement accessibles par moi (je suppose qu’il y en aura des tonnes :)) et tue le plus gros montant. S'il n'y en a pas, au moins j'essaierai de me protéger en passant au-dessus ou au-dessous du plus grand nombre d'ennemis dans l'espoir de les tuer.

J'ai abandonné la prise en compte des murs, alors je les ignore. C'est quand même assez long.

Je n'ai pas pu tester / exécuter ce code, il y aura donc beaucoup de bugs.


5

Blue Team - Chien de garde

var me = 38403;
var currentOwner = parseInt(getMsg(me));
var deltas = {1:{x:0,y:1},2:{x:0,y:-1},3:{x:1,y:-1},4:{x:-1,y:-1},5:{x:-1,y:1},6:{x:1,y:1}};
var check_danger = function(ennemi){
    for(var i in deltas){
        if(Math.abs(ennemi.x-x-deltas[i].x)<3 && Math.abs(ennemi.y-y-deltas[i].y)<2){
            delete deltas[i];
        }
    }
}
if(eNear.length > 0){
    for(var i in eNear){
        check_danger(eNear[i]);
    }
}
for(var i in deltas){
    if(x+deltas[i].x>126 || x+deltas[i].x<1 || y+deltas[i].y>126 || y+deltas[i].y<1)
        delete deltas[i];
}
if(!isNaN(currentOwner) && getMsg(currentOwner)!='X'){
    var Owner;
    if(tNear.length > 0){
        for(var i in tNear){
            if(tNear[i].id == currentOwner)
                Owner=tNear[i];
        }
    }
    if(Owner){
        var min=32;
        var choosen;
        var keys = Object.keys(deltas);
        if(keys.length>0){
            for(var i in deltas){
                var value = Math.abs(Owner.x-x-deltas[i].x)+Math.abs(Owner.y-y-deltas[i].y);
                if(value<min){
                    min=value;
                    choosen=i;
                }
            }
            if(min>0)
                return parseInt(choosen);
        }
    }
}
if(tNear.length > 0){
    setMsg(""+tNear[0].id);
}
var keys = Object.keys(deltas);
if(keys.length>0){
    if(eNear.length>0){
        var max=0;
        var choosen;
        for(var i in deltas){
            var value = Math.abs(eNear[0].x-x-deltas[i].x)+Math.abs(eNear[0].y-y-deltas[i].y);
            if(value>max){
                max=value;
                choosen=i;
            }
        }
        if(max>5)
            return parseInt(choosen);
    }
}
var deltas = {1:{x:0,y:1},2:{x:0,y:-1},3:{x:1,y:-1},4:{x:-1,y:-1},5:{x:-1,y:1},6:{x:1,y:1}};
if(eNear.length>0){
    var min=32;
    var choosen;
    for(var i in deltas){
        var value = Math.abs(eNear[0].x-x-deltas[i].x)+Math.abs(eNear[0].y-y-deltas[i].y);
        if(value<min){
            min=value;
            choosen=i;
        }
    }
    if(min==0)
        return parseInt(choosen);
}
return parseInt(keys[Math.floor(keys.length*Math.random())]);

Il se déplace de manière aléatoire jusqu'à ce qu'il attrape un allié, s'il le suit. Il essaie d'éviter d'être tué et de tuer s'il le peut. Désolé pour le code horrible, je suis allé tout droit et j'ai oublié de refactoriser. J'essaierai de gagner en lisibilité si j'ai le temps :)


5

Équipe Rouge - Commandant à la recherche

var myself = 29354;

//Adjust eNear to account for any friendly information, using Lazy Slayer format

//Automatically add Lazy Slayer to list, even if out of range
var mytNear = [{
    id: 14732
}].concat(tNear);

var myeNear = [].concat(eNear);
var commandable = [];
var orders = [];

for (var i = 0; i < mytNear.length; i++) {
    try {
        var msg = getMsg(mytNear[i].id);
        var enemies = undefined;
        if (msg.indexOf('"m":') !== -1) {
            commandable.push(mytNear[i]);
        }
        if (msg.indexOf(myself) !== -1) {
            var j = msg.indexOf(myself)+(myself+' ').length;
            for (; j < msg.length; j++) {
                var order = parseInt(msg.substr(j,1));
                if (order) {
                    orders.push(order);
                    break;
                }
            }
        }
        if (msg.indexOf('"e":') !== -1) {
            var enemies = msg.substr(msg.indexOf('"e":')+5).split('"')[0];
            if(!enemies) continue;
            if(enemies.charCodeAt(j) > (32+127)) {
                for (var j = 0; j < enemies.length-1; j+=2) {
                    myeNear.push({
                        x: enemies.charCodeAt(j)-174,
                        y: enemies.charCodeAt(j+1)-174,
                    });
                }
            } else {
                for (var j = 0; j < enemies.length-1; j+=2) {
                    myeNear.push({
                        x: enemies.charCodeAt(j)-32,
                        y: enemies.charCodeAt(j+1)-32,
                    });
                }
            }
        }
    } catch (e) {}
}

var calculateDistance = function(x1, y1, x2, y2) {
    return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
};

var iAmInDanger = function(meX, meY, himX, himY) {
    return (Math.abs(meY - himY) === 1 && Math.abs(meX - himX) <= 1);
};

var iCanKillHim = function(meX, meY, himX, himY) {
    return (Math.abs(meX - himX) === 1 && Math.abs(meY - himY) <= 1);
};

var getMove = function(x, y, tNear, eNear, messages) {
    var minimalDistanceToFriend = 2;
    var chosenMove = null;
    var newDistanceToFriend = null;
    var minimalVerticalDistanceToEnemy = null,
        minimalHorizontalDistanceToEnemy = null;
    var closestFriend = null;
    var closestEnemy = null;
    var possibleVictims = [];
    var possibleMoves = [{
        newX: x,
        newY: y
    }, {
        newX: x + 1,
        newY: y
    }, {
        newX: x - 1,
        newY: y
    }, {
        newX: x + 1,
        newY: y - 1
    }, {
        newX: x - 1,
        newY: y - 1
    }, {
        newX: x - 1,
        newY: y + 1
    }, {
        newX: x + 1,
        newY: y + 1
    }];

    for (i = 0; i < possibleMoves.length; i++) {
        if (possibleMoves[i].newX < 0 || possibleMoves[i].newY < 0 || possibleMoves[i].newX > 127 || possibleMoves[i].newY > 127) {
            possibleMoves[i] = null;
        }
    }

    for (var i = 0; i < eNear.length; i++) {
        if (closestEnemy === null || calculateDistance(x, y, closestEnemy.x, closestEnemy.y) > calculateDistance(x, y, eNear[i].x, eNear[i].y)) {
            closestEnemy = eNear[i];
        }
        if (Math.abs(x - eNear[i].x) <= 2 && Math.abs(y - eNear[i].y) <= 2) {
            possibleVictims.push(eNear[i]);
        }
    }

    for (i = 0; i < tNear.length; i++) {
        if (closestFriend === null || calculateDistance(x, y, closestFriend.x, closestFriend.y) > calculateDistance(x, y, tNear[i].x, tNear[i].y)) {
            closestFriend = tNear[i];
        }
    }

    //If moving to the spot would put me in danger, don't do it
    for (i = 0; i < possibleMoves.length; i++) {
        for (var j = 0; j < possibleVictims.length; j++) {
            if (possibleMoves[i] !== null && iAmInDanger(possibleMoves[i].newX, possibleMoves[i].newY, possibleVictims[j].x, possibleVictims[j].y)) {
                possibleMoves[i] = null;
            }
        }
    }

    //If moving to the spot kills an enemy, do it now
    for (i = 0; i < possibleMoves.length; i++) {
        for (j = 0; j < possibleVictims.length; j++) {
            if (possibleMoves[i] !== null && possibleMoves[i].newX === possibleVictims[j].x && possibleMoves[i].newY === possibleVictims[j].y) {
                messages[2] = 0;
                return i;
            }
        }
    }

    //Enemy in sight
    if (possibleVictims.length > 0) {
        //This can only occur when they are in my blind spot
        if (iAmInDanger(x, y, possibleVictims[0].x, possibleVictims[0].y)) {
            if (closestFriend !== null) {
                for (i = 0; i < possibleMoves.length; i++) {
                    if (possibleMoves[i] !== null) {
                        var distance = calculateDistance(possibleMoves[i].newX, possibleMoves[i].newY, closestFriend.x, closestFriend.y);
                        if (newDistanceToFriend === null || (distance < newDistanceToFriend && distance >= minimalDistanceToFriend)) {
                            newDistanceToFriend = distance;
                            chosenMove = i;
                        }
                    }
                }
                messages[2] = 0;
                setMessage();
                return chosenMove;
            } else {
                var aggressiveMoves = [];
                var randomMoves = [];

                for (i = 0; i < possibleMoves.length; i++) {
                    if (possibleMoves[i] !== null) {
                        if (iCanKillHim(possibleMoves[i].newX, possibleMoves[i].newY, possibleVictims[0].x, possibleVictims[0].y)) {
                            aggressiveMoves.push(i);
                        }
                        randomMoves.push(i);
                    }
                }
                var approachCount = messages[2] || 0;
                if (approachCount < 5 && aggressiveMoves.length > 0) {
                    messages[2] = approachCount + 1;
                    chosenMove = aggressiveMoves[Math.floor(Math.random() * aggressiveMoves.length)];
                    return chosenMove;
                } else {
                    chosenMove = randomMoves[Math.floor(Math.random() * randomMoves.length)];
                    return chosenMove;
                }
            }
        }

    }

    //Move towards closest enemy
    if (closestEnemy != null) {
        for (i = 1; i < possibleMoves.length; i++) {
            if (possibleMoves[i] !== null) {
                var verticalDistance = Math.abs(possibleMoves[i].newY - closestEnemy.y);
                var horizontalDistance = Math.abs(possibleMoves[i].newX - closestEnemy.x);
                if (minimalVerticalDistanceToEnemy === null || verticalDistance <= minimalVerticalDistanceToEnemy) {
                    if (minimalVerticalDistanceToEnemy !== null && verticalDistance === minimalVerticalDistanceToEnemy) {
                        if (minimalHorizontalDistanceToEnemy === null || horizontalDistance <= minimalHorizontalDistanceToEnemy) {
                            minimalHorizontalDistanceToEnemy = horizontalDistance;
                            chosenMove = i;
                        }
                    } else {
                        minimalVerticalDistanceToEnemy = verticalDistance;
                        minimalHorizontalDistanceToEnemy = horizontalDistance;
                        chosenMove = i;
                    }
                }
            }
        }
        messages[2] = 0;
        return chosenMove;
    }

    //Take the order
    for (var i = 0; i < orders.length; i++) {
        var order = orders[i].m || orders[i];
        if (possibleMoves[order]) {
            return orders;
        }
    }

    var seekStatus = messages[3] || 0;
    var seekCount = messages[4] || 0;
    seekStatus = parseInt(seekStatus, 10);
    seekCount = parseInt(seekCount, 10);

    switch (seekStatus) {
        case 0:
            if (x < 16) {
                seekCount = 0;
                if (y > 111) {
                    seekStatus = 4;
                } else {
                    seekStatus = 1;
                }
            } else {
                chosenMove = 2;
            }
            break;
        case 1:
            seekCount++;
            if (y > 111 || seekCount > 31) {
                seekStatus = 2;
            } else {
                if (seekCount % 2 === 0) {
                    chosenMove = 5;
                } else {
                    chosenMove = 6;
                }
            }
            break;
        case 2:
            if (x > 111) {
                seekCount = 0;
                if (y > 111) {
                    seekStatus = 4;
                } else {
                    seekStatus = 3;
                }
            } else {
                chosenMove = 1;
            }
            break;
        case 3:
            seekCount++;
            if (y > 111 || seekCount > 31) {
                seekStatus = 0;
            } else {
                if (seekCount % 2 === 0) {
                    chosenMove = 5;
                } else {
                    chosenMove = 6;
                }
            }
            break;
        case 4:
            seekCount++;
            if (y < 16) {
                if (x > 63) {
                    seekStatus = 0;
                } else {
                    seekStatus = 2;
                }
            } else {
                if (seekCount % 2 === 0) {
                    chosenMove = 3;
                } else {
                    chosenMove = 4;
                }
            }
            break;
    }

    messages[2] = 0;
    messages[3] = seekStatus;
    messages[4] = seekCount;
    return chosenMove;
}

var messageObj = JSON.parse('{'+getMsg(myself)+'}');
if (!messageObj.$) {
    messageObj = {$:0};
}
var approachCount = (messageObj.$ & 7);
var seekStatus = ((messageObj.$ >> 3) & 7);
var seekCount = ((messageObj.$ >> 6));
var messages = [x, y, approachCount, seekStatus, seekCount];
var myMove = getMove(x, y, mytNear, myeNear, messages);
var msg = '"$":'+(messages[2] + (messages[3]<<3) + (messages[4]<<6)+',"m":'+myMove);
orders.length = 0;

//Issue commands to my allies
for (var i = 0; i < commandable.length; i++) {
    var ally = commandable[i];
    var command = getMove(ally.x, ally.y, tNear, myeNear, messages);
    var cmdStr = ',"'+ally.id+'":{"m":"'+command+'","a":1,"id":'+myself+'}'
    if (msg.length + cmdStr.length < 64) {
        msg += cmdStr;
    }
}

if (msg.length+9 < 64) {
    //Add my list of enemies
    var enemies = "";
    for(var i = 0; i < myeNear; i++) {
        if (msg.length+enemies.length+9 > 64) {
            break;
        }
        enemies+=String.fromCharCode(eNear[i].x+174)+String.fromCharCode(eNear[i].y+174);
    }
    msg += ',"e":"'+enemies+'"';
}

setMsg(msg);
return myMove;

Celui-ci est une copie du SeekerBot de Minos avec quelques modifications.

  • Mémoire interne compressée pour une meilleure distribution des messages "$":[seekmode]

  • Lit les positions ennemies des alliés en utilisant le format JSON de Lazy Slayer "e":"[positions]"; accepte [positions]compensé par les deux 32et174

  • Affiche les positions ennemies au format JSON de Lazy Slayer, "e":"[positions]"compensées par174

  • Rapports derniers mouvements avec "m":[move]pour indiquer que ce bot peut être commandé

  • Émet des commandes à d'autres robots en utilisant "[ally_id]":{"m":[move],"a":1,"id":29354}. La commande utilise le même algorithme de chercheur, sauf à l'emplacement de l'allié. Si d'autres robots écoutent ces ordres, ils doivent se regrouper et chasser dans un groupe. Ordres donnés seulement si le message de l'allié comprend"m":

  • Suit les commandes d’autres robots, telles que: "29354":[move]ou "29354":{"m":[move]. Les commandes ne sont suivies que lorsqu'il n'y a pas d'ennemis à proximité et qu'aucun autre allié ne les rapporte


Je recommande incrémenter les coordonnées de 174 au lieu de 32. Certains messages que Lazy Slayer envoyais étaient comme: ""a":0,"o":[122,70],"m":0,"e":"f"". Vous pouvez nous rejoindre dans le chat si vous voulez aussi.
TheNumberOne

Hélas, je n'ai pas le temps. Je reviendrai plus tard ce soir, mais ça va être ça. J'ai mis à jour la publication pour utiliser le codage 174, à la fois pour la publication et l'analyse.
Wasmoo

5

Équipe Rouge - BouncerBot

function getDir(diff){
  return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
}
function randInt(max){
  return Math.ceil(Math.random() * max);
}
var me = 29750;
var moves = [
  [4,3,3],
  [2,0,1],
  [5,5,6]
]; // Directions: -1 = up/left, 1 = down/right, 0 = none
if(x === 0){
  moves[0] = [3,3,3];
  moves[2] = [6,6,6];
} else if(x == 127){
  moves[0] = [4,4,4];
  moves[2] = [5,5,5];
}
for(var i in eNear){
  var xDiff = eNear[i].x - x,
      yDiff = eNear[i].y - y;
  if(xDiff >= -1 && xDiff <= 1 && yDiff >= -1 && yDiff <= 1){
    // If the enemy is directly adjacent, attack
    setMsg('');
    return moves[yDiff + 1][xDiff + 1];
  }
}
if(eNear.length > 0){
  var xDiff = eNear[0].x - x,
      yDiff = eNear[0].y - y;
  // If it can't attack, move toward the enemy.
  if(Math.abs(yDiff) == 2){
    if(xDiff >= -2 && xDiff <= 0) return 1;
    else if(xDiff == 2 || xDiff === 1) return 2;
  }
  return moves[getDir(yDiff) + 1][getDir(xDiff) + 1];
}
var msg = getMsg(me) || '',
    newDir = parseInt(msg);
if(msg === ''){
  newDir = randInt(4) + 2;
}
var isEndgame = move > 512;
     if(x === 0 || (isEndgame && x < 11)) newDir = (msg == 4) ? 3 : 6;
else if(x == 127 || (isEndgame && x > 116)) newDir = (msg == 3) ? 4 : 5;
else if((!isEndgame && y < 11) || y === 0) newDir = (msg == 4) ? 5 : 6;
else if((!isEndgame && y > 116) || y == 127) newDir = (msg == 5) ? 4 : 3;
if(newDir != msg) setMsg(newDir.toString());
return newDir;

Mon bot rebondit de mur en mur (pas exactement, il couvre donc un terrain différent) à la recherche d'ennemis. S'il en a un dans son rayon d'action, il attaque, les traîne vers un mur et tente de les éliminer (pensez au videur dans un club).


5

Équipe rouge - SideKick

var possibleMoves = [
      {newX: x, newY: y, value: 1},
      {newX: x, newY: y + 1, value: 1},
      {newX: x, newY: y - 1, value: 1},
      {newX: x + 1, newY: y - 1, value: 1},
      {newX: x - 1, newY: y - 1, value: 1},
      {newX: x - 1, newY: y + 1, value: 1},
      {newX: x + 1, newY: y + 1, value: 1}
];

var isDeadly = function(myX, myY, eX, eY) {
      return (Math.abs(myY - eY) === 1 && Math.abs(myX - eX) <= 1);
}

//stay near helpful friends!
if (tNear.length > 0) {
      for (var i = 0; i < tNear.length; i++) {
      if (Math.abs(tNear[i].x - x) > 2) {
            if (tNear[i].x > x) {
                  possibleMoves[3].value = possibleMoves[3].value + 5;
                  possibleMoves[1].value = possibleMoves[1].value + 5;
                  possibleMoves[6].value = possibleMoves[6].value + 5;
            } else {
                  possibleMoves[4].value = possibleMoves[4].value + 5;
                  possibleMoves[2].value = possibleMoves[2].value + 5;
                  possibleMoves[5].value = possibleMoves[5].value + 5;
            }
      }
      if (Math.abs(tNear[i].y - y) > 2) {
            if (tNear[i].y > y) {
                  possibleMoves[5].value = possibleMoves[5].value + 5;
                  possibleMoves[6].value = possibleMoves[6].value + 5;
            } else {
                  possibleMoves[4].value = possibleMoves[4].value + 5;
                  possibleMoves[3].value = possibleMoves[3].value + 5;
            }
      }
      }
}
//chase those enemies!
if (eNear.length > 0) {
      for (var i = 0; i < eNear.length; i++) {
      if (Math.abs(eNear[i].x - x) > 2) {
            if (eNear[i].x > x) {
                  possibleMoves[3].value = possibleMoves[3].value + 5;
                  possibleMoves[1].value = possibleMoves[1].value + 5;
                  possibleMoves[6].value = possibleMoves[6].value + 5;
            } else {
                  possibleMoves[4].value = possibleMoves[4].value + 5;
                  possibleMoves[2].value = possibleMoves[2].value + 5;
                  possibleMoves[5].value = possibleMoves[5].value + 5;
            }
      }
      if (Math.abs(eNear[i].y - y) > 2) {
            if (eNear[i].y > y) {
                  possibleMoves[5].value = possibleMoves[5].value + 5;
                  possibleMoves[6].value = possibleMoves[6].value + 5;
            } else {
                  possibleMoves[4].value = possibleMoves[4].value + 5;
                  possibleMoves[3].value = possibleMoves[3].value + 5;
            }
      }
      }
}

//walls
if (x === 127){
       possibleMoves[3] = null;
       possibleMoves[1] = null;
       possibleMoves[6] = null;
}
if (x === 0){
       possibleMoves[4] = null;
       possibleMoves[2] = null;
       possibleMoves[5] = null;
}
if (y === 0){
       possibleMoves[3] = null;
       possibleMoves[4] = null;
}
if (y === 127){
       possibleMoves[5] = null;
       possibleMoves[6] = null;
}

//deadly enemies
for (var i = 0; i < eNear.length; i++) {
      for (var j = 0; j < possibleMoves.length; j++) {
            if (possibleMoves[j] !== null && isDeadly(possibleMoves[j].newX, possibleMoves[j].newY, eNear[i].x, eNear[i].y)) {
                  possibleMoves[j] = null;
            }
      }
}

var bestMoves = [];
for (var i = 0; i < possibleMoves.length; i++)
{
      if (possibleMoves[i] !== null) {
            if (bestMoves.length === 0 || possibleMoves[i].value > possibleMoves[bestMoves[0]].value) {
                  bestMoves = [i];
            }
            else if (possibleMoves[i].value === possibleMoves[bestMoves[0]].value) {
                  bestMoves.push(i);
            }
      }
}
var returnValue = bestMoves[Math.floor(Math.random()*(bestMoves.length))];

return returnValue;

Aime suivre ses coéquipiers, heureusement qu'il y en a beaucoup!


Il est drôle de noter que lorsque ce dernier s’associe au bot de Wasmoo, il peut parfois vaincre le duo bleu.
Nit

1
@Nit je ne l'ai pas vu; mais je suppose que le mien devient une distraction pour Wasmoo de les tuer? Si seulement je pouvais ajouter quelque chose maintenant; J'essayais de prévoir plusieurs tours d'avance et de voir quel genre de suicide - la tactique pourrait marcher contre le duo.
DoubleDouble

5

Blue Team - aimant indécis

var Mul = 4;
var Mu = 2;
var Mur = 3;
var Mdl = 5;
var Md = 1;
var Mdr = 6;
var Ms = 0;
var M = [Ms,Md,Mu,Mur,Mul,Mdl,Mdr];
var C =  [Mul,Mur,Mdl,Mdr];
var Mc = [{x:0,y:0},{x:0,y:1},{x:0,y:-1},{x:1,y:-1},{x:-1,y:-1},{x:-1,y:1},{x:1,y:1}];
/* If one or more enemies */
var nearEnemies = 0;
for(var i=0;i<eNear.length;i++){
    if(Math.abs(eNear[i].x-x)+Math.abs(eNear[i].y-y)<5){
        nearEnemies++;
    }
}
if(nearEnemies >0){
    //First check whether I can beat the enemy
    for(var i=0;i<eNear.length;i++){
        for(var j=0;j<7;j++){
            if(x+Mc[j].x == eNear[i].x && y+Mc[j].y == eNear[i].y){
                return j;
            }
        }
    }

    // Else advanced tactics
    function inRangeOfNEnemies(mx,my,eNear){
        var n=0;
        for(var i=0;i<eNear.length;i++){
            if( Math.abs(my-eNear[i].y)<=1 && Math.abs(mx-eNear[i].x)==1 ){
                n=n+1;
            }

        }
        return n;
    }

    //check all all possible moves:
    var moveDangerousness = new Array(7);;
    for(var i=0;i<7;i++)moveDangerousness[i]=1/(Math.abs(x+Mc[i].x-64)+Math.abs(y+Mc[i].y-64)+1);
    //calculate dangerouseness
    for(var i=0;i<7;i++){
        moveDangerousness[i] += inRangeOfNEnemies(x+Mc[i].x,y+Mc[i].y,eNear);
    }
    //mind walls
    for(var i=0;i<7;i++){
        if(x+Mc[i].x<0 ||  x+Mc[i].x>127 || y+Mc[i].y<0 ||  y+Mc[i].y>127 ){
            moveDangerousness[i] = 9999;
        }   
    }

    var leastDangerous = moveDangerousness.indexOf(Math.min.apply(Math,moveDangerousness));
    return leastDangerous;
} else if (eNear.length>3){ //run away from enemies
    var xmean = 0;
    var ymean = 0;
    for(var i=0;i<eNear.length;i++){
        xmean += eNear[i].x*1.0/eNear.length;
        ymean += eNear[i].y*1.0/eNear.length;       
    }
    var dx = x-xmean;
    var dy = y-ymean;
    if(dx >0){
        if(dy>0){
            return Mdr;
        } else {
            return Mur;
        }
    } else {
        if(dy>0){
            return Mdl;
        } else {
            return Mul;
        }
    }

} else {//* if there are no enemies *//
    //walk pattern until you find friend, then folloow friend
    var dx = 999; var dy = 999;
    if(tNear.length>0){
        for(var i=0;i<tNear.length;i++){
            if(Math.abs(dx)+Math.abs(dy) > Math.abs(tNear[i].x-x)+Math.abs(tNear[i].y-y)){
                dx = tNear[i].x-x;
                dy = tNear[i].y-y;
            }
        }
    } else {
        dx = 64-x+10*(Math.random()-0.5);
        dy = 64-y+10*(Math.random()-0.5);
    }

    if(dx >0){
        if(dy>0){
            return Mdr;
        } else {
            return Mur;
        }
    } else {
        if(dy>0){
            return Mdl;
        } else {
            return Mul;
        }
    }
}

Il a plusieurs stratégies: s'il peut vaincre un ennemi immédiatement, il le fera, et il s'éloignera des groupes d'ennemis s'il est suffisamment éloigné, sinon il se battra. Autre que cela, il est juste à la recherche de membres de l'équipe et d'essayer de les suivre.


4

Blue Team - Récupération [38953]

var me = 38953;
var msg = getMsg(me);
var register = msg ? JSON.parse(msg) : {};
var prevDanger = 0;
var danger;

var eScope = eNear;
var myX = x;
var myY = y;
var put = setMsg;
var get = getMsg;

function kill(){
  var move = -1;
  if(!eScope){return -1;}

  eScope.forEach(function(e){
    if(move > -1){return move;}

    var xDist = Math.abs(e.x-myX);
    var yDist = Math.abs(e.y-myY);

    if(xDist < 2 && yDist < 2){
      if(e.x == myX){
        if(e.y == myY-1){move = 2;}
        else if(e.y == myY+1){move = 1;}
      }
      else if(e.x == myX-1){
        if(e.y == myY-1){move = 4;}
        else if(e.y == myY+1){move = 5;}
      }
      else if(e.x == myX+1){
        if(e.y == myY-1){move = 3;}
        else if(e.y == myY+1){move = 6;}
      }
    }
  });

  return move;
}

function live(){
  var move = -1;
  if(!eScope){return -1;}
  var topHalf = (myY <= 64);

  eScope.forEach(function(e){
    if(move > 0){return move;} //0 on purpose; we might find a better escape

    var xDist = Math.abs(e.x-myX);
    var yDist = Math.abs(e.y-myY);

    if(xDist + yDist < 5){move = 0;}  //uh oh!  Stand still!

    if(e.y == myY){
      if(e.x == myX-1){move = (topHalf ? 5 : 4);}
      else if(e.x == myX+1){move = (topHalf ? 6 : 3);}
    }
  });

  return move;
}

function evalDanger(){
  danger = 0;

  if(register){prevDanger = register.d;}

  eScope.forEach(function(e){
    var xDist = Math.abs(e.x-myX);
    var yDist = Math.abs(e.y-myY);
    danger += ((1/yDist) * (1/xDist));
  });

  register.d = danger;
  put(JSON.stringify(register));
  return danger;
}

function distract(){
  //run to the edge if safe, to the middle if not
  var safe = (danger <= prevDanger && danger < .01);

  var topHalf = myY <= 64;
  var leftSide = myX <= 64;

  //lazy init to 'explore' mode
  if(!register.e){register.e = 1;}

  //lazy init to whatever corner we're in
  if(!register.f){
    register.f = topHalf ? leftSide ? 4 : 3 : leftSide ? 5 : 6;
  }

  //turn 'explore' on (1) or off (2);
  //if 'off' but hit 'home base', seek a corner
  if(register.e == 2 && ((myY > 54 && myY < 74) || (myX > 54 && myX < 74))){
    register.e = 1
    register.f = Math.floor(Math.random()*4)+3;
  }
  //if on the outskirts, go back to base
  if(myY < 10 || myY > 115 || myX < 10 || myX > 115){register.e = 2;}

  put(JSON.stringify(register));

  if(topHalf){
    if(leftSide){
      if(!safe || register.e == 2){return 6;}
    }
    else{
      if(!safe || register.e == 2){return 5;}
    }
  }
  else {
    if(leftSide){
      if(!safe || register.e == 2){return 3;}
    }
    else{
      if(!safe || register.e == 2){return 4;}
    }
  }
  return register.f;
}

evalDanger();
register.x = myX;
register.y = myY;

var whee = kill();
if(whee > -1){
    return whee;
}

whee = live();
if(whee > -1){
    return whee;
}

whee = distract();
return whee;

[modifications: il s'avère que cela fonctionne BEAUCOUP mieux lorsque j'utilise mon identifiant actuel et non -1!]

Un petit robot stupide qui court autour du tableau, faisant de son mieux pour attirer l'attention et attirer les poursuivants, puis se précipiter vers le milieu où (espérons-le) il trouvera quelqu'un pour l'aider, ou il bloquera simplement le poursuivant et l'arrêtera de la chasse.

Cela ne semble pas avoir un impact énorme sur le score total en raison de la puissance des équipes de Blue, mais au moins, je n’ai pas aggravé la situation!

Criez dans les 8 prochaines heures si vous voulez que je rajoute quelque chose d’utile à mon message.


Le milieu n'est pas le meilleur endroit pour attirer l'attention. de nombreux autres robots semblent entourer les bords lorsqu'ils cherchent des ennemis à combattre. Peut-être que votre bot devrait encercler le milieu?
theonlygusti

Il est plus facile de s’évader au milieu que dans les coins, mais si vous dites que je ne trouverais peut-être pas de coéquipiers au milieu ... eh bien, vous avez raison; Ma principale cause de décès en ce moment est que le rouge obtient un allié avant moi. Pour le prochain KotH, je suis prêt à améliorer considérablement la capacité d'appeler d'autres robots pour obtenir de l'aide lorsque j'ai trouvé une cible!
Hylianpuffball

Je travaille sur un bot appelé beacon; Il contient les positions de chaque ennemi et membre de l’équipe sur le terrain, et peut ensuite être utilisé par d’autres robots pour suivre et tuer lesdits ennemis, ou pour rester en présence de ses coéquipiers.
theonlygusti

4

Blue Team - PatrolBot

var directionMap = {'0,0':0, '0,1':1, '1,1':6, '1,0':null, '1,-1':3, '0,-1':2, '-1,-1':4, '-1,0':null, '-1,1':5},
    direction = parseInt((getMsg(38951) || getMsg(-1) || '').slice(0, 1));

if (typeof direction !== 'number' || isNaN(direction)) direction = 0;

if (!tNear.length && !eNear.length) {
    if (!isDirection(direction) || isNearWall(12, x, y)) {
        direction = moveTowardsCoords(64, 64, x, y, directionMap, eNear);
    } else {
        direction = direction;
    }
} else if (eNear.length) {
    if (canKill(x, y, eNear, directionMap)) {
        direction = kill(x, y, eNear, directionMap);
    } else if (isNearEnemy(x, y, eNear)) {
        direction = moveToBetterPosition(x, y, eNear, directionMap);
    } else if (tNear.length + 1 >= eNear.length) {
        direction = moveTowardsEnemy(eNear, x, y, directionMap);
    } else {
        if (tNear.length) {
            direction = moveTowardsTeam(tNear, x, y, directionMap);
        } else {
            direction = moveAwayFromEnemy(eNear, x, y);
        }
    }
} else if (tNear.length && Math.random() > 0.8) {
    direction = moveTowardsTeam(tNear, x, y, directionMap);
}

setMsg((direction || 0).toString());
return direction;

function find(arr, func) {
    for (var i = 0; i < arr.length; i++) {
        if (func(arr[i])) {
            return arr[i];
        }
    }
}

function invert(obj) {
    var result = {},
        key;

    for (key in obj) {
        if (obj.hasOwnProperty(key)) {
            result[obj[key]] = key;
        }
    }

    return result;
}

function isDirection(direction) {
    return direction >= 1 && direction <= 6;
}

function isNearWall(margin, x, y) {
    return x < margin || x > (127 - margin) || y < margin || y > (127 - margin);
}

function getDistance(x1, y1, x2, y2) {
    var xd, yd;

    xd = x2 - x1;
    xd = xd * xd;

    yd = y2 - y1;
    yd = yd * yd;

    return Math.sqrt(xd + yd);
}

function getCoordDiff(x1, y1, x2, y2) {
    return [x1 - x2, y1 - y2];
}

function identifyClosest(arr, x, y) {
    var lowest = 128;

    arr = arr.map(function(i) {
        i.distance = getDistance(x, y, i.x, i.y);
        return i;
    });

    arr.forEach(function(i) {
        if (i.distance < lowest) {
            lowest = i.distance;
        }
    });

    return find(arr, function(i) {
        return i.distance === lowest;
    });
}

function identifyClosestTeam(tNear, x, y) {
    return identifyClosest(tNear, x, y);
}

function identifyClosestEnemy(eNear, x, y) {
    return identifyClosest(eNear, x, y);
}

function kill(x, y, eNear, directionMap) {
    var enemy = identifyClosestEnemy(eNear, x, y);
    return enemy ? directionMap[getCoordDiff(enemy.x, enemy.y, x, y).toString()] : 0;
}

function canKill(x, y, eNear, directionMap) {
    return !!kill(x, y, eNear, directionMap);
}

function enemyCanKill(id, x, y, eNear) {
    var arr = ['1,0', '1,1', '1,-1', '-1,0', '-1,-1', '-1,1'],
        enemy = find(eNear, function(i) {
            return i.id === id;
        });

    if (!enemy) {
        return false;
    }

    return arr.indexOf(getCoordDiff(x, y, enemy.x, enemy.y).toString()) !== -1;
}

function isNearEnemy(x, y, eNear) {
    var enemy = identifyClosestEnemy(eNear, x, y);

    if (!enemy) {
        return 0;
    }

    return Math.max.apply(null, getCoordDiff(x, y, enemy.x, enemy.y).map(function(i){
        return Math.abs(i);
    })) <= 2;
}

function isIntoWall(dx, dy) {
    return dx > 127 || dx < 0 || dy > 127 || dy < 0;
}

/**
 * Picks a random direction heading towards {dx, dy}
 */
function moveTowardsCoords(destX, destY, oldX, oldY, directionMap, eNear) {
    return changeDirection(function(newX, newY) {
        return getDistance(oldX, oldY, destX, destY) - getDistance(newX, newY, destX, destY);
    }, oldX, oldY, eNear, directionMap);
}


function changeDirection (scoringFunction, x, y, eNear, directionMap) {
    var highest = 0,
        validDirections = (function() {
            var result = {};
            for (var key in directionMap) {
                if (directionMap.hasOwnProperty(key) && directionMap[key] !== null) {
                    result[key] = directionMap[key];
                }
            }
            return result;
        })(),
        coords = Object.keys(validDirections).map(function(i) {
            var result = {
                    vector: i,
                    score: 0
                },
                xy = i.split(',').map(function(term, i) {
                    return parseInt(term) + (i === 0 ? x : y);
                });

            result.x = xy[0];
            result.y = xy[1];

            result.score = scoringFunction(result.x, result.y, eNear, directionMap);

            if (result.score > highest) {
                highest = result.score;
            }

            return result;
        }),
        arr = coords.filter(function(i) {
            return i.score === highest;
        });

    var num = Math.floor(Math.random() * arr.length);

    return validDirections[arr[num].vector];
}

function moveTowards(id, x, y, tNear, eNear, directionMap) {
    var target = find([].concat(tNear, eNear), function(i) {
        return i.id === id;
    });

    if (target) {
        return moveTowardsCoords(target.x, target.y, x, y, directionMap, eNear);
    } else {
        return 0;
    }
}

function moveTowardsEnemy(eNear, x, y, directionMap) {
    var enemy = identifyClosestEnemy(eNear, x, y);

    return enemy ? moveTowards(enemy.id, x, y, [], eNear, directionMap) : 0;
}

function moveTowardsTeam(tNear, x, y, directionMap) {
    var team = identifyClosestTeam(tNear, x, y);

    return team ? moveTowards(team.id, x, y, tNear, [], directionMap) : 0;
}

function moveAwayFromEnemy(eNear, x, y) {
    var oppositeMap = {
        0: 0,
        1: 2,
        2: 1,
        3: 5,
        4: 6,
        5: 3,
        6: 4
    };
    return oppositeMap[moveTowardsEnemy(eNear, x, y, directionMap)];
}

/**
 * Gives points to each move based on three metrics:
 * 
 * 2) will not cause us to be killed next turn
 * 1) will let us kill next turn
 * 
 * Then randomly picks from the highest scoring moves
 */
function moveToBetterPosition(x, y, eNear, directionMap) {
    return changeDirection(function(x, y, eNear, directionMap) {
        var score = 0;

        if (canKill(x, y, eNear, directionMap)) {
            score += 1;
        }

        if (!eNear.some(function(e) {
                return enemyCanKill(e.id, x, y, eNear);
            })) {
            score += 2;
        }

        if (isIntoWall(x, y)) {
            score = 0;
        }

        return score;
    }, x, y, eNear, directionMap);
}

Le code est en quelque sorte auto-documenté. Ce qui pourrait être fait pour améliorer PatrolBot

  • Refactor - Déplacez tout dans IIFE, utilisez les variables de fermeture au lieu de les dépasser vingt fois.
  • Ajouter if (canBeKilled() || isInWall()) { moveToBetterPosition() } juste avant le retour.
  • Nettoyez le mauvais comportement lorsque vous suivez un membre de l'équipe près d'un mur.
  • Évitez d'atterrir sur les membres de l'équipe.
  • Éloignez-vous de l'ennemi s'il est continuellement engagé pendant 200 tours

C'est un très bon bot. Bon travail. Voici les résultats d'une série de 100 lancers
PhiNotPi

2

BLUE TEAM - 1 Point Awesome

//  1PointAwesome by Grant Davis

var myid=38941; //My ID for getMsg()

var result=0;
var leeway=1; //How close to follow enemy
var gForce=3; //How strongly gravity effects x/y
var futureDanger=true;
//Modifier Random Generation
var newX=Math.floor(Math.random()*3-1);
var newY=Math.floor(Math.random()*3-1);
var random10=Math.floor(Math.random()*2);

var dangerArray=[[false,false,false],[false,false,false],[false,false,false]];
var gravityX,gravityY,antiGravityX,antiGravityY;

//Sets defaults: gravity center
if(move==1){setMsg("64,64");}

//Change gravity when you have reached within 5 of gravity
if(eNear.length==0){
 if(Math.floor(Math.random()*2)==0){
  if(parseInt(getMsg(myid).split(",")[0])-x<5&&parseInt(getMsg(myid).split(",")[0])-x>-5){setMsg(Math.floor(Math.random()*32)+","+getMsg(myid).split(",")[1]);}
  if(parseInt(getMsg(myid).split(",")[1])-y<5&&parseInt(getMsg(myid).split(",")[1])-y>-5){setMsg(getMsg(myid).split(",")[0]+","+Math.floor(Math.random()*32));}
 }else{
  if(parseInt(getMsg(myid).split(",")[0])-x<5&&parseInt(getMsg(myid).split(",")[0])-x>-5){setMsg(Math.floor(Math.random()*32+96)+","+getMsg(myid).split(",")[1]);}
  if(parseInt(getMsg(myid).split(",")[1])-y<5&&parseInt(getMsg(myid).split(",")[1])-y>-5){setMsg(getMsg(myid).split(",")[0]+","+Math.floor(Math.random()*32+96));}
 }
}

//Pulls gravity from getMsg() and converts it into variables readable by the program
if(x<parseInt(getMsg(myid).split(",")[0])+Math.floor(Math.random()*30-15)){gravityX=1;antiGravityX=-1;}else{gravityX=-1;antiGravityX=1;}
if(y<parseInt(getMsg(myid).split(",")[1])+Math.floor(Math.random()*30-15)){gravityY=-1;antiGravityY=1;}else{gravityY=1;antiGravityY=-1;}

//Modifier Random Generation, Gravity bias.
if(Math.floor(Math.random()*gForce)!=0||x<31&&eNear.length==0||x>95&&eNear.length==0){newX=gravityX;}
if(Math.floor(Math.random()*gForce)!=0||y<31&&eNear.length==0||y>95&&eNear.length==0){newY=gravityY;}


//Avoid edges modifier:
//Sets gravity to 64,64 when within 32 of an edge

if(y<31&&eNear.length==0||y>95&&eNear.length==0){setMsg(getMsg(myid).split(",")[0]+",64");}
if(x<31&&eNear.length==0||x>95&&eNear.length==0){setMsg("64,"+getMsg(myid).split(",")[1]);}

//Targeting Modifier:
//Does not modify if outnumbered
//Tries to attack from above or below
//If enemy escapes: look where the enemy was last at
//Reset gravity if all targets

if(eNear.length<=tNear.length+1&&eNear.length!=0){

setMsg(eNear[0]["x"]+","+eNear[0]["y"]);
if(eNear[0]["x"]>x){newX=1;}else if(eNear[0]["x"]<x){newX=-1;}else{newX=0;}
if(eNear[0]["y"]>y+leeway){newY=-1;}else if(eNear[0]["y"]<y-leeway){newY=1;}
}



//Anti loop Modifier: Removed due to minor strategy flaw


//If I can get above or below a pixel, do it 


//If I can kill an enemy pixel, kill it
for(var ep=0;eNear.length>ep;ep+=1){

 if(eNear[ep]["x"]==x&&eNear[ep]["y"]-y==1){newY=-1;newX=0;}
 else if(eNear[ep]["x"]==x&&eNear[ep]["y"]-y==-1){newY=1;newX=0;}
 else if(eNear[ep]["x"]-x==-1){
  if(eNear[ep]["y"]-y==1){newX=-1;newY=-1;}
  else if(eNear[ep]["y"]-y==-1){newX=-1;newY=1;}
 }
 else if(eNear[ep]["x"]-x==1){
  if(eNear[ep]["y"]-y==1){newX=1;newY=-1;}
  else if(eNear[ep]["y"]-y==-1){newX=1;newY=1;}
 }
}

//Not allowed to move off screen.
if(x==0){for(var i=0;i<=2;i+=1){dangerArray[0][i]==true;}}
if(x==127){for(var i=0;i<=2;i+=1){dangerArray[2][i]==true;}}
if(y==0){for(var i=0;i<=2;i+=1){dangerArray[i][0]==true;}}
if(y==127){for(var i=0;i<=2;i+=1){dangerArray[i][2]==true;}}

var originalNewX=newX;
var originalNewY=newY;






//Double checks movement made by previous code, and then turns it into a number that Pixel Team Battlebots can read
for(var antiloop=0;futureDanger&&antiloop<20;antiloop+=1){

 futureDanger=false;


 //When bot tries to move left or right, it will move diagonal.
 if(newX!=0&&newY==0){
  newY=Math.floor(Math.random()*2);
  if(newY==0){newY=-1;}
 }


 if(eNear.length>0){ //Protocol Paranoid: When pixel attempts to move into dangerous square, The pixel will move into a different square, and recheck danger.




  for(var ep=0;ep<eNear.length;ep+=1){ //Checks for the danger level of the square pixel attempts to move in.

   if(Math.abs(eNear[ep]["x"]-(x+newX))==1 && eNear[ep]["y"]-(y-newY)<=1 && eNear[ep]["y"]-(y-newY)>=-1){
    futureDanger=true;

    dangerArray[newX+1][Math.abs(newY-1)]=true;
    if(dangerArray[1][1]==false){newX=0;newY=0;}//When attempt to move into dangerous square, do nothing
    else if(dangerArray[gravityX+1][gravityY+1]==false){newX=gravityX;newY=gravityY;}
    else if(dangerArray[antiGravityX+1][gravityY+1]==false){newX=antiGravityX;newY=gravityY;random10=1;}
    else if(dangerArray[gravityX+1][antiGravityY+1]==false){newX=gravityX;newY=antiGravityY;random10=0;}

    else if(dangerArray[antiGravityX+1][antiGravityY+1]==false){newX=antiGravityX;newY=antiGravityY;}
    else if(dangerArray[1][gravityY+1]==false){newX=0;newY=gravityY;}
    else if(dangerArray[1][antiGravityY+1]==false){newX=0;newY=antiGravityY;}
    else{newX=originalX;newY=originalY;}
   }
  }
 }else//End of Protocol Paranoid

 if(antiloop==18){newX=originalNewX;NewY=originalNewY;}

}//Big for end


if(newY==1){result=2;}else if(newY==-1){result=1;}

if(newX==1){if(result==2){result=3;}else if(result==1){result=6;}}else if(newX==-1){if(result==2){result=4;}else if(result==1){result=5;}}



return result;

Les priorités du pixel:

  • Ne jamais se déplacer dans des espaces dangereux (les espaces hors limites sont considérés comme dangereux)
  • Tuer si possible
  • Déplacez-vous vers Enemy (le premier dans eNear) tant que vous n'êtes pas en infériorité numérique
  • S'éloigner des bords
  • Aller au dernier emplacement connu des ennemis
  • Aller à l'endroit où la gravité est située

La gravité est réglée sur 64,64 au coup 1

La gravité est réglée sur l'emplacement de l'ennemi le plus proche (pour guider le pixel vers l'emplacement du dernier ennemi, si l'ennemi s'échappe)

La gravité change de manière aléatoire lorsque le pixel a atteint le centre de gravité ou près du bord.


2

Rouge - LoyalFollower [15080]

var dangerValues = {
    killEnemy:      -110,
    killMe:          160,
    nearEnemy:       -20,
    killPair:       -200,
    friendIsThere:    30,
    outside:         999,
    nearWall:         10,
    wayToMinos:       -2,
    wayToFriend:      -1,
    wayToEnemy:       -4,
    wayToManyEnemies:  3
};

var moves = [
    {newX: x, newY: y, danger: 0},
    {newX: x + 1, newY: y, danger: 0},
    {newX: x - 1, newY: y, danger: 0},
    {newX: x + 1, newY: y - 1, danger: 0},
    {newX: x - 1, newY: y - 1, danger: 0},
    {newX: x - 1, newY: y + 1, danger: 0},
    {newX: x + 1, newY: y + 1, danger: 0}
];
var closestEnemy = null;
var closestFriend = null;

var distance = function(x1, y1, x2, y2) {
    return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
};

var meKillable = function(meX, meY, himX, himY) {
    return (Math.abs(meY - himY) === 1 && Math.abs(meX - himX) <= 1);
};

var enemyKillable = function(meX, meY, himX, himY) {
    return (Math.abs(meX - himX) === 1 && Math.abs(meY - himY) <= 1);
};

for (i = 0; i < moves.length; i++) {
    if (moves[i].newX < 0 || moves[i].newY < 0 || moves[i].newX > 127 || moves[i].newY > 127) {
        moves[i].danger = dangerValues.outside;
    }
    if (moves[i].newX === 0 || moves[i].newX === 127 || moves[i].newY === 0 || moves[i].newY === 127) {
        moves[i].danger += dangerValues.nearWall;
    }
    for (var j = 0; j < eNear.length; j++) {
        if (closestEnemy === null || distance(x, y, closestEnemy.x, closestEnemy.y) > distance(x, y, eNear[j].x, eNear[j].y)) {
            closestEnemy = eNear[i];
        }

        if (moves[i].newX === eNear[j].x && moves[i].newY === eNear[j].y) {
            if (eNear[j].id === 21487 || eNear[j].id === 2867) {
                moves[i].danger += dangerValues.killPair;
            } else {            
                moves[i].danger += dangerValues.killEnemy;
            }
        }
        if (meKillable(moves[i].newX, moves[i].newY, eNear[j].x, eNear[j].y)) {
            moves[i].danger += dangerValues.killMe;
        }
        if (enemyKillable(moves[i].newX, moves[i].newY, eNear[j].x, eNear[j].y)) {
            moves[i].danger += dangerValues.nearEnemy;
        }
    }
    for (var j = 0; j < tNear.length; j++) {
        if (closestFriend === null || distance(x, y, closestFriend.x, closestFriend.y) > distance(x, y, tNear[j].x, tNear[j].y)) {
            closestFriend = tNear[i];
        }
        if (moves[i].newX === tNear[j].x && moves[i].newY === tNear[j].y) {
            moves[i].danger += dangerValues.friendIsThere;
        }
    }
}

var bestDistanceToMinos = 200;
var minos = 38926;
var minosMsg = getMsg(minos);
var manyEnemies = eNear.length > tNear.length;
if (minosMsg !== '' && minosMsg !== undefined) {
    minosMsg = minosMsg.split(";");
    var minosPos = {posX: parseInt(minosMsg[0], 10), posY: parseInt(minosMsg[1], 10)};
    for (i = 0; i < moves.length; i++) {
        var distanceToMinos = distance(moves[i].newX, moves[i].newY, minosPos.posX, minosPos.posY);
        if (distanceToMinos < bestDistanceToMinos) {
            bestDistanceToMinos = distanceToMinos;
        }       
    }
}
for (i = 0; i < moves.length; i++) {
    if (minosMsg !== '' && minosMsg !== undefined) {
        var distanceToMinos = distance(moves[i].newX, moves[i].newY, minosPos.posX, minosPos.posY);
        if (distanceToMinos === bestDistanceToMinos) {
            moves[i].danger += dangerValues.wayToMinos;
        }
    }
    if (closestFriend != null && distance(moves[i].x, moves[i].y, closestFriend.x, closestFriend.y) < distance(x, y, closestFriend.x, closestFriend.y)) {
        moves[i].danger += dangerValues.wayToFriend;
    }

    if (closestEnemy != null && distance(moves[i].x, moves[i].y, closestEnemy.x, closestEnemy.y) < distance(x, y, closestEnemy.x, closestEnemy.y)) {
        moves[i].danger += manyEnemies ? dangerValues.wayToManyEnemies : dangerValues.wayToEnemy;
    }
}

var bestMove = null;
var leastDanger = 10000;
for (i = 0; i < moves.length; i++) {
    if (moves[i].danger < leastDanger || (moves[i].danger === leastDanger && Math.random() < 0.5)) {
        leastDanger = moves[i].danger;
        bestMove = i;
    }
}
var newX = ("000" + moves[bestMove].newX).substr(-3, 3);
var newY = ("000" + moves[bestMove].newY).substr(-3, 3);
setMsg(newX + ";" + newY);
return bestMove;

Essaie de trouver Minos et de tuer ses ennemis. Malheureusement, l'équipe rouge perd toujours, peut-être parce que nous sommes moins joueurs ...


2

Blue Team - MiddleMan

// MiddleMan by Mwr247

// Self identification
var id = 30793;

// Bounds
var minPos = 0;
var midPos = 63;
var maxPos = 127;

// Movesets
var up = [0, 4, 2, 3, 5, 1, 6];
var down = [0, 5, 1, 6, 4, 2, 3];
var left = [0, 4, 5, 2, 1, 3, 6];
var right = [0, 3, 6, 2, 1, 4, 5];

// Our grid
var points = [0, 0, 0, 0, 0, 0, 0];

// Point system
var bound = -100000;
var death = -5000;
var dodge = 500;
var evade_best = 100;
var evade_better = 50;
var evade_good = 25;
var evade_bad = -25;
var evade_worse = -50;
var evade_worst = -100;
var kill = 4900;
var enemy = 5;

// Message
var msg = [[], []];

// Normalize values
var norm = function(val) {
    return Math.max(-1, Math.min(1, Math.round(val)));
};

// Get detailed ent data
var data = function(ent) {
    var info = {};
    info.x = ent.x - x;
    info.y = ent.y - y;
    info.normX = norm(info.x);
    info.normY = norm(info.y);
    info.distX = Math.abs(info.x);
    info.distY = Math.abs(info.y),
    info.dist = Math.sqrt(Math.pow(info.x, 2) + Math.pow(info.y, 2))
    return info
};

// Set position value
var pos = function(dir, index, val) {
    points[dir[index]] += val;
};

// Set position value above/below
var ver = function(dir, val) {
    pos(dir, 1, val);
    pos(dir, 2, val * 1.001);
    pos(dir, 3, val);
};

// Set position value on the sides
var hor = function(dir, val) {
    pos(dir, 1, val);
    pos(dir, 2, val);
};

// Vertical bound logic
if (y === minPos) {
    ver(up, bound);
} else if (y === maxPos) {
    ver(down, bound);
}

// Horizontal bound logic
if (x === minPos) {
    hor(left, bound);
} else if (x === maxPos) {
    hor(right, bound);
}

// Enemy logic
if (eNear.length) {
    var tmp;
    for (var i = 0; i < eNear.length; i++) {
        // Add the enemy to the message data
        msg[1].push([eNear[i].x, eNear[i].y]);
        tmp = data(eNear[i]);
        // We're touching, either attack or evade
        if (tmp.distY <= 1 && tmp.distX <= 1) {
            var d;
            if (tmp.distX !== 0) { // If we are not right above/below, current position is a death zone
                pos(up, 0, death);
            }
            if (tmp.distY === 0) { // Dodge like heck
                if (tmp.normX > 0) {
                    hor(right, dodge);
                    hor(left, evade_best);
                } else if (tmp.normX < 0) {
                    hor(left, dodge);
                    hor(right, evade_best);
                }
                pos(up, 2, death);
                pos(down, 2, death);
            } else { // We are above or below; finish them!
                d = tmp.y > 0 ? down : up;
                pos(d, 2 + tmp.normX, kill);
                if (tmp.normX === 0) {
                    pos(d, 1, death);
                    pos(d, 3, death);
                } else {
                    pos(d, 2, death);
                }
            }
        } else if (tmp.distY <= 2 && tmp.distX <= 2) { // We're a spot away, don't get too close!
            var d;
            if (tmp.distY === 2) { // They are two below
                d = tmp.y === 2 ? down : up;
                if (tmp.distX === 0) { // Straight down
                    pos(d, 1, death);
                    pos(d, 3, death);
                    pos(d, 2, dodge);
                    pos(d, 5, evade_good);
                    pos(d, 0, evade_best);
                } else if (tmp.distX === 1) { // One to the side
                    pos(d, 2, death);
                    pos(d, 2 + tmp.normX, dodge);
                    pos(d, 5 + tmp.normX, evade_better);
                    pos(d, 5 - tmp.normX, evade_bad);
                    pos(d, 2 - tmp.normX, evade_worst);
                } else { // Diagonals
                    pos(d, 2 + tmp.normX, death);
                    pos(d, 5 + tmp.normX, evade_better);
                    pos(d, 5 - tmp.normX, evade_bad);
                    pos(d, 2, evade_worse);
                    pos(d, 2 - tmp.normX, evade_worst);
                }
            } else { // They are to the sides
                d = tmp.normX === 1 ? right : left;
                if (tmp.distY === 0) { // Straight out
                    hor(d, death);
                    pos(d, 3, evade_better);
                    pos(d, 4, evade_better);
                } else { // A little angled
                    pos(d, 1 + (tmp.normY > 0), death);
                    pos(d, 1 + (tmp.normY < 0), evade_best);
                }
            }
        }

        // If there's a horizontal enemy, head that way
        if (tmp.x > 0) {
            hor(right, enemy + 16 - tmp.x);
        } else if (tmp.x < 0) {
            hor(left, enemy + 16 - tmp.x);
        }
        // If there's a vertical enemy, head that way
        if (tmp.y > 0) {
            ver(down, enemy + 16 - tmp.y);
        } else if (tmp.y < 0) {
            ver(up, enemy + 16 - tmp.y);
        }
    }

    // If we're near an enemy, lets try to bring them towards our friends
    if (tNear.length) {
        for (var i = 0; i < tNear.length; i++) {
            tmp = data(tNear[i]);
            if (tmp.x > 0) { // Horizontal moves
                hor(right, 1 + (16 - tmp.x) / 4);
            } else if (tmp.x < 0) {
                hor(left, 1 + (16 - tmp.x) / 4);
            }
            if (tmp.y > 0) { // Vertical moves
                ver(down, 1 + (16 - tmp.y) / 4);
            } else if (tmp.y < 0) {
                ver(up, 1 + (16 - tmp.y) / 4);
            }
        }
    }
}

// If not fighting, be the middleman you really want to be
if (y < midPos) {
    ver(down, 1);
} else if (y > midPos) {
    ver(up, 1);
}

// Hang around the horizontal middle, safe from those nasty corners
if (x < midPos) {
    hor(right, 1);
} else if (x > midPos) {
    hor(left, 1);
} else {
    pos(up, 0, 0.1);
}

// Evaluate our grid and find the winning move
var max = 0;
for (var i = 1; i < points.length; i++) {
    // If a clear winner, go with that. If there's a tie, randomize to keep things fresh
    if (points[max] < points[i] || (points[max] === points[i] && Math.round(Math.random()))) {
        max = i;
    }
}

// Set our new coordinates
var nX = x + (max === 3 || max === 6) - (max === 4 || max === 5);
var nY = y + (max === 5 || max === 1 || max === 6) - (max === 4 || max === 2 || max === 1);
msg[0] = [nX, nY];

// Set our message
setMsg(JSON.stringify(msg));

// Return the highest value move
return max;

MiddleMan est le frère jumeau de WallFlower (qu'il a remplacé). Comme son frère, il n'a pas tendance à être un type social. Il préférait rester au milieu de la pièce, regarder et attendre. Mais cela ne veut pas dire qu'il est passif ou timide. À son poste ou sur son chemin, s’il trouve un ennemi, quelle que soit sa taille, il se chargera de le combattre. Sachant qu'il y a de la force dans le nombre, il les attirera volontiers vers ses coéquipiers ou vers le centre dans l'espoir de trouver d'autres personnes. Une fois ses affaires terminées, il retourne à son poste, prêt pour la prochaine occasion d'aider son équipe.

Attention, équipe rouge. Bien qu'il puisse ne pas sembler beaucoup, il est aussi féroce et persistant qu'ils viennent; un maître de combat rapproché en solo. Il ne peut pas communiquer directement avec son équipe, mais il les reconnaît et travaillera ensemble pour vaincre l'ennemi commun. Il a récemment appris à envoyer des messages, même s'il n'écoute rien, mais pas son style. Le format est une chaîne JSON contenant un tableau comme celui-ci:, [[selfX,selfY],[[enemy1X,enemy1Y],[enemy2X,enemy2Y]]]et ainsi de suite pour plus d'ennemis.


1

Blue Team - VersaBot, un moteur polymorphe

Mon code suivra automatiquement le bot le plus proche situé à proximité, offrant une puissance de feu et une protection supplémentaires.

// VersaBot - The PolyMorphic Companion
// Copyright 2017.5 Sam Weaver
// For this SO challenge: http://codegolf.stackexchange.com/questions/48353/red-vs-blue-pixel-team-battlebots

//FUNctions
var randInt = function(min,max) {return Math.floor((Math.random() * ((max + 1) - min)) + min);};
var degrees = function(radians) {return radians * 180 / Math.PI;};

//variables
var me = 31743;
var friendId;

if(getMsg(me) == '') {
    friendId = 0;
    setMsg(friendId);
} else {
    friendId = getMsg(me);
}

//first, check if any teammates nearby
if(tNear.length > 0) {
    //loop through and see if friend is found
    var found = false;
    var fx,fy;
    for(var index in tNear) {
        var nearAlly = tNear[index];
        //check if friend
        if(nearAlly.id == friendId) {
            //yay, let's follow 'em
            fx = nearAlly.x;
            fy = nearAlly.y;
            found = true;
            break;
        }
    }
    if(!found) {
        //pick the first friend to be a new friend
        friendId = tNear[0].id;
        fx = tNear[0].x;
        fy = tNear[0].y;
    }

    //NOW, let's follow'em
    //get the radian angle in relation to me
    var radAngle = Math.atan2(fy-y,fx-x);
    //to degrees we go!
    //console.log('friend');
    var deg = Math.floor(degrees(radAngle));
    //now reverse it so it works
    deg = -1*deg;


    //we can return the right direction now
    if(deg > 120) {
        return 4; //up left
    } else if(deg > 60) {
        return 2; //up
    } else if(deg > 0) {
        return 3; //up right
    } else if(deg < -120) {
        return 5; //down left
    } else if(deg < -60) {
        return 1; //down
    } else if(deg < 0) {
        return 6; //down right
    }
    //for some reason?
    return 0;

} else {
    //pick a random direction
    return randInt(1,6);
}

Prendre plaisir!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.