Coleccionista de oro KoTH


48

Nota: La encuesta para los favoritos de la comunidad se lanzará pronto.

En este KoTH, el objetivo es ser el último bot vivo. Las monedas se colocarán en áreas aleatorias, y tu bot debe obtener las monedas primero. Si un bot se encuentra con otro bot, el bot con más monedas gana y el otro bot muere. Más detalles a continuación.

Tipos de monedas

Habrá 2 tipos de monedas: oro y plata. El oro agrega 5 monedas a la fuerza del robot, y la plata agrega 2. Una vez que se recoge una moneda, se coloca otra moneda en otro lugar del tablero. En cualquier momento, hay una moneda de oro y cuatro monedas de plata en la arena.

Colisiones de bot

En el caso de que dos bots intenten ocupar el mismo espacio, el que tenga más monedas se quedará y el que tenga menos ... no lo hará. El bot ganador ganará el 85% de las monedas de los oponentes (redondeado). Si están atados, ambos mueren. Si tres o más intentan ocupar el mismo espacio, el más poderoso gana y obtiene el 85% de todas las monedas del otro bot. En el caso de que el bot más poderoso sea un empate, todos los bots mueren que intentaron ingresar al espacio.

Arena

La longitud lateral de la arena se calcula con 4 + botCount. Al colocar bots al comienzo del juego, se eligen lugares aleatorios. El sistema garantiza que no se inicien bots en el mismo espacio o uno al lado del otro. Las monedas se generan aleatoriamente, excluyendo un cuadrado de 3 por 3 centrado en cada bot. Si se encuentra un bot fuera de la arena, muere instantáneamente. La arena comienza en (0,0), o Noroeste, en la esquina superior izquierda, y la ubicación de un bot siempre es un número entero.

Su bot

Su bot debe ser una función, en cualquier lenguaje orientado a objetos que tenga matrices, enteros, cadenas y funciones. Tenga en cuenta que todas las presentaciones se convertirán a Javascript, para simplificar las cosas. Para almacenar información entre movimientos, use botNotes.storeData(key, value)y botNotes.getData(key, value). No puede almacenar ni acceder a los datos de ninguna manera, que no sea la que se proporciona a través de los parámetros y botNotes. Debe crear una función que, cuando se le llama, devuelve una cadena north, east, south, west, o none. Habrá 3 argumentos para la función:

  • Un objeto con cuatro enteros ( locationX, locationY, coins, arenaLength), su ubicación actual, sus monedas, y la longitud de la Arena

  • Una matriz multidimensional con las coordenadas X e Y de otros bots, y su conteo de monedas, ex[[0,5,4],[4,7,1],[7,4,12]]

  • Una matriz con las ubicaciones de monedas enumeradas (el oro siempre es el primero)

Este es el desafío del rey de la colina, se prohíben las lagunas estándar . Su función se ejecutará varios miles de veces, cada vez que se permita un "Movimiento". Tenga en cuenta que si el juego supera los 20,000 movimientos , gana el bot con la mayor cantidad de monedas. Esto se hará 8,000 veces, para eliminar la aleatoriedad.

Sala de chat: https://chat.stackexchange.com/rooms/81347/gold-collectors-koth

Premios:

Primer lugar: recompensa de 100 puntos
Favorito de la comunidad: respuesta aceptada de 15 puntos

Ganadores:

Primer lugar: TBTPTGCBCBA
Segundo lugar: Big King Little Hill
Tercer lugar: Potencialmente victorioso
Cuarto lugar: Cortés borracho miope cortés
Quinto lugar: Moneda de seguridad


66
"Tenga en cuenta que todas las presentaciones se convertirán a Javascript, para simplificar las cosas". ¿Cómo se supone que esto funcione? ¿Haces la conversión?
Laikoni

21
No hay nada de malo en que un koth solo permita un solo idioma, especialmente uno tan extendido como JavaScript. En lugar de ambiguamente "convertir" respuestas a JavaScript (presumiblemente usted mismo y a mano), simplemente debe limitar el desafío a JS solamente. Después de todo, hemos tenido muchos koths solo para Java y Python en el pasado.
Skidsdev

2
Una versión de esto donde controlas la aceleración en lugar de la posición sería genial.
akozi

12
Para todos: Ya hay demasiados comentarios. No deje comentarios inútiles como "+1, buen bot" , y elimine sus comentarios si es redundante . No somos un sitio típico de preguntas y respuestas, pero a nadie le gusta leer cientos de comandos.
user202729

55
(A mi propia pregunta): Según NP en el chat, es lo último: todos los bots se mueven, luego se resuelven todos los conflictos, luego ocurren todas las recolecciones de monedas, luego se colocan todas las monedas nuevas.
BradC

Respuestas:


26

BaitBot - JavaScript Node.JS

¿Por qué molestarse en perseguir o correr si nunca puedes atrapar? En cambio, BaitBot encuentra la moneda más cercana y espera a que un robot más débil también se acerque a ella. Cuando ambos están adyacentes, baitBot va por la moneda asumiendo que el bot más débil también lo hará. Si baitBot está esperando y se acerca un robot más fuerte, simplemente agarra la moneda y se ensarta. ¡Pruébame!

function baitBot(me, others, coins) {
  let directions = ['none','east','south','west','north']
  function distanceTo(a) {
    return (Math.abs(a[0] - me.locationX) + Math.abs(a[1] - me.locationY))
  }
  function distanceBetween(a, b){
    return (Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]))
  }
  function adjacentDir(a) {
    //0 = no, 1,2,3,4 = ESWN
    if(distanceTo(a) == 1) {
      if(a[0] > me.locationX){ return 1}
      else if(a[0] < me.locationX) {return 3}
      else if(a[1] > me.locationY) {return 2}
      else{ return 4}
    }
    else {return 0}
  }
  function edibility(a) {
    return me.coins - a[2]
  }

  //Find nearest coin and get next to it
  let closestCoin = coins.sort((a,b) => distanceTo(a) - distanceTo(b))[0]
  if(distanceTo(closestCoin) > 1) {
    if(closestCoin[0] > me.locationX){ return 'east'}
    else if(closestCoin[0] < me.locationX){ return 'west'}
    else if(closestCoin[1] < me.locationY){ return 'north'}
    else if(closestCoin[1] > me.locationY){ return 'south'}
  }

  //If we're next to a coin and there's a threat close, just grab it
  let nearestThreat = others.filter(a => edibility(a) < 0).sort((a,b) => distanceBetween(a, closestCoin) - distanceBetween(b, closestCoin))[0]
  if(nearestThreat && distanceBetween(nearestThreat, closestCoin) <= 2) {
    return directions[adjacentDir(closestCoin)]
  }



  //Otherwise, wait until there's a target also next to the coin. If none are close, just take it
  let targets = others.filter(a => edibility(a) > 0 && distanceBetween(closestCoin, a) <= 3)
  targets.sort((a,b) => distanceBetween(a, closestCoin) - distanceBetween(b, closestCoin))
  if(targets.length > 0 && distanceBetween(targets[0], closestCoin) > 1){
    return directions[0]
  }
  return directions[adjacentDir(closestCoin)]

}

1
Ja, esa es una buena idea, me gusta.
Sundar - Restablece a Mónica el

Este enfoque es genial ... no, muy genial
Redwolf Programs

1
BaitBot necesita en nearestThreat && distanceTo(nearestThreat)lugar de solo distanceTo(nearestThreat). Falla cuando no hay amenaza.
Programas Redwolf

1
Sí, nearestThreates undefinedsi todos los demás bots tienen más puntos que los tuyos.
Noche2

1
Bueno, recibo avisos como [10] Bot Bait Bot tired of this world, and jumped off its edgeen mi registro de eventos
Redwolf Programs

17

Potencialmente victorioso | JavaScript

El color preferido para este bot es #1600a6.

function (me, others, coins)
{
    let huntingTimer = botNotes.getData("huntingTimer");
    let huntedIndex = botNotes.getData("huntedIndex");
    if(!huntingTimer)
    huntingTimer = 0;
    else if(huntingTimer >0)
    huntingTimer--;
    else if(huntingTimer == -1)
    huntingTimer = Math.ceil(20*(1+Math.log2(me.coins/25)));
    else
    huntingTimer++;

    function distanceFromMe(X, Y) { return Math.abs(me.locationX - X) + Math.abs(me.locationY - Y); }

    function U(x, y)
    {
    function distance(X, Y) { return Math.abs(X-x) + Math.abs(Y-y); }
    function gravitation(k, X, Y) { return - k / ( distance(X, Y) + .2 ); }
    function exponential(k, q, X, Y) { return - 5*k * Math.exp(- q * distance(X,Y)); }

    // No going away from the arena.
    if(!((0 <= x) && (x < me.arenaLength) && (0 <= y) && (y < me.arenaLength)))
    {
        return Infinity;
    }

    let reachability = [1, 1, 1, 1, 1];
    let distances = coins.map(c => distanceFromMe(c[0], c[1]));
    for(let i = 0; i < others.length; i++)
    {
        for(let coin = 0; coin < 5; coin++)
            reachability[coin] += (Math.abs(others[i][0] - coins[coin][0]) + Math.abs(others[i][1] - coins[coin][1])) < distances[coin];
    }

    let potential = gravitation(40, coins[0][0], coins[0][1]) / (reachability[0]); // Gold

    // Silver
    for(let i = 1; i < 5; i++)
    {
        potential += gravitation(10, coins[i][0], coins[i][1]) / (reachability[i]);
    }

    others.sort((a, b) => b[2] - a[2]);

    // Other bots
    for(let i = 0; i < others.length; i++)
    {
        if(
            ((Math.abs(me.locationX - others[i][0]) + Math.abs(me.locationY - others[i][1])) < 3) &&
            (huntingTimer == 0) &&
            (me.coins > 25) && 
            (me.coins < (others[0][2]*.9)) &&
            (others[i][2] < me.coins-5) && (others[i][2] >= 10)
        )
        {
            huntingTimer = -10;
            huntedIndex = i;
        }

        if((huntingTimer < 0) && (huntedIndex == i))
           potential += exponential(30, 1, others[i][0], others[i][1]);

        if(others[i][2] >= me.coins)
        {
        // Otherwise, they could eat us, and we will avoid them.
        potential += exponential(-1400, 3, others[i][0], others[i][1]);
        }
    }

    return potential;
    }

    // All possible squares we can move to, with their names.
    let movements = [
    [ "north", U(me.locationX, me.locationY - 1)],
    [ "south", U(me.locationX, me.locationY + 1)],
    [ "east", U(me.locationX + 1, me.locationY)],
    [ "west", U(me.locationX - 1, me.locationY)],
    [ "none", U(me.locationX, me.locationY)]
    ];

    botNotes.storeData("huntingTimer", huntingTimer);
    botNotes.storeData("huntedIndex", huntedIndex);

    // Sort them according to the potential U and go wherever the potential is lowest.
    movements.sort((a, b) => a[1] - b[1]);
    return movements[0][0];
}

(Disculpas por el formato descuidado, la sangría de 4 espacios para este sitio no va bien con mi costumbre de usar pestañas).

Explicación aproximada

Por la presente renuncio al intento de actualizar la explicación de las fórmulas. Los coeficientes cambian constantemente y es un poco difícil mantener actualizada la explicación. Así que solo explicaré el principio general.

Cada moneda y cada bot generan un campo de fuerza con cierto potencial. Solo agrego los potenciales de todo junto y el bot luego va a donde sea que el potencial sea el más bajo. (Obviamente esta idea es robada de la física).

Yo uso dos tipos de potenciales. El primero es pseudogravitacional (que actúa en cualquier rango), con Lakes una "fuerza" del campo y, con esta elección de signo, el potencial es atractivo. Laraquí (y en todas partes) es la distancia en la métrica del taxi,r = | x₁ - x₂ | + | y₁ - y₂ | .

U=kr+1511+n.

Yo uso k = 40 para monedas de oro y k = 10 para monedas de plata. n es el número de bots que están más cerca de la moneda particular que nosotros. De lo contrario, ignoramos absolutamente a los otros bots (si nos interponemos en el camino de un bot más fuerte, huimos, pero eso es todo). Valoro las monedas de oro por más de lo que valen porque, de lo contrario, los bots que van principalmente después del oro todo el tiempo me ganan.

El segundo potencial es uno en descomposición exponencial (que efectivamente actúa solo a distancias muy pequeñas). Esto es generado por los otros robots, principalmente los más potentes.

Estos producen un campo con Esta fuerza es prohibitivamente fuerte en el rango 0-1, pero decae a casi nada en las distancias más grandes. (Distancia + 1 significa cortar la fuerza en 1/20.)

U=5×1400e3r.

Por lo general, no atacamos a los otros bots intencionalmente (por supuesto, si se interponen en nuestro camino y los pisamos, es su culpa), pero existe la posibilidad de hacerlo. Si se cumplen algunas condiciones difíciles, podemos ingresar al modo de caza , enfocándonos en un solo bot. Para ingresar al modo de caza:

  1. Debemos tener al menos 25 monedas. (Necesitamos obtener algunas monedas primero).
  2. Deben tener como máximo (nuestras monedas - 5) monedas, y al menos 10 monedas. (No queremos estar cazando a alguien que agarra una moneda y de repente es más poderoso, y tampoco queremos perseguir bots de monedas cero).
  3. Debemos retrasarnos por lo menos en el bot líder actual en al menos 1/10 de sus monedas. (Debes tener la suerte de cazar algo, por lo que no es necesario regalar una buena posición solo para probar suerte).
  4. No debemos estar en un tiempo de reutilización de caza (ver más abajo).

