– of crisis and martyrdom
(that's the subtitle because subtitles are cool)
In this king-of-the-hill challenge in python (yup; you need go no farther to know you may not submit in java), you need to create a bot that plays a game very similar to welcome to the dungeon
Game Rules
(note that this is not the original game)
There is a deck, an item set, and some reward cards and death cards. Base HP is 3.
The deck consists of 13 monster cards numbered 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 9
to denote their strengths.
Item List
Demonic pact: Defeat the demon (strength 7 monster), and the monster below it on the dungeon pile. - (just defeats the demon if the demon was the last in the dungeon)
Health potion: When you fall to 0 HP, defeat the monster and return to 3 HP.
Holy grail: Defeat monsters of even-numbered strength (in the game, these are undead). If an even-numbered monster occurs after the demonic pact has been used, that acts first, and you will not get an extra-pact kill after this monster.
Vorpal dagger: Choose one monster before entering the dungeon; this type of monster is defeated. If the targeted monster occurs after the demonic pact has been used, that acts first, and you will not get an extra-pact kill after this monster.
Shield: Add 3 to total HP before spelunking. This does not affect usage of health potion, which will always return health to 3.
Armour: Add 5 to total HP before spelunking. This does not affect usage of health potion, which will always return health to 3.
Reward cards are used to keep track of who has succeeded in the dungeon. Death cards track who has failed in the dungeon.
Drawing Phase
Before the drawing phase begins all monster cards are returned to the deck, both players are restored to 3 HP, and all discarded items are restored such that there is one of each.
The first player decides whether to draw a card from the deck, hiding it from the other player. If so, they must choose to either place it on top of the dungeon pile or discard it along with an item of their choice. Discarded items and cards will be unavailable to either player until the next round.
After player one takes their turn, player two does the same. The players alternately decide whether to draw and what to do with the drawn card, until someone decides not to draw or a player takes the last card from the deck. If a player decides not to draw, or draws the last card, the drawing phase ends and the other player now has to enter the dungeon and begin spelunking.
Spelunking Phase
If the Vorpal dagger has not been discarded, the spelunking player must now decide which card to apply it to. There are no active decisions to be made for the rest of this phase.
The first player takes the top card; that is, the last card placed in the dungeon, and see its strength number. If demonic pact is active from the previous turn, the drawn card is discarded. Otherwise, the player's items will be checked in the order 'demonic pact', 'holy grail', 'Vorpal dagger'. The first un-discarded item capable of defeating the drawn card will then be used, and the card discarded. If demonic pact is used, it will now be active for the next card. The used item is not discarded.
If there is no applicable item available, the strength of the card is subtracted from the player's health. If their health is no longer positive they will be restored to 3 HP and the potion discarded if available, otherwise the dungeon crawl ends and they take a death card.
While the player is not defeated and there are cards remaining in the dungeon, this process of drawing the top card is repeated. Upon successfully defeating all cards in the dungeon the dungeon crawl ends and the spelunking player collects a reward card.
Full Game Description
A game consists of a series of rounds, each having a drawing phase and then a spelunking phase. At the end of each round one player will have collected either a death card or a reward card; once a player accumulates 5 of either type the game ends. If they have 5 death cards they lose the game. If they have 5 reward cards, they win. Either way, the other player receives the opposite result. If neither player has 5 cards of one type, play progresses to the next round and the player who went second in the previous round now goes first and vice versa.
KOTH details
Each bot will play 400 games against every other bot according to the rules described above. Which bot is player one (and so goes first in the first round) alternates each game, and all state is reset between games.
Here are the items again:
Demonic pact: Defeat the demon (strength 7 monster), and the monster below it on the dungeon pile. - (just defeats the demon if the demon was the last in the dungeon)
Health potion: When you fall to 0 HP, defeat the monster and return to 3 HP.
Holy grail: Defeat monsters of even-numbered strength (in the game, these are undead). If an even-numbered monster occurs after the demonic pact has been used, that acts first, and you will not get an extra-pact kill after this monster.
Vorpal dagger: Choose one monster before entering the dungeon; this type of monster is defeated. If the targeted monster occurs after the demonic pact has been used, that acts first, and you will not get an extra-pact kill after this monster.
Shield: Add 3 to total HP before spelunking. This does not affect usage of health potion, which will always return health to 3.
Armour: Add 5 to total HP before spelunking. This does not affect usage of health potion, which will always return health to 3.
and the deck: 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 9
.
You must implement a bot class that does not use class variables, deriving from the following base class:
class BasePlayer:
def start_turn(self, last_turn):
raise NotImplementedError
def play(self, card):
raise NotImplementedError
def vorpal_choice(self, last_turn):
raise NotImplementedError
def result(self, bot, result, dungeon, vorped):
raise NotImplementedError
This base class shows methods your class needs to implement, and the number of arguments taken by each.
Method Argument Descriptions
last_turn
invorpal_choice
andstart_turn
is an integer or a None value. A value of 0 to 5 indicates that the enemy discarded the drawn card along with the item indicated by that value (see the list of items above). A value of 6 indicates that the enemy placed the card in the dungeon. A None value indicates that the bot is playing first in this round (not possible forvorpal_choice
). Invorpal_choice
last_turn is likely to be 7, indicating that they passed that turn. The only circumstance in which it is not 7 is when the enemy drew the last card.card
is a number representing the strength of one of the cards from the deck as enumerated above.
Now, the arguments for result
are a little bit more complex:
bot
indicates the bot which entered the dungeon. 0 indicates entering the dungeon, and 1 indicates that the enemy entered the dungeon.result
indicates the success of the trip. False indicates the spelunking bot succeeded, while True indicates they failed.dungeon
is a list of cards/ints representing the cards that were in the dungeon. The dungeon is ordered by order placed; the first card placed in the dungeon is first in the list, and the last card placed in is at the end. You will not receive any info about discarded cards; they are secret from the other bot.vorped
is an integer representing thevorpal_choice
made by the spelunking bot. Ifbot==0
, you already know this, but ifbot==1
, this can be useful information.
I'll be honest, I don't entirely recall why I made winning result False, but I think it was a good idea at the time.
Return Values
start_turn
: Return 1 to draw a card, or 0 to pass.play
: Return 0 to 5 to discard the corresponding item and the drawn card, or 6 to place the card in the dungeon (consistent with last_turn input, except for passing, which is done during start_turn).vorpal_choice
: Return the number of the card you wish to eliminate with the Vorpal dagger (1 to eliminate 1s, 5 to eliminate 5s). Picking a non-existent card kills you (8 is illegal, 10 is illegal, 0 is illegal).result
: You may return anything, because this is an informing function to update the bot's data.
You can check out the controller here
Additional clarifications, or just repeating some small details you might have skipped past and might want to know quickly:
Bots play 400 games with each other bot.
No class variables
No targeting specific other bots
No propping up other bots
No reflection things like modifying the random module or other bots.
6 bots maximum (per person), unless it is obvious that all bots are worth including in the KOTH (but still probably don't make a bunch of bots please)
There is no specific end time for this KOTH, except the end of the bounty for what that is worth. Just try to be winning at each time.
Results so far (sorry for being rather lazy with these guys :P)
1 GrailThief 2732 0.98
2 Steve 2399 0.86
3 DevilWorshipper 1854 0.66
4 RunAway 1336 0.48
5 BoringPlayer 1190 0.42
6 SlapAndFlap 783 0.28
7 DareDevilDumDum 750 0.27
8 RandomMandom 156 0.06
Grailthief "steals" the bounty. not really, because it earned it. Good work, Sleafar!
2. place the item in the dungeon. The item goes in the dungeon (duh)
appears to be a typo; there isn't an item mentioned at that point (you just drew a card from the monster deck). The rules should probably be clarified a bit. \$\endgroup\$or any information known only to one player.
am i being unclear again? the dungeon is only revealed at the end, so cards drawn by a bot is known only to one bot. as a bonus, cards discarded are not revealed ever. if you think "oh well then there is a probabilistic best strategy", opponent prediction is still greatly important so this is also invalid \$\endgroup\$