Goldsammler KoTH


48

Hinweis: Die Umfrage zum Community-Favoriten wird in Kürze veröffentlicht

In diesem KoTH ist es das Ziel, der letzte lebende Bot zu sein. Münzen werden in zufälligen Bereichen platziert, und Ihr Bot muss zuerst die Münzen erhalten. Wenn ein Bot auf einen anderen Bot trifft, gewinnt der Bot mit mehr Münzen und der andere Bot stirbt. Weitere Details unten.

Münztypen

Es wird 2 Arten von Münzen geben: Gold und Silber. Gold erhöht die Stärke des Bots um 5 Münzen und Silber um 2. Sobald eine Münze gesammelt wurde, wird eine weitere Münze an einer anderen Stelle auf dem Brett platziert. Zu jeder Zeit befinden sich eine Goldmünze und vier Silbermünzen in der Arena.

Bot-Kollisionen

Wenn zwei Bots versuchen, den gleichen Platz einzunehmen, bleibt der mit den mehr Münzen und der mit den weniger ... nicht. Der siegreiche Bot erhält 85% der Münzen des Gegners (aufgerundet). Wenn sie gebunden sind, sterben beide. Versuchen drei oder mehr, dasselbe Feld zu besetzen, gewinnt der Mächtigste und erhält 85% aller Münzen des anderen Bots. Für den Fall, dass der mächtigste Bot ein Unentschieden ist, sterben alle Bots, die versucht haben, das Feld zu betreten.

Arena

Die Seitenlänge der Arena wird mit berechnet 4 + botCount. Wenn Bots zu Beginn des Spiels platziert werden, werden zufällige Orte ausgewählt. Das System stellt sicher, dass keine Bots im selben Raum oder nebeneinander beginnen. Münzen werden zufällig generiert, mit Ausnahme eines 3 x 3-Quadrats, das auf jedem Bot zentriert ist. Wird ein Bot außerhalb der Arena gefunden, stirbt er sofort. Die Arena beginnt bei (0,0) oder Nordwesten in der oberen linken Ecke, und die Position eines Bots ist immer eine Ganzzahl.

Dein Bot

Ihr Bot sollte eine Funktion in jeder objektorientierten Sprache sein, die Arrays, Ganzzahlen, Zeichenfolgen und Funktionen enthält. Beachten Sie, dass alle Einsendungen in Javascript konvertiert werden, um die Sache zu vereinfachen. Verwenden Sie botNotes.storeData(key, value)und, um Informationen zwischen den Zügen zu speichern botNotes.getData(key, value). Sie dürfen auf keine andere Weise als die durch die Parameter und angegebenen Daten speichern oder darauf zugreifen botNotes. Sie sollten eine Funktion erstellen , die, wenn sie aufgerufen wird , eine Zeichenfolge zurückgibt north, east, south, west, oder none. Es gibt 3 Argumente für die Funktion:

  • Ein Objekt mit vier ganzen Zahlen ( locationX, locationY, coins, arenaLength), momentaner Standort, Ihre Münzen, und die Länge der Arena

  • Ein mehrdimensionales Array mit den X- und Y-Koordinaten anderer Bots und deren Münzzahl[[0,5,4],[4,7,1],[7,4,12]]

  • Ein Array mit den aufgelisteten Münzpositionen (Gold steht immer an erster Stelle)

Dies ist ein König der Hügel Herausforderung, Standard-Schlupflöcher verboten. Ihre Funktion wird mehrere tausend Mal ausgeführt, wobei jedes Mal ein "Verschieben" zulässig ist. Beachten Sie, dass bei mehr als 20.000 Zügen der Bot mit den meisten Münzen gewinnt. Dies wird 8000-mal durchgeführt, um die Zufälligkeit zu beseitigen.

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

Preise:

Erster Platz: 100-Punkte-Kopfgeld
Community Favorit: 15-Punkte-akzeptierte Antwort

Gewinner:

Erster Platz: TBTPTGCBCBA
Zweiter Platz: Big King Little Hill
Dritter Platz: Potenziell siegreich
Vierter Platz: Höflicher, kurzsichtiger, betrunkener Bot
Fünfter Platz: Sicherheitsmünze


6
"Beachten Sie, dass alle Einsendungen in Javascript konvertiert werden, um die Sache zu vereinfachen." Wie soll das gehen? Machst du den Umbau?
Laikoni

21
Es ist nichts auszusetzen, wenn ein Koth nur eine Sprache zulässt, insbesondere eine, die so weit verbreitet ist wie JavaScript. Anstatt Antworten mehrdeutig in JavaScript umzuwandeln (vermutlich von Ihnen selbst und von Hand), sollten Sie die Herausforderung einfach auf JS beschränken. Immerhin hatten wir in der Vergangenheit viele Koths nur für Java und Python.
Skidsdev

2
Eine Version, bei der Sie die Beschleunigung anstelle der Position steuern, wäre ziemlich cool.
Akozi

12
An alle: Es gibt schon zu viele Kommentare. Hinterlassen Sie keine nutzlosen Kommentare wie "+1, netter Bot" und löschen Sie Ihre Kommentare, wenn sie überflüssig sind . Wir sind keine typische Q & A-Site, aber niemand liest gerne Hunderte von Befehlen.
User202729

