Ten konkurs został oficjalnie zakończony. Zespół niebieski wygrał!
Autoram dwa zestawy 50 bitew i, co zadziwiające, Blue wygrał wszystkie 100 z nich. Patrząc na statystyki, jasne jest, że wspólne wpisy PhiNotPi i Sp3000 były prawdziwymi bohaterami. Świetna robota! W rzeczywistości, jeśli zdyskwalifikujesz każdego członka Niebieskiej Drużyny , Sphiboty nadal będą walczyć bardzo dobrze . Niektórzy ludzie z Czerwonej Drużyny planowali zniszczyć Sphiboty, ale wysiłek ten wydawał się zniknąć. Przepraszamy Red Team.
Konkurs został oficjalnie zakończony, ale to nie znaczy, że nie możesz już odpowiedzieć, to tylko oznacza, że nigdy nie będę ponownie określać oficjalnego zwycięzcy. Obie drużyny mogą przesyłać boty, dla zabawy. Sterownik pozostanie włączony i będzie działał, dopóki nie zostaną złamane żadne przyszłe wpisy.
To jest król wzgórza konkurs , ale zamiast wszystkich walczących ze sobą, będą rywalizować dwie drużyny: czerwona i niebieska. Tylko jeden będzie zwycięzcą.
Zespół, w którym jesteś, zależy od twojego numeru ID użytkownika PPCG . Aby to znaleźć, kliknij swój awatar u góry ekranu (musisz być zalogowany) i spójrz na adres URL strony, która się otworzy. Liczba po users/
jest twoim numerem identyfikacyjnym:
https://codegolf.stackexchange.com/users/[id number]/[display name]
Na przykład mój identyfikator użytkownika PPCG to 26997:
https://codegolf.stackexchange.com/users/26997/calvins-hobbies
Zauważ, że ta liczba jest inna dla różnych stron Stack Exchange.
Jeśli twój identyfikator to parzysta liczba , oznacza to, że jesteś w drużynie Czerwonej .
Jeśli twój identyfikator to nieparzysta liczba , oznacza to, że jesteś w drużynie Niebieskiej .
Nie ma możliwości zmiany zespołów.
Musisz współpracować ze swoim zespołem, aby spróbować pokonać drugą drużynę w rodzaju bitwy królewskiej, w której każdy użytkownik kontroluje „piksel” koloru swojej drużyny na siatce 128 × 128, która jest polem bitwy. Piksele mogą się przemieszczać, komunikować z kolegami z drużyny i usuwać piksele drugiej drużyny. Gdyby ktokolwiek mógł utworzyć dowolną liczbę pikseli, wymknąłby się spod kontroli, więc każdy użytkownik może przesłać tylko jedną odpowiedź na to pytanie.
Ten fragment kodu (zminimalizowana wersja tego skrzypce [ pełny ekran ]) jest kontrolerem dla całego konkursu. Automatycznie odczytuje zgłoszenia, upewnia się, że są prawidłowe, i organizuje bitwy między zespołami. Robi to w przeglądarce w dowolnym momencie, używając JavaScript . Ponieważ JavaScript jest jedynym językiem skryptowym po stronie klienta obsługiwanym przez większość przeglądarek, wszystkie zgłoszenia muszą być również napisane w 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 = <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 = -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>
Dla widoczności pole bitwy Snippeta jest skalowane 3-krotnie, więc jest to 384 × 384 rzeczywistych pikseli, a „piksele” to 3 × 3.
Pixel Team Battlebots - Przegląd
Gracze
Każda ważna odpowiedź na to pytanie reprezentuje gracza . (Aby uzyskać szczegółowe informacje na temat ważności, zobacz „Zasady i dyskwalifikacje” .) Każdy gracz ma kontrolę nad pojedynczą komórką 1 × 1 (zwaną także pikselem) na polu bitwy o komórce 128 × 128 . Gracze w drużynie Czerwonych mają czerwone piksele, a gracze w drużynie Niebieskie mają niebieskie piksele.
Bitwy
Walka to walka pomiędzy wszystkich graczy obu zespołów, nawet jeśli zespoły nie mają równą liczbę graczy. Bitwa rozpoczyna się od umieszczenia każdego gracza na losowej pozycji na polu bitwy, to znaczy dowolnej współrzędnej całkowitej od (0,0) w lewym górnym rogu, do (127 127) w prawym dolnym rogu. Gwarantujemy, że dwóch graczy nie wystartuje w tej samej pozycji.
Rusza się
Każda bitwa jest podzielona na 2048 ruchów . Tylko jedna drużyna może przenieść swoich graczy podczas każdego ruchu. Ta drużyna zmienia się z czerwonej na niebieską, więc każda drużyna wykonuje łącznie 1024 ruchy (chyba że gra zakończy się wcześniej).
Zespół, który pierwszy ruszy, to opcja, którą musisz ustawić w kontrolerze.
Gdy bitwy są uruchamiane automatycznie, zespół, który porusza się pierwszy, zmienia się w każdej bitwie.
Gracz się porusza
Kiedy drużyna się porusza, wszyscy gracze w tej drużynie sami się poruszają. Połączenia te są wykonywane w całkowicie losowej kolejności dla każdego ruchu. Po wywołaniu każdy gracz otrzymuje dane o stanie bitwy, aby mógł zdecydować, w którą stronę się poruszać.
Wszystkie ruchy są oddalone tylko o jeden piksel. Cienie na tych schematach wskazują, które pozycje każdego kolorowego gracza (kwadraty) mogą przesunąć do:
Oba kolory mogą przesuwać się po przekątnej w dowolnym kierunku lub pozostać w bezruchu, ale tylko czerwoni gracze mogą poruszać się w prawo i w lewo, a tylko niebiescy gracze mogą poruszać się w dół i w górę. Dzięki Phi i innym.
Jeśli gracz próbuje wyjść poza granice pola bitwy lub zbyt długo decyduje, w którą stronę się poruszać, lub ma jakiś błąd, automatycznie pozostanie w bezruchu.
Oprócz poruszania się, podczas tury gracz może czytać wiadomości napisane przez członków swojej drużyny i pisać wiadomości, które z kolei mogą być czytane. Pozwala to na prostą formę komunikacji w zespole.
Kod, który przesyłasz jako odpowiedź, jest logiką, która określa, w jaki sposób przenieść odtwarzacz i jakie wiadomości przeczytać i napisać (patrz „Jak odpowiedzieć” ).
Usuwanie wrogich graczy
Kiedy gracz wchodzi do tej samej komórki, co gracz drużyny przeciwnej, ten przeciwnik jest natychmiast usuwany z bitwy. Gracz, który właśnie się przeprowadził, kontynuuje grę normalnie. To jedyny mechanizm, który usuwa graczy z bitwy, a opanowanie go jest kluczem do wygranej!
Jeśli w komórce znajduje się wielu przeciwników, do których gracz się właśnie przeniósł, wszyscy wrogowie zostaną usunięci. Nic się nie dzieje, jeśli dwóch graczy z tej samej drużyny zajmuje tę samą komórkę.
Wygranie bitwy
Bitwa kończy się po wykonaniu wszystkich 2048 ruchów lub gdy w jednej drużynie nie ma już graczy. Drużyna z największą liczbą ocalałych graczy wygrywa. Remis Jeśli obie drużyny mają taką samą liczbę graczy, którzy przeżyli.
Jak odpowiedzieć
W swojej odpowiedzi musisz podać kod JavaScript, który decyduje o tym, w jaki sposób twój piksel poruszy się, gdy zostanie do tego wezwany.
W pierwszym przykładzie kodu z wcięciem w odpowiedzi (poprzedzonym 4 spacjami) napisz treść tej funkcji:
function moveMe(move, x, y, tCount, eCount, tNear, eNear, setMsg, getMsg) {
//the body goes here
}
Nie ma potrzeby golfowania kodem.
Co zwrócić
Zwracana wartość funkcji określa, w jaki sposób porusza się piksel:
0
pozostać nieruchomym,
1
aby przejść w prawo dla drużyny Czerwonej, w dół, aby niebieska drużyna
2
ruszyła w lewo dla drużyny Czerwonej, w górę, aby Niebieska drużyna
3
przesunęła się po przekątnej w górę i w prawo,
4
aby przejść po przekątnej w górę i w lewo,
5
aby przejść po przekątnej w dół i w lewo,
6
aby przejść po przekątnej w dół i w prawo
Jako schemat:
Piksel pozostanie domyślnie nieruchomy, jeśli kod wykona jedną z następujących czynności:
- Zwraca wszystko oprócz liczby całkowitej od 0 do 6.
- Próby przesunięcia pikseli poza granice pola bitwy.
- Uruchomienie trwa dłużej niż 15 milisekund.
- Zgłasza każdy wyjątek.
Twój wpis nie musi być deterministyczny; używanie Math.random
jest w porządku.
Parametry
Pierwsze 7 parametrów funkcji moveMe
podaje informacje o stanie bitwy:
move
to liczba całkowita, która zaczyna się od 1 i zwiększa się po każdym ruchu, aż do 1024 w ostatnim ruchu twojej drużyny.x
to twoja bieżąca pozycja x, liczba całkowita od 0 (skrajnie lewy) do 127 (skrajnie prawy).y
to twoja aktualna pozycja y, liczba całkowita od 0 (najwyższa) do 127 (najniższa).tCount
to bieżąca całkowita liczba ocalałych graczy w Twojej drużynie.eCount
to bieżąca całkowita liczba ocalałych graczy w drużynie wroga.tNear
to lista obecnych, którzy przeżyli w twojej drużynie, którzy są mniej niż 16 pikseli od siebie (odległość euklidesowa). Każdy z elementówtNear
jest przedmiotem zx
,y
iid
właściwości:
x
jest pozycją x drugiego graczay
jest pozycją y drugiego graczaid
to numer identyfikacyjny użytkownika PPCG innego odtwarzacza (jako liczba całkowita)eNear
jest dokładnie tak, jaktNear
poza tym, że jest to lista pobliskich wrogich graczy, a nie członków drużyny.
Kręgi we fragmencie należą do każdego gracza tNear
i eNear
zasięgu.
Wiadomości
2 ostatnie parametry, setMsg
i getMsg
, mają nieco inne cele.
W trakcie bitwy każdy gracz ma ciąg do 64 znaków, którymi może manipulować podczas każdego ruchu, aby przechowywać dane i potencjalnie komunikować się z kolegami z drużyny. Ciąg każdego gracza zaczyna się jako pusty ciąg. Kiedy gracz jest usuwany z bitwy, jego ciąg znaków jest ustawiony na „X”.
setMsg
jest funkcją jednoparametrową, która ustawia ciąg na przekazany.- Jeśli przekazana wartość nie jest łańcuchem, łańcuch nie ulega zmianie.
- Jeśli wartość jest łańcuchem zawierającym więcej niż 64 znaki, zachowywane są tylko pierwsze 64 znaki.
getMsg
to funkcja jednego argumentu, która pobiera numer identyfikacyjny użytkownika PPCG (jako liczbę całkowitą) kogoś w zespole i zwraca jego ciąg.- Ten gracz może znajdować się w dowolnym miejscu na planszy. Nie muszą znajdować się w promieniu 16 pikseli.
undefined
jest zwracany, jeśli podany identyfikator nie został znaleziony.
Przykładowe przesłanie
Gracz porusza się w górę i w prawo, jeśli po lewej stronie znajduje się wróg, albo w dół i w lewo, jeśli kolega z drużyny o numerze 123 mówi, ale poza tym pozostaje:
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
Pamiętaj, że ten blok kodu to wszystko, co jest wymagane. Definicja funkcji i nawiasy nie powinny być obecne.
Zasady i dyskwalifikacje
Jeśli użytkownik nie przestrzega poniższych zasad, mogę oznaczyć go jako zdyskwalifikowanego, a kontroler automatycznie zignoruje jego odpowiedzi. Ufam, że większość użytkowników tutaj celowo nie złamie zasad i będzie tylko kilka tymczasowych dyskwalifikacji z przyczyn przypadkowych.
Ważne zasady
Możesz edytować swoją odpowiedź w ciągu 8 godzin bezpośrednio po jej opublikowaniu.
Odpowiedzi edytowane po 8 godzinach od opublikowania zostaną automatycznie zdyskwalifikowane przez kontrolera. Zasada ta ma na celu zapobieganie ciągłemu optymalizowaniu podejścia przez początkowe odpowiedzi, prawdopodobnie wykradając pomysły z późniejszych odpowiedzi. Twój zespół musi zadowolić się wszelkimi odpowiedziami, od których się zaczął.Nie możesz usuwać ani publikować odpowiedzi bez specjalnego zezwolenia. Dam to, jeśli ktoś przypadkowo edytuje Twój post po 8 godzinach lub coś w tym stylu, ale nie tylko dlatego, że znalazłeś błąd.
Jeśli usuniesz swój post i zdecydujesz się go cofnąć, reguła edycji będzie nadal obowiązywać. (Kontroler nie widzi usuniętych odpowiedzi).
Deklarując nową zmienną JavaScript, musisz użyć
var
słowa kluczowego.
Wynika to z faktu, że zmienna zadeklarowana bezvar
staje się globalna, a nie lokalna, więc łatwo byłoby przypadkowo (lub celowo) zepsuć kontroler lub swobodnie komunikować się z innymi graczami. Musi być jasne, że nie próbujesz oszukiwać.Podczas deklarowania funkcji najlepiej użyć również
var
słowa kluczowego. tzn. użyjvar f = function(...) {...}
zamiastfunction f(...) {...}
. Nie jestem do końca pewien, dlaczego, ale czasem wydaje się, że to robi różnicę.Twój kod nie powinien działać przez zbyt długi czas.
Jeśli uruchomienie kodu zajmie więcej niż 15 milisekund, piksel w ogóle się nie poruszy. Ponieważ jednak JavaScript jest trudny do zatrzymania funkcji w trakcie wykonywania, wszystkie skrypty odtwarzacza są uruchamiane do końca przy każdym ruchu, a czas jest sprawdzany później. Oznacza to, że jeśli Twój kod zajmuje trochę czasu, wszyscy korzystający z kontrolera zauważą i będą zirytowani.
Automatyczne dyskwalifikacje
Administrator automatycznie zdyskwalifikował wpisy z następujących powodów:
- Użytkownik już odpowiedział.
- Edycji dokonano ponad 8 godzin po utworzeniu.
- Użytkownik jest wyraźnie oznaczony jako zdyskwalifikowany.
Inne zasady
W swoim kodzie nie możesz ...
- próba dostępu lub modyfikacji kontrolera lub kodu innego gracza.
- próba modyfikacji czegokolwiek wbudowanego w JavaScript.
- próbować komunikować się z innymi graczami, z wyjątkiem używania
getMsg
isetMsg
. - tworzyć zapytania internetowe.
- rób inne złośliwe rzeczy.
Będę pilnować innych niesportowych zachowań, takich jak kradzież kodu dosłownie z innych odpowiedzi lub używanie marionetek w skarpetkach, aby zadzierać z drugą drużyną.
Zapraszamy do współpracy i planowania ze swoim zespołem, ale dbaj o przyjazność i etyczność konkursu.
Jeśli uważasz, że ktoś musi zostać zdyskwalifikowany, lub uważasz, że naprawiłeś przyczynę dyskwalifikacji, zostaw komentarz tutaj dla mnie lub na czacie dotyczącym konkretnego pytania . Nie biorę udziału w konkursie.
Sugerowany format odpowiedzi
#[team color] Team - [entry title]
//function body
//probably on multiple lines
Explanations, notes, etc.
Tytuł wpisu jest opcjonalną nazwą, którą możesz nadać, jeśli chcesz. Kontroler nic z tym nie robi.
Punktacja
Konkurs zostanie oficjalnie zakończony 19 kwietnia 2015 r. Tego dnia (około 23:00 UTC) przeprowadzę automatycznie co najmniej 100 bitew (być może o wiele więcej, w zależności od tego, jak długo potrwają bitwy). Drużyna, która wygra najwięcej, zostanie zwycięzcą ogólnym. Jeśli jest remis lub bardzo blisko, będę prowadził więcej bitew, dopóki nie będzie jasne, że jedna drużyna ma przewagę.
(Możesz odpowiedzieć po ustaleniu zwycięzcy, ale nie zmienię oficjalnego wyniku).
Będę je uruchamiać w najnowszej wersji Google Chrome na laptopie z 64-bitowym systemem Windows 8.1, 4 GB pamięci RAM i czterordzeniowym procesorem 1,6 GHz. Upewnij się, że JavaScript działa w Chrome.
Zwycięstwo dotyczy przede wszystkim chwały drużyny, ale zaakceptuję najlepiej głosowaną odpowiedź na zwycięską drużynę.
Przez cały czas trwania konkursu należy pamiętać, że aspekt zespołowy oraz fakt, że jest on uruchamiany wyłącznie w postaci fragmentu stosu, jest bardzo eksperymentalny. Mam wielkie nadzieje, ale nie jestem pewien, jak dobrze wszystko będzie działać.
Napiwki:
- Możesz przetestować wpisy przed odpowiedzią. Edytuj pole tekstowe „Wpis testowy” u dołu fragmentu stosu i kliknij „Przeładuj z wpisem testowym”. Jeśli nie jest pusty, staje się graczem w podanej drużynie.
- Odpowiedzi są uruchamiane w zakresie zamaskowanym, więc rzeczy takie jak
alert
iconsole.log
nie będą działać. Tegoconsole
obiektu można użyć tylko we wpisie testowym. - Zaznacz „Komunikaty debugowania” u dołu fragmentu stosu i spójrz na konsolę przeglądarki (F12). Wiele przydatnych informacji jest drukowanych podczas bitew.
- Możesz wykorzystać Meta Sandbox jako rodzaj miejsca postoju. Odpowiedzi tam są oczywiście inne niż tutaj, a kontroler może się zdezaktualizować.
- Ponieważ nie jest to oficjalna aplikacja Stack , kontroler może przestać ładować odpowiedzi, jeśli uruchomisz ją więcej niż 300 razy dziennie.
„Kontynuacja” tego wyzwania: Block Building Bot Flocks!
Szybkie linki
Fiddle Controller Pełny ekran Czat ogólny Czerwony czat (Niebieski czat?) SandboxPost
źródło
Odpowiedzi:
Blue Team - SphiNotPi3000
Ten bot tworzy parę z botem Sp3000 .
Podstawową ideą jest to, że dwa boty, ustawione obok siebie, pomagają sobie nawzajem osłaniać słabości, aby żaden bot nie miał odsłoniętej strony. Pomaga to chronić przed zagrożeniami i ograniczyć opcje ucieczki celu.
Na początku gry nawigują ku sobie i tworzą parę. Ta para porusza się następnie jako pojedyncza jednostka, a jeden bot prowadzi drugą. Oba boty mają prawie identyczny kod, co pozwala im na wymianę pozycji i ról w razie potrzeby.
W stanie bezczynności boty poruszają się po planszy w poszukiwaniu wrogów. Po wykryciu wroga ostrożnie manewrują w odpowiednich pozycjach do ataku. Bardzo fajną cechą jest zdolność formacji do poruszania się prosto w poziomie, uzyskana dzięki umieszczeniu botów na przemian.
źródło
var
nie jest używane w tym poście i Sp3000. Przypisująj
od razu 0 i nie ma to żadnego wpływu na kontroler, więc na szczęście w tym przypadku nie stanowi problemu.Blue Team - SphiNotPi3000
Ten bot tworzy parę z botem PhiNotPi . Zobacz post Phi, aby uzyskać krótkie wyjaśnienie naszej strategii.
źródło
Red Team - SeekerBot
Najwyższym priorytetem SeekerBot jest przetrwanie. Dlatego bierze pod uwagę tylko ruchy, które nie narażą go na śmierć w następnej turze (o ile takie ruchy istnieją).
Gdy żaden z przeciwników nie będzie widoczny, przesunie się po polu bitwy, co zapewni, że większość terenu będzie regularnie znajdować się w polu widzenia.
Jeśli SeekerBot zauważy wroga, ruszy w jego kierunku. Jeśli uda mu się zabić wroga, zrobi to tak długo, jak długo ruch będzie bezpieczny.
Jeśli nie może zabić wroga, ale wróg jest w stanie go zabić w następnej turze, SeekerBot spróbuje zwabić wroga w stronę przyjaciela (jeśli jest widoczny). Jeśli żaden członek zespołu nie będzie widoczny, będzie próbował przejść do pozycji, w której może zabić wroga w następnej turze. Jeśli to nie zadziała 5 razy z rzędu, zmieni taktykę i zacznie się poruszać losowo, prawdopodobnie zbliżając się do wroga w następnej rundzie.
Za ile jest warte, użyje pierwszych 7 znaków wiadomości, aby wykrzyczeć własną pozycję w formacie „x; y” (gdzie x i y są zerowane).
Z pewnością nie jest to najczystszy kod, ale wydaje się, że robi to, czego się od niego spodziewałem.
źródło
Red Team - Groomba
Uwagi w komentarzach.
źródło
self
. Ta zmienna jest zarezerwowana do wskazywaniawindow.self
.I
Zamiast tego należy użyć (wielkich i). Lubme
. Lub nawetmyself
.Red Team - Lazy Slayer
To najbardziej podstawowy, jaki mogłem to zdobyć.To nie jest już w 100% podstawowe.Porusza się tylko JEŚLI WYMAGANE .
Jeśli użytkownik wyśle wiadomość z 2 liczbami pomiędzy-1
i1
(np .:'1,0'
:), oddzielonych przecinkiem, przeniesie się tam. Całkowicie ufa swoim kolegom z drużyny.Komunikuje się teraz przez JSON. Ma bardzo podstawową strukturę:
Przykład komunikatu do sterowania:
Który wyśle:
Jest też trochę samolubny
i ci nie pomogęa teraz jest pomocny jako stacjonarny latarnia.Jeśli ten komunikat jest nieprawidłowy (format jest nieprawidłowy), spróbuj dodać
"}
zamiast}
.Zostało to zredagowane po upływie 6 godzin, a po przedłużeniu do 8.
Nie jest już zepsuty i pozostanie jako ostateczna wersja.
źródło
Drużyna Czerwona - Tchórz
Ten bot pozostaje nieruchomy, aby uniknąć wykrycia go w jak największym stopniu. Gdy w zasięgu wzroku jest jeden lub więcej wrogów, może się zdarzyć kilka rzeczy:
Nie komunikuje się z nikim, na wypadek gdyby ktoś go usłyszał i poszedł za nim.
Może nie jest to najbardziej przydatny bot dla zespołu, ale fajnie było patrzeć, jak próbuje uciec od wszystkich.
źródło
Niebieska drużyna - Eagle
W tej chwili jestem całkiem zadowolony z mojego bota. Ma następującą taktykę:
źródło
Niebieska drużyna - Wróg
Ten mały piksel szuka enimów wokół niego i próbuje go zjeść, jeśli nie ma wokół niego piksela, porusza się w losowym kierunku. Nie mogę się doczekać, aby zobaczyć, co wymyślą inni ludzie.
źródło
Math.floor
nieMath.float
!(Math.random() * 6) & 6
lub(Math.random() * 6) << 0
lub(Math.random() * 6) >> 0
(przydatne dla codegolf).Math.random() * 7
? Próbowałem kilka testów i wydaje się, że twój bot nie przechodzi do prawego dolnego rogu. IIRCMath.random()
zawiera 0 i wyklucza 1, co oznacza, że* 6
tak naprawdę nigdy nie ma 6.Czerwona drużyna - Roztrzęsiona Czerwona Ładowarka
Czerwona Ładowarka porusza się tylko w lewo i prawo, mając nadzieję, że wykorzysta niezdolność Niebieskiego Zespołu do poruszania się w tych kierunkach. Po dotarciu do ściany odwraca się i szarżuje w przeciwnym kierunku, mając nadzieję, że ślepo zniszczy wszystkie boty na swojej drodze.
EDYCJA: Czerwona Ładowarka właśnie wypiła galon napoju energetycznego i teraz nie może przestać drżeć, ma nadzieję, że wykorzysta to również na swoją korzyść. Jest zbyt kofeinowy, aby słuchać kolegów z drużyny, ale krzyczy każdy z jego ruchów.
źródło
Niebieska drużyna - LazySoldier
źródło
JSON.parse
w bloku try / catch lub coś w tym rodzaju… powoduje to zbyt wiele błędów.Blue Team - Mass Killer
Chyba całkiem prosta taktyka. Liczę wrogów, do których mam bezpośredni dostęp (przypuszczam, że będzie ich mnóstwo :)) i zabijaj najwięcej. Jeśli ich nie ma, przynajmniej spróbuję się osłonić, przekraczając lub przekraczając największą liczbę wrogów, mając nadzieję na zabicie ich w następnym kroku.
Zrezygnowałem, biorąc pod uwagę ściany, więc po prostu je ignoruję. To i tak dość długo.
Nie mogłem przetestować / uruchomić tego kodu, więc będzie wiele błędów.
źródło
Blue Team - WatchDog
Porusza się losowo, dopóki nie złapie sojusznika, jeśli tak, to podąża za nim. Stara się uniknąć zabicia i zabić, jeśli może. Przepraszam za okropny kod, poszedłem prosto i zapomniałem o refaktoryzacji. Spróbuję poprawić czytelność, jeśli będę miał czas :)
źródło
Czerwona Drużyna - Dowódca Poszukiwacza
To jest kopia SeekerBota Minosa z kilkoma modyfikacjami.
Skompresowana pamięć wewnętrzna dla lepszej dystrybucji wiadomości
"$":[seekmode]
Odczytuje pozycje przeciwników od sojuszników w formacie JSON Lazy Slayera
"e":"[positions]"
; akceptuje[positions]
przesunięcie zarówno przez, jak32
i174
Podaje pozycje wroga w formacie JSON Lazy Slayera, z
"e":"[positions]"
przesunięciem o174
Raportuje ostatni ruch za pomocą,
"m":[move]
aby wskazać, że ten bot może być dowodzonyWydaje polecenia innym botom za pomocą
"[ally_id]":{"m":[move],"a":1,"id":29354}
. Command używa tego samego algorytmu poszukiwacza, z wyjątkiem lokalizacji sojusznika. Jeśli inne boty słuchają tych rozkazów, powinny się zgrupować i polować w paczce. Rozkazy wydawane tylko, jeśli wiadomość sojusznika zawiera"m":
Wykonuje polecenia innych botów, takich jak:
"29354":[move]
lub"29354":{"m":[move]
. Polecenia są wykonywane tylko wtedy, gdy w zasięgu nie ma żadnych wrogów i żaden inny sojusznik nie zgłasza wrogówźródło
""a":0,"o":[122,70],"m":0,"e":"f""
. Możesz również dołączyć do nas na czacie, jeśli chcesz.Red Team - BouncerBot
Mój bot odbija się od ściany do ściany (niezupełnie, więc pokrywa inny teren) w poszukiwaniu wrogów. Jeśli znajdzie się w zasięgu, atakuje, ciągnie je do ściany i próbuje je wyciągnąć (pomyśl o bramkarzu w klubie).
źródło
Red Team - SideKick
Lubi śledzić członków drużyny, dobrze, że jest ich mnóstwo!
źródło
Blue Team - niezdecydowany magnes
Ma wiele strategii: jeśli natychmiast pokona wroga, zrobi to i ucieknie od grup wrogów, jeśli są wystarczająco daleko, w przeciwnym razie będzie walczył. Poza tym szuka tylko członków zespołu i próbuje ich śledzić.
źródło
Blue Team - Fetch [38953]
[edytuje: okazuje się, że działa DUŻO lepiej, kiedy używam mojego rzeczywistego identyfikatora, a nie -1!]
Głupi mały bot, który biegnie po planszy, starając się przyciągnąć uwagę i przyciągając ścigających, a następnie biegnie na środek, gdzie (mam nadzieję) znajdzie kogoś, kto mógłby mu pomóc, lub po prostu zatrzyma ścigającego i zatrzyma go z polowania.
Wydaje się, że nie ma to większego wpływu na ogólny wynik ze względu na to, jak potężne są niebieskie drużyny tagteam, ale przynajmniej nie pogorszyłem sytuacji!
Krzycz w ciągu następnych 8 godzin, jeśli chcesz, żebym dodał coś przydatnego do mojej wiadomości.
źródło
Blue Team - PatrolBot
Kod jest rodzajem samodokumentowania. Rzeczy, które można zrobić, aby poprawić PatrolBot
if (canBeKilled() || isInWall()) { moveToBetterPosition() }
tuż przed powrotem.źródło
BLUE TEAM - Awesome 1 punkt
Priorytety piksela:
Grawitacja jest ustawiona na 64,64 przy ruchu 1
Grawitacja jest ustawiona na najbliższą lokalizację przeciwnika (aby poprowadzić piksel do lokalizacji ostatniego wroga, jeśli wróg ucieknie)
Grawitacja zmienia się losowo, gdy piksel osiągnie środek ciężkości lub znajdzie się w pobliżu krawędzi
źródło
Czerwony - LoyalFollower [15080]
Próbuje znaleźć Minos i zabić wrogów. Niestety czerwona drużyna wciąż przegrywa, być może dlatego, że mamy mniej graczy ...
źródło
Blue Team - MiddleMan
MiddleMan jest bratem bliźniakiem WallFlower (którego zastąpił). Podobnie jak jego brat, nie jest typem towarzyskim. Wolałby po prostu spędzać czas na środku pokoju, obserwując i czekając. Ale to nie znaczy, że jest pasywny lub nieśmiały. Będąc na swoim miejscu lub w drodze do niego, jeśli znajdzie wroga, bez względu na rozmiar, pobierze szarżę, aby go zabrać. Wiedząc, że jest siła w liczbach, chętnie przyciągnie ich do każdego znalezionego członka drużyny lub, alternatywnie, do centrum w nadziei na znalezienie innych. Po zakończeniu swojej działalności wraca na swoje miejsce, gotowy na kolejną okazję, aby pomóc swojemu zespołowi.
Uważaj, czerwony zespole. Choć może nie wydawać się taki duży, jest tak zaciekły i wytrwały, jak to tylko możliwe; mistrz pojedynków w zwarciu. Może nie komunikować się bezpośrednio ze swoim zespołem, ale uznaje je i będzie współpracować, aby pokonać wspólnego wroga. Niedawno nauczył się wysyłać wiadomości, chociaż sam nie będzie nasłuchiwał, tylko swój styl. Format to ciąg JSON zawierający tablicę taką jak ta:
[[selfX,selfY],[[enemy1X,enemy1Y],[enemy2X,enemy2Y]]]
i tak dalej dla większej liczby wrogów.źródło
Niebieska drużyna - VersaBot, silnik polimorficzny
Mój kod automatycznie podąży za najbliższym botem w pobliżu, zapewniając dodatkową siłę ognia i ochronę.
Cieszyć się!
źródło