Questo è un gioco di cattura della bandiera, fortemente ispirato e basato su Red vs. Blue - Pixel Team Battlebots . Questa è stata una domanda fantastica (grazie mille Calvin'sHobbies; spero che non ti dispiaccia che ti abbia spudoratamente rubato un sacco di codice) - ecco un altro re della collina basato sul team. Si spera che catturare la bandiera richiederà più collaborazione di squadra e più strategia.
Per confonderlo, sei considerato nella squadra rossa se l'ultima cifra del tuo ID è compresa tra 0e 4compreso. Ciò dovrebbe impedire alle stesse squadre esatte di combattere di nuovo, se le stesse persone decidono di rispondere. Il consiglio è 350pxdi 350px. La squadra blu inizia nella metà superiore del tabellone e la squadra rossa inizia nella metà inferiore.
Il modo in cui giochi cattura la bandiera è il seguente: l'oggetto del gioco è prendere la bandiera della squadra avversaria e riportarla dalla tua parte. Se sei dalla loro parte, puoi essere taggato e mandato in prigione. Se sei in prigione, non puoi muoverti. Se sei dalla tua parte, il tuo compito è taggare i membri del team avversario per inviarli in prigione. L'unico modo per uscire di prigione è per qualcuno nella tua squadra che è libero di taggare tutti in prigione. (Nota che la prigione si trova dalla parte della squadra avversaria).
In particolare:
- C'è una costante -
FIELD_PADDING- impostata su 20. Questa è l'imbottitura per il campo. Se fosse zero, le bandiere e la prigione sarebbero esattamente agli angoli della tela. Poiché non lo è, la bandiera e la prigione sono distanti 20 pixel dagli angoli. - La bandiera blu (ricorda: la squadra blu è nella metà superiore) si trova
(WIDTH - FIELD_PADDING, FIELD_PADDING) = (330, 20)nell'angolo in alto a destra. - La bandiera rossa è a
(FIELD_PADDING, HEIGHT - FIELD_PADDING) = (20, 330) - La prigione blu (dove sono tenuti i membri rossi) si trova sul
(20, 20)lato blu, in alto a sinistra. - La prigione rossa, dove sono tenuti i membri blu, è a
(330, 330)
Ogni membro del team inizia casualmente in una posizione 45 < x < 305e 45 < y < 175per il blu e 175 < y < 305per il rosso. Nessun membro del team può andare all'interno dei DEFENSE_RADIUS = 25pixel della propria bandiera o della propria prigione (a meno che, ovviamente, la propria bandiera non sia stata presa da un bot avversario, nel qual caso è necessario taggare quel bot). Questo per prevenire la protezione dei cuccioli come i robot. Se si rientra in tale intervallo, si viene "respinti" indietro. Allo stesso modo, nessun membro del team può andare oltre i limiti (meno di zero o più di 350) - se lo fai, sei spinto indietro nel luogo legale più vicino che puoi essere.
Ogni volta che ti muovi, esaurisci strength. Il tuo strengthinizia alle 20e viene riempito da 2ogni turno. La quantità di forza che usi è uguale alla distanza che percorri. Se la tua forza diventa negativa spostandoti in un determinato luogo, ti viene impedito di fare quella mossa. Probabilmente è una buona idea andare a tutta velocità 2per la normale caccia. Dovresti usare velocità più alte se sei vicino alla vittoria e hai bisogno di una velocità extra (secondo me).
Spec :
Le specifiche sono abbastanza simili alla domanda Pixel Team Battlebots. Dovresti scrivere un blocco di codice (ricorda, nessuna variabile globale) in JavaScript. Dovrebbe restituire un oggetto con un xvalore e un valore che yrappresentano la modifica in xe la modifica in y valori. La seguente risposta:
return {
x: 0,
y: -2
};
si alza sempre, fino a quando non colpisce un muro. Non puoi modificare 8 ore dopo la pubblicazione (ad eccezione di LegionMammal98 che pensava che il controller non stesse caricando il suo codice e non ha eseguito il test) . Hai accesso alle seguenti variabili nel tuo codice:
this- te stesso, come giocatore (vedi sotto per cosa sono i giocatori)move- il numero rotondo, a partire da 0tJailed- una schiera di tutti i giocatori della tua squadra che sono imprigionatieJailed- una schiera di tutti i giocatori della squadra avversaria che vengono incarceratiteam- una schiera di tutti i giocatori della tua squadra, NON solo quelli vicini a teenemies- una schiera di tutti i giocatori dell'altra squadra, NON solo quelli vicini a tetFlag- la tua bandiera (stai cercando di proteggerla)eFlag- l'altra bandiera (stai cercando di rubarla)messages- spiegato di seguito- Un elenco di costanti:
WIDTH = 350,HEIGHT = 350,FIELD_PADDING = 20,DEFENSE_RADIUS = 25.
Ogni "giocatore" è un oggetto con le seguenti proprietà:
xeystrengthidisJailed- vero se il giocatore è in prigione
Ogni bandiera ha le seguenti proprietà:
xeypickedUpBy- il giocatore che ha attualmente la bandiera, o null se nessun giocatore ha la bandiera.
Ora, messagesè un oggetto condiviso tra i tuoi compagni di squadra. Non mi importa di cosa ci fai. Lo stesso oggetto viene condiviso e passato a ciascuno dei membri del team. Questo è l'unico modo per comunicare. Puoi associarvi proprietà, condividere oggetti, ecc. Può essere grande quanto vuoi - nessun limite di dimensione.
Ad ogni turno accade quanto segue:
- L'elenco dei giocatori (sia rosso che blu) viene mescolato casualmente per l'ordine dei turni.
- Ogni giocatore fa una mossa.
- Se qualche membro rosso della squadra tocca (entro 10 pixel) qualsiasi membro blu della squadra sul lato rosso, manda in galera i membri della squadra blu e viceversa. Un giocatore imprigionato lascia cadere la sua bandiera e la forza scende a zero. Si noti che la funzione di passaggio (codice fornito) viene comunque chiamata - in modo da poter ottenere / impostare messaggi, ma non è possibile spostarsi mentre si è in prigione.
- Se un giocatore tocca (entro 10 pixel) l'altra bandiera, allora l'altra bandiera viene contrassegnata come "raccolta da" quel giocatore. Quando il giocatore si muove, la bandiera si muove - fino a quando il giocatore non viene taggato e va in prigione, cioè.
- Se un giocatore tocca la prigione dell'altra parte, libera tutti quelli in quella prigione. Quando un giocatore viene liberato dalla prigione, viene teletrasportato in una posizione casuale dalla sua parte.
suggerimenti:
- Almeno nella normale cattura della bandiera, gli attacchi funzionano molto meglio quando molti giocatori vanno contemporaneamente, perché tende a confondere i difensori su quale giocatore dovrebbero inseguire.
- Allo stesso modo, i difensori potrebbero voler coordinare chi stanno inseguendo in modo che gli attacchi non passino
Snippet di stack:
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>
Controller: http://jsfiddle.net/prankol57/4L7fdmkk/
Controller a schermo intero: http://jsfiddle.net/prankol57/4L7fdmkk/embedded/result/
Fammi sapere se ci sono bug nel controller.
Nota: se vai al controller e pensi che non stia caricando nulla, premi "Nuovo gioco". Carica tutto solo dopo aver premuto "Nuova partita" in modo da poter caricare contemporaneamente tutti i robot e tutti i possibili robot di prova.
In bocca al lupo.
Se qualcuno vuole vedere una partita di esempio, ho creato un bot di esempio che puoi copiare e incollare nell'area di testo "testbot" (il testbot crea due duplicati su ciascuna squadra; controlla sia la squadra rossa che la squadra blu):
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
};
}