금 수집가 KoTH


48

참고 : 커뮤니티 즐겨 찾기 설문 조사가 곧 릴리스됩니다

이 KoTH에서 목표는 마지막 봇이되는 것입니다. 동전은 임의의 영역에 배치되며 봇은 먼저 동전을 가져와야합니다. 봇이 다른 봇을 만나면 더 많은 동전을 가진 봇이 이기고 다른 봇은 죽습니다. 자세한 내용은 아래를 참조하십시오.

동전 종류

금과 은의 두 가지 유형의 동전이 있습니다. 금은 봇의 힘에 5 개의 동전을 추가하고 2는 2를 더합니다. 동전을 수집하면 다른 동전이 보드의 다른 지점에 놓입니다. 언제든지 경기장에 금화 1 개와 은화 4 개가 있습니다.

봇 충돌

두 봇이 같은 공간을 차지하려고 할 때, 동전이 더 많은 사람은 머물고, 돈이 적은 사람은 ...하지 않습니다. 이기는 봇은 상대 동전의 85 % 를 얻 습니다 (반올림). 그들이 묶여 있으면 둘 다 죽습니다. 3 명 이상이 같은 공간을 차지하려고하면 가장 강력한 승자가되고 다른 봇의 동전 중 85 %를 얻습니다. 가장 강력한 봇이 동점 인 경우, 모든 봇은 우주로 들어 가려고 시도한 사람이 죽습니다.

투기장

경기장의 측면 길이는로 계산됩니다 4 + botCount. 게임 시작 부분에 봇을 배치 할 때 무작위 장소가 선택됩니다. 시스템은 동일한 공간에서 또는 서로 옆에 봇이 시작되지 않도록합니다. 동전은 각 봇을 중심으로 3 x 3 정사각형을 제외하고 무작위로 생성됩니다. 경기장 밖에서 봇이 발견되면 즉시 죽습니다. 경기장은 왼쪽 상단의 (0,0) 또는 노스 웨스트에서 시작하며 봇의 위치는 항상 정수입니다.

당신의 로봇

봇은 배열, 정수, 문자열 및 함수가있는 객체 지향 언어의 함수 여야합니다. 모든 제출물은 Javascript로 변환되어 작업이 단순 해집니다. 이동간에 정보를 저장하려면 botNotes.storeData(key, value)및을 사용하십시오 botNotes.getData(key, value). 매개 변수 및를 통해 제공되는 데이터 이외의 방식으로 데이터를 저장하거나 액세스 할 수 없습니다 botNotes. 당신은 전화했을 때, 문자열을 반환하는 함수를 만들어야합니다 north, east, south, west, 또는 none. 함수에는 3 가지 인수가 있습니다.

  • 네 개의 정수 (와 객체 locationX, locationY, coins, arenaLength), 현재 위치, 당신의 동전, 및 경기장의 길이

  • 다른 봇의 X 및 Y 좌표와 해당 코인 수를 가진 다차원 배열[[0,5,4],[4,7,1],[7,4,12]]

  • 동전 위치가 나열된 배열 (금은 항상 첫 번째 임)

이것은 언덕 도전의 왕이며 표준 허점은 금지되어 있습니다. 귀하의 기능은 수천 번 실행되며 매번 하나의 "이동"이 허용됩니다. 게임이 20,000 움직임을 초과하면 동전이 가장 많은 봇이 승리합니다. 이것은 무작위성을 제거하기 위해 8,000 번 수행됩니다.

대화방 : https://chat.stackexchange.com/rooms/81347/gold-collectors-koth

상금 :

1 등 : 100 점 현상금
커뮤니티 즐겨 찾기 : 15 점 허용 답변

수상자 :

1 위 : TBTPTGCBCBA
2 위 : Big King Little Hill
3 위 : 잠재적으로 승리하는
4 위 : 예의 바른 술취한 봇
5 위 : 안전 코인


6
"모든 제출물은 Javascript로 변환되어 일이 단순 해집니다." 이것은 어떻게 작동합니까? 당신은 변환합니까?
Laikoni

21
단일 언어, 특히 JavaScript만큼 널리 보급 된 언어 만 허용하는 koth에는 아무런 문제가 없습니다. JavaScript (아마도 직접 손으로)에 대한 답변을 모호하게 "변환"하는 대신 JS로만 문제를 제한해야합니다. 우리는 과거에 많은 Java 전용 및 Python 전용 코드를 사용했습니다.
Skidsdev

2
위치 대신 가속을 제어하는 ​​버전은 매우 시원합니다.
akozi

12
모두에게 : 댓글이 너무 많습니다. 예 : "+1, 좋은 봇"쓸모없는 댓글을 남길하지 마십시오 , 그리고 그것은 중복의 경우 귀하의 의견을 삭제하시기 바랍니다 . 우리는 전형적인 Q & A 사이트는 아니지만 수백 개의 명령을 읽는 것을 좋아하지 않습니다.
user202729

