4 인 스탠드 오프


54

4 인 스탠드 오프

기술

당신은 어떻게 든 자신을 4 방향 격리로 발견했습니다. 장전 된 총이 당신의 손에 달려 있고, 수류탄이 벨트에 걸렸습니다.

목표는 스탠드 오프가 끝날 때 가장 건강을 유지하는 것입니다. 최대 한 사람이 건강 상태가 양호하면 스탠드 오프가 종료됩니다.

각 플레이어는 5체력을 가지며 체력이 / 이하로 떨어지면 죽습니다 0. 플레이어가 죽는 턴은 플레이어가 마지막으로 피해를 입을 수있는 턴입니다.

스탠드 오프 끝에 라이브 플레이어가 있으면 해당 플레이어가 승리합니다. 그렇지 않으면 체력이 가장 낮은 플레이어가 승리합니다.

행위

  • 촬영 : 누군가를 촬영합니다.

    • 2 살아있는 적을 쏘면 피해
    • 0 죽은 적을 쏘면 피해
    • health_at_start_of_turn+2자신을 촬영하면 손상됩니다. (이것은 대부분의 -2건강 상태를 유지합니다.)
    • 한 차례의 적이 자신을 쏠 때와 같은 차례에 당신을 쏘면, -4 체력으로 스탠드 오프를 종료합니다 (여러분은 자신을 죽인 차례에 다른 플레이어에게 피해를 입 힙니다).
    • 다음 턴에 당신의 행동은 무시 될 것 Nothing입니다.
  • 닷지 : 상대방의 샷을 피하십시오.

  • 준비 : 수류탄을 풀고 던질 준비를합니다.

    • 폭파하기 전에 세 번만 던질 수 있습니다 ( 6자신에게 3피해 , 모든 살아있는 적에게 피해)
    • 던지지 않은 수류탄으로 죽는 것은 3 턴 동안 수류탄을 던지지 않는 것과 같습니다.
  • 던지기 : 수류탄을 누군가에게 물려주고 최선을 다하십시오.

    • 8살아있는 경우 대상이 피해를 받습니다.
    • 3살아있는 경우 다른 사람 (자신 포함)이 피해를 받습니다.
  • 아무것도 아님 : 차례를 지키고 모두가 죽는 것을 지켜보십시오.

입력

귀하의 프로그램에는 다음 정보가 전달됩니다 :

  • 각 선수의 건강
  • 스탠드 오프 시작 이후 해당 플레이어가 수행 한 작업 목록 아래는 플레이어 당 전달되는 정보의 형식입니다.

    [Health],[Action 1],[Action 2],[Action 3],...
    

조치는 출력 섹션에 지정된 형식으로 제공됩니다 .

공백으로 구분하여 하나의 인수로 전달 된 4 개의 문자열을받습니다. 이 문자열의 순서는 다음과 같습니다.

[Player Info] [Opponent 1 Info] [Opponent 2 Info] [Opponent 3 Info]

문자열은 두 번째 인수로 전달됩니다. 첫 번째 인수에는 규정중인 스탠드 오프를 고유하게 식별하는 정수가 포함됩니다. 동일한 플레이어 세트 사이의 스탠드 오프는 동시에 이루어지지 않아야합니다. 그러나 동시에 여러 스탠드 오프 발생합니다.

예를 들면 다음과 같습니다.

$./Player.bash 5 "3,S2,N 5,P,N 3,S0,N -2,S3,N"

현재 플레이어와 두 번째 상대의 체력은 3이고 첫 번째 상대의 체력은 5이고 세 번째 상대의 체력은 -2이며 죽었습니다.

첫 번째 차례 :

  • 플레이어 1 샷 적 2
  • 적 1은 수류탄을 준비했습니다
  • 적 2 탄 선수
  • 적 3는 자신을 쐈다

두 번째 차례 :

  • 모든 선수는 아무것도하지 않았다. (플레이어와 적 2는 이전 턴에서 쏜 이후로 아무 것도 할 수 없습니다. 적 3은 죽었습니다 : Nothing나머지 스탠드 오프를 위해 할 것 입니다.)

스탠드 오프 시작시 두 번째 인수는 다음과 같습니다 5 5 5 5.

산출

아래 나열된 형식으로 명령을 출력해야합니다. 유효하지 않은 출력은 'Nothing'으로 해석됩니다. 대상을 요구하는 명령 뒤에 정수 ( 0-3, 0플레이어를 1-3나타내고 적 1-3을 나타냄) 가 와야합니다 .

  • S[target]: [타겟]을 촬영합니다.
  • D[target]: [대상]을 피하려고합니다.
  • P: 수류탄을 준비하십시오.
  • T[target]: 수류탄을 [대상]에 던지십시오.
  • N: 아무것도하지 마세요.

타겟을 필요로하지만, 간격이 타겟에 공급되는 명령 03또는 전적으로 타겟팅 가정한다 공급 대상 0(플레이어).

채점

각 스탠드 오프가 끝나면 플레이어는 다음 공식으로 계산 한 점수를받습니다.

35 + health at end of standoff 

플레이어가 체력이 부정적인 상태에서 스탠드 오프를 끝내면 35미만 의 점수 받습니다 . 다음 포인트도 보너스로 보상됩니다.

  • 대부분의 건강 : +4 점
  • 두번째로 건강 : +2 포인트
  • 세 번째로 건강 : +1 포인트.

동점 인 경우, 더 낮은 보너스가 부여됩니다 (두 사람이 건강 상태가 가장 높으면 둘 다 +2, 가장 건강 상태가 좋은 사람이 3 명인 경우 +1, 모든 사람이 동등하게 종료하면 +0).

최종 점수는 모든 개별 점수의 평균을 계산하여 결정됩니다.

