Erstpreisauktion mit Siegelgebot

32

Endergebnis

Der Wettbewerb ist vorbei. Glückwunsch an hard_coded!

Einige interessante Fakten:

  • In 31600 von 40920 Auktionen (77,2%) hat der Gewinner der ersten Runde die meisten Runden in dieser Auktion gewonnen.

  • Wenn Beispiel-Bots in den Wettbewerb aufgenommen werden, ändern sich die ersten neun Plätze nicht AverageMineund heuristtauschen ihre Positionen.

  • Top 10 Ergebnisse einer Auktion:

[2, 2, 3, 3] 16637
[0, 3, 3, 4] 7186
[1, 3, 3, 3] 6217
[1, 2, 3, 4] 4561
[0, 1, 4, 5] 1148
[0, 2, 4, 4] 1111
[2, 2, 2, 4] 765
[0, 2, 3, 5] 593
[1, 1, 4, 4] 471
[0, 0, 5, 5] 462
  • Tie Zahl (Anzahl der Auktionen , dass der i-ten Runde hatte keinen Sieger): [719, 126, 25, 36, 15, 58, 10, 7, 19, 38].

  • Durchschnittliches Höchstgebot des i-ten Runde: [449.4, 855.6, 1100.8, 1166.8, 1290.6, 1386.3, 1500.2, 1526.5, 1639.3, 3227.1].

Anzeigetafel

Bot count: 33
hard_coded            Score: 16141  Total: 20075170
eenie_meanie_more     Score: 15633  Total: 18513346
minus_one             Score: 15288  Total: 19862540
AverageMine           Score: 15287  Total: 19389331
heurist               Score: 15270  Total: 19442892
blacklist_mod         Score: 15199  Total: 19572326
Swapper               Score: 15155  Total: 19730832
Almost_All_In         Score: 15001  Total: 19731428
HighHorse             Score: 14976  Total: 19740760
bid_higher            Score: 14950  Total: 18545549
Graylist              Score: 14936  Total: 17823051
above_average         Score: 14936  Total: 19712477
below_average         Score: 14813  Total: 19819816
Wingman_1             Score: 14456  Total: 18480040
wingman_2             Score: 14047  Total: 18482699
simple_bot            Score: 13855  Total: 20935527
I_Dont_Even           Score: 13505  Total: 20062500
AntiMaxer             Score: 13260  Total: 16528523
Showoff               Score: 13208  Total: 20941233
average_joe           Score: 13066  Total: 18712157
BeatTheWinner         Score: 12991  Total: 15859037
escalating            Score: 12914  Total: 18832696
one_upper             Score: 12618  Total: 18613875
half_in               Score: 12605  Total: 19592760
distributer           Score: 12581  Total: 18680641
copycat_or_sad        Score: 11573  Total: 19026290
slow_starter          Score: 11132  Total: 20458100
meanie                Score: 10559  Total: 12185779
FiveFiveFive          Score: 7110   Total: 24144915
patient_bot           Score: 7088   Total: 22967773
forgetful_bot         Score: 2943   Total: 1471500
bob_hater             Score: 650    Total: 1300
one_dollar_bob        Score: 401    Total: 401

In diesem Spiel simulieren wir eine Auktion mit Siegelgebot.

Jede Auktion ist ein 4-Spieler-Spiel, das aus 10 Runden besteht. Anfangs haben die Spieler kein Geld. Zu Beginn jeder Runde erhält jeder Spieler 500 US-Dollar und macht dann seine eigenen Gebote. Das Gebot kann eine nicht negative ganze Zahl sein, die kleiner oder gleich dem Betrag ist, den sie haben. Gewöhnlich gewinnt einer, der das höchste Gebot abgibt, die Runde. Wenn jedoch mehrere Spieler den gleichen Preis bieten, wird ihr Gebot nicht berücksichtigt (daher kann die Runde nicht gewonnen werden), um die Sache interessanter zu machen. Wenn zum Beispiel vier Spieler 400 400 300 200 bieten, gewinnt der eine 300; Wenn sie 400 400 300 300 bieten, gewinnt niemand. Der Gewinner muss bezahlen, was er geboten hat.

Da es sich um eine Auktion mit versiegeltem Gebot handelt, ist die einzige Information, die der Spieler über das Bieten erhält, der Gewinner und wie viel er zu Beginn der nächsten Runde gezahlt hat (damit der Spieler wissen kann, wie viel jeder hat).


Wertung

Für jede mögliche 4-Spieler-Kombination findet eine Auktion statt. Das heißt, wenn es insgesamt N Bots gibt, wird es eine N C 4 Auktion geben. Der Bot, der die meisten Runden gewinnt, ist der endgültige Gewinner. Bei einem Gleichstand gewinnt der Bot, der insgesamt am wenigsten bezahlt hat. Wenn es wie beim Bieten immer noch ein Unentschieden gibt, werden diese Unentschieden entfernt.


Codierung

Sie sollten eine Python 3- Klasse mit einer Member-Funktion implementieren play_round(und __init__bei Bedarf mit anderen). play_roundsollte 3 Argumente nehmen (einschließlich Selbst). Das zweite und dritte Argument lauten in der Reihenfolge: die ID des Gewinners der vorherigen Runde, gefolgt von der Höhe der Auszahlung. Wenn niemand gewinnt oder es die erste Runde ist, sind beide -1. Ihre ID ist immer 0, und ID 1–3 sind die anderen Spieler in einer Reihenfolge, die nur durch die Position in diesem Beitrag bestimmt wird.