5
(Zu meiner eigenen Frage): Laut NP im Chat ist es das letztere: Alle Bots bewegen sich, dann werden alle Konflikte gelöst, dann treten alle Münzsammlungen auf, dann werden alle neuen Münzen platziert.
BradC

Antworten:


26

BaitBot - JavaScript Node.JS

Warum jagen oder rennen, wenn man nie fangen kann? Stattdessen findet BaitBot die nächste Münze und wartet darauf, dass sich auch ein schwächerer Bot nähert. Wenn beide benachbart sind, geht baitBot für die Münze, vorausgesetzt, der schwächere Bot wird es auch. Wenn baitBot wartet und sich ein stärkerer Bot nähert, schnappt er sich einfach die Münze und die Skedaddles. Probier mich aus!

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, das ist eine nette Idee, ich mag es.
Sundar

Dieser Ansatz ist ziemlich cool ... nein, sehr cool
Redwolf-Programme

1
BaitBot braucht nearestThreat && distanceTo(nearestThreat)mehr als nur distanceTo(nearestThreat). Es schlägt fehl, wenn keine Bedrohung vorliegt.
Redwolf-Programme

1
Ja, nearestThreatist , undefinedwenn alle anderen Bots mehr Punkte als Ihre haben.
Night2

1
Nun, ich bekomme Hinweise wie [10] Bot Bait Bot tired of this world, and jumped off its edgein meinem Ereignisprotokoll
Redwolf Programs

17

Potenziell siegreich JavaScript

Bevorzugte Farbe für diesen Bot ist #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];
}

(Entschuldigung für die schlampige Formatierung, der 4-stellige Einzug für diese Site passt nicht zu meiner Gewohnheit, Tabulatoren zu verwenden.)

Grobe Erklärung

Ich verzichte hiermit auf den Versuch, die Erklärung der Formeln zu aktualisieren. Die Koeffizienten ändern sich ständig und es ist schwierig, die Erklärung auf dem neuesten Stand zu halten. Also werde ich nur das allgemeine Prinzip erklären.

Jede Münze und jeder Bot erzeugt ein Kraftfeld mit einem gewissen Potenzial. Ich addiere einfach die Potenziale von allem zusammen und der Bot geht dann dorthin, wo das Potenzial am niedrigsten ist. (Offensichtlich ist diese Idee aus der Physik gestohlen.)

Ich benutze zwei Arten von Potentialen. Das erste ist ein Pseudogravitationssystem (das in einem beliebigen Bereich wirkt) mit Das k ist eine "Stärke" des Feldes, und bei dieser Wahl des Zeichens ist das Potential attraktiv. Das r hier (und überall sonst) ist der Abstand in der Taximetrik, r = | x₁ - x₂ | + | y₁ - y₂ | .

U=kr+1511+n.

Ich benutze k = 40 für Goldmünzen und k = 10 für Silbermünzen. n ist die Anzahl der Bots, die näher an der jeweiligen Münze sind als wir. Ansonsten ignorieren wir die anderen Bots absolut (wenn wir einem stärkeren Bot im Weg stehen, rennen wir weg, aber das war's). Ich schätze Goldmünzen für mehr als sie wert sind, weil mich sonst die Bots schlagen, die hauptsächlich nach dem Gold streben.

Das zweite Potential ist ein exponentiell abfallendes Potential (das effektiv nur in sehr kleinen Abständen wirkt). Dies wird von den anderen, hauptsächlich mächtigeren Bots erzeugt.

Diese erzeugen ein Feld mit Diese Kraft ist im Bereich 0-1 unerschwinglich stark, nimmt aber in größeren Entfernungen fast nichts an. (Abstand + 1 bedeutet, dass die Kraft um 1/20 verringert wird.)

U=5×1400e3r.

Wir greifen die anderen Bots im Allgemeinen nicht absichtlich an (natürlich ist es ihre Schuld, wenn sie uns in die Quere kommen und wir darauf treten), aber es besteht die Möglichkeit, dies zu tun. Wenn einige raue Bedingungen erfüllt sind, können wir in den Jagdmodus wechseln und uns auf einen einzelnen Bot konzentrieren. So rufen Sie den Jagdmodus auf:

  1. Wir müssen mindestens 25 Münzen haben. (Wir müssen zuerst einige Münzen bekommen.)
  2. Sie müssen höchstens (unsere Münzen - 5) Münzen und mindestens 10 Münzen haben. (Wir wollen nicht jemanden jagen, der eine Münze schnappt und plötzlich mächtiger ist, und wir wollen auch keine Null-Münzen-Bots verfolgen.)
  3. Wir müssen um mindestens 1/10 seiner Münzen hinter dem derzeit führenden Bot zurückbleiben. (Sie müssen das Glück haben, etwas zu jagen. Es ist also nicht nötig, eine gute Position zu verraten, nur um unser Glück zu versuchen.)
  4. Wir dürfen keine Jagd-Abklingzeit haben (siehe unten).

Wenn all dies erfüllt ist, wird der Jagdmodus aktiviert. In den nächsten 10 Runden gibt der gejagte Bot nur das Potential Nach Ablauf dieser 10 Runden betreten wir die Jagd-Abklingzeit, in der wir möglicherweise nicht mehr in den Jagdmodus wechseln. (Das soll verhindern, dass wir einen Bot endlos und erfolglos verfolgen, während alle anderen glücklich nach Münzen greifen.) Die Jagdabklingzeit beträgt 20 Runden, wenn wir 25 Münzen haben, und erhöht sich um 20 Münzen pro Verdoppelung. (Mit anderen Worten, die Abklingzeit ist .) (Wir verwenden das, weil im Endspiel alle jagbaren Bots höchstwahrscheinlich tot sind und daher jede Jagd höchstwahrscheinlich vergeblich sein wird. Aus diesem Grund möchten wir die verschwendete Zeit begrenzen Aber manchmal kann ein glückliches spätes Spielessen alles ändern, also behalten wir die Möglichkeit.)

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

Schließlich wird die gesamte Arena in eine unendliche Potentialquelle gebracht, die das Entkommen des Bots verhindert.


Ich denke, dieser Bot schlägt wahrscheinlich auch meine gewichtete Bewegung aus.
8.

@ fəˈnəˈtɪk - Ich auch :—). Ich denke, dass dieser mit den anderen Bots viel besser umgehen kann. (Es wird auch nicht durch eine Münze auf einem angrenzenden Feld "geblendet".) Aber ich habe dir auf jeden Fall +1 gegeben, weil ich ein großer Fan dieser Idee bin.
Ramillies

