Collectionneur d'or KoTH


48

Remarque: l'enquête sur les favoris de la communauté sera publiée bientôt

Dans ce KoTH, l’objectif est d’être le dernier bot en vie. Les pièces seront placées dans des zones aléatoires, et votre bot doit d'abord obtenir les pièces. Si un bot rencontre un autre bot, le bot avec plus de pièces gagne et l'autre meurt. Plus de détails ci-dessous.

Types de pièces

Il y aura 2 types de pièces: or et argent. L'or ajoute 5 pièces à la force du bot et l'argent en ajoute 2. Une fois qu'une pièce est collectée, une autre pièce est placée à un autre endroit du tableau. À tout moment, il y a une pièce d'or et quatre pièces d'argent dans l'arène.

Collisions de bot

Dans le cas où deux robots essaient d'occuper le même espace, celui qui a le plus de pièces restera et celui qui en a moins ... pas. Le bot gagnant remportera 85% des pièces de l'adversaire (arrondi au maximum). S'ils sont attachés, les deux meurent. Si trois ou plus essaient d'occuper le même espace, le plus puissant gagne et obtient 85% de toutes les pièces des autres robots. Au cas où le bot le plus puissant serait à égalité, tous les robots mourants qui ont tenté d'entrer dans l'espace meurent.

Arène

La longueur du côté de l'arène est calculée avec 4 + botCount. Lors du placement de bots au début du jeu, des emplacements aléatoires sont choisis. Le système garantit qu'aucun robot ne démarre dans le même espace ou l'un à côté de l'autre. Les pièces sont générées aléatoirement, à l’exception du carré 3 × 3 centré sur chaque bot. Si un bot est trouvé à l'extérieur de l'arène, il meurt instantanément. L'arène commence à (0,0), ou Nord-Ouest, dans le coin supérieur gauche, et l'emplacement d'un bot est toujours un entier.

Votre bot

Votre bot doit être une fonction, dans tout langage orienté objet qui comporte des tableaux, des entiers, des chaînes et des fonctions. Notez que toutes les soumissions seront converties en Javascript, pour simplifier les choses. Pour stocker des informations entre les déplacements, utilisez botNotes.storeData(key, value)et botNotes.getData(key, value). Vous ne pouvez pas stocker ou accéder aux données de quelque manière que ce soit, autre que celle fournie par les paramètres et botNotes. Vous devez créer une fonction qui, lorsqu'elle est appelée, retourne une chaîne north, east, south, westou none. Il y aura 3 arguments pour la fonction:

  • Un objet avec quatre entiers ( locationX, locationY, coins, arenaLength), votre emplacement actuel, vos pièces, et la longueur de l'arène

  • Un tableau multidimensionnel avec les coordonnées X et Y d’autres bots, ainsi que leur nombre de pièces,[[0,5,4],[4,7,1],[7,4,12]]

  • Un tableau avec les emplacements de pièces énumérés (Gold est toujours le premier)

C’est un défi roi, les échappatoires standard sont interdites. Votre fonction sera exécutée plusieurs milliers de fois, à chaque fois autorisée un "Move". Notez que si le jeu dépasse 20 000 coups , le bot avec le plus de pièces gagne. Cela sera fait 8 000 fois, pour éliminer le caractère aléatoire.

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

Prix:

Première place: prime de 100 points
Communauté préférée: réponse acceptée de 15 points

Gagnants:

Première place: TBTPTGCBCBA
Deuxième place: Big roi colline
Troisième place: Potentiellement Victorieux
Quatrième place: Polite myopes Ivre Bot
Cinquième place: Sécurité Coin


6
"Notez que toutes les soumissions seront converties en Javascript, pour simplifier les choses." Comment cela est-il censé fonctionner? Faites-vous la conversion?
Laikoni

21
Il n'y a rien de mal à ce qu'un koth n'autorise qu'une seule langue, en particulier une langue aussi répandue que JavaScript. Plutôt que de "convertir" de manière ambiguë des réponses en JavaScript (probablement vous-même et manuellement), vous devriez simplement limiter le défi à JS. Après tout, nous avons eu beaucoup de koths uniquement Java et Python.
Skidsdev

2
Une version de celui-ci dans laquelle vous contrôleriez l'accélération au lieu de la position serait plutôt cool.
akozi

12
A tous: il y a déjà trop de commentaires. Ne laissez pas de commentaires inutiles tels que "+1, nice bot" et supprimez-les s'il est redondant . Nous ne sommes pas un site de questions / réponses typique, mais personne n'aime lire des centaines de commandes.
user202729