5
(내 자신의 질문에) : 채팅의 NP에 따르면, 후자는 모든 봇이 움직 인 다음 모든 충돌이 해결되고 모든 동전 픽업이 발생하고 모든 새로운 동전이 배치됩니다.
BradC

답변:


26

BaitBot-JavaScript Node.JS

당신이 결코 잡을 수 없다면 왜 쫓거나 달리는 것을 귀찮게합니까? 대신, BaitBot은 가장 가까운 동전을 찾고 약한 로봇이 동전에 접근 할 때까지 기다립니다. 그들이 둘 다 인접 해있을 때, 베이트 봇은 약한 봇도 마찬가지로 가정하여 동전을갑니다. 베이트 봇이 기다리고 있고 더 강한 봇이 다가 오면 코인과 스캐들만 잡습니다. 저를보십시오!

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
하, 그거 참 좋은 생각이야.
sundar

이 접근법은 꽤 멋지다 ... 아니, 아주 멋지다
Redwolf Programs

1
BaitBot은 nearestThreat && distanceTo(nearestThreat)단순한 것이 아니라 필요합니다 distanceTo(nearestThreat). 위협이 없으면 실패합니다.
Redwolf 프로그램

1
nearestThreat이며 undefined다른 모든 로봇이 당신보다 더 많은 포인트가 있다면.
Night2

1
글쎄, 나는 [10] Bot Bait Bot tired of this world, and jumped off its edge이벤트 로그 와 같은 통지를받습니다
Redwolf Programs

17

잠재적으로 승리 | 자바 스크립트

이 봇의 기본 색상은 #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];
}

(조잡한 서식에 대한 사과,이 사이트의 4 칸 들여 쓰기는 탭 사용에 대한 사용자 정의와 잘 맞지 않습니다.)

대략적인 설명

나는 공식의 설명을 업데이트하려는 시도에서 사임했다. 계수는 끊임없이 변하고 있으며 설명을 최신으로 유지하기가 다소 어렵습니다. 일반적인 원리를 설명하겠습니다.

각 코인과 각 봇은 잠재력이있는 힘장을 생성합니다. 나는 모든 것의 잠재력을 합치면 봇은 잠재력이 가장 낮은 곳으로 간다. (물론이 아이디어는 물리학에서 도난당했습니다.)

저는 두 가지 가능성을 사용합니다. 첫 번째는 의사 중력이며 (모든 범위에서 작동) k는기호의 선택과 함께, 가능성은 매력적이다 필드의 "힘"이며,. 여기서r은 다른 곳에서 택시 메트릭스의 거리입니다.r = | x₁-x₂ | + | y₁-y₂ | .

U=kr+1511+n.

금화 에는 k = 40 을, 은화에는 k = 10 을 사용합니다. n 은 우리보다 특정 동전에 더 가까운 봇의 수입니다. 그렇지 않으면 우리는 다른 봇을 절대 무시합니다 (더 강한 봇을 방해하면 도망 가지만 그게 다입니다). 그렇지 않으면 금을 주로 쫓는 봇이 항상 나를 이겼 기 때문에 나는 가치가있는 것보다 금화를 중요하게 생각합니다.

두 번째 잠재력은 기하 급수적으로 쇠퇴하는 것입니다 (이것은 아주 작은 거리에서만 효과적으로 작용합니다). 이것은 주로 더 강력한 봇에 의해 생성됩니다.

이들은 함께 필드를 생성 이 힘은 0-1 범위에서 엄청나게 강하지 만 더 먼 거리에서는 거의 붕괴되지 않습니다. (거리 + 1은 1/20에서 힘을 절단하는 것을 의미합니다.)

U=5×1400e3r.

우리는 일반적으로 다른 봇을 의도적으로 공격하지는 않지만 (물론 그들이 우리의 길에 들어서서 발을 딛 으면 그들의 잘못입니다), 그렇게 할 가능성이 있습니다. 가혹한 조건이 충족되면 단일 봇에 집중 하면서 사냥 모드로 들어갈 수 있습니다 . 헌팅 모드로 들어가려면

  1. 최소 25 개의 동전이 있어야합니다. (우리는 먼저 동전을 가져와야합니다.)
  2. 그들은 최대 (우리의 동전-5) 동전과 10 동전 이상을 가져야합니다. (우리는 하나의 동전을 들고 갑자기 더 강력한 사람을 사냥하고 싶지 않으며 제로 코인 봇을 추구하고 싶지도 않습니다.)
  3. 우리는 그의 동전의 적어도 1/10만큼 현재 최고의 봇보다 뒤쳐 져야합니다. (당신은 무언가를 사냥하기 위해 운이 좋을 필요가 있으므로, 우리의 운을 시험해보기 위해 좋은 위치를 줄 필요가 없습니다.)
  4. 사냥 쿨 다운 상태 에 있지 않아야합니다 (아래 참조).