Könnten Sie das Prinzip der geringsten Wirkung auf dieses anwenden?
Beta Decay

@BetaDecay: Ich fürchte nicht ganz, Kalkül reagiert nicht gut auf diskrete Probleme wie dieses. Sogar im kontinuierlichen Fall wäre es nicht trivial (wegen der festen Größe der Geschwindigkeit), aber es könnte nach einigen Polarkoordinaten machbar sein, denke ich.
Ramillies

4
Das ist cool. Ich bin mir nicht sicher, ob das Risiko in einem monotonen Verhältnis zur Entfernung steht. Es scheint, als würde Sie eine Bedrohung in 2 Feldern Entfernung eher töten als eine benachbarte, da in letzterem Fall einer von Ihnen stationär bleiben muss, damit eine Kollision stattfinden kann.
Cain

16

Lernalgorithmus der ersten Generation | JavaScript (Node.js)

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

Probieren Sie es online!

Haben Sie jemals die Zeitraffer von Lernalgorithmen gesehen, die das Spielen lernen? Sie bewegen sich in den ersten Generationen oft fast zufällig ...


LOL ... Es könnte immer noch funktionieren!
Redwolf-Programme

2
Die meisten Lernalgorithmen arbeiten in den ersten paar Iterationen buchstäblich zufällig, nicht nur fast zufällig.
8.

Erraten Sie, was? Dieser Bot hat im Durchschnitt fast 0,22 Münzen pro Runde!
Redwolf-Programme

16

Big King Little Hill | JavaScript

function BigKingLittleHill(me, enemies, coins) {

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

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

Probieren Sie es online!

Big King Little Hill trifft Entscheidungen auf der Grundlage von „Kontrollzonen“. Es werden nur Münzen verfolgt, die sich in seiner Kontrollzone befinden, was bedeutet, dass es die Münze erreichen kann, bevor es ein anderer Bot kann. Befinden sich keine Münzen in der Kontrollzone, wird stattdessen die Größe der Kontrollzone maximiert. Big King Little Hill berechnet die Kontrollzone für jede seiner 5 möglichen Bewegungen und bevorzugt die Bewegungen, die die Größe seiner Kontrollzone maximieren. Auf diese Weise erreicht Big King Little Hill schließlich ein lokales Kontrollmaximum (Little Hill) und wartet darauf, dass in seiner Zone eine Münze generiert wird. Außerdem lehnt Big King Little Hill jede Aktion ab, die zum Tod führen könnte, sofern es keine Alternativen gibt.

Big King Little Hill ist ein Pessimist (er bevorzugt den Begriff Realist), weil er sich nicht die Mühe macht, eine Münze anzufechten, deren Erhalt nicht garantiert ist. Es ist auch ein Pazifist, da es in keiner Weise schwächere Bots verfolgt (obwohl es auf einen treten könnte, wenn sie in die Quere kommen). Schließlich ist Big King Little Hill ein Feigling, der sein eigenes Leben nicht für Belohnungen aufs Spiel setzt, es sei denn, er muss es unbedingt.


1
Willkommen bei PPCG! Das ist ein sehr guter Bot = D
Luis Felipe De Jesus Munoz

Dies ist, was ich für einen Bot gedacht habe. Gut gemacht.
Jo.

10

Sicherheitsmünze | 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";}
  }
}

