Kolektor Emas KoTH


48

Catatan: Survei untuk favorit komunitas akan segera dirilis

Dalam KoTH ini, tujuannya adalah untuk menjadi bot terakhir yang masih hidup. Koin akan ditempatkan di area acak, dan bot Anda harus mendapatkan koin terlebih dahulu. Jika bot berlari ke bot lain, bot dengan lebih banyak koin menang, dan bot lainnya mati. Lebih detail di bawah ini.

Jenis koin

Akan ada 2 jenis koin: emas dan perak. Emas menambah 5 koin ke kekuatan bot, dan perak menambahkan 2. Setelah koin dikumpulkan, koin lain ditempatkan di tempat lain di papan tulis. Pada waktu tertentu, ada satu koin emas dan empat koin perak di arena.

Tabrakan bot

Dalam hal dua bot mencoba untuk menempati ruang yang sama, yang satu lebih banyak koin akan tetap, dan yang lebih sedikit akan ... tidak. Bot yang menang akan mendapatkan 85% dari koin lawan (Dibulatkan ke Atas). Jika mereka diikat, keduanya mati. Jika tiga atau lebih mencoba untuk menempati ruang yang sama, yang paling kuat menang, dan mendapat 85% dari semua koin bot lainnya. Jika bot yang paling kuat adalah seri, semua bot mati yang mencoba memasuki ruang angkasa.

Arena

Panjang sisi arena dihitung dengan 4 + botCount. Saat menempatkan bot di awal permainan, tempat acak dipilih. Sistem memastikan bahwa tidak ada bot yang dimulai di ruang yang sama, atau bersebelahan. Koin dihasilkan secara acak, tidak termasuk 3 x 3 persegi yang berpusat pada setiap bot. Jika bot ditemukan di luar arena, ia mati seketika. Arena dimulai pada (0,0), atau Northwest, di sudut kiri atas, dan lokasi bot selalu berupa bilangan bulat.

Bot Anda

Bot Anda harus berupa fungsi, dalam bahasa berorientasi objek apa pun yang memiliki larik, bilangan bulat, string, dan fungsi. Perhatikan bahwa semua pengiriman akan dikonversi ke Javascript, untuk mempermudah. Untuk menyimpan informasi antar gerakan, gunakan botNotes.storeData(key, value)dan botNotes.getData(key, value). Anda tidak boleh menyimpan atau mengakses data dengan cara apa pun, selain dari yang disediakan melalui parameter dan botNotes. Anda harus membuat sebuah fungsi yang, saat dipanggil, mengembalikan string north, east, south, west, atau none. Akan ada 3 argumen untuk fungsi:

  • Sebuah objek dengan empat bilangan bulat ( locationX, locationY, coins, arenaLength), lokasi Anda saat ini, koin, dan panjang arena

  • Array multidimensi dengan koordinat X dan Y dari bot lain, dan jumlah koinnya, misalnya[[0,5,4],[4,7,1],[7,4,12]]

  • Array dengan lokasi koin terdaftar (Emas selalu menjadi yang pertama)

Ini adalah tantangan raja bukit, Standar Lubang dilarang. Fungsi Anda akan dijalankan beberapa ribu kali, setiap kali diperbolehkan satu "Pindah". Perhatikan bahwa jika permainan melebihi 20.000 gerakan , bot dengan koin terbanyak menang. Ini akan dilakukan 8.000 kali, untuk menghilangkan keacakan.

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

Hadiah:

Tempat Pertama: hadiah 100 poin
Favorit Komunitas: jawaban diterima 15 poin

Pemenang:

Tempat Pertama: TBTPTGCBCBA
Tempat Kedua: Big King Little Hill
Tempat Ketiga: Berpotensi Menang
Keempat Tempat: Bot Mabes Polite Near-Sighted
Fifth Place: Safety Coin


6
"Perhatikan bahwa semua pengiriman akan dikonversi ke Javascript, untuk mempermudah." Bagaimana cara kerjanya? Apakah Anda melakukan konversi?
Laikoni

21
Tidak ada yang salah dengan koth yang hanya mengizinkan satu bahasa, terutama bahasa yang tersebar luas seperti JavaScript. Daripada secara ambigu "mengonversi" jawaban ke JavaScript (mungkin Anda dan tangan), Anda hanya perlu membatasi tantangan hanya untuk JS. Kami telah memiliki banyak koth hanya Java dan hanya Python di masa lalu.
Skidsdev

2
Versi ini di mana Anda mengontrol akselerasi alih-alih posisi akan sangat keren.
akozi

12
Untuk semua orang: Sudah terlalu banyak komentar. Jangan tinggalkan komentar yang tidak berguna seperti "+1, bot bagus" , dan harap hapus komentar Anda jika berlebihan . Kami bukan situs tanya jawab yang umum, tetapi tidak ada yang suka membaca ratusan perintah.
user202729