이 모든 것이 만족되면 헌팅 모드가 활성화됩니다. 다음 10 라운드 들어, 사냥 봇은 잠재적 방출 이 10 라운드가 경과 한 후에는 사냥 쿨 다운에 들어가고, 그 동안 사냥 모드로 다시 들어 가지 않을 수 있습니다. (이것은 우리가 하나의 봇을 끝없이 쫓아가는 동안 다른 모든 동전을 행복하게 잡는 것을 막는 것입니다.) 사냥 쿨 다운은 25 개의 동전이있을 때 20 라운드이며, 두 배가 될 때마다 20 동전이 증가합니다. 즉, 재사용 대기 시간은

U=150er.
20(1 + log2(c / 25)).) (우리는 최종 게임에서 모든 사냥 가능한 봇이 죽었을 가능성이 높기 때문에 모든 사냥이 헛된 것입니다. 그로 인해 우리는 낭비되는 시간을 제한하려고합니다. 게임 식사는 모든 것을 바꿀 수 있으므로 가능성을 유지하십시오.)

마지막으로, 전체 경기장은 봇이 탈출하는 것을 막는 무한한 잠재적 우물에 배치됩니다.


나는이 봇이 아마도 나의 가중치 움직임을 능가한다고 생각합니다.
fəˈnɛtɪk

@ fəˈnɛtɪk — 나도 그렇게한다 :—). 나는 이것이 다른 봇을 아주 잘 처리 할 수 ​​있다고 생각합니다. (또한 인접한 광장에서 동전으로 "눈을 멀게"하지는 않습니다.)하지만 저는이 아이디어의 열렬한 팬이기 때문에 +1을주었습니다.
Ramillies

이에 최소 행동 원칙을 적용 할 수 있습니까?
Beta Decay

@BetaDecay : 나는 두려워하지 않습니다. 미적분학은 이와 같은 이산 문제에 잘 반응하지 않습니다. 연속적인 경우에도 고정 된 크기의 속도 때문에 사소하지는 않지만 일부 극좌표 마법 후에는 가능할 수 있습니다.
Ramillies

4
이것은 멋지다. 비록 위험이 거리와 단조 적으로 관련되어 있다고 확신하지는 않습니다 .2 공간 떨어진 위협은 인접한 공간보다 당신을 죽일 가능성이 높습니다. 후자의 경우 충돌이 발생하기 위해 정지 상태를 유지해야하기 때문에
가인

16

1 세대 학습 알고리즘 | 자바 스크립트 (Node.js)

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

온라인으로 사용해보십시오!

게임 알고리즘을 배우는 학습 알고리즘의 시간 경과를 본 적이 있습니까? 그들은 처음 몇 세대 동안 거의 무작위로 움직입니다 ...


LOL ... 아직 작동 할 수도 있습니다!
레드 울프 프로그램

2
대부분의 학습 알고리즘은 거의 무작위가 아니라 처음 몇 번의 반복에 대해 문자 그대로 무작위로 작동합니다.
fəˈnɛtɪk

맞춰봐? 이 봇은 라운드 당 평균 0.22 개의 코인을 얻었습니다!
레드 울프 프로그램 22. 18. 18.

16

빅 킹 리틀 힐 | 자바 스크립트

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

온라인으로 사용해보십시오!

Big King Little Hill은“통제 구역”을 기반으로 결정을 내립니다. 그것은 통제 구역에있는 동전만을 추구하여 다른 봇보다 먼저 동전에 도달 할 수 있습니다. 통제 구역에 동전이 없으면 대신 통제 구역의 크기를 최대화하기 위해 이동합니다. Big King Little Hill은 5 개의 가능한 동작 각각의 제어 영역을 계산하고 해당 제어 영역의 크기를 최대화하는 동작을 선호합니다. 이런 식으로, Big King Little Hill은 결국 지역 최대 통제 (작은 언덕)에 도달하고 해당 구역 내에서 동전이 생성 될 때까지 기다립니다. 또한, Big King Little Hill은 대안이없는 한 사망을 초래할 수있는 모든 행동을 거부합니다.

Big King Little Hill은 비관론자입니다 (실제 주의자라는 용어를 선호합니다). 또한 어떤 식 으로든 약한 봇을 추구하지 않는다는 점에서 평화 주의자입니다. 마지막으로, Big King Little Hill은 절대로 그렇지 않으면 보상을 받기 위해 자신의 생명을 위태롭게하지 않는 겁쟁이입니다.


1
PPCG에 오신 것을 환영합니다! 그것은 매우 좋은 봇 = D입니다
Luis felipe De jesus Munoz

이것이 제가 봇을 위해 생각한 것입니다. 잘 했어.
조.

10

안전 동전 | 자바 스크립트

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

이 봇은 가중 가치 동전 (가치 / 거리)을 향해 직진하며, 동시에 또는 다른 봇에 도달하여 사망 할 수 없습니다. 이 속성을 가진 유효한 동전이 없으면 봇이 임의의 안전한 방향으로 이동하는 곳에 앉아 있습니다. 경기장 바로 옆에 가중).