규칙 / 세부 사항

  • 턴 내 이벤트 순서는 다음과 같습니다.
    • 모든 플레이어는 자신의 행동을합니다.
    • 체력이 0 이하인 플레이어는 죽습니다.
    • 미사일 수류탄은 폭발해야하며 폭발합니다 (방금 사망 한 플레이어는 여전히 부상을당했습니다.
  • 항목 간 협업이 없습니다.
  • 각 4 명의 플레이어 사이에 3 개의 스탠드 오프가 발생합니다. (플레이어 주문은 각 격리에 따라 다를 수 있습니다).
  • 디스크 공간의 과도한 메모리를 사용하는 항목은 실격됩니다.
  • 출품작 이외의 파일을 읽거나 수정하면 출품작이 실격 처리됩니다.
  • 음주 운전으로 구동되는 트럭은 50th턴이 끝나도 스탠드 오프가 아직 끝나지 않은 경우 턴 후에 모든 살아있는 플레이어를 50th돌립니다.
    • 이 트럭은 모든 라이브 플레이어에게 20의 피해를줍니다.
  • 스탠드 오프가 빠르게 발생합니다. 1 초 후에 프로그램이 중단됩니다.
  • 당신이 죽은 후에도 매번 프로그램이 호출됩니다.
  • 디렉토리에서만 파일을 읽거나 쓸 수 있습니다 (항목 이름이 JohnDoe 인 경우 디렉토리 player / JohnDoe /에 파일을 저장할 수 있음). 그러나 스크립트가 실행되는 동안 현재 디렉토리가 아닙니다.
  • 스탠드 오프는 Arch Linux (릴리스 2014.08.01)를 실행하는 시스템에서 진행됩니다.

컨트롤러는 GitHub에서 사용할 수 있습니다 .

게시물에 다음을 포함하십시오.

  • 봇의 이름
  • 봇 (예 :) java Doe.java입력 을 실행하기위한 쉘 명령 은 단일 인수 ( java Doe.java 5 "-2,S0 -2,S1 -2,S2 5,N") 로 명령 행을 통해 전달됩니다.
  • 봇 코드
  • 봇 컴파일 방법 (해당되는 경우)
  • 언어 (및 특히 파이썬의 경우 해당되는 버전)

* 컨트롤러가 6 분 동안 너무 오래 걸립니다.

스코어 보드

                      Observer 43.280570409982
                   MuhammadAli 43.134861217214
                         Osama 43.031983702572
                    LateBoomer 42.560275019099
                 SimpleShooter 42.412885154062
             LessSimpleShooter 42.3772
                           Neo 42.3738
                        Scared 42.3678
                     Richochet 42.3263
                   Equivocator 42.2833
  TwentyFourthsAndAHalfCentury 42.2640
                        Darwin 42.1584
                       HanSolo 42.1025
                        Coward 42.0458
           ManipulativeBastard 41.8948
                        Sadist 41.7232
                     Aggressor 41.7058
                 CourageTheDog 41.5629
                     Grenadier 40.9889
                     Bomberman 40.8840
                         Spock 40.8713
                        Sniper 40.6346
                 DONTNUKEMEBRO 39.8151
               PriorityTargets 39.6126
                     Hippolyta 39.2480
                     EmoCowboy 39.2069
                      Zaenille 39.1971
                 AntiGrenadier 39.1919
      PoliticallyCorrectGunman 39.1689
                 InputAnalyzer 39.1517
                      Rule0Bot 39.1000
                     BiasedOne 39.0664
                      Pacifist 39.0481
               StraightShooter 39.0292
                         Ninja 38.7801
                           MAD 38.2543
                        Monkey 37.7089
                   Label1Goto1 36.2131
Generated: 2014/08/22 03:56:13.470264860 UTC

로그 : GitHub에서


1
정확히 하나의 수류탄을 가지고 있습니까? 한 번에 여러 수류탄을 준비 할 수 있습니까?
isaacg

2
@Bob 확실히 EmoWolf 가 더 이상 재미 있지 않은 표준 허점에 추가되었습니다 . 자살 항목은 실제로 그렇게 그렇게하지 않을 수 있습니다.
es1024

3
모두에게 교훈 : 음주 운전하지 마십시오.
Mark Gabriel

8
@ es1024 자살이 실제로 실행 가능한 전략 인 경우 EmoWolf 유형 제출이 실제로 허용되어야합니다. 특히 사용 가능한 조치에 명시 적으로 suiciding이 포함 된 경우! 지금은 "허점"이 아닌가? 그리고 대부분의 허점은 실제로 불공평 한 이점이 아닙니다. 하지만 그건 내 의견 일뿐입니다.
Bob

3
컨트롤러를 몇 번 실행 한 결과 꽤 시끄러운 것 같습니다. 이 콘테스트가 종료되면 아마 약간의 뛰기를 위해 런 수를 늘려야합니다.
Davis Yoshida 4

답변:


7

관찰자

이 사람은 그의 적을 분석합니다. 목표는 단 하나의 "공격적"상대 만 남을 때까지 생존 한 다음 서사시 대결에서 상대를 죽이는 것입니다.

컴파일 : javac Observer.java실행 :java Observer arg0 arg1

import java.util.List;
import java.util.ArrayList;
import java.util.Random;

class Observer {
    private static List<Integer> aggressiveEnemies = new ArrayList<>();
    private static List<Integer> enemyGrenadiers = new ArrayList<>();
    private static List<Integer> aliveEnemies = new ArrayList<>();

    public static void main(String[] args) {
        if (args[1].length() <= 7) { //first round
            Random rand = new Random();
            printResult("D" + (rand.nextInt(3) + 1));
        }
        String players[] = args[1].split(" ");

        if (truckIsOnWay(players[0])) {
            printResult("P");
        }       

        calcEnemyInfo(players);

        // end this standoff now
        if (truckWillHit(players[0])) {
            if (isGrenadier(players[0]))
                printResult("T" + aliveEnemies.get(0));
            else
                printResult("S0");
        }

        // shoot enemy who is not aggressive
        if (aggressiveEnemies.size() == 0) {
            printResult("S" + aliveEnemies.get(0));
        }

        // only one enemy to handle
        if (aggressiveEnemies.size() == 1) {
            String player = players[aggressiveEnemies.get(0)];
            if (isGrenadier(player)) {
                printResult("S" + aggressiveEnemies.get(0));
            } else if (shotLastTurn(player, aggressiveEnemies.get(0))) {
                //safe to shoot him without receiving damage
                printResult("S" + aggressiveEnemies.get(0));
            } else {
                printResult("D" + aggressiveEnemies.get(0));
            }
        }

        // multiple aggressive enemies
        if (enemyGrenadiers.size() > 0) {
            printResult("S" + enemyGrenadiers.get(0));
        } else {
            int id = aggressiveEnemies.get(0);
            for (int playerId : aggressiveEnemies) {
                if (!shotLastTurn(players[playerId], playerId)) {
                    id = playerId;
                }
            }
            printResult("D" + id);
        }
    }

    private static void printResult(String result) {
        System.out.print(result);
        System.exit(0);
    }

    private static boolean isAlive(String player) {
        return !(player.charAt(0) == '-' || player.charAt(0) == '0');
    }

    private static void calcEnemyInfo(String[] players) {
        for (int i = 1; i < players.length; i++) {
            if (isAlive(players[i])) {
                aliveEnemies.add(i);
                if (isAggressive(players[i], i)) {
                    aggressiveEnemies.add(i);
                }
                if (isGrenadier(players[i])) {
                    enemyGrenadiers.add(i);
                }
            }
        }
    }

    private static boolean truckIsOnWay(String player) {
        return player.length() - player.replace(",", "").length() == 48;
    }

    private static boolean truckWillHit(String player) {
        return player.length() - player.replace(",", "").length() == 49;
    }

    private static boolean isAggressive(String player, int id) {
        return (player.contains("S") || player.contains("P")) && !player.contains("S" + id);
    }

    private static boolean isGrenadier(String player) {
        return player.contains("P");
    }

    private static boolean shotLastTurn(String player, int id) {
        return player.charAt(player.length() - 2) == 'S' && !player.contains("S" + id);
    }
}

!player.contains("S" + id)"isAggressive"기능에 필요한 조건입니까? 자살 선수는 어쨌든 죽을 것입니다
Cruncher

22

척탄병

총이 과대 평가되었습니다. 사실 스코틀랜드의 교착 상태는 다음과 같이 간다 :

  • 준비
  • 건강 상태가 가장 좋은 적을 처치하십시오
  • 반복하십시오 (일부 기적에 의해 여전히 살아 있다면)

이것은 사소한 것처럼 보이지만 아마도 끔찍한 전략 은 아닙니다 . 총과 수류탄 모두 두 차례의주기를 가지고 있기 때문에,이 훨씬 더 효율적입니다 (1 개) 피해를 처리하는 방법.

물론, 세 명의 상대가 모두 첫 라운드에서 나를 쏘면 좋지 않습니다. 그러나 다른 것도 많지 않을 것입니다.

public class Grenadier {
    public static void main(String[] args) {
        if(args.length < 2)
            return;
        String[] list = args[1].split(" ");
        if(list.length < 4)
            return;

        if(list[0].charAt(list[0].length()-1) != 'P'){
            System.out.print("P");
            return;
        }

        int target = 1;
        for(int i=2;i<4;i++)
            if(list[i].charAt(0)>list[target].charAt(0))
                target = i;

        System.out.print("T"+target);
    }
}

표준 Java 방식으로 컴파일 / 실행 :

> javac Grenadier.java
> java Grenadier arg0 arg1

무의미한 각주 1 개


41
hahaha 각주
자랑스런 Haskeller

수류탄을 던지고 촬영하는 것이 더 효율적이라고 생각합니다. 이 전략으로 4 턴을 생존 할 확률은 상당히 낮습니다. 그러나 아마도 3 개 (예, 둘 다 2 개를 but지만 촬영을위한 두 번째 턴은 이전이 아니라 조치 이후에
진행됨

@Cruncher 아마 옳을 것입니다. 에릭 은 채팅에서 같은 말을했다. 나는 내 남자가 총을 믿지 않으며 그 논리를 사용하기에는 너무 고집이 났다고 말하면서 그 전략을 게시했습니다. 그러나 우리가 엄격히 말하면 피해를 입히는 경우 여전히 더 효율적 이라고 생각합니다 . 그렇다고 게임에서이기는 것이 더 효과적 이라는 것은 아닙니다 . 세 번째 턴에서 죽어도 두 번째 수류탄은 여전히 ​​사라집니다. 내가 그때까지 산다면, 그것은 게임 오버 모두에게 6 + 이상의 피해를 보장합니다.
Geobits

@Geobits 이제는 그것에 대해 생각합니다. 가장 중요한 것은 당신과 상대방 사이의 델타입니다. 수류탄이 터지면 던진 사람과 +3의 델타를 얻습니다. +3의 그물. 촬영. 촬영 한 사람과 +2 델타를 얻습니다. 나머지는 +0입니다. 문제는 이미 죽은 사람들과 당신이 -3이라는 것입니다. 누군가 죽었다면 쏴야합니다 :)
Cruncher

2
@codebreaker 한번도 연주하지 않았습니다. 그것은이다 실생활 참조.
Geobits

16

아시모프의 규칙 번호 0 봇-Python

로봇은 인류에게 해를 끼치 지 않거나, 무 활동으로 인해 인류가 해를 입을 수 있습니다.

아주 간단하게, 그는 대부분의 인간을 보호하기 위해 수류탄을 들고있는 첫 번째 플레이어를 공격 할 것입니다. 아무도 대다수의 인간을 위협하지 않는다면 그는 아무것도하지 않을 것입니다.

import sys

def total_humans_alive(humans):
  return sum([is_alive(human) for human in humans])

def is_alive(x):
  return int(x.split(",")[0]) > 0  

def is_threat_to_humanity(lastAction):
  return lastAction == "P"

action = "N"
threat_id = 1
humans = sys.argv[2].split()[1:];

if total_humans_alive(humans) == 3:
  for human in humans:
    if is_threat_to_humanity(human[-1]):
      action = "S" + str(threat_id)
      break
    threat_id= threat_id+ 1

print action

다음과 같이 실행하십시오.

python rule0bot.py

2
당신의 로봇은 비논리적입니다. 수류탄을 들고있는 플레이어가 던지면 인류는 8 + 3 + 3 + 3 = 17의 데미지를 입습니다. 당신이 총으로 그를 죽이면, 인류는 2 + 6 + 3 + 3 + 3 = 17의 피해를 입습니다. 두 시나리오 모두 수류탄을 날려 버린 사람은 누구나 8을, 다른 모든 사람은 3을 취합니다 (이전에 죽지 않는 한). 인류 전체는 영향을받지 않습니다. 그래도 여전히 마음에 듭니다. +1 : D
Geobits

4
실제로 인류를 위한 최고의 시나리오 는 수류탄이 로봇에 던져지기를 희망하는 것입니다.)
Geobits

1
@Geobits 위협하는 사람을 막으려 고하지 않는 것은 로봇의 본질에 위배됩니다. 수류탄을 들고있는 사람을 막아 대다수 (다른 2 명)가 다 치지 않도록 노력할 것입니다. 로봇 읽었 어? 이 논리는 Little Lost Robot과 Evitable Conflict에 의해 뒷받침됩니다.
William Barbosa

나는 그것을 읽었지만 내가 말하는 것은 그들을 쏘는 것이 여기서 멈추지 않는다는 것입니다. 수류탄을 잡고 사망하면 여전히 폭발합니다. 뿐만 아니라 인류에 대한 총 피해량은 동일합니다. 당신은 인류에게 이익을주지 않으면 서 인간에게 직접적인 해를 끼치고 있습니다.
Geobits

2
+1 Kyle Kanos의 투표에 동의하지 않고 무효화하고 싶습니다. 또한 Geobits는 이것이 인류를 돕기 위해 아무 것도하지 않는다고 가정 할 때 잘못되었습니다. 물론 최악의 시나리오에서는 인류가 나아지지 않을 수도 있지만 다른 두 선수가 수류탄을 휘두르는 수류탄을 쏘면 모두 더 나아질 것입니다.
FreeAsInBeer

14

한 솔로-파이썬

한이 먼저 쐈어. 이 경우, 그는 가장 가까운 표적을 선택하여 먼저 쏠 것입니다.

import sys

def is_alive(player):
  return int(player.split(",")[0]) > 0

closest_living_target = 1;

for player in sys.argv[2].split()[1:]:
  if is_alive(player):
    action = "S" + str(closest_living_target)
    break

  closest_living_target = closest_living_target + 1

print action

다음과 같이 실행하십시오.

python hansolo.py

참고 : 이것은 내가 파이썬에서 쓴 첫 번째 것이므로 파이썬 관련 나쁜 습관이 있으면 알려주십시오.


1
pep8 스타일은 귀하의 방법이 다음과 같아야 함을 제안합니다is_alive
Daenyth

4
@WilliamBarbosa는 pep8을 보았습니다. 모든 사람이 사용하는 파이썬 스타일 가이드입니다. legacy.python.org/dev/peps/pep-0008
Daenyth

2
8/11 라운드에서 평균 체력이 0보다 큰 유일한 봇이 된 것을 축하합니다.
isaacg

6
"스타일 가이드"인 IMO는 프로그래머가 아닌 헤어 드레서 용입니다.
Kyle Kanos

2
@KyleKanos 그래도 일관성을 유지하는 것이 좋습니다. 프로젝트 개발자의 절반이 낙타 케이스를 사용하고 나머지 절반이 이와 같은 경우 결과는 "blergh"가 될 것입니다.
William Barbosa

12

이모 카우보이