5
(À ma propre question): Selon NP en discussion, il s’agit de la dernière: tous les robots bougent, puis tous les conflits sont résolus, puis toutes les collectes de pièces se produisent, puis toutes les nouvelles pièces sont placées.
BradC

Réponses:


26

BaitBot - Node JavaScript.JS

Pourquoi se donner la peine de courir ou de courir si vous ne pouvez jamais attraper? Au lieu de cela, BaitBot trouve la pièce la plus proche et attend qu'un bot plus faible s'en approche également. Quand ils sont tous les deux adjacents, baitBot cherche la pièce en supposant que le bot le plus faible le sera également. Si baitBot attend et qu'un bot plus fort s'approche, il attrape juste la pièce et monte à cheval. Essaie-moi!

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

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

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



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

}

1
Ha, c'est une bonne idée, je l'aime bien.
dimanche - Réintégrer Monica

Cette approche est assez cool ... non, très cool
Programmes Redwolf

1
BaitBot a besoin nearestThreat && distanceTo(nearestThreat)plutôt que juste distanceTo(nearestThreat). Il échoue lorsqu'il n'y a pas de menace.
Programmes Redwolf

1
Oui, nearestThreatest undefinedsi tous les autres robots ont plus de points que le vôtre.
Night2

1
Eh bien, je reçois des avis comme [10] Bot Bait Bot tired of this world, and jumped off its edgedans mon journal des événements
Programmes Redwolf

17

Algorithme d'apprentissage de première génération | JavaScript (Node.js)

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

Essayez-le en ligne!

Avez-vous déjà vu ces timelapses d'apprentissage d'algorithmes apprendre à jouer à un jeu? Ils se déplacent souvent de manière presque aléatoire au cours des premières générations ...


LOL ... Ca pourrait encore marcher!
Programmes Redwolf

2
La plupart des algorithmes d'apprentissage fonctionnent littéralement de manière aléatoire pour les premières itérations, et pas seulement de manière presque aléatoire.
fəˈnɛtɪk

Devine quoi? Ce bot a reçu en moyenne près de 0,22 pièce par tour!
Programmes Redwolf

17

Potentiellement victorieux | JavaScript

La couleur préférée pour ce bot est #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];
}

(Toutes mes excuses pour la mise en forme peu soignée, l'indentation de 4 espaces pour ce site ne va pas bien avec ma coutume d'utiliser des onglets.)

Explication approximative

Je démissionne par la présente pour tenter de mettre à jour l'explication des formules. Les coefficients changent constamment et il est un peu difficile de garder l'explication à jour. Je vais donc simplement expliquer le principe général.

Chaque pièce et chaque bot génère un champ de force avec un potentiel. J'ajoute simplement les potentiels de tout et le bot va ensuite là où le potentiel est le plus bas. (Évidemment, cette idée est volée à la physique.)

J'utilise deux types de potentiels. Le premier est un pseudo-gravitationnel (qui agit à toute distance), avec Lekest une "force" du champ et, avec ce choix de signe, le potentiel est attrayant. Lerici (et partout ailleurs) est la distance dans la métrique du taxi,r = | x₁ - x₂ | + | y₁ - y₂ | .

U=kr+1511+n.

J'utilise k = 40 pour les pièces d'or et k = 10 pour les pièces d'argent. n est le nombre de robots qui sont plus proches de la pièce que nous. Sinon, nous ignorons absolument les autres robots (si nous nous opposons à un bot plus puissant, nous nous enfuyons, mais c'est tout). J'apprécie les pièces d'or pour plus qu'elles ne valent, car sinon, les bots qui ont pour objectif principal de chercher après l'or me battent tout le temps.