5
(Untuk pertanyaan saya sendiri): Menurut NP dalam obrolan, ini adalah yang terakhir: semua bot bergerak, lalu semua konflik diselesaikan, maka semua pickup koin terjadi, lalu semua koin baru ditempatkan.
BradC

Jawaban:


26

BaitBot - JavaScript Node.JS

Mengapa repot-repot mengejar atau berlari jika Anda tidak pernah bisa menangkap? Sebaliknya, BaitBot menemukan koin terdekat dan menunggu bot yang lebih lemah juga mendekatinya. Ketika keduanya berdekatan, baitBot berlaku untuk koin dengan asumsi bot yang lebih lemah juga. Jika baitBot sedang menunggu dan bot yang lebih kuat mendekat, ia hanya mengambil koin dan melaju cepat. Coba saya!

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, itu ide yang rapi, saya menyukainya.
sundar

Pendekatan ini sangat keren ... tidak, sangat keren
Program Redwolf

1
BaitBot membutuhkan, nearestThreat && distanceTo(nearestThreat)bukan hanya distanceTo(nearestThreat). Gagal ketika tidak ada ancaman.
Program Redwolf

1
Ya, nearestThreatadalah undefinedjika semua bot lain memiliki poin lebih banyak dari Anda.
Night2

1
Yah, saya mendapat pemberitahuan seperti [10] Bot Bait Bot tired of this world, and jumped off its edgedi log acara saya
Program Redwolf

17

Berpotensi Menang | JavaScript

Warna yang disukai untuk bot ini adalah #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];
}

(Permintaan maaf untuk pemformatan yang ceroboh, lekukan 4 spasi untuk situs ini tidak sesuai dengan kebiasaan saya menggunakan tab.)

Penjelasan kasar

Saya dengan ini mengundurkan diri dalam upaya untuk memperbarui penjelasan formula. Koefisien terus berubah dan agak sulit untuk menjaga penjelasannya tetap terbaru. Jadi saya hanya akan menjelaskan prinsip umum.

Setiap koin dan setiap bot menghasilkan medan gaya dengan beberapa potensi. Saya hanya menambahkan potensi dari semuanya bersama-sama dan bot kemudian pergi ke mana pun potensinya paling rendah. (Jelas gagasan ini dicuri dari fisika.)

Saya menggunakan dua jenis potensi. Yang pertama adalah gravitasi pseudo-gravitasi (yang bekerja pada kisaran apa pun), dengan The k adalah "kekuatan" dari lapangan, dan, dengan pilihan ini tanda, potensi menarik. The r sini (dan di tempat lain) adalah jarak di taksi metrik, r = | x₁ - x₂ | + | y₁ - y₂ | .

U=kr+1511+n.

Saya menggunakan k = 40 untuk koin emas dan k = 10 untuk koin perak. n adalah jumlah bot yang lebih dekat ke koin tertentu daripada kita. Kalau tidak, kita benar-benar mengabaikan bot lain (jika kita menghalangi bot yang lebih kuat, kita melarikan diri, tapi hanya itu). Saya menghargai koin emas lebih dari nilainya karena jika tidak, bot yang terutama mengejar emas selalu mengalahkan saya.

Potensi kedua adalah yang secara eksponensial membusuk (yang secara efektif hanya bertindak pada jarak yang sangat kecil). Ini dihasilkan oleh yang lain, terutama bot yang lebih kuat.

Ini menghasilkan bidang dengan Kekuatan ini sangat kuat pada kisaran 0-1, tetapi meluruh hampir tidak ada pada jarak yang lebih besar. (Jarak + 1 berarti memotong gaya dalam 1/20.)

U=5×1400e3r.

Kami umumnya tidak menyerang bot lain dengan sengaja (tentu saja jika mereka menghalangi kami dan kami menginjaknya, itu adalah kesalahan mereka), tetapi ada kemungkinan untuk melakukan itu. Jika beberapa kondisi keras terpenuhi, kita dapat memasuki mode berburu , dengan fokus pada satu bot. Untuk masuk ke mode berburu:

  1. Kami harus memiliki setidaknya 25 koin. (Kita perlu mendapat koin dulu.)
  2. Mereka harus memiliki paling banyak (koin kita - 5) koin, dan setidaknya 10 koin. (Kami tidak ingin memburu seseorang yang mengambil satu koin dan tiba-tiba lebih kuat, dan kami juga tidak ingin mengejar bot nol koin.)
  3. Kita harus ketinggalan di belakang bot yang saat ini memimpin dengan setidaknya 1/10 dari koinnya. (Kamu harus beruntung untuk berburu sesuatu, jadi tidak perlu memberikan posisi yang baik hanya untuk mencoba keberuntungan kita.)
  4. Kita tidak harus berada di cooldown berburu (lihat di bawah).