Dieser Bot geht direkt auf eine gewichtete Wertmünze (Wert / Entfernung) zu, an deren Erreichen er nicht gleichzeitig oder nach einem anderen Bot sterben kann. Wenn es keine gültige Münze mit dieser Eigenschaft gibt, befindet sie sich dort, wo sich der Bot jetzt in eine zufällige sichere Richtung bewegt (Sicherheit bedeutet, dass eine Sicherheitsmünze nicht kollidieren kann, wenn sich ein Bot darauf zubewegt. Auf diese Weise kann der Bot die Plätze mit einem anderen Bot tauschen, wenn direkt daneben), gewichtet zur Arena-Mitte.


1
Huh, das kann tatsächlich gewinnen. Obwohl es viele Bots gibt
Redwolf-Programme

Diese Methode wird mehr Probleme haben, je ungleichmäßiger die feindlichen Bots mit höherem oder gleichem Wert platziert werden.
8.

1
Nun, sie werden wahrscheinlich alle eine Linie zu der Münze machen, die ihnen am nächsten ist / Goldmünze.
Redwolf-Programme

Es wird nur gut gehen, wenn es gelingt, gleich zu Beginn ein paar Münzen zu bekommen.
Freitag,

Und das ist größtenteils Glück, da der Ort, an dem Münzen generiert werden, zufällig bestimmt wird
Redwolf Programs

10

Der Bot, der das Spiel vorsichtig spielt, aber aggressiv sein kann | JavaScript

Bevorzugte Farbe: #F24100

Hinweis: Obwohl dieser Bot den 1. Platz belegt hat, hat er sich am Ende mit "Feudal Noble" zusammengetan und frisst ihn nach mehr Münzen. Andernfalls wäre dieser Bot Dritter geworden. Wenn Sie an individuell leistungsstärkeren Bots interessiert sind, schauen Sie sich Potenziell siegreich und Big King Little Hill an .

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

Dieser Bot (auch "TBTPTGCBCBA" genannt) versucht die bestmögliche Entscheidung zu treffen, indem er für jeden möglichen Zug eine Punktzahl generiert und den Zug mit der höheren Punktzahl für jeden Zug auswählt.

Das Punktesystem enthält viele Details, die seit Beginn der Herausforderung entwickelt wurden. Sie können allgemein so beschrieben werden:

  • Je näher die Münzen an einem möglichen Zug sind, desto mehr Punkte erhält dieser Zug. Wenn eine Münze keine anderen möglichen Teilnehmer hat, ist die Punktzahl noch höher. Wenn eine Münze andere mögliche Teilnehmer hat, sinkt die Punktzahl.
  • Befindet sich ein anderer Bot in der Nähe eines möglichen Zuges und hat er je nach Spielphase weniger Münzen, könnte dies bedeuten, dass dieser Zug mehr Punkte bringt. Daher ist es für "TBTPTGCBCBA" eine Gelegenheit, in jedem Spiel ein paar andere Bots zu essen.
  • Befindet sich ein anderer Bot in der Nähe eines möglichen Zuges mit gleichen oder mehr Punkten, erhält dieser Zug genügend negative Punkte, um sicherzustellen, dass der Tod vermieden wird. Natürlich kann es vorkommen, dass alle möglichen Züge schlecht sind und der Tod nicht vermieden werden kann, aber das ist sehr selten.
  • Es gibt einen Mechanismus, mit dem die Anzahl der Bots in den letzten 20 Runden in der Mitte des Bretts verfolgt werden kann. Wenn der Durchschnitt niedrig genug ist, erhalten alle Bewegungen zu Münzen in der Mitte mehr Punkte, und wenn der Durchschnitt hoch ist, erhalten alle Bewegungen zu Münzen in der Mitte weniger Punkte. Dieser Mechanismus ermöglicht es, Konflikte mit "Feudal Noble" zu vermeiden. Da sich "Feudal Noble" immer in der Mitte befindet (es sei denn, es wird gejagt), steigt die durchschnittliche Anzahl der Bots in der Mitte und "TBTPTGCBCBA" vermeidet die mittlere, wenn es eine bessere Option außerhalb des mittleren Bereichs gibt. Wenn "Feudal Noble" stirbt, sinkt der Durchschnitt und "TBTPTGCBCBA" versteht, dass es die Mitte verwenden kann.
  • Es gibt einige Faktoren, die sich je nach Spielphase dynamisch ändern (anhand der Anzahl der aktiven Bots). Diese Faktoren wirken sich auf die Wertung der oben genannten Punkte aus.
  • Dieser Bot hat eine besondere Fähigkeit. Mit der Zeit wird es der Selbstsucht von "Feudal Noble" und der Unterdrückung der Bauern müde. Im richtigen Moment wird es dazu kommen, das unangenehme Feudalismus-System zu beenden. Ein erfolgreicher Versuch hilft nicht nur armen Bauern, sondern bietet auch eine höhere Gewinnchance durch die vom "Feudaladel" entnommenen Münzen.

Es scheint viel intelligenter als die anderen
Redwolf-Programme

5
Ich mag die Monster Teil der params
Redwolf-Programme

9

Der Antikapitalist | Javascript