Le second potentiel est un potentiel en décroissance exponentielle (qui n'agit effectivement que sur de très petites distances). Ceci est généré par les autres robots, principalement les plus puissants.

Celles-ci produisent un champ avec Cette force est prohibitive à la gamme 0-1, mais décroît à presque rien aux distances plus grandes. (Distance + 1 signifie couper la force en 1/20.)

U=5×1400e3r.

En général, nous n'attaquons pas les autres robots de manière intentionnelle (bien sûr, s'ils nous gênent et que nous leur piétinons, c'est de leur faute), mais il est possible de le faire. Si certaines conditions difficiles sont remplies, nous pouvons passer en mode chasse en étant concentrés sur un seul bot. Pour entrer en mode chasse:

  1. Nous devons avoir au moins 25 pièces. (Nous devons d'abord obtenir des pièces de monnaie.)
  2. Ils doivent avoir au plus (nos pièces - 5) pièces et au moins 10 pièces. (Nous ne voulons pas chasser quelqu'un qui attrape une pièce et est soudain plus puissant, et nous ne voulons pas non plus poursuivre les robots à zéro pièce.)
  3. Nous devons prendre au moins 1/10 de ses pièces par rapport au bot actuellement en tête du classement. (Vous devez avoir la chance de chasser quelque chose, il n’est donc pas nécessaire de donner une bonne position juste pour tenter notre chance.)
  4. Nous ne devons pas être sur un temps de recharge de chasse (voir ci-dessous).

Si toutes ces conditions sont remplies, le mode de recherche est activé. Pour les 10 tours suivants, le bot traqué n’émet que le potentiel Une fois ces 10 tours écoulés, nous entrons dans le temps de recharge de la chasse, pendant lequel nous ne pouvons plus entrer en mode chasse. (C'est pour nous empêcher de poursuivre inutilement et infructueusement un bot pendant que tous les autres saisissent des pièces avec bonheur.) Le temps de recharge de la chasse est de 20 tours lorsque nous avons 25 pièces et augmente de 20 pièces par double de ce montant. (En d’autres termes, le temps de recharge est

U=150er.
20(1 + log2(c / 25)).) (Nous l’utilisons parce qu’en fin de jeu, tous les robots pouvant être chassés sont probablement morts, et donc toute chasse sera probablement vaine. Pour cette raison, nous voulons limiter le temps perdu. Mais parfois, un retard chanceux manger du gibier peut tout changer, alors nous gardons la possibilité.)

Enfin, l’arène entière est placée dans un puits de potentiel infini qui empêche le bot de s’échapper.


Je pense que ce bot bat probablement aussi mon mouvement pondéré.
fəˈnɛtɪk

@ fəˈnɛtɪk - Moi aussi :—). Je pense que celui-ci peut gérer les autres robots un peu mieux. (En outre, ce n'est pas "aveuglé" par une pièce de monnaie sur une place adjacente.) Mais je vous ai certainement donné +1 car je suis un grand fan de cette idée.
Ramillies

Pourriez-vous appliquer le principe de moindre action à cela?
Beta Decay

@BetaDecay: Je crains fort que le calcul ne réponde pas bien à des problèmes aussi discrets que celui-ci. Même dans le cas continu, cela ne serait pas trivial (à cause de la magnitude fixe de la vitesse), mais cela pourrait être faisable après une certaine magie des coordonnées polaires je suppose.
Ramillies

4
C'est cool. Je ne suis pas sûr que le risque soit lié de manière monotone à la distance, cependant, il semble qu'une menace située à deux espaces de distance soit plus susceptible de vous tuer que celle adjacente, car dans ce dernier cas, l'un de vous deux doit rester immobile pour qu'une collision se produise.
Cain

16

Grand roi petite colline | 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])
}

Essayez-le en ligne!

Big King Little Hill prend ses décisions en fonction de «zones de contrôle». Il ne poursuivra que les pièces qui se trouvent dans sa zone de contrôle, ce qui signifie qu'il peut atteindre la pièce avant tout autre bot. Lorsqu'il n'y a pas de pièces dans sa zone de contrôle, il se déplace plutôt pour maximiser la taille de sa zone de contrôle. Big King Little Hill calcule la zone de contrôle de chacun de ses 5 mouvements possibles et privilégie les mouvements qui maximisent la taille de sa zone de contrôle. De cette manière, Big King Little Hill atteint finalement un maximum de contrôle local (petite colline) et attend qu'une pièce soit générée dans sa zone. De plus, Big King Little Hill rejette toute initiative qui pourrait entraîner sa mort, à moins qu'il n'y ait pas d'alternative.

Big King Little Hill est un pessimiste (il préfère le terme réaliste) car il ne se donne pas la peine de contester une pièce qu'il n'est pas assuré d'obtenir. C'est aussi un pacifiste dans le sens où il ne recherche en aucun cas les robots les plus faibles (bien qu'il puisse en faire un s'ils ne gênent pas). Enfin, Big King Little Hill est un lâche qui ne mettra pas sa vie en péril pour quelque récompense que ce soit, sauf obligation absolue.


1
Bienvenue chez PPCG! C'est un très bon bot = D
Luis felipe De jesus Munoz

C'est ce que je pensais pour un bot. Bon travail.
Jo.

10

Pièce de sécurité | 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";}
  }
}

