Coletor de ouro KoTH


48

Nota: a pesquisa de favoritos da comunidade será lançada em breve

Neste KoTH, o objetivo é ser o último bot vivo. As moedas serão colocadas em áreas aleatórias, e seu bot deve obter as moedas primeiro. Se um bot se depara com outro bot, o bot com mais moedas vence e o outro bot morre. Mais detalhes abaixo.

Tipos de moedas

Haverá 2 tipos de moedas: ouro e prata. O ouro adiciona 5 moedas à força do bot e a prata adiciona 2. Depois que uma moeda é coletada, outra moeda é colocada em outro local no tabuleiro. A qualquer momento, há uma moeda de ouro e quatro moedas de prata na arena.

Colisões de bot

No caso de dois robôs tentarem ocupar o mesmo espaço, aquele com mais moedas permanecerá e o que tiver menos moedas ... não. O bot vencedor ganhará 85% das moedas dos oponentes (arredondado para cima). Se eles estão empatados, ambos morrem. Se três ou mais tentarem ocupar o mesmo espaço, o mais poderoso vence e recebe 85% de todas as moedas do outro bot. No caso em que o bot mais poderoso é o empate, todos os bots morrem tentando entrar no espaço.

Arena

O comprimento lateral da arena é calculado com 4 + botCount. Ao colocar bots no início do jogo, lugares aleatórios são escolhidos. O sistema garante que nenhum robô inicie no mesmo espaço ou próximo um do outro. As moedas são geradas aleatoriamente, excluindo um quadrado de 3 por 3 centrado em cada bot. Se um bot é encontrado fora da arena, ele morre instantaneamente. A arena começa em (0,0), ou Noroeste, no canto superior esquerdo, e a localização de um bot é sempre um número inteiro.

Seu bot

Seu bot deve ser uma função, em qualquer linguagem orientada a objetos que possua matrizes, números inteiros, strings e funções. Observe que todos os envios serão convertidos para Javascript, para simplificar. Para armazenar informações entre movimentos, use botNotes.storeData(key, value)e botNotes.getData(key, value). Você não pode armazenar ou acessar dados de qualquer maneira, exceto a que é fornecida através dos parâmetros e botNotes. Você deve criar uma função que, quando chamada, retorna uma string north, east, south, west, ou none. Haverá 3 argumentos para a função:

  • Um objeto com quatro inteiros ( locationX, locationY, coins, arenaLength), sua localização atual, suas moedas, eo comprimento da arena

  • Uma matriz multidimensional com as coordenadas X e Y de outros bots e sua contagem de moedas,[[0,5,4],[4,7,1],[7,4,12]]

  • Uma matriz com os locais das moedas listados (o ouro é sempre o primeiro)

Este é um desafio do tipo rei da colina, proibidas as brechas padrão . Sua função será executada milhares de vezes, sempre que for permitido um "movimento". Note que se o jogo exceder 20.000 jogadas , o bot com mais moedas ganha. Isso será feito 8.000 vezes, para remover a aleatoriedade.

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

Prémios:

Primeiro Lugar: Recompensa de 100 pontos
Favorito da Comunidade: resposta aceita de 15 pontos

Vencedores:

Primeiro Lugar: TBTPTGCBCBA
Segundo Lugar: Big King Little Hill
Terceiro Lugar: Potencialmente Vitorioso
Quarto: Polido Bot bêbado e míope
Quinto Lugar: Moeda de Segurança


6
"Observe que todos os envios serão convertidos para Javascript, para simplificar." Como é que isso deveria funcionar? Você faz a conversão?
Laikoni 8/08

21
Não há nada de errado em um koth permitir apenas um único idioma, especialmente um tão difundido quanto o JavaScript. Em vez de ambiguamente "converter" respostas para JavaScript (presumivelmente você e manualmente), você deve limitar o desafio apenas a JS. Afinal, tivemos muitos koths somente em Java e somente em Python.
Skidsdev

2
Uma versão disso em que você controla a aceleração em vez da posição seria muito legal.
akozi

12
Para todos: já existem muitos comentários. Não deixe comentários inúteis como "+1, bom bot" e exclua seus comentários se forem redundantes . Não somos um site típico de perguntas e respostas, mas ninguém gosta de ler centenas de comandos.
User202729

