Este es un juego de capturar la bandera, fuertemente inspirado y basado en Red vs. Blue - Pixel Team Battlebots . Esa fue una pregunta asombrosa (muchas gracias a los hobbies de Calvin; espero que no te importe que te robé descaradamente mucho código). Aquí hay otro equipo del rey de la colina. Con suerte, capturar la bandera requerirá más cooperación del equipo, así como más estrategia.
Para mezclarlo, se lo considera en el equipo rojo si el último dígito de su identificación está entre 0
e 4
incluye. Esto debería evitar que exactamente los mismos equipos vuelvan a pelear, si las mismas personas deciden responder. El tablero está 350px
por 350px
. El equipo azul comienza en la mitad superior del tablero y el equipo rojo comienza en la mitad inferior.
La forma en que juegas para capturar la bandera es la siguiente: el objetivo del juego es tomar la bandera del equipo contrario y traerla de vuelta a tu propio lado. Si estás de su lado, puedes ser etiquetado y enviado a la cárcel. Si estás en la cárcel, entonces no puedes moverte. Si está de su lado, su trabajo es etiquetar a los miembros del equipo contrario para enviarlos a la cárcel. La única forma de salir de la cárcel es para alguien en su equipo que es libre de etiquetar a todos en la cárcel. (Tenga en cuenta que la cárcel se encuentra en el lado del equipo contrario).
Específicamente:
- Hay una constante -
FIELD_PADDING
establecida en 20. Este es el relleno para el campo. Si fuera cero, las banderas y la cárcel estarían exactamente en las esquinas del lienzo. Como no es así, la bandera y la cárcel están a 20 píxeles de distancia de las esquinas. - La bandera azul (recuerde: el equipo azul está en la mitad superior) se encuentra en la
(WIDTH - FIELD_PADDING, FIELD_PADDING) = (330, 20)
esquina superior derecha. - La bandera roja está en
(FIELD_PADDING, HEIGHT - FIELD_PADDING) = (20, 330)
- La cárcel azul (donde se guardan los miembros rojos) está en
(20, 20)
el lado azul, arriba a la izquierda. - La cárcel roja, donde se guardan los miembros azules, está en
(330, 330)
Cada miembro del equipo comienza al azar en una posición 45 < x < 305
y 45 < y < 175
para azul y 175 < y < 305
para rojo. Ningún miembro del equipo puede ir dentro de los DEFENSE_RADIUS = 25
píxeles de su propia bandera o de su propia cárcel (a menos, por supuesto, que su propia bandera haya sido tomada por un bot contrario, en cuyo caso debe etiquetar ese bot). Esto es para evitar la protección de los cachorros como los bots. Si vas dentro de ese rango, eres "empujado" hacia atrás. Del mismo modo, ningún miembro del equipo puede salir de los límites (menos de cero o más de 350); si lo hace, lo empujan al lugar legal más cercano en el que puede estar.
Cada vez que te mueves, te gastas strength
. Sus strength
inicia en 20
y se repone por 2
cada vuelta. La cantidad de fuerza que usa es igual a la distancia que viaja. Si tu fuerza se volviera negativa al moverte a un lugar determinado, no puedes hacer ese movimiento. Probablemente sea una buena idea ir a la velocidad 2
de la persecución normal. Solo debes usar velocidades más altas si estás cerca de ganar y necesitas la velocidad extra (en mi opinión).
Especificaciones :
La especificación es bastante similar a la pregunta de Pixel Team Battlebots. Debe escribir un bloque de código (recuerde, sin variables globales) en javascript. Debería devolver un objeto con un x
valor y un y
valor que represente su cambio en x y cambio en los valores de y. La siguiente respuesta:
return {
x: 0,
y: -2
};
siempre se mueve hacia arriba, hasta que golpea una pared. No puede editar 8 horas después de la publicación (a excepción de LegionMammal98 que pensó que el controlador no estaba cargando su código y no realizó la prueba) . Tiene acceso a las siguientes variables en su código:
this
- usted mismo, como jugador (vea a continuación qué son los jugadores)move
- el número redondo, que comienza en 0tJailed
- una variedad de todos los jugadores de tu equipo que están encarceladoseJailed
- una serie de todos los jugadores del equipo contrario que están encarceladosteam
- una variedad de todos los jugadores de tu equipo, NO solo los que están cerca de tienemies
- una variedad de todos los jugadores del otro equipo, NO solo los que están cerca de titFlag
- su bandera (está tratando de protegerla)eFlag
- la otra bandera (estás intentando robarla)messages
- explicado a continuación- Una lista de constantes:
WIDTH = 350
,HEIGHT = 350
,FIELD_PADDING = 20
,DEFENSE_RADIUS = 25
.
Cada "jugador" es un objeto con las siguientes propiedades:
x
yy
strength
id
isJailed
- cierto si el jugador está en la cárcel
Cada bandera tiene las siguientes propiedades:
x
yy
pickedUpBy
- el jugador que actualmente tiene la bandera, o nulo si ningún jugador tiene la bandera.
Ahora, messages
es un objeto que se comparte entre tus compañeros de equipo. No me importa lo que hagas con eso. El mismo objeto se comparte y se pasa a cada uno de los miembros de su equipo. Esta es la única forma en que puedes comunicarte. Puede adjuntarle propiedades, compartir objetos, etc. Puede ser tan grande como desee, sin límite de tamaño.
En cada turno sucede lo siguiente:
- La lista de jugadores (tanto roja como azul) se baraja aleatoriamente por orden de turno.
- Cada jugador hace un movimiento.
- Si algún miembro del equipo rojo toca (dentro de 10 píxeles de) cualquier miembro del equipo azul en el lado rojo, envíe a los miembros del equipo azul a la cárcel y viceversa. Un jugador encarcelado deja caer su bandera y su fuerza cae a cero. Tenga en cuenta que la función de paso (código que proporciona) todavía se llama, por lo que puede obtener / configurar mensajes, pero no puede moverse mientras está en la cárcel.
- Si algún jugador toca (dentro de 10 píxeles de) la otra bandera, la otra bandera se marca como "recogida por" ese jugador. Cuando el jugador se mueve, la bandera se mueve, hasta que el jugador es etiquetado y va a la cárcel, eso es.
- Si algún jugador toca la cárcel del otro lado, libere a todos en esa cárcel. Cuando un jugador es liberado de la cárcel, él / ella es teletransportado a una ubicación aleatoria de su lado.
Consejos:
- Al menos en la captura regular de la bandera, los ataques funcionan mucho mejor cuando muchos jugadores van a la vez, porque tiende a confundir a los defensores sobre qué jugador deben perseguir.
- Del mismo modo, los defensores pueden querer coordinar a quién persiguen para que los ataques no pasen
Fragmento de pila:
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>
Controlador: http://jsfiddle.net/prankol57/4L7fdmkk/
Controlador de pantalla completa: http://jsfiddle.net/prankol57/4L7fdmkk/embedded/result/
Avíseme si hay algún error en el controlador.
Nota: Si vas al controlador y piensas que no está cargando nada, presiona "Nuevo juego". Solo carga todo después de presionar "Nuevo juego" para que pueda cargar todos los bots y posibles bots de prueba a la vez.
Buena suerte.
Si alguien quiere ver un juego de ejemplo, hice un bot de ejemplo que puede copiar y pegar en el área de texto "testbot" (el testbot crea dos duplicados en cada equipo; marque el equipo rojo y el equipo azul):
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
};
}
fuente
Respuestas:
Rojo - Lazy Jail Hog | Lazy Flagger
Se mueve hacia el más cercano de estos dos: la cárcel de blue, o la bandera de blue.
Finalmente, su cerebro está completamente almacenado
messages[29354]
e inicializado solo en el primer movimiento. Por lo tanto, si los aliados encuentran un mejor uso para este bot, pueden reemplazar su cerebro para su propósito superior.fuente
Rojo - La Guardia
Este bot guardará la bandera bastante bien. No te metas en su camino ...
fuente
Azul - LegionMammal978
Defensa bot.
fuente
this
dentro de una función (en suforEach
bucle). Tienes que guardarlo como una variable de antemano (es decirvar _this = this;
) y usarlo_this
. Lo agregaré como una excepción si edita pronto porque pensó que el controlador no estaba cargando su código y no pudo probarlo.forEach
es opcionalthisArg
.Rojo - Cazador de banderas
Intenta conseguir la bandera. Si alguien más lo tiene, Flag Hunter camina hacia la cárcel, confundiendo al enemigo o liberando a los miembros de su equipo.
fuente
Azul - Un buen compañero alegre
Primero intente programar en Javascript y en code-golf. Perseguirá cualquier cosa que se acerque demasiado a la bandera, intentando adelantar sus movimientos. De lo contrario, correrá para rescatar a los compañeros de equipo en la cárcel, o perezosamente tratará de llegar a la bandera del otro equipo.
fuente