Ce bot se dirige directement vers une pièce de valeur pondérée (valeur / distance) qu'il ne peut pas mourir d'atteindre en même temps ou après un autre bot. S'il n'y a pas de pièce de monnaie valide avec cette propriété, elle se trouve là où il se trouve que le bot se déplace maintenant dans une direction de sécurité aléatoire (la sécurité signifie que si un bot s'approche de lui, la pièce de sécurité ne peut pas entrer en collision. Cela lui permet d'échanger des places avec un autre bot si juste à côté) pesant vers le centre de l’arène.


1
Euh, cela peut réellement gagner. Bien qu'il y ait beaucoup de robots
Programmes Redwolf

Cette méthode aura plus de problèmes, plus les bots ennemis avec une valeur supérieure ou égale seront placés de manière inégale.
fəˈnɛtɪk

1
Eh bien, ils vont probablement tous faire un beeline à la pièce la plus proche d'eux / pièce d'or.
Programmes Redwolf

Cela ne fonctionnera que s’il parvient à obtenir des pièces dès le départ.
fəˈnɛtɪk

Et c'est surtout de la chance, car l'endroit où les pièces sont générées est choisi au hasard
Programmes Redwolf

10

Le bot qui joue le jeu avec prudence mais qui peut être agressif | JavaScript

Couleur préférée: #F24100

Note: Bien que ce bot ait pris la 1ère place, il doit faire équipe avec "Feudal Noble" à la fin et le manger pour plus de pièces. Sinon, ce bot aurait été 3ème. Si vous êtes intéressé par les robots qui sont plus puissants individuellement, allez voir Potential Victorious et 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;
}

Ce bot (aka "TBTPTGCBCBA") tente de prendre la meilleure décision possible en générant un score pour chaque coup possible et sélectionne le coup avec le score le plus élevé à chaque tour.

Le système de notation comporte de nombreux détails qui ont évolué depuis le début du défi. Ils peuvent être décrits généralement comme ceci:

  • Plus les pièces sont proches d'un mouvement possible, plus le score obtenu est important. Si une pièce n'a pas d'autre concurrent possible, le score va encore plus haut. Si une pièce a d'autres concurrents possibles, le score diminue.
  • Si un autre bot est proche d'un mouvement possible et a moins de pièces, selon la phase du jeu, cela pourrait signifier plus de points pour ce mouvement. Il est donc décontracté pour "TBTPTGCBCBA" de manger quelques autres bots à chaque match.
  • Si un autre bot est proche d'un mouvement possible avec un nombre de points égal ou supérieur, ce mouvement obtient un score négatif suffisant pour éviter la mort. Bien sûr, il peut arriver que tous les mouvements possibles soient mauvais et que la mort ne puisse être évitée, mais cela est très rare.
  • Il existe un mécanisme permettant de suivre le nombre de robots au milieu du tableau pour les 20 derniers tours. Si la moyenne est suffisamment basse, tous les mouvements vers les pièces du milieu obtiennent un score plus élevé. Si la moyenne est élevée, tous les mouvements vers les pièces du milieu obtiennent un score inférieur. Ce mécanisme permet d'éviter les conflits avec "Feudal Noble". Puisque le "Noble féodal" est toujours au centre (sauf s'il est chassé), le nombre moyen de robots au milieu augmente et "TBTPTGCBCBA" comprend qu'il faut éviter le milieu s'il y a une meilleure option en dehors de la zone centrale. Si "Feudal Noble" meurt, la moyenne baisse et "TBTPTGCBCBA" comprend qu'il peut utiliser le milieu.
  • Certains facteurs changent de manière dynamique en fonction de la phase du jeu (détectés en fonction du nombre de bots vivants), ces facteurs affectent le score de chacun des éléments ci-dessus.
  • Ce bot a une capacité spéciale. Au fil du temps, il se lasse de l'égoïsme de "Feudal Noble" et de l'oppression des paysans. Au bon moment, cela mettra fin au désagréable système de féodalisme. Une tentative réussie aide non seulement les paysans pauvres, mais offre également une plus grande chance de gagner grâce aux pièces prises au "Féodal Noble".

Il semble beaucoup plus ... intelligent que les autres
Programmes Redwolf

5
J'aime les monstres qui font partie des params
Programmes Redwolf

9

L'anti-capitaliste | Javascript

N'a aucune incitation à aller après les pièces de monnaie, mais essaie de se placer exactement entre les deux bots les plus riches avec le même montant d'argent, dans l'espoir qu'ils le pourchasseront et le rattraperont en même temps, emmenant deux capitalistes avec lui à sa mort. . Ne résiste pas activement à obtenir des pièces de monnaie, il pourrait donc devenir une cible plus juteuse.

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

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