왜 죽기를 기다 립니까? 지금 자살하세요 바라건대 나머지 바보들은 서로를 -2보다 훨씬 적게 날려 버릴 것입니다.

점수는 일반적으로 -2입니다. 사람들이 나를 박쥐에서 쏘기로 결정하면 때때로 -4입니다. 그보다 드물게, 이것은 현재 제출 된 것 중 몇 개를 이겨야 함을 의미합니다.

파이썬

print('S0')

python EmoCowboy.py

편집 : 이것은 농담이 아니기 때문에 일반적으로 이러한 이모 제출이 찡그린 이유입니다. 이것은 합법적 인 전략입니다. 살아있는 것은 치명적입니다!


11

평화 주의자

그는 정말 부풀어 오른 사람이고 방금 틀린 군중에 사로 잡혔습니다.

main = putStr "N"

로 실행 runghc pacifist.hs하지만 효율성에 문제가있는 경우 -O3으로 컴파일 할 수 있습니다.


1
이름을 Luigi로 바꾸고 그가 이길 수 있는지 봅시다!
William Barbosa

1
@WilliamBarbosa 루이지? 루이지 라고 했어 ?
killmous

7
마치 괴물 같은 -O3차이를 만드는 것처럼 롤 .
tomsmeding

@tomsmeding runghc측면 이 느립니다 . 실제로 내 Linux 상자에서 10 배 느립니다.
Ray

5
즉, 폭력의 존재를 의미한다, 우리의 평화가 처리 할 준비가되어 있지 인 의미는
killmous

9

원숭이 -파이썬 (최초 참가!)

원숭이 참조, 원숭이 무작위 플레이어가 수행 한 마지막 동작을 정확하게 반복합니다.

import sys, random
targetData = sys.argv[2].split()[random.randint(0,3)]
print(targetData.split(',')[len(targetData.split(','))-1])

다음과 같이 실행할 수 있습니다. "python monkey.py args"추가 단계가 필요하지 않습니다.


2
그들이 당신을 쏘지 않았기를 바랍니다! 파이썬은 음의 배열 인덱스를 지원하므로 길이를 계산하고 빼지 않아도됩니다. -1직접 사용하십시오 .
comperendinous

@comperendinous 나는 그들의 목록에 S3이라고 말한다. S3를 실행하면 어리석지 않습니다. 또한 -1 인덱스는 마지막 요소를 반환합니까? 그렇다면 멋지다! 꼭 추가하겠습니다.
Elias Benevedes

그리고 첫 번째 (정수) 논쟁을 잊지 마십시오. 당신은 필요한 argv[2]선수 기록을 얻을 수 있습니다.
comperendinous

Emo Cowboy와 어울리지 않기를 바랍니다.
codebreaker

6

간단한 사수-펄 (고정 버그)

이 봇은 체력이 가장 높은 상대를 쏴 버립니다. 매우 간단한 전략이지만 실제로 잘 수행 할 가능성이 높다고 생각합니다.

@history = map([split(",",$_)],split(" ",$ARGV[1]));
$target = 1;
for(2..3){
 if($history[$_][0] >= $history[$target][0]){$target = $_}
}
print "S$target"

다음은 예제 입력을 사용하여 실행하는 방법입니다.

perl simpleshooter.plx 7 "3,S2,N 5,P,N 3,S0,N -2,S3,N"

와. 간단하고 똑똑합니다.
Soham Chowdhury

6

Python 3.x의 Spock

