Red vs. Blue - Battlebots ทีมพิกเซล


133

การประกวดครั้งนี้จบลงแล้วอย่างเป็นทางการ ทีมสีฟ้าชนะ!

ฉันทำการต่อสู้สอง ชุด 50 ครั้งและน่าประหลาดใจสีน้ำเงินชนะทั้งหมด 100 ครั้ง เมื่อดูจากสถิติแล้วเห็นได้ชัดว่ารายการความร่วมมือของPhiNotPiและSp3000เป็นฮีโร่ที่แท้จริง คุณทำได้ดีมาก! ในความเป็นจริงถ้าคุณตัดสิทธิ์สมาชิกทุกคนอื่น ๆ ของทีมสีน้ำเงินที่ Sphibots ยังคงนำขึ้นต่อสู้ที่ดีมาก ทีมสีแดงบางคนกำลังวางแผนที่จะกำจัด Sphibots แต่ความพยายามนี้ดูเหมือนจะหมดไป ขออภัยทีมสีแดง

การประกวดสิ้นสุดลงอย่างเป็นทางการแล้ว แต่นั่นไม่ได้หมายความว่าคุณจะไม่สามารถตอบได้อีกต่อไปมันหมายความว่าฉันจะไม่ประกาศผู้ชนะอย่างเป็นทางการอีกต่อไป ทั้งสองทีมยินดีที่จะส่งบอทอย่างต่อเนื่องเพื่อความสนุกสนาน คอนโทรลเลอร์จะยังคงทำงานอยู่ตราบใดที่ไม่มีรายการในอนาคตแตก


นี่คือกษัตริย์ของเนินเขาประกวด แต่แทนที่จะให้ทุกคนต่อสู้กับแต่ละอื่น ๆ จะมีสองทีมที่แข่งขัน: สีแดงและสีน้ำเงิน ผู้ชนะเพียงคนเดียวเท่านั้น

ทีมที่คุณใช้จะขึ้นอยู่กับหมายเลขประจำตัวผู้ใช้PPCGของคุณ ในการค้นหาสิ่งนี้ให้คลิกที่รูปประจำตัวของคุณที่ด้านบนของหน้าจอ (คุณต้องเข้าสู่ระบบ) และดูที่ URL ของหน้าเว็บที่เปิดขึ้นมา หมายเลขหลังจากนั้นusers/คือหมายเลข ID ของคุณ:

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

ตัวอย่างเช่นหมายเลขประจำตัวผู้ใช้ PPCG ของฉันคือ 26997:

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

โปรดทราบว่าหมายเลขนี้แตกต่างกันสำหรับไซต์ Stack Exchange ที่แตกต่างกัน

หาก ID ของคุณเป็นเลขคู่แล้วคุณจะอยู่ในทีมสีแดง
หาก ID ของคุณเป็นเลขคี่แล้วคุณอยู่ในทีมสีฟ้า
ไม่มีทางเปลี่ยนทีมได้

คุณต้องทำงานร่วมกับทีมของคุณเพื่อพยายามเอาชนะทีมอื่นในรูปแบบการต่อสู้ที่ผู้ใช้ทุกคนควบคุม "พิกเซล" ของสีทีมของพวกเขาในตาราง 128 × 128 นั่นคือสนามรบ พิกเซลสามารถเคลื่อนที่ไปมาสื่อสารกับเพื่อนร่วมทีมและนำพิกเซลของทีมอื่นมาใช้ มันคงจะไม่เกิดอะไรขึ้นถ้าใคร ๆ ก็สามารถสร้างจำนวนพิกเซลได้ดังนั้นผู้ใช้ทุกคนอาจส่งคำตอบสำหรับคำถามนี้เพียงคำเดียวเท่านั้น

Stack Snippet นี้ (เวอร์ชั่นย่อของซอนี้ [ เต็มหน้าจอ ]) เป็นตัวควบคุมสำหรับการแข่งขันทั้งหมด มันอ่านการส่งโดยอัตโนมัติทำให้แน่ใจว่าพวกเขาถูกต้องและขั้นตอนการต่อสู้ระหว่างทีม มันไม่ได้สิทธินี้ในเบราว์เซอร์ของคุณในเวลาที่คุณต้องการโดยใช้JavaScript เนื่องจาก JavaScript เป็นภาษาสคริปต์ฝั่งไคลเอ็นต์เท่านั้นที่เบราว์เซอร์ส่วนใหญ่สนับสนุนดังนั้นการส่งทั้งหมดจึงต้องเขียนใน 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>

สำหรับการมองเห็นสนามรบของสนิเพตถูกปรับอัตราส่วนเป็น 3 เท่าดังนั้นจึงเป็นพิกเซลจริง 384 × 384 และ "พิกเซล" เป็น 3 × 3

Pixel Team Battlebots - ภาพรวม

ผู้เล่น

แต่ละคำตอบที่ถูกต้องสำหรับคำถามนี้หมายถึงผู้เล่น (สำหรับรายละเอียดเกี่ยวกับความถูกต้องดู"หลักเกณฑ์และลักษณะต้องห้าม" .) ผู้เล่นทุกคนมีการควบคุมเดียว 1 × 1 เซลล์ (aka พิกเซล) บน 128 × 128 เซลล์สนามรบ ผู้เล่นในทีม Red มีพิกเซลสีแดงและผู้เล่นในทีม Blue จะมีพิกเซลสีน้ำเงิน

การต่อสู้

การต่อสู้เป็นการต่อสู้ระหว่างผู้เล่นทุกคนในทั้งสองทีมแม้ว่าทีมจะไม่มีผู้เล่นเท่ากัน การต่อสู้เริ่มต้นด้วยผู้เล่นทุกคนที่ถูกวางตำแหน่งสุ่มในสนามรบนั่นคือพิกัดจำนวนเต็มใด ๆ จาก (0,0) ที่ด้านซ้ายบนถึง (127,127) ที่มุมล่างขวา มันรับประกันว่าจะไม่มีผู้เล่นสองคนที่จะเริ่มต้นในตำแหน่งเดียวกัน

การเคลื่อนไหว

การต่อสู้แต่ละถูกแบ่งออกเป็น 2048 ย้าย มีเพียงทีมเดียวเท่านั้นที่จะย้ายผู้เล่นของพวกเขาในระหว่างการย้ายแต่ละครั้ง ทีมนั้นสลับไปมาจากสีแดงเป็นสีน้ำเงินดังนั้นแต่ละทีมมีการเคลื่อนที่ทั้งหมด 1024 ครั้ง (ยกเว้นว่าเกมจะจบเร็ว)

ทีมที่ได้รับการเลื่อนอันดับแรกคือตัวเลือกที่คุณต้องตั้งค่าในคอนโทรลเลอร์
เมื่อการต่อสู้มีการทำงานอัตโนมัติทีมที่ย้ายตัวเลือกแรกในการต่อสู้ทุกครั้ง

ผู้เล่นย้าย

เมื่อทีมย้ายผู้เล่นทุกคนในทีมนั้นจะถูกเรียกตัวเพื่อย้ายตัวเอง การโทรเหล่านี้จะดำเนินการตามลำดับแบบสุ่มโดยสมบูรณ์สำหรับการย้ายแต่ละครั้ง เมื่อมีการเรียกผู้เล่นแต่ละคนจะได้รับข้อมูลเกี่ยวกับสถานะของการต่อสู้เพื่อให้พวกเขาสามารถตัดสินใจได้ว่าจะเคลื่อนที่แบบใด