1
허, 이것은 실제로 이길 수 있습니다.
그럼에도

이 방법은 값이 같거나 같은 적 로봇이 배치 될수록 더 많은 문제가 발생합니다.
fəˈnɛtɪk

1
글쎄, 그들은 아마도 그들 / 금화에 가장 가까운 동전에 대한 벌을 만들 것입니다.
Redwolf 프로그램

처음에 동전을 얻을 수 있다면 잘 될 것입니다.
fəˈnɛtɪk

동전이 생성되는 장소가 무작위로 결정되기 때문에 대부분 운이
좋습니다.

10

조심스럽게 게임을하는 봇, 공격적 일 수있는 봇 | 자바 스크립트

선호하는 색상 : #F24100

참고 : 이 봇은 1 위를 차지했지만 마지막에는 "Feudal Noble"과 팀을 이루어 더 많은 동전을 먹기 때문입니다. 그렇지 않으면이 봇은 3 위 였을 것입니다. 개별적으로 더 강력한 봇에 관심이 있다면 잠재적으로 승리 하고 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;
}

이 봇 (일명 "TBTPTGCBCBA")은 가능한 각 이동에 대한 점수를 생성하여 최선의 결정을 내리려고 시도하고 각 차례에 대해 더 높은 점수를 가진 이동을 선택합니다.

스코어링 시스템은 챌린지 시작 이후 진화 된 많은 세부 사항을 가지고 있습니다. 일반적으로 다음과 같이 설명 할 수 있습니다.

  • 코인이 가능한 움직임에 가까울수록 더 많은 점수를 얻습니다. 동전에 다른 참가자가 없으면 점수가 더 높아집니다. 동전에 다른 참가자가 있으면 점수가 낮아집니다.
  • 게임의 단계에 따라 다른 봇이 가능한 움직임에 가깝고 동전이 적 으면 그 움직임에 대한 점수가 더 높을 수 있습니다. 따라서 "TBTPTGCBCBA"는 각 게임에서 다른 봇 몇 개를 먹는 것이 일반적입니다.
  • 다른 봇이 동일하거나 더 많은 포인트로 가능한 이동에 가까워지면, 그 이동은 충분한 부정적인 점수를 얻어 사망을 피할 수 있습니다. 물론 모든 가능한 움직임이 나쁘고 죽음을 피할 수없는 경우도 있지만 매우 드 rare니다.
  • 지난 20 턴 동안 보드 중앙에있는 봇 수를 추적하는 메커니즘이 있습니다. 평균이 충분히 낮 으면 중간에있는 동전을 향한 모든 움직임이 더 많은 점수를 얻고 평균이 높으면 중간에있는 동전을 향한 모든 움직임이 더 낮은 점수를 얻습니다. 이 메커니즘을 통해 "Feudal Noble"과의 충돌을 피할 수 있습니다. "Feudal Noble"은 항상 중간에 있기 때문에 (추적되지 않는 한) 중간에있는 평균 봇 수가 올라가고 "TBTPTGCBCBA"는 중간 영역 외부에 더 나은 옵션이있는 경우 중간을 피하는 것으로 이해합니다. "Feudal Noble"이 사망하면 평균이 낮아지고 "TBTPTGCBCBA"는 중간을 사용할 수 있음을 이해합니다.
  • 봇의 수에서 감지 된 게임의 단계에 따라 동적으로 변경되는 몇 가지 요소가 있으며, 이러한 요소는 위의 각 항목의 점수에 영향을줍니다.
  • 이 봇에는 특별한 능력이 있습니다. 시간이 지남에 따라 "푸달 귀족"의 이기심과 농민의 억압에 질리게됩니다. 적절한 순간에, 그것은 불쾌한 봉건 제도를 종식시킬 것입니다. 성공적인 시도는 가난한 농민을 도울뿐만 아니라 "푸달 귀족 (Feudal Noble)"에서 가져온 동전으로 인해 승리 확률이 높습니다.

그것은 다른 것보다 훨씬 더 지능적인 것 같습니다
Redwolf Programs

5
나는 매개 변수의 괴물 부분을 좋아합니다
Redwolf Programs

9

반 자본주의 | 자바 스크립트

동전을 따를 인센티브는 없지만, 돈이 같은 가장 부유 한 두 봇 사이에 정확하게 자신을 배치하려고합니다. . 적극적으로 동전을 얻는 것에 저항하지 않으므로 더 육즙이 많은 대상이 될 수 있습니다.

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

함께 잠재적으로 승리 봇 필드와 동전 필드 : 우리는 두 개의 필드를 가지고있다. 그러나 자연은 그렇게 복잡하지 않습니다. 이제 그랜드 통합 이론 을 만들기 위해 두 분야를 통합 할 때 입니다.

먼저, 우리는 해당 분야의 잠재력이 무엇인지 알아 내야합니다. 자체 봇이 어떤 방식 으로든 필드에 영향을 미치지 않는다고 가정하면 다음과 같이 작성할 수 있습니다.

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