Zusätzliche Regeln

1. Deterministisch: Das Verhalten Ihrer Funktion sollte nur von den Eingabeargumenten innerhalb einer Auktion abhängen. Das heißt, Sie können nicht auf Dateien, Zeit, globale Variablen oder irgendetwas zugreifen, das Zustände zwischen verschiedenen Auktionen oder Bots speichert . Wenn Sie einen Pseudozufallsgenerator verwenden möchten, ist es besser, ihn selbst zu schreiben (um zu verhindern, dass die Programme anderer wie randomin Python lib beeinflusst werden) und ihn mit einem festen Startwert in __init__oder in der ersten Runde zurückzusetzen.

2. Drei Bots pro Person: Sie dürfen höchstens drei Bots einsenden, damit Sie eine Strategie entwickeln können, mit der Ihre Bots auf irgendeine Weise "kooperieren".

3. Nicht zu langsam: Da es viele Auktionen geben wird, stellen Sie sicher, dass Ihre Bots nicht zu langsam laufen. Ihre Bots sollten in der Lage sein, mindestens 1.000 Auktionen in einer Sekunde abzuschließen.


Regler

Hier ist der Controller, den ich verwende. Alle Bots werden importiert und bot_listin der Reihenfolge in diesem Beitrag hinzugefügt .

# from some_bots import some_bots

bot_list = [
    #one_bot, another_bot, 
]

import hashlib

def decide_order(ls):
    hash = int(hashlib.sha1(str(ls).encode()).hexdigest(), 16) % 24
    nls = []
    for i in range(4, 0, -1):
        nls.append(ls[hash % i])
        del ls[hash % i]
        hash //= i
    return nls

N = len(bot_list)
score = [0] * N
total = [0] * N

def auction(ls):
    global score, total
    pl = decide_order(sorted(ls))
    bots = [bot_list[i]() for i in pl]
    dollar = [0] * 4
    prev_win, prev_bid = -1, -1
    for rounds in range(10):
        bids = []
        for i in range(4): dollar[i] += 500
        for i in range(4):
            tmp_win = prev_win
            if prev_win == i: tmp_win = 0
            elif prev_win != -1 and prev_win < i: tmp_win += 1
            bid = int(bots[i].play_round(tmp_win, prev_bid))
            if bid < 0 or bid > dollar[i]: raise ValueError(pl[i])
            bids.append((bid, i))
        bids.sort(reverse = True)
        winner = 0
        if bids[0][0] == bids[1][0]:
            if bids[2][0] == bids[3][0]: winner = -1
            elif bids[1][0] == bids[2][0]: winner = 3
            else: winner = 2
        if winner == -1:
            prev_win, prev_bid = -1, -1
        else:
            prev_bid, prev_win = bids[winner]
            score[pl[prev_win]] += 1
            total[pl[prev_win]] += prev_bid
            dollar[prev_win] -= prev_bid

for a in range(N - 3):
    for b in range(a + 1, N - 2):
        for c in range(b + 1, N - 1):
            for d in range(c + 1, N): auction([a, b, c, d])

res = sorted(map(list, zip(score, total, bot_list)), key = lambda k: (-k[0], k[1]))

class TIE_REMOVED: pass

for i in range(N - 1):
    if (res[i][0], res[i][1]) == (res[i + 1][0], res[i + 1][1]):
        res[i][2] = res[i + 1][2] = TIE_REMOVED
for sc, t, tp in res:
    print('%-20s Score: %-6d Total: %d' % (tp.__name__, sc, t))

Beispiele

Wenn Sie einen Pseudozufallsgenerator benötigen, finden Sie hier einen einfachen.

class myrand:
    def __init__(self, seed): self.val = seed
    def randint(self, a, b):
        self.val = (self.val * 6364136223846793005 + 1) % (1 << 64)
        return (self.val >> 32) % (b - a + 1) + a

class zero_bot:
    def play_round(self, i_dont, care): return 0

class all_in_bot:
    def __init__(self): self.dollar = 0
    def play_round(self, winner, win_amount):
        self.dollar += 500
        if winner == 0: self.dollar -= win_amount
        return self.dollar

class random_bot:
    def __init__(self):
        self.dollar = 0
        self.random = myrand(1)
    def play_round(self, winner, win_amount):
        self.dollar += 500
        if winner == 0: self.dollar -= win_amount
        return self.random.randint(0, self.dollar)

class average_bot:
    def __init__(self):
        self.dollar = 0
        self.round = 11
    def play_round(self, winner, win_amount):
        self.dollar += 500
        self.round -= 1
        if winner == 0: self.dollar -= win_amount
        return self.dollar / self.round

class fortytwo_bot:
    def play_round(self, i_dont, care): return 42

Ergebnis

all_in_bot           Score: 20     Total: 15500
random_bot           Score: 15     Total: 14264
average_bot          Score: 15     Total: 20000
TIE_REMOVED          Score: 0      Total: 0
TIE_REMOVED          Score: 0      Total: 0

Der Gewinner ist all_in_bot. Beachten Sie, dass zero_botund fortytwo_bothaben die gleiche Punktzahl und Summe, so dass sie entfernt werden.