Si todos estos se satisfacen, se activa el modo de búsqueda. Para las siguientes 10 rondas, el bot cazado solo emite el potencial Después de que transcurran estas 10 rondas, ingresamos al tiempo de reutilización de caza, durante el cual es posible que no volvamos a ingresar al modo de caza. (Eso es para evitar que persigamos interminablemente e infructuosamente un bot mientras todos los demás agarran monedas felizmente). El tiempo de reutilización de caza es de 20 rondas cuando tenemos 25 monedas, y aumenta en 20 monedas por cada duplicación de eso. (En otras palabras, el tiempo de reutilización es

U=150er.
20(1 + log2(c / 25)).) (Usamos eso porque al final del juego, todos los bots que se pueden cazar probablemente estén muertos, por lo que cualquier caza será muy probable en vano. Por eso, queremos limitar el tiempo perdido. Pero a veces, un retraso afortunado- comer comer puede cambiarlo todo, así que mantenemos la posibilidad).

Finalmente, toda la arena se coloca en un pozo de potencial infinito que evita que el bot escape.


Creo que este robot probablemente también supera mi movimiento ponderado.
fəˈnɛtɪk

@ fəˈnɛtɪk - Yo también :—). Creo que este puede manejar los otros bots bastante mejor. (Tampoco está "cegado" por una moneda en un cuadrado adyacente). Pero definitivamente te di +1 porque soy un gran admirador de esta idea.
Ramillies

¿Podría aplicar el principio de menor acción a esto?
Decaimiento Beta

@BetaDecay: No mucho, me temo, el cálculo no responde bien a problemas discretos como este. Incluso en el caso continuo no sería trivial (debido a la magnitud fija de la velocidad), pero podría ser posible después de algunas coordenadas polares mágicas, supongo.
Ramillies

44
Esto es genial Sin embargo, no estoy seguro de que el riesgo esté relacionado monotónicamente con la distancia, parece que una amenaza a 2 espacios de distancia tiene más probabilidades de matarlo que uno adyacente, ya que en este último caso uno de ustedes debe permanecer inmóvil para que ocurra una colisión.
Caín

16

Algoritmo de aprendizaje de primera generación | JavaScript (Node.js)

function run() {
	return ['north','east','south','west'][(Math.random()*4)|0];
}

Pruébalo en línea!

¿Alguna vez has visto esos timelapses de algoritmos de aprendizaje aprendiendo a jugar un juego? A menudo se mueven casi al azar en las primeras generaciones ...


LOL ... ¡Todavía podría funcionar!
Programas Redwolf

2
La mayoría de los algoritmos de aprendizaje funcionan literalmente al azar durante las primeras iteraciones, no solo casi al azar.
fəˈnɛtɪk

¿Adivina qué? ¡Este bot obtuvo casi 0.22 monedas por ronda en promedio!
Programas Redwolf

16

Big King Little Hill | JavaScript

function BigKingLittleHill(me, enemies, coins) {

	
	// Is a move safe to execute?
	function isItSafe(x){
			let loc = [x[0] + me.locationX,x[1] + me.locationY];
			return loc[0] >= 0 && loc[0] < me.arenaLength
			&& loc[1] >= 0 && loc[1] < me.arenaLength
			&& enemies
					.filter(enemy => me.coins <= enemy[2])
					.filter(enemy => getDist(enemy,loc) == 1).length === 0;
	}

	
	// Dumb conversion of relative coord to direction string
	function coordToString(coord){
		if (coord[0] == 0 && coord[1] == 0) return 'none';
		if (Math.abs(coord[0]) > Math.abs(coord[1]))
			return coord[0] < 0 ? 'west' : 'east';
		return coord[1] < 0 ? 'north' : 'south';
	}
	
	
	// Calculate a square's zone of control
	function getZOC(x) {
		let n = 0;
		for(let i = 0; i < me.arenaLength;i++){
			for(let j = 0; j < me.arenaLength;j++){
				if (doesAControlB(x, [i,j])) n++;
			}
		}
		return n;
	}
	
	function doesAControlB(a, b) {
		return getEnemyDist(b) > getDist(a, b);
	}
  
	// Distance to nearest enemy
	function getEnemyDist(x) {
			return enemies.filter(enemy => enemy[2] >= me.coins/50).map(enemy => getWeightedDist(enemy, x)).reduce((accumulator, current) => Math.min(accumulator, current));
	}
  
	// Weights distance by whether enemy is weaker or stronger
	function getWeightedDist(enemy, pos) {
		return getDist(enemy, pos) + (enemy[2] < me.coins ? 1 : 0);
	}
  
	function getDist(a, b){
		return (Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]))
	}
	
	//check whether there are coins in our Zone of Control, if yes move towards the closest one
	let loc = [me.locationX,me.locationY];
	let sortedCoins = coins.sort((a,b) => getDist(loc,a) - getDist(loc,b));
	for (let coin of sortedCoins) {
		if (doesAControlB(loc,coin)){
			return coordToString([coin[0] - loc[0],coin[1] - loc[1]]);
		}
	}
	
	//sort moves by how they increase our Zone of Control
	northZOC = [[0,-1], getZOC([loc[0],loc[1]-1])];
	southZOC = [[0,1], getZOC([loc[0],loc[1]+1])];
	westZOC = [[-1,0], getZOC([loc[0]-1,loc[1]])];
	eastZOC = [[1,0], getZOC([loc[0]+1,loc[1]])];
	noneZOC = [[0,0], getZOC([loc[0],loc[1]])];
	let moves = [northZOC,southZOC,westZOC,eastZOC,noneZOC].sort((a,b) => b[1] - a[1]);
	
	//check whether these moves are safe and make the highest priority safe move
	for (let move of moves) {
		if (isItSafe(move[0])) { 
			return coordToString(move[0]);
		}
	}
	//no moves are safe (uh oh!), return the highest priority
	return coordToString(moves[0][0])
}

Pruébalo en línea!

Big King Little Hill toma decisiones basadas en "zonas de control". Solo buscará monedas que estén en su zona de control, lo que significa que puede alcanzar la moneda antes que cualquier otro bot. Cuando no hay monedas en su zona de control, se mueve para maximizar el tamaño de su zona de control. Big King Little Hill calcula la zona de control de cada uno de sus 5 movimientos posibles y favorece los movimientos que maximizan el tamaño de su zona de control. De esta manera, Big King Little Hill finalmente alcanza un máximo local (pequeña colina) de control y espera a que se genere una moneda dentro de su zona. Además, Big King Little Hill rechaza cualquier movimiento que pueda resultar en su muerte a menos que no haya alternativas.

Big King Little Hill es un pesimista (prefiere el término realista) porque no se molesta en disputar ninguna moneda que no está segura de obtener. También es pacifista en el sentido de que no persigue a los robots más débiles en ningún sentido (aunque podría pisar a uno si se interponen en el camino). Por último, Big King Little Hill es un cobarde que no pondrá en peligro su propia vida por ninguna recompensa a menos que sea absolutamente necesario.


1
Bienvenido a PPCG! Ese es un muy buen bot = D
Luis felipe De jesus Munoz

Esto es lo que estaba pensando para un bot. Buen trabajo.
Jo.

10

Moneda de seguridad | JavaScript

SafetyCoin=(myself,others,coins)=>{
  x=myself.locationX;
  y=myself.locationY;
  power=myself.coins;
  arenaSize=myself.arenaLength;
  dist=0;
  optimalCoin=7;
  optimalDist=11*arenaSize;
  for(i=0;i<coins.length;i++){
    enemyDist=3*arenaSize;
    dist=Math.abs(x-coins[i][0])+Math.abs(y-coins[i][1])
    for(j=0;j<others.length;j++){
      if(i==0){
        if(others[j][2]+5>=power){
          enemyDist=Math.min(enemyDist,Math.abs(others[j][0]-coins[i][0])+Math.abs(others[j][1]-coins[i][1]))
        }
      }
      else{
        if(others[j][2]+2>=power){
          enemyDist=Math.min(enemyDist,Math.abs(others[j][0]-coins[i][0])+Math.abs(others[j][1]-coins[i][1]))
        }
      }

    }
    if(enemyDist>dist){
      if(i==0){
        if(dist/5<optimalDist){
          optimalDist=dist/5;
          optimalCoin=i;
        }
      }
      else{
        if(dist/2<optimalDist){
          optimalDist=dist/2;
          optimalCoin=i;
        }
      }
    }
  }
  if(optimalCoin==7){
    safeDir=15;
    if(x==0){safeDir-=8;}
    if(x==arenaSize-1){safeDir-=2;}
    if(y==0){safeDir-=1;}
    if(y==arenaSize-1){safeDir-=4;}
    for(i=0;i<others.length;i++){
      if(others[i][2]>=power){
        if(Math.abs(x-others[i][0])+Math.abs(y-others[i][1])==2){
          if(x-others[i][0]>0){safeDir-=8;}
          if(x-others[i][0]<0){safeDir-=2;}
          if(y-others[i][1]>0){safeDir-=1;}
          if(y-others[i][1]<0){safeDir-=4;}
        }
      }
    }
    directions=["north","east","south","west"];
    if(safeDir!=0){
      tmp="";
      tmp+="0".repeat(Math.max(Math.sqrt(arenaSize)/2|0,y-(arenaSize/2|0)));
      tmp+="2".repeat(Math.max(Math.sqrt(arenaSize)/2|0,(arenaSize/2|0)-y));
      tmp+="1".repeat(Math.max(Math.sqrt(arenaSize)/2|0,(arenaSize/2|0)-x));
      tmp+="3".repeat(Math.max(Math.sqrt(arenaSize)/2|0,x-(arenaSize/2|0)));
      rnd=tmp[Math.random()*tmp.length|0];
      while(!(2**rnd&safeDir)){rnd=tmp[Math.random()*tmp.length|0];}
      return directions[rnd];
    }
    return "none";//the only safe move is not to play :P
  }
  distX=coins[optimalCoin][0]-x;
  distY=coins[optimalCoin][1]-y;
  if(Math.abs(distX)>Math.abs(distY)){
    if(distX>0){return "east";}
    else{return "west";}
  }
  else{
    if(distY>0){return "south";}
    else{return "north";}
  }
}

Este bot se dirige directamente hacia una moneda de valor ponderado (valor / distancia) que no puede morir al alcanzar al mismo tiempo o después de otro bot. Si no hay una moneda válida con esta propiedad, se ubica donde está el bot ahora se mueve en una dirección segura aleatoria (seguridad significa que si un bot se mueve hacia ella, la moneda de seguridad no puede chocar. Esto permite que el bot intercambie lugares con otro bot si inmediatamente al lado), ponderada hacia el centro de la arena.


1
Huh, esto realmente puede ganar. Aunque, hay muchos bots
Programas Redwolf

Este método tendrá más problemas cuanto más desigualmente se coloquen los bots enemigos con mayor o igual valor.
fəˈnɛtɪk

1
Bueno, probablemente todos irán en línea recta hacia la moneda más cercana / moneda de oro.
Programas Redwolf

Solo funcionará bien si logra obtener algunas monedas desde el principio.
fəˈnɛtɪk

Y eso es sobre todo suerte, ya que el lugar donde se generan las monedas se decide al azar
Redwolf Programs

10

El bot que juega el juego con cautela pero puede ser agresivo | JavaScript

Color preferido: #F24100

Nota: Aunque este bot ha tomado el 1er lugar, se debe al equipo con "Feudal Noble" al final y se lo está comiendo por más monedas. De lo contrario, este bot habría sido tercero. Si está interesado en bots que son más potentes individualmente, consulte Potencialmente victorioso y Big King Little Hill .