การเคลื่อนไหวทั้งหมดอยู่ห่างออกไปเพียงหนึ่งพิกเซล วงกลมสีเข้มในไดอะแกรมเหล่านี้ทำเครื่องหมายตำแหน่งของผู้เล่นแต่ละคนที่มีสี (สี่เหลี่ยม) สามารถเลื่อนไปที่:

ทีมสีแดงย้ายไดอะแกรม ทีมสีน้ำเงินย้ายไดอะแกรม

ทั้งสองสีสามารถเคลื่อนที่ในแนวทแยงมุมในทิศทางใดก็ได้หรืออยู่นิ่ง ๆ แต่มีเพียงผู้เล่นสีแดงเท่านั้นที่สามารถเลื่อนไปทางขวาและซ้ายและมีเพียงผู้เล่นสีน้ำเงินเท่านั้นที่สามารถเลื่อนขึ้นและลง ขอบคุณพี่และคนอื่น ๆ

หากผู้เล่นพยายามย้ายออกจากสนามรบหรือใช้เวลานานเกินไปในการตัดสินใจว่าจะย้ายทางไหนหรือมีข้อผิดพลาดบางอย่างพวกเขาจะยังคงอยู่โดยอัตโนมัติ

นอกเหนือไปจากการเคลื่อนไหวในระหว่างการเปิดผู้เล่นสามารถอ่านข้อความที่เขียนโดยเพื่อนร่วมทีมและเขียนข้อความที่อาจจะอ่าน สิ่งนี้จะช่วยให้การสื่อสารแบบทีมหยาบ

รหัสที่คุณส่งเป็นคำตอบคือตรรกะที่กำหนดวิธีในการย้ายเครื่องเล่นของคุณและข้อความที่จะอ่านและเขียน (ดู"วิธีการตอบ" )

การลบผู้เล่นศัตรู

เมื่อผู้เล่นเดินเข้ามาในเซลล์เช่นเดียวกับผู้เล่นในทีมตรงข้ามว่าผู้เล่นฝ่ายตรงข้ามจะทันทีลบออกจากการสู้รบ ผู้เล่นที่เพิ่งย้ายยังคงดำเนินต่อไปตามปกติ นี่เป็นกลไกเดียวที่จะลบผู้เล่นออกจากการต่อสู้และการฝึกฝนเป็นกุญแจสำคัญในการชนะ!

หากมีผู้เล่นศัตรูหลายคนในเซลล์ที่ผู้เล่นเพิ่งย้ายไปแล้วผู้เล่นศัตรูทั้งหมดจะถูกลบออก ไม่มีอะไรเกิดขึ้นถ้าผู้เล่นสองคนในทีมเดียวกันครอบครองเซลล์เดียวกัน

ชนะการต่อสู้

การต่อสู้สิ้นสุดลงเมื่อมีการเคลื่อนไหวทั้งหมด 2048 ครั้งหรือเมื่อทีมใดทีมหนึ่งไม่มีผู้เล่นเหลือ ทีมที่มีจำนวนผู้เล่นรอดชีวิตมากที่สุดเป็นผู้ชนะ ถ้าทั้งสองทีมมีผู้เล่นที่มีชีวิตรอดเท่ากัน

วิธีการตอบ

ในคำตอบของคุณคุณต้องให้รหัส JavaScript ที่ตัดสินใจว่าพิกเซลของคุณจะย้ายไปทางไหนเมื่อถูกเรียกให้ทำเช่นนั้น

ในตัวอย่างโค้ดที่เยื้องครั้งแรกในคำตอบของคุณ (อันที่อยู่ด้านหน้ามี 4 ช่องว่าง) ให้เขียนเนื้อความสำหรับฟังก์ชั่นนี้:

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

ไม่จำเป็นต้องตีรหัสของคุณ

สิ่งที่จะกลับมา

ค่าตอบแทนของฟังก์ชั่นกำหนดวิธีที่พิกเซลของคุณย้าย:

0จะยังคงอยู่
1เพื่อย้ายขวาสำหรับทีมสีแดงลงสำหรับทีมสีน้ำเงิน
2เพื่อย้ายไปทางซ้ายสำหรับทีมสีแดงขึ้นสำหรับทีมสีน้ำเงิน
3เพื่อย้ายแนวทแยงมุมขึ้นและขวา
4เพื่อย้ายแนวทแยงมุมขึ้นและซ้าย
5เพื่อย้ายตามแนวทแยงมุมขึ้นและซ้าย
6เพื่อเลื่อนตามแนวทแยงมุม ลงและขวา

เป็นแผนภาพ:

ย้ายแผนภาพค่าตอบแทน

พิกเซลของคุณจะยังคงเป็นค่าเริ่มต้นหากรหัสของคุณทำสิ่งเหล่านี้:

  • ส่งคืนสิ่งใด ๆ นอกเหนือจากจำนวนเต็มตั้งแต่ 0 ถึง 6
  • พยายามย้ายพิกเซลออกจากขอบเขตสนามรบ
  • ใช้เวลานานกว่า 15 มิลลิวินาทีในการเรียกใช้
  • โยนข้อยกเว้นใด ๆ

ข้อมูลของคุณไม่จำเป็นต้องกำหนดขึ้นเอง ใช้งานMath.randomได้ดี

พารามิเตอร์

พารามิเตอร์ฟังก์ชัน 7 ตัวแรกของการmoveMeให้ข้อมูลเกี่ยวกับสถานะของการต่อสู้:

  • move เป็นจำนวนเต็มที่เริ่มต้นที่ 1 และเพิ่มขึ้นหลังจากการย้ายทุกครั้งจนกว่าจะเป็น 1024 ในการย้ายครั้งสุดท้ายของทีม
  • x คือตำแหน่ง x ปัจจุบันของคุณจำนวนเต็มตั้งแต่ 0 (ซ้ายสุด) ถึง 127 (ขวาสุด)
  • y คือตำแหน่ง y ปัจจุบันของคุณจำนวนเต็มตั้งแต่ 0 (บนสุด) ถึง 127 (ล่างสุด)
  • tCount คือจำนวนผู้เล่นที่มีชีวิตรอดทั้งหมดในทีมของคุณ
  • eCount คือจำนวนผู้เล่นที่มีชีวิตรอดทั้งหมดในทีมศัตรู
  • tNearคือรายชื่อผู้เล่นที่มีชีวิตรอดในทีมของคุณซึ่งอยู่ห่างออกไปไม่ถึง 16 พิกเซล (ระยะทางแบบยุคลิด) องค์ประกอบของแต่ละคนtNearเป็นวัตถุที่มีx, yและidคุณสมบัติ:
    • x คือตำแหน่ง x ของผู้เล่นอื่น
    • y คือตำแหน่ง y ของผู้เล่นอื่น
    • id คือหมายเลขประจำตัวผู้ใช้ PPCG ของผู้เล่นอื่น (เป็นจำนวนเต็ม)
  • eNearเหมือนกับทุกอย่างtNearยกเว้นเป็นรายชื่อผู้เล่นศัตรูใกล้เคียงไม่ใช่เพื่อนร่วมทีม

วงกลมในตัวอย่างเป็นผู้เล่นแต่ละคนtNearและeNearช่วง