Diese Bots werden nicht in den Wettbewerb aufgenommen. Sie können sie verwenden, wenn Sie denken, dass sie großartig sind.


Die Endrunde findet am 23.11.2017 um 14:00 Uhr (UTC) statt . Sie können Ihre Bots vorher beliebig ändern.

Colera Su
quelle
5
Bekommen sie 500 Dollar pro Runde oder jede Auktion (die 10 Runden dauert)?
Stewie Griffin
1
Der @ KamilDrakari-Wettbewerb wird neu gestartet, und der anstößige Bot wird von der Liste entfernt.
Colera So
4
@Shufflepants Stimmt, aber das ist bei KotH-Herausforderungen immer der Fall. In der Vergangenheit machten einige Leute tatsächlich gegen Ende einen Bot, um alle Bots bis zu diesem Zeitpunkt zu kontern. Aber es ist nur ein Teil der Herausforderung im KotH-Stil. Und so wie die meisten KotH-Herausforderungen funktionieren, ist der Vorteil nicht so groß. Sie können nur so viele Bots gleichzeitig kontern. Schöne erste Herausforderung, Colera Su , und willkommen bei PPCG! Ich freue mich auf die Ergebnisse. :)
Kevin Cruijssen
4
Hier ist ein Testlauf auf TIO mit allen aktuellen Bots.
Steadybox
2
Es ist im Moment ein enges Rennen ...
Zaid

Antworten:

13

hard_coded

class hard_coded:
  def __init__(self):
    self.money = 0
    self.round = 0

  def play_round(self, did_i_win, amount):
    self.money += 500
    self.round += 1
    if did_i_win == 0:
      self.money -= amount
    prob = [500, 992, 1170, 1181, 1499, 1276, 1290, 1401, 2166, 5000][self.round - 1]
    if prob > self.money:
      return self.money
    else:
      return prob    

Dieser Bot ist das Ergebnis von Gentraining gegen viele andere Pseudo-Zufalls-Bots (und einige der Bots in anderen Antworten). Ich habe am Ende einige Zeit mit der Feinabstimmung verbracht, aber die Struktur ist eigentlich sehr einfach.

Die Entscheidungen stützen sich nur auf einen festgelegten Parametersatz und nicht auf das Ergebnis früherer Runden.

Der Schlüssel scheint die erste Runde zu sein: Man muss All-In gehen, 500 zu bieten ist der sichere Zug. Zu viele Bots versuchen, den ersten Zug zu überlisten, indem sie 499 oder 498 bieten. Wenn Sie die erste Runde gewinnen, haben Sie einen großen Vorteil für den Rest der Auktion. Sie sind nur 500 Dollar im Rückstand und haben Zeit, sich zu erholen.

Eine sichere Wette in der zweiten Runde ist etwas mehr als 990, aber selbst wenn Sie 0 bieten, erhalten Sie ein gutes Ergebnis. Zu hohe Gebote und Gewinne könnten schlimmer sein, als diese Runde zu verlieren.

In der dritten Runde hören die meisten Bots auf zu eskalieren: 50% von ihnen haben mittlerweile weniger als 1500 Dollar, sodass Sie in dieser Runde kein Geld verschwenden müssen. 1170 ist ein guter Kompromiss. Gleiches in der vierten Runde. Wenn Sie die ersten drei verloren haben, können Sie diese sehr billig gewinnen und haben immer noch genug Geld für die nächste.

Danach beträgt das durchschnittliche Geld, das benötigt wird, um eine Runde zu gewinnen, 1500 Dollar (was die logische Schlussfolgerung ist: Jeder gewinnt inzwischen eine Runde von vier, weniger zu bieten, um später zu gewinnen, ist nur Geldverschwendung, die Situation hat sich stabilisiert und es ist einfach rund. Robin von nun an).

Die letzte Runde muss All-In sein, und die anderen Parameter sind genau abgestimmt, um die letzte Runde zu gewinnen, indem bis dahin so niedrig wie möglich geboten wird.

Viele Bots versuchen, die neunte Runde zu gewinnen, indem sie mehr als 2000 Dollar bieten. Deshalb habe ich das berücksichtigt und versucht, sie zu überbieten (ich kann sowieso nicht beide Runden gewinnen, und die letzte wird schwieriger).

GB
quelle
1
Das ist ein Weg, um zu gewinnen. Herzliche Glückwünsche!
Luca H
Aber ich muss zugeben, dass ich andere Einreichungen mehr mag, weil es eine andere Form des Denkens gibt. Ich habe nicht ausprobiert, wie ich gegen diese anderen Bots gewinnen würde, aber was könnte eine gute Taktik gegen irgendeinen zufälligen Bot sein.
Luca H
Ich kann verstehen, dass ich einige andere Einsendungen mochte (und hochgestuft habe), aber dies ist ein Problem auf einer endlichen Domäne, und viele Einsendungen sind einfach zu komplex. Der Kern des Problems besteht darin, eine Folge von 10 Zahlen zu generieren. Daher habe ich mich für die Optimierung für eine bestimmte Domäne entschieden, anstatt eine allgemeine Vorgehensweise zu finden. Ich bin Ingenieur und kein Mathematiker.
GB
2
@LucaH Die offensichtliche Einfachheit des Ansatzes steht im Widerspruch zum Arbeitsaufwand, der erforderlich ist, um zu dieser bestimmten Menge von Zahlen zu gelangen. Aus statistischer Sicht habe ich mit meinem eigenen Bot etwas Ähnliches versucht, und es war nicht einfach
Zaid,
1
@Zaid natürlich gibt es eine Menge Arbeit, aber Brute Forcing ist einfach so ... brutal;)
Luca H
12