function (me, monsters, coins) {
    var i, monstersCount = monsters.length, phaseSize = Math.round((me.arenaLength - 4) / 4),
        center = (me.arenaLength - 1) / 2, centerSize = me.arenaLength / 4,
        centerMin = center - centerSize, centerMax = center + centerSize, centerMonsters = 0, centerMonstersAvg = null,
        end = 2e4, apocalypse = end - ((me.arenaLength * 2) + 20), mode = null;

    var getDistance = function (x1, y1, x2, y2) {
        return (Math.abs(x1 - x2) + Math.abs(y1 - y2)) + 1;
    };

    var isAtCenter = function (x, y) {
        return (x > centerMin && x < centerMax && y > centerMin && y < centerMax);
    };

    var round = botNotes.getData('round');
    if (round === null || !round) round = 0;
    round++;
    botNotes.storeData('round', round);

    var isApocalypse = (round >= apocalypse && round <= end);
    if (isApocalypse) {
        mode = botNotes.getData('mode');
        if (mode === null || !mode) mode = 1;
    }

    for (i = 0; i < monstersCount; i++) if (isAtCenter(monsters[i][0], monsters[i][1])) centerMonsters++;

    var lc = botNotes.getData('lc');
    if (lc === null || !lc) lc = [];
    if (lc.length >= 20) lc.shift();
    lc.push(centerMonsters);
    botNotes.storeData('lc', lc);

    if (lc.length >= 20) {
        centerMonstersAvg = 0;
        for (i = 0; i < lc.length; i++) centerMonstersAvg += lc[i];
        centerMonstersAvg = centerMonstersAvg / lc.length;
    }

    var getScore = function (x, y) {
        var score = 0, i, chaseFactor = 0.75, coinFactor = 1;

        if (monstersCount < phaseSize) {
            chaseFactor = 0;
            coinFactor = 0.25;
        } else if (monstersCount < phaseSize * 2) {
            chaseFactor = 0;
            coinFactor = 0.5;
        } else if (monstersCount < phaseSize * 3) {
            chaseFactor = 0.5;
            coinFactor = 0.75;
        }

        if (isApocalypse) {
            if (mode === 1) {
                var centerDistance = getDistance(x, y, center, center);
                if (centerDistance <= 3) {
                    mode = 2;
                } else {
                    score += 5000 / (centerDistance / 10);
                }
            }
            if (mode === 2) chaseFactor = 1000;
        }

        for (i = 0; i < monstersCount; i++) {
            var monsterCoins = monsters[i][2], monsterDistance = getDistance(x, y, monsters[i][0], monsters[i][1]);
            if (me.coins > monsterCoins && monsterDistance <= 3) {
                score += (Math.min(5, monsterCoins) * chaseFactor) / monsterDistance;
            } else if (me.coins <= monsterCoins && monsterDistance <= 3) {
                score -= (monsterDistance === 3 ? 50 : 10000);
            }
        }

        for (i = 0; i < coins.length; i++) {
            var coinDistance = getDistance(x, y, coins[i][0], coins[i][1]),
                coinDistanceCenter = getDistance(center, center, coins[i][0], coins[i][1]),
                coinValue = (i === 0 ? 250 : 100), coinCloserMonsters = 0;

            for (var j = 0; j < monstersCount; j++) {
                var coinMonsterDistance = getDistance(monsters[j][0], monsters[j][1], coins[i][0], coins[i][1]);
                monsterCoins = monsters[j][2];

                if (
                    (coinMonsterDistance < coinDistance && monsterCoins >= me.coins / 2) ||
                    (coinMonsterDistance <= coinDistance && monsterCoins >= me.coins)
                ) {
                    coinCloserMonsters++;
                }
            }

            var coinMonsterFactor = (100 - ((100 / monstersCount) * coinCloserMonsters)) / 100;
            if (coinMonsterFactor < 1) coinMonsterFactor *= coinFactor;
            if (coinMonsterFactor >= 1) coinMonsterFactor *= 15;
            score += ((coinValue * coinMonsterFactor) / coinDistance) + (centerMonstersAvg === null || centerMonstersAvg > 1.75 ? -1 * (50 / coinDistanceCenter) : 200 / coinDistanceCenter);
        }

        return score + Math.random();
    };

    var possibleMoves = [{x: 0, y: 0, c: 'none'}];
    if (me.locationX > 0) possibleMoves.push({x: -1, y: 0, c: 'west'});
    if (me.locationY > 0) possibleMoves.push({x: -0, y: -1, c: 'north'});
    if (me.locationX < me.arenaLength - 1) possibleMoves.push({x: 1, y: 0, c: 'east'});
    if (me.locationY < me.arenaLength - 1) possibleMoves.push({x: 0, y: 1, c: 'south'});

    var topCommand, topScore = null;
    for (i = 0; i < possibleMoves.length; i++) {
        var score = getScore(me.locationX + possibleMoves[i].x, me.locationY + possibleMoves[i].y);
        if (topScore === null || score > topScore) {
            topScore = score;
            topCommand = possibleMoves[i].c;
        }
    }

    if (isApocalypse) botNotes.storeData('mode', mode);

    return topCommand;
}

Este bot (también conocido como "TBTPTGCBCBA") intenta tomar la mejor decisión posible generando una puntuación para cada movimiento posible y selecciona el movimiento con una puntuación más alta para cada turno.

El sistema de puntuación tiene muchos detalles que han evolucionado desde el inicio del desafío. Generalmente se pueden describir así:

  • Cuanto más se acerquen las monedas a un posible movimiento, más puntuación obtendrá ese movimiento. Si una moneda no tiene otros posibles concursantes, el puntaje va aún más alto. Si una moneda tiene otros posibles concursantes, la puntuación baja.
  • Si otro bot está cerca de un posible movimiento y tiene menos monedas, dependiendo de la fase del juego, podría significar más puntaje para ese movimiento. Por lo tanto, es casual que "TBTPTGCBCBA" coma algunos otros bots en cada juego.
  • Si otro bot está cerca de un posible movimiento con igual o más puntos, ese movimiento obtiene suficiente puntaje negativo para asegurarse de evitar la muerte. Por supuesto, podría haber algunos casos en los que todos los movimientos posibles sean malos y no se pueda evitar la muerte, pero eso es muy raro.
  • Hay un mecanismo para realizar un seguimiento del número de bots en el medio del tablero durante los últimos 20 turnos. Si el promedio es lo suficientemente bajo, todos los movimientos hacia las monedas en el medio obtienen más puntaje y si el promedio es alto, entonces todos los movimientos hacia las monedas en el medio obtienen un puntaje más bajo. Este mecanismo permite evitar conflictos con "Noble feudal". Dado que el "Noble feudal" siempre está en el medio (a menos que esté siendo perseguido), el número promedio de bots en el medio aumenta y "TBTPTGCBCBA" comprende evitar el medio si hay una mejor opción fuera del área central. Si "Noble feudal" muere, el promedio baja y "TBTPTGCBCBA" entiende que puede usar el medio.
  • Hay algunos factores que cambian dinámicamente según la fase del juego (detectada por el número de bots vivos), estos factores afectan la puntuación en cada uno de los elementos anteriores.
  • Este bot tiene una habilidad especial. Con el tiempo se cansa del egoísmo del "noble feudal" y de la opresión de los campesinos. En el momento adecuado, se elevará para poner fin al desagradable sistema de feudalismo. Un intento exitoso no solo ayuda a los campesinos pobres, sino que también brinda una mayor posibilidad de ganar debido a las monedas tomadas del "Noble Feudal".

Parece mucho más ... inteligente que los demás
Redwolf Programs

55
Me gustan los monstruos que forman parte de los params
Programas Redwolf

9

El anti capitalista | Javascript

No tiene ningún incentivo para perseguir monedas, pero trata de ubicarse exactamente entre los dos bots más ricos con la misma cantidad de dinero, con la esperanza de que lo cacen y eventualmente lo atrapen al mismo tiempo, llevándose a dos capitalistas cuando muera. . No se resiste activamente a conseguir monedas, por lo que podría convertirse en un objetivo más jugoso.

function antiCapitalist(me, capitalists, coins){

    function acquireTargets(capitalists){
        capitalists.sort((a, b) => a[2] < b[2]);
        let previousCapitalist;
        for(let i in capitalists){
            let capitalist = capitalists[i];

            if(capitalist[2] === 0){
                return false;
            }
            if(previousCapitalist && capitalist[2] === previousCapitalist[2]){
                return [previousCapitalist, capitalist];
            }

            previousCapitalist = capitalist;
        }

        return false;
    }

    function move(){
        const targets = acquireTargets(capitalists);
        if(!targets){
            return 'none';
        }

        const coordinates = [Math.floor((targets[0][0] + targets[1][0]) / 2), Math.floor((targets[0][1] + targets[1][1]) / 2)];
        if(me.locationX !== coordinates[0]){
            return me.locationX < coordinates[0] ? 'east' : 'west';
        }
        else if(me.locationX !== coordinates[1]){
            return me.locationY < coordinates[1] ? 'south' : 'north';
        }
        else {
            return 'none';
        }
    }

    return move();
}

9

El intestino, JavaScript

function gut(me, others, coins) {
    // Prepare values for the calculation
    var x = me.locationX;
    var y = me.locationY;
    var cMe = me.coins+1;
    var arenaLen = me.arenaLength;

    var objects = [];

    // Add bots to objects
    for (var i = 0; i < others.length; i++) {
        objects.push([others[i][0],others[i][1],others[i][2]/cMe]);
    }

    // Add coins to objects
    for (var j = 0; j < coins.length; j++) {
        var coinVal = 0;

        if (j == 0) {
            // Gold has a higher coin value
            coinVal = -10;
        } else {
            // Silver has a lower coin value
            coinVal = -5;
        }

        objects.push([coins[j][0],coins[j][1],coinVal/cMe]);
    }

    // Perform the calculation
    // x acceleration
    var x_acceleration = 0;

    for (var k=0; k < objects.length; k++) {
        var kval = objects[k][2];
        var xval = objects[k][0];

        x_acceleration += 200*kval/cMe*(x-xval)*Math.exp(Math.pow(kval,2)-50*Math.pow(x-xval,2));
    }

    // y acceleration
    var y_acceleration = 0;

    for (var l=0; l < objects.length; l++) {
        var kval = objects[l][2];
        var yval = objects[l][1];

        y_acceleration += 200*kval/cMe*(y-yval)*Math.exp(Math.pow(kval,2)-50*Math.pow(y-yval,2));
    }

    // Compare the values
    if (Math.abs(y_acceleration)>Math.abs(x_acceleration)) {
        if (y_acceleration < 0) {
            // Don't fall off the edge
            if (y>0) {
                return "north";
            } else {
                return "none";
            }
        } else {
            if (y<arenaLen-1) {
                return "south";
            } else {
                return "none";
            }
        }
    } else if (Math.abs(y_acceleration)<Math.abs(x_acceleration)) {
        if (x_acceleration < 0) {
            if (x>0) {
                return "west";
            } else {
                return "none";
            }
        } else {
            if (x<arenaLen-1) {
                return "east";
            } else {
                return "none";
            }
        }
    } else {
        return "none";
    }
}

Con Potencialmente victorioso tenemos dos campos: el campo bot y el campo de monedas. Sin embargo, la naturaleza no es tan complicada. Es hora de unificar los dos campos para producir la Gran Teoría Unificada .

En primer lugar, tenemos que determinar cuál es el potencial del campo. Asumiendo que nuestro propio bot no influye en el campo de ninguna manera, podemos escribir esto como:

V=nkn(ekn2100(xxn)2+ekn2100(yyn)2)

knorte(xnorte,ynorte)

La propiedad relativa del objeto se calcula así:

k=CobjetoCyo

CCyo=Cyo+1Cyo

Llamemos a esta corrección parte de Dinámica Betaniana Modificada (MOBD) .

También podemos encontrar la energía cinética como:

T=12Cyo(X˙2+y˙2)

Ahora podemos calcular la acción:

Acción=unasi(T-V)ret=unasi(12Cyo(X˙2+y˙2)-norteknorte(miknorte2-100(X-Xnorte)2+miknorte2-100(y-ynorte)2))ret

Y entonces el lagrangiano de nuestro bot en el campo coin-bot es:

L=12Cyo(X˙2+y˙2)-norteknorte(miknorte2-100(X-Xnorte)2+miknorte2-100(y-ynorte)2)

Ahora necesitamos resolver las ecuaciones de Euler-Lagrange:

reretLX˙=LX

y:

reretLy˙=Ly

Entonces:

reretLX˙=reret[CyoX˙]=CyoX¨

LX=norte200knorte(X-Xnorte)miknorte2-100(X-Xnorte)2

X¨=norte200knorteCyo(X-Xnorte)miknorte2-100(X-Xnorte)2

Y también:

reretLy˙=reret[Cyoy˙]=Cyoy¨

Ly=norte200knorte(y-ynorte)miknorte2-100(y-ynorte)2

y¨=norte200knorteCyo(y-ynorte)miknorte2-100(y-ynorte)2

Ahora no necesitamos ir más allá: solo miramos la dirección de la aceleración general:

salida={norteSi y¨<0 0 y El |y¨El |>El |X¨El |surSi y¨>0 0 y El |y¨El |>El |X¨El |OesteSi X¨<0 0 y El |X¨El |>El |y¨El |esteSi X¨>0 0 y El |X¨El |>El |y¨El |ningunaSi El |y¨El |=El |X¨El |

Y así, hemos unificado las monedas y los bots. ¿Dónde está mi premio Nobel?


55
Su Premio Nobel se perdió en el correo, pero podríamos darle un Premio Emmy en su lugar
Programas Redwolf

1
Parece que la física comienza a popularizarse en este desafío. :-RE. Y, por supuesto, tengo mucha curiosidad acerca de qué tan bien lo hará.
Ramillies

1
(Por cierto, podría haber ahorrado la molestia con las ecuaciones de Euler-Lagrange, porque reducen al hecho bien conocido de que F = c_me a = - grad U :—).)
Ramillies

@Ramillies Meh, fue más divertido hacerlo de esta manera: D
Beta Decay

1
¿Estás seguro de que quieres usar las monedas k = de otra cosa / tus monedas? Empiezas sin monedas ... y con NaN en todas partes, no es muy probable que obtengas ninguna.
Ramillies

8

Ricitos de oro, JavaScript (Node.js)

function goldilocks(me, others, coins) {
  let target = coins[0]; // Gold
  let x = target[0] - me.locationX;
  let y = target[1] - me.locationY;

  mymove = 'none'
  if (Math.abs(x) <= Math.abs(y) && x != 0)
    mymove = x < 0 ? 'west' : 'east'
  else if (y != 0)
    mymove = y < 0 ? 'north' : 'south'

  return mymove
}

Pruébalo en línea!

Simplemente se fija en la ubicación de la moneda de oro y se mueve hacia ella cada vez. (Gracias al bot 'B33-L1N3' de @ Mayube por el código original que usó, aunque apenas queda algo de él).


Este es un bot bastante agradable y simple. Me gusta.
Programas Redwolf