kn(xn,yn)

객체의 상대 속성은 다음과 같이 계산됩니다.

k=cobjectcme

ccme=cself+1cself

이 수정 부분을 MOBD (Modified Betanian Dynamics)의 일부로 부르겠습니다 .

또한 운동 에너지를 다음과 같이 찾을 수 있습니다.

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

이제 조치를 계산할 수 있습니다.

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

코인 봇 분야에서 우리 로봇의 Lagrangian은 다음과 같습니다.

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

이제 오일러 라그랑주 방정식을 풀어야합니다.

ddtLx˙=Lx

과:

ddtLy˙=Ly

그래서:

엑스˙=[나를엑스˙]=나를엑스¨

엑스=200케이(엑스엑스)이자형케이2100(엑스엑스)2

엑스¨=200케이나를(엑스엑스)이자형케이2100(엑스엑스)2

그리고 또한:

와이˙=[나를와이˙]=나를와이¨

와이=200케이(와이와이)이자형케이2100(와이와이)2

와이¨=200케이나를(와이와이)이자형케이2100(와이와이)2

이제 더 이상 진행할 필요가 없습니다. 전체 가속 방향을 살펴 보겠습니다.

산출={북쪽만약 와이¨<0 과 |와이¨|>|엑스¨|남쪽만약 와이¨>0 과 |와이¨|>|엑스¨|서쪽만약 엑스¨<0 과 |엑스¨|>|와이¨|동쪽만약 엑스¨>0 과 |엑스¨|>|와이¨|none만약 |와이¨|=|엑스¨|

그리고 우리는 동전과 봇을 통합했습니다. 나의 노벨상은 어디에 있습니까?


5
우편으로 노벨상을 잃어 버렸지 만 대신 에미 상을 수여했습니다.
Redwolf Programs

1
이 도전에서 물리학이 인기를 얻는 것처럼 보입니다. :-디. 그리고 물론 그것이 얼마나 잘되는지 궁금합니다.
Ramillies

1
(그런데, F = c_me a =-grad U : —라는 잘 알려진 사실로 축소되기 때문에 오일러-라그랑주 방정식으로 번거 로움을 줄일 수있었습니다.)
Ramillies

@Ramillies Meh, 이런 식으로하는 것이 더 재미있었습니다 : D
Beta Decay

1
다른 것 / 동전의 k = 동전을 사용 하시겠습니까? 당신은 동전없이 시작합니다 ... 그리고 NaN은 모든 곳에서, 당신은 너무 얻을 가능성이 없습니다.
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
}

온라인으로 사용해보십시오!

금화의 위치에 고정하고 매번 동전을 향해 움직입니다. (이것은 거의 사용되지 않았지만 @Mayube의 'B33-L1N3'봇이 사용한 원래 코드에 감사합니다.)


이것은 꽤 좋고 간단한 봇입니다. 나는 그것을 좋아한다.
Redwolf 프로그램

2
그런데, 나는 (내 컨트롤러에 대한 테스트로이 로봇을 사용하고 있습니다 :
Redwolf 프로그램

8

3 세대 학습 알고리즘 | 자바 스크립트 (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)];
}

온라인으로 사용해보십시오!

몇 세대의 학습 후,이 봇은 경기장을 떠나는 것이 나쁘다는 것을 알게되었습니다


오 좋네. 나는 이것이 "천연 선택"이라고 들었습니다
Redwolf 프로그램

5
어디 두 번째 세대
루이스 펠리페 드 예수님 무 노즈

11
@LuisfelipeDejesusMunoz 그는 경기장을 떠났습니다.
조.

이것은 컨트롤러 디버깅을위한 좋은 봇입니다
Redwolf Programs

3
아, 그런데 경기장은 0에서 시작하므로이어야합니다 arenaLength - 1. 이것은 당신의 봇을 여러 번 공정하게 죽였습니다
Redwolf Programs

7

B33-L1N3 | 자바 스크립트 (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');
}

온라인으로 사용해보십시오!

가장 가까운 동전에 대한 을 만듭니다


아, B33-L1N3는 모델 번호의 일종이라고 생각
Redwolf 프로그램

이름 +1
Cain

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


5

Livin 'on the Edge, JavaScript

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

이 경기장의 가장자리가 위험한 곳이라고 들었습니다. 두려움을 알지 못하고, 경계선 뒤에서 기다리고있는 특정 죽음에서 불과 몇 인치 떨어져 보드를 시계 방향으로 끊임없이 돌면서 다른 봇이 가장자리 근처로 너무 가까이 감히 감히하지 않기를 바랍니다.


1
동전이 하나 더있는 다른 봇이 만들어져 반대 방향으로 국경을 순찰하면 제대로 끝나지 않을 것입니다 (:
Redwolf Programs

8
나는 국경 통제 농담을 할 것입니다,하지만 @BetaDecay까지 그 중 하나를 떠날거야
Redwolf 프로그램

5

Damacy, JavaScript (Node.js)

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

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

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

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

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

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

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

  if (!done)
    dir = 'none'


  return dir
}