5
(Para minha própria pergunta): De acordo com o NP no bate-papo, é o último: todos os bots se movem, todos os conflitos são resolvidos, todos os recolhimentos de moedas ocorrem e todas as novas moedas são colocadas.
BradC 9/08/19

Respostas:


26

BaitBot - JavaScript Node.JS

Por que se preocupar em perseguir ou correr, se você nunca pode pegar? Em vez disso, o BaitBot encontra a moeda mais próxima e espera que um bot mais fraco também se aproxime dela. Quando ambos estão adjacentes, o baitBot vai para a moeda, assumindo que o bot mais fraco também. Se o baitBot estiver esperando e um bot mais forte se aproximar, ele simplesmente pega a moeda e faz bolinhas. Me teste!

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

}

11
Ah, é uma ideia legal, eu gosto.
Sundar

Essa abordagem é bem legal ... não, muito legal #
Redwolf Programs

11
O BaitBot precisa nearestThreat && distanceTo(nearestThreat)e não apenas distanceTo(nearestThreat). Falha quando não há ameaça.
Redwolf Programs

11
Sim, nearestThreaté undefinedse todos os outros bots tiverem mais pontos que o seu.
night2

11
Bem, eu recebo avisos como [10] Bot Bait Bot tired of this world, and jumped off its edgeno meu log de eventos
Redwolf Programs

17

Potencialmente vitorioso | Javascript

A cor preferida para este bot é #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];
}

(Desculpas pela formatação desleixada, a indentação de 4 espaços deste site não combina bem com o meu costume de usar guias.)

Explicação aproximada

Por meio deste, renuncio à tentativa de atualizar a explicação das fórmulas. Os coeficientes estão mudando constantemente e é meio difícil manter a explicação atualizada. Então, vou apenas explicar o princípio geral.

Cada moeda e cada bot gera um campo de força com algum potencial. Eu apenas adiciono os potenciais de tudo e o bot vai para onde quer que o potencial seja menor. (Obviamente, essa idéia é roubada da física.)

Eu uso dois tipos de potenciais. O primeiro é um pseudo-gravitacional (que atua em qualquer faixa), com O k é uma "força" do campo, e, com esta escolha de sinal, o potencial é atraente. A r aqui (e em qualquer outro lugar) é a distância no táxi métrica, r = | símbolos X- - x₂ | + | y₁ - y₂ | .

U=kr+1511+n.

Eu uso k = 40 para moedas de ouro ek = 10 para moedas de prata. n é o número de bots que estão mais próximos da moeda específica do que nós. Caso contrário, ignoramos absolutamente os outros bots (se atrapalharmos um bot mais forte, fugiremos, mas é isso). Eu valorizo ​​as moedas de ouro por mais do que valem, porque, caso contrário, os robôs que perseguem principalmente o ouro o tempo todo me vencem.

O segundo potencial é um exponencialmente decadente (que efetivamente atua apenas a distâncias muito pequenas). Isso é gerado pelos outros bots, principalmente os mais poderosos.

Eles produzem um campo com Essa força é proibitivamente forte no intervalo de 0 a 1, mas decai para quase nada nas distâncias maiores. (Distância + 1 significa cortar a força em 1/20.)

U=5×1400e3r.

Geralmente não atacamos os outros bots intencionalmente (é claro que se eles atrapalharem e pisarmos neles, a culpa é deles), mas existe a possibilidade de fazer isso. Se algumas condições adversas forem cumpridas, podemos entrar no modo de caça , concentrando-nos em um único bot. Para entrar no modo de caça:

  1. Devemos ter pelo menos 25 moedas. (Precisamos pegar algumas moedas primeiro.)
  2. Eles devem ter no máximo (nossas moedas - 5) moedas e pelo menos 10 moedas. (Não queremos caçar alguém que agarra uma moeda e, de repente, é mais poderoso, e também não queremos perseguir bots com moeda zero.)
  3. Devemos ficar atrás do bot atualmente líder em pelo menos 1/10 de suas moedas. (Você precisa ter sorte em caçar alguma coisa, por isso não há necessidade de revelar uma boa posição apenas para tentar a nossa sorte.)
  4. Não devemos estar em um tempo de espera de caça (veja abaixo).