2
Por cierto, estoy usando este bot como prueba para mi controlador (:
Programas Redwolf

8

Algoritmo de aprendizaje de tercera generación | JavaScript (Node.js)

function run(me) {
	options = [];
	if (me.locationX > 0) options.push('west');
	if (me.locationY > 0) options.push('north');
	if (me.locationX < me.arenaLength) options.push('east');
	if (me.locationY < me.arenaLength) options.push('south');

	return options[Math.floor(Math.random() * options.length)];
}

Pruébalo en línea!

Después de algunas generaciones de aprendizaje, este bot ha aprendido que abandonar la arena = malo


Oh Dios. Escuché que esto se llama "Selección Natural"
Programas Redwolf

55
¿Dónde está la segunda generación?
Luis felipe De jesus Munoz

11
@LuisfelipeDejesusMunoz Salió de la arena.
Jo.

Este es un buen bot para depurar el controlador
Redwolf Programs

3
Ah, por cierto, la arena comienza en 0, por lo que debería ser arenaLength - 1. Esto mató a su bot varias veces para muchos
Redwolf Programs

7

B33-L1N3 | JavaScript (Node.js)

function(me, others, coins) {
	// Do nothing if there aren't any coins
	if (coins.length == 0) return 'none';
	// Sort by distance using Pythagoras' Theorem
	coins = coins.sort((a, b) => (a[0] ** 2 + a[1] ** 2) - (b[0] ** 2 + b[1] ** 2));
	// Closest coin
	let target = coins[0];
	let x = target[0];
	let y = target[1];

	// Util function for movement
	function move(pos, type) {
		let moveTypes = { X: ['east', 'west'], Y: ['south', 'north'] };
		if (pos > me['location'+type]) return moveTypes[type][0];
		else return moveTypes[type][1];
	}

	// Move the shortest distance first
	if (x < y && x != me.locationX) return move(x, 'X');
	else if (y != me.locationY) return move(y, 'Y');
}

Pruébalo en línea!

Hace una línea recta hacia la moneda más cercana


Oh, pensé B33-L1N3 era una especie de número de modelo
Programas Redwolf

+1 para el nombre
Caín

let coins = ...Uncaught SyntaxError: Identifier 'coins' has already been declared
Noche2

Eliminar ellet
Programas Redwolf

5

Viviendo en el borde, JavaScript

function LivinOnTheEdge (myself, others, coins) {
  x = myself.locationX;
  y = myself.locationY;
  xymax = myself.arenaLength - 1;
  if (x < xymax && y == 0) {
      return 'east';
    } else if (y < xymax && x == xymax) {
      return 'south';
    } else if (x > 0 && y == xymax) {
      return 'west';
  } else {
    return 'north';
  }
}

Este escuchó que el borde de la arena es un lugar peligroso para estar. Sin temor, gira incansablemente el tablero en el sentido de las agujas del reloj, a solo centímetros de la muerte segura que espera detrás de la frontera, esperando que ningún otro robot se atreva a moverse tan cerca de la vecindad del borde.


1
Esto no terminaría bien si se creara otro bot que tuviera 1 moneda más, y patrullara el borde en la dirección opuesta (:
Programas Redwolf

8
Haría una broma de control fronterizo, pero la dejo a @BetaDecay
Redwolf Programs

5

Damacy, JavaScript (Node.js)

function damacy(me, others, coin) {
  let xdist = t => Math.abs(t[0] - me.locationX)
  let ydist = t => Math.abs(t[1] - me.locationY)
  function distanceCompare(a, b, aWt, bWt) {
    aWt = aWt || 1
    bWt = bWt || 1
    return (xdist(a) + ydist(a)) / aWt - (xdist(b) + ydist(b)) / bWt
  }
  function hasThreat(loc) {
    let threat = others.filter(b => b[0] == loc[0] && b[1] == loc[1] && b[2] >= me.coins)
    return (threat.length > 0)
  }
  function inArena(loc) {  // probably unnecessary for this bot
    return loc[0] >= 0 && loc[1] >= 0 && loc[0] < me.arenaLength && loc[1] < me.arenaLength
  }
  function sortedCoins() {
    coinsWithValues = coin.map((coords, i) => coords.concat((i == 0) ? 5 : 2))
    coinsWithValues.sort((a, b) => distanceCompare(a, b, a[2], b[2]))
    return coinsWithValues.map(c => c.slice(0, 2))
  }
  othersPrev = botNotes.getData('kata_others_pos')
  botNotes.storeData('kata_others_pos', others)
  if (othersPrev) {

    for(let i = 0; i < others.length; i++) {
      let bot = others[i]

      let matchingBots = othersPrev.filter(function (b) {
        let diff = Math.abs(b[0] - bot[0]) + Math.abs(b[1] - bot[1])
        if (diff >= 2)
          return false // bot can't have jumped
        return [0, 2, 5].includes(bot[2] - b[2])
      })

      if (matchingBots.length > 0) {
        let botPrev = matchingBots.shift()
        // remove matched bot so it doesn't get matched again later
        othersPrev = othersPrev.filter(b => b[0] != botPrev[0] || b[1] != botPrev[1])
        bot[0] = Math.min(Math.max(bot[0] + bot[0] - botPrev[0], 0), me.arenaLength-1)
        bot[1] = Math.min(Math.max(bot[1] + bot[1] - botPrev[1], 0), me.arenaLength-1)
      }
    }
  }

  let eatables = others.filter(b => b[2] < me.coins && b[2] > 0)
  let targets
  if (eatables.length > 0) {
    targets = eatables.sort(distanceCompare)
  }
  else {
    targets = sortedCoins()
  }

  let done, newLoc, dir
  while (!done && targets.length > 0) {
    t = targets.shift()
    if ((xdist(t) <= ydist(t) || ydist(t) == 0) && xdist(t) != 0) {
      let xmove = Math.sign(t[0] - me.locationX)
      dir = xmove < 0 ? 'west' : 'east'
      newLoc = [me.locationX + xmove, me.locationY]
      if (!hasThreat(newLoc) && inArena(newLoc))
        done = 1
    }

    if (!done) {
      let ymove = Math.sign(t[1] - me.locationY)
      dir = ['north', 'none', 'south'][ymove + 1]
      newLoc = [me.locationX, me.locationY + ymove]
      if (!hasThreat(newLoc) && inArena(newLoc))
        done = 1
    }
  }

  if (!done)
    dir = 'none'


  return dir
}

Pruébalo en línea!

Un último bot basado en katamari para hoy, esta vez con un poco de memoria. Gracias a @BetaDecay por la sugerencia de nombre, definitivamente un nombre más divertido que el mío simplePredictorKatamari.

Intenta descubrir cómo se han movido los bots en el último turno, y en base a eso, predice dónde intentarán moverse al final de este turno (suponiendo que continúen moviéndose en la misma dirección).

(Gracias a @ fəˈnɛtɪk, por notar que estaba llamando al nombre de función incorrecto en botNotes, y a @ OMᗺ por notar un error en el código base).


Este es probablemente el único en este momento que puede atrapar a otros fuera de ser afortunado.
Caín

¿No se supone que las notas son "storedata" no setdata?
fəˈnɛtɪk

@ fəˈnɛtɪk Mira, ¡ya necesita una corrección de errores! :) Gracias, corregido ahora.
sundar - Restablece a Mónica el

Debe reemplazar aWt = 1en los params con aWty poner aWt = aWt || 1debajo (Igual con bWt). Esto evita errores.
Programas Redwolf

5

Protón | JavaScript

Proton=(myself,others,coins)=>{
  x=myself.locationX;
  y=myself.locationY;
  power=myself.coins;
  arenaSize=myself.arenaLength;
  forceX=0;
  forceY=0;
  prevState=botNotes.getData("proton_velocity");
  if(prevState){
    velocity=prevState[0];
    direction=prevState[1];
  }
  else{
    velocity=0;
    direction=0;
  }
  for(i=0;i<coins.length;i++){
    if(Math.abs(x-coins[i][0])+Math.abs(y-coins[i][1])==1){
      velocity=0;
      direction=0;
      botNotes.storeData("proton_velocity",[velocity,direction]);
      if(x-coins[i][0]==1){return "west";}
      if(coins[i][0]-x==1){return "east";}
      if(y-coins[i][1]==1){return "north";}
      if(coins[i][1]-y==1){return "south";}
    }
    else{
      dist=Math.sqrt(Math.pow(x-coins[i][0],2)+Math.pow(y-coins[i][1],2));
      if(i==0){
        forceX+=(x-coins[i][0])*5/Math.pow(dist,3);
        forceY+=(y-coins[i][1])*5/Math.pow(dist,3);
      }
      else{
        forceX+=(x-coins[i][0])*2/Math.pow(dist,3);
        forceY+=(y-coins[i][1])*2/Math.pow(dist,3);
      }
    }
  }
  for(i=0;i<others.length;i++){
    if(Math.abs(x-others[i][0])+Math.abs(y-others[i][1])==1&&power>others[i][2]){
      velocity=0;
      direction=0;
      botNotes.storeData("proton_velocity",[velocity,direction]);
      if(x-others[i][0]==1){return "west";}
      if(others[i][0]-x==1){return "east";}
      if(y-others[i][1]==1){return "north";}
      if(others[i][1]-y==1){return "south";}
    }
    else{
      dist=Math.sqrt(Math.pow(x-others[i][0],2)+Math.pow(y-others[i][1],2));
      forceX+=(x-others[i][0])*others[i][2]/Math.pow(dist,3);
      forceY+=(y-others[i][1])*others[i][2]/Math.pow(dist,3);
    }
  }
  vX=velocity*Math.cos(direction)+10*forceX/Math.max(1,power);
  vY=velocity*Math.sin(direction)+10*forceY/Math.max(1,power);
  velocity=Math.sqrt(vX*vX+vY*vY);
  if(velocity==0){return "none"}
  retval="none";
  if(Math.abs(vX)>Math.abs(vY)){
    if(vX>0){
      if(x<arenaSize-1){retval="east";}
      else{vX=-vX;retval="west";}
    }
    else{
      if(x>0){retval="west";}
      else{vX=-vX;retval="east";}
    }
  }
  else{
    if(vY>0){
      if(y<arenaSize-1){retval="south";}
      else{vY=-vY;retval="north";}
    }
    else{
      if(y>0){retval="north";}
      else{vY=-vY;retval="south";}
    }
  }
  direction=Math.atan2(-vY,vX);
  botNotes.storeData("proton_velocity",[velocity,direction]);
  return retval;
}

Todas las monedas (incluidas las que tienen otros bots) emiten una fuerza repulsiva hacia Protonbot. Basado en esta fuerza, aumenta la velocidad y rebota en las paredes (se da vuelta inmediatamente al golpear un límite). Si termina al lado de un bot o moneda que puede consumir, la fuerza nuclear fuerte se hace cargo y se mueve para consumirlo, bajando toda la velocidad cuando lo hace.


¿La física nuclear aplicada a la búsqueda del tesoro? ¡Esto supera a Science Channel cualquier día!
Programas Redwolf

sinMath.sincosMath.cos
Debe

4

No tan ciegamente | JavaScript (Node.js)

Nota importante: este enfoque no es del todo mío y ha sido respondido en un pregunta similar . Asegúrese de votar esa respuesta también.

¿Alguna vez has oído hablar del algoritmo de búsqueda de rutas A *? aquí está. Crea el mejor camino desde un punto hasta la moneda menos valiosa (como todos buscan lo más valioso, nadie apuesta por lo menos) e intenta no chocar con ningún otro usuario.

Espera parámetros de la siguiente manera:

AI({locationX: 3, locationY: 1, arenaLength: [5,5]}, [[2,1],[2,2], ...],[[1,2],[3,1], ...])

Tal vez hago uno que va a cazar a otros bots


function AI(me, others, coins){
    var h = (a,b) => Math.abs(a[0] -b[0]) + Math.abs(a[1] -b[1])
    var s = JSON.stringify;
    var p = JSON.parse;
    var walls = others.slice(0,2).map(s);
    var start = [me.locationX, me.locationY];
    var goal = coins.pop();
    var is_closed = {};
    is_closed[s(start)] = 0;
    var open = [s(start)];
    var came_from = {};
    var gs = {};
    gs[s(start)] = 0;
    var fs = {};
    fs[s(start)] = h(start, goal);
    var cur;
    while (open.length) {
        var best;
        var bestf = Infinity;
        for (var i = 0; i < open.length; ++i) {
            if (fs[open[i]] < bestf) {
                bestf = fs[open[i]];
                best = i;
            }
        }
        cur = p(open.splice(best, 1)[0]);
        is_closed[s(cur)] = 1;
        if (s(cur) == s(goal)) break;
        for (var d of [[0, 1], [0, -1], [1, 0], [-1, 0]]) {
            var next = [cur[0] + d[0], cur[1] + d[1]];
            if (next[0] < 0 || next[0] >= me.arenaLength[0] ||
                next[1] < 0 || next[1] >= me.arenaLength[1]) {
                continue;
            }
            if (is_closed[s(next)]) continue;
            if (open.indexOf(s(next)) == -1) open.push(s(next));
            var is_wall = walls.indexOf(s(next)) > -1;
            var g = gs[s(cur)] + 1 + 10000 * is_wall;
            if (gs[s(next)] != undefined && g > gs[s(next)]) continue;
            came_from[s(next)] = cur;
            gs[s(next)] = g;
            fs[s(next)] = g + h(next, goal);
        }
    }
    var path = [cur];
    while (came_from[s(cur)] != undefined) {
        cur = came_from[s(cur)];
        path.push(cur);
    }
    var c = path[path.length - 1];
    var n = path[path.length - 2];
    if(n){
        if (n[0] < c[0]) {
            return "west";
        } else if (n[0] > c[0]) {
            return "east";
        } else if (n[1] < c[1]) {
            return "north";
        } else {
            return "south";
        }
    }else{
        return "none";
    }
}

1
Wow ... un algoritmo de búsqueda de ruta ya? ¡Solo han pasado 3 horas!
Programas Redwolf

@RedwolfPrograms Como dije, está copiado de otro desafío similar. Solo necesitaba adaptarlo a este.
Luis felipe De jesus Munoz

Mis algoritmos se aplican a las monedas más seguras.
fəˈnɛtɪk

4

Cobarde | Python 2

import random

def move(me, others, coins):
    target = (me.locationX, me.locationY)

    # Identify the dangerous opponents.
    threats = [i for i, value in enumerate(others[2]) if value >= me.coins]

    # If no one scary is nearby, find a nearby coin.
    safe = True
    for x, y in self.coins:
        distance = abs(me.locationX - x) + abs(me.locationY - y)
        safe = True
        for i in threats:
            if abs(others[0][i] - x) + abs(others[1][i] - y) <= distance:
                safe = False
                break

        if safe:
            target = (x, y)
            break

    # Otherwise, just try not to die.
    if not safe:
        certain = []
        possible = []
        for x, y in [
            (me.locationX, me.locationY),
            (me.locationX + 1, me.locationY),
            (me.locationX - 1, me.locationY),
            (me.locationX, me.locationY + 1),
            (me.locationX, me.locationY - 1),
        ]:
            # Don't jump off the board.
            if x < 0 or y < 0 or x == me.arenaLength or y == me.arenaLength:
                continue

            # Check if we can get away safely.
            for i in threats:
                if abs(others[0][i] - x) + abs(others[1][i] - y) <= 1:
                    break
            else:
                certain.append((x, y))

            # Check if we can take a spot someone is leaving.
            for i in threats:
                if others[0][i] = x and others[1][i] == y:
                    for i in threats:
                        if abs(others[0][i] - x) + abs(others[1][i] - y) == 1:
                            break
                    else:
                        possible.append((x, y))

        if certain:
            target = random.choice(certain)
        elif possible:
            target = random.choice(possible)
        # Otherwise, we're doomed, so stay still and pray.

    directions = []
    x, y = target
    if x < me.locationX:
        directions.append('west')
    if x > me.locationX:
        directions.append('east')
    if y < me.locationY:
        directions.append('north')
    if y > me.locationY:
        directions.append('south')
    if not directions:
        directions.append('none')

    return random.choice(directions)

Evite los robots con más dinero si es posible. De lo contrario, tome el dinero que está por ahí.


Este es el bot más básico que tiene la oportunidad de ganar
Redwolf Programs

4

Ganso salvaje Chase Bot, Javascript

Un bot que es realmente bueno esquivando a otros bots, pero muy malo para conseguir monedas.


Algoritmo:

  1. Si no hay bots adyacentes, no devuelva ninguno
  2. De otra manera:
    1. No devuelva ninguno con una probabilidad aleatoria de 1/500 de probabilidad (esto está destinado a evitar estancamientos).
    2. Determine a qué espacios es seguro moverse (es decir, dentro de la arena y no ocupados por otro bot)
    3. Devuelve uno al azar

Código:

function wildGooseChase(me, others, coins){
    x = me.locationX;
    y = me.locationY;

    dirs = {};
    dirs[(x+1)+" "+y] = "east";
    dirs[(x-1)+" "+y] = "west";
    dirs[x+" "+(y+1)] = "south";
    dirs[x+" "+(y-1)] = "north";

    mov = {};
    mov["east"] = [x+1,y];
    mov["west"] = [x-1,y];
    mov["north"] = [x,y-1];
    mov["south"] = [x,y+1]; 

    possibleDirs = ["east","west","north","south"];

    for (i = 0; i < others.length; i++){
        if (others[i][0]+" "+others[i][1] in dirs){
            possibleDirs.splice(possibleDirs.indexOf(dirs[others[i][0]+" "+others[i][1]]),1);
        }
    }

    if (possibleDirs.length == 4 || Math.floor(Math.random() * 500) == 0){
        return "none"
    }

    for (i = 0; i < possibleDirs.length; i++){
        if (mov[possibleDirs[i]][0] == me.arenaLength || mov[possibleDirs[i]][0] < 0 
        || mov[possibleDirs[i]][1] == me.arenaLength || mov[possibleDirs[i]][1] < 0){
            var index = possibleDirs.indexOf(possibleDirs[i]);
            if (index != -1) {
                possibleDirs.splice(index, 1);
                i--;
            }
        }
    }

    if (possibleDirs.length == 0){
         return "none";
    }

    return possibleDirs[Math.floor(Math.random() * possibleDirs.length)];
}

Pruébalo en línea!

Nota para los programas Redwolf:

Este bot tiene el potencial de causar rondas muy largas. Me he tomado algunas libertades para evitar estancamientos, pero no he probado si son realmente efectivos. Si este bot se convierte en un problema durante la prueba, no dude en descalificarlo.


Gracias por la nota Un evasor experto tiene una buena oportunidad si por casualidad recolecta suficientes monedas mientras es perseguido
Programas Redwolf

Me gusta esto. Es casi como un cebo para los robots de caza
Beta Decay

4

KatamariWithValues, JavaScript (Node.js) ,

function katamariWithValues(me, others, coin) {
  let xdist = t => Math.abs(t[0] - me.locationX)
  let ydist = t => Math.abs(t[1] - me.locationY)
  function distanceCompare(a, b, aWt = 1, bWt = 1) {
    return (xdist(a) + ydist(a)) / aWt - (xdist(b) + ydist(b)) / bWt
  }
  function hasThreat(loc) {
    let threat = others.filter(b => b[0] == loc[0] && b[1] == loc[1] && b[2] >= me.coins)
    return (threat.length > 0)
  }
  function inArena(loc) {  // probably unnecessary for this bot
    return loc[0] >= 0 && loc[1] >= 0 && loc[0] < me.arenaLength && loc[1] < me.arenaLength
  }
  function sortedCoins() {
    coinsWithValues = coin.map((coords, i) => coords.concat((i == 0) ? 5 : 2))
    coinsWithValues.sort((a, b) => distanceCompare(a, b, a[2], b[2]))
    return coinsWithValues.map(c => c.slice(0, 2))
  }

  let eatables = others.filter(b => b[2] < me.coins && b[2] > 0)
  let targets
  if (eatables.length > 0) {
    targets = eatables.sort(distanceCompare)
  }
  else {
    targets = sortedCoins()
  }

  let done, newLoc, dir
  while (!done && targets.length > 0) {
    t = targets.shift()
    if ((xdist(t) <= ydist(t) || ydist(t) == 0) && xdist(t) != 0) {
      let xmove = Math.sign(t[0] - me.locationX)
      dir = xmove < 0 ? 'west' : 'east'
      newLoc = [me.locationX + xmove, me.locationY]
      if (!hasThreat(newLoc) && inArena(newLoc))
        done = 1
    }

    if (!done) {
      let ymove = Math.sign(t[1] - me.locationY)
      dir = ['north', 'none', 'south'][ymove + 1]
      newLoc = [me.locationX, me.locationY + ymove]
      if (!hasThreat(newLoc) && inArena(newLoc))
        done = 1
    }
  }

  if (!done)
    dir = 'none'

  return dir
}

Pruébalo en línea!

(Gracias a @ OMᗺ por señalar un error en el código original en el que se basa).

Intenta crecer "comiendo" bots con menos monedas que él mismo. Si eso no es posible (no existe tal bot), entonces busca la moneda más cercana.

Esta versión tiene pequeños ajustes para (a) dar mayor preferencia a las monedas de oro que a las monedas de plata, con el riesgo de que buscar una moneda de oro más distante pueda terminar costando la vida del bot o conducir a perseguir al oro del tonto (b) saltar bots con 0 monedas: no hay necesidad de perder el tiempo persiguiendo esas.


Un cazador inteligente ... bueno, ¡eso es aún mejor!
Programas Redwolf

@RedwolfPrograms ¡Esperemos que sí! :)
Sundar - Restablece a Mónica el

