Jest to gra polegająca na zdobyciu flagi, mocno inspirowana i oparta na grze Red vs. Blue - Pixel Team Battlebots . To było niesamowite pytanie (bardzo dziękuję hobby Calvina; mam nadzieję, że nie masz nic przeciwko temu, że bezwstydnie ukradłem ci dużo kodu) - oto inny oparty na drużynie król wzgórza. Mamy nadzieję, że zdobycie flagi będzie wymagało większej współpracy zespołu i strategii.
Aby to pomieszać, jesteś brany pod uwagę w czerwonej drużynie, jeśli ostatnia cyfra Twojego identyfikatora znajduje się pomiędzy 0i 4włącznie. To powinno zapobiec ponownej walce dokładnie tych samych drużyn, jeśli te same osoby zdecydują się odpowiedzieć. Zarząd jest 350pxprzez 350px. Drużyna niebieska zaczyna od górnej połowy planszy, a drużyna czerwona zaczyna od dolnej połowy.
Sposób, w jaki grasz w zdobywanie flagi, jest następujący: celem gry jest wzięcie flagi drużyny przeciwnej i przywrócenie jej na swoją stronę. Jeśli jesteś po ich stronie, możesz zostać oznaczony i wysłany do więzienia. Jeśli jesteś w więzieniu, nie możesz się ruszyć. Jeśli jesteś po twojej stronie, Twoim zadaniem jest oznaczenie przeciwnych członków zespołu, aby wysłali ich do więzienia. Jedynym sposobem na wyjście z więzienia jest osoba z twojego zespołu, która może dowolnie oznaczać wszystkich w więzieniu. (Pamiętaj, że więzienie znajduje się po stronie drużyny przeciwnej).
Konkretnie:
- Jest stała -
FIELD_PADDINGustawiona na 20. Jest to wypełnienie pola. Gdyby było zero, flagi i więzienie byłyby dokładnie na rogach płótna. Ponieważ tak nie jest, flaga i więzienie znajdują się 20 pikseli od rogów. - Niebieska flaga (pamiętaj: niebieska drużyna znajduje się w górnej połowie) znajduje się
(WIDTH - FIELD_PADDING, FIELD_PADDING) = (330, 20)np. W prawym górnym rogu. - Czerwona flaga jest na
(FIELD_PADDING, HEIGHT - FIELD_PADDING) = (20, 330) - Niebieskie więzienie (w którym przebywają czerwoni członkowie) znajduje się po
(20, 20)stronie niebieskiej, w lewym górnym rogu. - Czerwone więzienie, w którym przebywają niebiescy członkowie, znajduje się w
(330, 330)
Każdy członek drużyny zaczyna losowo na pozycji 45 < x < 305i 45 < y < 175na niebiesko i 175 < y < 305na czerwono. Żaden członek zespołu nie może przejść w odległości kilku DEFENSE_RADIUS = 25pikseli od własnej flagi lub własnego więzienia (chyba że twoja flaga została przejęta przez przeciwnego bota, w którym to przypadku musisz oznaczyć tego bota). Ma to na celu zapobieganie pilnowaniu szczeniaków jak boty. Jeśli przekroczysz ten zakres, zostaniesz „wypchnięty” z powrotem. Podobnie, żaden członek zespołu nie może wyjść poza granice (mniej niż zero lub więcej niż 350) - jeśli to zrobisz, zostaniesz zepchnięty z powrotem do najbliższego legalnego miejsca, w którym możesz być.
Za każdym razem, gdy się poruszasz, zużywasz strength. Twój strengthzaczyna się o 20i jest uzupełniany za 2każdym razem. Użyta siła jest równa odległości, którą pokonujesz. Jeśli twoja siła stałaby się ujemna przez przeniesienie się w określone miejsce, nie możesz tego zrobić. Prawdopodobnie dobrym pomysłem jest po prostu przyśpieszenie 2do normalnego ścigania. Powinieneś używać wyższych prędkości tylko wtedy, gdy jesteś blisko wygranej i potrzebujesz dodatkowej prędkości (moim zdaniem).
Specyfikacja :
Specyfikacja jest dość podobna do pytania Pixel Team Battlebots. Powinieneś napisać blok kodu (pamiętaj, że nie ma zmiennych globalnych) w javascript. Powinien zwrócić obiekt z x-wartością i y-wartością reprezentującą zmianę x oraz zmianę wartości y. Następująca odpowiedź:
return {
x: 0,
y: -2
};
zawsze porusza się w górę, aż uderzy w ścianę. Nie możesz edytować 8 godzin po opublikowaniu (z wyjątkiem LegionMammal98, który uważał, że kontroler nie ładuje swojego kodu i nie testował) . Masz dostęp do następujących zmiennych w kodzie:
this- ty, jako gracz (patrz poniżej, kim są gracze)move- okrągły numer, zaczynający się od 0tJailed- tablica wszystkich graczy w drużynie, którzy zostali uwięzienieJailed- tablica wszystkich graczy w drużynie przeciwnej, którzy zostali uwięzieniteam- tablica wszystkich graczy w twoim zespole, NIE TYLKO tych w pobliżuenemies- tablica wszystkich graczy z drugiej drużyny, NIE tylko tych z Twojej okolicytFlag- twoja flaga (próbujesz ją chronić)eFlag- druga flaga (próbujesz ją ukraść)messages- wyjaśniono poniżej- Lista stałych:
WIDTH = 350,HEIGHT = 350,FIELD_PADDING = 20,DEFENSE_RADIUS = 25.
Każdy „gracz” jest obiektem o następujących właściwościach:
xiystrengthidisJailed- prawda, jeśli gracz jest w więzieniu
Każda flaga ma następujące właściwości:
xiypickedUpBy- gracz, który aktualnie ma flagę, lub zero, jeśli żaden gracz nie ma flagi.
Teraz messagesjest to obiekt współdzielony przez twoich towarzyszy. Nie obchodzi mnie, co z tym zrobisz. Ten sam obiekt jest udostępniany i przekazywany każdemu członkowi zespołu. To jedyny sposób na komunikację. Możesz dołączać do niego właściwości, udostępniać obiekty itp. Może być tak duży, jak chcesz - bez limitu rozmiaru.
Przy każdej turze następują:
- Lista graczy (zarówno czerwona, jak i niebieska) jest losowo tasowana w kolejności kolejności.
- Każdy gracz wykonuje ruch.
- Jeśli którykolwiek z członków czerwonego zespołu dotknie (w odległości 10 pikseli) dowolnego członka drużyny niebieskiej po stronie czerwonej, wyślij członków niebieskiego zespołu do więzienia i odwrotnie. Więziony gracz upuszcza swoją flagę i siła spada do zera. Pamiętaj, że funkcja kroku (kod, który podajesz) jest nadal wywoływana - możesz więc otrzymywać / ustawiać wiadomości, ale nie możesz się poruszać w więzieniu.
- Jeśli któryś gracz dotyka (w odległości 10 pikseli) drugiej flagi, wówczas druga flaga jest oznaczona jako „wybrana przez” tego gracza. Kiedy gracz się porusza, flaga się porusza - dopóki gracz nie zostanie oznaczony i nie trafi do więzienia.
- Jeśli którykolwiek gracz dotyka więzienia drugiej strony, uwolnij wszystkich w tym więzieniu. Kiedy gracz zostaje zwolniony z więzienia, zostaje teleportowany do losowego miejsca po swojej stronie.
Poradnik:
- Przynajmniej przy regularnym zdobywaniu flagi ataki działają znacznie lepiej, gdy wielu graczy idzie na raz, ponieważ zwykle myli obrońców z tym, który gracz powinien ścigać.
- Podobnie obrońcy mogą chcieć koordynować, kogo ścigają, aby ataki nie przeszły
Fragment kodu:
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>
Kontroler: http://jsfiddle.net/prankol57/4L7fdmkk/
Kontroler pełnoekranowy: http://jsfiddle.net/prankol57/4L7fdmkk/embedded/result/
Daj mi znać, jeśli w kontrolerze są jakieś błędy.
Uwaga: jeśli podejdziesz do kontrolera i myślisz, że nic nie ładuje, naciśnij „Nowa gra”. Ładuje wszystko dopiero po naciśnięciu przycisku „Nowa gra”, dzięki czemu może załadować wszystkie boty i możliwe boty testowe naraz.
Powodzenia.
Jeśli ktoś chce zobaczyć przykładową grę, stworzyłem przykładowego bota, który można skopiować i wkleić do obszaru tekstowego „testbot” (testbot tworzy dwa duplikaty dla każdej drużyny; sprawdź zarówno drużynę czerwoną, jak i niebieską):
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
};
}