Chụp cờ


12

Đây là một trò chơi bắt cờ, lấy cảm hứng rất nhiều và dựa trên Red vs. Blue - Pixel Team Battlebots . Đó là một câu hỏi tuyệt vời (cảm ơn bạn rất nhiều Calvin's Hy vọng, việc bắt được cờ sẽ đòi hỏi nhiều sự hợp tác của đội cũng như nhiều chiến lược hơn.

Để kết hợp nó, bạn được xem xét trong nhóm màu đỏ nếu chữ số cuối cùng của id của bạn nằm giữa 04bao gồm. Điều này sẽ ngăn các đội chính xác chiến đấu một lần nữa, nếu cùng một người quyết định trả lời. Hội đồng quản trị là 350pxbởi 350px. Đội màu xanh bắt đầu ở nửa trên của bảng và đội màu đỏ bắt đầu ở nửa dưới.

Cách bạn chơi bắt cờ như sau: đối tượng của trò chơi là lấy cờ của đội đối thủ và mang nó về phe của bạn. Nếu bạn đứng về phía họ, bạn có thể bị gắn thẻ và bị tống vào tù. Nếu bạn ở trong tù, thì bạn không thể di chuyển. Nếu bạn đứng về phía bạn, công việc của bạn là gắn thẻ các thành viên trong nhóm đối lập để tống họ vào tù. Cách duy nhất để ra khỏi tù là cho ai đó trong nhóm của bạn có thể tự do gắn thẻ mọi người trong tù. (Lưu ý rằng nhà tù nằm ở phía đối thủ).

Đặc biệt:

  • Có một hằng số - FIELD_PADDING- được đặt thành 20. Đây là phần đệm cho trường. Nếu nó bằng 0, thì cờ và tù sẽ chính xác trên các góc của khung vẽ. Vì không phải vậy, cờ và tù cách các góc 20 pixel.
  • Cờ màu xanh (nhớ: đội màu xanh nằm ở nửa trên) được đặt tại (WIDTH - FIELD_PADDING, FIELD_PADDING) = (330, 20) góc trên bên phải.
  • Cờ đỏ là tại (FIELD_PADDING, HEIGHT - FIELD_PADDING) = (20, 330)
  • Nhà tù màu xanh (nơi giữ các thành viên màu đỏ) ở (20, 20)bên cạnh màu xanh, phía trên bên trái.
  • Nhà tù đỏ, nơi giữ các thành viên màu xanh, đang ở (330, 330)

Mỗi thành viên trong nhóm bắt đầu ngẫu nhiên tại một vị trí 45 < x < 30545 < y < 175cho màu xanh và 175 < y < 305màu đỏ. Không thành viên nào trong nhóm có thể đi theo DEFENSE_RADIUS = 25pixel của cờ riêng hoặc nhà tù của riêng họ (tất nhiên trừ khi cờ của bạn bị bot đối lập lấy, trong trường hợp bạn cần gắn thẻ bot đó). Điều này là để ngăn chặn bảo vệ chó con như bot. Nếu bạn đi trong phạm vi đó, bạn sẽ bị "đẩy" lại. Tương tự, không thành viên nào trong nhóm có thể vượt ra khỏi giới hạn (dưới 0 hoặc hơn 350) - nếu bạn làm thế, bạn sẽ bị đẩy trở lại nơi hợp pháp gần nhất mà bạn có thể.

Mỗi khi bạn di chuyển, bạn sử dụng lên strength. strengthBắt đầu của bạn tại 20và được bổ sung bởi 2mỗi lượt. Lượng sức mạnh bạn sử dụng bằng với quãng đường bạn đi. Nếu sức mạnh của bạn trở nên tiêu cực bằng cách di chuyển đến một nơi nhất định, bạn sẽ bị ngăn không cho di chuyển. Có lẽ là một ý tưởng tốt để chỉ đi ở tốc độ 2cho đuổi theo bình thường. Bạn chỉ nên sử dụng tốc độ cao hơn nếu bạn gần chiến thắng và cần thêm tốc độ (theo ý kiến ​​của tôi).

Thông số :

Thông số kỹ thuật khá giống với câu hỏi Pixel Team Battlebots. Bạn nên viết một khối mã (hãy nhớ, không có biến toàn cục) trong javascript. Nó sẽ trả về một đối tượng có giá xtrị-và giá ytrị đại diện cho thay đổi của bạn trong x và thay đổi giá trị y. Câu trả lời sau:

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

luôn luôn di chuyển lên, cho đến khi nó chạm vào một bức tường. Bạn không thể chỉnh sửa 8 giờ sau khi đăng (ngoại trừ LegionMammal98, người nghĩ rằng bộ điều khiển không tải mã của mình và không kiểm tra) . Bạn có quyền truy cập vào các biến sau trong mã của mình:

  • this - chính bạn, với tư cách là một người chơi (xem bên dưới để biết người chơi là gì)
  • move - số tròn, bắt đầu từ 0
  • tJailed - một loạt tất cả người chơi trong đội của bạn bị bỏ tù
  • eJailed - một loạt tất cả người chơi trong nhóm đối thủ bị bỏ tù
  • team - một loạt tất cả người chơi trong đội của bạn, KHÔNG chỉ những người ở gần bạn
  • enemies - một loạt tất cả người chơi trong đội khác, KHÔNG chỉ những người ở gần bạn
  • tFlag - cờ của bạn (bạn đang cố bảo vệ nó)
  • eFlag - cờ khác (bạn đang cố đánh cắp nó)
  • messages - giải thích bên dưới
  • Một danh sách các hằng số: WIDTH = 350, HEIGHT = 350, FIELD_PADDING = 20, DEFENSE_RADIUS = 25.

Mỗi "người chơi" là một đối tượng có các thuộc tính sau:

  • xy
  • strength
  • id
  • isJailed - đúng nếu người chơi ở tù

Mỗi cờ có các thuộc tính sau:

  • xy
  • pickedUpBy - người chơi hiện có cờ hoặc null nếu không có người chơi nào có cờ.

Bây giờ, messageslà một đối tượng được chia sẻ giữa các đồng đội của bạn. Tôi không quan tâm bạn làm gì với nó. Cùng một đối tượng được chia sẻ và truyền cho mọi thành viên trong nhóm của bạn. Đây là cách duy nhất bạn có thể giao tiếp. Bạn có thể đính kèm các thuộc tính cho nó, chia sẻ các đối tượng, v.v. Nó có thể lớn như bạn muốn - không giới hạn kích thước.

Mỗi lượt sau đây xảy ra:

  • Danh sách người chơi (cả đỏ và xanh) được xáo trộn ngẫu nhiên theo thứ tự lần lượt.
  • Mỗi người chơi thực hiện một di chuyển.
  • Nếu bất kỳ thành viên nhóm màu đỏ nào chạm vào (trong vòng 10 pixel), bất kỳ thành viên nhóm màu xanh nào ở bên cạnh màu đỏ, hãy gửi các thành viên nhóm màu xanh vào tù và ngược lại. Một người chơi bị bỏ rơi lá cờ của mình và có sức mạnh giảm xuống không. Lưu ý rằng chức năng bước (mã bạn cung cấp) vẫn còn được gọi - vì vậy bạn có thể nhận / đặt tin nhắn, nhưng bạn không thể di chuyển trong khi ở tù.
  • Nếu bất kỳ người chơi nào chạm vào (trong vòng 10 pixel) thì cờ khác, thì cờ khác được đánh dấu là "được chọn bởi" người chơi đó. Khi người chơi di chuyển, cờ sẽ di chuyển - cho đến khi người chơi được gắn thẻ và vào tù, đó là.
  • Nếu bất kỳ người chơi nào chạm vào nhà tù khác, hãy giải phóng mọi người trong nhà tù đó. Khi một người chơi được giải thoát khỏi nhà tù, anh ta / cô ta được dịch chuyển đến một vị trí ngẫu nhiên về phía anh ta / cô ta.

Gợi ý:

  • Ít nhất là trong việc bắt giữ cờ thường xuyên, các cuộc tấn công hoạt động tốt hơn nhiều khi nhiều người chơi cùng một lúc, bởi vì nó có xu hướng gây nhầm lẫn cho những người bảo vệ rằng họ nên đuổi theo người chơi nào.
  • Tương tự như vậy, những người bảo vệ có thể muốn phối hợp những người họ đang đuổi theo để các cuộc tấn công không đi qua

Đoạn trích:

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>

Trình điều khiển: http://jsfiddle.net/prankol57/4L7fdmkk/

Bộ điều khiển toàn màn hình: http://jsfiddle.net/prankol57/4L7fdmkk/embedded/result/

Hãy cho tôi biết nếu có bất kỳ lỗi trong bộ điều khiển.

Lưu ý: Nếu bạn truy cập bộ điều khiển và nghĩ rằng nó không tải bất cứ thứ gì, hãy nhấn "Trò chơi mới". Nó chỉ tải mọi thứ sau khi bạn nhấn "Trò chơi mới" để có thể tải tất cả các bot và các bot thử nghiệm có thể cùng một lúc.

Chúc may mắn.


Nếu bất cứ ai muốn xem một trò chơi mẫu, tôi đã tạo một bot mẫu mà bạn có thể sao chép và dán vào textarea "testbot" (testbot tạo hai bản sao trên mỗi đội; kiểm tra cả đội đỏ và đội xanh):

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
Bạn có thể muốn đăng bài này trong meta dưới dạng bài đăng hộp cát trước (hoặc thậm chí đồng thời) như tôi đã làm với RvB . Đây là một loại cuộc thi phức tạp và có một nơi mà bạn và những người khác có thể gỡ lỗi là rất hữu ích. (Btw, tôi không phiền bạn sử dụng mã của tôi, mặc dù tôi không thể nói rằng nó đã được ghi chép lại hoặc thậm chí được tổ chức rất tốt: P)
Sở thích của Calvin

1
Sẽ thật tuyệt vời nếu bạn thay đổi liên kết bộ điều khiển thành jsfiddle.net/prankol57/4L7fdmkk/embedded/result cho toàn màn hình.
LegionMammal978

2
Không phải bộ điều khiển là một trong những phần quan trọng nhất ...?
Alex A.

1
@AlexA Vâng, nhưng làm thế nào để đăng nó trong hộp cát giúp sửa lỗi trong bộ điều khiển (không tải câu trả lời, chạy câu trả lời)? Mọi người sẽ phải bắt đầu đăng các câu trả lời thực tế, theo ý kiến ​​của tôi, meta này dùng để làm gì, có nghĩa là tôi có lẽ chỉ nên đăng nó ở đây. Lỗi chắc chắn sẽ xuất hiện ngay cả trong các bộ điều khiển KOTH thông thường.
soktinpk

1
Bot của tôi không xuất hiện trên bộ điều khiển.
LegionMammal978

Câu trả lời:


4

Đỏ - Nhà tù lười biếng Hog | Flagger lười biếng

Di chuyển về phía gần hơn của hai người này: nhà tù của màu xanh hoặc cờ màu xanh.

  • Nếu đi tù, sẽ chuyển vào tù và dừng lại. (Vì màu xanh không thể chạm vào nhà tù của chính nó, nó sẽ bất khả chiến bại và tự động giải phóng tất cả các đồng minh)
  • Nếu đi tìm cờ, nó sẽ di chuyển một cách mù quáng cho cờ và trở về.

Cuối cùng, bộ não của nó hoàn toàn được lưu trữ messages[29354]và khởi tạo chỉ trong lần di chuyển đầu tiên. Do đó, nếu các đồng minh tìm thấy cách sử dụng tốt hơn cho bot này, họ có thể thay thế bộ não của mình cho mục đích cao hơn.

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

Bộ điều khiển sử dụng khoảng cách euclide cho các phong trào.
TheNumberOne

4

Đỏ - Bảo vệ

Bot này sẽ bảo vệ cờ khá tốt. Đừng cản đường ...

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

Màu xanh - 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) };