Jika semua ini puas, mode berburu diaktifkan. Untuk 10 putaran berikutnya, bot yang diburu hanya memancarkan potensi Setelah 10 putaran ini berlalu, kita memasuki cooldown berburu, di mana kita mungkin tidak masuk mode berburu lagi. (Itu untuk mencegah kita dari mengejar satu bot tanpa henti dan tanpa hasil sementara semua lainnya dengan gembira mengambil koin.) Cooldown berburu adalah 20 putaran ketika kita memiliki 25 koin, dan bertambah 20 koin per setiap penggandaannya. (Dengan kata lain, cooldown adalah .) (Kami menggunakannya karena pada akhirnya, semua bot yang dapat diburu kemungkinan besar mati, dan setiap perburuan kemungkinan besar akan sia-sia. Karena itu, kami ingin membatasi waktu yang terbuang. Tapi kadang-kadang, makan di akhir permainan yang beruntung bisa mengubah segalanya, jadi kami menjaga kemungkinan itu.)

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

Akhirnya, seluruh arena ditempatkan ke sumur potensial tak terbatas yang mencegah bot melarikan diri.


Saya pikir bot ini mungkin mengalahkan gerakan tertimbang saya juga.
fəˈnɛtɪk

@ fəˈnɛtɪk - Begitu juga saya :—). Saya pikir yang satu ini dapat menangani bot lain sedikit lebih baik. (Juga itu tidak "dibutakan" oleh koin di alun-alun yang berdekatan.) Tapi saya pasti memberi Anda +1 karena saya penggemar ide ini.
Ramillies

Bisakah Anda menerapkan prinsip tindakan paling tidak untuk ini?
Beta Decay

@ BetaDecay: Tidak cukup saya khawatir, kalkulus tidak merespon dengan baik untuk masalah diskrit seperti ini. Bahkan dalam kasus kontinu itu tidak akan sepele (karena besarnya kecepatan tetap), tapi itu bisa dilakukan setelah beberapa koordinat kutub sihir kurasa.
Ramillies

4
Ini keren. Saya tidak yakin risiko terkait secara monoton dengan jarak, sepertinya ancaman 2 ruang jauhnya lebih mungkin membunuh Anda daripada yang berdekatan, karena dalam kasus terakhir salah satu dari Anda harus tetap diam agar tabrakan terjadi.
Kain

16

Algoritma Pembelajaran Gen Pertama | JavaScript (Node.js)

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

Cobalah online!

Pernahkah Anda melihat garis waktu algoritma belajar belajar bermain game? Mereka sering bergerak hampir secara acak dalam beberapa generasi pertama ...


LOL ... Mungkin masih berfungsi!
Program Redwolf

2
Kebanyakan algoritma pembelajaran bekerja secara acak untuk beberapa iterasi pertama, bukan hanya hampir secara acak.
fəˈnɛtɪk

Tebak apa? Bot ini rata-rata mendapat hampir 0,22 koin per putaran!
Program Redwolf

16

Big King Little Hill | JavaScript

function BigKingLittleHill(me, enemies, coins) {

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

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

Cobalah online!

Big King Little Hill membuat keputusan berdasarkan "zona kontrol". Itu hanya akan mengejar koin yang berada di zona kontrol yang berarti dapat mencapai koin sebelum bot lain bisa. Ketika tidak ada koin di zona kontrolnya, ia malah bergerak untuk memaksimalkan ukuran zona kontrolnya. Big King Little Hill menghitung zona kontrol dari masing-masing 5 gerakan yang mungkin dan mendukung gerakan yang memaksimalkan ukuran zona kontrolnya. Dengan cara ini, Big King Little Hill akhirnya mencapai kontrol maksimum (bukit kecil) lokal dan menunggu koin dihasilkan dalam zonanya. Selain itu, Big King Little Hill menolak segala tindakan yang dapat mengakibatkan kematiannya kecuali tidak ada alternatif.

Big King Little Hill adalah orang yang pesimis (lebih suka istilah realis) karena tidak mau repot-repot memperebutkan koin apa pun yang tidak dijamin diperolehnya. Ia juga seorang pasifis karena ia tidak mengejar bot yang lebih lemah dalam arti apa pun (meskipun mungkin akan menginjaknya jika mereka menghalangi). Terakhir, Big King Little Hill adalah seorang pengecut yang tidak akan membahayakan hidupnya sendiri untuk imbalan apa pun kecuali benar-benar harus.


1
Selamat datang di PPCG! Bot yang sangat bagus = D
Luis felipe De jesus Munoz

Inilah yang saya pikirkan untuk bot. Kerja bagus.
Jo.

10

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

Bot ini langsung menuju koin bernilai tertimbang (nilai / jarak) yang tidak dapat mati karena mencapai pada saat yang sama atau setelah bot lain. Jika tidak ada koin yang valid dengan properti ini, ia duduk di tempat bot berada sekarang bergerak ke arah aman acak (keselamatan berarti bahwa jika bot bergerak ke arahnya, koin pengaman tidak dapat bertabrakan. Hal ini memungkinkan bot untuk bertukar tempat dengan bot lain jika tepat di sebelahnya), tertimbang menuju pusat arena.


1
Huh, ini mungkin benar-benar menang. Meskipun, ada banyak bot
Program Redwolf

Metode ini akan memiliki lebih banyak masalah semakin banyak bot musuh dengan nilai yang lebih tinggi atau sama ditempatkan.
fəˈnɛtɪk

1
Yah, mereka semua mungkin akan langsung menuju ke koin terdekat dengan mereka / koin emas.
Program Redwolf

Ini hanya akan berhasil jika berhasil mendapatkan beberapa koin tepat di awal.
fəˈnɛtɪk

Dan itu sebagian besar keberuntungan, karena tempat di mana koin menghasilkan secara acak diputuskan
Program Redwolf

10

Bot yang Memainkan Gim Dengan Hati-Hati Tetapi Bisa Agresif | JavaScript

Warna yang disukai: #F24100

Catatan: Meskipun bot ini telah menempati posisi pertama, itu karena bergabung dengan "Feudal Noble" di akhir dan memakannya untuk mendapatkan lebih banyak koin. Kalau tidak, bot ini akan menjadi yang ke-3. Jika Anda tertarik dengan bot yang lebih kuat secara individual, checkout Potential Victorious dan Big King Little Hill .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return score + Math.random();
    };

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

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

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

    return topCommand;
}

