Piloto de teste • Discussão do desafio • Enviar aventureiro
( Fonte da imagem )
Vários aventureiros rivais estão invadindo as ruínas em busca de tesouros, mas eles só podem carregar muito de cada vez e têm seus limites de resistência. Eles querem obter o tesouro mais valioso e sair antes que fiquem cansados demais para continuar. Eles estão tentando ficar o mais ricos possível com suas travessuras de saques.
Jogabilidade
Cada aventureiro começa na primeira sala da masmorra com 1000 pontos de resistência e 50 kg de espaço na mochila.
O jogo funciona em turnos, com todos os jogadores resolvendo seus turnos simultaneamente. A cada turno, você pode executar uma das seguintes ações:
- Mover para a próxima sala.
- Mover para a sala anterior.
- Ofereça resistência para pegar um tesouro.
- Largue um tesouro.
Mover-se entre os quartos exige 10 pontos de resistência, mais 1 por cada 5 kg atualmente em sua mochila, arredondados. Por exemplo, um aventureiro carregando 3kg de tesouro requer 11 resistência para se mover e um carregando 47kg requer 20 resistência para se mover.
Soltar um tesouro requer 1 ponto de resistência, independentemente do tesouro descartado.
Ao sair das ruínas, o jogador não realiza mais turnos.
Se um jogador não puder realizar nenhuma dessas ações (devido à falta de resistência ou ausência de tesouros), seu aventureiro morre de exaustão, despejando seu tesouro na sala atualmente ocupada. Da mesma forma, se um jogador tentar fazer uma ação inválida, seu aventureiro será morto por uma armadilha, resultando no mesmo derramamento de tesouro.
Licitação
A oferta mínima para um tesouro é de 1 resistência por 1 kg que o tesouro pesa. Você também pode oferecer pontos de resistência adicionais para ter mais chances de obter o tesouro. O vigor que foi oferecido é consumido, independentemente do resultado.
No caso de vários jogadores oferecerem o mesmo tesouro, o jogador que fizer o lance mais alto receberá o tesouro. Se mais de um jogador fez a oferta mais alta, nenhum deles receberá o tesouro.
Condição da vitória
O jogador com o maior valor total de tesouros é o vencedor. No improvável evento de empate, os empates têm o menor peso total, o menor número de tesouros e o valor do tesouro mais valioso, o segundo mais valioso, o terceiro ... até que o empate seja quebrado. No evento quase impossível de que ainda haja um empate nesse momento, o piloto de teste diz "estrague tudo" e o vencedor é, assim, determinado arbitrariamente.
No contexto do torneio, os jogadores serão classificados com o primeiro lugar recebendo 10 pontos, o segundo lugar com 9 pontos, o terceiro lugar com 8 pontos, etc ..., com jogadores mortos e aventureiros sem tesouros marcando 0 pontos.
Sobre as ruínas
- Cada quarto contém inicialmente entre e tesouros. (Onde é o número do quarto)
- Existem arbitrariamente muitos quartos, limitados apenas pela resistência e vontade de explorar dos aventureiros.
- Cada tesouro terá um valor monetário (em dólares inteiros) e um peso (em kg inteiros).
- Os tesouros tendem a ser mais valiosos e abundantes à medida que você se aprofunda nas ruínas.
- As fórmulas específicas para gerar tesouros são as seguintes: (usando a notação para de dados)
- O peso é gerado primeiro usando a fórmula (mínimo de 1)
- O valor do tesouro é gerado através de (onde é o número do quarto é o peso)
Informações visíveis para jogadores
A cada turno, os jogadores recebem as seguintes informações:
- O número da sala em que estão atualmente. Isso é indexado em 1; portanto, conceitualmente, a saída está na "sala 0"
- Uma lista de tesouros atualmente na sala
- Uma lista de outros jogadores que também estão atualmente na sala.
- Seu inventário atual de tesouros
- Seu nível atual de resistência
Codificação
O driver de teste pode ser encontrado aqui .
Você deve implementar uma subclasse desta Adventurer
classe:
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
Você só precisa substituir o get_action
método. enter_ruins
é executado antes do início do jogo e é sua chance de preparar o que você deseja que esteja pronto para o jogo. Você não precisa substituir __init__
, e realmente não deveria . Se __init__
falhar, você será desqualificado.
get_action
recebe um único argumento que é a namedtuple
com os seguintes campos (nessa ordem, se você preferir desestruturar):
room
: o número da sala em que você está atualmentetreasures
: a lista de tesouros na salaplayers
: a lista de outros jogadores na sala. Você só recebe o nome do jogador dessa maneira, então você não sabe qual bot está controlando eles ou seu inventário / resistência.inventory
: a lista de tesouros na sua mochilastamina
: seu nível atual de resistência
Este objeto também fornece duas propriedades de utilitário:
carry_weight
: o peso total de todos os tesouros que você está carregandototal_value
: o valor total de todos os tesouros que você está carregando
As listas treasures
e inventory
contêm namedtuple
s com estes atributos:
name
: o nome do tesouro (para fins cosméticos)value
: o valor monetário do tesouro em $.weight
: peso do tesouro em kg
get_action
deve retornar um dos seguintes valores / padrões:
'next'
ou'previous'
para ir para as salas seguintes / anteriores'take', <treasure index>, <bid>
(sim, como uma tupla, embora qualquer sequência também funcione tecnicamente) para licitar no tesouro no índice especificado na lista de tesouros da sala. Ambos os argumentos devem ser inteiros. Os carros alegóricos serão arredondados para baixo.'drop', <inventory index>
para largar o tesouro carregado encontrado no índice fornecido. O índice deve (naturalmente) ser um número inteiro.
Outras Restrições
- Você só pode usar a instância aleatória fornecida a você durante a inicialização para pseudo-aleatoriedade.
- Qualquer outra coisa que possa introduzir não determinismo comportamental não é permitida. A intenção aqui é fazer com que os bots se comportem de forma idêntica quando recebem a mesma semente para ajudar no teste de novos bots (e potencialmente bugs no driver de teste). Somente a radiação cósmica deve causar algum desvio / não-determinismo.
- Lembre-se de que os códigos de hash são randomizados no Python 3, portanto, o uso
hash
para qualquer tomada de decisão não é permitido.dict
s são bons mesmo quando se usa ordem de iteração para decisões, pois a ordem é garantida de forma consistente desde o Python 3.6.
- Você não pode contornar o driver de teste usando
ctypes
hacks ouinspect
empilhar vodu (ou qualquer outro método). Existem algumas coisas impressionantemente assustadoras que você pode fazer com esses módulos. Por favor não.- Cada bot tem uma caixa de areia razoavelmente bem através de cópias defensivas e da imutabilidade natural de
namedtuple
s, mas existem algumas brechas / explorações inatacáveis. - Outra funcionalidade
inspect
ectypes
pode ser usada desde que nenhuma seja usada para contornar a funcionalidade do controlador. - Qualquer método de captura de instâncias dos outros bots no seu jogo atual não é permitido.
- Cada bot tem uma caixa de areia razoavelmente bem através de cópias defensivas e da imutabilidade natural de
- Os bots devem operar sozinhos e não podem se coordenar com outros bots de forma alguma para qualquer finalidade. Isso inclui a criação de dois bots com objetivos diferentes, de modo que um se sacrifique pelo sucesso do outro. Quando houver mais de 10 competidores, você não terá a garantia de ter os dois bots no mesmo jogo e os nomes dos aventureiros não darão nenhuma indicação da classe de bot, portanto esses tipos de estratégias são limitadas de qualquer maneira.
- No momento, não há nenhuma restrição rígida no tempo de execução, no entanto, eu me reservo o direito de restringi-lo no futuro se os torneios começarem a demorar muito. Seja razoável e tente manter o processamento de turnos abaixo de 100ms , pois não prevejo a necessidade de restringi-lo abaixo desse limite. (Os torneios ocorrerão em cerca de 2 horas se todos os bots demorarem cerca de 100 ms por turno.)
- Sua classe de bot deve ser nomeada exclusivamente entre todos os envios.
- Você pode não se lembrar de nada entre os jogos. (No entanto, você pode se lembrar de coisas entre turnos )
- Não edite sys.modules. Qualquer coisa fora das variáveis de instância deve ser tratada como uma constante.
- Você não pode modificar o código de nenhum bot programaticamente, incluindo o seu.
- Isso inclui excluir e restaurar seu código. Isso é para tornar a depuração e os torneios mais dinâmicos.
- Qualquer código que cause falha no controlador será imediatamente desqualificado. Embora a maioria das exceções seja detectada, algumas podem passar despercebidas e as segfaults são inalcançáveis. (Sim, você pode segfault em Python graças a
ctypes
)
Submissões
Para ajudar na raspagem da resposta, indique o nome do seu bot na parte superior da resposta com ae #Header1
garanta que sua resposta inclua pelo menos um bloco de código (somente o primeiro em sua resposta será usado). Você não precisa incluir nenhuma importação ou documentação, pois elas serão adicionadas automaticamente pelo raspador.
Estarei mais inclinado a votar novamente com explicações detalhadas e compreensíveis. É provável que outros se comportem da mesma maneira.
Grosso modo, sua resposta deve ser formatada da seguinte forma:
# Name of Bot
Optional blurb
#imports go here
class BotName(Adventurer):
#implementation
Explanation of bot algorithm, credits, etc...
(processado como)
Nome do Bot
Destaque opcional
#imports go here class BotName(Adventurer): #implementation
Explicação do algoritmo de bot, créditos, etc ...
Executando o driver de teste localmente
Você precisará do Python 3.7+ e eu recomendo que você instale também tabulate
via pip. Raspar esta página para envios requer adicionalmente lxml
e requests
. Você também deve usar um terminal com suporte para escapes de cores ANSI para obter melhores resultados. Informações sobre como configurar isso no Windows 10 podem ser encontradas aqui .
Adicione seu bot a um arquivo em um subdiretório no mesmo diretório que ruins.py
( ruins_bots
por padrão) e não se esqueça de adicionar from __main__ import Adventurer
à parte superior do módulo. Isso é adicionado aos módulos quando o raspador baixa o seu envio e, embora seja definitivamente hacky, esta é a maneira mais direta de garantir que seu bot tenha acesso adequado Adventurer
.
Todos os bots nesse diretório serão carregados dinamicamente no tempo de execução, portanto, nenhuma alteração adicional será necessária.
Torneio
O vencedor final será determinado em uma série de jogos com até 10 bots em cada jogo. Se houver mais de 10 envios no total, os 10 melhores bots serão determinados dividindo-os sistematicamente em grupos de 10 até que cada bot jogue (exatamente) 20 jogos. Os 10 melhores bots serão selecionados deste grupo com redefinições de pontuação e jogarão até que o bot do primeiro lugar tenha alcançado uma vantagem de 50 pontos sobre o bot do segundo lugar ou até que 500 jogos tenham sido jogados.
Até que haja pelo menos 10 inscrições, vagas vazias serão preenchidas com "Bêbados", que vagam aleatoriamente pelas ruínas e pegam (e ocasionalmente jogam) tesouros aleatórios até que fiquem sem energia e precisem seguir para a saída.
Os torneios serão repetidos semanalmente se houver novos envios. Este é um desafio KOTH aberto, sem data final definida.
Entre os melhores
A partir de quarta-feira, 4 de maio de 2019 às 16h25 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
Atualização - 15 de abril: algumas atualizações / esclarecimentos de regras
Atualização - 17 de abril: banindo alguns casos notáveis de ações nefastas, como modificar o código de outros bots.
Atualização - 4 de maio: Recompensa concedida a Sleafar por destruir absolutamente para trás. Parabéns!
pip
instalado e ativado PATH
(o que é padrão para instalações mais recentes do AFAIK), a partir do Windows, você pode executar pip install modulename
no prompt de comando. Para outras circunstâncias (das quais não conheço), vá para o pip , procure o módulo necessário e escolha uma opção.