Se tudo isso for satisfeito, o modo de caça é ativado. Nas próximas 10 rodadas, o bot caçado emite apenas o potencial Após essas 10 rodadas, entramos na recarga de caça, durante a qual não podemos entrar no modo de caça novamente. (Isso nos impede de perseguir infinitamente e sem frutos um bot enquanto todos os outros pegam moedas com alegria.) A recarga de caça é de 20 rodadas quando temos 25 moedas e aumenta em 20 moedas por cada duplicação. (Em outras palavras, a recarga é .) (Usamos isso porque, no final do jogo, todos os bots caçáveis ​​provavelmente estão mortos e, portanto, qualquer caçada será provavelmente em vão. Por isso, queremos limitar o tempo perdido. Mas, às vezes, comer com sorte no final do jogo pode mudar tudo, por isso mantemos a possibilidade.)

U=150er.
20(1 + log2(c / 25))

Finalmente, toda a arena é colocada em um poço de potencial infinito que impede o bot de escapar.


Eu acho que esse bot provavelmente supera meu movimento de peso também.
f Augnɛtɪk 8/08/18

@ fəˈnɛtɪk - Eu também :—). Eu acho que este pode lidar com os outros bots um pouco melhor. (Também não é "cegado" por uma moeda em um quadrado adjacente.) Mas eu definitivamente lhe dei +1 porque sou um grande fã dessa idéia.
Ramillies

Você poderia aplicar o princípio da menor ação a isso?
Beta Decay

@BetaDecay: Não estou com medo, o cálculo não responde bem a problemas discretos como esse. Mesmo no caso contínuo, não seria trivial (por causa da magnitude fixa da velocidade), mas poderia ser possível depois de algumas mágicas de coordenadas polares, eu acho.
Ramillies

4
Isso é legal. Não tenho certeza se o risco está monotonicamente relacionado à distância, porém, parece que uma ameaça a dois espaços de distância é mais provável que o mate do que um adjacente, já que no último caso, um de vocês precisa ficar parado para que ocorra uma colisão.
Caim

16

Algoritmo de aprendizado de primeira geração | JavaScript (Node.js)

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

Experimente online!

Você já viu aquelas timelapses de algoritmos de aprendizado aprendendo a jogar um jogo? Eles costumam se mover quase aleatoriamente nas primeiras gerações ...


LOL ... Ainda pode funcionar!
RedWolf Programas

2
A maioria dos algoritmos de aprendizado funciona literalmente aleatoriamente nas primeiras iterações, não apenas quase aleatoriamente.
fənɛtɪk

Adivinha? Este bot recebeu, em média, quase 0,22 moedas por rodada!
RedWolf Programas

16

Grande rei 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])
}

Experimente online!

Big King Little Hill toma decisões com base em "zonas de controle". Ele buscará apenas moedas que estão em sua zona de controle, o que significa que pode alcançá-la antes que qualquer outro bot possa. Quando não há moedas em sua zona de controle, ele se move para maximizar o tamanho de sua zona de controle. Big King Little Hill calcula a zona de controle de cada um de seus 5 movimentos possíveis e favorece os movimentos que maximizam o tamanho de sua zona de controle. Dessa maneira, Big King Little Hill finalmente alcança um máximo local (little hill) de controle e aguarda a geração de uma moeda dentro de sua zona. Além disso, Big King Little Hill rejeita qualquer movimento que possa resultar em sua morte, a menos que não haja alternativas.

Big King Little Hill é um pessimista (prefere o termo realista) porque não se incomoda em contestar qualquer moeda que não é garantida a sua obtenção. É também pacifista, pois não busca bots mais fracos em nenhum sentido (embora possa pisar em um se atrapalhar). Por fim, Big King Little Hill é um covarde que não comprometerá sua própria vida por nenhuma recompensa, a menos que seja absolutamente necessário.


11
Bem-vindo ao PPCG! Isso é um bot muito bom = D
Luis felipe De jesus Munoz

Isto é o que eu estava pensando para um bot. Bom trabalho.
Jo.

10

Moeda de segurança | 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";}
  }
}