Bot ini (alias "TBTPTGCBCBA") mencoba membuat keputusan terbaik dengan menghasilkan skor untuk setiap gerakan yang mungkin dan memilih gerakan dengan skor yang lebih tinggi untuk setiap belokan.

Sistem penilaian memiliki banyak detail yang berkembang sejak awal tantangan. Mereka dapat digambarkan secara umum seperti ini:

  • Semakin dekat koin dengan gerakan yang mungkin, semakin banyak skor yang bergerak. Jika koin tidak memiliki kontestan lain yang memungkinkan, skornya bahkan lebih tinggi. Jika sebuah koin memiliki kemungkinan kontestan lain, skornya menjadi lebih rendah.
  • Jika bot lain dekat dengan gerakan yang mungkin dan memiliki lebih sedikit koin, tergantung pada fase permainan, itu bisa berarti lebih banyak skor untuk langkah itu. Jadi biasa untuk "TBTPTGCBCBA" untuk makan beberapa bot lain di setiap pertandingan.
  • Jika bot lain dekat dengan gerakan yang mungkin dengan poin yang sama atau lebih, gerakan itu mendapat skor negatif yang cukup untuk memastikan kematian dihindari. Tentu saja mungkin ada beberapa kasus bahwa semua gerakan yang mungkin adalah buruk dan kematian tidak dapat dihindari, tetapi itu sangat jarang.
  • Ada mekanisme untuk melacak jumlah bot di tengah papan selama 20 putaran terakhir. Jika rata-rata cukup rendah, semua bergerak ke arah koin di tengah mendapatkan skor lebih banyak dan jika rata-rata tinggi, maka semua bergerak ke arah koin di tengah mendapatkan skor lebih rendah. Mekanisme ini memungkinkan untuk menghindari konflik dengan "Feudal Noble". Karena "Feudal Noble" selalu di tengah (kecuali sedang dikejar), rata-rata jumlah bot di tengah naik dan "TBTPTGCBCBA" mengerti untuk menghindari tengah jika ada pilihan yang lebih baik di luar daerah tengah. Jika "Feudal Noble" mati, rata-rata turun dan "TBTPTGCBCBA" mengerti bahwa ia dapat menggunakan tengah.
  • Ada beberapa faktor yang berubah secara dinamis berdasarkan fase permainan (terdeteksi dari jumlah bot hidup), faktor-faktor ini mempengaruhi penilaian di masing-masing item di atas.
  • Bot ini memiliki kemampuan khusus. Seiring waktu ia mulai bosan dengan keegoisan "Feodal Noble" dan penindasan petani. Pada saat yang tepat, ia akan bangkit untuk mengakhiri sistem feodalisme yang tidak menyenangkan. Upaya yang berhasil tidak hanya membantu petani miskin, tetapi juga memberikan peluang kemenangan yang lebih tinggi karena koin yang diambil dari "Feudal Noble".

Tampaknya jauh lebih ... cerdas daripada yang lain
Program Redwolf

5
Saya suka monster bagian dari params
Redwolf Programs

9

The AntiCapitalist | Javascript

Tidak memiliki insentif untuk mengejar koin, tetapi mencoba menempatkan dirinya tepat di antara dua bot terkaya dengan jumlah uang yang sama, dengan harapan mereka akan memburunya dan akhirnya menangkapnya pada saat yang sama, membawa dua kapitalis bersamanya ketika dia mati . Tidak secara aktif menolak untuk mendapatkan koin, jadi dia mungkin menjadi target yang lebih menarik.

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

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