Debería haber llamado a esto Damacy;)
Beta Decay


4

Cortés borracho miope bot | JavaScript

function politeNearSightedDrunkBot(me, others, coins) {
  let directions = ['none','east','south','west','north']
  let drunkennessCoefficient = .2
  let nearSightedness = me.arenaLength - others.length + 2
  //drawCircle(me.locationX, me.locationY, nearSightedness*squareSize)

  function randomInt(a) {
    return Math.floor(Math.random() * a);
  }
  function getRandomDirection() {
    return ['east', 'west', 'north', 'south'][randomInt(4)]
  }

  function distanceTo(a) {
    return (Math.abs(a[0] - me.locationX) + Math.abs(a[1] - me.locationY))
  }
  function distanceBetween(a, b){
    return (Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]))
  }
  function isTargetSafe(a) {
    for (let i = 0; i < others.length; i++) {
      if (others[i][2] >= me.coins && distanceBetween(a, others[i]) <= distanceTo(a)) {
        return false //unnecessary loop, but I don't want to split out into a function
      }
    }
    return true
  }
  function amISafe() {
    for (let i = 0; i < others.length; i++) {
      if (others[i][2] >= me.coins && distanceTo(others[i]) == 1) {
        /*let num = botNotes.getData('turnsSpentAdjacentToEnemy')
        if (!num) {
          console.log('politeNearSightedDrunkBot: Woops!')
          botNotes.storeData('turnsSpentAdjacentToEnemy', 1)
        } else if (num == 1) {
          console.log('politeNearSightedDrunkBot: \'Scuse me...')
          botNotes.storeData('turnsSpentAdjacentToEnemy', 2)
        } else if (num == 2) {
          console.log('politeNearSightedDrunkBot: D\'ye mind?')
          botNotes.storeData('turnsSpentAdjacentToEnemy', 3)
        } else if (num == 3) {
          console.log('politeNearSightedDrunkBot: Bugger off!')
        }*/
        return false
      }
    }
    return true
  }
  function getSafeDirections() {
    let candidates = {'none': true, 'east': true, 'south': true, 'west': true, 'north': true}
    if (me.locationY == 0) {
      candidates['north'] = false
    } else if (me.locationY == me.arenaLength - 1) {
      candidates['south'] = false
    }
    if (me.locationX == 0) {
      candidates['west'] = false
    } else if (me.locationX == me.arenaLength - 1) {
      candidates['east'] = false
    }
    if (!amISafe()) {
      candidates['none'] = false
    }/* else {
      botNotes.storeData('turnsSpentAdjacentToEnemy', 0)
    }*/
    if (candidates['north'] && !isTargetSafe([me.locationX, me.locationY-1])) {
      candidates['north'] = false
    }
    if (candidates['south'] && !isTargetSafe([me.locationX, me.locationY+1])) {
      candidates['south'] = false
    }
    if (candidates['west'] && !isTargetSafe([me.locationX-1, me.locationY])) {
      candidates['west'] = false
    }
    if (candidates['east'] && !isTargetSafe([me.locationX+1, me.locationY])) {
      candidates['east'] = false
    }
    if (candidates['none']) {
    }
    return candidates
  }
  function getSafeCoins() {
    let safestCoins = []
    let coinSizes = [5, 2, 2, 2, 2]
    for (let i = 0; i < coins.length; i++) {
      let distanceToThisCoin = distanceTo(coins[i])
      if (distanceToThisCoin < nearSightedness && isTargetSafe(coins[i])) {
        safestCoins.push([coins[i][0], coins[i][1], coinSizes[i], distanceToThisCoin])
        //alert('Coin at (' + coins[i][0] + ', ' + coins[i][1] + ') is safe!')
      }
    }
    if (safestCoins.length == 0) {
      //alert('No safe coins!')
    }
    return safestCoins
  }

  function getAdditiveBestDirectionToTargets(targets) {
    let candidates = {'east': 0, 'south': 0, 'west': 0, 'north': 0}
    for (let i = 0; i < targets.length; i++) {
      if (targets[i][0] < me.locationX) { 
        candidates['west'] = candidates['west'] + targets[i][2]/targets[i][3]
      } else if (targets[i][0] > me.locationX) {
        candidates['east'] = candidates['east'] + targets[i][2]/targets[i][3]
      }
      if (targets[i][1] > me.locationY) { 
        candidates['south'] = candidates['south'] + targets[i][2]/targets[i][3]
      } else if (targets[i][1] < me.locationY) {
        candidates['north'] = candidates['north'] + targets[i][2]/targets[i][3]
      }
    }
    for (let key in candidates) {
      //alert(key + ': ' + candidates[key])
    }
    return candidates
  }

    let targetCoins = getSafeCoins()
    let safeDirections = getSafeDirections()
    let chosenDir = null
    if (targetCoins.length > 0) {
      //alert('Coins found! Exactly ' + targetCoins.length)
      let weightedDirections = getAdditiveBestDirectionToTargets(targetCoins)
      let bestOptionWeight = 0
      let choices = []
      for (let key in safeDirections) {
        if (safeDirections[key] && key != 'none') {
          if (weightedDirections[key] == bestOptionWeight) {
            choices.push(key)
          } else if (weightedDirections[key] > bestOptionWeight) {
            choices = [key]
            bestOptionWeight = weightedDirections[key]
          }
        }
      }
      if (choices.length > 0) {
        //alert('Picking from choices, ' + choices.length + ' options and best weight is ' + bestOptionWeight)
        chosenDir = choices[randomInt(choices.length)]
      } else {
        //alert('No safe choices!')
      }
    } else {
      let lastDir = botNotes.getData('direction') || 'none'
      if (safeDirections[lastDir] && Math.random() >= drunkennessCoefficient) {
        chosenDir = lastDir
      }
    }

    if (!chosenDir) {
      //alert('indecisive!')
      let choices = []
      for (key in safeDirections) {
        if (safeDirections[key]) {
          choices.push(key)
        }
      }
      if (choices.length > 0) {
        chosenDir = choices[randomInt(choices.length)]
      } else {
        chosenDir = getRandomDirection()
      }
    }

    botNotes.storeData('direction', chosenDir)
    //alert('Moving ' + chosenDir)
    return chosenDir
}

Se tambalea al recoger monedas cercanas, pero al azar cambia de dirección de vez en cuando. Hace lo que puede para evitar toparse con alguien, pero se pone ... beligerante ... cuando se agrava. Tiende a estar sobrio a medida que avanza la competencia.