Avec Potential Victorious, nous avons deux champs: le champ bot et le champ pièce. Cependant, la nature n'est pas si compliquée. Il est temps d'unifier les deux champs pour produire la grande théorie unifiée .

Premièrement, nous devons déterminer le potentiel de ce domaine. En supposant que notre propre bot n'influence en aucun cas le champ, nous pouvons écrire ceci comme suit:

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

kn(xn,yn)

La propriété relative de l'objet est calculée comme suit:

k=cobjectcme

ccme=cself+1cself

Appelons simplement cette correction une partie de Modified Betanian Dynamics (MOBD) .

Nous pouvons également trouver l'énergie cinétique sous la forme:

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

Nous pouvons maintenant calculer l'action:

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

Et ainsi le lagrangien de notre bot dans le champ coin-bot est:

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

Nous devons maintenant résoudre les équations d'Euler-Lagrange:

ddtLx˙=Lx

et:

ddtLy˙=Ly

Alors:

ddtLx˙=ddt[cmex˙]=cmex¨

Lx=n200kn(xxn)ekn2100(xxn)2

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

Et aussi:

ddtLy˙=ddt[cmey˙]=cmey¨

Ly=n200kn(yyn)ekn2100(yyn)2

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

Maintenant, nous n’avons plus besoin d’aller plus loin: nous examinons simplement la direction de l’accélération globale:

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¨|

Et juste comme ça, nous avons unifié les pièces et les robots. Où est mon prix Nobel?


5
Votre prix Nobel a été perdu dans le courrier, mais nous pourrions vous donner un Emmy Award
Programmes Redwolf

1
On dirait que la physique commence à devenir populaire dans ce défi. :-RÉ. Et bien sûr, je suis très curieux de savoir si ça va bien se passer.
Ramillies

1
(Soit dit en passant, vous auriez pu sauver les tracas avec les équations d' Euler-Lagrange, parce qu'ils réduisent au fait bien connu que F = c_me a = - grad U :-).)
Ramillies

@Ramillies Meh, c'était plus amusant de le faire de cette façon: D
Beta Decay

1
Êtes-vous sûr de vouloir utiliser les k = pièces de quelque chose d'autre / de vos pièces? Vous commencez sans pièces de monnaie ... et avec NaN partout, vous n'êtes pas très susceptible d'en obtenir.
Ramillies

8

Boucle d'or, 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
}

Essayez-le en ligne!

Il suffit de verrouiller l'emplacement de la pièce d'or et de s'y déplacer à chaque fois. (Merci au bot 'B33-L1N3' de @ Mayube pour le code original utilisé, bien qu'il ne reste pratiquement plus rien.)


C'est un joli joli bot simple. Je l'aime.
Programmes Redwolf

2
En passant, j'utilise ce bot comme test pour mon contrôleur (:
Programmes Redwolf

8

Algorithme d'apprentissage de troisième génération | 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)];
}

Essayez-le en ligne!

Après quelques générations d'apprentissage, ce bot a appris que quitter l'arène = mauvais


Oh super. J'ai entendu dire que cela s'appelle "Sélection naturelle"
Programmes Redwolf 8/08

5
Où est la deuxième génération
Luis felipe De jesus Munoz

11
@LuisfelipeDejesusMunoz Il a quitté l'arène.
Jo.

C'est un bon bot pour déboguer le contrôleur
Programmes Redwolf

3
Oh, au fait, l'arène commence à 0, il devrait en être ainsi arenaLength - 1. Cela a tué votre bot plusieurs fois sur plusieurs
Programmes Redwolf

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

Essayez-le en ligne!

Fait un beeline pour la pièce la plus proche


Oh, je pensais que B33-L1N3 était une sorte de numéro de modèle
Programmes Redwolf

+1 pour le nom
Cain

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

Supprimer lelet
Programmes Redwolf

5

Livin 'on the Edge, 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';
  }
}

Celui-ci a entendu dire que le bord de l'arène était un endroit dangereux. Ne sachant aucune peur, il tourne inlassablement le tableau dans le sens des aiguilles d'une montre, à seulement quelques centimètres de la mort certaine qui l'attend derrière la frontière, espérant qu'aucun autre bot n'ose se déplacer si près du bord.


1
Cela ne finirait pas bien si un autre bot était créé, qui avait 1 pièce de plus et patrouillait la frontière dans la direction opposée (:
Programmes Redwolf

8
Je ferais une blague de contrôle des frontières, mais je la laisse à @BetaDecay
Programmes Redwolf.

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
}

Essayez-le en ligne!