Dengan Potential Victorious, kami memiliki dua bidang: bidang bot dan bidang koin. Namun, alam tidaklah rumit. Sudah waktunya untuk menyatukan dua bidang untuk menghasilkan Grand Unified Theory .

Pertama, kita perlu mencari tahu apa potensi lapangan itu. Dengan asumsi bot kita sendiri tidak mempengaruhi bidang dengan cara apa pun, kita dapat menulis ini sebagai:

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

kn(xn,yn)

Properti relatif objek dihitung seperti ini:

k=cobjectcme

ccme=cself+1cself

Sebut saja bagian koreksi ini dari Modified Betanian Dynamics (MOBD) .

Kita juga dapat menemukan energi kinetik sebagai:

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

Kami sekarang dapat menghitung tindakan:

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

Dan Lagrangian bot kami di bidang koin-bot adalah:

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

Kita sekarang perlu menyelesaikan persamaan Euler-Lagrange:

ddtLx˙=Lx

dan:

ddtLy˙=Ly

Begitu:

ddtLx˙=ddt[cmex˙]=cmex¨

Lx=n200kn(xxn)ekn2100(xxn)2

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

Dan juga:

ddtLy˙=ddt[cmey˙]=cmey¨

Ly=n200kn(yyn)ekn2100(yyn)2

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

Sekarang kita tidak perlu melangkah lebih jauh: kita hanya melihat arah percepatan keseluruhan:

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

Dan seperti itu, kami telah menyatukan koin dan bot. Di mana Hadiah Nobel saya?


5
Hadiah Nobel Anda hilang dalam surat, tetapi kami bisa memberikan Anda Emmy Award
Redwolf Program

1
Sepertinya fisika mulai menjadi populer dalam tantangan ini. :—D. Dan tentu saja saya sangat ingin tahu tentang seberapa baik itu akan dilakukan.
Ramillies

1
(Ngomong-ngomong, kamu bisa menyelamatkan kerumitan dengan persamaan Euler-Lagrange, karena mereka mengurangi fakta yang terkenal bahwa F = c_me a = - lulusan U :—).)
Ramillies

@Ramillies Meh, lebih menyenangkan melakukannya dengan cara ini: D
Beta Decay

1
Apakah Anda yakin ingin menggunakan k = koin dari sesuatu yang lain / koin Anda? Anda mulai tanpa koin ... dan dengan NaN di mana-mana, Anda tidak terlalu mungkin untuk mendapatkannya.
Ramillies

8

Goldilocks, 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
}

Cobalah online!

Cukup kunci ke lokasi koin emas dan bergerak ke arah itu setiap saat. (Terima kasih kepada bot 'B33-L1N3' dari @ Mayube untuk kode asli yang digunakan ini, meskipun hampir tidak ada yang tersisa.)


Ini adalah bot yang cukup bagus dan sederhana. Saya suka itu.
Program Redwolf

2
Omong-omong, saya menggunakan bot ini sebagai tes untuk controller saya (:
Program Redwolf

8

Algoritma Pembelajaran Gen Ketiga | 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)];
}

Cobalah online!

Setelah beberapa generasi belajar, bot ini telah belajar bahwa meninggalkan arena = buruk


Oh bagus. Saya pernah mendengar ini disebut "Seleksi Alam"
Program Redwolf

5
Di mana gen kedua
Luis felipe De jesus Munoz

11
@LuisfelipeDejesusMunoz Dia meninggalkan arena.
Jo.

Ini adalah bot yang bagus untuk debugging controller
Program Redwolf

3
Oh, omong-omong, arena dimulai dari 0, jadi seharusnya begitu arenaLength - 1. Ini membunuh bot Anda beberapa kali bagi banyak orang
Program Redwolf

7

B33-L1N3 | JavaScript (Node.js)

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

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

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

Cobalah online!

Membuat langsung menuju untuk koin terdekat


Oh, saya pikir B33-L1N3 adalah semacam nomor model
Program Redwolf

+1 untuk namanya
Kain

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

Hapuslet
Program Redwolf

5

Tinggal di Edge, JavaScript

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

Yang satu ini mendengar ujung arena adalah tempat yang berbahaya. Mengetahui tidak ada rasa takut, ia tanpa lelah melingkari papan searah jarum jam, hanya beberapa senti dari kematian tertentu yang menunggu di belakang perbatasan, berharap tidak ada bot lain yang berani bergerak begitu dekat ke sekitar tepi.


1
Ini tidak akan berakhir dengan baik jika bot lain dibuat yang memiliki 1 koin lagi, dan berpatroli di perbatasan ke arah yang berlawanan (:
Program Redwolf

8
Saya akan membuat lelucon kontrol perbatasan, tapi saya akan menyerahkannya ke @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
}