ข้อความ

พารามิเตอร์ 2 ตัวสุดท้ายsetMsgและgetMsgมีจุดประสงค์ที่แตกต่างกันเล็กน้อย

ตลอดการต่อสู้ผู้เล่นแต่ละคนมีตัวละครมากถึง 64 ตัวที่พวกเขาสามารถจัดการได้ในทุก ๆ การเคลื่อนไหวเพื่อเก็บข้อมูลและสื่อสารกับเพื่อนร่วมทีมได้ สตริงของผู้เล่นแต่ละคนเริ่มจากสตริงที่ว่างเปล่า เมื่อผู้เล่นถูกนำออกจากการต่อสู้สตริงของพวกเขาจะถูกตั้งค่าเป็น "X"

  • setMsg เป็นฟังก์ชั่นการโต้แย้งอย่างใดอย่างหนึ่งที่กำหนดสตริงของคุณเป็นสตริงที่ส่งผ่านมา
    • หากค่าที่ส่งเข้าไม่ใช่สตริงสตริงของคุณจะไม่เปลี่ยนแปลง
    • หากค่าเป็นสตริงที่มีอักขระมากกว่า 64 ตัวจะเก็บเฉพาะ 64 ตัวแรกเท่านั้น
  • getMsg เป็นฟังก์ชั่นการโต้แย้งหนึ่งที่ใช้หมายเลขประจำตัวผู้ใช้ PPCG (เป็นจำนวนเต็ม) ของใครบางคนในทีมของคุณและส่งคืนสตริงของพวกเขา
    • ผู้เล่นนั้นอาจอยู่ที่ใดก็ได้ในกริด พวกเขาไม่จำเป็นต้องอยู่ในรัศมี 16 พิกเซลของคุณ
    • undefined จะถูกส่งคืนหากไม่พบ ID ที่ระบุ

ส่งตัวอย่าง

ผู้เล่นนี้เลื่อนขึ้นและขวาหากมีศัตรูทางซ้ายหรืออื่น ๆ ลงและไปทางซ้ายหากเพื่อนร่วมทีมที่มี ID 123 บอกว่าจะทำเช่นนั้น แต่ก็ยังคงอยู่:

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

โปรดทราบว่าการบล็อกโค้ดนี้เป็นสิ่งที่จำเป็นทั้งหมด ไม่ควรมีคำจำกัดความของฟังก์ชันและวงเล็บเหลี่ยม

กฎและการตัดสิทธิ์

หากผู้ใช้ไม่ปฏิบัติตามกฎด้านล่างฉันอาจทำเครื่องหมายว่าถูกตัดสิทธิ์และผู้ควบคุมจะเพิกเฉยต่อคำตอบของพวกเขาโดยอัตโนมัติ ฉันเชื่อว่าผู้ใช้ส่วนใหญ่ที่นี่จะไม่ละเมิดกฎโดยเจตนาและจะมีการตัดสิทธิ์ชั่วคราวเพียงเล็กน้อยสำหรับสาเหตุที่เกิดจากอุบัติเหตุ

กฎสำคัญ

  1. คุณสามารถแก้ไขคำตอบของคุณในช่วงเวลา 8 ชั่วโมงโดยตรงหลังจากโพสต์
    คำตอบที่ถูกแก้ไขหลังจาก 8 ชั่วโมงนับจากเมื่อพวกเขาถูกโพสต์จะถูกตัดสิทธิ์โดยผู้ควบคุม กฎนี้คือการป้องกันไม่ให้คำตอบเริ่มต้นจากการเพิ่มประสิทธิภาพของวิธีการอย่างต่อเนื่องอาจขโมยความคิดจากคำตอบในภายหลัง ทีมของคุณต้องทำทุกอย่างเพื่อตอบคำถามที่เริ่มต้นด้วย

    คุณไม่สามารถลบและโพสต์คำตอบของคุณใหม่โดยไม่ได้รับอนุญาตพิเศษ ฉันจะให้สิ่งนี้ถ้ามีคนแก้ไขโพสต์ของคุณโดยไม่ตั้งใจหลังจากทำเครื่องหมาย 8 ชั่วโมงหรืออะไรทำนองนั้น แต่ไม่ใช่เพียงเพราะคุณพบข้อบกพร่อง

    หากคุณลบโพสต์และเลือกที่จะยกเลิกการลบกฎการแก้ไขจะยังคงมีผลอยู่ (ผู้ควบคุมไม่เห็นคำตอบที่ถูกลบ)

  2. เมื่อประกาศตัวแปร JavaScript ใหม่คุณต้องใช้varคำหลัก
    นี่เป็นเพราะตัวแปรที่ประกาศโดยไม่varกลายเป็นโกลบอลแทนที่จะเป็นโลคัลดังนั้นจึงเป็นการง่ายที่จะบังเอิญยุ่งเหยิง (หรือจงใจ) กับตัวควบคุมหรือสื่อสารกับผู้เล่นคนอื่นได้อย่างอิสระ ต้องชัดเจนว่าคุณไม่ได้พยายามโกง

    เมื่อประกาศฟังก์ชั่นจะเป็นการดีที่สุดที่จะใช้varคำหลักเช่นกัน เช่นใช้แทนvar f = function(...) {...} function f(...) {...}ฉันไม่แน่ใจทั้งหมดว่าทำไม แต่บางครั้งก็ดูเหมือนจะสร้างความแตกต่าง

  3. รหัสของคุณไม่ควรใช้เวลานานเกินไป
    หากรหัสของคุณใช้เวลารันมากกว่า 15 มิลลิวินาทีพิกเซลของคุณจะไม่เคลื่อนที่เลย อย่างไรก็ตามเนื่องจากเป็นเรื่องยากใน JavaScript ที่จะหยุดฟังก์ชั่น mid-execution สคริปต์ของผู้เล่นทั้งหมดจึงถูกเรียกใช้ให้เสร็จสมบูรณ์ในทุก ๆ การเคลื่อนไหวและเวลาจะถูกตรวจสอบในภายหลัง ซึ่งหมายความว่าหากรหัสของคุณใช้เวลามากทุกคนที่เรียกใช้คอนโทรลเลอร์จะสังเกตเห็นและรำคาญ

ตัดสิทธิ์โดยอัตโนมัติ

ตัวควบคุมตัดสิทธิ์รายการโดยอัตโนมัติด้วยเหตุผลเหล่านี้:

  • ผู้ใช้มีคำตอบแล้ว
  • ทำการแก้ไขมากกว่า 8 ชั่วโมงหลังจากการสร้าง
  • ผู้ใช้ถูกทำเครื่องหมายว่าถูกตัดสิทธิ์โดยเฉพาะ

กฎอื่น ๆ

ในรหัสของคุณคุณอาจไม่ ...

  • พยายามเข้าถึงหรือแก้ไขคอนโทรลเลอร์หรือรหัสของผู้เล่นอื่น
  • พยายามแก้ไขสิ่งที่มีอยู่ใน JavaScript
  • พยายามที่จะสื่อสารกับผู้เล่นอื่น ๆ ยกเว้นโดยใช้และgetMsgsetMsg
  • ทำแบบสอบถามเว็บ
  • ทำสิ่งที่เป็นอันตรายเป็นอย่างอื่น