이 코드는 좀 더 실험적이지만 (따라서 Spock의 이름을 따서 명명되었습니다. 이 코드의 배후에있는 주된 이유는 게임 규칙이 주어지면 Spock과 같이 훌륭하고 논리적 인 존재가 할 것이라는 가정입니다.


이 게임의 목표는 점수 때문에 최대 점수를 얻는 것입니다. 점수는 트럭으로 인해 정지 상태에있는 모든 사람이 할 수 있습니다.

  • Spock이 준수해야하는 지침 중 하나는 트럭이 나타나지 않도록하는 것입니다. 트럭이 나타나기 전에 한 명을 제외한 모든 사람이 죽었는지 확인하십시오.

Spock이 게임의 나머지 부분에서하는 방식은 그의 유명한 인용문에 의해 요약 될 수 있습니다. " 많은 사람들의 요구는 소수의 요구를 능가합니다 ." 다시 말해, 스팍은 피해를주는 사람들을 죽임으로써 최소한의 피해를 입어야합니다. 그가하는 방법 :

  • 수류탄을 준비한 플레이어가 없다면, 여전히 가장 건강한 선수를 목표로 삼으십시오.
  • 수류탄을 준비한 플레이어가 있다면 가장 적은 대상을 목표로합니다.

그 이유는 가장 약한 플레이어를 대상으로하여 피해의 원인을 종료하고 있기 때문입니다. 수류탄의 배후는 그들이 무방비 상태로 떨어지고 던지지 않으면 피해가 적다는 것입니다.


이 봇이 작동합니다. 입력 오류에 대해 광범위하게 테스트하지 않았으므로 (문제가 발생하면 경고하십시오) 대부분의 문제를 해결했다고 확신합니다. HanSolo 봇의 코드 중 일부를 기반으로했지만 대부분 코드가 복잡합니다. 즐겨.

def IsAlive(player):
  return int(player[1].split(",")[0]) > 0
def IsTarget(player, target_health):
  return int(player[1].split(",")[0]) < target_health
def HasGrenade(player):
  max_range = max(-4,-current_turn)
  for foo in range(-1,max_range,-1):
    if "P" in player[1].split(",")[foo]:
      for bar in range(-1,foo-1,-1):
        if player[1].split(",")[bar] not in ["T0", "T1", "T2", "T3"]:
          return True
  return False

import sys
info_list = sys.argv[2].split()
current_turn = len(info_list[0].split(","))
action = "N"

def Startgame():
  global action

  target = 1
  target_health = 5
  grenade_list=[]

  for player in zip(range(1,4),info_list[1:]):
    if HasGrenade(player):
      grenade_list.append(player)

  if not grenade_list:
    foo_list = []
    for player in zip(range(1,4),info_list[1:]):
      foo_list.append(player)
    target_list = foo_list
  else:
    target_list = grenade_list

  # Choose the least healthy player
  for player in target_list:
    if IsAlive(player) and IsTarget(player, target_health):
      target = player[0]
      target_health = int(player[1][0])

  action = "S" + str(target)

def Endgame(turn):
  global action

  if turn in [47, 49]:
    # Check if in 2 moves he can do enough damage
    rem_health = 0
    for player in zip(range(1,4),info_list[1:]):
      if IsAlive(player): rem_health += player[0]

    if rem_health < 5:
      Startgame() # It's lazy, but it should work
      return
    else:
      action = "P"
      return

  if turn in [48, 50]:
    # If Spock shot someone before, it needs to shoot again
    if info_list[0].split(",")[-1] in ["S0", "S1", "S2", "S3"]:
      Startgame()
      return
    else:
    # There's no rule against throwing grenades to dead bodies, so if
    # possible it will be thrown there.    
      target = 1
      target_health = 5

      foo_list = []
      for player in zip(range(1,4),info_list[1:]):
        foo_list.append(player)
      target_list = foo_list

      for player in target_list:
        if IsTarget(player, target_health):
          target = player[0]
          target_health = int(player[1][1])

      action = "T" + str(target)
      return

if current_turn > 46:
  Endgame(current_turn)
else:
  Startgame()

print(action)

다음과 같이 실행하십시오.

python spock.py

2014-08-12-수류탄 탐지에 관한 사소한 버그 수정
2014-08-14-이전 게임에서 지적한 isaacg 덕분에 최종 게임에 관한 사소한 버그 수정


두 라운드마다 한 번 이상 쏠 수 없습니다. 촬영 사양을 읽으십시오.
isaacg

@isaacg 미리 알림 (행동을 설명하는)에 감사하지만 잠깐의 버그가있는 것 같습니다. 의 예를 들어 그 (솔로가 더이 건강을했을 경우에도) 라이브 수류탄을했기 때문에 스팍 InputAnalyser을 촬영 한 것이다.
Doktoro Reichard

Traceback (most recent call last): File "./players/Spock/Spock.py", line 87, in <module>: Endgame(current_turn) File "./players/Spock/Spock.py", line 79, in Endgame: if IsTarget(player, target_health): File "./players/Spock/Spock.py", line 4, in IsTarget: return int(player[1].split(",")[0]) < target_health TypeError: unorderable types: int() < str()
es1024

player[1][1]이어야합니다 int(player[1][1]).
isaacg

@isaacg 다시, ​​나는 도움을 주셔서 감사합니다. 나는 이것을 더 빨리했을 것이다. 그러나 나는 물건으로 늪에 빠졌다. Spock은 궁극적으로 이것이 어떻게 진행되는지에 대한 잘못된 개념을 바탕으로 구축되었으므로 상대적으로 낮은 점수를 얻었습니다. 나는 새로운 봇에 대한 몇 가지 아이디어를 가지고 있지만, 많은 사람들과 함께 이제는 기본 아이디어가 독창적이어야합니다.
Doktoro Reichard

5

정치적으로 올바른 총잡이

차별을하지 않기 때문에 정치적으로 매우 정확합니다. 따라서 그것은 똑똑하지 않습니다.

import random

array = ["P", "N", "S0", "S1", "S2", "S3", "D1", "D2", "D3", "T1", "T2", "T3"]

print(array[random.randrange(0,11)])

그것은 ... 어떤 인수가 어떻게 전달되는지는 중요하지 않습니다. python politicallycorrectgunman.py


대괄호가 출력의 일부라고 생각하지 않습니다. 아마도 @ es1024가이를 확인할 수 있습니다. 그리고 random.choice에 대해 알고 있습니까? 이런 종류의 선택에 좋습니다.
comperendinous

출력 뒤에는 액션과 대상 앞에 어떤 것도있을 수 없지만 그 뒤에는 무시됩니다
es1024

@ es1024가 더 좋아 보입니까?
취소

@Undo 예, 완벽하게 작동합니다
es1024

7
그냥 사용할 수 random.choice(array)없습니까?
user2357112

5

스트레이트 슈터

그는 기병대에서 훈련을 받았으며 여러 언어로 대화를하지만 깜빡 거리는 스트레이트 슈터는 한 명의 적을 볼 수 있습니다. 말이 기 때문에 그는 당신이 샷 사이에서 기다려야한다는 것을 이해하지 못합니다.

print('S2')

Perl, Python 2/3, Ruby :이 말은 실제로 polygot 항목입니다.

어쨌든 승리하고 있습니다. 나는 잃을 수 없다. 당신은 나를 쏠 수 있지만 당신은 나를 죽일 수 없습니다. 에디 씨는 나 한테 똥이 없어!

좀 더 생각하고 기능적인 패러다임에 대한 대답은 24 세기와 30 세기를 참조하십시오 .


5

수류탄 방지제

수류탄이 나쁩니다. 아주 나쁜. 누군가가 하나를 준비하고 있다면 가장 좋은 방법은 그들을 쏘는 것입니다. 그렇지 않으면, 우리는 그냥 어울릴 것입니다.

-- Antigrenadier
local args = {...}  -- command line arguments

match = args[2]     -- store the set of matches

-- why this isn't standard in Lua....
function string:split( inSplitPattern, outResults )
  if not outResults then
    outResults = { }
  end
  local theStart = 1
  local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
  while theSplitStart do
    table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
    theStart = theSplitEnd + 1
    theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
  end
  table.insert( outResults, string.sub( self, theStart ) )
  return outResults
end

-- set up the players
players = match:split(" ")

-- search other players for someone who pulled a grenade
for i=2,#players do
   moves = players[i]
   -- test if person is alive
   if moves:sub(1,1) ~= "-" then
      -- cycle through all elements of the string
      for j=#moves,2,-1 do
         -- if found, shoot!
         if moves:sub(j,j) == "P" then
            print("S"..i-1)
            os.exit()
         end
      end
   end
end

-- otherwise we just relax
print("N")

4

리코 chet-Perl

이 도전에서는 간단한 전략이 괜찮은 것처럼 보이므로 여기에 또 다른 것이 있습니다. 그것은 임의의 살아있는 플레이어를 쏴. 트럭을 피하기 위해 끝에 자살을 저지르는 기능이 추가되었습니다.

@history = map([split(",",$_)],split(" ",$ARGV[1]));
$health = $history[0][0];
@options = ();
for(1..3){
 if($history[$_][0] > 0){
  push(@options,$_);
 }
}
$target = @options[int(rand(~~@options))];
if(~~@{$history[0]} == 50){
 $target = 0;
}
print"S$target";

다음과 같이 실행하십시오.

perl ricochet.plx 5 "-2,S0 -2,S1 -2,S2 5,N" 

4

침략자

1 라운드를 잡아 당기고 2 라운드에서 가장 높은 체력의 상대를 던져 그 이후 가장 높은 체력의 상대를 쏜다.

#include <cstdio>
#include <cstring>

int main(int argc, char** argv){
   char* t;
   t = strtok(argv[2]," ");
   int len = strlen(t);
   int max = -50, maxP;
   for(int i=1;i<4;i++){
      int cur;
      t = strtok(NULL," ");
      if(t[0]=='-'){cur = -1*(t[1]-'0');}
      else{cur = t[0]-'0';}
      if(cur>max){
         max = cur;
         maxP = i;
      }
   }
   if(len == 1){printf("P\n"); return 0;}
   if(len == 3){printf("T%d\n",maxP); return 0;}
   printf("S%d\n",maxP);
   return 0;
}

./agg ID "5 5 5 5"와 같이 실행하십시오.


4

닌자

적중하지 않기 위해 무작위로 피하다.

math.randomseed(os.time())
print("D"..tostring(math.random(4)-1))

로 실행

lua ninja.lua

Args는 불필요하지만 문제없이 추가 할 수 있습니다.


2
@KyleKanos는 닌자 자신의 샷을 피할 것인가?
skeggse

2
@distilledchaos : ... 예, 그렇습니다.
Kyle Kanos

4

이름 : PriorityTargets

셸 명령 : ruby ​​PriorityTargets.rb 5 [game_state]

언어 : 루비 V2.1.2

설명 : PriorityTargets는 일반적인 플레이 스타일을 찾으려고 시도합니다. 그런 다음 해당 플레이 스타일에 따라 공격 할 대상과 사용할 무기를 결정합니다.

참고 : 퍼스트 코드 골프 제출! 내가 약간 미쳤 기 때문에 다른 제출물보다 훨씬 큽니다.

#!/usr/bin/env ruby

class PriorityTargets
  class PlayerAction
    SHOOT = 'S'
    DODGE = 'D'
    PREPARE_GRENADE = 'P'
    THROW_GRENADE = 'T'
    NOTHING = 'N'
    attr_accessor :action, :target

    def initialize(action_string)
        @action = action_string[0, 1]
        @target = self.has_target? ? action_string[1, 1].to_i : false
    end

    def to_s
      string = @action
      string << @target.to_s if self.has_target?
      string
    end

    def has_cooldown?
      [SHOOT].include? @action
    end

    def is_aggressive?
      [SHOOT, PREPARE_GRENADE, THROW_GRENADE].include? @action
    end

    def has_target?
      [SHOOT, DODGE, THROW_GRENADE].include? @action
    end
  end


  class Player
    attr_reader :identifier, :health, :history
    attr_accessor :playstyles

    def initialize(player_identifier, player_string)
      @identifier = player_identifier
      @playstyles = []

      player_info = player_string.split(',')
      @health = player_info.shift.to_i
      @history = parse_history(player_info)
    end


    def has_attacked?(player, round = nil)
      round ||= self.history.length - 1
      player.history[0, round].each do |turn|
        did_attack = true and break if turn.is_aggressive? && turn.has_target? && turn.target == player.identifier
      end
      did_attack ||= false
    end

    def is_holding_grenade?(round = nil)
      round ||= self.history.length
      turn_history = self.history[0, round]
      is_holding = false

      turn_history.each_with_index do |turn, curr_round|
        if turn.action == PlayerAction::PREPARE_GRENADE && curr_round >= round - 3
          is_holding = true if turn_history.drop(curr_round).select{|turn| turn.action == PlayerAction::THROW_GRENADE }.length == 0
        end
      end

      is_holding
    end

    def is_dead?; self.health <= 0; end
    def is_on_cooldown?
      return false if self.history.length == 0
      self.history.last.has_cooldown?
    end

    def turn_at_round(round); self.history[round-1]; end

    private

      def parse_history(history_array)
        parsed = []
        history_array.each {|action_string| parsed << PlayerAction.new(action_string) }
        parsed
      end
  end

  class PlayerList
    include Enumerable

    def initialize(player_list = [], filter_list = false)
      @list = player_list
      @filter = filter_list if filter_list
    end

    #Enumerable Methods
    def each
      list = @list.select{|player| @filter.include?(player.identifier) } if @filter
      list = @list unless @filter
      list.each {|player| yield(player) }
    end

    def <<(player); @list << player; end
    def [](key)
      player = @list.select{|player| @filter.include?(player.identifier) }[key] if @filter
      player = @list[key] unless @filter
      player
    end

    def length
      list = @list.select{|player| @filter.include?(player.identifier) } if @filter
      list = @list unless @filter
      list.length
    end

    def empty?; self.length == 0; end
    def not_empty?; self.length > 0; end

    def create_filtered_list(player_ids)
      new_player_list = PlayerList.new(@list, player_ids)
      new_player_list
    end

    #PlayerList Methods
    def includes_playstyle?(playstyle)
      (self.with_playstyle(playstyle).length > 0)
    end

    def have_executed_action?(action)
      action_found = false
      self.each {|player| action_found = true and break if player.history.select {|turn| turn.action == action}.length > 0 }
      action_found
    end

    def direct_damages(round = nil)
      round ||= self.first.history.length

      damage_list = {}
      @list.each {|player| damage_list[player.identifier] = 0 }

      if round >= 1
        @list.each do |player|
          player.history[0, round].each_with_index do |turn, curr_round|

            if turn.has_target?
              target_player = @list.select{|curr_player| curr_player.identifier == turn.target }.first
              target_turn = target_player.turn_at_round(curr_round)

              damage_list[turn.target] += 8 if turn.action == PlayerAction::THROW_GRENADE

              if turn.action == PlayerAction::SHOOT
                damage_list[turn.target] += 2 unless target_turn.action == PlayerAction::DODGE && target_turn.target == player.identifier
              end
            end
          end
        end
      end

      damage_list.select! {|key| @filter.include? key } if @filter
      damage_list
    end


    def filtered_with_condition(&condition_block)
      player_ids = []
      self.each {|player| player_ids << player.identifier if condition_block.call(player) }
      create_filtered_list(player_ids)
    end

    def on_cooldown; filtered_with_condition {|player| player.is_on_cooldown?} end
    def not_on_cooldown; filtered_with_condition {|player| !player.is_on_cooldown?} end

    def dead; filtered_with_condition {|player| player.is_dead?} end
    def not_dead; filtered_with_condition {|player| !player.is_dead?} end

    def with_playstyle(playstyle); filtered_with_condition {|player| player.playstyles.include?(playstyle)} end
    def not_with_playstyle(playstyle); filtered_with_condition {|player| !player.playstyles.include?(playstyle)} end

    def with_max_health(round = nil)
      round ||= self.first.history.length
      player_damages = direct_damages(round)
      filtered_with_condition {|player| player_damages[player.identifier] == player_damages.values.min }
    end

    def with_identifier(identifier)
      matches = self.with_identifiers([ identifier ])
      return nil if matches.empty?
      matches.first
    end

    def with_identifiers(identifiers)
      create_filtered_list(identifiers)
    end
  end

  class PlayerTypes
    GRENADIER = :GRENADIER
    COWBOY = :COWBOY
    SKIDDISH = :SKIDDISH
    AGGRESSOR = :AGGRESSOR
    DEFENSIVE = :DEFENSIVE
    ANTI_GRENADIER = :ANTI_GRENADIER
    PLAYSTYLE_ORDER = [GRENADIER, COWBOY, SKIDDISH, AGGRESSOR, DEFENSIVE, ANTI_GRENADIER]

    def initialize(player_list)
      @players = player_list
    end

    def analyze_playstyles
      return if @players.first.history.length == 0

      PLAYSTYLE_ORDER.each do |playstyle|
        check_fnc = "is_"+playstyle.to_s+'?'
        @players.each {|player| player.playstyles << playstyle if self.send(check_fnc, player) }
      end
    end

    def is_GRENADIER?(player)
      #Grenade on first turn
      #Used more than one grenade
      #Never used gun, only grenade
      shoot_count = player.history.count {|turn| turn.action == PlayerAction::SHOOT }
      grenade_count = player.history.count {|turn| turn.action == PlayerAction::PREPARE_GRENADE }

      profiled ||= true if player.history.first.action == PlayerAction::PREPARE_GRENADE
      profiled ||= true if grenade_count > 1
      profiled ||= true if shoot_count == 0 && grenade_count > 0
      profiled ||= false
    end

    def is_COWBOY?(player)
      #Never used grenade, only gun
      shoot_count = player.history.count {|turn| turn.action == PlayerAction::SHOOT }
      grenade_count = player.history.count {|turn| turn.action == PlayerAction::PREPARE_GRENADE }

      profiled ||= true if grenade_count == 0 && shoot_count > 0
      profiled ||= false
    end

    def is_SKIDDISH?(player)
      #Dodged more than once
      #Never hurts anybody
      dodge_count = player.history.count {|turn| turn.action == PlayerAction::DODGE }
      attack_count = player.history.count {|turn| turn.is_aggressive? }

      profiled ||= true if dodge_count > 1
      profiled ||= true if attack_count == 0 && player.history.length > 1
      profiled ||= false
    end

    def is_AGGRESSOR?(player)
      #Only shoots person >= most health
      profiled = false
      player.history.each {|turn| profiled = true if turn.is_aggressive? && turn.has_target? }

      player.history.each_with_index do |turn, round|
        if turn.is_aggressive? && turn.has_target?
          profiled = false if !@players.with_max_health(round).include? @players.with_identifier(turn.target)
        end
      end
      profiled
    end

    def is_DEFENSIVE?(player)
      #Only hurts people who hurt them first
      player.history.each {|turn| profiled = true if turn.is_aggressive? && turn.has_target? }

      player.history.each_with_index do |turn, round|
        if turn.is_aggressive? && turn.has_target?
          target_player = @players.with_identifier(turn.target)
          profiled = false unless target_player.has_attacked?(player, round)
        end
      end
      profiled ||= false
    end

    def is_ANTI_GRENADIER?(player)
      #After a Grenadier has been shown, only shoots grenadier
      shots_fired = 0
      shots_fired_while_holding = 0

      player.history.each_with_index do |turn, round|
        if turn.is_aggressive? && turn.has_target?
          target_player = @players.with_identifier(turn.target)
          shots_fired += 1
          shots_fired_while_holding += 1 if target_player.is_holding_grenade?(round)
        end
      end

      (shots_fired > 0 && shots_fired/2.0 <= shots_fired_while_holding)
    end
  end




  def initialize(game_state)
    players_info = game_state.split(' ')
    @player = Player.new(0, players_info.shift)
    @players = PlayerList.new
    @players << @player
    enemy_identifiers = []

    players_info.each_with_index {|info, index| @players << Player.new(index+1, info); enemy_identifiers << index+1; }

    @enemies = @players.with_identifiers(enemy_identifiers  )
  end

  def analyze_playstyles
    types = PlayerTypes.new(@players)
    types.analyze_playstyles
  end

  def find_dodge_target
    armed_aggressors = @enemies.with_playstyle(PlayerTypes::AGGRESSOR).not_on_cooldown().not_dead()

    if armed_aggressors.not_empty?
      return armed_aggressors.with_max_health().first if @players.with_max_health().include?(@player) && @players.with_max_health().length == 1
    end

    return @enemies[Random.rand(3)] if @player.history.length == 0
    nil
  end

  def find_target
    unarmed_aggressors = @enemies.with_playstyle(PlayerTypes::AGGRESSOR).on_cooldown().not_dead()
    anti_grenadiers = @enemies.with_playstyle(PlayerTypes::ANTI_GRENADIER).not_dead()
    grenadiers = @enemies.with_playstyle(PlayerTypes::GRENADIER).not_dead()
    cowboys = @enemies.with_playstyle(PlayerTypes::COWBOY).not_dead()
    skiddish = @enemies.with_playstyle(PlayerTypes::SKIDDISH).not_dead()
    defensive = @enemies.with_playstyle(PlayerTypes::DEFENSIVE).not_dead()

    if unarmed_aggressors.not_empty?
      return unarmed_aggressors.with_max_health().first if @players.with_max_health().include?(@player) && @players.with_max_health().length == 1
    end

    return anti_grenadiers.with_max_health().first if anti_grenadiers.not_empty?
    return grenadiers.with_max_health().first if grenadiers.not_empty?
    return cowboys.with_max_health().first if cowboys.not_empty?
    return skiddish.with_max_health().first if skiddish.not_empty?
    return defensive.with_max_health().first if defensive.not_empty?
    return @enemies.with_max_health().not_dead().first if @enemies.with_max_health().not_dead().length > 0
    nil
  end

  def find_weapon
    return PlayerAction::THROW_GRENADE if @player.is_holding_grenade?

    anti_grenadiers = @enemies.with_playstyle(PlayerTypes::ANTI_GRENADIER).not_dead()

    return PlayerAction::PREPARE_GRENADE if anti_grenadiers.empty? && @enemies.have_executed_action?(PlayerAction::PREPARE_GRENADE)
    PlayerAction::SHOOT
  end

  def make_decision
    dodge_target = self.find_dodge_target
    target = self.find_target
    weapon = self.find_weapon

    decision ||= PlayerAction.new(PlayerAction::NOTHING) if @player.is_on_cooldown? || @enemies.with_max_health().not_dead().length == 0
    decision ||= PlayerAction.new(PlayerAction::DODGE + dodge_target.identifier.to_s) if dodge_target
    decision ||= PlayerAction.new(weapon + target.identifier.to_s)
    STDOUT.write decision.to_s
  end
end

priority_targets = PriorityTargets.new(ARGV[1])
priority_targets.analyze_playstyles
priority_targets.make_decision

1
나는 당신의 접근 방식을 좋아합니다. 나는 그것이 어떻게 될지를 기대합니다.
overactor

슬프게도 Grenadier를 만든 버그가있는 것 같습니다. 아 잘, 다음 번에 더 잘 할 것입니다 :)
fingerco