Cobalah online!

Satu bot berbasis katamari terakhir untuk hari ini, kali ini dengan sedikit memori. Terima kasih kepada @BetaDecay untuk saran nama - pasti nama yang lebih menyenangkan daripada saya simplePredictorKatamari.

Berusaha mengetahui bagaimana bot telah bergerak di belokan terakhir, dan berdasarkan itu, memprediksi ke mana mereka akan mencoba bergerak di akhir belokan ini (dengan asumsi mereka terus bergerak ke arah yang sama).

(Terima kasih kepada @ fəˈnɛtɪk, karena memperhatikan bahwa saya memanggil nama fungsi yang salah di botNotes, dan ke @ OMᗺ karena memperhatikan bug dalam kode dasar.)


Ini mungkin satu-satunya saat ini yang dapat menangkap orang lain di luar hanya karena beruntung.
Kain

Bukankah botnotes seharusnya "disimpanata" bukan setdata?
fəˈnɛtɪk

@ fəˈnɛtɪk Lihat, sudah membutuhkan perbaikan bug! :) Terima kasih, diperbaiki sekarang.
sundar

Anda harus mengganti aWt = 1params dengan aWt, dan meletakkannya di aWt = aWt || 1bawah (Sama dengan bWt). Ini mencegah kesalahan.
Program Redwolf

5

Proton | JavaScript

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

Semua koin (termasuk yang dipegang oleh bot lain) memancarkan gaya tolak terhadap Protonbot. Berdasarkan kekuatan ini, ia membangun kecepatan dan memantul dari dinding (berbalik segera setelah mengenai batas). Jika berakhir di sebelah bot atau koin yang dapat dikonsumsi, gaya nuklir Strong mengambil alih dan bergerak untuk mengkonsumsinya, menjatuhkan semua kecepatan ketika melakukannya.


Hmm, fisika nuklir diterapkan pada perburuan harta karun? Ini mengalahkan Science Channel setiap hari!
Program Redwolf

Anda harus mengganti sindengan Math.sin, cosdengan Math.cos, dan seterusnya
Program Redwolf

4

Tidak begitu Buta | JavaScript (Node.js)

Catatan Penting: Pendekatan ini tidak sepenuhnya milik saya dan telah dijawab dalam pertanyaan serupa . Pastikan untuk memilih jawaban itu juga.

Pernahkah Anda mendengar tentang algoritma pathfinding A *? ini dia. Ini menciptakan jalur terbaik dari satu titik ke koin yang kurang berharga (karena semua orang mencari yang paling berharga, tidak ada yang mencari yang kurang) dan mencoba untuk tidak bertabrakan dengan pengguna lain.

Diharapkan parameter sebagai berikut:

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

Mungkin saya melakukan satu yang pergi berburu bot lain


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 ... sudah ada algoritma pathfinding? Ini baru 3 jam!
Program Redwolf

@RedwolfPrograms Seperti yang saya katakan, itu disalin dari tantangan lain yang serupa. Hanya perlu menyesuaikannya dengan yang ini.
Luis felipe De jesus Munoz

Algoritma saya memilih koin mana yang paling aman untuk dikunjungi.
fəˈnɛtɪk

4

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

Hindari bot dengan lebih banyak uang jika memungkinkan. Kalau tidak, ambil uang yang ada di sekitar.


Ini adalah bot paling dasar yang memiliki peluang untuk menang
Program Redwolf

4

Bot Goose Chase Liar, Javascript

Bot yang sangat bagus untuk menghindari bot lain, tetapi sangat buruk dalam mendapatkan koin.


Algoritma:

  1. Jika tidak ada bot yang berdekatan, kembalikan tidak ada
  2. Jika tidak:
    1. Tidak mengembalikan apa pun dengan kesempatan acak 1/500 (ini dimaksudkan untuk mencegah kebuntuan).
    2. Tentukan ruang mana yang aman untuk dipindahkan (yaitu di dalam arena dan tidak ditempati oleh bot lain)
    3. Kembalikan satu secara acak

Kode:

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

Cobalah secara Online!

Catatan untuk Program Redwolf:

Bot ini berpotensi menyebabkan putaran yang sangat panjang. Saya telah mengambil beberapa kebebasan untuk mencegah kebuntuan, tetapi belum menguji apakah mereka benar-benar efektif. Jika bot ini menjadi masalah selama pengujian, silakan didiskualifikasi.


Terima kasih atas catatannya. Seorang ahli evader memiliki peluang yang bagus jika itu terjadi untuk mengumpulkan koin yang cukup saat dikejar
Redwolf Programs

Saya suka ini. Ini hampir seperti umpan untuk robot berburu
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
}

Cobalah online!

(Terima kasih kepada @ OMᗺ karena menunjukkan bug dalam kode asli yang menjadi dasar ini.)

