Bayrağı Ele Geçirme


12

Bu, bayrak esir alma oyunudur, büyük ilhamdan esinlenilmiştir ve Red vs. Blue - Pixel Team Battlebots'a dayanır . Bu harika bir soruydu (çok teşekkür ederim Calvin'sHobbies; Umarım senden çok fazla kod utanmadan çaldığımı umursamıyorsun) - işte başka bir takım tabanlı tepenin kralı. Umarım bayrağı yakalamak daha fazla takım işbirliğinin yanı sıra daha fazla strateji gerektirir.

Karıştırmak için, kimliğinizin son basamağı arasında 0ve 4kapsayıcıysa kırmızı takımda değerlendirilirsiniz . Bu, aynı kişiler cevap vermeye karar verirse, aynı takımların tekrar savaşmasını engellemelidir. Yönetim kurulu 350pxtarafından 350px. Mavi takım tahtanın üst yarısında başlar ve kırmızı takım alt yarısında başlar.

Bayrağı ele geçirme şekliniz şu şekildedir: Oyunun amacı rakip takımın bayrağını alıp kendi tarafınıza geri getirmektir. Onların yanındaysanız, etiketlenebilir ve hapse gönderilebilirsiniz. Hapisteyseniz, hareket edemezsiniz. Sizin tarafınızdaysanız, işiniz rakip ekip üyelerini onları hapse göndermek için etiketlemektir. Hapisten çıkmanın tek yolu, ekibinizdeki herkesi hapiste etiketlemekte özgür olan kişiler içindir. (Hapishanenin karşı takım tarafında yer aldığını unutmayın).

özellikle:

  • Sabit - FIELD_PADDING- 20 olarak ayarlanmıştır. Bu alanın doldurulmasıdır. Sıfır olsaydı, bayraklar ve hapishane tam olarak tuvalin köşelerinde olurdu. Olmadığı için, bayrak ve hapishane köşelerden 20 piksel uzakta.
  • Mavi bayrak (unutmayın: mavi takım üst yarıdadır) (WIDTH - FIELD_PADDING, FIELD_PADDING) = (330, 20)yani sağ üst köşede bulunur.
  • Kırmızı bayrak (FIELD_PADDING, HEIGHT - FIELD_PADDING) = (20, 330)
  • Mavi hapishane (kırmızı üyelerin tutulduğu yer) (20, 20)yani mavi tarafta, sol üstte.
  • Mavi üyelerin tutulduğu kırmızı hapishane (330, 330)