Puede necesitar alguna depuración, cuando el controlador esté completamente listo, trabajaré en ello.


3
Hmm, sube el listón, luego se emborracha
Programas Redwolf del

4

Movimiento ponderado | JavaScript

WeightedMotion=(myself,others,coins)=>{
  x=myself.locationX;
  y=myself.locationY;
  power=myself.coins;
  arenaSize=myself.arenaLength;
  dirX=0;
  dirY=0;
  for(i=0;i<coins.length;i++){
    if(i==0){
      dirX+=5/(x-coins[i][0]);
      dirY+=5/(y-coins[i][1]);
    }
    else{
      dirX+=2/(x-coins[i][0]);
      dirY+=2/(y-coins[i][1]);
    }
  }
  for(i=0; i<others.length;i++){
    dirX+=(power-others[i][2])/(2*(x-others[i][0]));
    dirY+=(power-others[i][2])/(2*(y-others[i][1]));
  }
  if(Math.abs(dirX)>Math.abs(dirY)){
    if(dirX>0){
      if(x>0){return "west";}
      else{
        if(dirY>0){if(y>0)return "north";}
        else if(dirY<0){if(y<arenaSize-1)return "south";}
      }
    }
    else if(x<arenaSize-1){return "east";}
    else{
      if(dirY>0){if(y>0)return "north";}
      else if(dirY<0){if(y<arenaSize-1)return "south";}
    }
  }
  else{
    if(dirY>0){
      if(y>0){return "north";}
      else{
        if(dirX>0){if(x>0)return "west";}
        else if(dirX<0){if(x<arenaSize-1)return "east";}
      }
    }
    else if(y<arenaSize-1){return "south";}
    else{
      if(dirX>0){if(x>0)return "west";}
      else if(dirX<0){if(x<arenaSize-1){return "east";}
    }
  }
  return "none";
}

Se mueve en la dirección en que se le ha asignado el valor más alto, evitando al mismo tiempo correr fuera del borde del tablero.

El valor se calcula como tal:

  • Moneda = potencia de la moneda / distancia a la moneda
  • Bot = Diferencia en el poder de los bots / 2 * distancia al bot

1
Bueno, esto parece un bot bastante impresionante. Asegúrese de verificar las instrucciones, ya que sería una pérdida real si su bot fuera un maestro en escapar de las monedas (:
Programas Redwolf

Bueno, aun así. Tengo que ser amable, ¿verdad?
Programas Redwolf

Bueno, publícalo! Compensará los bots más pequeños y rápidos que también existen en este momento en grandes cantidades.
Programas Redwolf

for(i=0;i<6;i++){solo hay 5 monedas en total, 1 de oro y 4 de plata. Su ciclo se ejecuta 6 veces de 0 a 5.
Noche2

3

Ciego | JavaScript (Node.js)

Esto definitivamente no ganará pero al menos participará. Primero intente en el desafío de KoH. Ordena las monedas y va a la más cercana. No busca jugadores, así que no le importa si choca con otros.

function(myself, others, coins){
    mx = myself.locationX
    my = myself.locationY
    l="west"
    r="east"
    u="north"
    d="south"
    n="none"

    if(coins.length == 0)
        return n

    var closestCoin = coins.sort(a=>Math.sqrt(Math.pow(mx-a[0],2) + Math.pow(my-a[1],2))).pop()
    cx = closestCoin[0]
    cy = closestCoin[1]

    return mx>cx?l:mx<cx?r:my>cy?u:my<cy?d:n
}

Hmm, podría funcionar ya que otros bots buscarán el oro principalmente, lo que posiblemente te dejará obtener la plata sin pelear
Redwolf Programs

3

Noble feudal | JavaScript

Color preferido: #268299

function (noble, peasants, coins) {
    var center = (noble.arenaLength - 1) / 2, centerSize = noble.arenaLength / 4, peasantsCount = peasants.length,
        centerMin = center - centerSize, centerMax = center + centerSize, apocalypse = 2e4 - ((noble.arenaLength * 2) + 20), inDanger = false;

    var round = botNotes.getData('round');
    if (round === null || !round) round = 0;
    round++;
    botNotes.storeData('round', round);

    var getDistance = function (x1, y1, x2, y2) {
        return (Math.abs(x1 - x2) + Math.abs(y1 - y2)) + 1;
    };

    var isAtCenter = function (x, y) {
        return (x > centerMin && x < centerMax && y > centerMin && y < centerMax);
    };

    var getScore = function (x, y) {
        var score = 0, i, centerFactor = 10;

        for (i = 0; i < peasantsCount; i++) {
            var peasantCoins = peasants[i][2], peasantDistance = getDistance(x, y, peasants[i][0], peasants[i][1]);

            if (noble.coins > peasantCoins && isAtCenter(x, y)) {
                score += Math.min(100, peasantCoins) / peasantDistance;
            } else if (noble.coins <= peasantCoins && peasantDistance <= 3) {
                score -= (peasantDistance === 3 ? 50 : 2000);
                inDanger = true;
            }
        }

        for (i = 0; i < coins.length; i++) {
            if (isAtCenter(coins[i][0], coins[i][1])) {
                var coinDistance = getDistance(x, y, coins[i][0], coins[i][1]),
                    coinValue = (i === 0 ? 500 : 200),
                    coinCloserPeasants = 1;

                for (var j = 0; j < peasantsCount; j++) {
                    var coinPeasantDistance = getDistance(peasants[j][0], peasants[j][1], coins[i][0], coins[i][1]);
                    if (coinPeasantDistance <= coinDistance && peasants[j][2] >= noble.coins) coinCloserPeasants++;
                }

                score += (coinValue / coinCloserPeasants) / (coinDistance / 3);
            }
        }

        if (round >= apocalypse) centerFactor = 1000;
        score -= getDistance(x, y, center, center) * centerFactor;

        return score;
    };

    var possibleMoves = [{x: 0, y: 0, c: 'none'}];
    if (noble.locationX > 0) possibleMoves.push({x: -1, y: 0, c: 'west'});
    if (noble.locationY > 0) possibleMoves.push({x: -0, y: -1, c: 'north'});
    if (noble.locationX < noble.arenaLength - 1) possibleMoves.push({x: 1, y: 0, c: 'east'});
    if (noble.locationY < noble.arenaLength - 1) possibleMoves.push({x: 0, y: 1, c: 'south'});

    var topCommand, topScore = null;
    for (var i = 0; i < possibleMoves.length; i++) {
        var score = getScore(noble.locationX + possibleMoves[i].x, noble.locationY + possibleMoves[i].y);
        if (topScore === null || score > topScore) {
            topScore = score;
            topCommand = possibleMoves[i].c;
        }
    }

    if (round >= apocalypse) {
        var dg = botNotes.getData('dg');
        if (dg === null || !dg) dg = [];
        if (dg.length >= 20) dg.shift();
        dg.push(inDanger);
        botNotes.storeData('dg', dg);
        if (dg.length >= 20) {
            var itsTime = true;
            for (i = 0; i < dg.length; i++) if (!dg[i]) itsTime = false;
            if (itsTime) return 'none';
        }
    }

    return topCommand;
}

Este noble feudal se queda en el centro del campo y lo reclama como su propio palacio. Recoge cualquier cosa en el centro para sí mismo, pero cualquier cosa en granjas lejanas debería ser traída por los campesinos. Por supuesto, si un poderoso campesino enojado aparece en el palacio, los nobles podrían huir para salvar su vida, ¡pero regresa tan pronto como sea seguro!

A medida que pasa el tiempo, los campesinos se vuelven cada vez más fuertes. Luchadores profesionales y héroes poderosos comienzan a surgir del campesinado. El poder de los nobles sigue decayendo. Intenta mantener su riqueza y su sistema de feudalismo juntos todo el tiempo que pueda. Pero finalmente llega un momento en que debe aceptar su fe, debe aceptar que la gente ya no quiere el feudalismo. Ese es el día en que el noble feudal abandona todo, ya no huye de poderosos campesinos y es asesinado por uno de ellos.


2

Quantum Gnat Bot | JavaScript

function quantumGnatBot(me, others, coins) {
  let quantumCoefficient = .2
  let turn = botNotes.getData('turn')
  botNotes.storeData('turn', turn+1)
  botNotes.storeData('test', [2, 5, 7])
  botNotes.getData('test')
  let dG = {'none': [0, 0, -2, -2], 'east': [1, 0, me.arenaLength-1, -2], 'south': [0, 1, -2, me.arenaLength-1], 'west': [-1, 0, 0, -2], 'north': [0, -1, -2, 0]}

  function randomInt(a) {
    return Math.floor(Math.random() * a);
  }
  function getRandomDirection() {
    return ['east', 'west', 'north', 'south'][randomInt(4)]
  }
  function distanceBetween(a, b){
    return (Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]))
  }
  function isTargetSafe(a) {
    for (let i = 0; i < others.length; i++) {
      if (others[i][2] >= me.coins && distanceBetween(a, others[i]) <= 1) {
        return false
      }
    }
    return true
  }
  function isEnemySquare(a) {
    for (let i = 0; i < others.length; i++) {
      if (distanceBetween(a, others[i]) == 0) {
        return true
      }
    }
    return false
  }
  function getSafeDirections() {
    let candidates = {'none': true, 'east': true, 'south': true, 'west': true, 'north': true}
    for (let key in dG) {
      if (me.locationX == dG[key][2] || me.locationY == dG[key][3] || !isTargetSafe([me.locationX+dG[key][0], me.locationY+dG[key][1]])) {
        candidates[key] = false
      }
    }
    //alert('Safe: ' + candidates['north'] + ', ' + candidates['east'] + ', ' + candidates['south'] + ', ' + candidates['west'])
    return candidates
  }
  function getThreatDirections() {
    let candidates = {'none': false, 'east': false, 'south': false, 'west': false, 'north': false}
    for (let key in dG) {
      if (isEnemySquare([me.locationX+dG[key][0], me.locationY+dG[key][1]])) {
        candidates[key] = true
      }
    }
    return candidates
  }
  function getTargetDirections() {
    let targetBot = null
    let candidates = {'none': false, 'east': false, 'south': false, 'west': false, 'north': false}
    for (let i = 0; i < others.length; i++) {
      if (distanceBetween([me.locationX, me.locationY], others[i]) > 2 && (!targetBot || targetBot[2] < others[i][2])) {
        targetBot = others[i]
      }
    }
    if (targetBot[0] < me.locationX) {
      candidates['west'] = true
    } else if (targetBot[0] > me.locationX) {
      candidates['east'] = true
    }
    if (targetBot[1] > me.locationY) {
      candidates['south'] = true
    } else if (targetBot[1] < me.locationY) {
      candidates['north'] = true
    } 
    //alert('Chasing ' + targetBot[0] + ', ' + targetBot[1] + ' (' + targetBot[2] + ')')
    //alert('Path: ' + candidates['north'] + ', ' + candidates['east'] + ', ' + candidates['south'] + ', ' + candidates['west'])
    return candidates
  }

  let safeDirections = getSafeDirections()
  let threatDirections = getThreatDirections()
  let targetDirections = getTargetDirections()
  let chosenDir = null
  let choices = []
  for (key in safeDirections) {
    if (safeDirections[key] && targetDirections[key]) {
      choices.push(key)
    }
  }
  if (choices.length == 0) {
    //alert('Best options are blocked...')
    for (key in safeDirections) {
      if (safeDirections[key]) {
        choices.push(key)
      }
    }
  }
  for (key in threatDirections) {
    if (threatDirections[key] && Math.random() < quantumCoefficient) {
      //alert('Chance for quantum swap!')
      choices.push(key)
    }
  }
  if (choices.length > 0) {
    chosenDir = choices[randomInt(choices.length)]
  } else {
    //alert('No options? Guess we spin the wheel.')
    chosenDir = getRandomDirection()
  }

  return chosenDir
}

Este molesto robot intenta zumbar alrededor del robot más fuerte sin ser golpeado y tiene una pequeña posibilidad de atravesar a aquellos que intentan cazarlo. Tiene una tendencia a atraer a los dos bots más poderosos a la proximidad ...;)


Si no puede encontrar un objetivo adecuado en getTargetDirections() , entonces comienzan a suceder cosas interesantes. (Como desglosar todo debido a un undefined has no property 0error).
Ramillies

2

Agente de ICE retirado, JavaScript

Color preferido: indianred

function(me, others, coins) {
    me.arenaLength = me.arenaLength - 1;
    // Calculate the average coin value of bots
    var avg = 2;

    for (var i = 0; i < others.length; i++) {
    avg += others[i][2];
    }

    avg /= others.length;

    // Find nearest coins
    var min = [];
    var min_distance = 100000
    for (var j = 0; j < coins.length; j++) {
    var distance = Math.sqrt(Math.pow(me.locationX - coins[j][0],2) + Math.pow(me.locationY - coins[j][1],2));
    if (distance < min_distance) {
        min_distance = distance;
        min = coins[j];
    }
    }

    if (me.coins <= avg || min_distance < 5) {
    // If own coinage is lower than the average or a coin is very close, find some coins

    // Move straight to the nearest coin
    if (me.locationY != min[1]) {
        if (me.locationY - min[1] > 0) {
        return "north";
        } else {
        return "south";
        }
    } else {
        if (me.locationX - min[0] > 0) {
        return "west";
        } else {
        return "east";
        }
    }
    } else {
        // You have enough money to eat most bots
        // Find the weakest bot
        var weakling = [];
        var weakling_money = 1000000;

        for (var k = 0; k < others.length; k++) {
            if (others[k][2] < weakling_money) {
                weakling_money = others[k][2];
                weakling = others[k];
            }
        }

        // Move to the weakest bot
        if (me.locationY != weakling[1]) {
            if (me.locationY - weakling[1] > 0) {
                return "north";
            } else {
                return "south";
            }
        } else {
            if (me.locationX - weakling[0] > 0) {
                return "west";
            } else {
                return "east";
            }
        }
    }
}