Berusaha untuk tumbuh dengan "memakan" bot dengan koin lebih sedikit dari dirinya sendiri. Jika itu tidak mungkin (tidak ada bot seperti itu), maka cari koin terdekat.

Versi ini memiliki sedikit penyesuaian untuk (a) memberikan preferensi lebih tinggi pada koin emas daripada koin perak - dengan risiko bahwa mencari koin emas yang lebih jauh akan berakhir dengan mengorbankan nyawa bot atau menyebabkan pengejaran emas bodoh (b) lewati bot dengan 0 koin - tidak perlu membuang waktu untuk mengejar mereka.


Seorang pemburu yang pintar ... yah, itu lebih baik!
Program Redwolf

@RedwolfPrograms Semoga begitu! :)
sundar

Seharusnya menyebut Damacy ini;)
Beta Decay

1
@BetaDecay Wish dikabulkan.
sundar

4

Bot Mabuk Dekat-Penglihatan | 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
}

Tersandung di sekitar mengambil koin di dekatnya, tetapi secara acak sering mengubah arah. Melakukan apa yang dia bisa untuk menghindari menabrak siapa pun, tetapi dia menjadi ... berperang ... ketika diperparah. Cenderung sadar saat kompetisi berlangsung.

Mungkin perlu debugging, ketika controller sudah selesai saya akan bekerja di atasnya.


3
Hmm, itu meningkatkan standar, lalu mabuk karenanya
Program Redwolf

4

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

Bergerak ke arah itu ia telah menetapkan nilai tertinggi sambil menghindari lari dari tepi papan.

Nilai dihitung seperti itu:

  • Koin = kekuatan koin / jarak ke koin
  • Bot = Perbedaan kekuatan bot / 2 * jarak ke bot

1
Nah, ini terlihat seperti bot yang cukup mengagumkan. Pastikan untuk memeriksa arah, karena itu akan menjadi kerugian nyata jika bot Anda adalah seorang ahli dalam melarikan diri dari koin (:
Program Redwolf

Yah, tetap saja. Aku harus bersikap baik, bukan?
Program Redwolf

Baiklah, pasang! Ini akan menggantikan bot yang lebih kecil dan lebih cepat yang juga ada saat ini dalam jumlah besar.
Program Redwolf

for(i=0;i<6;i++){hanya ada 5 koin total, 1 emas dan 4 perak. Loop Anda berjalan 6 kali dari 0 hingga 5.
Night2

3

Blindy | JavaScript (Node.js)

Ini pasti tidak akan menang tetapi setidaknya berpartisipasi. Pertama kali mencoba tantangan KoH. Ini memilah koin dan pergi ke yang terdekat. Dia tidak mencari pemain sehingga dia tidak peduli jika dia bertabrakan dengan yang lain.

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, mungkin berhasil karena bot lain akan mencari emas terutama, berpotensi meninggalkan Anda untuk mendapatkan perak tanpa pertempuran
Program Redwolf

3

Mulia Feodal | JavaScript

Warna yang disukai: #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;
}

Bangsawan feodal ini tinggal di tengah lapangan dan mengklaimnya sebagai istananya sendiri. Mengumpulkan apa pun di pusat untuk dirinya sendiri, tetapi apa pun di pertanian jauh harus dibawa kepadanya oleh petani. Tentu saja jika seorang petani kuat yang marah muncul di istana, bangsawan mungkin melarikan diri untuk menyelamatkan hidupnya, tetapi dia kembali segera setelah itu aman!

Seiring berjalannya waktu, petani menjadi semakin kuat. Pejuang profesional dan pahlawan yang kuat mulai bangkit dari kaum tani. Kekuatan bangsawan terus membusuk. Dia mencoba untuk menjaga kekayaan dan sistem Feodalismenya bersama selama dia bisa. Tetapi akhirnya tiba saatnya ia harus menerima imannya, ia harus menerima bahwa orang tidak menginginkan Feodalisme lagi. Itu adalah hari dimana bangsawan feodal menyerahkan segalanya, tidak lari dari petani yang kuat lagi dan terbunuh oleh salah satu dari mereka.


2

Galat Kuantum | 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
}

Bot menjengkelkan ini mencoba untuk berdengung di sekitar bot terkuat tanpa mendapatkan ditepuk dan memiliki sedikit kesempatan untuk melakukan pentahapan melalui mereka yang mencoba memburunya. Ini memiliki kecenderungan untuk menarik dua bot paling kuat ke dekat ...;)


Jika dia tidak dapat menemukan target yang cocok getTargetDirections(), maka hal-hal menarik mulai terjadi. (Seperti menghancurkan segala sesuatu karena undefined has no property 0kesalahan.)
Ramillies

2

Agen Pensiunan ICE, JavaScript

Warna yang disukai: 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";
            }
        }
    }
}