Überdurchschnittlich

Gebote über dem durchschnittlichen Geldbetrag der anderen Spieler. Bietet alles in der letzten Runde.

class above_average:
  def __init__(self):
    self.round = 0
    self.player_money = [0] * 4
  def play_round(self, winner, winning_bid):
    self.round += 1
    self.player_money = [x+500 for x in self.player_money]
    if winner != -1:
      self.player_money[winner] -= winning_bid
    if self.round == 10:
      return self.player_money[0]
    bid = sum(self.player_money[1:]) / 3 + 1
    if bid > self.player_money[0]:
      return self.player_money[0]
    return min(self.player_money[0], bid)
Okx
quelle
12

Ich tue nicht einmal

class I_Dont_Even:
	def __init__(self):
		self.money = 0
		self.round = 0
	def play_round(self, loser, bid):
		self.money += 500 - (not loser) * bid
		self.round += 1
		return self.money * (self.round & 1 or self.round == 10)

Nimmt nur an ungeraden und letzten Runden teil.

Dennis
quelle
7

Der vergessliche Bot weiß nicht, wie viel Geld er hat, also setzt er nur das Geld ein, das er für diese Runde erhalten hat. Wenn er am Ende etwas Geld findet, spendet er es einfach an eine Wohltätigkeitsorganisation.

class forgetful_bot:
  def play_round(self, winner, amt):
    return 500
RamenChef
quelle
15
Ich bin nicht der Abwähler, aber vielleicht liegt es daran, dass Sie Ihrem Bot keine Mühe gegeben haben
Mischa
9
Dies ist eine der ersten Antworten. Etwas ist nötig, um den Ball ins Rollen zu bringen.
Khuldraeseth na'Barya
Ich habe nicht abgelehnt, aber vielleicht liegt es daran, dass, obwohl etwas benötigt wird, um den Ball ins Rollen zu bringen, vielleicht etwas Interessanteres getan wird? Zumal dies praktisch identisch ist mit One Dollar Bob, mit dem es gestartet wurde
HyperNeutrino
7

One Upper

Ich weiß nicht viel über Python, daher könnte ich einen Fehler machen

class one_upper:
    def __init__(self): 
        self.money = 0
        self.round = 0
    def play_round(self, winner, win_amount):
        self.money += 500
        if winner == 0: self.money -= win_amount
        self.round += 1
        bid = win_amount + 1
        if self.money < bid or self.round == 10:
            bid = self.money
        return bid

bietet 1 höher als das vorherige Gewinngebot oder geht in der letzten Runde All-in.

Ich kann mich in Zukunft für eine andere Strategie entscheiden, wenn win_amount-1 ist

Kamil Drakari
quelle
7

Patient Bot

class patient_bot:
    def __init__(self):
        self.round = 0
        self.money = 0
    def rand(self, seed, max):
        return (394587485 - self.money*self.round*seed) % (max + 1)
    def play_round(self, winner, amount):
        self.round += 1
        self.money += 500
        if winner == 0:
            self.money -= amount
        if self.round < 6:
            return 0
        else:
            bid = 980 + self.rand(amount, 35)
            if self.money < bid or self.round == 10:
                bid = self.money
            return bid

Bietet nichts für die ersten fünf Runden, bietet dann ~ 1000 Dollar für die nächsten vier Runden und bietet schließlich alles, was es in der letzten Runde hat.

Steadybox
quelle
7

Nachahmer oder traurig

Dritter und letzter Bot.
Dieser Bot bietet genau den gleichen Betrag wie der vorherige Gewinner (einschließlich sich selbst). Wenn es jedoch nicht genug Geld dafür hat, wird es traurig sein und stattdessen einen miesen 1-Dollar-Schein mit seiner Träne drauf bieten. In der letzten Runde geht es All-In.

class copycat_or_sad:
  def __init__(self):
    self.money = 0
    self.round = -1
  def play_round(self, winner, win_amount):
    # Default actions:
    #  Collect 500 dollars
    self.money += 500
    #  If it was the winner: subtract the win_amount from his money
    if winner == 0:
      self.money -= win_amount
    #  One round further
    self.round += 1

    # If it's the final round: bid all-in
    if self.round == 9:
      return self.money
    # Else-if there was no previous winner, or it doesn't have enough money left: bid 1
    if win_amount < 1 or self.money < win_amount:
      return 1
    # Else: bid the exact same as the previous winner
    return win_amount

Ich programmiere nie in Python. Wenn Sie also Fehler sehen, lassen Sie es mich wissen.

Kevin Cruijssen
quelle
2
Dies bietet -1auf die erste Auktion.
Okx
7

Testlauf

Ich habe einen früheren von Steadybox zusammengestellten Testlauf bearbeitet und die neuesten Einsendungen hinzugefügt.