Un dernier bot katamari pour aujourd'hui, cette fois avec un peu de mémoire. Merci à @BetaDecay pour la suggestion de nom - certainement un nom plus amusant que monsimplePredictorKatamari .

Essaie de comprendre comment les bots se sont déplacés lors du dernier tour et, en fonction de cela, prédit où ils vont essayer de se déplacer à la fin de ce tour (en supposant qu'ils continuent à avancer dans la même direction).

(Merci à @ fəˈnɛtɪk, pour avoir remarqué que j'appelais un nom de fonction incorrect dans botNotes, et à @ OM pour avoir remarqué un bogue dans le code de base.)


C’est probablement le seul à l’heure actuelle qui peut attraper d’autres personnes que la chance.
Cain

Les notes de bot ne sont-elles pas supposées être des "données stockées" non des données setdata?
fəˈnɛtɪk

@ fəˈnɛtɪk Vous voyez, il faut déjà un correctif! :) Merci, corrigé maintenant.
dimanche

Vous devriez remplacer aWt = 1dans les paramètres avec aWt, et mettre aWt = aWt || 1dessous (idem avec bWt). Cela évite les erreurs.
Programmes Redwolf

5

Proton | 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;
}

Toutes les pièces (y compris celles détenues par d'autres robots) émettent une force répulsive envers Protonbot. Basé sur cette force, il accumule de la vitesse et rebondit sur les murs (se retourne immédiatement après avoir heurté une limite). Si elle finit à côté d'un robot ou d'une pièce de monnaie, elle peut consommer, la force nucléaire Forte prend le relais et bouge pour la consommer, réduisant ainsi sa vitesse.


Hmm, la physique nucléaire appliquée à la chasse au trésor? Cela bat Science Channel n'importe quel jour!
Programmes Redwolf

Vous devez remplacer sinpar Math.sin, cosavec Math.cos, etc.
Programmes Redwolf

4

Pas si aveugle | JavaScript (Node.js)

Note importante: Cette approche n’est pas tout à fait la mienne et une réponse à cette question a été donnée . Assurez-vous de voter cette réponse aussi.

Avez-vous déjà entendu parler de l'algorithme A * pathfinding? C'est ici. Il crée le meilleur chemin d'un point à la pièce de moindre valeur (chacun cherchant le plus précieux, personne ne cherchant le moins) et essaie de ne pas entrer en collision avec un autre utilisateur.

Paramètres attendus comme suit:

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

Peut-être que j'en fais un qui chasse d'autres bots


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

1
Wow ... un algorithme de recherche de chemin déjà? Cela ne fait que 3 heures!
Programmes Redwolf

@RedwolfPrograms Comme je l'ai dit, il est copié d'un autre défi similaire. Juste besoin de l'adapter à celui-ci.
Luis felipe De jesus Munoz

Mes algorithmes s’appliquent aux pièces les plus sûres.
fəˈnɛtɪk

4

Lâche | 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)

Évitez les robots avec plus d'argent si possible. Sinon, prenez l'argent qui traîne.


Ceci est le bot le plus élémentaire qui a une chance de gagner
Programmes Redwolf

4

Wild Goose Chase Bot, Javascript

Un bot qui sait très bien éviter les autres robots, mais très mal à obtenir des pièces.


Algorithme:

  1. S'il n'y a pas de robots adjacents, renvoyez aucun
  2. Autrement:
    1. Ne renvoyer aucun avec une chance aléatoire de 1/500 chance (ceci est destiné à éviter les impasses).
    2. Déterminez les espaces où vous pouvez vous déplacer en toute sécurité (à l'intérieur de l'arène et non occupés par un autre bot)
    3. Renvoyer un au hasard

Code:

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

Essayez-le en ligne!

Note aux programmes Redwolf:

Ce bot a le potentiel de provoquer de très longs rounds. J'ai pris quelques libertés pour éviter les impasses, mais je n'ai pas vérifié si elles étaient réellement efficaces. Si ce bot pose un problème lors des tests, n'hésitez pas à le disqualifier.


Merci pour la note. Un expert en évasion a de bonnes chances s'il
réussit

J'aime ça. C'est presque comme un appât pour les robots de chasse
Beta Decay

4

KatamariWithValues, JavaScript (Node.js) ,

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

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

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

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

  if (!done)
    dir = 'none'

  return dir
}

Essayez-le en ligne!

(Merci à @ OMᗺ pour avoir signalé un bogue dans le code d'origine sur lequel il était basé.)

Essaie de grandir en "mangeant" des robots avec moins de pièces que lui-même. Si ce n'est pas possible (aucun tel bot n'existe), alors cherche la pièce la plus proche.