Sekarang sudah pensiun, agen ICE ini pahit tentang kemanusiaan. Akibatnya, Pensiunan ICE sekarang menargetkan bot terlemah, sambil menjaga nilai koinnya di atas rata-rata (sesuai kebijakan ICE).


2

Greedy-Pursuit | Haskell

Warna yang disukai: #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"

Cobalah online! *

Strategi yang cukup sederhana, mengambil keputusan pertama dari:

  • jika ada bot dengan koin lebih sedikit: pilih yang terdekat dan bergerak ke arahnya
  • jika ada koin: pilih yang terdekat dan bergeraklah ke sana
  • default: tinggal

Bot hanya mencoba menangkap bot atau koin lain tanpa peduli dengan bot yang berpotensi lebih kuat yang mungkin mencoba menangkapnya.

* Saya tidak benar-benar tahu JavaScript, tetapi saya melakukan hal dengan google (mungkin tidak akurat): Coba online!


6
Saya ingin tahu bagaimana dia akan menerjemahkan haskell menjadi js
Luis felipe De jesus Munoz

3
@LuisfelipeDejesusMunoz: Ya saya juga. Tapi untungnya, itu bukan kode yang sangat canggih.
ბიმო

@LuisfelipeDejesusMunoz Cukup gunakan Node.JS dan process.open(atau child_process.spawn, atau serupa) dengan beberapa parsing.
user202729

@LuisfelipeDejesusMunoz: Saya mencoba menerjemahkannya dan menambahkan tautan, tapi saya tidak merasa sangat percaya diri menulis JavaScript, jadi mungkin buggy.
ბიმო

4
@LuisfelipeDejesusMunoz Akan menjadi satu hal jika ini adalah program pembelajaran AI 10.000 baris, tapi saya rasa saya bisa mengelolanya (:
Program Redwolf

1

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

Bot ini agak bodoh, mengarah ke arah koin yang paling bisa didapat. Ini termasuk koin yang tidak bisa didapat karena bot lain memiliki kekuatan lebih tinggi daripada dirinya sendiri.


1

Agen ICE | Javascript

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

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

    avg /= others.length;

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

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

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

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

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

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

Apa gunanya perbatasan jika tidak dipatroli? ICE bergerak berlawanan arah jarum jam di sekitar perbatasan, mengambil bot yang tersesat di jalurnya.

Sebelum dapat melakukannya, perlu makan bot lain terlebih dahulu. Untuk alasan itu ICE, simpan koinnya di atas rata-rata semua bot.

Dijamin mencuri anak-anak dari orang tua mereka ™


Ini akan lebih lucu jika tidak begitu relevan
Don Thousand

1

X Menandai Bintik | 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 menandai titik, jadi semua emas harus pada sumbu x, kan? Bot saya langsung menuju ke garis y = 0 lalu tetap di sana, bergerak secara acak.


Huh, memang metode yang menarik
Program Redwolf


1
Karena itu The arena starts at (0,0) in the upper left corner, apakah Anda yakin ingin pindah southke sana y=0?
AdmBorkBork

@ AdmBorkBork Terima kasih, itu bisa saja buruk
Beta Decay

1

Burung api

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

Dirubah total menjadi lebih mematikan dari sebelumnya (:



Itu tidak menargetkan mereka, itu menghindarinya
Program Redwolf

Oh maaf, saya salah paham
Beta Decay

1

A-Path-y | JavaScript

Warna yang disukai untuk bot ini adalah #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);
}

Bot ini menggunakan pencarian jalur yang digabungkan dengan peta keinginan sel untuk menghindari bot yang bisa membunuh kita, mencari koin yang dekat, bukan jebakan dan paling tidak berisiko.

Tampaknya tidak menjadi penantang untuk tempat yang menang, tetapi itu memang memiliki sendiri dan akan hidup pada akhir pertandingan jika selamat dari huru-hara awal.

Bot sekarang memiliki strategi permainan menengah ke atas yang mengabaikan koin yang tidak dapat dijangkau sebelum bot lain dan jika tidak bisa pergi ke koin apa pun kemudian pindah ke sel terdekat yang paling jauh dari semua bot lain yang lebih kuat dari dirinya sendiri.

Sekarang memiliki peluang untuk menang.

Catatan maaf untuk kode jelek, saya telah secara otomatis mengubahnya dari Jawa


Pastikan untuk segera mendapatkan bug dan / atau pembaruan, 18 jam sebelum batas waktu!
Program Redwolf

@RedwolfPrograms Sudahkah Anda mengamati bug? jika demikian tolong beri tahu saya agar saya dapat memperbaiki. Terima kasih
Moogie

Tidak, tetapi Anda tidak pernah tahu. Pastikan untuk mengecek, karena saya telah melihat banyak bot kehilangan karena satu nomor yang salah, atau fungsi yang salah, atau salah ketik lebih dari yang bisa saya hitung
Program Redwolf
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.