ยึดธง


12

นี้เป็นเกมของการจับภาพธงแรงบันดาลใจอย่างหนักและตามออกของสีแดงกับสีน้ำเงิน - Pixel ทีม BattleBots นั่นเป็นคำถามที่ยอดเยี่ยม (ขอบคุณมาก Calvin'sHobbies ฉันหวังว่าคุณจะไม่รังเกียจว่าฉันขโมยรหัสจากคุณไปอย่างไร้ยางอาย) - นี่คือทีมจาก King-of-the-hill อีกทีมหนึ่ง หวังว่าการยึดธงจะต้องอาศัยความร่วมมือของทีมและกลยุทธ์มากขึ้น

ในการมิกซ์มันคุณจะได้รับการพิจารณาในทีมสีแดงหากตัวเลขหลักสุดท้ายของ ID ของคุณอยู่ระหว่าง0และ4รวม สิ่งนี้ควรป้องกันไม่ให้ทีมเดียวกันต่อสู้อีกครั้งหากคนคนเดียวกันตัดสินใจที่จะตอบ คณะกรรมการจะโดย350px 350pxทีมสีน้ำเงินเริ่มต้นครึ่งบนของกระดานและทีมสีแดงเริ่มครึ่งล่าง

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

โดยเฉพาะ:

  • มีค่าคงที่ - FIELD_PADDINGตั้งไว้ที่ 20 นี่คือช่องว่างภายในสำหรับเขตข้อมูล ถ้ามันเป็นศูนย์ธงและคุกก็จะอยู่ตรงมุมผ้าใบ เนื่องจากไม่ใช่ธงและคุกอยู่ห่างจากมุม 20 พิกเซล
  • ธงสีฟ้า (จำไว้ว่า: ทีมสีน้ำเงินอยู่ครึ่งบน) ตั้งอยู่ที่(WIDTH - FIELD_PADDING, FIELD_PADDING) = (330, 20)มุมบนขวา
  • ธงสีแดงอยู่ที่ (FIELD_PADDING, HEIGHT - FIELD_PADDING) = (20, 330)
  • เรือนจำสีน้ำเงิน (ซึ่งสมาชิกสีแดงจะถูกเก็บไว้) อยู่ที่(20, 20)ด้านสีน้ำเงินด้านบนซ้าย
  • คุกแดงซึ่งสมาชิกสีน้ำเงินถูกเก็บรักษาไว้อยู่ที่ (330, 330)

สมาชิกทุกคนในทีมเริ่มสุ่มที่ตำแหน่ง45 < x < 305และ45 < y < 175สำหรับสีน้ำเงินและ175 < y < 305สีแดง สมาชิกในทีมไม่สามารถเข้าไปในDEFENSE_RADIUS = 25พิกเซลของธงของพวกเขาเองหรือคุกของพวกเขาเอง (เว้นแต่แน่นอนว่าธงของคุณถูกยึดโดยบอตรงข้ามซึ่งในกรณีนี้คุณต้องติดแท็กบ็อตนั้น) นี่คือการป้องกันไม่ให้ลูกสุนัขเฝ้าเหมือนบอท หากคุณอยู่ในช่วงดังกล่าวคุณจะถูก "ดัน" กลับ ในทำนองเดียวกันสมาชิกในทีมไม่สามารถออกนอกขอบเขต (น้อยกว่าศูนย์หรือมากกว่า 350) - ถ้าคุณทำคุณจะถูกผลักกลับไปยังสถานที่ทางกฎหมายที่ใกล้ที่สุดที่คุณสามารถ

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

สเป็ค :

สเป็คค่อนข้างคล้ายกับคำถามของทีมพิกเซลบอทบอท คุณควรเขียน code block (จำไว้ว่าไม่มีตัวแปรทั่วโลก) ใน javascript มันควรจะคืนค่าออบเจกต์ด้วย - xค่าและ - yค่าแทนการเปลี่ยนแปลงของคุณใน x และเปลี่ยนค่า y คำตอบต่อไปนี้:

return {
  x: 0,
  y: -2
};

เลื่อนขึ้นเรื่อย ๆ จนกว่าจะชนกำแพง คุณไม่สามารถแก้ไข 8 ชั่วโมงหลังการโพสต์ (ยกเว้น LegionMammal98 ใครที่คิดว่าควบคุมไม่ได้โหลด / รหัสของเขาและเธอไม่ได้ทดสอบ) คุณสามารถเข้าถึงตัวแปรต่อไปนี้ในรหัสของคุณ:

  • this - ตัวคุณเองในฐานะผู้เล่น (ดูด้านล่างสำหรับสิ่งที่ผู้เล่น)
  • move - จำนวนรอบเริ่มต้นที่ 0
  • tJailed - อาร์เรย์ของผู้เล่นทั้งหมดในทีมของคุณที่ถูกจำคุก
  • eJailed - อาร์เรย์ของผู้เล่นทั้งหมดในทีมตรงข้ามที่ถูกจำคุก
  • team - อาร์เรย์ของผู้เล่นทุกคนในทีมของคุณไม่ใช่แค่คนที่อยู่ใกล้คุณ
  • enemies - อาเรย์ของผู้เล่นทุกคนในทีมอื่น ๆ ไม่ใช่แค่คนที่อยู่ใกล้คุณ
  • tFlag - ธงของคุณ (คุณกำลังพยายามปกป้องมัน)
  • eFlag - ธงอื่น ๆ (คุณกำลังพยายามขโมย)
  • messages - อธิบายไว้ด้านล่าง
  • รายการของค่าคงที่ A: WIDTH = 350, HEIGHT = 350, ,FIELD_PADDING = 20DEFENSE_RADIUS = 25

"ผู้เล่น" ทุกคนเป็นวัตถุที่มีคุณสมบัติดังต่อไปนี้:

  • x และ y
  • strength
  • id
  • isJailed - จริงหากผู้เล่นอยู่ในคุก

ทุกธงมีคุณสมบัติดังต่อไปนี้:

  • x และ y
  • pickedUpBy - ผู้เล่นที่มีสถานะปัจจุบันหรือเป็นโมฆะหากผู้เล่นไม่มีธง

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

ทุก ๆ สิ่งที่เกิดขึ้นมีดังต่อไปนี้:

  • รายชื่อผู้เล่น (ทั้งสีแดงและสีน้ำเงิน) จะถูกสุ่มสับเพื่อเปลี่ยน
  • ผู้เล่นทุกคนทำให้เคลื่อนไหว
  • หากสมาชิกทีมสีแดงใด ๆ แตะ (ภายใน 10 พิกเซล) สมาชิกทีมสีน้ำเงินใด ๆ ที่อยู่ด้านข้างสีแดงให้ส่งสมาชิกทีมสีน้ำเงินเข้าคุกและในทางกลับกัน ผู้เล่นที่ถูกจำคุกจะทิ้งธงของตนและมีความแข็งแกร่งลดลงเหลือศูนย์ โปรดทราบว่ายังมีการเรียกใช้ฟังก์ชันขั้นตอน (รหัสที่คุณให้ไว้) เพื่อให้คุณสามารถรับ / ตั้งค่าข้อความได้ แต่คุณไม่สามารถเคลื่อนที่ในขณะที่อยู่ในคุกได้
  • หากผู้เล่นคนใดแตะ (ภายใน 10 พิกเซล) ธงอื่น ๆ ธงอื่น ๆ จะถูกทำเครื่องหมายเป็น "หยิบโดย" ผู้เล่นนั้น เมื่อผู้เล่นเคลื่อนที่ธงจะขยับ - จนกว่าผู้เล่นจะถูกแท็กและเข้าคุกนั่นคือ
  • หากผู้เล่นคนใดแตะต้องคุกของอีกฝั่งให้ปล่อยตัวทุกคนในคุกนั้น เมื่อผู้เล่นถูกปล่อยตัวออกจากคุกเขา / เธอจะถูกส่งไปยังตำแหน่งสุ่มที่ด้านข้างของเขา / เธอ

คำแนะนำ:

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

ตัวอย่างสแต็ก:

window.onload=function(){(function(){function p(a,b,c,e){return Math.sqrt((a-c)*(a-c)+(b-e)*(b-e))}function l(a,b){this.x=this.y=0;this.id=a.id;this.title=a.title+" ["+this.id+"]";this.link=a.link||"javascript:;";this.team=b;this.isJailed=!1;this.flag=null;this.moveFn=new Function("move","tJailed","eJailed","team","enemies","tFlag","eFlag","messages","WIDTH","HEIGHT","FIELD_PADDING","DEFENSE_RADIUS",a.code);this.init()}function x(a,b){return Math.floor(Math.random()*(b-a))+a}function q(a,b){this.startX=this.x=a;this.startY=
this.y=b;this.following=null}function t(a,b){return a===e&&b||a===h&&!b?{x:20,y:20}:{x:g.width-20,y:g.height-20}}function y(){var a,b=$("#redTeam"),c=$("#blueTeam");for(a=0;a<e.length;++a)e[a].addToDiv(b);for(a=0;a<h.length;++a)h[a].addToDiv(c)}function z(){d.clearRect(0,0,g.width,g.height);d.beginPath();d.moveTo(0,g.height/2);d.lineTo(g.width,g.height/2);d.stroke();var a=e.concat(h),b,c;for(b=a.length-1;0<b;b--){c=Math.floor(Math.random()*(b+1));var f=a[b];a[b]=a[c];a[c]=f}for(b=0;b<a.length;++b)a[b].step(u);
for(b=0;b<e.length;++b)for(c=0;c<h.length;++c)10>p(e[b].x,e[b].y,h[c].x,h[c].y)&&(e[b].y<g.height/2&&e[b].goToJail(),h[c].y>g.height/2&&h[c].goToJail());for(b=0;b<a.length;++b)c=a[b].team===e!==!0?m:n,!c.following&&10>p(a[b].x,a[b].y,c.x,c.y)&&(c.following=a[b]);for(b=0;b<a.length;++b)if(c=t(a[b].team,!0),!a[b].isJailed&&10>p(a[b].x,a[b].y,c.x,c.y))for(c=a[b].team,f=0;f<c.length;++f)c[f].isJailed&&(c[f].isJailed=!1,c[f].init());m.follow();n.follow();b=m.y<g.height/2;c=n.y>g.height/2;b&&c&&alert("EXACT TIE!!!! This is very unlikely to happen.");
b&&!c&&(alert("Blue wins!"),$("#playpause").click().hide());c&&!b&&(alert("Red wins!"),$("#playpause").click().hide());for(b=0;b<a.length;++b)a[b].draw(d);m.draw("red");n.draw("blue");u++}$.ajaxSetup({cache:!1});var e=[],h=[],g=$("canvas")[0],d=g.getContext("2d"),v,u=0,m={},n={},r=!0,A={},B={},w;l.prototype.init=function(){this.x=x(45,g.width-45);this.y=x(45,g.height/2);this.team===e&&(this.y+=g.height/2);this.strength=20};l.prototype.makeShallowCopy=function(){return{x:this.x,y:this.y,strength:this.strength,
id:this.id,isJailed:this.isJailed}};l.prototype.goToJail=function(){this.isJailed=!0;var a=this.team===e!==!0?m:n;(this.team===e!==!0?m:n).following===this&&(a.following=null);a=t(this.team,!0);this.x=a.x;this.y=a.y;this.strength=0};l.prototype.step=function(a){function b(a,b,c){var e,d,f;for(e=0;e<a.length;++e)d=a[e],d!==C&&(f=d.makeShallowCopy(),d.isJailed?b.push(f):c.push(f))}var c=[],f=[],d=[],k=[],l=this.team===e?h:e,C=this,q=this.team===e?m:n,r=this.team===e?n:m;b(this.team,c,d);b(l,f,k);f=
this.moveFn.call(this.makeShallowCopy(),a,c,f,d,k,q.copy(),r.copy(),this.team===e?A:B,g.width,g.height,20,25);"object"===typeof f&&"number"===typeof f.x&&"number"===typeof f.y&&(d=p(0,0,f.x,f.y),a=t(this.team,!1),c=this.team===e!==!1?m:n,d<=this.strength&&(this.strength-=d,this.x+=f.x,this.y+=f.y,0>this.x&&(this.x=0),0>this.y&&(this.y=0),this.x>g.width&&(this.x=g.width),this.y>g.height&&(this.y=g.height),f=p(this.x,this.y,c.x,c.y),d=p(this.x,this.y,a.x,a.y),25>f&&null===c.following&&(this.x=25*(this.x-
c.x)/f*1.3+c.x,this.y=25*(this.y-c.y)/f*1.3+c.y),25>d&&(this.x=25*(this.x-a.x)/d*1.3+a.x,this.y=25*(this.y-a.y)/d*1.3+a.y)),this.isJailed||(this.strength+=2),20<this.strength&&(this.strength=20))};l.prototype.addToDiv=function(a){var b=$("<option>").text(this.title).val(this.id);a.find(".playersContainer").append(b)};l.prototype.draw=function(a){a.fillStyle=this.team===e?"red":"blue";a.beginPath();a.arc(this.x,this.y,5,0,2*Math.PI,!0);a.fill();!this.isJailed&&$("#labels").is(":checked")&&a.fillText(this.title,
this.x+5,this.y+10)};q.prototype.draw=function(a){d.strokeStyle=a;d.beginPath();d.arc(this.x,this.y,5,0,2*Math.PI,!0);d.stroke();d.fillStyle=a;d.strokeRect(this.x-2,this.y-2,4,2);d.beginPath();d.moveTo(this.x-2,this.y);d.lineTo(this.x-2,this.y+3);d.stroke()};q.prototype.copy=function(){return{x:this.x,y:this.y,pickedUpBy:this.following&&this.following.makeShallowCopy()}};q.prototype.follow=function(){null!==this.following&&(this.x=this.following.x,this.y=this.following.y)};$("#newgame").click(function(){function a(a,
b){w?b(w):$.get("https://api.stackexchange.com/2.2/questions/"+(49028).toString()+"/answers",{page:a.toString(),pagesize:100,order:"asc",sort:"creation",site:"codegolf",filter:"!JDuPcYJfXobC6I9Y-*EgYWAe3jP_HxmEee"},b,"json")}function b(g){w=g;g.items.forEach(function(a){function b(a){return $("<textarea>").html(a).text()}var d=4>=a.owner.user_id%10?e:h;a.owner.display_name=b(a.owner.display_name);if(!(a.hasOwnProperty("last_edit_date")&&28800<a.last_edit_date-a.creation_date&&33208!==a.owner.user_id||
-1<p.indexOf(a.owner.user_id))){p.push(a.owner.user_id);var g=c.exec(a.body);if(!(null===g||1>=g.length)){var f={};f.id=a.owner.user_id;f.title=a.owner.display_name;f.code=b(g[1]);f.link=a.link;d.push(new l(f,d))}}});g.has_more?a(++d,b):(console.log("Red team",e),console.log("Blue team",h),y(),clearInterval(v),r=!0,$("#playpause").show().click())}var c=/<pre><code>((?:\n|.)*?)\n<\/code><\/pre>/,d=1,p=[];e=[];h=[];u=0;m=new q(20,g.height-20);n=new q(g.width-20,20);$(".teamColumn select").empty();var k=
$("#testbotCode").val();0<k.length&&(console.log("Using test entry"),k={title:"TEST ENTRY",link:"javascript:;",code:k},$("#testbotIsRed").is(":checked")&&(k.id=-1,e.push(new l(k,e)),k.id=-3,e.push(new l(k,e))),$("#testbotIsBlue").is(":checked")&&(k.id=-2,h.push(new l(k,h)),k.id=-4,h.push(new l(k,h))));a(1,b)});$("#playpause").hide().click(function(){r?(v=setInterval(z,25),$(this).text("Pause")):(clearInterval(v),$(this).text("Play"));r=!r})})();}
#main{padding:10px;text-align:center}#testbot{padding:10px;clear:both}.teamColumn{width:25%;padding:0 10px;border:3px solid;border-color:#000;text-align:center;height:500px;overflow:scroll;white-space:nowrap}.playersContainer p{padding:0;margin:0}#redTeam{float:left;border-color:red;color:red;background-color:#fee}#blueTeam{float:right;border-color:#00f;color:#00f;background-color:#fee}#arena{display:inline-block;width:40%;text-align:center}canvas{border:1px solid #000}select{width:100%}
<script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script><div id=main><div class=teamColumn id=redTeam><h1>Red Team</h1><select size=20 class=playersContainer></select></div><div id=arena><h1>Battlefield</h1><canvas width=350 height=350></canvas></div><div class=teamColumn id=blueTeam><h1>Blue Team</h1><select size=20 class=playersContainer></select></div><div id=loadingInfo><button id=newgame>New Game</button> <button id=playpause>Play</button><br><input type=checkbox id="labels"> Show labels</div></div><div id=testbot><textarea id=testbotCode placeholder="testbot code"></textarea><br><input type=checkbox id="testbotIsRed">Red Team<br><input type=checkbox id="testbotIsBlue">Blue Team<br></div>

ผู้ควบคุม: http://jsfiddle.net/prankol57/4L7fdmkk/

ตัวควบคุมเต็มหน้าจอ: http://jsfiddle.net/prankol57/4L7fdmkk/embedded/result/

แจ้งให้เราทราบหากมีข้อบกพร่องใด ๆ ในตัวควบคุม

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

โชคดี.


หากใครต้องการเห็นเกมตัวอย่างฉันสร้างบอทตัวอย่างที่คุณสามารถคัดลอกและวางลงใน textarea "testbot" (testbot สร้างรายการที่ซ้ำกันสองรายการในแต่ละทีมตรวจสอบทั้งทีมสีแดงและทีมสีน้ำเงิน):

var r2 = Math.sqrt(2);
if (this.id === -1) {
  // red team 1
  // go after flag regardless of what is going on
  if (eFlag.pickedUpBy !== null && eFlag.pickedUpBy.id === this.id) {
    return {
      x: 0,
      y: 2
    };
  }
  return {
    x: this.x < eFlag.x ? r2 : -r2,
    y: this.y < eFlag.y ? r2 : -r2
  };
}
if (this.id === -2) {
  // blue team 1
  // a) go after opposing team members on your side b) get the other flag if no enemies on your side
  var closestEnemy = null;
  for (var i = 0; i < enemies.length; ++i) {
    if (enemies[i].y < HEIGHT/2 && (closestEnemy === null || enemies[i].y < closestEnemy.y)) {
      closestEnemy = enemies[i];
    }
  }
  if (closestEnemy !== null) {
    return {
      x: this.x < closestEnemy.x ? r2 : -r2,
      y: this.y < closestEnemy.y ? r2 : -r2
    };
  }
  if (eFlag.pickedUpBy !== null && eFlag.pickedUpBy.id === this.id) {
    return {
      x: 0,
      y: -2
    };
  }
  return {
    x: this.x < eFlag.x ? r2 : -r2,
    y: this.y < eFlag.y ? r2 : -r2
  };
}
if (this.id === -3) {
  // red team 2
  // a) defend the flag b) if at least half of enemies in jail and no enemies on this side, free jailed reds and quickly return
  var closestEnemy = null;
  for (var i = 0; i < enemies.length; ++i) {
    if (enemies[i].y > HEIGHT/2 && (closestEnemy === null || enemies[i].y > closestEnemy.y)) {
      closestEnemy = enemies[i];
    }
  }
  if (closestEnemy !== null) {
    return {
      x: this.x < closestEnemy.x ? r2 : -r2,
      y: this.y < closestEnemy.y ? r2 : -r2
    };
  }
  if (enemies.length / eJailed.length <= 1 && tJailed.length > 0) {
    return {
      x: this.x < FIELD_PADDING ? r2 : -r2,
      y: this.y < FIELD_PADDING ? r2 : -r2
    };
  }
  if (this.y < 350/2) return {x: 0, y: 2};
  return {
    x: this.x < tFlag.x ? r2 : -r2, 
    y: this.y < tFlag.y ? r2 : -r2
  };
}
if (this.id === -4) {
  // blue team 2
  // a) try freeing jail if there are jailed team members b) capture the flag
  if (tJailed.length > 0) {
    return {
      x: this.x < WIDTH - FIELD_PADDING ? r2 : -r2,
      y: this.y < HEIGHT - FIELD_PADDING ? r2 : -r2
    };
  }
  if (eFlag.pickedUpBy !== null && eFlag.pickedUpBy.id === this.id) {
    return {
      x: 0,
      y: -2
    };
  }
  return {
    x: this.x < eFlag.x ? r2 : -r2,
    y: this.y < eFlag.y ? r2 : -r2
  };
}

8
คุณอาจต้องการที่จะโพสต์นี้ในเมตาเป็นโพสต์ Sandbox แรก (หรือแม้กระทั่งพร้อมกัน) เช่นผมกับ RVB มันเป็นประเภทของการแข่งขันที่ซับซ้อนและการมีสถานที่ที่คุณและผู้อื่นสามารถแก้ไขข้อบกพร่องนั้นมีประโยชน์มาก (Btw ฉันไม่รังเกียจที่คุณใช้รหัสของฉันแม้ว่าฉันไม่สามารถพูดได้ว่ามันเป็นเอกสารหรือจัดได้ดีมาก: P)
งานอดิเรกของ Calvin

1
มันจะเป็นการพักครึ่งหากคุณเปลี่ยนลิงค์ควบคุมเป็นjsfiddle.net/prankol57/4L7fdmkk/embedded/resultสำหรับเต็มหน้าจอ
LegionMammal978

2
ตัวควบคุมไม่ใช่หนึ่งในส่วนที่สำคัญที่สุดใช่ไหม
Alex A.

1
@AlexA ใช่ แต่จะโพสต์ไว้ในแซนด์บ็อกซ์ช่วยแก้ไขข้อบกพร่องในคอนโทรลเลอร์ได้อย่างไร (ไม่โหลดคำตอบวิ่งคำตอบ) ผู้คนจะต้องเริ่มโพสต์คำตอบจริงที่ใช้งานซึ่งในความคิดของฉันไม่ได้ใช้เมตาอะไรซึ่งหมายความว่าฉันควรจะโพสต์ไว้ที่นี่ ข้อบกพร่องจะเกิดขึ้นอย่างหลีกเลี่ยงไม่ได้แม้จะอยู่ในตัวควบคุม KOTH ปกติ
soktinpk

1
บอทของฉันไม่ปรากฏบนคอนโทรลเลอร์
LegionMammal978

คำตอบ:


4

สีแดง - คุกขี้เกียจ ขี้เกียจ Flagger

เคลื่อนไปสู่จุดที่ใกล้ที่สุดของทั้งสองนี้: คุกของสีน้ำเงินหรือธงของสีน้ำเงิน

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

ในที่สุดสมองของมันจะถูกเก็บไว้ในmessages[29354]และเริ่มต้นในการย้ายครั้งแรกเท่านั้น ดังนั้นหากพันธมิตรพบว่าการใช้บอทนี้ดีขึ้นพวกเขาสามารถแทนที่สมองของมันเพื่อจุดประสงค์ที่สูงขึ้น

if (move === 0) {
    //On the first turn, set messages[this.id] to the function I will call to move me
    messages[this.id] = function(move, tJailed, eJailed, team, enemies, tFlag, eFlag, messages) {
        //Arbitrary function to move to a point at some speed, which may be in the point
        //  If we are at the point, undefined is returned
        var moveTo = function(p, max) {
            if (!p) {
                return {x:0, y:0};
            }
            max = Math.min(this.strength, max || p.max || 2);
            var dx = p.x - this.x;
            var dy = p.y - this.y;
            var dist = Math.abs(dx)+Math.abs(dy);
            if (dist === 0) {
                return undefined; 
            } else if (dist < max) {
                return {x: dx, y: dy};
            }
            var ux = Math.floor(max * dx / dist);
            var uy = Math.floor(max * dy / dist);
            while (Math.abs(ux) + Math.abs(uy) < max) {
                if (ux + this.x !== p.x) {
                    ux += ux > 0 ? 1 : -1;
                } else if (uy + this.y !== p.y) {
                    uy += uy > 0 ? 1 : -1;
                } else {
                    break;
                }
            }
            return {x: ux, y:uy};
        }.bind(this);

        //Set the way points
        var points = [];
        if (this.x > WIDTH/2) {
            points.push({x: WIDTH-FIELD_PADDING, y:HEIGHT/2+5});
            points.push({x: WIDTH-FIELD_PADDING, y:FIELD_PADDING, max: 5});
            points.push({x: WIDTH-FIELD_PADDING, y:HEIGHT/2+25, max: 5});
        } else {
            points.push({x: FIELD_PADDING, y:HEIGHT/2+5});
            points.push({x: FIELD_PADDING, y:FIELD_PADDING, max: 5});
            points.push(undefined); //Special case to do nothing / hog the jail
        }

        //Move through the points
        var state = messages[this.id].state || 0;
        var ret;
        while (!ret) {
            //Special case: if we were doing nothing, make sure we're where we think we were
            if (!points[state]) {
                ret = moveTo(points[state-1]);
                if (ret) {
                    state = 0;
                }
            }

            //Move to the next point
            ret = moveTo(points[state]);
            if (!ret) {
                state = (state + 1) % points.length;
            }
        }
        messages[this.id].state = state;
        return ret;
    };
}
//Move me based on that function, which may be changed by my allies
return messages[this.id].call(this, move, tJailed, eJailed, team, enemies, tFlag, eFlag, messages);

ตัวควบคุมใช้ระยะทางแบบยุคลิดสำหรับการเคลื่อนไหว
TheNumberOne

4

แดง - ยาม

บอทนี้จะปกป้องธงสวยดี อย่าเข้าไปขวาง ...

if (!messages[this.id]) {
    //On the first turn, set messages[this.id] to the function I will call to move me. You can replace this function on subsequent turns
    //to control it. Additionally, you can use it as a library to find one of the best places to go to defend.
    messages[this.id] = function(move, tJailed, eJailed, team, enemies, tFlag, eFlag, messages, WIDTH, HEIGHT, FIELD_PADDING, DEFENSE_RADIUS) {
        var distance = function(p1, p2) {
            var dx = p1.x - p2.x;
            var dy = p1.y - p2.y;
            return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
        }

        var moveTo = function(p) {
            if (!p) {
                return {x:0, y:0};
            }
            var dx = p.x - this.x;
            var dy = p.y - this.y;
            var max = this.strength;
            var dist = distance(p, this);
            if (dist < max) {
                return {x: dx, y: dy};
            }
            dx = dx * max / dist;
            dy = dy * max / dist;
            while (Math.sqrt(Math.abs(dx)+Math.abs(dy)) > max) {
                if (dx > dy) {
                    dx = dx - 0.001;
                } else {
                    dy = dy - 0.001;
                }
            }
            return {x: dx, y:dy};
        }.bind(this);

        if (tFlag.pickedUp) {
            if (tFlag.y - HEIGHT / 2 > distance(this, {x: tFlag.x, y: HEIGHT / 2})) {
                return moveTo(tFlag);
            } else {
                return moveTo({y: Math.min(this.y, tFlag.y), x: tFlag.x });
            }
        }

        if (eFlag.pickedUp == this.id) {
            return moveTo({x: x, y: HEIGHT / 2});            
        }

        var targetPoints = [];
        var crossedBorder = false;

        var weightedMiddlePoint = function(enemy) {
            var x1 = (enemy.x + tFlag.x) / 2;
            var y1 = (enemy.y + tFlag.y) / 2;
            var w = 1/Math.pow(distance(enemy, tFlag),2);
            return {x:x1,y:y1,w:w};
        }

        for (var i = 0; i < enemies.length; i++) {
            var enemy = enemies[i];
            if (enemy.isJailed){
                continue;
            }
            if (enemy.y > HEIGHT / 2) {
                crossedBorder = true;
            }
        }

        for (var i = 0; i < enemies.length; i++) {
            enemy = enemies[i];
            if (enemy.isJailed){
                continue;
            }
            if (crossedBorder) {
                if (enemy.y > HEIGHT / 2) {
                    targetPoints.push(weightedMiddlePoint(enemy));
                }
            } else {
                targetPoints.push(weightedMiddlePoint(enemy));
            }
        }

        if (targetPoints.length == 0) {
            return moveTo(eFlag);
        }

        var sumX = 0;
        var sumY = 0;
        var sumW = 0;

        for (var i = 0; i < targetPoints.length; i++) {
            point = targetPoints[i];
            sumX += point.x * point.w;
            sumY += point.y * point.w;
            sumW += point.w;
        }

        var targetPoint = {x: sumX / sumW, y: sumY / sumW};

        return moveTo(targetPoint);

    };
}

return messages[this.id].call(this, move, tJailed, eJailed, team, enemies, tFlag, eFlag, messages, WIDTH, HEIGHT, FIELD_PADDING, DEFENSE_RADIUS);

4

น้ำเงิน - LegionMammal978

function repeat(el, n) // Helper function
{
    var rtn = [];
    for (var i = 0; i < n; i++)
        rtn.push(el);
    return rtn;
}
function sign(n) { return n ? n < 0 ? -1 : 1 : 0; } // Another helper function
if (!messages[this.id])
    messages[this.id] = { "dir": 1 };
if (this.isJailed) // Oh noes, I'm in jail!
{
    console.log(this.id, messages);
    if (!messages[this.id].jailTicks)
        messages[this.id].jailTicks = 0;
    messages[this.id].jailTicks++;
    // Call for help!
    messages.callsForHelp = repeat(["Help!", this.id, this.x, this.y], messages[this.id].jailTicks);
    return { "x": 0, "y": 0 };
}
if (messages[this.id].jailTicks)
    if (!(delete messages[this.id].jailTicks && delete messages.callsForHelp)) // Cleanliness
        messages[this.id].jailTicks = messages.callsForHelp = undefined;       // ...
var bounds = Math.floor(HEIGHT / 2); // Be safe with fractions
if (this.y > bounds - 5) // Get back to shelter!
    return { "x": 0, "y": this.y - this.strength <= bounds - 5 ? bounds - 5 - this.y : -4 };
var target = { "none": true, "x": WIDTH << 1, "y": HEIGHT << 1 };
enemies.forEach(function (en) { if (!en.isJailed && en.y < bounds - 5 && Math.abs(en.x - this.x) < Math.abs(target.x - this.x) && Math.abs(en.y - this.y) < Math.abs(target.y - this.y)) target = en; }, this);
if (target.none)
{
    if (this.y < bounds - 5)
        return { "x": 0, "y": 2 };
    var speed = this.strength < 30 ? 1 : 2;
    if (this.x == 5 || this.x == WIDTH - 5)
        messages[this.id].dir = -messages[this.id].dir;
    return { "x": speed * messages[this.id].dir, "y": 0 };
}
if (this.x - target.x >= 0 && this.x - target.x < this.strength)
{
    if (this.y - target.y > 0 && this.y - target.y < this.strength + target.x - this.x)
        return { "x": this.x - target.x, "y": this.y - target.y };
    if (target.y - this.y > 0 && target.y - this.y < this.strength + target.x - this.x)
        return { "x": this.x - target.x, "y": target.y - this.y };
}
if (target.x - this.x > 0 && target.x - this.x < this.strength)
{
    if (this.y - target.y > 0 && this.y - target.y < this.strength + this.x - target.x)
        return { "x": target.x - this.x, "y": this.y - target.y };
    if (target.y - this.y > 0 && target.y - this.y < this.strength + this.x - target.x)
        return { "x": target.x - this.x, "y": this.y - target.y };
}
return { "x": 6 * sign(target.x - this.x), "y": 6 * sign(target.y - this.y) };

บอทป้องกัน


1
สิ่งเล็ก ๆ น้อย ๆ เกี่ยวกับ javascript - คุณไม่สามารถใช้thisภายในฟังก์ชัน (ในforEachลูปของคุณ) คุณจะต้องบันทึกเป็นตัวแปรก่อน (คือvar _this = this;) _thisและการใช้งาน ฉันจะเพิ่มคุณเป็นข้อยกเว้นหากคุณแก้ไขในไม่ช้าเพราะคุณคิดว่าตัวควบคุมไม่ได้โหลดรหัสของคุณและไม่สามารถทดสอบได้
soktinpk

@soktinpk เพียงใช้forEach's thisArgตัวเลือก
LegionMammal978

ฉันอัปเดตคอนโทรลเลอร์เพื่อให้คุณสามารถแก้ไขได้แม้ว่าคุณจะมาช้า
soktinpk

1

แดง - นักล่าธง

var distance = function(x1, y1, x2, y2) {
    return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
var moveTo = function(x, y, max) {
    if (max > this.strength)
        max = this.strength;
    var dX = x - this.x;
    var dY = y - this.y;
    var dist = distance(x, y, this.x, this.y);
    if (dist <= max) {
        return {x: dX, y: dY};
    }
    dX = dX * max / dist;
    dY = dY * max / dist;
    while (Math.sqrt(Math.abs(dX)+Math.abs(dY)) > max) {
        if (dX > dY) {
            dX = dX - 0.001;
        } else {
            dY = dY - 0.001;
        }
    }
    return {x: dX, y:dY};
}.bind(this);

var getSurroundingPoints = function(x, y, dist) {
    var points = [];
    for (var i = x - dist; i <= x + dist; i+= 0.2) {
        for (var j = y - dist; j <= y + dist; j+= 0.2) {
            if (i >= 0 && j >= 0 && j <= 180 && distance(i,j,x,y) <= dist) {
                points.push({x: i, y: j, danger: 0});
            }
        }
    }
    return points;
}

if (this.isJailed) {
    return {x:0, y:0};
}

var destination = {x: eFlag.x, y: eFlag.y}; //default: try to get the flag
if (eFlag.pickedUpBy != null) { //we got the flag
    if (eFlag.pickedUpBy.id == this.id) { //I got the flag => get back to the red side
        if (distance(this.x, this.y, this.x, 175.1) <= this.strength) {
            return moveTo(this.x, 175.1, this.strength);
        }
        destination.x = this.x;
        destination.y = 180;
    } else { //someone else got the flag => free those in the jail
        destination.x = 20;
        destination.y = 20;
    }
} else if (this.y > HEIGHT / 2) { //I am on the red side
    return moveTo(175, 175, 2);
} else if (distance(this.x, this.y, eFlag.x, eFlag.y) <= 15)  { //I am in the safe zone (flag)
    if (this.strength < 20)
        return {x:0, y:0};
    return moveTo(eFlag.x, eFlag.y, 2); //get the flag
} else if (distance(this.x, this.y, eFlag.x, eFlag.y) - this.strength <= 15)  { //I can reach the safe zone (flag)
    return moveTo(eFlag.x, eFlag.y, distance(this.x, this.y, eFlag.x, eFlag.y) - 14);
} else if (distance(this.x, this.y, 20, 20) < 10)  { //I am in the safe zone (jail)
    if (this.strength < 20)
        return {x:0, y:0};
} else if (distance(this.x, this.y, eFlag.x, eFlag.y) - this.strength <= 15)  { //I can reach the safe zone (jail)
    return moveTo(20, 20, this.strength);
}

//I am somewhere on the blue side
var points = getSurroundingPoints(this.x, this.y, this.strength);
var me = this;
points.forEach(function(point) {
    if (point.y < 175) {
        enemies.forEach(function(enemy) {
            if (distance(enemy.x, enemy.y, point.x, point.y) <= enemy.strength+10) {
                point.danger += 5;
            }
        });
        if (distance(me.x, me.y, point.x, point.y) <= 2 && point.danger == 0) {
            point.danger--;
        }
    }
});
var bestPoint = points[0];
points.forEach(function(point) {
    if (point.danger < bestPoint.danger || (point.danger == bestPoint.danger && distance(point.x, point.y, destination.x, destination.y) < distance(bestPoint.x, bestPoint.y, destination.x, destination.y))) {
        bestPoint = point;
    }
});
return moveTo(bestPoint.x, bestPoint.y, this.strength);

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


1

น้ำเงิน - เป็นคนดีร่าเริง

ความพยายามครั้งแรกทั้งที่การเขียนโปรแกรมใน Javascript และที่ code-golf มันจะไล่ล่าทุกสิ่งที่เข้ามาใกล้ธงเกินไปพยายามวิ่งไปข้างหน้า ไม่เช่นนั้นมันจะวิ่งไปช่วยเพื่อนร่วมทีมในคุกหรือพยายามที่จะไปที่ธงของทีมอื่นอย่างเกียจคร้าน

// Euclidean distance
var distance = function(p1,p2){
 return Math.sqrt( (p1.x - p2.x)**2 + (p1.y - p2.y)**2 );
}

// points from p1 to p2
var direction = function(p1, p2){
 return Math.atan2( p2.y - p1.y, p2.x - p1.x);
}

//moving
var move2 = function(dir, step){
    if(isNaN(dir)){   dir = 0; };
    if(isNaN(step)){ step = 0; };
    return {
        x: Math.cos(dir)*step,
        y: Math.sin(dir)*step
    };
}


var intercept_at = function(me, they, field){
    if ( distance(me, they)<me.strength ){
        return they;
    }

    //console.log("I am at (", me.x, me.y, ") ");
    //console.log("They are at (", they.x, they.y, ") ");           


    //first goal
    if( field.my_flag.pickedUpBy == null ){
        their_goal = field.my_flag;
        eta = (distance(they, their_goal) - they.strength)/2;
        their_dir = direction(they, their_goal);
        for( var i=1; i<eta; i++){
          they_next = {
            x: they.x + Math.cos(their_dir)*(they.strength/2 + (i+1)*2),
            y: they.y + Math.sin(their_dir)*(they.strength/2 + (i+1)*2)
          };
          if( (distance(me, they_next) )<(1.95*i) ){
            //console.log("goal is flag at (", their_goal.x, their_goal.y, ") ");   
            //console.log("I can reach it at (", they_next.x, they_next.y, ") in less than ", i);
            return they_next;
          }
        }
    // second goal  
    }

    my_flag = field.my_flag;
    their_goal = { x: my_flag.x, y:field.h/2 - 5};
    eta = (distance(my_flag, their_goal) - they.strength)/2;
    their_dir = direction(my_flag, their_goal);
    for( var i=0; i<eta; i++){
        they_next = {
            x: my_flag.x + Math.cos(their_dir)*(they.strength/2 + (i+1)*2),
            y: my_flag.y + Math.sin(their_dir)*(they.strength/2 + (i+1)*2)
        };
        if( (distance(me, they_next) )<(1.95*i) ){
            //console.log("goal is escaping at (", their_goal.x, their_goal.y, ") "); 
            //console.log("I can front-run it at (", they_next.x, they_next.y, ") in less than ", i);
            return they_next;
        }       
    }
    //console.log("Goose chase at (", they.x, they.y, ") ");
    return they;
}

var intercept = function(me, they, field){
  they_at = intercept_at(me, they, field);
  they_at.y = Math.min(they_at.y, field.h/2-5)
  dist2me = distance(me, they_at);
  dir2me = direction(me, they_at);  
  if ( dist2me<me.strength ){
    return move2(dir2me, dist2me);
  }else{
    return move2(dir2me, 2);
  }
}


var closest_enemy = function(my_flag, enemies){
    cur_tgt_num = null;
    cur_tgt_dst = 999;

    for( var i=0; i<enemies.length; i++){
      if(!enemies[i].isJailed){
        cur_dst = distance(enemies[i], my_flag);
        if ( cur_dst < cur_tgt_dst ){
          cur_tgt_dst = cur_dst;
          cur_tgt_num = i;
        }
      }
    }    

    return enemies[cur_tgt_num];
}


var enemies_closer_than = function(enemies, radius, field){
    closer_than = 0;
    for( var i = 0; i<enemies.length; i++){
        if(!enemies[i].isJailed){
            closer_than = closer_than + ( distance(enemies[i], field.my_flag)<radius );
        }
    }
    return closer_than;
}


var team_jailed = function(team){
    for( var i = 0; i<team.length; i++){
        if(team[i].isJailed){
            return team[i];
        }
    }
    return null;
}


var bound_positions = function(p0, field){
    p0.x = Math.max(0, Math.min(p0.x, field.w));
    p0.y = Math.max(0, Math.min(p0.y, field.h));    
    return p0;
}

var avoid_obstacle = function(me, goal, obstacle, field, can_run){
    //we know that there is a safe haven
    if( distance(me, goal)<me.strength && can_run){
        return move2(direction(me, goal), me.strength)
    }

    if( obstacle == null ){
        return move2(direction(me, goal), 2);
    }

    ob_dir = direction(me, obstacle);
    if( distance(me, obstacle) < Math.sqrt(2)*(4+obstacle.strength)){
        me_next1 = bound_positions({x: me.x - 4*Math.cos(ob_dir),y: me.y - 4*Math.sin(ob_dir)}, field);
        me_next2 = bound_positions({x: me.x - 4*Math.sin(ob_dir),y: me.y - 4*Math.cos(ob_dir)}, field);
        me_next3 = bound_positions({x: me.x - 4*Math.sin(ob_dir),y: me.y - 4*Math.cos(ob_dir)}, field);
        if( distance(goal, me_next1) < distance(goal, me_next2) ){
          if( distance(goal, me_next1) < distance(goal, me_next3) ){
            me_next = me_next1;
          }else{
            me_next = me_next3;
          }
        }else{
          if( distance(goal, me_next2) < distance(goal, me_next3) ){
            me_next = me_next2;
          }else{
            me_next = me_next3;
          }
        }           

        //console.log("Escaping from (", obstacle.x, obstacle.y, ")");
        return move2(direction(me, me_next), 4);
    }

    eta = (distance(me, goal)/2);
    my_dir = direction(me, goal);
    me_next = me;
    i=0;
    while(i<eta && (distance(me_next, obstacle) > obstacle.strength+2*i)){
       i++;
       me_next = {x: me_next.x + i*Math.cos(my_dir),y: me_next.y + i*Math.sin(my_dir)};
       me_next = bound_positions(me_next, field);
       if( distance(me_next, obstacle) < obstacle.strength+2*i ){
         me_next1 = {x: me_next.x + i*Math.sin(ob_dir),y: me_next.y - i*Math.cos(ob_dir)};
         me_next2 = {x: me_next.x - i*Math.sin(ob_dir),y: me_next.y + i*Math.cos(ob_dir)};
         if( distance(goal, me_next1) > distance(goal, me_next2) ){
            me_next = bound_positions(me_next2, field);
         }else{
            me_next = bound_positions(me_next1, field);
         }
       }
    }
    if( distance(me_next, obstacle) > obstacle.strength+2*i ){
        //console.log("Trying to reach goal at (", goal.x, goal.y, ") by pointing at (",me_next.x, me_next.y,")");      
        return move2(direction(me, me_next), 2);
    }

    //console.log("Waiting to reach (", goal.x, goal.y,")");
    my_dir = direction(me, goal);
    me_next = {
        x: me.x + Math.cos(my_dir)*6,
        y: me.y + Math.sin(my_dir)*6
    }
    for( var i=0; i<field.team.length; i++){
        me_next.x = me_next.x - Math.sign(field.team[i].x - me_next.x);
        me_next.y = me_next.y - Math.sign(field.team[i].y - me_next.y);
    }               
    return move2(direction(me, me_next), Math.floor(Math.random() * 2));
}


var field = {
    w: WIDTH, 
    h: HEIGHT, 
    g: DEFENSE_RADIUS,
    my_flag: tFlag,
    their_flag: eFlag,
    team: team,
    enemies: enemies
    };

var n_enemy = enemies.length;


  if( enemies_closer_than(enemies, field.h*0.67, field)>0 || tFlag.pickedUpBy !== null){
    //console.log("My flag is in danger");      

    // directive defend
    messages[123 + this.id] = 'defend_own_flag';
    if ( tFlag.pickedUpBy !== null ) {
      return intercept(this, tFlag.pickedUpBy, field);
    }else{
      return intercept(this, closest_enemy(tFlag, enemies), field);
    }   
  }else{

    if( tJailed.length>0 ){

        // directive support
        console.log("rescueing team member");
        console.log(tJailed);
        return avoid_obstacle(this, tJailed[0], closest_enemy(this, enemies), field, 0);
    }else{

      // directive attack
      messages[123 + this.id] = 'capture_enemy_flag';
      if ( eFlag.pickedUpBy == null ){
        //console.log("Going to capture the flag");
        return avoid_obstacle(this, eFlag, closest_enemy(this, enemies), field, 0)

      }else if (this.id == eFlag.pickedUpBy.id){
        //console.log("I have the flag");
        return avoid_obstacle(this, {x:this.x, y:field.h/2 - 1}, closest_enemy(this, enemies), field, 1);      

      }else {
        //console.log("Someone else has the flag");
        return avoid_obstacle(this, eFlag, closest_enemy(this, enemies), field, 0);

      }
    }
  }

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