Ich poste es hier, damit es einen Ort gibt, an dem der Link mit neueren Versionen aktualisiert werden kann. Dieser Beitrag ist ein Community-Wiki. Sie können ihn also jederzeit aktualisieren, wenn Sie einen neuen Beitrag posten, einen alten ändern oder einfach etwas sehen neu von einem anderen Beitrag!

Hier ist der Link zum Testlauf! (TIO)

Leo
quelle
Sollte ich deprimiert sein, dass mein Bot, der störend wirken sollte, meine beiden "echten" Einsendungen übertrifft?
thegreatemu
@thegreatemu Es ist interessant zu sehen, wie die Bots miteinander interagieren. Ein einzelner neuer Bot könnte die Rangliste dramatisch verändern. Interessant ist, dass meine beiden Bots an die Spitze der Rangliste gelangen, wenn der gelöschte Blacklist-Bot des Histokraten teilnimmt. :)
Jo.
6

Zur Hälfte

Dieser Bot bietet immer die Hälfte von dem, was er übrig hat, außer in der letzten Runde, in der er alles geben wird.

class half_in:
  def __init__(self):
    self.money = 0
    self.round = -1
  def play_round(self, winner, win_amount):
    # Default actions:
    #  Collect 500 dollars
    self.money += 500
    #  If it was the winner: subtract the win_amount from his money
    if winner == 0:
      self.money -= win_amount
    #  One round further
    self.round += 1

    # If it's the final round: bid all in
    if self.round == 9:
      return self.money
    # Else: Bid half what it has left:
    return self.money / 2

Ich programmiere nie in Python. Wenn Sie also Fehler sehen, lassen Sie es mich wissen.

Kevin Cruijssen
quelle
6

Graylist