ฉันจะจับตาดูพฤติกรรมที่ไม่เหมือนนักกีฬาอื่น ๆ เช่นการขโมยรหัสคำต่อคำจากคำตอบอื่น ๆ หรือการใช้หุ่นกระบอกถุงเท้าไปยุ่งกับทีมอื่น

คุณสามารถร่วมมือและวางแผนกับทีมของคุณได้ แต่ให้การแข่งขันเป็นมิตรและมีจริยธรรม

หากคุณคิดว่าคนที่จะต้องมีการขาดคุณสมบัติหรือคิดว่าคุณคงเหตุผลที่คุณถูกตัดสิทธิ์ออกความคิดเห็นที่นี่สำหรับผมหรือในการแชทโดยเฉพาะคำถาม ฉันไม่ได้เข้าร่วมการแข่งขัน

รูปแบบคำตอบที่แนะนำ

#[team color] Team - [entry title]

    //function body
    //probably on multiple lines

Explanations, notes, etc.

ชื่อรายการเป็นชื่อที่คุณเลือกได้หากคุณต้องการ คอนโทรลเลอร์ไม่ได้ทำอะไรกับมัน

เกณฑ์การให้คะแนน

การประกวดนี้จะมีขึ้นอย่างเป็นทางการในวันที่ 19 เมษายน 2558ในวันนั้น (ประมาณ 23.00 น. UTC) ฉันจะทำงานอัตโนมัติอย่างน้อย 100 ครั้ง (อาจมีอีกมากขึ้นอยู่กับระยะเวลาในการต่อสู้) ทีมที่ชนะมากที่สุดจะเป็นผู้ชนะโดยรวม ถ้ามันเสมอกันหรือใกล้มากฉันจะวิ่งการต่อสู้มากกว่านี้จนกว่าจะเห็นได้ชัดว่าทีมหนึ่งมีข้อได้เปรียบ

(คุณอาจตอบหลังจากผู้ชนะได้รับการตัดสิน แต่ฉันจะไม่เปลี่ยนผลอย่างเป็นทางการ)

ฉันจะใช้งานพวกเขาใน Google Chrome เวอร์ชันล่าสุดบนแล็ปท็อปที่มี Windows 8.1 64-bit, 4 GB ram และโปรเซสเซอร์ 1.6GHz quad core ตรวจสอบให้แน่ใจว่า JavaScript ของคุณใช้งานได้ใน Chrome

ชัยชนะเป็นเรื่องเกี่ยวกับความรุ่งโรจน์ของทีมเป็นหลัก แต่ฉันจะยอมรับคำตอบที่ได้รับคะแนนสูงสุดในทีมที่ชนะ

ตลอดการแข่งขันโปรดจำไว้ว่าลักษณะพื้นฐานของทีมและความจริงที่ว่ามันทำงานโดยสิ้นเชิงใน Stack Snippet นั้นเป็นการทดลองอย่างมาก ฉันมีความหวังสูง แต่ฉันไม่สามารถพูดได้อย่างแน่นอนว่าจะทำงานได้ดีเพียงใด

เคล็ดลับ:

  • คุณสามารถทดสอบรายการก่อนตอบ แก้ไขกล่องข้อความ "รายการทดสอบ" ใกล้กับด้านล่างของส่วนย่อยของข้อมูลและคลิก "โหลดพร้อมรายการทดสอบ" ถ้ามันไม่ว่างเปล่ามันจะกลายเป็นผู้เล่นในทีมที่ระบุ
  • รู้รอบถูกเรียกใช้ในขอบเขตที่สวมหน้ากากดังนั้นสิ่งที่ต้องการalertและconsole.logไม่ทำงาน consoleวัตถุสามารถนำมาใช้เฉพาะในการเข้าทดสอบ
  • ทำเครื่องหมายที่ "Debug Messages" ที่ด้านล่างของ Stack Snippet และดูคอนโซลของเบราว์เซอร์ของคุณ (F12) ข้อมูลที่มีประโยชน์มากมายถูกพิมพ์เมื่อการต่อสู้กำลังทำงาน
  • คุณสามารถใช้โพสต์ Meta Sandboxเป็นพื้นที่จัดเตรียม คำตอบมีแน่นอนแตกต่างจากที่นี่และผู้ควบคุมอาจล้าสมัย
  • เนื่องจากนี่ไม่ใช่แอปสแต็คอย่างเป็นทางการผู้ควบคุมอาจหยุดโหลดคำตอบสำหรับคุณถ้าคุณรีสตาร์ทมากกว่า 300 ครั้งในหนึ่งวัน

ความท้าทาย "ภาคต่อ" ของBlock Building Bot Flocks!

ลิงค์ด่วน

Fiddle Controller    Fullscreen    แชททั่วไป   Red Chat    (แชทสีน้ำเงิน)    SandboxPost


51
คุณทำหน้าที่ได้ยอดเยี่ยมมาก
Alex A.

6
ทุกคนโปรดใช้การแชทเพื่อแสดงความคิดเห็นที่ไม่สำคัญ
งานอดิเรกของ Calvin

4
ทีมสีแดงกำลังประสานงานในห้องแชทนี้: chat.stackexchange.com/rooms/22548/…
Adam Davis

5
ช่วยฉันฉันรักอย่างนี้ โปรดกระจายคำให้กับนักพัฒนาทุกคนที่คุณรู้จัก
Hylianpuffball

3
@HelkaHomba Hiya! แค่อยากให้คุณรู้ว่าคอมมิวนิตี้แก้ไขคำตอบบางอย่างที่ทำให้พวกเขาแพ้
สตีเฟ่น

คำตอบ:


52

ทีมสีน้ำเงิน - 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;
    }
}

ธ ปทนี้เป็นคู่กับบอ SP3000 ของ

แนวคิดพื้นฐานคือบอทสองตัวที่อยู่ติดกันช่วยปกปิดจุดอ่อนของบอทดังนั้นบอททั้งสองจึงไม่มีด้านที่เปิดเผย สิ่งนี้จะช่วยป้องกันภัยคุกคามและ จำกัด ตัวเลือกการหลบหนีของเป้าหมาย

ในตอนต้นของเกมพวกเขานำทางไปยังแต่ละอื่น ๆ และสร้างคู่ คู่นี้จะย้ายเป็นยูนิตเดียวโดยมีบอทหนึ่งอันนำอีกอัน บอตทั้งสองมีรหัสที่เหมือนกันเกือบทุกตัวทำให้สามารถซื้อขายตำแหน่งและบทบาทได้เมื่อจำเป็น

เมื่อไม่มีการใช้งานบอทจะเคลื่อนที่ไปรอบ ๆ กระดานเพื่อค้นหาศัตรู เมื่อพวกเขาเห็นศัตรูแล้วพวกเขาก็วางแผนที่จะโจมตีอย่างถูกต้อง คุณสมบัติที่ประณีตมากคือความสามารถในการก่อตัวของการเคลื่อนที่ในแนวนอนโดยทำได้โดยให้บอตสลับตำแหน่ง


9
โอ้ที่รัก! ทันทีที่ทั้งคู่รวมตัวกันจะเป็นการสูญเสียอัตโนมัติของสีแดง
Minos

@Minos สวยมากใช่ :)
theonlygusti