Hat keinen Anreiz, nach Münzen zu suchen, sondern versucht, sich genau zwischen die beiden reichsten Bots mit dem gleichen Geldbetrag zu setzen, in der Hoffnung, dass sie ihn jagen und schließlich zur gleichen Zeit fangen und zwei Kapitalisten mitnehmen, wenn er stirbt . Widersetzt sich nicht aktiv dem Erhalten von Münzen, sodass er möglicherweise ein saftigeres Ziel wird.

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

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

Mit Potenziell siegreich haben wir zwei Felder: das Bot-Feld und das Münzfeld. Die Natur ist jedoch nicht so kompliziert. Es ist Zeit, die beiden Felder zu vereinen, um die Grand Unified Theory zu erstellen .

Zunächst müssen wir herausfinden, welches Potenzial das Gebiet hat. Vorausgesetzt, unser eigener Bot beeinflusst das Feld in keiner Weise, können wir dies wie folgt schreiben:

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

kn(xn,yn)

Die relative Eigenschaft des Objekts wird folgendermaßen berechnet:

k=cobjectcme

ccme=cself+1cself

Nennen wir diesen Korrekturteil einfach Modified Betanian Dynamics (MOBD) .

Wir können die kinetische Energie auch finden als:

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

Wir können jetzt die Aktion berechnen:

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

Und so ist der Lagrange unseres Bots auf dem Gebiet der Münzbots:

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

Wir müssen nun die Euler-Lagrange-Gleichungen lösen:

ddtLx˙=Lx

und:

ddtLy˙=Ly

Damit:

ddtLx˙=ddt[cmex˙]=cmex¨

Lx=n200kn(xxn)ekn2100(xxn)2

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

Und auch:

ddtLy˙=ddt[cmey˙]=cmey¨

Ly=n200kn(yyn)ekn2100(yyn)2

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

Jetzt brauchen wir nicht weiter zu gehen: Wir schauen uns nur die Richtung der Gesamtbeschleunigung an:

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

Und einfach so haben wir die Münzen und die Bots vereinheitlicht. Wo ist mein Nobelpreis?


5
Ihr Nobelpreis ging in der Post verloren, aber wir könnten Ihnen stattdessen einen Emmy Award geben
Redwolf Programs

1
Es sieht so aus, als würde die Physik bei dieser Herausforderung immer beliebter. : - D. Und natürlich bin ich sehr gespannt, wie gut es funktionieren wird.
Ramillies

1
(Übrigens hätten Sie den Aufwand mit Euler-Lagrange-Gleichungen sparen können, weil sie sich auf die bekannte Tatsache reduzieren, dass F = c_me a = - grad U: -).)
Ramillies

@ Ramillies Meh, es hat mehr Spaß gemacht, es so zu machen: D
Beta Decay

1
Sind Sie sicher, dass Sie die k = Münzen von etwas anderem / Ihren Münzen verwenden möchten? Sie fangen ohne Münzen an ... und mit NaN bekommen Sie wahrscheinlich keine.
Ramillies

8

Goldlöckchen, 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
}

Probieren Sie es online!

Lässt sich einfach auf die Position der Goldmünze fixieren und bewegt sich jedes Mal darauf zu. (Dank @ Mayubes 'B33-L1N3'-Bot für den verwendeten Originalcode, von dem jedoch kaum noch etwas übrig ist.)


Dies ist ein ziemlich netter, einfacher Bot. Ich mag das.
Redwolf-Programme

2
Übrigens benutze ich diesen Bot als Test für meinen Controller (:
Redwolf Programs

8

Lernalgorithmus der dritten Generation | 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)];
}

Probieren Sie es online!

Nach ein paar Generationen des Lernens hat dieser Bot gelernt, dass das Verlassen der Arena = schlecht ist


Oh gut. Ich habe gehört, dass dies "Natürliche Selektion" heißt
Redwolf Programs

5
Wo ist das zweite Gen
Luis Felipe De Jesus Munoz

11
@ LuisfelipeDejesusMunoz Er verließ die Arena.
Jo.

Dies ist ein guter Bot zum Debuggen des Controllers
Redwolf Programs

3
Oh, die Arena beginnt übrigens bei 0, also sollte es sein arenaLength - 1. Dies brachte Ihren Bot ein paar Mal um
Redwolf Programs

7

B33-L1N3 | JavaScript (Node.js)

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

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

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

Probieren Sie es online!

Stellt eine Linie für die nächste Münze her


Oh, ich dachte, B33-L1N3 wäre eine Art Modellnummer
Redwolf Programs

+1 für den Namen
Cain

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

Löschen Sie dielet
Redwolf-Programme

5

Leben am Rande, 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';
  }
}

Dieser hörte, der Rand der Arena sei ein gefährlicher Ort. Da er keine Angst kennt, kreist er unermüdlich im Uhrzeigersinn, nur wenige Zentimeter von dem sicheren Tod entfernt, der hinter der Grenze auf ihn wartet, und hofft, dass kein anderer Bot es wagt, sich so nah an die Kante zu bewegen.


1
Dies würde nicht gut enden, wenn ein anderer Bot erstellt würde, der 1 weitere Münze hat und die Grenze in die entgegengesetzte Richtung patrouilliert (:
Redwolf Programs

8
Ich würde einen Witz über Grenzkontrollen machen, aber ich überlasse diesen @BetaDecay
Redwolf Programs

5

Damacy, JavaScript (Node.js)

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

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

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

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

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

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

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

  if (!done)
    dir = 'none'


  return dir
}