class Graylist:
  def __init__(self):
    self.round = 0
    self.player_money = [0] * 4
    self.ratios = {1}
    self.diffs = {0}
  def play_round(self, winner, winning_bid):
    self.round += 1
    if winner != -1:
      if winner >0 and winning_bid>0:
        self.ratios.add(self.player_money[winner]/winning_bid)
        self.diffs.add(self.player_money[winner]-winning_bid)
      self.player_money[winner] -= winning_bid
    self.player_money = [x+500 for x in self.player_money]
    tentative_bid = min(self.player_money[0],max(self.player_money[1:])+1, winning_bid+169, sum(self.player_money[1:])//3+169)
    while tentative_bid and (tentative_bid in (round(m*r) for m in self.player_money[1:] for r in self.ratios)) or (tentative_bid in (m-d for m in self.player_money[1:] for d in self.diffs)):
      tentative_bid = tentative_bid - 1
    return tentative_bid

Inspiriert von der Blacklist-Einreichung des Histokraten , behält dieser Bot alle vorherigen Gewinnwetten anderer Spieler im Gedächtnis, sowohl als Verhältnis des Geldes zu ihrem vollen Geld als auch als Differenz zwischen ihrem Einsatzbetrag und dem vollen Betrag. Um eine Niederlage zu vermeiden (was anscheinend ein wichtiger Faktor in diesem Wettbewerb ist), wird darauf verzichtet, eine beliebige Zahl zu setzen, die bei den aktuellen Geldern des Gegners zu den gleichen Ergebnissen führen könnte.

BEARBEITEN: Als Startwert für das Gebot wird nun das Minimum zwischen dem aktuellen Geld, 1 mehr als das Geld des reichsten Gegners, X mehr als die letzte Gewinnwette oder Y mehr als das durchschnittliche Geld seiner Gegner verwendet. X und Y sind Konstanten, die wahrscheinlich vor dem Ende des Wettbewerbs geändert werden.

Löwe
quelle
6

AverageMine

Dieser Spieler berechnet den Prozentsatz (Gebot / Gesamtgeld) für den Gewinner jeder Runde und bietet seinen (Gesamtgeld * durchschnittlicher Gewinnprozentsatz + 85), sofern er nicht mehr Geld hat als alle anderen Spieler, dann bietet er 1 mehr als der höchste Konkurrent . Beginnt mit einem Gebot von 99,0% des Startbetrags.

class AverageMine:
    nplayers = 4
    maxrounds = 10
    def __init__(self):
        self.money = [0] * self.nplayers
        self.wins = [0] * self.nplayers
        self.round = 0
        self.average = 0
    def play_round(self, winner, win_amt):
        self.round += 1
        for i in range(self.nplayers):
            if i == winner:
                self.average = (self.average * (self.round - 2) + (win_amt / self.money[i])) / (self.round - 1)
                self.money[i] -= win_amt
                self.wins[i] += 1
            self.money[i] += 500
        if self.round == 1:
            return int(0.990 * self.money[0])
        elif self.round < self.maxrounds:
            if self.money[0] > self.money[1] + 1 and self.money[0] > self.money[2] + 1 and self.money[0] > self.money[3] + 1:
                return max(self.money[1],self.money[2],self.money[3]) + 1
            bid = int(self.average * self.money[0]) + 85
            return min(self.money[0],bid)
        else:
            bid = self.money[0]
            return bid
Jo.
quelle
6

Eenie Meanie More

Dieser Spieler ist mit Ausnahme einer Variablen mit Meanie identisch. Diese Version bietet aggressiver und veranlasst einige Spieler, mehr Geld auszugeben, als Meanie für die Auktion wert hält.

class eenie_meanie_more:
    def __init__(self):
        self.money = [0] * 4
        self.rounds = 11
        self.total_spent = 0

    def play_round(self, winner, winning_bid):
        self.money = [x+500 for x in self.money]
        self.rounds -= 1
        if winner != -1:
            self.money[winner] -= winning_bid
            self.total_spent += winning_bid
        bid = 500
        if self.rounds > 0 and self.total_spent < 20000:
            bid = int((20000 - self.total_spent)/self.rounds/4)+440
        return min(bid, max(self.money[1:])+1, self.money[0])
Nee
quelle
5

Verteiler

Wenn dieser Bot eine Runde verliert, verteilt er das überschüssige Geld auf alle nächsten Runden. Er setzt in der ersten Runde 499 $ ein und denkt, dass die anderen mit 500 $ gleichziehen und eliminiert werden.

class distributer:
  def __init__(self):
    self.money = 0
    self.rounds = 11
  def play_round(self, winner, amt):
    self.money += 500
    self.rounds -= 1
    if self.rounds == 10:
      return 499
    if winner == 0:
      self.money -= amt
    return ((self.rounds - 1) * 500 + self.money) / self.rounds
RamenChef
quelle
1
Die Verwendung von roundsanstelle von self.roundsführt zu Fehlern. Gleiche mit money.
Jeremy Weirich
5

Meanie

Dieser Spieler erhält das gesamte Geld, das in das Spiel kommt, um das Durchschnittsgebot für die Anzahl der Spieler und verbleibenden Runden zu erhalten. Wenn dieses Ziel höher ist als das aller anderen Spieler, senkt es sein Gebot auf den Kontostand seines größten Konkurrenten plus eins. Wenn sich der Spieler sein Ziel nicht leisten kann, ist er All-In.

class meanie:
    def __init__(self):
        self.money = [0] * 4
        self.rounds = 11
        self.total_spent = 0

    def play_round(self,winner,winning_bid):
        self.money = [x+500 for x in self.money]
        self.rounds -= 1
        if winner != -1:
            self.money[winner] -= winning_bid
            self.total_spent += winning_bid
        bid = 500
        if self.rounds > 0 and self.total_spent < 20000:
            bid = int((20000 - self.total_spent)/self.rounds/4)+1
        return min(bid,max(self.money[1:])+1,self.money[0])
Nee
quelle
5

Schlage den Sieger

Bieten Sie 1 mehr als der Spieler mit den meisten Gewinnen

class BeatTheWinner:
    nplayers = 4
    maxrounds = 10
    def __init__(self):
        self.money = [0] * self.nplayers
        self.wins = [0] * self.nplayers
        self.round = 0

    def play_round(self, winner, win_amt):
        self.round += 1
        for i in range(self.nplayers):
            self.money[i] += 500
            if i == winner:
                self.money[i] -= win_amt
                self.wins[i] += 1
        mymoney = self.money[0]
        for w,m in sorted(zip(self.wins, self.money),reverse=True):
            if mymoney > m:
                return m+1
        #if we get here we can't afford our default strategy, so
        return int(mymoney/10)
thegreatemu
quelle
4
Sind Sie m,win der richtigen Reihenfolge?
Jo.
5

Minus eins

class minus_one:
    def __init__(self):
        self.money = 0
    def play_round(self, winner, amount):
        self.money += 500
        if winner == 0:
            self.money -= amount
        return self.money - 1
Steadybox
quelle
5

Bieten Sie höher

class bid_higher:
    def __init__(self):
        self.dollar = 0
        self.round = 0
    def play_round(self, winner, win_amount):
        self.dollar += 500
        self.round += 1
        inc = 131
        if winner == 0: self.dollar -= win_amount
        if self.round == 10: return self.dollar
        if win_amount == 0: win_amount = 500
        if self.dollar > (win_amount + inc):
            return win_amount + inc
        else:
            if self.dollar > 1:
                return self.dollar -1
            else:
                return 0

Lerne noch Python; Bieten Sie etwas höher als der letzte Gewinner.

rancid_banana
quelle
Willkommen bei PPCG! Es scheint , dass der Bot wird noch besser eine Punktzahl , wenn Sie ändern inc = 100zu inc = 101.
Steadybox
Ich gehe hier wirklich gegen meine eigenen Interessen vor, aber Sie könnten Ihre Punktzahl leicht verbessern, indem Sie die Kurven verfolgen und in der letzten Runde All-in gehen;)
Leo
Danke für die Vorschläge; Ich fügte ein All-In für die letzte Runde hinzu,
verfeinerte
Hallo, ich hoffe, es macht Ihnen nichts aus, aber ich habe eine Testbench mit allen aktuellen Einsendungen zusammengestellt und festgestellt, dass Ihr Code in der letzten Runde manchmal ungültige Werte zurückgab. Deshalb habe ich den Fehler durch Neuanordnung behoben die bestellung ein paar zeilen. Tut mir leid, wenn ich etwas geändert habe, das Sie nicht hätten, können Sie die Änderungen jederzeit rückgängig machen und den Fehler auf andere Weise beheben!
Leo
@Leo: Kein Problem, danke für
dein
4

FiveFiveFive

Überspringt die erste Runde und bietet in den verbleibenden Runden 555 $. In der letzten Runde geht alles rein, es sei denn, 2 andere Bots haben den gleichen Betrag (und binden vermutlich aus).