온라인으로 사용해보십시오!

오늘 약간의 기억력을 가진 오늘의 마지막 katamari 기반 봇. 이름 제안에 대한 @BetaDecay 에게 감사합니다 simplePredictorKatamari. 내 것보다 확실히 더 재미있는 이름 입니다.

마지막 턴에서 봇이 어떻게 움직 였는지 알아 내려고 시도하고,이를 바탕으로 이번 턴이 끝날 때 봇이 어디로 이동하려고하는지 예측합니다 (계속 같은 방향으로 이동한다고 가정).

(botnotes에서 잘못된 함수 이름을 호출하고 있음을 알리고 @ fəˈnɛtɪk에게 감사하고 기본 코드에서 버그를 발견하면 @ OMᗺ에 감사합니다.)


이것은 아마도 운이 좋은 것 이외의 사람들을 잡을 수있는 유일한 사람 일 것입니다.
가인

봇 노트가 "storedata"로 설정되어 있지 않습니까?
fəˈnɛtɪk 1

@ fəˈnɛtɪk See, 이미 버그 수정이 필요합니다! :) 고마워, 이제 수정되었습니다.
sundar

aWt = 1매개 변수를로 바꾸고 그 아래에 (와 동일 ) aWt놓아야 합니다. 이것은 오류를 방지합니다. aWt = aWt || 1bWt
Redwolf 프로그램

5

양성자 | 자바 스크립트

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

다른 봇이 보유한 동전을 포함하여 모든 동전은 Protonbot쪽으로 반발력을 방출합니다. 이 힘을 기반으로 속도를 높이고 벽에서 튀어 오릅니다 (경계를 치면 즉시 돌아갑니다). 그것이 봇이나 동전 옆에서 소비 될 수 있다면, 강한 핵력이 차지하고 그것을 소비하여 움직일 때 모든 속도를 떨어 뜨립니다.


흠, 핵 물리가 보물 찾기에 적용 되었습니까? 이것은 언제든지 Science Channel을 이깁니다!
레드 울프 프로그램 2 :

당신은 교체해야 sinMath.sin, cosMath.cos등, 그리고
Redwolf 프로그램

4

맹목적으로 | 자바 스크립트 (Node.js)

중요 사항 : 이 접근법은 전적으로 내 것이 아니며 비슷한 질문에 대한 답변을 받았습니다 . 그 답변도 투표하십시오.

A * 경로 찾기 알고리즘에 대해 들어 본 적이 있습니까? 여기있어. 그것은 한 지점에서 덜 가치있는 동전으로가는 가장 좋은 길을 만듭니다.

다음과 같은 매개 변수가 필요합니다.

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

어쩌면 나는 다른 봇을 사냥하는 사람을 할 수도 있습니다.


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
와 ... 길 찾기 알고리즘은 이미? 3 시간 밖에 안 걸 렸어요!
Redwolf 프로그램 17

@RedwolfPrograms 내가 말했듯이, 그것은 다른 비슷한 도전에서 복사되었습니다. 이것을 이것에 적응시켜야했습니다.
Luis felipe De jesus Munoz

내 알고리즘은 가장 안전한 동전을 사용합니다.
fəˈnɛtɪk

4

겁쟁이 | 파이썬 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)

가능하면 돈이 더 많은 봇을 피하십시오. 그렇지 않으면, 주위에 돈을 잡아.


이 기회를 가질 수있는 가장 기본적인 봇입니다
Redwolf Programs

4

와일드 구스 체이스 봇, 자바 스크립트

다른 봇을 피하는 데는 좋지만 동전을 얻는 데는 매우 나쁜 봇입니다.


연산:

  1. 인접한 봇이 없으면 none을 반환합니다.
  2. 그렇지 않으면:
    1. 무작위 확률 1/500 확률로 아무 것도 반환하지 않습니다 (이것은 교착 상태를 방지하기위한 것입니다).
    2. 이동할 수있는 공간을 결정하십시오 (예 : 경기장 내부 및 다른 봇이 차지하지 않는 공간)
    3. 무작위로 하나를 반환

암호:

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

온라인으로 사용해보십시오!

Redwolf 프로그램 참고 사항 :

이 봇은 매우 긴 라운드를 일으킬 가능성이 있습니다. 나는 교착 상태를 예방하기 위해 자유를 얻었지만 실제로 효과가 있는지 테스트하지는 않았습니다. 이 봇이 테스트 중에 문제가된다면, 실격을 해제하십시오.


메모 주셔서 감사합니다. 추격하는 동안 충분한 동전을 모으는 경우 전문가
회피자는

나는 이것을 좋아한다. 사냥 로봇의 미끼와 거의 같습니다
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
}

온라인으로 사용해보십시오!

(이 코드는 원래 코드의 버그를 지적한 @ OMᗺ에게 감사합니다.)

