테스트 드라이버 • 챌린지 토론 • 모험가 제출
( 이미지 소스 )
몇몇 라이벌 모험가들은 보물을 위해 폐허를 습격하고 있지만, 한 번에 많은 양을 운반 할 수 있으며 지구력의 한계를 가지고 있습니다. 그들은 가장 귀중한 보물을 얻고 너무 피곤해지기 전에 나가기를 원합니다. 그들은 약탈하는 세 나니 간에서 가능한 한 부자가 되려고 노력하고 있습니다.
게임 플레이
각 모험가는 1000 개의 체력 포인트와 50kg의 백팩 공간으로 지하 감옥의 첫 방에서 시작합니다.
이 게임은 턴 기반 방식으로 작동하며 모든 플레이어는 턴을 동시에 해결합니다. 매번 다음 작업 중 하나를 수행 할 수 있습니다.
- 다음 방으로 가십시오.
- 이전 방으로 이동하십시오.
- 체력을 쌓아 보물을 가져 가라.
- 보물을 버려라.
방 사이를 이동하려면 10 개의 체력과 현재 배낭에있는 5kg 당 1을 반올림해야합니다. 예를 들어, 3kg의 보물을 가지고 다니는 모험가에게는 움직이기 위해 11의 체력이 필요하고, 47kg의 나르기에 이동하려면 20의 체력이 필요합니다.
보물을 떨어 뜨리려면 보물을 떨어 뜨려도 체력이 1이 필요합니다.
폐허를 빠져 나가면 플레이어는 더 이상 회전을하지 않습니다.
플레이어가 체력이 부족하거나 보물이 없기 때문에 이러한 행동을 할 수 없다면 모험가는 소진되어 사망 한 보물을 현재 점유중인 방에 쏟아 부었습니다. 마찬가지로, 플레이어가 유효하지 않은 행동을 시도하면, 모험가는 대신 함정에 의해 죽게되어 같은 보물 유출이 발생합니다.
입찰
보물에 대한 최소 입찰은 보물의 무게가 1kg 당 1 체력입니다. 보물을 획득 할 가능성이 더 높은 스태미나 포인트를 추가로 입찰 할 수도 있습니다. 입찰 된 체력은 결과가 무엇이든 상관없이 소비됩니다.
여러 플레이어가 같은 보물을 가져 가려고 입찰 한 경우 가장 높은 입찰을 한 플레이어가 보물을 얻습니다. 둘 이상의 플레이어가 최고 입찰을 한 경우, 아무도 보물을받지 못합니다.
승리 조건
보물의 총 가치가 가장 큰 플레이어가 승자입니다. 혹시 동점 인 경우, 동점은 가장 작은 총 중량, 가장 적은 수의 보물, 가장 중요한 보물의 가치, 두 번째로 가장 가치있는, 세 번째로 연결됩니다. 이 시점에서 여전히 동점이있는 거의 불가능한 상황에서, 테스트 드라이버는 "나사"라고 말하고 승자는 임의로 결정됩니다.
토너먼트의 맥락에서, 플레이어는 10 점을받는 1 등, 9 점을 가진 2 등, 8 점을 가진 3 등 등으로 순위가 매겨 질 것입니다.
폐허에 대하여
- 각 방에는 처음에 과 보물이 있습니다. ( 은 방 번호입니다)
- 모험가의 체력과 탐험 의지에 의해서만 제한되는 임의로 많은 방이 있습니다.
- 각 보물은 금전적 가치 ($)와 무게 (kg)입니다.
- 유적에 깊이 들어가면 보물은 더 가치 있고 풍성한 경향이 있습니다.
- 보물을 생성하는 구체적인 공식은 다음과 같습니다. ( 주사위 롤에 표기법 사용 )
- 공식 (최소 1)를 사용하여 가중치가 먼저 생성됩니다.
- 그런 다음 통해 보물 값이 생성됩니다 (여기서 은 방 번호이고 는 무게입니다)
플레이어에게 공개되는 정보
매 턴마다 플레이어는 다음 정보를 얻습니다.
- 현재있는 방의 수입니다. 이것은 1- 인덱스이므로 개념적으로 출구는 "방 0"에 있습니다.
- 현재 방에있는 보물 목록
- 현재 룸에있는 다른 플레이어의 목록입니다.
- 현재 보물 목록
- 현재 체력 수준
코딩
이 Adventurer
클래스 의 서브 클래스를 구현해야합니다 .
class Adventurer:
def __init__(self, name, random):
self.name = name
self.random = random
def get_action(self, state):
raise NotImplementedError()
def enter_ruins(self):
pass
get_action
메소드 를 대체하기 만하면됩니다. enter_ruins
게임을 시작하기 전에 실행되며 원하는 게임을 준비 할 수있는 기회입니다. 재정의 할 필요가 없으며 __init__
실제로 는 안됩니다 . 귀하의 경우 __init__
충돌, 당신은 실격 처리됩니다.
get_action
namedtuple
다음 필드를 가진 단일 인수를받습니다 (구조화 를 선호하는 경우이 순서대로).
room
: 현재있는 방의 수treasures
: 방에있는 보물 목록players
: 방에있는 다른 플레이어의 목록. 당신은 이런 식으로 플레이어 이름을 얻습니다. 그래서 당신은 봇이 그들을 제어하거나 그들의 인벤토리 / 스태미너를 알지 못합니다.inventory
: 배낭에 담긴 보물 목록stamina
: 현재 체력 수준
이 객체는 두 가지 유틸리티 속성을 추가로 제공합니다.
carry_weight
: 당신이 가지고있는 모든 보물의 총 무게total_value
: 당신이 가지고있는 모든 보물의 총 가치
treasures
및 inventory
목록이 포함되어 namedtuple
이러한 특성으로들 :
name
: 보물의 이름 (화장 용)value
: 보물의 금전적 가치 $.weight
: 보물의 무게 (kg)
get_action
다음 값 / 패턴 중 하나를 반환해야합니다.
'next'
또는'previous'
다음 / 이전 방으로 이동'take', <treasure index>, <bid>
(예, 어떤 순서로든 기술적으로도 효과가 있지만 튜플로서) 방의 보물 목록에 주어진 색인에서 보물에 입찰하는 것입니다. 두 인수는 모두 정수 여야합니다. 수레는 반올림됩니다.'drop', <inventory index>
주어진 색인에서 발견 된 소지품을 버립니다. 색인은 자연스럽게 정수 여야합니다.
기타 제한 사항
- 의사 난수를 위해 초기화하는 동안 제공된 임의 인스턴스 만 사용할 수 있습니다.
- 행동 비결정론을 유발할 수있는 어떤 것도 허용되지 않습니다. 여기서 새로운 봇 (및 테스트 드라이버의 잠재적 버그)을 테스트 할 수 있도록 동일한 시드가 제공 될 때 봇이 동일하게 동작하도록 의도합니다. 우주 방사선 만이 편차 / 비결정론을 유발해야합니다.
- 해시 코드는 Python 3에서 무작위로 생성되므로
hash
의사 결정에 사용할 수 없습니다.dict
파이썬 3.6부터 순서가 일관성을 보장했기 때문에 의사 결정에 반복 순서를 사용할 때도 괜찮습니다.
ctypes
해킹이나inspect
스택 부두 (또는 다른 방법)를 사용하여 테스트 드라이버를 피할 수 없습니다 . 해당 모듈로 할 수있는 무서운 일이 있습니다. 제발 하지마- 각 봇은 방어 카피와
namedtuple
s 의 자연적인 불변성을 통해 합리적으로 잘 샌드 박스 처리 되지만 패치 할 수없는 허점 / 공격이 있습니다. - 기타의 기능
inspect
과ctypes
만큼도 사용될 수있다을 우회하기 컨트롤러 기능에 사용된다. - 현재 게임에서 다른 봇의 인스턴스를 잡는 방법은 허용되지 않습니다.
- 각 봇은 방어 카피와
- 봇은 단독으로 작동해야하며 어떤 목적 으로든 다른 봇과 조정할 수 없습니다. 여기에는 다른 목표를 가진 두 개의 봇을 만들어 다른 하나의 성공을 위해 하나를 희생하는 것이 포함됩니다. 경쟁자가 10 명 이상이면 실제로 동일한 게임에서 두 개의 봇이 있다고 보장 할 수 없으며 모험가 이름은 봇 클래스를 표시하지 않으므로 이러한 유형의 전략은 어쨌든 제한됩니다.
- 현재 실행 시간에 대한 엄격한 제한은 없지만 토너먼트가 너무 오래 걸리기 시작하면 향후에 제한 할 수있는 권리가 있습니다. 이 임계 값 이하로 제한 할 필요가 없으므로 합리적이고 턴 처리를 100ms 미만으로 유지 하십시오 . (모든 봇이 턴당 약 100ms를 소요하면 토너먼트는 약 2 시간 내에 실행됩니다.)
- 봇 클래스는 모든 제출물 중에서 고유하게 이름을 지정해야합니다.
- 게임 사이에 아무 것도 기억 나지 않을 수 있습니다. (단, 턴 사이의 것을 기억할 수 있습니다 )
- sys.modules를 편집하지 마십시오. 인스턴스 변수 이외의 것은 상수로 취급해야합니다.
- 자신의 코드를 포함하여 프로그래밍 방식으로 봇 코드를 수정할 수 없습니다.
- 여기에는 코드 삭제 및 복원이 포함됩니다. 이것은 디버깅과 토너먼트를보다 능률화하기위한 것입니다.
- 컨트롤러 충돌을 일으키는 모든 코드는 즉시 실격됩니다. 대부분의 예외는 잡히지 만 일부는 빠져 나갈 수 있으며 segfault는 잡을 수 없습니다. (예, Python 덕분에 segfault를 사용할 수 있습니다
ctypes
)
제출물
답변 스크래핑을 돕기 위해 답변 상단에 봇 이름을 표시하고 #Header1
답변에 하나 이상의 코드 블록이 포함되어 있는지 확인합니다 (답변의 첫 번째 코드 블록 만 사용됨). 가져 오기 또는 문서 문자열은 스크레이퍼에 의해 자동으로 추가되므로 가져 오기 또는 문서화 문자열을 포함 할 필요가 없습니다.
자세하고 이해하기 쉬운 설명으로 답변을 찬성하는 경향이 있습니다. 다른 사람들도 똑같이 행동 할 것입니다.
대략적으로 말하면 대답은 다음과 같이 형식화되어야합니다.
# Name of Bot
Optional blurb
#imports go here
class BotName(Adventurer):
#implementation
Explanation of bot algorithm, credits, etc...
(로 렌더링)
봇 이름
선택적 블러
#imports go here class BotName(Adventurer): #implementation
봇 알고리즘, 크레딧 등에 대한 설명
로컬로 테스트 드라이버 실행
Python 3.7 이상이 필요하며 tabulate
pip를 통해 설치하는 것이 좋습니다 . 제출이 페이지를 긁어내는 것은 추가로 필요 lxml
하고 requests
. 최상의 결과를 얻으려면 ANSI 색상 이스케이프를 지원하는 터미널을 사용해야합니다. Windows 10에서이를 설정하는 방법에 대한 정보는 여기를 참조하십시오 .
봇을 ruins.py
( ruins_bots
기본적으로)와 같은 디렉토리 내의 하위 디렉토리에있는 파일에 추가 from __main__ import Adventurer
하고 모듈 상단에 추가하십시오 . 이는 스크레이퍼가 제출물을 다운로드 할 때 모듈에 추가되며, 해킹이 확실하지만 봇이에 올바르게 액세스 할 수 있도록하는 가장 간단한 방법입니다 Adventurer
.
해당 디렉토리의 모든 봇은 런타임에 동적으로로드되므로 추가 변경이 필요하지 않습니다.
토너먼트
최고의 승자는 각 게임마다 최대 10 개의 봇을 가진 일련의 게임에서 결정됩니다. 총 제출 횟수가 10 회를 초과하는 경우 모든 봇이 (정확하게) 20 개의 게임을 플레이 할 때까지 상위 10 개의 봇을 10 개의 그룹으로 체계적으로 분할하여 결정합니다. 이 그룹에서 상위 10 개의 봇이 재설정 점수로 선택되며 1 등 봇이 2 등 봇보다 50 점 앞서거나 500 게임이 끝날 때까지 게임을합니다.
출품작이 10 회 이상이 될 때까지 빈 슬롯에는 폐허를 통해 무작위로 방황하고 체력이 떨어지고 출구로 나가야 할 때까지 무작위 보물을 가져가는 (그리고 때때로 떨어 뜨릴 수있는) "Drunkards"가 채워집니다.
토너먼트는 새로운 제출이있을 경우 매주 다시 실행됩니다. 종료 날짜가없는 공개 KOTH 챌린지입니다.
리더 보드
2019 년 5 월 4 일 오후 4시 25 분 MDT에서 실행 : (2019-05-04 4:25 -6 : 00)
Seed: K48XMESC
Bot Class | Score | Mean Score
--------------+---------+--------------
BountyHunter | 898 | 7.301
Scoundrel | 847 | 6.886
Accountant | 773 | 6.285
Ponderer | 730 | 5.935
Artyventurer | 707 | 5.748
PlanAhead | 698 | 5.675
Sprinter | 683 | 5.553
Accomodator | 661 | 5.374
Memorizer | 459 | 3.732
Backwards | 296 | 2.407
업데이트-4 월 15 일 : 몇 가지 규칙 업데이트 / 설명
업데이트-4 월 17 일 : 다른 봇 코드 수정과 같은 악의적 인 행동의 몇 가지 주요 사례를 금지합니다.
업데이트-5 월 4 일 : Sleafar에게 보상금이 수여되었습니다. 축하합니다!