Probieren Sie es online!

Ein letzter Katamari-basierter Bot für heute, diesmal mit ein bisschen Gedächtnis. Danke an @BetaDecay für den Namensvorschlag - definitiv ein lustigerer Name als mein simplePredictorKatamari.

Versucht herauszufinden, wie sich Bots in der letzten Runde bewegt haben, und prognostiziert basierend darauf, wo sie am Ende dieser Runde versuchen werden, sich zu bewegen (vorausgesetzt, sie bewegen sich weiterhin in dieselbe Richtung).

(Vielen Dank an @ fəˈnəˈtɛk, dass ich in botNotes den falschen Funktionsnamen aufgerufen habe, und an @ OMᗺ, dass ich einen Fehler im Basiscode bemerkt habe.)


Dies ist wahrscheinlich der einzige, der im Moment andere erwischen kann, ohne nur Glück zu haben.
Cain

Sollen Botnotes nicht "gespeicherte Daten" sein, nicht gesetzte Daten?
9.

@ fəˈnəˈtɛk See, braucht schon einen Bugfix! :) Danke, jetzt korrigiert.
Sonntag,

Sie sollten aWt = 1in den params mit ersetzen aWtund aWt = aWt || 1darunter setzen (selbe mit bWt). Dies verhindert Fehler.
Redwolf-Programme

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

Alle Münzen (einschließlich der von anderen Bots gehaltenen) stoßen Protonbot ab. Basierend auf dieser Kraft baut es Geschwindigkeit auf und prallt von Wänden ab (dreht sich sofort um, wenn es auf eine Grenze trifft). Wenn es neben einem Bot oder einer Münze landet, die es konsumieren kann, übernimmt die starke Kernkraft und es bewegt sich, um sie zu konsumieren, wobei es die gesamte Geschwindigkeit verliert, wenn es dies tut.


Hmm, Nuklearphysik für die Schatzsuche? Das schlägt Science Channel jeden Tag!
Redwolf-Programme

Sie müssen sinmit Math.sin, cosmit Math.cosund so weiter ersetzen
Redwolf-Programme

4

Nicht so blind JavaScript (Node.js)

Wichtiger Hinweis: Dieser Ansatz gehört nicht ganz mir und wurde in einer ähnlichen Frage beantwortet . Stellen Sie sicher, dass Sie auch für diese Antwort stimmen.

Haben Sie jemals von einem A * -Pfadfindungsalgorithmus gehört? hier ist es. Es schafft den besten Weg von einem Punkt zur weniger wertvollen Münze (da jeder den höchsten Wert anstrebt, niemand den niedrigsten) und versucht, nicht mit einem anderen Benutzer zusammenzustoßen.

Erwartet folgende Parameter:

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

Vielleicht mache ich einen, der andere Bots jagt


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 ... ein Wegfindungsalgorithmus schon? Es ist nur 3 Stunden gewesen!
Redwolf-Programme

@ RedwolfPrograms Wie gesagt, es wird von einer anderen ähnlichen Herausforderung kopiert. Musste es nur an dieses anpassen.
Luis Felipe De Jesus Munoz

Meine Algorithmen richten sich nach den sichersten Münzen.
8.

4

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

Vermeiden Sie Bots mit mehr Geld, wenn dies möglich ist. Ansonsten schnapp dir Geld, das herumliegt.


Dies ist der einfachste Bot, der eine Gewinnchance hat
Redwolf Programs

4

Wild Goose Chase Bot, Javascript

Ein Bot, der wirklich gut darin ist, anderen Bots auszuweichen, aber sehr schlecht darin, Münzen zu bekommen.


Algorithmus:

  1. Wenn keine benachbarten Bots vorhanden sind, geben Sie keine zurück
  2. Andernfalls:
    1. Gib keine mit einer zufälligen Chance von 1/500 zurück (dies soll Patt verhindern).
    2. Bestimmen Sie, zu welchen Feldern Sie sich sicher bewegen können (dh innerhalb der Arena und nicht von einem anderen Bot besetzt)
    3. Gib eine nach dem Zufallsprinzip zurück

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

Probieren Sie es online!

Hinweis für Redwolf-Programme:

Dieser Bot kann sehr lange Runden verursachen. Ich habe mir einige Freiheiten genommen, um Pattsituationen vorzubeugen, aber nicht getestet, ob sie tatsächlich wirksam sind. Wenn dieser Bot während des Testens zu einem Problem wird, können Sie ihn jederzeit disqualifizieren.


Danke für den Hinweis. Ein Experte hat eine gute Chance, wenn er genug Münzen einsammelt, während er verfolgt wird
Redwolf Programs

Ich mag das. Es ist fast wie ein Köder für die Jagdroboter
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
}

Probieren Sie es online!

(Vielen Dank an @ OMᗺ für den Hinweis auf einen Fehler im Originalcode, auf dem dieser basiert.)