봇을 자신보다 적은 동전으로 "먹고"성장하려고합니다. 그것이 가능하지 않으면 (그러한 봇이 존재하지 않는 경우) 가장 가까운 동전을 찾으십시오.

이 버전은 (a) 은화보다 금화를 더 선호합니다. 먼 거리의 금화를 찾으려면 봇의 수명이 길어 지거나 바보의 금 (b) 봇을 건너 뛸 수 있습니다. 0 동전-그 후에 쫓는 시간을 낭비 할 필요가 없습니다.


스마트 사냥꾼 ... 음, 더 나은입니다!
Redwolf 프로그램

@RedwolfPrograms 희망합시다! :)
sundar

이 Damacy를 호출해야합니다.)
Beta Decay


4

예의 바른 술취한 봇 | 자바 스크립트

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
}

근처의 동전을 집어 들기 위해 엇갈리게하지만, 종종 방향을 무작위로 전환합니다. 그가 누군가에게 부딪히는 것을 피할 수는 있지만, 악화되면 ... 호전적입니다 ... 경쟁이 계속됨에 따라 냉정한 경향이 있습니다.

컨트롤러가 완전히 완료되면 디버깅이 필요할 수 있습니다.


3
흠, 그것은 막대를
올린

4

가중 모션 | 자바 스크립트

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

보드의 가장자리를 벗어나지 않으면 서 가장 높은 값으로 지정된 방향으로 이동합니다.

값은 다음과 같이 계산됩니다.

  • 코인 = 코인의 힘 / 코인까지의 거리
  • 봇 = 봇의 힘의 차이 / 2 * 봇까지의 거리

1
글쎄, 이것은 꽤 멋진 봇처럼 보입니다. 당신의 로봇이 실행에 마스터했다 경우 실제 손실이 될 것이기 때문에 방향을 확인해야합니다 멀리 : (동전에서
Redwolf 프로그램

그래도 난 잘 지내야 해, 그렇지?
Redwolf 프로그램 17

글쎄! 현재 대량으로 존재하는 더 작고 빠른 봇을 보완합니다.
Redwolf 프로그램

for(i=0;i<6;i++){총 5 개의 동전, 1 개의 금 및 4 개의 은이 있습니다. 루프는 0에서 5까지 6 번 실행됩니다.
Night2

3

장님 | 자바 스크립트 (Node.js)

이것은 확실히 이길 수는 없지만 최소한 참여합니다. 먼저 KoH 챌린지를 시도하십시오. 동전을 정렬하고 가장 가까운 동전으로갑니다. 그는 선수를 찾지 않기 때문에 다른 선수와 충돌해도 상관 없습니다.

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
}

흠, 다른 봇이 주로 금을 찾고 있기 때문에 효과가있을 수 있습니다. 잠재적으로 어떤 전투도
없이은

3

봉건 귀족 | 자바 스크립트

선호하는 색상 : #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;
}

이 봉건 귀족은 들판 중앙에 머물며 자신의 궁전이라고 주장합니다. 중앙에있는 물건을 스스로 모으지 만, 농민들은 농장에서 멀리 떨어진 물건을 가져 가야합니다. 물론 화난 강력한 농민이 궁전에 나타나면 귀족이 도망 가서 생명을 구할 수는 있지만 안전 해지 자마자 돌아옵니다!

시간이 지남에 따라 농민은 점점 더 강해집니다. 프로 파이터와 강력한 영웅은 농민으로부터 상승하기 시작합니다. 귀족의 힘이 계속 부패합니다. 그는 가능한 한 부와 봉건 제도를 함께 유지하려고 노력합니다. 그러나 마침내 그의 믿음을 받아 들여야 할 때가 왔습니다. 그는 사람들이 더 이상 봉건주의를 원하지 않는다는 것을 받아 들여야합니다. 그것은 봉건 귀족이 모든 것을 포기하고 더 이상 강력한 농민들로부터 도망 치지 않고 그들 중 하나에 의해 죽는 날입니다.


2

양자 모기 봇 | 자바 스크립트

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
}

이 성가신 봇은 힘을 들이지 않고 가장 강한 봇 주위에서 윙윙 거리려고 시도하며 사냥하려고하는 사람들을 통해 약간의 단계를 밟을 수 있습니다. 가장 강력한 두 개의 봇을 근접하게 만드는 경향이 있습니다 ...;)


에서에서 적합한 목표를 찾지 못하면 getTargetDirections()흥미로운 일이 시작됩니다. ( undefined has no property 0오류 로 인해 모든 것을 무너 뜨릴 수 있습니다.)
Ramillies

2

은퇴 한 ICE 에이전트, JavaScript

선호하는 색상 : 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";
            }
        }
    }
}

이제 은퇴 한이 ICE 요원은 인류에 대해 씁쓸합니다. 결과적으로 Retired ICE는 이제 가장 약한 봇을 목표로하면서 동전 가치를 평균 이상으로 유지합니다 (ICE 정책에 따라).