Bot quốc phòng.


1
Điều nhỏ về javascript - bạn không thể sử dụng thisbên trong hàm (trong forEachvòng lặp của bạn ). Bạn phải lưu nó dưới dạng một biến trước đó (tức là var _this = this;) và sử dụng _this. Tôi sẽ thêm bạn làm ngoại lệ nếu bạn chỉnh sửa sớm vì bạn nghĩ rằng bộ điều khiển không tải mã của bạn và không thể kiểm tra.
soktinpk

@soktinpk Chỉ cần sử dụng forEachtùy chọn thisArg.
LegionMammal978

Tôi đã cập nhật bộ điều khiển để cho phép bạn mặc dù bạn đã chỉnh sửa muộn.
soktinpk

1

Thợ săn cờ đỏ

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

Cố gắng để có được cờ. Nếu ai đó đã có nó, Flag Hunter đi về phía nhà tù, hoặc gây nhầm lẫn cho kẻ thù hoặc giải thoát các thành viên trong đội của anh ta.


1

Blue - Một người bạn tốt

Đầu tiên hãy thử cả lập trình trong Javascript và tại golf-code. Nó sẽ đuổi theo bất cứ thứ gì đến quá gần cờ, cố gắng chạy trước di chuyển của chúng. Nếu không, nó sẽ chạy đến giải cứu đồng đội trong tù, hoặc lười biếng cố gắng đến cờ của đội khác.

// 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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.