Versucht zu wachsen, indem er Bots mit weniger Münzen als sich selbst "isst". Wenn dies nicht möglich ist (es gibt keinen solchen Bot), wird die nächstgelegene Münze gesucht.

Diese Version hat kleine Optimierungen, um (a) Goldmünzen eine höhere Priorität einzuräumen als Silbermünzen - mit dem Risiko, dass die Suche nach einer weiter entfernten Goldmünze das Leben des Bots kostet oder dazu führt, dass er dem Narren nachjagt, mit dem er Gold überspringt. (B) Bots überspringen 0 Münzen - Verschwenden Sie keine Zeit damit, diesen nachzujagen.


Ein kluger Jäger ... nun, das ist noch besser!
Redwolf-Programme

@RedwolfPrograms Hoffen wir es! :)
Sundar

Hätte das Damacy nennen sollen;)
Beta Decay

1
@BetaDecay Wunsch
Sundar

4

Höflicher kurzsichtiger betrunkener Bot | JavaScript

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

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

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

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

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

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

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

Stolpert herum und sammelt Münzen in der Nähe auf, wechselt aber von Zeit zu Zeit die Richtung. Tut, was er kann, um nicht auf jemanden zu stoßen, aber er wird ... kriegerisch ..., wenn er sich verschlimmert. Neigt dazu, im Verlauf des Wettbewerbs zu nüchtern.

Möglicherweise muss ein wenig debuggt werden, wenn der Controller vollständig fertig ist, werde ich daran arbeiten.


3
Hmm, es
legt

4

Gewichtete Bewegung | 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";
}

Bewegt sich in die Richtung, in der es den höchsten Wert zugewiesen hat, ohne über die Kante der Platine zu rennen.

Wert wird als solcher berechnet:

  • Münze = Kraft der Münze / Abstand zur Münze
  • Bot = Unterschied in der Kraft der Bots / 2 * Abstand zum Bot

1
Nun, das sieht aus wie ein ziemlich toller Bot. Achten Sie darauf , die Anweisungen zu überprüfen, da es ein echter Verlust wäre , wenn Ihr Bot ein Meister am Laufen war weg von Münzen (:
Redwolf Programme

Na ja, immer noch. Ich muss nett sein, oder?
Redwolf-Programme

Nun, poste es! Dies gleicht die kleineren, schnelleren Bots aus, die derzeit auch in großen Mengen vorhanden sind.
Redwolf-Programme

for(i=0;i<6;i++){Insgesamt gibt es nur 5 Münzen, 1 Gold und 4 Silber. Deine Runde läuft 6 mal von 0 bis 5.
Night2

3

Blindy | JavaScript (Node.js)

Dies wird definitiv nicht gewinnen, aber zumindest teilnehmen. Versuchen Sie es zuerst bei der KoH-Herausforderung. Es sortiert die Münzen und geht zum nächsten. Er sucht nicht nach Spielern, deshalb ist es ihm egal, ob er mit anderen zusammenstößt.

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

    if(coins.length == 0)
        return n

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

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

Hmm, es könnte funktionieren, da andere Bots in erster Linie das Gold suchen und Sie möglicherweise kampflos das Silber holen müssen
Redwolf Programs

3

Feudaladel | JavaScript

Bevorzugte Farbe: #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;
}

Dieser feudale Adel bleibt im Zentrum des Feldes und beansprucht es als seinen eigenen Palast. Sammelt alles in der Mitte für sich selbst, aber alles in Farmen weit weg sollte von Bauern zu ihm gebracht werden. Natürlich, wenn ein wütender mächtiger Bauer im Palast auftaucht, könnte der Adlige davonlaufen, um sein Leben zu retten, aber er kommt zurück, sobald es sicher ist!

Mit der Zeit werden die Bauern immer stärker. Professionelle Kämpfer und mächtige Helden erheben sich aus der Bauernschaft. Die Macht des Adligen schwindet immer weiter. Er versucht, seinen Reichtum und sein Feudalismus-System so lange wie möglich zusammenzuhalten. Aber endlich kommt eine Zeit, in der er seinen Glauben akzeptieren sollte, er sollte akzeptieren, dass die Menschen keinen Feudalismus mehr wollen. Das ist der Tag, an dem der feudale Adel alles aufgibt, nicht mehr vor mächtigen Bauern davonläuft und von einem von ihnen getötet wird.


2

Quantenmückenbot | 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
}

Dieser ärgerliche Bot versucht, den stärksten Bot zu umrunden, ohne dass er angeschlagen wird, und es besteht eine geringe Chance, dass er diejenigen durchläuft, die versuchen, ihn zu jagen. Es hat die Tendenz, die beiden mächtigsten Bots in die Nähe zu ziehen ...;)


Wenn er kein passendes Ziel findet getTargetDirections(), passieren interessante Dinge. (Wie zum Beispiel alles wegen eines undefined has no property 0Fehlers zu brechen .)
Ramillies

2

Pensionierter ICE-Agent, JavaScript

Bevorzugte Farbe: 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";
            }
        }
    }
}