Esse bot vai direto para uma moeda com valor ponderado (valor / distância) que não pode morrer ao atingir ao mesmo tempo ou após outro bot. Se não houver uma moeda válida com essa propriedade, ela fica onde está o bot agora se move em uma direção segura aleatória (segurança significa que, se um bot se move em sua direção, a moeda de segurança não pode colidir. Isso permite que o bot troque de lugar com outro bot se imediatamente ao lado), ponderado em direção ao centro da arena.


11
Huh, isso pode realmente ganhar. Embora existam muitos bots
Programas Redwolf

Este método terá mais problemas quanto mais desigualmente forem colocados os bots inimigos com valor maior ou igual.
fənɛtɪk

11
Bem, provavelmente todos estarão seguindo a moeda mais próxima deles / moeda de ouro.
RedWolf Programas

Só funcionará bem se conseguir algumas moedas logo no início.
fənɛtɪk

E isso é principalmente sorte, uma vez que o lugar onde moedas de gerar é decidido aleatoriamente
RedWolf Programas

10

O bot que joga o jogo com cautela, mas pode ser agressivo | Javascript

Cor preferida: #F24100

Nota: Embora este bot tenha ficado em 1º lugar, é devido a uma parceria com "Feudal Noble" no final e comê-lo por mais moedas. Caso contrário, esse bot teria sido o terceiro. Se você estiver interessado em bots mais poderosos individualmente, faça o check-out Potencialmente Vitorioso e 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;
}

Esse bot (também conhecido como "TBTPTGCBCBA") tenta tomar a melhor decisão possível, gerando uma pontuação para cada movimento possível e seleciona o movimento com maior pontuação para cada turno.

O sistema de pontuação tem muitos detalhes que evoluíram desde o início do desafio. Eles podem ser descritos geralmente assim:

  • Quanto mais próximas as moedas estiverem de um possível movimento, maior será a pontuação desse movimento. Se uma moeda não tiver outros concorrentes possíveis, a pontuação será ainda maior. Se uma moeda tem outros concorrentes possíveis, a pontuação diminui.
  • Se outro bot estiver próximo de um possível movimento e tiver menos moedas, dependendo da fase do jogo, isso pode significar mais pontos para esse movimento. Portanto, é casual para "TBTPTGCBCBA" comer alguns outros bots em cada jogo.
  • Se outro bot estiver próximo de um movimento possível com pontos iguais ou mais, esse movimento recebe pontuação negativa suficiente para garantir que a morte seja evitada. É claro que em alguns casos todos os movimentos possíveis são ruins e a morte não pode ser evitada, mas isso é muito raro.
  • Existe um mecanismo para acompanhar o número de bots no meio do tabuleiro nas últimas 20 rodadas. Se a média é baixa o suficiente, todos os movimentos em direção às moedas no meio obtêm mais pontos e se a média for alta, todos os movimentos em direção às moedas no meio obtêm uma pontuação mais baixa. Este mecanismo permite evitar conflitos com o "Feudal Noble". Como o "Feudal Noble" está sempre no meio (a menos que esteja sendo perseguido), o número médio de bots no meio aumenta e "TBTPTGCBCBA" entende para evitar o meio, se houver uma opção melhor fora da área central. Se "Feudal Noble" morre, a média diminui e "TBTPTGCBCBA" entende que ele pode usar o meio.
  • Existem alguns fatores que mudam dinamicamente com base na fase do jogo (detectada a partir do número de bots ativos), esses fatores afetam a pontuação em cada um dos itens acima.
  • Este bot tem uma habilidade especial. Com o tempo, se cansa do egoísmo do "Nobre Feudal" e da opressão dos camponeses. No momento certo, surgirá para acabar com o desagradável sistema de feudalismo. Uma tentativa bem-sucedida não apenas ajuda os camponeses pobres, mas também oferece uma chance de vitória mais alta devido às moedas retiradas do "Feudal Noble".

Parece muito mais ... inteligente que os outros #
Redwolf Programs

5
Eu gosto da parte dos monstros dos parâmetros
Redwolf Programs

9

O anticapitalista | Javascript

Não tem incentivo para ir atrás das moedas, mas tenta se colocar exatamente entre os dois bots mais ricos com a mesma quantia de dinheiro, na esperança de que eles o caçam e, eventualmente, o peguem ao mesmo tempo, levando dois capitalistas com ele quando ele morrer. . Não resiste ativamente a conseguir moedas, para que ele possa se tornar um alvo mais interessante.

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