Cette version comporte de petites modifications pour (a) donner une préférence plus grande aux pièces d'or qu'aux pièces d'argent - avec le risque de rechercher une pièce d'or plus éloignée pouvant coûter la vie du bot ou conduire à la poursuite de celui du fou (b) sauter des bots avec 0 pièces - pas besoin de perdre du temps à courir après celles-ci.


Un chasseur malin ... eh bien, c'est encore mieux!
Programmes Redwolf

@RedwolfPrograms Espérons-le! :)
dimanche

J'aurais dû appeler ça Damacy;)
Beta Decay

1
@BetaDecay Souhait exaucé.
dimanche

4

Bot ivre à vision courte et poli | 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
}

Staggers autour ramasser des pièces de monnaie à proximité, mais change de direction au hasard de temps en temps. Fait ce qu'il peut pour ne pas heurter quelqu'un, mais il devient ... belligérant ... lorsqu'il est aggravé. A tendance à se dégriser au fur et à mesure de la compétition.

Il faudra peut-être un peu de débogage, lorsque le contrôleur sera terminé, je travaillerai dessus.


3
Hmm, il monte la barre, puis s'enivre
Programmes Redwolf

4

Mouvement pondéré | JavaScript

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

Se déplace dans la direction dans laquelle il a attribué la valeur la plus élevée tout en évitant de sortir du bord du tableau.

La valeur est calculée comme telle:

  • Pièce = puissance de la pièce / distance par pièce
  • Bot = Différence de puissance des bots / 2 * distance au bot

1
Eh bien, cela ressemble à un bot assez génial. Assurez-vous de vérifier les instructions, car ce serait une perte réelle si votre bot était un maître pour fuir les pièces de monnaie (:
Programmes Redwolf

Eh bien, toujours. Je dois être gentil, non?
Programmes Redwolf

Eh bien, postez-le! Cela compensera les bots plus rapides et plus petits qui existent également en ce moment en grande quantité.
Programmes Redwolf

for(i=0;i<6;i++){il n'y a que 5 pièces au total, 1 or et 4 argent. Votre boucle est en cours d'exécution 6 fois de 0 à 5.
Night2

3

Aveugle | JavaScript (Node.js)

Cela ne va certainement pas gagner mais au moins participer. Essayez d'abord le défi KoH. Il trie les pièces et va au plus proche. Il ne cherche pas de joueurs, donc il ne se soucie pas de se heurter aux autres.

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
}

Hum, ça pourrait marcher puisque d'autres bots chercheront principalement de l'or, ce qui vous laissera potentiellement l'argent sans combat
Programmes Redwolf

3

Noble féodal | JavaScript

Couleur préférée: #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;
}

Ce noble féodal reste au centre du domaine et le revendique comme son propre palais. Il ramasse n'importe quoi au centre, mais tout ce qui se trouve dans des fermes lointaines doit lui être apporté par les paysans. Bien sûr, si un paysan puissant et furieux apparaît au palais, le noble pourrait s'enfuir pour sauver sa vie, mais il reviendra dès qu'il sera en sécurité!

Au fil du temps, les paysans deviennent de plus en plus forts. Les combattants professionnels et les héros puissants commencent à sortir de la paysannerie. Le pouvoir du noble ne cesse de se dégrader. Il essaie de garder sa richesse et son système de féodalisme ensemble aussi longtemps qu'il le peut. Mais finalement, un temps vient où il devrait accepter sa foi, il devrait accepter que les gens ne veulent plus du féodalisme. C'est le jour où le noble féodal abandonne tout, ne court plus de paysans puissants et se fait tuer par l'un d'entre eux.


2

Quantum Gnot Bot | JavaScript

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

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

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

  return chosenDir
}

Ce bot agaçant essaie de siffler autour du bot le plus puissant sans se faire écraser et a une légère chance de voir passer ceux qui tentent de le chasser. Il a tendance à rapprocher les deux robots les plus puissants ...;)


S'il ne peut pas trouver une cible appropriée getTargetDirections(), des choses intéressantes commencent alors à se produire. (Par exemple, tout casser à cause d'une undefined has no property 0erreur.)
Ramillies

2

Agent ICE à la retraite, JavaScript

Couleur préférée: 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";
            }
        }
    }
}

Maintenant à la retraite, cet agent ICE est amer pour l'humanité. Par conséquent, ICE, retraité, cible désormais le bot le plus faible, tout en maintenant sa valeur de pièce au-dessus de la moyenne (conformément à la politique ICE).


2

Greedy-Pursuit | Haskell

Couleur préférée: #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"