ฉันคิดว่าการเขียนบอทที่คล้ายกันสำหรับสีแดง แต่ไม่ได้รับมันก่อนหน้านี้ตอนนี้ฉันต้องคิดกลยุทธ์ที่สามารถเอาชนะคู่ได้
นิตย์

สำหรับบันทึกฉันเห็นว่ามีสถานที่ที่varไม่ได้ใช้ในโพสต์นี้และของ Sp3000 พวกเขากำหนดให้jเป็น 0 ทันทีและไม่รบกวนการทำงานของตัวควบคุมเลยดังนั้นจึงไม่มีปัญหาในกรณีนี้
งานอดิเรกของ Calvin

47

ทีมสีน้ำเงิน - 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;
    }
}

ธ ปทนี้เป็นคู่กับบอ PhiNotPi ของ ดูโพสต์ของพีสำหรับคำอธิบายสั้น ๆ เกี่ยวกับกลยุทธ์ของเรา


อุ๊ย! สิ่งที่ดี ..
DoubleDouble

21

Red Team - 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;

ความสำคัญสูงสุดของ SeekerBot คือการเอาชีวิตรอด ดังนั้นจะพิจารณาเฉพาะการเคลื่อนไหวที่จะไม่ทำให้เป็นการเสี่ยงต่อการถูกฆ่าในเทิร์นถัดไป (ตราบเท่าที่การเคลื่อนไหวดังกล่าวมีอยู่)

เมื่อไม่มีฝ่ายตรงข้ามอยู่ในมุมมองมันจะเคลื่อนที่ในรูปแบบเหนือสนามรบซึ่งจะทำให้แน่ใจได้ว่าพื้นที่ส่วนใหญ่จะอยู่ในระยะมอง

หากผู้มองเห็นพบศัตรูก็จะเคลื่อนที่ไปหามัน ถ้ามันสามารถฆ่าศัตรูได้มันก็จะทำเช่นนั้นตราบใดที่การเคลื่อนไหวนั้นถูกบันทึกไว้

หากมันไม่สามารถฆ่าศัตรูได้ แต่ศัตรูอยู่ในตำแหน่งที่จะฆ่ามันได้ในเทิร์นถัดไป SeekerBot จะพยายามหลอกล่อศัตรูให้ไปหาเพื่อน (ถ้ามองไม่เห็น) หากไม่มีสมาชิกในทีมอยู่ในมุมมองก็จะพยายามย้ายเข้าไปในตำแหน่งที่สามารถฆ่าศัตรูในเทิร์นถัดไป หากสิ่งนี้ไม่ทำงาน 5 ครั้งติดต่อกันมันจะเปลี่ยนยุทธวิธีและเริ่มเคลื่อนที่ในรูปแบบสุ่มซึ่งอาจปิดศัตรูอีกครั้งในรอบถัดไป

สำหรับสิ่งที่คุ้มค่ามันจะใช้อักขระ 7 ตัวแรกของข้อความเพื่อตะโกนตำแหน่งของตนเองในรูปแบบ "x; y" (โดยที่ x และ y เป็นศูนย์เบาะ)

แน่นอนว่าไม่ใช่รหัสที่สะอาดที่สุด แต่ดูเหมือนว่าจะทำสิ่งที่ฉันคาดไว้



2
คุณได้นำทีมสีแดงขึ้นมาเพื่อชนะทุกครั้งที่ฉันวิ่ง จะน่าสนใจที่จะเห็นว่าบอทสีน้ำเงินใหม่สองอันทำอะไรกัน
Adam Davis

มันสนุกมากที่ได้ดูบลูส์สังหารคนนี้ :)
TheNumberOne

@ AdamDavis ผู้ประสานงานของบอทสีน้ำเงินสองคนนั้นเป็นคนบ้า ทุกเกมที่ฉันเคยดูมาพวกเขาได้เล่นกันแล้ว!
theonlygusti

12

ทีมสีแดง - 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;

หมายเหตุในความคิดเห็น


3
selfอย่าใช้ window.selfตัวแปรที่สงวนไว้ให้ชี้ไปที่ ใช้I(ตัวใหญ่ i) แทน meหรือ myselfหรือแม้กระทั่ง
Ismael Miguel

11

Red Team - Lazy 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;

นี่คือพื้นฐานที่สุดที่ฉันจะได้รับ สิ่งนี้ไม่เป็นพื้นฐาน 100% อีกต่อไป

มันจะย้ายถ้าจำเป็นเท่านั้น

หากผู้ใช้ส่งข้อความด้วยตัวเลข 2 หมายเลขระหว่าง-1และ1(เช่น'1,0':) คั่นด้วยเครื่องหมายจุลภาคมันจะย้ายไปที่นั่น มันเชื่อมั่นโดยสิ้นเชิงว่าเป็นเพื่อนร่วมทีม

ตอนนี้สื่อสารผ่าน JSON แล้ว มันมีโครงสร้างพื้นฐานมาก:

  • getMsg:
    • a: ยับยั้งการกระทำ:
      • 0: หยุด
      • 1: ย้าย
    • m: การเคลื่อนไหวที่จะส่ง
      • {x: n, y: n}: วัตถุที่มี x และ y ระหว่าง -1 ถึง 1
      • ค่า raw ที่จะส่งคืนพร้อมหมายเลขที่แสดงในกริด
  • setMsg:
    • a: ระบุว่ามันเคลื่อนไหวหรือหยุด
    • o: อาร์เรย์ที่มีตำแหน่งเดิมของฉัน
    • m: การเคลื่อนไหวแบบดิบที่ส่งคืนโดยโค้ด
    • id: ถ้าคำสั่งนั้นได้รับการเคารพสิ่งนี้จะมีรหัสของผู้กระทำผิด
    • e: แสดงตำแหน่งศัตรูทั้งหมด แต่ละตำแหน่งมีความเอนเอียง 32 เพื่อหลีกเลี่ยงตัวอักษรที่ไม่สามารถพิมพ์ได้ ใช้ string.charCodeAt (i) -32 เพื่อรับตำแหน่งข้าศึก นี่จะเป็นสตริงที่มีความยาวเท่ากัน ศัตรูแต่ละคนจะมี 2 ตัวอักษร

ตัวอย่างของข้อความที่จะควบคุม:

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

ซึ่งจะส่ง:

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

เขาเป็นคนเห็นแก่ตัวเช่นกัน และจะไม่ช่วยคุณ และตอนนี้เขามีประโยชน์ในฐานะสัญญาณเตือนภัยที่หยุดนิ่ง

หากข้อความนี้ไม่ถูกต้อง (รูปแบบที่ไม่เหมาะสม) ลองเพิ่มแทน"}}


สิ่งนี้ถูกแก้ไขหลังจากการ จำกัด 6 ชั่วโมงและหลังจากนั้นก็ขยายเป็น 8

มันจะไม่แตกอีกต่อไปและจะยังคงเป็นรุ่นสุดท้าย


2
ในฐานะที่เป็นคนในทีมสีแดงฉันคิดว่าสิ่งสำคัญอย่างหนึ่งที่เราควรรวมไว้คือตั้งค่าข้อความกับสถานะปัจจุบันของคุณและสิ่งรอบตัวในรูปแบบของวัตถุที่ตกลงกันไว้ (สิ่งนี้จะต้องรวมถึงสิ่งที่ย้ายไป ไม่รู้ว่ารัฐไหนล้าสมัย) สิ่งนี้จะทำให้คนอื่น ๆ บอทได้รับรู้มากกว่าสภาพแวดล้อมของพวกเขาเองอาจเป็นคณะกรรมการทั้งหมดและตัดสินใจได้ดีขึ้น
นิตย์