O GUT, 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";
    }
}

Com Potencialmente Vitorioso , temos dois campos: o campo bot e o campo coin. No entanto, a natureza não é tão complicada. É hora de unificar os dois campos para produzir a Grande Teoria Unificada .

Primeiro, precisamos descobrir qual é o potencial do campo. Supondo que nosso próprio bot não influencie o campo de forma alguma, podemos escrever isso como:

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

kn(xn,yn)

A propriedade relativa do objeto é calculada da seguinte forma:

k=cobjectcme

ccme=cself+1cself

Vamos apenas chamar essa correção de parte da Dinâmica Betaniana Modificada (MOBD) .

Também podemos encontrar a energia cinética como:

T=12cme(x˙2+y˙2)

Agora podemos calcular a ação:

Action=ab(TV)dt=ab(12cme(x˙2+y˙2)nkn(ekn2100(xxn)2+ekn2100(yyn)2))dt

E assim, o Lagrangiano do nosso bot no campo de bot de moedas é:

L=12cme(x˙2+y˙2)nkn(ekn2100(xxn)2+ekn2100(yyn)2)

Agora precisamos resolver as equações de Euler-Lagrange:

ddtLx˙=Lx

e:

ddtLy˙=Ly

Assim:

ddtLx˙=ddt[cmex˙]=cmex¨

Lx=n200kn(xxn)ekn2100(xxn)2

x¨=n200kncme(xxn)ekn2100(xxn)2

E também:

ddtLy˙=ddt[cmey˙]=cmey¨

Ly=n200kn(yyn)ekn2100(yyn)2

y¨=n200kncme(yyn)ekn2100(yyn)2

Agora não precisamos ir mais longe: apenas olhamos para a direção da aceleração geral:

output={northif y¨<0 and |y¨|>|x¨|southif y¨>0 and |y¨|>|x¨|westif x¨<0 and |x¨|>|y¨|eastif x¨>0 and |x¨|>|y¨|noneif |y¨|=|x¨|

E assim, unificamos as moedas e os bots. Onde está o meu Prêmio Nobel?


5
Seu Prêmio Nobel foi perdido no correio, mas poderíamos dar-lhe um prêmio Emmy
Programas Redwolf

11
Parece que a física começa a ficar popular nesse desafio. :—D. E é claro que estou muito curioso sobre o quão bem isso vai acontecer.
Ramillies

11
(By the way, você poderia ter salvo o aborrecimento com as equações de Euler-Lagrange, porque reduzem ao fato bem conhecido que F = c_me a = - grad U :-).)
Ramillies

@Ramillies Meh, foi mais divertido fazê-lo desta maneira: D
Beta Decay

11
Tem certeza de que deseja usar as moedas k = de outra coisa / suas moedas? Você começa sem moedas ... e com o NaN em todos os lugares, não é provável que você obtenha nenhum.
Ramillies

8

Cachinhos Dourados, 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
}

Experimente online!

Apenas trava na localização da moeda de ouro e se move em direção a ela todas as vezes. (Obrigado ao bot 'B33-L1N3' do @ Mayube pelo código original usado, embora quase nada disso permaneça.)


Este é um bot simples e agradável. Eu gosto disso.
RedWolf Programas

2
A propósito, estou usando esse bot como teste para o meu controlador (:
Redwolf Programs 08/08/18

8

Algoritmo de Aprendizagem de Terceira Geração | 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)];
}

Experimente online!

Após algumas gerações de aprendizado, esse bot aprendeu que sair da arena é ruim


Oh bom. Ouvi dizer que isso se chama "Seleção Natural"
Programas Redwolf 08/08/18

5
Onde está a segunda geração
Luis felipe De jesus Munoz

11
@LuisfelipeDejesusMunoz Ele saiu da arena.
Jo.

Este é um bom bot para depurar o controlador
Programas Redwolf

3
Ah, a propósito, a arena começa em 0, assim deve ser arenaLength - 1. Isso matou seu bot algumas vezes várias vezes para muitos
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');
}

Experimente online!

Faz um caminho mais curto para a moeda mais próxima


Oh, eu pensei B33-L1N3 era algum tipo de número de modelo
RedWolf Programas

+1 para o nome
Caim

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

Exclualet
Redwolf Programs

5