Der inzwischen pensionierte ICE-Agent steht der Menschheit bitter gegenüber. Infolgedessen zielt Retired ICE jetzt auf den schwächsten Bot ab, während sein Münzwert über dem Durchschnitt liegt (gemäß der ICE-Richtlinie).


2

Gierige Verfolgung | Haskell

Bevorzugte Farbe: #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"

Probieren Sie es online! *

Ziemlich einfache Strategie, trifft die erste Entscheidung aus:

  • Wenn es Bots mit weniger Münzen gibt: Wähle die nächstgelegene und bewege dich darauf zu
  • Wenn es Münzen gibt: Wähle die nächstgelegene und bewege dich darauf zu
  • Standard: bleiben

Der Bot versucht nur, andere Bots oder Münzen zu fangen, ohne sich um potenziell stärkere Bots zu kümmern, die versuchen könnten, sie zu fangen.

* Ich kenne JavaScript nicht wirklich, aber ich habe es mit Google gemacht (möglicherweise ungenau): Probieren Sie es online aus!


6
Ich frage mich, wie er haskell in js übersetzen wird
Luis felipe De jesus Munoz

3
@ LuisfelipeDejesusMunoz: Ja ich auch. Aber zum Glück ist es kein sehr ausgefeilter Code.
8.

@LuisfelipeDejesusMunoz Verwenden Sie einfach Node.JS und process.open(oder child_process.spawnoder ähnliches) mit etwas Analyse.
user202729

@LuisfelipeDejesusMunoz: Ich habe versucht, es zu übersetzen und habe einen Link hinzugefügt, aber ich bin nicht sehr zuversichtlich, JavaScript zu schreiben, daher ist es möglicherweise fehlerhaft.
8.

4
@LuisfelipeDejesusMunoz Es wäre eine Sache, wenn dies ein 10.000-Zeilen-KI-Lernprogramm wäre, aber ich denke, ich kann das schaffen (:
Redwolf-Programme

1

Münzen-Magnet | 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";
}

Dieser Bot ist ziemlich dumm, er steuert in Richtung der am besten zu erwerbenden Münzen. Dies schließt Münzen ein, die es nicht bekommen kann, weil andere Bots eine höhere Macht als er selbst haben.


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

Was nützt eine Grenze, wenn sie nicht überwacht wird? ICE bewegt sich gegen den Uhrzeigersinn um die Grenze und nimmt alle Bots auf, die sich auf seinem Weg befinden.

Bevor es das kann, muss es in der Lage sein, andere Bots zu fressen. Aus diesem Grund hält ICE seine Münzen über dem Durchschnitt aller Bots.

Stiehlt garantiert Kindern ihre Eltern ™


Das wäre witziger, wenn es nicht so relevant wäre
Don Thousand

1

X markiert die Stelle | 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 markiert den Punkt, also muss alles Gold auf der x-Achse liegen, richtig? Mein Bot macht eine Linie für die y = 0 Linie und bleibt dann dort und bewegt sich zufällig.


Huh, eine interessante Methode in der Tat
Redwolf Programs


1
Sind The arena starts at (0,0) in the upper left cornerSie sicher, dass Sie umziehen möchten, um southzu gelangen y=0?
AdmBorkBork

@AdmBorkBork Danke, das hätte schlimm sein können
Beta Decay

1

Feuervogel

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

Komplett überarbeitet, um tödlicher zu sein als zuvor (:


2
Mein absoluter Verlierer eines Bots
Redwolf Programs

Es zielt nicht auf sie ab, sondern vermeidet sie
Redwolf-Programme

Oh sorry, ich habe falsch verstanden
Beta Decay

1

A-Pfad-y | JavaScript

Bevorzugte Farbe für diesen Bot ist #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);
}

Dieser Bot verwendet die Wegfindung in Verbindung mit einer Karte der Zellwünsche, um Bots zu vermeiden, die uns töten könnten.

Es scheint kein Anwärter auf den Siegerplatz zu sein, aber es behauptet sich und wird am Ende des Spiels am Leben sein, wenn es den anfänglichen Nahkampf überlebt.

Bot hat jetzt eine Mid-to-Late-Spielstrategie, die Münzen ignoriert, die er nicht vor anderen Bots erreichen kann. Wenn er keine Münze erhalten kann, bewegt er sich zur nächsten Zelle, die am weitesten von allen anderen Bots entfernt ist, die stärker als er selbst sind.

Es hat jetzt eine Gewinnchance.

Hinweis: Entschuldigung für den beschissenen Code, ich habe ihn automatisch von Java konvertiert


Stellen Sie sicher, dass alle Bugs und / oder Updates bald, 18 Stunden vor Fälligkeit, aus dem Weg geräumt werden!
Redwolf-Programme

@RedwolfPrograms Hast du einen Fehler beobachtet? Wenn ja, lassen Sie es mich bitte wissen, damit ich korrigieren kann. Vielen Dank
Moogie

Nein, aber du weißt es nie. Stellen Sie sicher, dass Sie dies noch einmal überprüfen, da ich gesehen habe, dass viele Bots aufgrund einer falschen Nummer oder Funktion verloren haben oder öfter falsch getippt wurden, als ich zählen kann
Redwolf-Programme
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.