@Nit ฉันเห็นด้วยกับคุณและนั่นเป็นเหตุผลที่ฉันเลือกตัวเลือกนี้เพื่อใช้ JSON ในการสื่อสาร ฉันมีเวลา 5 ชั่วโมงและ 22 นาทีในการเปลี่ยนแปลง มีความคิดอื่น ๆ อีกหรือไม่
Ismael Miguel

1
ฉันคิดว่าสองสามคนแรกต้องเป็นสแกนเนอร์ เราต้องการเพียงสี่เพื่อกวาดไปทางด้านข้างเพื่อเว้าบอร์ดทั้งหมด (32 ความกว้างการสแกนที่มีประสิทธิภาพครอบคลุม 1/4 ของบอร์ด) ย้ายจากด้านหนึ่งไปอีกด้านหนึ่ง setmsg ที่ใกล้ที่สุด N คนไม่ดีโดยใช้สตริงไบนารีหรือบีบอัดและหลีกเลี่ยงคนเลวหรือค้นหาและฆ่าคนเลวโดยใช้กลยุทธ์ที่เหมาะสมเพื่อหลีกเลี่ยงการถูกฆ่าตาย (อย่าปล่อยให้พวกเขาเข้ามุมของคุณ คุณ?).
Adam Davis

1
@ IsmaelMiguel Nope ฉันหวังว่าจะส่งเร็ว ๆ นี้เช่นกัน แต่ไม่ทราบว่า Javascript ทำให้ฉันช้าลง
Adam Davis

3
หากไม่เสียให้ลบความคิดเห็นที่ล้าสมัยเพื่อลดความยุ่งเหยิง
นิตย์

10

Red Team - The Coward

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);
        }
    }
}

บอทนี้ยังคงอยู่เพื่อหลีกเลี่ยงการถูกตรวจจับมากที่สุด เมื่อมีศัตรูอยู่ในสายตาอย่างน้อยหนึ่งอย่างสามารถเกิดขึ้นได้หลายอย่าง:

  • หากมีศัตรูมากกว่าบอทและพันธมิตรของเขาในสายตาเขาพยายามที่จะหนีจากศัตรูที่ใกล้ที่สุด
  • หากมีเพื่อนในสายตามากกว่าศัตรูความเหนือกว่าที่เป็นตัวเลขจะทำให้บอทมีความกล้าหาญและพยายามที่จะออกไปและโจมตีศัตรู
  • หากเขาสามารถฆ่าศัตรูที่อยู่ข้างๆเขาจะพยายามไม่ว่าจะมีบอทศัตรูและเพื่อนมากมายกี่คนพยายามที่จะจบลงในห้องขังที่ไม่สามารถถูกบอทอื่นโจมตีได้
  • หากศัตรูทั้งหมดได้รับการคุ้มครองจากศัตรูอื่นพยายามหลบหนี
  • หากเขาไม่สามารถไปได้ทุกที่เพราะทุกตำแหน่งสามารถถูกโจมตีได้ให้เข้าสู่โหมดกามิกาเซ่และพยายามอย่างน้อยพาใครสักคนไปกับเขา

ไม่สื่อสารกับทุกคนในกรณีที่มีคนได้ยินเขาและไปตามเขา

มันอาจไม่ใช่บอทที่มีประโยชน์ที่สุดสำหรับทีม แต่มันสนุกที่ได้เห็นเขาพยายามที่จะหนีจากทุกคน


โอเคฉันรักบอทของคุณ Mine เป็นสิ่งตรงกันข้าม (มันจะค้นหาศัตรูแล้ววิ่งไปที่กึ่งกลาง) ดังนั้นพวกเขาจึงมีปฏิสัมพันธ์ที่น่าอัศจรรย์ที่เหมืองของฉันอาจพยายามแกล้งคุณออกจากมุมแล้วลากไปที่กลาง แต่ถ้าคุณเห็นใครสักคนกลัว และวิ่งกลับไปที่มุมขณะที่ฉันไล่มัน
Hylianpuffball

ขอบคุณ! ฉันคิดว่ามันตลกที่เห็นเขาโต้ตอบกับคนอื่น แต่ฉันพบข้อผิดพลาดสองสามข้อเกี่ยวกับขอบเขตและวิธีการที่จะตีกลับ แต่สายเกินไปที่จะแก้ไขพวกเขา ... ดังนั้นมันจึงไม่ดีเท่าที่ฉันต้องการ
rorlork

9

ทีมสีน้ำเงิน - อีเกิล

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;
}

ตอนนี้ฉันมีความสุขมากกับบอทของฉัน มันมีกลยุทธ์ดังต่อไปนี้:

  • หากไม่มีศัตรูอยู่รอบย้ายไปในทิศทางที่สุ่ม ถ้าฉันชนกำแพงหรือหลัง 33 รอบฉันจะเปลี่ยนทิศทาง
  • ถ้าฉันเห็นศัตรูฉันก็เข้าหาเขา (อย่างระมัดระวังที่จะไม่ย้ายไปยังเขตข้อมูลที่ศัตรูสามารถฆ่าฉัน) พอฉันเข้าใกล้พอแล้วก็ขยับไปหาเขาจากบนหรือล่างแล้วฆ่า

7

Blue team - 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);

พิกเซลเล็ก ๆ นี้มองหาศัตรูที่อยู่รอบ ๆ และพยายามที่จะกินถ้าไม่มีพิกเซลอยู่รอบ ๆ มันจะเคลื่อนที่ไปในทิศทางที่สุ่ม ฉันรอคอยที่จะเห็นสิ่งที่คนอื่น ๆ มาด้วย


ขออภัยครั้งล่าสุดที่ฉันเขียนรหัสจาวาสคริปต์เหมือนเมื่อ 2 ปีที่แล้ว
Loovjo

2
Math.floorไม่ใช่Math.float!
Jakube

1
@Jakube (Math.random() * 6) & 6หรือ(Math.random() * 6) << 0หรือ(Math.random() * 6) >> 0 (มีประโยชน์สำหรับ codegolf)
Ismael Miguel

คุณไม่จำเป็นต้องทำMath.random() * 7? ฉันได้ลองใช้การทดสอบสองสามครั้งและดูเหมือนว่าบอทของคุณไม่ไปที่ด้านล่างขวา IIRC Math.random()รวม 0 และเอกสิทธิ์ 1 ซึ่งหมายความว่า* 6ไม่เคยเป็น 6 จริง ๆ
Destrictor

1
ขอโทษทุกคนฉันดูดที่ JavaScript
Loovjo

7

ทีมสีแดง - ที่ชาร์จสีแดงที่กระวนกระวายใจ

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 จะเลื่อนไปทางซ้ายและขวาเท่านั้นหวังว่าจะใช้ประโยชน์จาก Blue Team ที่ไม่สามารถเคลื่อนที่ไปในทิศทางเหล่านั้นได้ หลังจากถึงกำแพงมันจะหมุนไปรอบ ๆ และพุ่งไปในทิศทางตรงกันข้ามโดยหวังว่าจะทำลายบ็อตใด ๆ ในเส้นทางของมัน