Vivendo no limite, 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 ouviu que a borda da arena é um lugar perigoso para se estar. Sem medo, circula incansavelmente a prancha no sentido horário, a apenas alguns centímetros da morte certa que espera atrás da fronteira, esperando que nenhum outro bot se atreva a se mover tão perto da borda.


11
Isso não iria acabar bem se outro bot foram criados que tinha mais 1 moeda, e patrulhavam a fronteira na direção oposta (:
RedWolf Programas

8
Gostaria de fazer uma piada de controle de fronteira, mas estou deixando essa até @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
}

Experimente online!

Um último bot baseado em katamari de hoje, desta vez com um pouco de memória. Obrigado a @BetaDecay pela sugestão de nome - definitivamente um nome mais divertido que o meu simplePredictorKatamari.

Tenta descobrir como os bots se moveram no último turno e, com base nisso, prevê para onde eles tentarão se mover no final desse turno (supondo que continuem se movendo na mesma direção).

(Obrigado a @ fəˈnɛtɪk, por perceber que eu estava chamando o nome da função errada em botNotes, e a @ OMᗺ por perceber um erro no código base.)


Este é provavelmente o único agora que pode pegar outras pessoas além de apenas ter sorte.
Caim

As notas de bot não devem ser "dados armazenados" não são dados definidos?
f Augnɛtɪk 9/08/18

@ fəˈnɛtɪk Veja, já precisa de uma correção de bug! :) Obrigado, corrigido agora.
Sundar

Você deve substituir aWt = 1nos parâmetros por aWte colocar aWt = aWt || 1embaixo (o mesmo com bWt). Isso evita erros.
RedWolf Programas

5

Protão 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 as moedas (incluindo as mantidas por outros bots) emitem uma força repulsiva em relação ao Protonbot. Com base nessa força, ele aumenta a velocidade e salta das paredes (vira-se imediatamente ao atingir um limite). Se acabar ao lado de um bot ou moeda que possa consumir, a força nuclear forte assume o controle e se move para consumi-lo, diminuindo toda a velocidade quando o faz.


Hmm, física nuclear aplicada à caça ao tesouro? Isso supera o Science Channel a qualquer dia!
RedWolf Programas

Você precisa substituir sinpor Math.sin, cospor Math.cose assim por diante
Programas Redwolf

4

Não é tão cego | JavaScript (Node.js)

Nota importante: Essa abordagem não é totalmente minha e foi respondida em uma pergunta semelhante . Certifique-se de votar nessa resposta também.

Você já ouviu falar sobre o algoritmo A * pathfinding? Aqui está. Ele cria o melhor caminho de um ponto para a moeda menos valiosa (como todo mundo está buscando o mais valioso, ninguém está apostando pelo menos) e tenta não colidir com nenhum outro usuário.

Espera parâmetros da seguinte maneira:

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

Talvez eu faça um que vá caçar outros 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";
    }
}

11
Uau ... um algoritmo de busca de caminhos já? Faz apenas 3 horas!
RedWolf Programas

@RedwolfPrograms Como eu disse, ele é copiado de outro desafio semelhante. Só precisava adaptá-lo a este.
Luis felipe De jesus Munoz

Meus algoritmos vão para as moedas mais seguras.
fənɛtɪk

4

Covarde | 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 bots com mais dinheiro, se possível. Caso contrário, pegue o dinheiro que está por aí.


Este é o bot mais básico que tem uma chance de ganhar
RedWolf Programas

4

Bot de caça ao ganso selvagem, Javascript

Um bot que é realmente bom em desviar de outros bots, mas muito ruim em conseguir moedas.


Algoritmo:

  1. Se não houver bots adjacentes, não retorne
  2. De outra forma:
    1. Não retorne nenhum com uma chance aleatória 1/500 de chance (isso se destina a evitar impasses).
    2. Determine para quais espaços é seguro mover (ou seja, dentro da arena e não ocupado por outro bot)
    3. Devolver um aleatoriamente

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

Experimente Online!

Nota para os programas Redwolf:

Este bot tem o potencial de causar rodadas muito longas. Tomei algumas liberdades para evitar impasses, mas não testei se eles são realmente eficazes. Se este bot se tornar um problema durante o teste, fique à vontade para desqualificá-lo.