Essayez-le en ligne! *

Stratégie assez simple, prend la première décision parmi:

  • s'il y a des robots avec moins de pièces: choisissez le plus proche et avancez vers lui
  • s'il y a des pièces: choisissez le plus proche et avancez vers elle
  • défaut: rester

Le bot essaie seulement d'attraper d'autres robots ou des pièces sans se soucier des robots potentiellement plus puissants qui pourraient essayer de l'attraper.

* Je ne connais pas vraiment JavaScript mais j’ai fait la même chose avec Google (peut-être inexact): essayez-le en ligne!


6
Je me demande comment il va traduire haskell en js
Luis felipe De jesus Munoz

3
@ LuisfelipeDejesusMunoz: Ouais moi aussi. Mais heureusement, ce n'est pas un code très sophistiqué.
ბიმო

@LuisfelipeDejesusMunoz Utilisez simplement Node.JS et process.open(ou child_process.spawn, ou similaire) avec une analyse syntaxique.
user202729

@LuisfelipeDejesusMunoz: J'ai essayé de le traduire et ajouté un lien, mais je ne me sens pas très en confiance pour écrire du JavaScript, ce qui pourrait bien être un buggy.
ბიმო

4
@LuisfelipeDejesusMunoz Ce serait une chose s'il s'agissait d'un programme d'apprentissage de 10 000 lignes d'intelligence artificielle, mais je pense que je peux y arriver (:
Programmes Redwolf

1

Aimant de pièce | 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";
}

Ce bot est plutôt stupide, il se dirige vers les pièces les plus accessibles. Cela inclut les pièces qu'il ne peut pas obtenir car d'autres robots ont un pouvoir plus élevé que lui-même.


1

ICE Agent | 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";
            }
        }
    }
}

Quel est l'intérêt d'une frontière si on ne patrouille pas? ICE se déplace dans le sens inverse des aiguilles d'une montre autour de la frontière, ramassant les bots qui s'égarent sur son chemin.

Avant de pouvoir le faire, il doit d'abord pouvoir manger d'autres robots. Pour cette raison, ICE maintient ses pièces au-dessus de la moyenne de tous les robots.

Garanti de voler les enfants de leurs parents ™


Ce serait plus drôle si ce n'était pas si pertinent
Don Thousand

1

X marque le spot | 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 marque l'endroit, donc tout l'or doit être sur l'axe des x, non? Mon bot fait un beeline pour la ligne y = 0 puis y reste, se déplaçant au hasard.


Euh, une méthode intéressante
Programmes Redwolf


1
Étant donné que The arena starts at (0,0) in the upper left corner, êtes - vous sûr que vous voulez déplacer southpour se rendre à y=0?
AdmBorkBork

@AdmBorkBork Merci, ça aurait pu être mauvais
Beta Decay

1

Oiseau de feu

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

Complètement réorganisé pour être plus meurtrier qu'auparavant (:


2
Mon perdant absolu d'un bot
Programmes Redwolf

Ce n'est pas pour les cibler, mais pour les éviter
Programmes Redwolf

Oh désolé, j'ai mal compris
Beta Decay

1

A-Path-y | JavaScript

La couleur préférée pour ce bot est #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);
}

Ce bot utilise la recherche de trajectoire couplée à une carte de la désirabilité des cellules pour éviter les robots susceptibles de nous tuer, optez pour des pièces proches, pas des pièges et qui présentent le moins de risques.

Il ne semble pas être un prétendant à la place gagnante, mais il tient bon et sera en vie à la fin du match s'il survit à la mêlée initiale.

Bot a maintenant une stratégie de jeu allant du milieu à la fin qui ignore les pièces qu'il ne peut pas atteindre avant les autres robots. S'il ne peut accéder à aucune pièce, il se déplace ensuite vers la cellule la plus proche qui est la plus éloignée de tous les autres robots plus puissants que la sienne.

Il a maintenant une chance de gagner.

Remarque désolé pour le code merdique, je l'ai automatiquement converti à partir de Java


Assurez-vous que tous les bogues et / ou mises à jour soient résolus sous peu, 18 heures avant la date d'échéance!
Programmes Redwolf

@RedwolfPrograms Avez-vous observé un bug? Si tel est le cas, faites le moi savoir afin que je puisse corriger. Merci
Moogie

Non, mais on ne sait jamais. Assurez-vous simplement de vérifier, car j'ai vu beaucoup de bots perdre à cause d'un seul numéro, d'une mauvaise fonction ou d'un type incorrect plus de fois que je ne peux les compter
Programmes Redwolf
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.