2

탐욕 추구 | 하스켈

선호하는 색상 : #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"

온라인으로 사용해보십시오! *

매우 간단한 전략은 다음에서 첫 번째 결정을 내립니다.

  • 동전이 적은 봇이있는 경우 : 가장 가까운 곳을 선택하고 그쪽으로 이동하십시오
  • 동전이있는 경우 : 가장 가까운 곳을 골라 동전쪽으로 이동
  • 기본 : 숙박

봇은 다른 봇이나 동전을 잡으려고 시도 할 가능성이있는 잠재적으로 더 강한 봇을 신경 쓰지 않고 시도합니다.

* 나는 JavaScript를 잘 모르지만 구글과 관련이 있습니다 (정확하지 않을 수도 있습니다) : 온라인으로 사용해보십시오!


6
나는 그가 JS로 하스켈을 번역하는 것입니다 궁금해
루이스 펠리페 드 예수님 무 노즈

3
@LuisfelipeDejesusMunoz : 그래 나도. 그러나 운 좋게도 매우 복잡한 코드는 아닙니다.
ბიმო

@LuisfelipeDejesusMunoz 단지 구문 분석과 함께 Node.JS 및 process.open( child_process.spawn또는 유사한)를 사용하십시오.
user202729

@LuisfelipeDejesusMunoz : 번역을 시도하고 링크를 추가했지만 JavaScript를 작성하는 데 자신감이 없으므로 버그가있을 수 있습니다.
ბიმო

4
@LuisfelipeDejesusMunoz 이것이 10,000 라인 AI 학습 프로그램이라면 한 가지 일 것이지만, 내가 이것을 관리 할 수 ​​있다고 생각합니다. (:
Redwolf Programs

1

동전 자석 | 자바 스크립트

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

이 봇은 다소 바보이며 가장 획득 가능한 동전의 방향으로 향합니다. 여기에는 다른 봇이 자체보다 높은 힘을 가지고 있기 때문에 얻을 수없는 동전이 포함됩니다.


1

ICE 에이전트 | 자바 스크립트

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

순찰되지 않는 경우 국경의 요점은 무엇입니까? ICE는 경계선을 반 시계 방향으로 움직여 경로에 떠오르는 봇을 들어 올립니다.

그렇게하려면 먼저 다른 봇을 먹을 수 있어야합니다. 이러한 이유로 ICE는 동전을 모든 봇의 평균 이상으로 유지합니다.

부모의 자녀를 훔치도록 보장 ™


관련이없는 경우 더 재미있을 것입니다
Don Thousand

1

X는 그 자리를 표시합니다 | 자바 스크립트

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가 그 자리를 표시하므로 모든 금이 x 축에 있어야합니까? 내 봇은 y = 0의 선을 만든 다음 무작위로 움직입니다.


허, 흥미로운 방법
Redwolf Programs


1
그 점을 감안할 때 The arena starts at (0,0) in the upper left corner, 당신은 이동 south하기를 원 y=0하십니까?
AdmBorkBork

@AdmBorkBork 고마워, 그것은 나빴을지도 모른다
Beta Decay

1

파이어 버드

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

이전보다 더 치명적으로 수정되었습니다 (:


2
봇의 절대 패배자
Redwolf Programs

그것은 그들을 대상으로하지 않고 피하는 것입니다.
Redwolf Programs

죄송합니다, 오해
Beta Decay

1

경로 Y | 자바 스크립트

이 봇의 기본 색상은 #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);
}

이 봇은 우리를 죽일 수있는 함정을 피하고, 함정이없고, 가장 위험하지 않은 동전을 찾는 봇을 피하기 위해 셀 선호도 맵과 함께 경로 찾기를 사용합니다.

이기는 장소의 경쟁자 인 것 같지는 않지만, 제 1의 근접전에서 살아남는 경우에는 자신의 입장을 유지하며 경기가 끝날 때 살아남을 것입니다.

봇은 이제 다른 봇보다 먼저 도달 할 수없는 동전을 무시하는 중후반 게임 전략을 가지고 있으며, 어떤 동전으로도 갈 수 없다면 자신보다 강한 다른 모든 봇에서 가장 가까운 가장 가까운 셀로 이동합니다.

이제 이길 기회가 있습니다.

참고 엉터리 코드에 대한 미안, 나는 자동으로 자바에서 변환 한


기한까지 18 시간 안에 버그 나 업데이트를 미리 받으십시오!
레드 울프 프로그램

@RedwolfPrograms 버그를 관찰 했습니까? 그렇다면 정정 할 수 있도록 알려주십시오. 감사합니다
Moogie

아뇨,하지만 당신은 몰라요 많은 수의 봇이 하나의 잘못된 숫자 나 잘못된 기능으로 인해 잃어버린 것을 보았거나 내가 셀 수있는 것보다 많은 시간을 잘못
타는 것을 보았으므로 다시 확인하십시오.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.