Obrigado pela observação. Um evasor especialista tem uma boa chance, se acontecer de coletar moedas suficientes enquanto estiver sendo perseguido.
Programas Redwolf

Eu gosto disso. É quase como isca para os robôs de caça
Decay Beta

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
}

Experimente online!

(Obrigado a @ OMᗺ por apontar um bug no código original em que ele se baseava.)

Tenta crescer "comendo" bots com menos moedas do que ele próprio. Se isso não for possível (não existe esse bot), procure a moeda mais próxima.

Esta versão possui pequenos ajustes para (a) dar maior preferência às moedas de ouro do que às moedas de prata - com o risco de que procurar uma moeda de ouro mais distante possa acabar custando a vida do bot ou levar à perseguição ao ouro do tolo (b) pule os robôs com 0 moedas - não há necessidade de perder tempo correndo atrás delas.


Um caçador inteligente ... bem, isso é ainda melhor!
RedWolf Programas

@RedwolfPrograms Vamos esperar que sim! :)
sundar

Deveria ter chamado isso de Damacy;)
Decay Beta

11

4

Educado Bot bêbado míope | 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
}

Cambaleia por aí pegando moedas próximas, mas muda de direção aleatoriamente de vez em quando. Faz o que pode para evitar esbarrar em alguém, mas ele fica ... beligerante ... quando agravado. Tende a ficar sóbrio à medida que a competição continua.

Pode precisar de alguma depuração, quando o controlador estiver totalmente pronto, trabalharei nele.


3
Hmm, ele levanta a barra, então fica bêbada em que
RedWolf Programas

4

Movimento 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";
}

Move-se na direção em que o valor mais alto foi atribuído e evita a fuga da borda do quadro.

O valor é calculado da seguinte forma:

  • Moeda = poder da moeda / distância da moeda
  • Bot = Diferença na potência dos bots / 2 * distância ao bot

11
Bem, isso parece um bot bastante incrível. Certifique-se de verificar as direções, uma vez que seria uma perda real se o seu bot era um mestre em executar longe de moedas (:
RedWolf Programas

Bem, ainda. Eu tenho que ser legal, certo?
RedWolf Programas

Bem, poste! Isso compensará os bots menores e mais rápidos que também existem no momento em grandes quantidades.
RedWolf Programas

for(i=0;i<6;i++){existem apenas 5 moedas no total, 1 ouro e 4 prata. Seu loop está sendo executado 6 vezes de 0 a 5.
night2

3

Cego JavaScript (Node.js)

Definitivamente, isso não vai ganhar, mas pelo menos participar. Primeira tentativa no desafio KoH. Classifica as moedas e vai para a mais próxima. Ele não procura jogadores, então não se importa se colidir com outros.

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, ele poderia funcionar uma vez que outros bots vai procurar o ouro, principalmente, potencialmente deixando-o para obter a prata sem qualquer combate
RedWolf Programas

3

Nobre Feudal | Javascript

Cor preferida: #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;
}

Esse nobre feudal fica no centro do campo e o reivindica como seu próprio palácio. Coleta qualquer coisa no centro para si, mas qualquer coisa em fazendas distantes deve ser trazida a ele pelos camponeses. É claro que se um poderoso camponês raivoso aparecer no palácio, nobres podem fugir para salvar sua vida, mas ele volta assim que for seguro!

À medida que o tempo passa, os camponeses ficam cada vez mais fortes. Lutadores profissionais e heróis poderosos começam a surgir dos camponeses. O poder dos nobres continua decaindo. Ele tenta manter sua riqueza e seu sistema feudalismo juntos o máximo que puder. Mas finalmente chega um momento em que ele deve aceitar sua fé, ele deve aceitar que as pessoas não querem mais o feudalismo. É o dia em que o nobre feudal desiste de tudo, não foge mais de camponeses poderosos e é morto por um deles.


2

Bot de mosquito quântico | 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
}

Esse bot irritante tenta zumbir em torno do bot mais forte sem ser atingido e tem uma pequena chance de passar por aqueles que tentam caçá-lo. Ele tende a aproximar os dois bots mais poderosos ...;)


Se ele não consegue encontrar um alvo adequado getTargetDirections(), coisas interessantes começam a acontecer. (Tais como quebrar tudo devido a undefined has no property 0erro.)
Ramillies