Her takım üyesi rastgele bir konumda başlayan 45 < x < 305ve 45 < y < 175mavi ve 175 < y < 305kırmızı için. Hiçbir takım üyesi DEFENSE_RADIUS = 25kendi bayrağının pikselleri veya kendi hapishanelerinin içine giremez (tabii ki kendi bayrağınız zıt bir bot tarafından alınmadıkça, bu durumda o botu etiketlemeniz gerekir). Bu, botlar gibi köpeklerin korunmasını önlemek içindir. Eğer o aralığa girerseniz, geri itilirsiniz. Benzer şekilde, hiçbir ekip üyesi sınır dışına çıkamaz (sıfırdan az veya 350'den fazla) - eğer yaparsanız, olabileceğiniz en yakın yasal yere geri itilirsiniz.

Her hareket ettiğinde, tükeniyorsun strength. Başlangıç strengthsaatiniz başlar 20ve 2her turda yenilenir . Kullandığınız güç miktarı seyahat ettiğiniz mesafeye eşittir. Eğer gücünüz belli bir yere taşınarak negatif hale gelirse, o hareketi yapmanız engellenir. Muhtemelen 2normal kovalamaca hızlanmak iyi bir fikirdir . Daha yüksek hızları sadece kazanmaya yakınsanız ve ekstra hıza ihtiyacınız varsa kullanmalısınız (bence).

Spec :

Spesifikasyon, Pixel Team Battlebots sorusuna oldukça benziyor. Javascript bir kod bloğu yazmalısınız (unutmayın, global değişken yok). xX'teki ve yy değerlerindeki değişikliği temsil eden bir -value ve -value değerine sahip bir nesne döndürmelidir . Aşağıdaki cevap:

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

her zaman duvara çarpana kadar yukarı hareket eder. Gönderdikten sonra 8 saat düzenleyemezsiniz (denetleyicinin kodunu yüklemediğini ve test etmediğini düşünen LegionMammal98 hariç) . Kodunuzda aşağıdaki değişkenlere erişiminiz var:

  • this - kendiniz, bir oyuncu olarak (oyuncuların ne olduğu için aşağıya bakın)
  • move - 0'dan başlayan yuvarlak sayı
  • tJailed - ekibinizdeki hapisteki tüm oyuncular dizisi
  • eJailed - rakip takımdaki hapisteki tüm oyuncular dizisi
  • team - ekibinizdeki tüm oyuncular dizisi, sadece yakınınızdakiler değil
  • enemies - sadece yakınınızdakiler DEĞİL, diğer takımdaki tüm oyunculardan oluşan bir dizi
  • tFlag - bayrağınız (onu korumaya çalışıyorsunuz)
  • eFlag - diğer bayrak (çalmaya çalışıyorsun)
  • messages - aşağıda açıklanmıştır
  • Sabitler listesi: WIDTH = 350, HEIGHT = 350, FIELD_PADDING = 20, DEFENSE_RADIUS = 25.

Her "oynatıcı" aşağıdaki özelliklere sahip bir nesnedir:

  • x ve y
  • strength
  • id
  • isJailed - oyuncu hapiste ise doğru

Her bayrak aşağıdaki özelliklere sahiptir:

  • x ve y
  • pickedUpBy - şu anda bayrağa sahip olan oyuncu veya bayrağa sahip olmayan oyuncu null.

Şimdi, messagestakım arkadaşlarınız arasında paylaşılan bir nesne. Onunla ne yaptığın umrumda değil. Aynı nesne paylaşılır ve ekip üyelerinizin her birine iletilir. İletişim kurmanın tek yolu budur. Ona özellikler ekleyebilir, nesneleri paylaşabilir, vb. İstediğiniz kadar büyük olabilir - boyut sınırı yoktur.

Her dönüşte şunlar olur:

  • Oyuncu listesi (hem kırmızı hem de mavi) dönüş sırası için rastgele karıştırılır.
  • Her oyuncu bir hamle yapar.
  • Kırmızı takım üyelerinden herhangi biri kırmızı taraftaki mavi takım üyelerine dokunursa (10 piksel içinde), mavi takım üyelerini hapse gönderir veya bunun tersi de geçerlidir. Hapisteki bir oyuncu bayrağını düşürür ve gücü sıfıra düşer. Adım işlevinin (sağladığınız kod) hala çağrıldığını unutmayın - böylece iletileri alabilir / ayarlayabilirsiniz, ancak hapishanedeyken hareket edemezsiniz.
  • Herhangi bir oyuncu diğer bayrağa dokunuyorsa (10 piksel içinde), o zaman diğer bayrak o oyuncu tarafından "alındı" olarak işaretlenir. Oyuncu hareket ettiğinde, bayrak hareket eder - oyuncu etiketlenene ve hapse girene kadar.
  • Herhangi bir oyuncu diğer tarafın hapishanesine dokunuyorsa, o hapisteki herkesi serbest bırakın. Bir oyuncu hapisten kurtulduğunda, yanında rastgele bir yere ışınlanır.

İpuçları:

  • En azından bayrağı düzenli olarak ele geçirirken, birçok oyuncu aynı anda gittiğinde saldırılar çok daha iyi çalışır, çünkü savunucuları hangi oyuncuyu kovalamaları gerektiği konusunda karıştırır.
  • Benzer şekilde, savunmacılar kovaladıkları kişileri koordine etmek isteyebilir, böylece saldırılar gerçekleşmez

Yığın snippet'i:

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>

Denetleyici: http://jsfiddle.net/prankol57/4L7fdmkk/

Tam ekran denetleyicisi: http://jsfiddle.net/prankol57/4L7fdmkk/embedded/result/

Denetleyicide herhangi bir hata olup olmadığını bana bildirin.

Not: Denetleyiciye gidip hiçbir şey yüklemediğini düşünüyorsanız, "Yeni Oyun" a basın. Sadece "Yeni Oyun" a bastıktan sonra her şeyi yükler, böylece tüm botları ve olası test botlarını aynı anda yükleyebilir.

İyi şanslar.


Birisi örnek bir oyun görmek isterse, kopyalayıp "testbot" metin alanına yapıştırabileceğiniz bir örnek bot yaptım (testbot her takımda iki kopya oluşturur; hem kırmızı takımı hem de mavi takımı kontrol edin):

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
Bunu ilk önce (hatta eşzamanlı olarak) RvB'de yaptığım gibi meta olarak bir sanal alan postası olarak göndermek isteyebilirsiniz . Bu karmaşık bir yarışma türüdür ve sizin ve başkalarının hata ayıklayabileceği bir yere sahip olmak çok yararlıdır. (Btw, kodumu kullandığınızı umursamıyorum, ancak belgelendiğini veya çok iyi organize edildiğini söyleyemem: P)
Calvin'in Hobileri

1
Tam ekran için denetleyici bağlantısını jsfiddle.net/prankol57/4L7fdmkk/embedded/result olarak değiştirirseniz çok işe yarayabilir .
LegionMammal978

2
Kontrolör en önemli parçalardan biri değil mi?
Alex

1
@AlexA Evet, ancak sanal alana göndermek, denetleyicideki hataları düzeltmeye nasıl yardımcı olur (yanıtları yüklememek, yanıtları çalıştırmak)? İnsanlar işe yarayan gerçek cevaplar göndermeye başlamak zorunda kalacaklardı, bence meta ne için değil, muhtemelen burada göndermeliyim. Hatalar kaçınılmaz olarak normal KOTH kontrolörlerinde bile ortaya çıkacaktır.
soktinpk

1
Botum denetleyicide görünmüyor.
LegionMammal978

Yanıtlar:


4

Kırmızı - Tembel Hapishane Domuzu | Tembel Bayrakçı

Bu ikisinin yakınına doğru ilerler: mavi hapishane veya mavi bayrak.

  • Hapse girecek olursan, hapse girer ve durur. (Mavi kendi hapishanesine dokunamadığından, yenilmez olacak ve tüm müttefikleri otomatik olarak serbest bırakacak)
  • Bayrağa gidiyorsanız, bayrak için körü körüne hareket edecek ve geri dönecektir.

Son olarak, beyni tamamen messages[29354]sadece ilk hamlede depolanır ve başlatılır. Böylece, eğer müttefikler bu bot için daha iyi bir kullanım bulursa, beynini daha yüksek amaçları için değiştirebilirler.

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

Kontrolör hareketler için öklid mesafesini kullanır.
TheNumberOne

4

Kızıl - Muhafız

Bu bot bayrağı oldukça iyi koruyacak. Yoluna çıkma ...

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

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

Savunma botu.


1
Javascript hakkında küçük bir şey - thisbir işlevin içinde ( forEachdöngü içinde) kullanamazsınız . Önceden bir değişken olarak kaydetmeniz (yani var _this = this;) ve kullanmanız gerekir _this. Denetleyicinin kodunuzu yüklemediğini ve test edemediğini düşündüğünüz için yakında düzenlerseniz sizi bir istisna olarak ekleyeceğim.
soktinpk

@soktinpk Sadece kullanılan forEachisteğe bağlıdır thisArg.
LegionMammal978

Denetleyiciyi, geç düzenlemiş olmanıza rağmen izin verecek şekilde güncelledim.
soktinpk

1

Kırmızı - Bayrak Avcısı

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

Bayrağı almaya çalışır. Başka biri zaten yakaladıysa, Bayrak Avcısı ya düşmanı karıştırarak ya da ekip üyelerini serbest bırakarak hapishaneye doğru yürür.


1

Mavi - Neşeli iyi bir adam

İlk olarak hem Javascript'te hem de kod golfde programlama yapmaya çalışın. Bayrağa çok yaklaşan her şeyi kovalayacak ve hamlelerini ön plana çıkarmaya çalışacak. Aksi takdirde, hapishanede takım arkadaşlarını kurtarmak için koşacak veya tembel olarak diğer takımın bayrağına ulaşmaya çalışacaktır.

// 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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.