27
16
Create a bot to choose the smallest unique number.
(Based on a psychology experiment I heard about many years ago but haven't been able to track down again.)
Rules
- Each game will consist of 10 randomly selected bots playing 1000 rounds.
- Each round, all bots select an integer from 1 to 10 (inclusive). Any bots that choose the same value will be be excluded, and the remaining bot with the smallest value will receive a point.
- In the event that no bot picks a unique value, no points will be awarded.
- At the end of 1000 rounds, the bot with the most points (or all bots tied with the most points) wins the game.
- The tournament will last 200 * (number of players) games.
- The bot with the highest win percentage wins the tournament.
Specifications
Bots must be Python 3 classes and must implement two methods: select
and update
.
Bots will be constructed with an index.
select
is passed no arguments and returns the bot's choice for the current round.
update
is passed a list of the choices made by each bot in the previous round.
Example
class Lowball(object):
def __init__(self, index):
# Initial setup happens here.
self.index = index
def select(self):
# Decision-making happens here.
return 1
def update(self, choices):
# Learning about opponents happens here.
# Note that choices[self.index] will be this bot's choice.
pass
Controller
import numpy as np
from bots import allBotConstructors
allIndices = range(len(allBotConstructors))
games = {i: 0 for i in allIndices}
wins = {i: 0 for i in allIndices}
for _ in range(200 * len(allBotConstructors)):
# Choose players.
playerIndices = np.random.choice(allIndices, 10, replace=False)
players = [allBotConstructors[j](i) for i, j in enumerate(playerIndices)]
scores = [0] * 10
for _ in range(1000):
# Let everyone choose a value.
choices = [bot.select() for bot in players]
for bot in players:
bot.update(choices[:])
# Find who picked the best.
unique = [x for x in choices if choices.count(x) == 1]
if unique:
scores[choices.index(min(unique))] += 1
# Update stats.
for i in playerIndices:
games[i] += 1
bestScore = max(scores)
for i, s in enumerate(scores):
if s == bestScore:
wins[playerIndices[i]] += 1
winRates = {i: wins[i] / games[i] for i in allIndices}
for i in sorted(winRates, key=lambda i: winRates[i], reverse=True):
print('{:>40}: {:.4f} ({}/{})'.format(allBotConstructors[i], winRates[i], wins[i], games[i]))
Additional information
- No bot will play in a game against itself.
- In the unlikely event that a bot is included in less than 100 games, the tournament will be rerun.
- Bots may store state between rounds, but not between games.
- Accessing the controller or other bots is not allowed.
- The number of games and number of rounds per game are subject to increase if the results are too variable.
- Any bots that raise errors or give invalid responses (non-ints, values outside [1, 10], etc.) will be disqualified, and the tournament will be rerun without them.
- There is no time limit for rounds, but I may implement one if bots take too long to think.
- There is no limit on the number of submissions per user.
The deadline for submissions is 23:59:59 UTC on Friday, September 28.The tournament is now closed for submissions.
Results
BayesBot: 0.3998 (796/1991)
WhoopDiScoopDiPoop: 0.3913 (752/1922)
PoopDiScoopty: 0.3216 (649/2018)
Water: 0.3213 (660/2054)
Lowball: 0.2743 (564/2056)
Saboteur: 0.2730 (553/2026)
OneUpper: 0.2640 (532/2015)
StupidGreedyOne: 0.2610 (516/1977)
SecondSaboteur: 0.2492 (492/1974)
T42T: 0.2407 (488/2027)
T4T: 0.2368 (476/2010)
OpportunityBot: 0.2322 (454/1955)
TheGeneral: 0.1932 (374/1936)
FindRepeats: 0.1433 (280/1954)
MinWin: 0.1398 (283/2025)
LazyStalker: 0.1130 (226/2000)
FollowBot: 0.1112 (229/2060)
Assassin: 0.1096 (219/1999)
MostlyAverage: 0.0958 (194/2024)
UnchosenBot: 0.0890 (174/1955)
Raccoon: 0.0868 (175/2015)
Equalizer: 0.0831 (166/1997)
AvoidConstantBots: 0.0798 (158/1980)
WeightedPreviousUnchosen: 0.0599 (122/2038)
BitterBot: 0.0581 (116/1996)
Profiteur: 0.0564 (114/2023)
HistoryBot: 0.0425 (84/1978)
ThreeFourSix: 0.0328 (65/1984)
Stalker: 0.0306 (61/1994)
Psychadelic: 0.0278 (54/1943)
Unpopulist: 0.0186 (37/1994)
PoissonsBot: 0.0177 (35/1978)
RaccoonTriangle: 0.0168 (33/1964)
LowHalfRNG: 0.0134 (27/2022)
VictoryPM1: 0.0109 (22/2016)
TimeWeighted: 0.0079 (16/2021)
TotallyLost: 0.0077 (15/1945)
OneTrackMind: 0.0065 (13/1985)
LuckySeven: 0.0053 (11/2063)
FinalCountdown: 0.0045 (9/2000)
Triangle: 0.0039 (8/2052)
LeastFrequent: 0.0019 (4/2067)
Fountain: 0.0015 (3/1951)
PlayerCycle: 0.0015 (3/1995)
Cycler: 0.0010 (2/1986)
SecureRNG: 0.0010 (2/2032)
SneakyNiner: 0.0005 (1/2030)
I_Like_Nines: 0.0000 (0/1973)
Comments are not for extended discussion; this conversation has been moved to chat.
– Mego – 2018-09-16T18:37:11.593Will the indexes be from 0 to 9? – ev3commander – 2018-09-19T01:50:00.007
@ev3commander Yes. – None – 2018-09-19T03:06:35.427
What time zone is the end time? – Arcanum – 2018-09-28T02:58:09.840
@Arcanum I'll say the deadline is 23:59:59 UTC on Friday, but I'll probably also include anything submitted before I wake up on Saturday. – None – 2018-09-28T04:16:51.667
@Mnemonic Thanks; I will submit something. – Arcanum – 2018-09-29T12:20:18.630
2@Mnemonic Any news? – user1502040 – 2018-10-02T20:43:14.220
@user1502040 Sorry, I've been way too busy for the past few days. I'll run it tomorrow night. – None – 2018-10-03T00:09:09.120
@Mnemonic - when you do run it, you may want to consider running without PatternMatcher. When I ran a tournament locally, that one slowed everything down considerably. However, it does have a comment about a variable to adjust if it is too slow, so it may be worth looking into that. – Justin – 2018-10-03T12:14:55.093
@Mnemonic Anything? – Herohtar – 2018-10-05T14:47:02.070
4@Herohtar I set it running before I left for work. With any luck, it should be done when I get home. – None – 2018-10-05T15:16:05.447
1@Mnemonic Has it finished yet? – user1502040 – 2018-10-10T20:16:21.790
@user1502040 I seem to have run into a lot of technical difficulties. Maybe I should look into getting a less broken Python environment. In the meantime, I'll try running it with Python 2 (and make the associated changes to the bots).
– None – 2018-10-10T20:25:31.517Would you like someone else to run it for you? I'm able to run it ok here. (My bot is nowhere close to winning, so not a major conflict of interest in that regard). – Justin – 2018-10-11T13:09:00.043
2@Justin It's running right now, and doesn't seem to be crashing, but I definitely wouldn't mind the help if this run fails. – None – 2018-10-11T13:24:18.363
@Mnemonic When will the results be available? – RedClover – 2018-10-20T12:45:01.453
@SpookClover I've had it running constantly for the past week and still isn't finished. I'm going to rerun it with all the slow bots removed and hope it finishes in a reasonable time span. I apologize for all the delays. – None – 2018-10-20T19:44:42.383
@Mnemonic Wow. Do you know what is the current iteration/game? – RedClover – 2018-10-20T19:54:35.007
@SpookClover No. I didn't think to add debug info until it had been running for a few days, and by then I didn't want to stop it. – None – 2018-10-20T20:14:37.683
After all that, I just removed PatternMatcher and it ran in 30 minutes. – None – 2018-10-20T20:50:38.937
@Mnemonic Would make sense, as @RobertFraser pointed in the comments, it can start an infinite loop
– RedClover – 2018-10-21T06:10:21.207Was WaitWhatBot too slow to use too?? – Jonathan Allan – 2018-10-26T18:32:01.417
@JonathanAllan I had to switch to Python 2 and had too much trouble debugging it. – None – 2018-10-26T21:47:09.833
@Mnemonic haha hardly surprising – Jonathan Allan – 2018-10-26T21:48:36.260
Henlo, I would like to run this, how do I put all the bots into
from bots import allBotConstructors
? – Mihail Malostanidis – 2018-11-16T12:11:06.3731@MihailMalostanidis Create a file called
bots.py
in the same directory containing all the bots. At the end, create a list of the constructors:allBotConstructors = [Lowball, BayesBot, ...]
– None – 2018-11-16T14:36:19.267@Mnemonic oh, okay. I thought there was a way to import all the modules in the directory as a hash or array. – Mihail Malostanidis – 2018-11-16T23:32:32.583
1I'm voting to close this question because it is already de-facto closed to new answers ("The tournament is now closed for submissions.") – pppery – 2019-09-04T20:46:18.327
@pppery As it doesn't appear like we have a consensus here just yet, I think it would be best to avoid closing any more KoTHs until we do
– caird coinheringaahing – 2019-09-05T07:51:41.187