3

겁쟁이-펄

매우 비겁하게 행동합니다. 건강하다고 느끼면 기분이 좋지 않은 적을 선택하고 쏴 버립니다. 마지막 턴을당한 적에게 보너스 포인트 ( Nothing이 턴을 하는 것으로 알려져 있기 때문에 방어력이 전혀 없기 때문에). 기분이 좋지 않을 때는 숨을 구하기 위해 엄폐물로 달려 가서 가끔 누군가를 쏴 버립니다.

#!/usr/bin/perl

@allinfo = map { [split/,/] } split / /, $ARGV[1];
@life = map { $_->[0] } @allinfo;
@action = map { @$_>1 ? $_->[-1] : () } @allinfo;

if($life[0] < 3 && rand() < .5 )
{
    printf "D%d", +(sort { ($life[$a]>0)*($action[$a] eq "N") <=> ($life[$b]>0)*($action[$b] eq "N") } 1..3)[2]
}
else
{
    @score = map { $life[$_]>0 ? (5/$life[$_] + 2*($action[$_] =~ /S./)) : 0 } 1..3;
    printf "S%d", +(sort { $score[$a] <=> $score[$b] } 1..3);
}

꽤 표준적인 펄 코드; 파일에 저장 한 다음 실행하십시오 perl file argument argument [...]. 구문을 확인했는데 괜찮 았으므로 아무런 문제가 없기를 바랍니다.

E : 0으로 나눌 가능성을 제거했습니다.


3

봄버맨

R로 작성된 봇, 커맨드 라인은 다음과 같습니다 : Rscript Bomberman.R arg0 arg1
나는이 봇을 작성하기 시작한 후에 Geobits가 이미 수류탄을 만들었다는 것을 깨달았 지만 수류탄을 준비하기 전에 건강이 3 이상임을 확인하고 수류탄을 던졌습니다. 마지막 사수를 먼저, 가장 건강한 두 번째를 기록하고, 체력이 3 미만인 경우 위험한 선수를 피하거나 (마지막 라운드에서 죽거나 사살하지 않음) 남은 선수를 쏴야합니다.

input <- commandArgs(TRUE)
history <- do.call(rbind,strsplit(scan(textConnection(input[2]),"",quiet=TRUE),","))
health <- as.integer(history[,1])
last_shooter <- which(grepl("S",history[-1,ncol(history)]))
last_prepare <- which(history[1,]=="P")
if(!length(last_prepare)) last_prepare <- -1
last_throw <- which(grepl("T",history[1,]))
if(!length(last_throw)) last_throw <- 0
most_healthy <- which.max(health[-1])
dead <- which(health[-1]<=0)
inoffensive <- c(last_shooter,dead)
danger <- which(!(1:3)%in%inoffensive)
alive <- which(!(1:3)%in%dead)
if(health[1]>3 & last_throw > last_prepare) out <- "P"
if(last_throw < last_prepare) out <- ifelse(length(last_shooter),paste("T",last_shooter[1],sep=""),paste("T",most_healthy[1],sep=""))
if(health[1]<=3 & last_throw > last_prepare){
    if(length(danger)){
        out <- paste("D",sample(danger,1),sep="")
    }else{
        out <- paste("S",sample(alive,1),sep="")
    }
}
cat(out)

편집하다

내가 본 모든 로그가 내 봇만 출력한다는 것을 보여 주었으므로이 봇과 컨트롤러간에 약간의 통신 문제가있는 것 같습니다 N. 따라서 여기에 동일한 봇이 있지만 파이썬으로 다시 작성되었습니다.이 또한 통신 문제가 있으면 누군가 볼 수 있기를 바랍니다.
로 호출됩니다 python Bomberman.py arg0 arg1.

import sys,re,random

history = sys.argv[2]
history = [k.split(",") for k in history.split()]
health = [k[0] for k in history]
last_turn = [k[-1] for k in history]
last_shooter = [i for i,x in enumerate(last_turn) if re.search(r'S[0-3]',x)]
last_prepare = [i for i,x in enumerate(history[0]) if x=='P']
if not len(last_prepare):
    last_prepare = [-1]

last_throw = [i for i,x in enumerate(history[0]) if re.search(r'T[0-3]',x)]
if not len(last_throw):
    last_throw = [0]

most_healthy = [i for i,x in enumerate(health) if x==max(health)]
dead = [i for i,x in enumerate(health) if x<=0]
inoffensive = last_shooter+dead
danger = [k for k in range(1,4) if k not in inoffensive]
alive = [k for k in range(1,4) if k not in dead]
if health[0]>3 and last_throw[-1] > last_prepare[-1]:
    out = 'P'

if last_throw[-1] < last_prepare[-1]:
    if len(last_shooter):
        out = 'T'+random.choice(last_shooter)
    else:
        out = 'T'+random.choice(most_healthy)

if health[0]<=3 and last_throw[-1] > last_prepare[-1]:
    if len(danger):
        out = 'D'+random.choice(danger)
    else:
        out = 'S'+random.choice(alive)

print(out)

봇의 이름은 비교적 약하지만, 더 나은 이름을 생각할 수 있다면 의견을 말하십시오 :)
plannapus

GymnastBomber !!
Cruncher

3

네오

마지막 턴을 쏘지 않은 살아있는 플레이어를 피하십시오. 모두가 마지막 턴에 산다면 무작위로 살아있는 선수를 쏴라. 헤드 라이트가 보이면 자살합니다.