Ahora retirado, este agente de ICE está amargado por la humanidad. Como resultado, Retired ICE ahora apunta al bot más débil, mientras mantiene su valor de moneda por encima del promedio (según la política de ICE).


2

Búsqueda codiciosa | Haskell

Color preferido: #62bda4

import Data.List

f x y c _ bs _
  | [bx,by,_]:_ <- sortByDist x y $ filter ((c>).last) bs = toDir (bx-x,by-y)
f x y _ _ _ cs
  | [cx,cy,_]:_ <- sortByDist x y cs = toDir (cx-x,cy-y)
f _ _ _ _ _ _ = "none"


sortByDist x y = sortOn (\[bx,by,_]-> abs (bx-x) + abs (by-y))

toDir (dx,dy)
  | dx > 0 = "east"
  | dx < 0 = "west"
  | dy > 0 = "south"
  | dy < 0 = "north"
  | otherwise = "none"

Pruébalo en línea! * *

Estrategia bastante simple, toma la primera decisión de:

  • si hay bots con menos monedas: elige el más cercano y avanza hacia él
  • si hay monedas: elija la más cercana y avance hacia ella
  • predeterminado: quedarse

El bot solo intenta atrapar otros bots o monedas sin preocuparse por los bots potencialmente más fuertes que podrían intentar atraparlo.

* Realmente no conozco JavaScript, pero hice lo mismo con Google (podría ser inexacto): ¡ Pruébelo en línea!


66
Me pregunto cómo va a traducir Haskell en js
Luis felipe De jesus Munoz

3
@LuisfelipeDejesusMunoz: Sí, yo también. Pero afortunadamente, no es un código muy sofisticado.
ბიმო

@LuisfelipeDejesusMunoz Solo use Node.JS y process.open(o child_process.spawn, o similar) con algún análisis.
user202729

@LuisfelipeDejesusMunoz: Traté de traducirlo y agregué un enlace, pero no me siento muy seguro escribiendo JavaScript, por lo que podría tener errores.
ბიმო