class FiveFiveFive:
    nplayers = 4
    maxrounds = 10
    def __init__(self):
        self.money = [0] * self.nplayers
        self.wins = [0] * self.nplayers
        self.round = 0

    def play_round(self, winner, win_amt):
        self.round += 1
        for i in range(self.nplayers):
            self.money[i] += 500
            if i == winner:
                self.money[i] -= win_amt
                self.wins[i] += 1
        if self.round == 1:
            return 0
        elif self.round < self.maxrounds:
            return min(555, self.money[0])
        else:
            bid = self.money[0]
            return bid if self.money.count(bid) < 3 else bid-1
thegreatemu
quelle
4

Fast alles in

class Almost_All_In:
	def __init__(self):
		self.money = 0
		self.round = 0
	def play_round(self, loser, bid):
		self.money += 500 - (not loser) * bid
		self.round += 1
		return self.money - self.round % 3 * 3 - 3

Bietet immer etwas weniger als es hat.

Dennis
quelle
4

Schnell eskalieren

Bietet mehr Bruchteile seines Geldes pro Runde (bitte lassen Sie mich wissen, wenn Fehler aufgetreten sind, seit ich Python verwendet habe)

class escalating:
  def __init__(self):
    self.money = 0
    self.round = 0
  def play_round(self, winner, win_amount):
    # Default actions:
    #  Collect 500 dollars
    self.money += 500
    #  If it was the winner: subtract the win_amount from his money
    if winner == 0:
      self.money -= win_amount
    #  One round further
    self.round += 1

    # bid round number in percent times remaining money, floored to integer
    return self.money * self.round // 10
Scott
quelle
4

Unterdurchschnittlich

Ähnlich wie überdurchschnittlich, geht aber etwas tiefer

class below_average:
  def __init__(self):
    self.round = 0
    self.player_money = [0] * 4
  def play_round(self, winner, winning_bid):
    self.round += 1
    self.player_money = [x+500 for x in self.player_money]
    if winner != -1:
      self.player_money[winner] -= winning_bid
    if self.round == 10:
      return self.player_money[0]
    bid = sum(self.player_money[1:]) / 3 - 2
    if bid > self.player_money[0]:
      return self.player_money[0]
    return min(self.player_money[0], bid)
Okx
quelle
4

Hohes Ross

Dieser Spieler bietet sein gesamtes Geld abzüglich der aktuellen Rundenanzahl, außer in der letzten Runde, in der er All-In geht.

class HighHorse:
    maxrounds = 10
    def __init__(self):
        self.money = 0
        self.round = 0
    def play_round(self, winner, win_amt):
        self.round += 1
        if 0 == winner:
            self.money -= win_amt
        self.money += 500
        if self.round < self.maxrounds:
            return self.money - self.round
        else:
            bid = self.money
            return bid
Jo.
quelle
4

Swapper

Wechselt zwischen Bieten unter seinem Maximum und All-In.

class Swapper:
    def __init__(self):
        self.money = 0
        self.round = 0
    def play_round(self, loser, bid):
        self.money += 500 - (not loser) * bid
        self.round += 1
        if self.round & 1:
            return self.money - 1
        return self.money

Ich dachte, ich müsste etwas finden, das Steadybox 'minus_one übertreffen könnte. :)

Jo.
quelle
4

Modulare Blacklist

class blacklist_mod:
  def __init__(self):
    self.round = 0
    self.player_money = [0] * 4
    self.blacklist = {0, 499}
  def play_round(self, winner, winning_bid):
    self.round += 1
    self.player_money = [x+500 for x in self.player_money]
    if winner != -1:
      self.player_money[winner] -= winning_bid
      self.blacklist.add(winning_bid % 500)
      self.blacklist |= {x % 500 for x in self.player_money[1:]}
    tentative_bid = self.player_money[0]
    autowin = max(self.player_money[1:])+1
    if tentative_bid < autowin:
      while tentative_bid and (tentative_bid % 500) in self.blacklist:
        tentative_bid = tentative_bid - 1
    else:
      tentative_bid = autowin
    self.blacklist.add(tentative_bid % 500)
    return tentative_bid

Setzt den höchsten Betrag, der nicht mit dem Modulo 500 kongruent ist, auf eine zuvor gesehene Zahl.

Bearbeitet, um die schwarze Liste nicht anzuwenden, wenn ein garantierter Gewinn erzielt werden kann.

Histokrat
quelle
Seltsamerweise scheint das neueste Update Ihres anderen Bots diesen Bot negativ zu beeinflussen. Derzeit blacklist_modist Fünfter in der Rangliste , während blacklistauf dem zweiten Platz. Wird blackliststattdessen die ältere Version von verwendet, blacklistfällt der auf den sechsten Platz, blacklist_mod übernimmt aber die Führung !
Steadybox
Alles blacklistwegzuwerfen scheintblacklist_mod eine noch solidere Führung zu geben , aber das ist nicht schlüssig.
Steadybox
Oh, danke, das macht Sinn - sie kommen dem gleichen Algorithmus schon früh ohne die alte Spezialfalllogik nahe und treten sich gegenseitig auf die Zehen. Ich denke, ich entferne nur den Original-Bot. Ich kann mir keinen guten Grund vorstellen, es zu behalten.
Histokrat
4