import java.util.Random;
public class Neo {
    public static void main(String[] args) {
        if(args.length < 2)
            return;
        String[] list = args[1].split(" ");
        if(list.length < 4)
            return;
        Random rand = new Random();
        int turn = list[0].split(",").length;
        if(turn == 49){
            System.out.print("S0");
            return;
        }
        int target=0;
        for(int i=1;i<4;i++)
            if(list[i].length()<2 || (list[i].charAt(0)!='-' && list[i].charAt(list[i].length()-2)!='S'))
                target=i;
        if(target>0){
            System.out.print("D"+target);
            return;
        }
        while(target<1){
            int i=rand.nextInt(3)+1;
            if(list[i].charAt(0)!='-')
                target=i;
        }
        System.out.print("S"+target);
    }
}

나는 수류탄 척에 대해이 사람으로부터 많은 것을 기대하지 않지만, 저격수에 대해서는 꽤 잘 작동 할 수 있습니다. 우리는 볼 수 있습니다.


내 대답 에 귀하의 상용구 코드 중 일부를 사용했습니다 . 나는 그것이 괜찮기를 바랍니다.
overactor

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1 at java.lang.String.charAt(String.java:658) at Neo.main(Neo.java:17)
es1024

@ es1024 지금 가봐야하고 매 차례마다 아무 것도하지 않습니다.
Geobits

2

24 세기와 반세기

이 Python 항목은 수동 플레이어 또는 공격적인 단일 플레이어 만 남을 때까지 피킹 및 회피 한 다음 촬영을 시작합니다. 지나가는 화성인이 수류탄과 술취한 트럭 운전사를 돌보기를 희망합니다.

내가 잘못한 것이 아니라면 이것은 기능적인 파이썬입니다. 하스켈과 친구들이 저를 발견하기 전에 필자가 쓴 종류의 파이썬처럼 보이지는 않습니다. 그러나 당신이 더 잘 알고 있다면 알려주십시오.

#!/usr/bin/env python
import sys
import random

## ==== Move Types ================================================== ##
def move_type (move):
    if "" == move:
        return "N"
    return move[0]

def is_passive_move (move):
    if "N" == move:
        return True
    if "D" == move_type (move):
        return True
    return False

def is_aggressive_move (move):
    return not is_passive_move (move)

def passive_moves (moves):
    return [m for m in moves if is_passive_move (m)]

def aggressive_moves (moves):
    return [m for m in moves if is_aggressive_move (m)]
## ================================================== Move Types ==== ##

## ==== Player Model ================================================ ##
class Player:
    def __init__ (self, number, health, moves):
        self.number = number
        self.health = health
        self.moves  = moves

    def last_move (self):
        if 0 == len (self.moves):
            return ""
        return self.moves[-1]

def player_from (number, player_string):
    x = player_string.split (",")
    health = int (x[0].strip ())
    moves = [move.strip () for move in x[1:]]

    return Player (number, health, moves)

def players_from (game_state):
    return [player_from (n, p) for (n, p) in
                                   zip (range(4), game_state.split ())]

def is_alive (player):
    return 0 < player.health

def i_am_dead (me):
    return not is_alive (me)

def can_shoot (player):
    return "S" != move_type (player.last_move ())

def is_passive (player):
    passive_move_count = len (passive_moves (player.moves))
    aggressive_move_count = len (aggressive_moves (player.moves))

    return passive_move_count > (aggressive_move_count + 1)

def players_who_can_breathe (players):
    return [p for p in players if is_alive (p)]

def players_who_can_shoot (players):
    return [p for p in players if can_shoot (p)]

def players_who_stand_around (players):
    return [p for p in players if is_passive (p)]
## ================================================ Player Model ==== ##

## ==== Actions ===================================================== ##
def shoot_randomly_at (possible_targets):
    chosen_target = random.choice (possible_targets)
    return "S{0}".format (chosen_target.number)

def dodge_one_of_the (potential_shooters):
    chosen_shooter = random.choice (potential_shooters)
    return "D{0}".format (chosen_shooter.number)

def do_nothing ():
    return "N"

def pick_move (game_state):

    players = players_from (game_state)
    me = players[0]
    enemies = players[1:]

    if i_am_dead (me):
        return do_nothing ()

    living_enemies = players_who_can_breathe (enemies)
    if 1 == len (living_enemies):
        return shoot_randomly_at (living_enemies)

    passive_enemies = players_who_stand_around (living_enemies)
    if len (living_enemies) == len (passive_enemies):
        return shoot_randomly_at (passive_enemies)

    potential_shooters = players_who_can_shoot (living_enemies)
    if 0 < len (potential_shooters):
        return dodge_one_of_the (potential_shooters)

    return do_nothing ()
## ===================================================== Actions ==== ##

if "__main__" == __name__:

    game_state = sys.argv[2]
    print (pick_move (game_state))

다음으로 실행 :

python twenty-fourth-and-a-halfth-century.py 0 "5 5 5 5"

2

깜짝 놀란

이 제출물은 모두를 두려워합니다. 그러나 일부 사람들은 특히 두렵습니다. 그래서 누가 가장 위험한지 알아 내고 쏴 버립니다. 여러 명의 적이 가장 위험한 것처럼 보이면 무작위로 쏴집니다.

import sys
import random


def is_alive(player):
    return int(player.split(",")[0]) > 0


# Anyone with a live grenade who is alive is dangerous
def is_dangerous(player):
    return player.count("P") > player.count("T") and \
        int(player.split(",")[0]) > 0


def health(player):
    return int(player.split(",")[0])


# Failing that, healthy people are dangerous
def danger_rating(player):
    return 6 if is_dangerous(player) else health(player)

enemies = sys.argv[2].split()[1:]

highest_danger = max(danger_rating(enemy) for enemy in enemies)
most_dangerous_enemy = random.choice(
    [enemy_num+1 for enemy_num in range(len(enemies))
     if danger_rating(enemies[enemy_num]) == highest_danger])

print("S"+str(most_dangerous_enemy))

이것은 파이썬입니다 (2 또는 3, 둘 중 하나와 같은 결과). 다른 이름으로 저장 scared.py,로 실행python3 scared.py


2

조작 자식 – 파이썬

수류탄을 준비하고 던졌습니다. 시간이 없다고 생각하거나 적이 너무 적 으면 쏴 버립니다. 그가 혼자라면 그는 다른 사람을 능가하려고한다.

import sys

def health(p):
    return int(p[0])

def is_alive(p):
    return health(p) > 0

def can_act(p):
    return is_alive(p) and p[-1][0] != 'S'

def can_throw(p):
    return is_alive(p) and p[-1][0] == 'P'

def shot_first(p):
    if len(p) == 1:
        return False
    return p[1][0] == 'S'

def act(a):
    print a
    sys.exit(0)

player = sys.argv[2].split()[0].split(',')
enemies = [e.split(',') for e in sys.argv[2].split()[1:]]
healthiest = sorted(enumerate(enemies, 1), key=lambda e:health(e[1]))[-1]
alive = sum(is_alive(e) for e in enemies)

if alive == 1:
    i, e = healthiest
    if health(e) <= 2 and not can_act(e):
        act('S%d' % i)
    if can_throw(player):
        act('T%d' % i)
    if can_throw(e):
        act('S%d' % i)
    if can_act(e) and shot_first(e) and len(player) < 40:
        act('D%d' % i)
    if len(player) > 45:
        act('P')
    act('S%d' % i)

if can_throw(player):
    i, e = healthiest
    act('T%d' % i)

if len(player) > 45:
    act('P')

if health(player) <= 2 or any(can_throw(e) for e in enemies) or alive == 2:
    i, e = healthiest
    act('S%d' % i)

act('P')

2

오사마

나는 하루 동안 이것을 시도해 왔으며, 이제 다른 사람들이 그 동안 어떻게 진화했는지 게시하고 볼 차례입니다.

module Main where

import Data.List
import Data.Ord
import System.Environment