แก้ไข: Red Charger เพิ่งลดระดับแกลลอนเครื่องดื่มให้พลังงานและตอนนี้ไม่สามารถหยุดกระวนกระวายใจก็หวังว่าจะใช้สิ่งนี้เพื่อประโยชน์ของตน มันมีคาเฟอีนเกินกว่าที่จะฟังเพื่อนร่วมทีม แต่มันก็กรีดร้องออกมาทุกการเคลื่อนไหว


6

ทีมสีน้ำเงิน - 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;
}

โดยปกติแล้วข้อความ JSON จะมีความยาวกี่ไบต์คุณรู้หรือไม่? สามารถเก็บได้เพียง 64 ตัวอักษรแรกของข้อความ
PhiNotPi

.. ฉันลืมข้อ จำกัด ดังกล่าว: (
Dieter

ฉันคิดว่ามันจะขึ้นอยู่กับจำนวนของฝ่ายตรงข้ามเนื่องจากสตริง json รวมถึงตำแหน่งของ eminems ที่อยู่ใกล้เคียง
dieter

ฉันเปลี่ยนแปลงรูปแบบในขณะนี้
หิวโหย

1
คุณต้องใส่สิ่งนั้นลงJSON.parseในบล็อกลอง / จับหรือบางสิ่งบางอย่าง ... มันทำให้เกิดข้อผิดพลาดมากเกินไป
12Me21

6

ทีมสีน้ำเงิน - ฆาตกรมาก

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);

ฉันคิดว่าชั้นเชิงที่ค่อนข้างตรงไปตรงมา ฉันนับศัตรูที่เข้าถึงได้โดยตรงโดยฉัน (ฉันคิดว่าจะมีพวกมันมากมาย :)) และฆ่าจำนวนที่มากที่สุด หากไม่มีอย่างน้อยฉันก็จะพยายามป้องกันตัวเองโดยการเหยียบเหนือหรือต่ำกว่าจำนวนศัตรูที่ใหญ่ที่สุดที่หวังจะฆ่าพวกเขาในขั้นตอนต่อไป

ฉันเลิกคำนึงถึงกำแพงดังนั้นฉันจึงเพิกเฉยต่อมัน มันค่อนข้างยาวอยู่แล้ว

ฉันไม่สามารถทดสอบ / เรียกใช้รหัสนี้ดังนั้นจะมีข้อบกพร่องมากมาย


5

Blue Team - WatchDog

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())]);

มันจะเคลื่อนที่แบบสุ่มจนกว่าจะจับพันธมิตรถ้าเป็นเช่นนั้นจะติดตามเขา มันพยายามหลีกเลี่ยงการถูกฆ่าและฆ่าถ้าทำได้ ขออภัยสำหรับรหัสที่น่ากลัวฉันตรงไปและลืมเกี่ยวกับการปรับโครงสร้าง ฉันจะพยายามทำให้อ่านไม่ออกถ้าฉันมีเวลา :)


5

ทีมสีแดง - ผู้บัญชาการ

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;

อันนี้เป็นสำเนาของ SeekerBot ของ Minos โดยมีการดัดแปลงเล็กน้อย

  • บีบอัดหน่วยความจำภายในเพื่อการกระจายข้อความที่ดีขึ้น "$":[seekmode]

  • อ่านตำแหน่งศัตรูจากพันธมิตรโดยใช้รูปแบบ JSON ของ Lazy Slayer "e":"[positions]"; ยอมรับการ[positions]ชดเชยโดยทั้งสอง32และ174

  • รายงานตำแหน่งศัตรูในรูปแบบ JSON ของ Lazy Slayer "e":"[positions]"ชดเชยด้วย174

  • รายงานการเคลื่อนไหวครั้งสุดท้ายด้วย"m":[move]เพื่อระบุว่าบอทนี้สามารถสั่งการได้

  • คำสั่งประเด็นที่บอทอื่น ๆ "[ally_id]":{"m":[move],"a":1,"id":29354}ที่ใช้ คำสั่งใช้อัลกอริทึมผู้ค้นหาเดียวกันยกเว้นที่ตำแหน่งของพันธมิตร หากบอทคนอื่นฟังคำสั่งเหล่านี้พวกเขาควรรวมกลุ่มและล่าสัตว์เป็นชุด คำสั่งซื้อที่ให้ไว้เฉพาะเมื่อข้อความของพันธมิตรรวมถึง"m":

  • ต่อไปนี้คำสั่งจากบอทอื่น ๆ เช่น: หรือ"29354":[move] "29354":{"m":[move]มีการติดตามคำสั่งเฉพาะเมื่อไม่มีศัตรูอยู่ในระยะและไม่มีพันธมิตรรายใดรายงานถึงศัตรู


ฉันจะแนะนำการเพิ่มพิกัด 174 แทน 32. ""a":0,"o":[122,70],"m":0,"e":"f""ข้อความบางอย่างที่ฆ่าคนขี้เกียจได้รับการส่งเป็นเหมือน: คุณสามารถเข้าร่วมแชทกับเราหากคุณต้องการเช่นกัน
TheNumberOne

อนิจจาฉันไม่มีเวลา ฉันจะกลับมาตรวจสอบอีกครั้งในคืนนี้ แต่นั่นจะเป็นเช่นนั้น ฉันได้อัปเดตโพสต์เพื่อใช้การเข้ารหัส 174 ทั้งการโพสต์และการแยกวิเคราะห์
Wasmoo

5

Red Team - 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;

บอทของฉันกระเด้งจากผนังหนึ่งไปอีกกำแพง หากได้รับหนึ่งในระยะของมันโจมตี, ลากพวกเขาไปที่ผนังและพยายามที่จะนำพวกเขาออก (คิดว่าโกหกที่สโมสร)


5

ทีมสีแดง - เพื่อนสนิท

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;

ชอบติดตามเพื่อนร่วมทีมสิ่งที่ดีมีอยู่มากมาย!


ตลกที่จะต้องทราบเมื่อทีมนี้เล่นกับบอทของ Wasmoo บางครั้งก็สามารถเอาชนะคู่หูสีน้ำเงินได้
นิตย์

1
@Nit ฉันไม่ได้เห็นมัน แต่ฉันเดาว่าของฉันจะกลายเป็นสิ่งที่ทำให้ว้าวุ่นเข่นฆ่าไปฆ่าพวกเขาเหรอ? หวังว่าฉันจะเพิ่มมันในตอนนี้; ฉันจะลองทำนายหลาย ๆ รอบล่วงหน้าและดูว่าการฆ่าตัวตายแบบไหนกลยุทธ์อาจใช้ได้กับทั้งคู่
DoubleDouble

5

ทีมสีน้ำเงิน - แม่เหล็กที่เด็ดเดี่ยว

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;
        }
    }
}

มันมีกลยุทธ์หลายอย่าง: ถ้ามันสามารถเอาชนะศัตรูได้ทันทีมันจะทำเช่นนั้นและมันจะวิ่งหนีออกมาจากกลุ่มของศัตรูหากพวกเขาอยู่ไกลพออื่น ๆ ก็จะต่อสู้ นอกเหนือจากนั้นมันเป็นเพียงการมองหาสมาชิกในทีมและพยายามที่จะติดตามพวกเขา


4