Heurist

Der Heurist betrachtet dieses Spiel als ein Spiel mit wiederholbarer Wahrscheinlichkeit, sodass er weiß, wo er die Grenze ziehen muss.

Es ist auch geizig, also bietet es das Nötigste, das für einen Sieg erforderlich ist, wenn es kann.

class heurist:
    def __init__(self):
        self.money = 0
        self.round = -1
        self.net_worth = [0] * 4
    def play_round(self, winner, bid):
        self.round += 1
        self.money += 500
        if winner == 0: self.money -= bid
        if winner != -1: self.net_worth[winner] -= bid
        self.net_worth = [x+500 for x in self.net_worth]
        max_bid = [498,1000,1223,1391,1250,1921,2511,1666,1600,5000][self.round]
        if self.money > max_bid:
            return 1 + min(max_bid,max(self.net_worth[1:3]))
        else:
            return self.money

Haftungsausschluss: max_bidÄnderungen vorbehalten

Zaid
quelle
4

bob_hater

Dieser Bot mag Bob nicht und bietet daher immer 2 $, um gegen Bob zu gewinnen.

class bob_hater:
    def play_round(bob,will,loose):
        return 2
Luca H
quelle
4

Angeben

Dies ist der Typ, der seine mathematischen Fähigkeiten in Situationen unter Beweis stellt, in denen wirklich nichts so Kompliziertes erforderlich ist. Bis zur letzten Runde (in der er All-In geht) verwendet er ein logistisches Modell, um sein Gebot zu bestimmen, mehr, wenn seine Feinde einen größeren Teil ihres Geldes übrig haben.

class Showoff:
  def __init__(self):
      self.moneys = [0, 0, 0]
      self.roundsLeft = 10
  def play_round(self, winner, winning_bid):
      import math
      self.moneys = [self.moneys[0] + 500,
                     self.moneys[1] + 1500,
                     self.moneys[2] + 1500]
      self.roundsLeft -= 1
      if winner > 0:
          self.moneys[1] -= winning_bid
      if winner == 0:
          self.moneys[0] -= winning_bid
      if self.roundsLeft == 0:
          return self.moneys[0]
      ratio = self.moneys[1] / self.moneys[2]
      logisticized = (1 + (math.e ** (-8 * (ratio - 0.5)))) ** -1
      return math.floor(self.moneys[0] * logisticized)

Die verwendete Logistikkurve ist f (x) = 1 / (1 + e -8 (x-0,5) ), wobei x das Verhältnis des aktuellen Feindgeldes zum gesamten potenziellen Feindgeld der Runde ist. Je mehr die anderen haben, desto mehr bietet er. Dies hat den möglichen Vorteil, dass in der ersten Runde fast 500 US-Dollar geboten werden.

Khuldraeseth na'Barya
quelle
3

AntiMaxer

Kombiniere den höchsten Betrag, den wir uns von allen Spielern leisten können. Wird dazu führen, dass ein Bot, der in dieser Runde All-In geht, aussteigt.

class AntiMaxer:
    nplayers = 4
    maxrounds = 10
    def __init__(self):
        self.money = [0] * self.nplayers
        self.wins = [0] * self.nplayers
        self.round = 0

    def play_round(self, winner, win_amt):
        self.round += 1
        for i in range(self.nplayers):
            self.money[i] += 500
            if i == winner:
                self.money[i] -= win_amt
                self.wins[i] += 1
        return max((m for m in self.money[1:] if m<=self.money[0]),
                   default=0)    
thegreatemu
quelle
3

Einfacher Bot

class simple_bot:
    def __init__(self):
        self.round = 0
        self.money = 0
    def rand(self, seed, max):
        return (394587485 - self.money*self.round*seed) % (max + 1)
    def play_round(self, winner, amount):
        self.round += 1
        self.money += 500
        if winner == 0:
            self.money -= amount
        bid = 980 + self.rand(amount, 135)
        if self.money < bid or self.round == 10:
            bid = self.money
        return bid

Fast dasselbe wie Patient Bot, aber nicht als Patient. Erzielt jedoch ein viel besseres Ergebnis.

Steadybox
quelle
3

Flügelmann 2

Wenn ein Flügelmann gut ist, müssen zwei besser sein?

class wingman_2:
    def __init__(self):
        self.dollar = 0
        self.round = 0
    def play_round(self, winner, win_amount):
        self.round += 1
        self.dollar += 500
        inc = 129
        if win_amount == 0: win_amount = 500
        if winner == 0: self.dollar -= win_amount
        if self.round == 10: return self.dollar
        if self.dollar > win_amount + inc:
            return win_amount + inc
        else:
            if self.dollar > 1: return self.dollar -1
            else:
                return 0
rancid_banana
quelle
Ihr Code wird nicht funktionieren, weil Sie Einrückungen für das Zeug in der Klasse
benötigen
Interessanterweise scheinen beide Flügelmänner Ihren ursprünglichen Bot zu schlagen (der Pastebin-Link enthält den TIO-Link, der zu lang für einen Kommentar und sogar zu lang für URL-
Kürzungen ist
1
Ich fand, dass die Ergebnisse sehr empfindlich auf den Pool anderer Bots reagierten. geringfügige Änderungen des Inkrementwerts scheinen unverhältnismäßige Ergebnisse zu haben.
rancid_banana