2

Agente ICE aposentado, JavaScript

Cor preferida: 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";
            }
        }
    }
}

Agora aposentado, esse agente do ICE é amargo com a humanidade. Como resultado, o ICE aposentado agora tem como alvo o bot mais fraco, mantendo o valor da moeda acima da média (conforme a política do ICE).


2

Perseguição Gananciosa | Haskell

Cor preferida: #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"

Experimente online! *

Estratégia bastante simples, escolhe a primeira decisão de:

  • se houver bots com menos moedas: escolha o mais próximo e avance para ele
  • se houver moedas: escolha o mais próximo e avance para ele
  • padrão: stay

O bot só tenta pegar outros bots ou moedas sem se importar com bots potencialmente mais fortes que possam tentar pegá-lo.

* Eu realmente não sei JavaScript, mas fiz o que fiz com o Google (pode ser impreciso): Experimente on-line!


6
Eu me pergunto como ele vai traduzir haskell em js
Luis Felipe de Jesus Munoz

3
@LuisfelipeDejesusMunoz: Sim, eu também. Mas, felizmente, não é um código muito sofisticado.
ბიმო

@LuisfelipeDejesusMunoz Basta usar o Node.JS e process.open(ou child_process.spawn, ou similar) com algumas análises.
user202729

@LuisfelipeDejesusMunoz: Tentei traduzi-lo e adicionei um link, mas não me sinto muito confiante ao escrever JavaScript, portanto pode ser um bug.
ბიმო

4
@LuisfelipeDejesusMunoz Seria uma coisa se esta era uma 10,000 linha de programa de aprendizagem AI, mas acho que pode gerir este (:
RedWolf Programas

1

Ímã da moeda | 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 é bastante idiota, ele segue na direção das moedas mais adquiríveis. Isso inclui moedas que não podem ser adquiridas porque outros bots têm maior poder do que ele.


1

Agente 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";
            }
        }
    }
}

Qual o sentido de uma fronteira se não está sendo patrulhada? O ICE se move no sentido anti-horário ao redor da fronteira, pegando todos os bots que se desviam no caminho.

Antes que possa fazer isso, ele precisa conseguir comer outros bots primeiro. Por esse motivo, o ICE mantém suas moedas acima da média de todos os bots.

Garantido para roubar crianças de seus pais ™


Isso seria mais engraçado se não fosse tão relevante #
Don Thousand

1

X marca o ponto | 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 o ponto, então todo o ouro deve estar no eixo x, certo? Meu bot vai direto para a linha y = 0 e fica lá, movendo-se aleatoriamente.


Huh, um método interessante, de fato #
Redwolf Programs


11
Dado que The arena starts at (0,0) in the upper left corner, tem certeza de que deseja mover southpara chegar y=0?
AdmBorkBork

@AdmBorkBork Obrigado, isso poderia ter sido ruim
Decay Beta

1

Firebird

    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 mais mortal do que antes (:


2
Meu perdedor absoluto de um bot
Redwolf Programs

Não está alvejando-los, é evitá-los
RedWolf Programas

Ah, desculpe, eu entendi errado #
1023 Decay Beta

1

A-caminho-y | Javascript

A cor preferida para este bot é #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 usa a localização de caminhos, juntamente com um mapa de conveniência das células, para evitar bots que podem nos matar, buscar moedas próximas, não armadilhas e menos arriscadas.

Não parece ser um candidato ao lugar vencedor, mas se mantém e estará vivo no final da partida, se sobreviver ao confronto inicial.

O Bot agora tem uma estratégia de jogo do meio ao fim, que ignora as moedas que não podem ser alcançadas antes dos outros bots e, se não puder ir a nenhuma moeda, passa para a célula mais próxima mais distante de todos os outros bots que são mais fortes que ele.

Agora tem uma chance de ganhar.

Nota desculpe pelo código de baixa qualidade, eu o converti automaticamente de Java


Certifique-se de obter quaisquer erros e / ou atualizações fora do caminho em breve, 18 horas antes da data prevista!
RedWolf Programas

@RedwolfPrograms Você já observou um bug? se assim for, por favor me avise para que eu possa corrigir. Obrigado
Moogie

Não, mas você nunca sabe. Apenas certifique-se de verificar
novamente
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.