Blue Team - Fetch [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;

[การแก้ไข: กลายเป็นว่าทำงานได้ดีขึ้นมากเมื่อฉันใช้รหัสจริงของฉันและไม่ใช่ -1!]

บอทเล็ก ๆ น้อย ๆ ที่วิ่งไปรอบ ๆ กระดานพยายามอย่างเต็มที่เพื่อดึงดูดความสนใจและดึงดูดผู้ไล่ล่าจากนั้นวิ่งไปที่ตรงกลาง (หวังว่า) เขาจะหาคนมาช่วยเขาหรือเขาจะหยุดล่าและหยุดเขา จากการล่าสัตว์

ดูเหมือนจะไม่ส่งผลกระทบอย่างมากต่อคะแนนโดยรวมเนื่องจากแท็กเล็ตสีน้ำเงินทรงพลัง แต่อย่างน้อยที่สุดฉันก็ไม่ได้ทำสิ่งที่แย่กว่านี้!

ตะโกนในอีก 8 ชั่วโมงข้างหน้าถ้าคุณต้องการให้ฉันเพิ่มสิ่งที่เป็นประโยชน์กับข้อความของฉัน


ตรงกลางไม่ใช่ที่ที่ดีที่สุดที่จะดึงดูดความสนใจ บอทอื่น ๆ ดูเหมือนจะวนรอบขอบเมื่อมองหาศัตรูที่จะต่อสู้ บางที ธ ปท. ของคุณควรวนกลาง?
theonlygusti

มันง่ายกว่าที่จะหลบอยู่ตรงกลางระหว่างมุม แต่ถ้าคุณพูดว่าฉันอาจไม่พบเพื่อนร่วมทีมตรงกลาง ... เอาละคุณพูดถูก สาเหตุอันดับหนึ่งของการเสียชีวิตของฉันตอนนี้คือสีแดงที่ได้รับพันธมิตรก่อนที่ฉันจะทำ สำหรับ KotH ต่อไปฉันพร้อมที่จะปรับปรุงความสามารถในการโทรหาบอตอื่น ๆ เพื่อขอความช่วยเหลือเมื่อฉันพบเป้าหมาย!
Hylianpuffball

ฉันกำลังทำงานกับบอทชื่อบีคอน มันคือผงชูรสจะมีตำแหน่งของศัตรูทุกคนและสมาชิกในทีมบนสนามและจากนั้นบอทอื่น ๆ ก็สามารถใช้เพื่อติดตามและฆ่าศัตรูที่กล่าวมา
theonlygusti

4

ทีมสีน้ำเงิน - 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);
}

รหัสคือการจัดเรียงเอกสารด้วยตนเอง สิ่งที่สามารถทำได้เพื่อปรับปรุง PatrolBot

  • Refactor - ย้ายทุกอย่างไปยัง IIFE ใช้ตัวแปรจากการปิดแทนที่จะส่งผ่านยี่สิบล้านครั้ง
  • เพิ่มif (canBeKilled() || isInWall()) { moveToBetterPosition() }ก่อนส่งคืน
  • ทำความสะอาดพฤติกรรมที่ไม่ดีเมื่อติดตามสมาชิกในทีมถัดจากกำแพง
  • หลีกเลี่ยงการลงจอดบนสมาชิกในทีม
  • ย้ายออกจากศัตรูหากเข้าร่วมอย่างต่อเนื่องเป็นเวลา 200 รอบ

นี่เป็นบอทที่ดีมาก ทำได้ดีมาก นี่คือผลลัพธ์จากการวิ่ง 100 รอบ: chat.stackexchange.com/transcript/message/20949696#20949696
PhiNotPi

2

BLUE TEAM - 1 คะแนนยอดเยี่ยม

//  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;

ลำดับความสำคัญของพิกเซล:

  • อย่าย้ายเข้าสู่พื้นที่อันตราย (นอกพื้นที่ จำกัด ถือเป็นอันตราย)
  • ฆ่าถ้าทำได้
  • ย้ายไปยังศัตรู (คนแรกใน eNear) ตราบใดที่ไม่ได้มีจำนวนมากกว่า
  • ย้ายออกจากขอบ
  • ไปที่ศัตรูที่รู้ตำแหน่งสุดท้าย
  • ไปที่ที่ตั้งของแรงโน้มถ่วง

แรงโน้มถ่วงถูกตั้งค่าเป็น 64,64 ที่การเคลื่อนไหว 1

แรงโน้มถ่วงถูกตั้งค่าไว้ที่ตำแหน่งศัตรูที่ใกล้ที่สุด (เพื่อนำทางพิกเซลไปยังตำแหน่งสุดท้ายของศัตรูหากศัตรูหลบหนี)

แรงโน้มถ่วงจะเปลี่ยนแบบสุ่มเมื่อพิกเซลมาถึงจุดศูนย์ถ่วงหรือใกล้ขอบ


2

Red - ผู้ภักดีผู้ติดตาม [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;

พยายามหา Minos และฆ่าศัตรู น่าเสียดายที่ทีมสีแดงยังคงแพ้บางทีอาจเป็นเพราะเราเป็นผู้เล่นน้อย ...


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 เป็นพี่ชายฝาแฝดของ WallFlower (ซึ่งเขาแทนที่) เหมือนพี่ชายของเขาเขาไม่ได้มีแนวโน้มที่จะเป็นคนประเภทสังคม เขาอยากออกไปเที่ยวกลางห้องดูและรอ แต่นั่นไม่ใช่การบอกว่าเขาเป็นคนขี้เกียจหรือขี้อาย ในขณะที่อยู่ในจุดของเขาหรือในทางของเขาหากเขาพบศัตรูไม่ว่าขนาดใดเขาจะเรียกเก็บเงินเพื่อรับพวกเขา เมื่อรู้ว่ามีจุดแข็งในจำนวนมากเขาจะดึงพวกเขาไปยังเพื่อนร่วมทีมที่เขาค้นพบหรืออีกทางหนึ่งเพื่อมุ่งสู่การหาผู้อื่น เมื่อธุรกิจของเขาเสร็จสิ้นเขามุ่งหน้ากลับไปที่จุดของเขาพร้อมสำหรับโอกาสต่อไปที่จะช่วยทีมของเขา

ระวังทีมสีแดง ในขณะที่เขาอาจดูเหมือนไม่มากเขาดุร้ายและติดตาเหมือนที่พวกเขามา ปรมาจารย์ด้านการต่อสู้เดี่ยวระยะประชิด เขาอาจไม่สื่อสารโดยตรงกับทีมของเขา แต่เขายอมรับพวกเขาและจะทำงานร่วมกันเพื่อกำจัดศัตรูร่วม เมื่อไม่นานมานี้เขาได้เรียนรู้วิธีการส่งข้อความถึงแม้ว่าเขาจะไม่ฟังด้วยตัวเอง แต่ก็ไม่ใช่สไตล์ของเขา รูปแบบคือสตริง JSON ที่มีอาร์เรย์ดังนี้: [[selfX,selfY],[[enemy1X,enemy1Y],[enemy2X,enemy2Y]]]และอื่น ๆ สำหรับศัตรูมากขึ้น


1

Blue Team - VersaBot เอ็นจิ้น polymorphic

รหัสของฉันจะติดตามบอทที่อยู่ใกล้ที่สุดโดยอัตโนมัติซึ่งให้อาวุธและการป้องกันเพิ่มเติม

// 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);
}

สนุก!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.