words' "" = []
words' s = s' : words' (tail' s'')
  where
    (s', s'') = break (==',') s
    tail' (',':r) = r
    tail' r = r

nRound = length . words'

lastAction = last . words'

health :: String -> Int
health = read . head . words'

alive = (>0) . health

grenadeAge :: String -> Int
grenadeAge p | not (alive p) = 0
             | otherwise = g 0 $ tail $ words' p
  where
    g n (a:b:r) | head a == 'S' = g (if n>0 then n+2 else 0) r
    g 0 ("P":r) = g 1 r
    g n (('T':_):r) | n>0 = g 0 r
    g n (_:r) | n>0 = g (n+1) r
    g n (_:r) = g n r
    g n [] = n

prepared :: String -> Bool
prepared p = alive p && head (lastAction p) /= 'S'

nShotMe = length . filter (=="S0") . words'

getPlayer = (!!)

action players@(me:them) | not (prepared me) = "S2" -- bogus
                         | nRound me >= 49 = "S0"
                         | grenadeAge me >= 1 = 'T':(show $ maximumBy (comparing (nShotMe . getPlayer players)) l)
                         | any prepared them && nRound me > 0 = 'D':(show $ maximumBy (comparing (nShotMe . getPlayer players)) l)
                         | otherwise = 'S':(show $ maximumBy (comparing (health . getPlayer players)) l)
  where l = filter (alive . (getPlayer players)) [1..3]



main = do
  players <- fmap (words . head . tail) getArgs
  putStrLn $ action players

로 컴파일 한 ghc -O2 osama.hs다음을 사용하여 실행하십시오 ./players/Osama/osama.


2

스나이퍼-루아

첫 턴에는 무작위로 사람을 쏴 죽일 수있는 모든 플레이어를 쏴 버립니다 (2 또는 1 체력). 둘 중 어느 것도 작동하지 않으면 마지막으로 쏜 플레이어를 쏘려고 시도하고, 그렇지 않으면 임의의 플레이어를 쏠 것입니다. 로 실행lua Sniper.lua

turns = arg[2]
health = string.sub(turns, 1, 1)
--make random numbers random
math.randomseed(io.popen("date +%s%N"):read("*all"))
math.random(); math.random(); math.random()
function Split(str, delim, maxNb)
    -- Eliminate bad cases...
    if string.find(str, delim) == nil then
        return { str }
    end
    if maxNb == nil or maxNb < 1 then
        maxNb = 0    -- No limit
    end
    local result = {}
    local pat = "(.-)" .. delim .. "()"
    local nb = 0
    local lastPos
    for part, pos in string.gmatch(str, pat) do
        nb = nb + 1
        result[nb] = part
        lastPos = pos
        if nb == maxNb then break end
    end
    -- Handle the last field
    if nb ~= maxNb then
        result[nb + 1] = string.sub(str, lastPos)
    end
    return result
end
enemies = Split(turns, " ")
--first turn
if #enemies[1] == 1 then
  print(string.format("S%i",math.random(1,3)))
  os.exit()
end
--kills if possible
for enemy=1,3 do
  if (tonumber(string.sub(enemies[enemy + 1],1,1)) or 0) < 3 and string.sub(enemies[enemy + 1],1,1) ~= "-" then
    print(string.format("S%i",enemy))
    os.exit()
  end
end
--shoots the last person that shot at it
for enemy=1,3 do
  if string.sub(enemies[enemy + 1],#enemies[enemy + 1]-1) == "S0" and tonumber(string.sub(enemies[enemy + 1],1,1)) > 0 then
    print(string.format("S%i",enemy))
    os.exit()
  end
end
--otherwise shoot a random alive person
local aliveEnemies = {}
for enemy=1,3 do
  if string.sub(enemies[enemy + 1],1,1) ~= "-" then
    aliveEnemies[#aliveEnemies+1]=enemy
  end
end
print(string.format("S%i",math.random(1,#aliveEnemies)))

실제로 추가 인수로 먼저 실행됩니다. 예를 들어, lua Sniper.lua 3 "5,S1 3,D3 5,N 5,P". arg색인 을 확인해야 할 수도 있습니다 .
comperendinous

@comperendinous, 고마워, 지금 고쳐
waylon531

안녕하세요, @ waylon531, 루아에 대한 질문 : randomseed math.randoms "math.randomseed (os.time ()) math.random (); math.random (); math.random ()"은 무작위로 충분하지 않습니다. 스크립트?
AndoDaan

1
AndoDaan은에 따라 lua-users.org/wiki/MathLibraryTutorial 일부 OS의 항상 ()를 호출 같은 번호에게 처음 인 Math.random를 반환합니다.
waylon531

lua: ./players/Sniper/Sniper.lua:38: attempt to compare nil with number스택 추적 :./players/Sniper/Sniper.lua:38: in main chunk [C]: in ?
es1024

2

다윈

적자 생존은 최소한의 건강은 반드시 죽어야한다는 것을 의미합니다.

이론적 해석

화요일 (12 일)부터 결과 배치를 보면 세 가지 그룹이 있습니다. 생존자; 효과적으로 자살; 쓸모없는 것보다 더 나쁜 생존자들은 간단한 슈팅 기반 전략을 공유합니다. 다른 봇 ( Spock , Coward )은 건강에 가장 좋지 않은 적을 목표로하지만 다른 행동과 전략을 복잡하게 만듭니다. 이건 아닙니다. Simple Shooter 와 마찬가지로 대상을 명확하게 정의하고 끊임없이 고수합니다. 결과에서 어디에 맞는지 보는 것이 흥미로울 것입니다.

#!/usr/bin/env python

import sys
import random

## ==== Player Model ================================================ ##
class Player:
    def __init__ (self, number, health):
        self.number = number
        self.health = health

def player_from (number, player_string):
    x = player_string.split (",")
    health = int (x[0].strip ())

    return Player (number, health)

def players_from (game_state):
    return [player_from (n, p) for (n, p) in
                                   zip (range(4), game_state.split ())]

def is_alive (player):
    return 0 < player.health

def i_am_dead (me):
    return not is_alive (me)

def players_who_can_breathe (players):
    return [p for p in players if is_alive (p)]

def players_by_health (players):
    return sorted (players, key=lambda p: p.health)

def least_healthy_players (players):
    sorted_living_players = \
        players_by_health (players_who_can_breathe (players))
    lowest_living_health = sorted_living_players[0].health
    return [p for p in players if lowest_living_health == p.health]
## ================================================ Player Model ==== ##

## ==== Actions ===================================================== ##
def shoot_randomly_at (possible_targets):
    chosen_target = random.choice (possible_targets)
    return "S{0}".format (chosen_target.number)

def do_nothing ():
    return "N"

def pick_move (game_state):
    players = players_from (game_state)
    me = players[0]
    enemies = players[1:]

    if i_am_dead (me):
        return do_nothing ()

    least_healthy_enemies = least_healthy_players (enemies)
    return shoot_randomly_at (least_healthy_enemies)
## ===================================================== Actions ==== ##

if "__main__" == __name__:

    game_state = sys.argv[2]
    print (pick_move (game_state))

이것은 이전의 Twenty-Fourth and Halfth Century의 탈피하고 약간 수정 된 버전이며 , 그 호출을 공유합니다 :

python darwin.py 3 "5 5 5 5"

2

자에 닐-C

우선 순위 :

  1. 왼쪽이 1 대 1이면 쏴
  2. 수류탄을 쏴
  3. 다지
  4. 아무것도 (혼란하기 위해)

로 컴파일하십시오 gcc <filename.c>.

로 실행하십시오 ./a.out <parameters>.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]){
    char* input = argv[2];
    int enemyCount=1;
    int aliveCount=0;
    int aliveEnemy=0;

    //default
    char action = 'N';
    int target = NULL;

    const char delim[1] = " ";
    char *token;

    //first turn
    if(strcmp(input,"5 5 5 5")==0){
        printf("D1");
        return 0;
    }

    token = strtok(input, delim);
    token = strtok(NULL, delim); //skip to the first enemy

    while(token != NULL){
        //if someone is alive :
        if(strstr(token,"-")==NULL && token[0]!='0'){
            aliveCount++;
            aliveEnemy=enemyCount;
            //if that person did nothing this turn, take it as a tip that he will shoot next turn, and dodge
            if(strstr(token, "N")!=NULL){
                action = 'D';
                target=enemyCount;
            }

            //if that person prepared a grenade, shoot him down
            if(strstr(token, "P")!=NULL){
                action = 'S';
                target=enemyCount;
            }
        }

        token = strtok(NULL, delim);
        enemyCount++;
    }

    //if there is 1 enemy left, shoot him down
    if(aliveCount==1){
        action='S';
        target=aliveEnemy;
    }

    printf(action=='N'?"N":"%c%d",action,target);

    return 0;
}

1
첫 번째 (정수) 인수는 질문에 주어진 예제가지나 가면 반올림 횟수를 나타내지 않습니다. 당신은 스탠드 오프 번호 82에 할당 되었기 때문에 첫 번째 턴에서 자신을 쏘고 싶지 않을 것입니다.
comperendinous

정말? D : @comperendinous에게 감사합니다. 코드를 편집합니다.
Mark Gabriel

2

입력 분석기

이와 같은 게임의 핵심은 모든 상대가 그에 따라 반응하는 방식을 분석하는 것입니다. 내 봇은 복잡한 알고리즘을 사용하여 상대방을 사용하면 결정적인 승리를 거두는 이점을 얻습니다.

편집 : 나는 지금

  1. 수류탄이있는 선수를 피하다
  2. 더 이상 자신을 쏘거나 던지거나 피하려고하지 않습니다.

import System.Environment   
import Data.Char (ord)
import Data.List.Split

main = do 
    args <- getArgs
    let secondArg = (last args)
    let opt = (argCount secondArg 0)
    let list = (splitOn " " secondArg)
    let enemysToCheck = [1,2,3]
    let target = (avoidShootingSelf (findTarget (last args) 0 0 0 0))
    putStrLn (decide list enemysToCheck opt target)

argCount :: String -> Int -> Int
argCount (s:str) i
    |(length str) == 0 = i `mod` 4
    | otherwise = (argCount str (i + (ord s)))

--myPseudo takes number 0-3, and a possible target and translates it to a command 
myPseudo :: Int -> Int -> String
myPseudo 0 b = "S" ++ (show b)
myPseudo 1 b = "D" ++ (show b)
myPseudo 2 b = "P"
myPseudo 3 b = "T" ++ (show b)

decide :: [String] -> [Int] -> Int -> Int -> String
decide [] [] a b = (myPseudo a b)
decide (x:xs) [] a b = (myPseudo a b)
decide xs (y:ys) a b
    | (liveGrenade z 0) == True = "D" ++ (show y)
    | otherwise = (decide xs ys a b)
    where z = xs!!y

--checks if a player has a live grenade
liveGrenade :: String -> Int -> Bool
liveGrenade [] a = a > 0
liveGrenade (s:str) a
    | s == 'T' = (liveGrenade str (a - 1))
    | s == 'P' = (liveGrenade str (a + 1))
    | otherwise = (liveGrenade str a)

--findTarget picks a target by doing some irrelevant string processing on the 2nd argument
findTarget :: String -> Int -> Int -> Int -> Int -> Int
findTarget [] a b c d = ((maximum [a,b,c,d]) `mod` 4)
findTarget (s:str) a b c d
    | s == 'S' = (findTarget str (a + 1) b c d)
    | s == 'D' = (findTarget str a (b + 1) c d)
    | s == 'P' = (findTarget str a b (c + 1) d)
    | s == 'T' = (findTarget str a b c (d + 1))
    | s == 'N' = (findTarget str a b c (d + 1))
    | otherwise = (findTarget str a b c d)

--Makes sure I do target myself takes int 0-3
avoidShootingSelf :: Int -> Int
avoidShootingSelf 0 = 1
avoidShootingSelf a = a

다음 명령으로 봇을 컴파일하십시오 (ghc가 필요함).

ghc-입력 InputAnalyzer.hs

실행할 Shell 명령은 다음과 같아야합니다.

./InputAnalyzer

참고 : Windows에서 테스트 했으므로 컴파일 / 실행과 관련하여 문제가있는 경우 의견을 말해주십시오. 올바른 명령을 찾으려면 최선을 다할 것입니다.


1
글쎄, 이것이 하스켈에서 가중 의사 난수 발생기를 얻는 한 가지 방법이라고 생각합니다.
comperendinous

2

용기라는 개

먼저 나쁜 사람들을 쏴라. 그런 다음 누군가가 수류탄을 준비 할 때까지 무작위로 피하십시오. 그런 다음 모두가 그를 쏠 때 내 수류탄을 준비하고 누군가에게 던지십시오. 그러나 산만 한 사람.

편집 : 이제 생각대로 구현되었습니다. 전에, 점수는 : 35.9

업데이트 : 때때로 회피 대신 촬영

couragethedog.py

import sys
from collections import defaultdict as ddict
from random import choice
args = sys.argv
info = " ".join(args[2:]).strip('"').split(" ")
players = ddict(dict)
for i,s in enumerate(info):
    parts = s.split(",")
    players[i]["health"]=int(parts[0])
    players[i]["last"]=parts[-1]
    players[i]["history"]=parts[1:]
    players[i]["turn"]=len(parts)
me=0
others=[1,2,3]
turn=players[me]["turn"]
alive = filter(lambda p:players[p]["health"]>0,others)
def act():
    if turn is 1:
        return "S%d" % choice(alive)
    if "P" == players[me]["history"][-1]:
        targets = set(alive)
        for i in alive:
            if "P" == players[i]["history"][-2]:
                targets.remove(i)
        return "T%d" % choice(list(targets))
    for i in others:
        if players[i]["history"][-1] is "P":
            return "P"
    if choice([True,False,False]):
        return "S%d" % choice(alive)
    return "D%d" % choice(alive)
print act()

다음으로 실행

python couragethedog.py

2

MAD-자바

MAD 봇은 상호 보장 된 파괴를 통해 협박의 힘을 신뢰합니다 . 준비된 수류탄이 없을 때마다 수류탄을 준비합니다. 그런 다음 누군가가 자신에게 피해를 주려고하거나 수류탄이 폭발 할 때까지 총잡이를 피합니다. 그가 공격을당하는 순간부터, 그는 지금까지이 시합에서 더 많은 데미지를 주려고 시도한 사람에게 수류탄을 s습니다. 수류탄이 폭발하려 할 때, 그는 주요 선수를 폭격합니다. MAD는 수류탄을 피하거나 직접 집어 넣을 것이없고, 그의 수류탄이 여전히 적어도 한 턴에 좋은 경우 누군가에게 총을 쏘는 것에 반대하지 않습니다.

    import java.util.ArrayList;
import java.util.Random;

public class MAD 
{
    public static void main(String[] args) 
    {
        if(args.length < 2)
        {
            return; // nothing to do here
        }
        String[] players = args[1].split(" ");
        if(players.length < 4 || !isAlive(players[0]))
        {
            return; // nothing to do here
        }
        Random rand = new Random();

        int grenadeExplodes = grenadeExplodes(players[0]);        
        if(grenadeExplodes==-1)
        {
            System.out.print("P"); // I don't feel safe without a prepared grenade in my hand
            return;
        }

        int highestDamage = -1;
        int playerToShoot = -1;        
        for(int i=1; i<4; i++) // did anyone try to hit me?
        {
            int damage = damageAttempted(players[i], 0);
            if(isAlive(players[i]) && (damage>highestDamage || (damage==highestDamage && rand.nextDouble()>0.5)))
            {
                highestDamage = damage;
                playerToShoot = i;
            }           
        }

        if(highestDamage > 0)
        {
            System.out.print("T" + Integer.toString(playerToShoot)); // don't tell me I didn't warn you
            return;
        }

        int highestHealth = -1;
        int healthiestPlayer = -1;      
        for(int i=1; i<4; i++) // who is doing too well for their own good?
        {
            int health = getHealth(players[i]);
            if(health>highestHealth || (health==highestHealth && rand.nextDouble()>0.5))
            {
                highestHealth = health;
                healthiestPlayer = i;
            }
        }

        if(grenadeExplodes==0)
        {
            System.out.print("T" + Integer.toString(healthiestPlayer).charAt(0)); // get this hot head outta here!!
            return;
        }

        // I've got time to flaunt my grenade around

        ArrayList<Integer> playersToDodge = new ArrayList<Integer>();       
        for(int i=1; i<4; i++) // lets see who could shoot me
        {
            if(canMove(players[i]) && grenadeExplodes(players[i])!=0)
            {
                playersToDodge.add(i);
                if(grenadeExplodes(players[i])==-1) // players who have no grenade are more likely to shoot
                {
                    playersToDodge.add(i);
                }
            }
        }

        if(playersToDodge.size()>0)
        {
            System.out.print("D" + Integer.toString(playersToDodge.get(rand.nextInt(playersToDodge.size() - 1))).charAt(0)); // what do we say to would-be gunners?
            return;
        }

        if(grenadeExplodes!=1)
        {
            System.out.print("S" + Integer.toString(healthiestPlayer).charAt(0)); // seems like I can take a free shot at someone
        }
        else
        {
            System.out.print("N"); // wouldn't want to end up with an exploding grenade in my hand while being unable to throw it.
        }

    }

    public static boolean isAlive(String player) 
    {
        return player.charAt(0)!='-'; 
    }

    public static boolean canMove(String player)
    {
        return isAlive(player) && player.charAt(player.length()-2)!='S';
    }

    public static int grenadeExplodes(String player)
    {
        String[] actions = player.split(",");

        if(actions.length>3 && actions[actions.length - 3].charAt(0)=='P' 
            && actions[actions.length - 2].charAt(0)=='T' 
            && actions[actions.length - 1].charAt(0)=='P')
        {
            return 0;
        } 
        else if(actions.length>2 && actions[actions.length - 2].charAt(0)=='P' 
            && actions[actions.length - 1].charAt(0)=='T')
        {
            return 1;
        } 
        else if(actions.length>1 && actions[actions.length - 1].charAt(0)=='P')
        {
            return 2;
        }
        else
        {
            return -1;
        }
    }

    public static int damageAttempted(String player, int target)
    {
        String[] actions = player.split(",");
        int damage = 0;
        char targetChar = Integer.toString(target).charAt(0);
        for(int i=0; i<actions.length; i++)
        {
            if(actions[i].charAt(0)=='S' && actions[i].charAt(1)==targetChar)
            {
                damage += 2;
            } 
            else if (actions[i].charAt(0)=='T')
            {
                if(actions[i].charAt(1)==targetChar)
                {
                    damage += 8;
                }
                else
                {
                    damage += 3;
                }
            }
        }

        return damage;
    }

    public static int getHealth(String player)
    {
        return Integer.parseInt(player.split(",")[0]);
    }
}

이 봇은 성능이 좋지 않지만 어쨌든 아이디어가 마음에 들었습니다. MAD는 다른 봇의 행동을 기록하는 스마트 한 봇과 4 개의 봇 사이에서 더 많은 경기를하는 분야에서 더 잘 수행 할 것입니다.


일부 신용 shoudl은 Geobits로 가서 그의 Neo 항목의 보일러 플레이트 코드를 훔쳤습니다.
overactor

당신은 많은 신용을 필요로하지 않았다 :)
Geobits

호출 java MAD 43 "5 5 5 5"하면 아무것도 출력되지 않는 것 같습니다.
es1024

2

사디스트

파이썬

그의 우선 순위는 통증과 수류탄을 유발하는 것입니다. 그는 첫 턴을 당깁니다. 그는 당신이 공격 할 수 없을 때 죽이고 싶어합니다. 그는 지배를 연장하기 위해 회피하고 당겨서 SSS (단일 단순 사수)로 장난감을 가지고 있습니다. 그는 아무에게도하지 않은 사람을 먼저 공격하기로 결정했습니다.

수류탄을 사용하기 때문에, 그 (그리고 다른 모든 사람)는 일반적으로 두 번째 또는 세 번째 라운드에서 살아남지 못할 것입니다. 그가 다른 수류탄과 짝을 이루면 모두 죽을 것입니다. 이것은 내가 이길 것으로 기대하지는 않지만 파이썬을 배우기 위해 이것을 썼다는 것을 의미합니다 (이전에 사용한 적이 없으며 새로운 언어에 대해 소개하려고합니다). 다른 "풀 우선"이 있으므로 너무 단순하다고 생각되면 알려주십시오. 그러나 다른 사람들은 기꺼이 당기고 회피하는 것처럼 보이지 않습니다.

import sys    

def ident(thatguy):

    return int(thatguy.split(",")[0])

def health(thatguy):
    return int(thatguy.split(",")[1])

def shooter(thatguy):
    if(len(thatguy.split(","))<3):
        return 1==1
    else: return thatguy.split(",")[2][0]=="S"

def mosthealth(group):
    bigbad=group[0]
    for foe in group:
        if (health(foe)>health(bigbad)): bigbad=foe
    return bigbad

def igotanuke(mine):
    return mine.count("P")-mine.count("T")>0

def guytonuke(allguys,fighters):
    backup=allguys[:]
    for Aguy in backup:
        if(health(Aguy)<4):
            allguys.remove(Aguy)
            if (shooter(Aguy)): fighters.remove(Aguy)

    if(len(allguys)==0): return mosthealth(backup)
    if (len(allguys)==len(fighters)):
        return mosthealth(allguys)
    else:
        for fighter in fighters: allguys.remove(fighter)
        return mosthealth(allguys)

raw = sys.argv[2]
player = raw.split(" ")
thisisme=player.pop(0)
turn = len(player[0].split(","))-1

guys=[]
gunners=[]
c=1
for dude in player:
    dude=str(c)+","+dude
    c+=1
    if (health(dude)>0): 
        guys.append(dude)
        if (shooter(dude)):
            gunners.append(dude)

if (turn==0): print "P"
elif(turn==49): print"S0"
elif(igotanuke(thisisme))&( turn % 2 == 1): print "T"+str(ident(guytonuke(guys,gunners)))
elif(len(guys)<2)&(len(gunners)>0) & (turn % 2 == 1): print P
elif(turn % 2 == 0) & (len(gunners)>0): print "D"+str(ident(mosthealth(gunners)))
elif(turn % 2 == 1) & (len(gunners)>0): print "S"+str(ident(mosthealth(gunners)))
else: print "S"+str(ident(mosthealth(guys)))

나는 그것이 효과가 있다고 생각하지 않습니다 raw_input. sys.argv[2]파이썬 항목에 대한 합의 인 것 같습니다. 에 대한 사용을 찾을 수도 있습니다 . 그러면 더 간단 pop하게 압축 할 수 있습니다 . thisisme=player[0];player.remove(player[0])thisisme=player.pop(0)
comperendinous

@comperendinous Ideone에서 코드를 테스트하고 있었고 sys.argv가 전혀 작동하지 않습니다 (sys 가져 오기로 인해). 그래서 내가 raw_input을 사용했습니다. 후자가 작동하지 않는 차이가 있습니까? 그렇다면 파이썬 용 다른 온라인 컴파일러를 찾아야 할 것입니다. 팝으로 제안 해 주셔서 감사합니다! 나는 그 명령으로 인덱스를 지정할 수 있다는 것을 몰랐다. 향후 파이썬 코드에 사용할 것입니다.
kaine

1
raw_input에서 가져 STDIN오지만 플레이어 기록은 명령 줄 인수로 프로그램에 전달되므로 sys.argv. 테스트를 위해를 사용하여 수동으로 설정할 수 있습니다 sys.argv = ["sadist.py", "0", "5 5 5 5"]. 그런 다음에 전화 할 수 있어야합니다 player=sys.argv[2].split(). 가져 오기가 sys실제로 불가능한 경우 테스트를 위해 점을 삭제하고 배열을 호출 할 수도 sysargv있습니다. 다른 모든 것이 작동하고 sys.argv제출에서 다시 돌아가는 한 괜찮습니다.
comperendinous

@comperendinous는 sys.argv를 호출하면 0의 프로그램 이름, 1의 단일 번호 및 2의 실제 부분을 배열로 반환합니까? 그들은 모두 문자열입니다. 그 정보로 나는 그것을 적절히 편집 할 수 있어야한다. 대단히 감사합니다!
kaine
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.