44
@LuisfelipeDejesusMunoz Sería una cosa si este fuera un programa de aprendizaje de AI de 10,000 líneas, pero creo que puedo manejar esto (:
Programas Redwolf

1

Imán de la moneda | JavaScript

CoinMagnet=(myself,others,coins)=>{
  x=myself.locationX;
  y=myself.locationY;
  power=myself.coins;
  arenaSize=myself.arenaLength;
  dirX=0;
  dirY=0;
  for(i=0;i<coins.length;i++){
    if(i==0){
      dirX+=(coins[i][0]-x)*3
      dirY+=(coins[i][1]-y)*3
    }
    dirX+=(coins[i][0]-x)*2
    dirY+=(coins[i][1]-y)*2
  }
  for(i=0;i<others.length;i++){
    dirX+=Math.ceil(0.85*others[i][2])*(others[i][0]-x)
    dirX+=Math.ceil(0.85*others[i][2])*(others[i][1]-y)
  }
  if(Math.abs(dirX)>Math.abs(dirY)){
    if(dirX>0){return "east";}
    else{return "west";}
  }
  else if(dirY!=0){
    if(dirY>0){return "south";}
    else{return "north";}
  }
  return "none";
}

Este bot es bastante tonto, se dirige en la dirección de las monedas más adquiribles. Esto incluye monedas que no puede obtener porque otros bots tienen mayor poder que él mismo.


1

Agente de ICE | Javascript

function(me, others, coins) {
    me.arenaLength = me.arenaLength - 1;
    // Calculate the average coin value of bots
    var avg = 2;

    for (var i = 0; i < others.length; i++) {
        avg += others[i][2];
    }

    avg /= others.length;

    // Find nearest coins
    var min = [];
    var min_distance = 100000
    for (var j = 0; j < coins.length; j++) {
        var distance = Math.sqrt(Math.pow(me.locationX - coins[j][0],2) + Math.pow(me.locationY - coins[j][1],2));
        if (distance < min_distance) {
            min_distance = distance;
            min = coins[j];
        }
    }

    if (me.coins <= avg || min_distance < 5) {
        // If own coinage is lower than the average or a coin is very close, find some coins

        // Move straight to the nearest coin
        if (me.locationY != min[1]) {
            if (me.locationY - min[1] > 0) {
                return "north";
            } else {
                return "south";
            }
        } else {
            if (me.locationX - min[0] > 0) {
                return "west";
            } else {
                return "east";
            }
        }
    } else {
        // You have enough money to eat most bots
        // Check if already on border
        if (me.locationX == 0 || me.locationX == me.arenaLength || me.locationY == 0 || me.locationY == me.arenaLength) {
            // Move anticlockwise around the border
            if (me.locationX == 0 && me.locationY != 0 && me.locationY != me.arenaLength) {
                return "south";
            }
            if (me.locationX == 0 && me.locationY == 0) {
                return "south";
            }

            if (me.locationY == me.arenaLength && me.locationX != 0 && me.locationX != me.arenaLength) {
                return "east";
            }
            if (me.locationX == 0 && me.locationY == me.arenaLength) {
                return "east";
            }

            if (me.locationX == me.arenaLength && me.locationY != 0 && me.locationY != me.arenaLength) {
                return "north";
            }
            if (me.locationX == me.arenaLength && me.locationY == me.arenaLength) {
                return "north";
            }

            if (me.locationY == 0 && me.locationX != 0 && me.locationX != me.arenaLength) {
                return "west";
            }
            if (me.locationX == me.arenaLength && me.locationY == 0) {
                return "west";
            }
        } else {
            // Find the nearest border and move to it
            if (me.locationX <= me.arenaLength - me.locationX) {
                // Move to left border
                return "west";
            } else {
                // Move to right border
                return "east";
            }
        }
    }
}

¿Cuál es el punto de una frontera si no se está patrullando? ICE se mueve en sentido contrario a las agujas del reloj alrededor de la frontera, recogiendo cualquier bot que se interponga en su camino.

Antes de que pueda hacer eso, primero debe poder comer otros bots. Por esa razón, ICE mantiene sus monedas por encima del promedio de todos los bots.

Garantizado para robar niños de sus padres ™


Esto sería más divertido si no fuera tan relevante
Don Thousand

1

X marca el lugar | JavaScript

function(me, others, coins){
    if (me.locationY != 0) {
        // If not on X axis
        if (others.every(other => other[1]==me.locationY-1)) {
            // If any in my way
            if (!others.every(other => other[0]==me.locationX-1)) {
                if (me.locationX != 0) {
                    // If no one to my left and not on edge of board
                    return "west"
                } else {
                    return "none"
                }
            } else if (!others.some(other => other[0]==me.locationX+1)) {
                if (me.locationX != me.arenaLength-1) {
                    // If no one to my right and not on edge of board
                    return "east"
                } else {
                    return "none"
                }
            } else {
                // I'm surrounded
                return "none"
            }
        } else {
            // No one in my way
            return "north"
        }
    } else {
        // If on the x axis
        if (!others.some(other => Math.abs(other[0]-me.locationX)==1 && other[1] == me.locationY)) {
            // If no one next to me
            move = ["east","west"][Math.floor(Math.random()*2)]

            // Prevent from falling off the board
            if (move == "east" && me.locationX == me.arenaLength-1) {
                return "west"
            } else if (move == "west" && me.locationX == 0) {
                return "east"
            } else {
                return move
            }
        } else {
            // I'm surrounded
            return "none"
        }
    }
}

X marca el lugar, por lo que todo el oro debe estar en el eje x, ¿verdad? Mi bot hace una línea recta hacia la línea y = 0 y luego permanece allí, moviéndose al azar.


Eh, un método interesante de hecho
Programas Redwolf


1
Dado eso The arena starts at (0,0) in the upper left corner, ¿estás seguro de que quieres moverte southpara llegar y=0?
AdmBorkBork

@AdmBorkBork Gracias, eso podría haber sido malo
Decaimiento Beta

1

Pájaro de fuego

    function(me,others,coins) {
        var x = me.locationX;
        var y = me.locationY;
        var safe = [true, true, true, true];
        var threats = [];
        var targets = [];
        var opps = [];

        var meTo = (loc) => (Math.abs(x - loc[0]) + Math.abs(y - loc[1]));
        var inSquare = (loc, r) => (Math.abs(loc[0] - x) <= r && Math.abs(loc[1] - y) <= r);
        var distance = (from, loc) => (Math.abs(from[0] - loc[0]) + Math.abs(from[1] - loc[1]));
        var attackRange = (from, check, r) => {
            for (var i = 0; i < check.length; i++) {
                if (distance(check[i], from) == (r || 1)) {
                    return true;
                }
            }
            return false;
        };
        var dirStr = (dir) => (['north','east','south','west'][dir]);

        var i, n, o, p;
        for (i = 0; i < others.length; i++) {
            o = others[i];
            if (o[2] >= me.coins) {
                threats.push(o);
            } else {
                targets.push([o[0], o[1], Math.floor(o[2] * 0.55)]);
            }
        }
        for (i = 1; i < 5; i++) {
            targets.push([coins[i][0], coins[i][1], 2]);
        }
        targets.push([coins[0][0], coins[0][1], 5]);
        if (y === 0 || attackRange([x, y - 1], threats)) {
            safe[0] = false;
        }
        if (x == me.arenaLength - 1 || attackRange([x + 1, y], threats)) {
            safe[1] = false;
        }
        if (y == me.arenaLength - 1 || attackRange([x, y + 1], threats)) {
            safe[2] = false;
        }
        if (x === 0 || attackRange([x - 1, y], threats)) {
            safe[3] = false;
        }
        if (safe.includes(false)) {
            if (!(safe[0]) && safe[2]) {
               opps.push(2);
            }
            if (!(safe[1]) && safe[3]) {
                opps.push(3);
            }
            if (!(safe[2]) && safe[0]) {
                opps.push(0);
            }
            if (!(safe[3]) && safe[1]) {
                opps.push(1);
            }
        } else {
            targets.sort((a,b)=>(meTo(a) - meTo(b)));
            o = targets[0];
            if (o[0] == x) {
                if (o[1] < y) {
                    return 'north';
                } else {
                    return 'south';
                }
            } else if (o[1] == y) {
                if (o[0] < x) {
                    return 'west';
                } else {
                    return 'east';
                }
            } else if (Math.abs(o[0] - x) < Math.abs(o[1] - y)) {
                if (o[1] < y) {
                    return 'north';
                } else {
                    return 'south';
                }
            } else if (Math.abs(o[0] - x) > Math.abs(o[1] - y)) {
                if (o[0] < x) {
                    return 'west';
                } else {
                    return 'east';
                }
            }
        }
        console.log(safe[opps[0]]);
        var lx, ly;
        for (i = 0; i < opps.length; i++) {
            if (opps[i] === 0) {
                lx = x;
                ly = y - 1;
            }
            if (opps[i] == 1) {
                lx = x + 1;
                ly = y;
            }
            if (opps[i] == 2) {
                lx = x;
                ly = y + 1;
            }
            if (opps[i] == 3) {
                lx = x - 1;
                ly = y;
            }
            if (attackRange([lx, ly], targets, 0)) {
                return dirStr(opps[i]);
            }
        }
        return dirStr(opps[0]);
    }

Completamente renovado para ser más mortal que antes (:


2
Mi absoluto perdedor de un bot
Programas Redwolf

No está apuntando a ellos, los está evitando
Programas Redwolf

Oh lo siento, entendí mal
Beta Decay

1

A-Path-y | JavaScript

El color preferido para este bot es #0077b3.

 run: function (me, others, coins)
{
    var X_INDEX = 0;
    var Y_INDEX = 1;
    var COIN_INDEX = 2;

    var GOLD_POINTS = 5;
    var SILVER_POINTS = 2;

    var NORTH = 0;
    var SOUTH = 1;
    var WEST = 2;
    var EAST = 3;
    var IDLE = 4;
    var MOVE_COMMANDS_COUNT = IDLE+1;

    var MAP_TYPE_BLANK = 0;
    var MAP_TYPE_BOT = 1;
    var MAP_TYPE_GOLD_COIN = 2;
    var MAP_TYPE_SILVER_COIN = 3;

    var MIDGAME_THRESHOLD = 25;

    var PATH_FINDING_MAX_STEPS = 10000;
    var offsets = [[0,-1],[1,0],[0,1],[-1,0]];

function randInt(min,max)
    {
        return  Math.floor(Math.random() * ((max - min) + 1)) + min;
    }


    /**
     * Find a path using a*, returns the direction to take from the starting position coupled with a metric describing the cost of the path
     */
function pathFind(startX,startY,targetX,targetY,map,mapSize)
    {
        var i;
        var j;

        // shuffleIndecies to make path selection slightly random
        var indecies = [0,1,2,3];
        var shuffleIndecies = new Array(4);
        for (j=0;j<4;j++)
        {
            var randomIndex = randInt(0,3-j);
            shuffleIndecies[j] = indecies[randomIndex];
            indecies[randomIndex] = indecies[0];
            var lastElementIndex = 4-j-1;
            indecies[0] = indecies[lastElementIndex];
        }

        // A*
        if (!(startX===targetX && startY===targetY))
        {

            var tileX = new Array(PATH_FINDING_MAX_STEPS);
            var tileY = new Array(PATH_FINDING_MAX_STEPS);
             var fscore = new Array(PATH_FINDING_MAX_STEPS);
             var gscore = new Array(PATH_FINDING_MAX_STEPS);
             var openList = new Array(PATH_FINDING_MAX_STEPS);
             var tileParent = new Array(PATH_FINDING_MAX_STEPS);
             var tileIsClosed = new Array(mapSize);

             for (i = 0;i<PATH_FINDING_MAX_STEPS;i++)
             {
                 tileX[i]=0;
                 tileY[i]=0;
                 fscore[i]=0;
                 gscore[i]=0;
                 openList[i]=0;
                 tileParent[i]=0;
             }


             for (i = 0;i<mapSize;i++)
             {
                 var newArray = new Array(mapSize);
                 tileIsClosed[i] = newArray;
                 for (j = 0;j<mapSize;j++)
                 {
                     tileIsClosed[i][j] = 0;
                 }
             }

             var currentIndex = -1;     

            var openListSize=1;
            var tileId=1;

            tileX[0]=targetX;
            tileY[0]=targetY;
            fscore[0]=1;
            gscore[0]=map[targetX][targetY].negativeWeight;



            do
            {
              var currentBestIndex=-1;
              var currentBestScore=2147483647;
              //  Look for the lowest F cost square on the open list
              for (var ii=0;ii<openListSize;ii++)
              {
                if (fscore[openList[ii]]<currentBestScore)
                {
                  currentBestScore=fscore[openList[ii]];
                  currentBestIndex=ii;
                }
              }
              if (currentBestIndex===-1)
              {
                break;
              }
              currentIndex=openList[currentBestIndex];
              var currentTileX=tileX[currentIndex];
              var currentTileY=tileY[currentIndex];

              // found path
              if (startX===currentTileX && startY===currentTileY)
              {
                break;
              }

              // if not in closed list
              if (tileIsClosed[currentTileX][currentTileY]===0)
              {
                    // Switch it to the closed list.
                    tileIsClosed[currentTileX][currentTileY]=1;
                    // remove from openlist
                    openList[currentBestIndex]=openList[--openListSize];   

                    // add neighbours to the open list if necessary
                    for (j=0;j<4;j++)
                    {
                        i = shuffleIndecies[j];

                        var surroundingCurrentTileX=currentTileX+offsets[i][0];
                        var surroundingCurrentTileY=currentTileY+offsets[i][1];
                        if (surroundingCurrentTileX>=0 && surroundingCurrentTileX<mapSize &&
                            surroundingCurrentTileY>=0 && surroundingCurrentTileY<mapSize )
                        {
                          tileX[tileId]=surroundingCurrentTileX;
                          tileY[tileId]=surroundingCurrentTileY;

                          var surroundingCurrentGscore=gscore[currentIndex] + map[surroundingCurrentTileX][surroundingCurrentTileY].negativeWeight;
                          gscore[tileId]=surroundingCurrentGscore;
                          fscore[tileId]=surroundingCurrentGscore+Math.abs( surroundingCurrentTileX-startX)+Math.abs( surroundingCurrentTileY-startY);
                          tileParent[tileId]=currentIndex;
                          openList[openListSize++]=tileId++;
                        }
                    }
              }
              else
              {
              // remove from openlist
              openList[currentBestIndex]=openList[--openListSize];    
              }
            } while(true);

            if (tileX[tileParent[currentIndex]]<startX) return {moveDirection:WEST, pathLength:currentIndex, pathScore:gscore[currentIndex]+currentIndex/4};
            else if (tileX[tileParent[currentIndex]]>startX) return {moveDirection:EAST, pathLength:currentIndex, pathScore:gscore[currentIndex]+currentIndex/4};
            else if (tileY[tileParent[currentIndex]]<startY) return {moveDirection:NORTH, pathLength:currentIndex, pathScore:gscore[currentIndex]+currentIndex/4};
            else if (tileY[tileParent[currentIndex]]>startY) return {moveDirection:SOUTH, pathLength:currentIndex, pathScore:gscore[currentIndex]+currentIndex/4};
        }
        console.log("Path finding failed");
        return {moveDirection:IDLE, pathLength:0, pathScore:2147483647};
     }

function process(info,bots,coins)
    {
        var i;
        var j;
        var k;
        var x;
        var y;

        // initialise map
        var mapSize = info.arenaLength;
        var map = new Array(mapSize);
        for (i = 0;i < info.arenaLength;i++)
        {
            var newArray = new Array(info.arenaLength);
            map[i] =  newArray;
            for (j = 0;j < mapSize;j++)
            {
                map[i][j] = {type:MAP_TYPE_BLANK, coins: 0 , negativeWeight:i===0||i===mapSize-1||j===0||j===mapSize-1?3:1};
            }
        }

        // populate map with bots
        for (i = 0 ; i<bots.length;i++)
        {
            map[bots[i][X_INDEX]][bots[i][Y_INDEX]].type = MAP_TYPE_BOT;
            map[bots[i][X_INDEX]][bots[i][Y_INDEX]].coins = bots[i][COIN_INDEX];

            for (j=-1;j<2;j++)
            {
                x = bots[i][X_INDEX] + j;
                if (x>=0 && x < mapSize)
                {
                    for(k=-1;k<2;k++)
                    {
                        if (Math.abs((k+j)%2) === 1)
                        {
                            y = bots[i][Y_INDEX] + k;
                            if (y>=0 && y< mapSize )
                            {
                                // are we adjacent the bot or potentially will be?
                                if (Math.abs(info.locationX-x)<=1 && Math.abs(info.locationY-y)<=1)
                                {
                                    // make the cell significantly less attractive when the bot is stronger than us, or
                                    // make the cell slightly more attactive when the bot is weaker than us, or
                                    // not change if the bot has no coins
                                    map[x][y].negativeWeight+= bots[i][COIN_INDEX] >= info.coins?100000:(bots[i][COIN_INDEX]===0?0:-1);
                                }
                                // another bot is not a direct threat/target
                                else
                                {
                                    // make the cell moderately less attractive when the bot is stronger than us, or
                                    // make the cell slightly more attactive when the bot is weaker than us, or
                                    // not change if the bot has no coins
                                    map[x][y].negativeWeight+= bots[i][COIN_INDEX] >= info.coins?3:(bots[i][COIN_INDEX]===0?0:-1);
                                }
                            }
                        }
                    }
                }
            }
        }

        // populate map with coins
        for (i = 0 ; i<coins.length;i++)
        {
            map[coins[i][X_INDEX]][coins[i][Y_INDEX]].type = i === 0?MAP_TYPE_GOLD_COIN:MAP_TYPE_SILVER_COIN;
            map[coins[i][X_INDEX]][coins[i][Y_INDEX]].coins = i === 0?GOLD_POINTS:SILVER_POINTS;

            // check to see whether bots are adjacent to the coin
            for (j=-1;j<2;j++)
            {
                x = coins[i][X_INDEX] + j;
                if (x>=0 && x < mapSize)
                {
                    for(k=-1;k<2;k++)
                    {
                        if ((k+j)%2 === 1)
                        {
                            y = coins[i][Y_INDEX] + k;
                            if (y>=0 && y< mapSize )
                            {
                                if (map[x][y].type === MAP_TYPE_BOT)
                                {
                                    // this coin looks like a trap as a stronger bot is adjacent to it
                                    if (map[x][y].coins >= info.coins)
                                    {
                                        map[coins[i][X_INDEX]][coins[i][Y_INDEX]].negativeWeight+=100000;
                                    }
                                    else
                                    {
                                        // are we adjacent the coin? we might be able to kill another bot if it trys to get the coin
                                        if (Math.abs(info.locationX-coins[i][X_INDEX])<=1 && Math.abs(info.locationY-coins[i][Y_INDEX])<=1)
                                        {
                                            map[coins[i][X_INDEX]][coins[i][Y_INDEX]].negativeWeight+=-20;
                                        }
                                        // another bot is likely to get this coin... make it less attractive
                                        else
                                        {
                                            map[coins[i][X_INDEX]][coins[i][Y_INDEX]].negativeWeight=+100;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // add the coin attractiveness, more for gold coins
            map[coins[i][X_INDEX]][coins[i][Y_INDEX]].negativeWeight += i === 0?-20:-10;
        }


        var pathBest = {moveDirection:IDLE, pathLength: 2147483647, pathScore: 2147483647};

        if (info.coins > MIDGAME_THRESHOLD)
        {
            var viableCoinCount =0;
            var viableCoins = new Array(5); 


            // find coins that are reachable before any other bot
            outer1:
            for (j = 0 ; j<coins.length;j++)
            {
                var contention = 0;

                var myDistanceToCoin = Math.abs(info.locationX-coins[j][X_INDEX]) + Math.abs(info.locationY-coins[j][Y_INDEX]);

                for (i = 0 ; i<bots.length;i++)
                {
                    var dist = Math.abs(bots[i][X_INDEX]-coins[j][X_INDEX]) + Math.abs(bots[i][Y_INDEX]-coins[j][Y_INDEX]);
                    if (dist < myDistanceToCoin)
                    {
                        continue outer1;
                    }
                }
                viableCoins[viableCoinCount++] = j;
            }

            // no coins are reachable before another bot so find the cell that is furthest away from any bot and head there
            if (viableCoinCount ===0)
            {
                var mostIsolatedCellX = mapSize/2;
                var mostIsolatedCellY = mapSize/2;
                var mostIsolatedCellMinBotDistance = 0;

                for (x=5;x<mapSize-5;x++)
                {
                    for (y=5;y<mapSize-5;y++)
                    {
                        if (x!= info.locationX && y!=info.locationY)
                        {

                            // ignore coin attractiveness
                            map[x][y].negativeWeight = map[x][y].negativeWeight<-4?map[x][y].negativeWeight:1;


                            var currentCellMinBotDistance = 2147483647;

                            for (i = 0 ; i<bots.length;i++)
                            {
                                var dist = Math.abs(bots[i][X_INDEX]-x) + Math.abs(bots[i][Y_INDEX]-y) + Math.abs(info.locationX-x) + Math.abs(info.locationY-y);
                                if (dist < currentCellMinBotDistance )
                                {
                                    {
                                        currentCellMinBotDistance = dist;                           
                                        if (currentCellMinBotDistance>mostIsolatedCellMinBotDistance)
                                        {
                                            mostIsolatedCellMinBotDistance = currentCellMinBotDistance;
                                            mostIsolatedCellX=x;
                                            mostIsolatedCellY=y;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // attempt to find path to most isolated cell
                pathBest = pathFind(info.locationX, info.locationY, mostIsolatedCellX,mostIsolatedCellY, map, mapSize);
            }

            // attempt to find paths to each viable coin, keeping the best result
            for (i = 0 ; i<viableCoinCount;i++)
            {
                var path = pathFind(info.locationX, info.locationY, coins[viableCoins[i]][X_INDEX],coins[viableCoins[i]][Y_INDEX], map, mapSize);
                if (path.pathScore < pathBest.pathScore)
                {
                    pathBest = path;
                }
            }
        }
        else
        {
            // attempt to find paths to each coin, keeping the best result
            for (i = 0 ; i<coins.length;i++)
            {
                var path = pathFind(info.locationX, info.locationY, coins[i][X_INDEX],coins[i][Y_INDEX], map, mapSize);
                if (path.pathScore < pathBest.pathScore)
                {
                    pathBest = path;
                }
            }
        }


        var move = IDLE;
        if (pathBest.pathLength === 2147483647)
        {
            outer:
            for (i=0;i<MOVE_COMMANDS_COUNT;i++)
            {
                switch (i)
                {
                    case NORTH:
                        if (info.locationY-1 < 0)
                        {
                            continue;
                        }
                        move = i;
                        break outer;
                    case SOUTH:
                        if (info.locationY+1 === info.arenaLength)
                        {
                            continue;
                        }
                        move = i;
                        break outer;
                    case WEST:
                        if (info.locationX-1 < 0)
                        {
                            continue;
                        }
                        move = i;
                        break outer;
                    case EAST:
                        if (info.locationX+1 === info.arenaLength)
                        {
                            continue;
                        }
                        move = i;
                        break outer;
                    case IDLE:
                        move = i;
                        break;
                    default:
                }
            }
        }
        else
        {
            move = pathBest.moveDirection;
        }

        switch (move)
        {
        case NORTH:
            return "north";
        case SOUTH:
            return "south";
        case EAST:
            return "east";
        case WEST:
            return "west";
        default:
            return "none";
        }
    }
    return process(me, others, coins);
}

Este bot utiliza la búsqueda de rutas junto con un mapa de las deseabilidades de las celdas para evitar los bots que podrían matarnos, buscar monedas que estén cerca, no trampas y que sean menos riesgosas.

No parece ser un contendiente para el lugar ganador, pero se mantiene firme y estará vivo al final del partido si sobrevive al combate cuerpo a cuerpo inicial.

El bot ahora tiene una estrategia de juego de medio a tardío que ignora las monedas que no puede alcanzar antes que otros bots y, si no puede ir a ninguna moneda, se mueve a la celda más cercana que está más lejos de todos los otros bots que son más fuertes que él.

Ahora tiene una posibilidad de ganar.

Tenga en cuenta que lo siento por el código malo, lo he convertido automáticamente de Java


¡Asegúrese de eliminar cualquier error o actualización pronto, 18 horas antes de la fecha de vencimiento!
Programas Redwolf

@RedwolfPrograms ¿Has observado un error? Si es así, hágamelo saber para que pueda corregir. Gracias
Moogie

No, pero nunca se sabe. Solo asegúrese de verificar dos veces, ya que he visto que muchos bots pierden debido a un número incorrecto o una función incorrecta, o escriben mal más veces de las que puedo contar
Programas Redwolf
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.