Аукціон із запечатаною ставкою за першою ціною


32

Остаточний результат

Конкурс закінчився. Вітаємо hard_coded!

Деякі цікаві факти:

  • У 31600 з 40920 аукціонів (77,2%) переможець першого туру виграв найбільшу кількість турів на цьому аукціоні.

  • Якщо приклади ботів будуть включені в змагання, дев'ять найкращих місць не зміниться, окрім цього, AverageMineі поміняють heuristсвої позиції.

  • 10 найкращих результатів на аукціоні:

[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 (кількість аукціонів , які я-го туру не було переможця): [719, 126, 25, 36, 15, 58, 10, 7, 19, 38].

  • Середня виграшна ставка І -го туру: [449.4, 855.6, 1100.8, 1166.8, 1290.6, 1386.3, 1500.2, 1526.5, 1639.3, 3227.1].

Табло

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

У цій грі ми будемо імітувати аукціон із запечатаними ставками.

Кожен аукціон - це гра для 4 гравців, складається з 10 раундів. Спочатку у гравців немає грошей. На початку кожного раунду кожен гравець отримає 500 доларів, а потім зробить власні ставки. Ставка може бути будь-яким невід’ємним цілим числом, меншим або рівним суми, яку вони мають. Зазвичай той, хто запропонував найбільшу кількість, виграє раунд. Однак, щоб зробити речі цікавішими, якщо кілька гравців подають одну і ту ж ціну, їх ставка не буде врахована (таким чином, не виграти раунду). Наприклад, якщо чотири гравці подають заявку на 400 400 300 200, один пропонує ставки 300 виграшів; якщо вони запропонують 400 400 300 300, ніхто не виграє. Переможець повинен заплатити те, що запропонував.

Оскільки це аукціон із запечатаною ставкою, про те, що учасники торгів будуть знати лише переможця та скільки вони заплатили, коли розпочнеться наступний раунд (тому гравець може знати, скільки має кожен).


Оцінка балів

Один аукціон буде проведений для кожної можливої ​​комбінації 4 гравців. Тобто, якщо всього буде N ботів, відбудеться аукціон N C 4 . Кінцевим переможцем стане бот, який виграє найбільшу кількість турів. У випадку, якщо є нічия, виграє бот, який заплатив менше всього. Якщо все-таки буде зв'язано, таким же чином, як і торги, ці зв'язки будуть видалені.


Кодування

Ви повинні реалізувати клас Python 3 з функцією-членом play_round(та __init__або іншими, якщо вам потрібно). play_roundслід взяти 3 аргументи (включаючи власні). Другий та третій аргументи будуть в порядку: ідентифікація переможця попереднього раунду з подальшим виплатою. Якщо ніхто не виграє або це перший тур, вони обидва будуть -1. Ваш ідентифікатор завжди буде 0, а id 1–3 будуть інші гравці в порядку, визначеному лише позицією на цій посаді.


Додаткові правила

1. Детермінований: поведінка вашої функції повинна залежати лише від вхідних аргументів аукціону. Тобто ви не можете отримати доступ до файлів, часу, глобальних змінних або будь-якого іншого, що зберігатиме стани між різними аукціонами чи ботами . Якщо ви хочете використовувати генератор псевдовипадкових випадків, краще написати його самостійно (щоб не впливати на чужі програми, як-от randomв Python lib), і переконайтеся, що ви зможете скинути його з фіксованим насінням у __init__або в першому раунді.

2. Три боти на особу: Вам дозволяється подавати щонайбільше 3 бота, тож ви можете розробити стратегію, щоб змусити ваших ботів "співпрацювати" якимось чином.

3. Не надто повільно: оскільки буде багато аукціонів, переконайтеся, що ваші боти не працюватимуть занадто повільно. Ваші боти повинні мати можливість закінчити принаймні 1000 аукціонів за секунду.


Контролер

Ось контролер, який я використовую. Усі боти будуть імпортовані та додані до bot_listпорядку в цій публікації.

# 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))

Приклади

Якщо вам потрібен генератор псевдовипадкових випадків, ось простий.

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

Результат

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

Переможець all_in_bot. Зверніть увагу , що zero_botі fortytwo_botмають однакову кількість очок і загальний, тому вони видалені.

Ці боти не будуть включені до змагань. Ви можете використовувати їх, якщо вважаєте, що вони чудові.


Фінальний конкурс відбудеться в 2017/11/23 14:00 (UTC) . Ви можете внести будь-які зміни до своїх ботів до цього.


5
Вони отримують 500 доларів за кожен раунд або кожен аукціон (що триває 10 раундів)?
Стюі Гріффін

1
Конкурс @KamilDrakari відновиться, коли бот, який порушив правопорушення, видалений зі списку.
Colera Su

4
@Shufflepants Щоправда, але це завжди так, як це стосується KotH. У минулому деякі люди справді робили бота в кінці, щоб протистояти всім ботам до цього моменту. Але це лише частина виклику в стилі KotH. І те, як працює більшість викликів KotH, включаючи цей, перевага не буде такою великою. Ви можете протиставити лише стільки ботів одночасно. Перший приємний виклик, Colera Su , і ласкаво просимо до PPCG! Чекаючи результатів. :)
Kevin Cruijssen

4
Ось тестовий запуск TIO з усіма поточними ботами.
Steadybox

2
Наразі це жорстка гонка ...
Заїд

Відповіді:


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    

Цей бот є результатом генетичної підготовки проти багатьох інших псевдовипадкових ботів (і деяких ботів в інших відповідях). Я провів деякий час, доопрацювавши наприкінці, але його структура насправді дуже проста.

Рішення базуються лише на фіксованому наборі параметрів, а не на результатах попередніх раундів.

Ключовим, здається, є перший раунд: ви повинні пройти все-все, ставка 500 - це безпечний хід. Занадто багато ботів намагаються перехитрити початковий хід, торгуючи 499 або 498. Перемога в першому раунді дає велику перевагу для решти аукціону. У вас лише 500 доларів позаду, і ви встигаєте видужати.

Безпечна ставка у другому раунді - трохи більше 990, але навіть ставка 0 дає хороший результат. Занадто високі ставки та перемога можуть бути гіршими, ніж програти цей раунд.

У третьому раунді більшість ботів припиняють ескалацію: 50% з них мають менше 1500 доларів на даний момент, тому немає потреби витрачати гроші на цей раунд, 1170 - це хороший компроміс. Те саме в четвертому раунді. Якщо ви програли першу трійку, ви можете виграти цю дуже дешеву і все ж мати достатньо грошей на наступну.

Після цього середні гроші, необхідні для виграшу раунду, - це 1500 доларів (що є логічним висновком: кожен зараз виграє раунд із чотирьох, ставши менше, щоб виграти пізніше, просто витрачайте гроші, ситуація стабілізується, і це просто Робін відтепер).

Останній раунд повинен бути розіграшем, а інші параметри будуть налагоджені, щоб виграти останній раунд, виставляючи торги якомога нижче до цього моменту.

Багато ботів намагаються виграти дев'ятий раунд, запропонувавши більше 2000 доларів, тому я взяв це до уваги і намагаюся їх перекрити (я не можу виграти обидва останні раунди, і останній буде складніше).


1
Ну, це один із способів перемогти. Вітаємо!
Лука H

Але я повинен визнати, що мені більше подобаються інші подання, тому що в них виникла інша форма думки. Не випробовуючи, як я виграю проти цих інших ботів, але яка може бути хорошою тактикою проти будь-якого випадкового бота.
Лука Н

Я можу зрозуміти, що мені сподобалися (і схвалили) деякі інші подання, але це проблема в обмеженому домені, і багато матеріалів є занадто складними. Основою проблеми є генерування послідовності з 10 чисел, тому я вирішив оптимізувати для конкретного домену замість пошуку загальної процедури. Я інженер, а не математик.
ГБ

2
@LucaH очевидна простота підходу відповідає обсягу роботи, необхідної для досягнення цього конкретного набору чисел. Я намагався подібну річ зі своїм власним ботом зі статистичної точки зору, і це було непросто
Zaid

1
@Zaid, звичайно, над цим багато роботи, але грубе насильство просто так ... грубо;)
Лука H

12

Вище середнього

Ставки вище середньої суми грошей, які мають інші гравці. Ставить усі пропозиції в останньому турі.

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)

12

Я навіть не хочу

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)

Бере участь лише у непарних раундах та останньому раунді.


7

Забувливий бот не знає, скільки у нього грошей, тому він просто вкладає гроші, які йому дали за цей раунд. Якщо він виявить, що у нього є гроші в кінці, він просто дарує їх на благодійність.

class forgetful_bot:
  def play_round(self, winner, amt):
    return 500

15
Я не прихильник, але, можливо, це тому, що ти не доклав жодних зусиль до свого бота
Mischa

9
Це одна з перших відповідей. Щось потрібно для того, щоб кулька котилася.
Khuldraeseth na'Barya

Я не виступав проти цього, але, можливо, це тому, що хоч щось потрібно, щоб м'яч котився, може, зробити щось трохи цікавіше? Тим більше, що це практично ідентично Боб в один долар, який використовувався для його початку
HyperNeutrino

7

Один верхній

Я мало знаю про Python, тому я можу зробити якусь помилку

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

ставки на 1 вищі, ніж попередня перемогла ставка, або піднімаються під час останнього раунду.

В майбутньому я можу визначитися з іншою стратегією, коли win_amountце -1


7

Пацієнт Бот

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

Перші п’ять раундів нічого не ставить, потім виставляє ставки ~ 1000 доларів на наступні чотири раунди і, нарешті, виставляє ставки за все, що є в останньому раунді.


7

Copycat Або сумно

Третій і заключний бот.
Цей бот призначає ставки точно такої ж, як і попередній переможець (включаючи самого себе). Однак, якщо для цього не вистачить грошей, це буде сумно, і він запропонує намір замість себе пошкодити 1 доларову купюру. У фінальному раунді він пройде ол-ін.

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

Я ніколи не програмую в Python, тому якщо ви бачите якісь помилки, дайте мені знати.


2
Це торги -1на першому аукціоні.
Okx

7

Тестовий запуск

Я відредагував попередній тестовий цикл, складений Steadybox, додавши до найновіших матеріалів.

Я публікую його тут, щоб було місце, де посилання можна буде оновити більш новими версіями, ця публікація є вікі спільноти, тому сміливо оновіть її, якщо ви опублікуєте нове подання, зміните старе або просто побачите щось нове від іншого подання!

Ось посилання на тестовий пробіг! (TIO)


Чи слід мені пригнічувати, що мій бот, який мав на меті бути руйнівним, вибиває два мої "реальні" матеріали?
thegreatemu

@thegreatemu Цікаво подивитися, як боти взаємодіють між собою. Один новий бот може кардинально змінити рейтинг. Щось цікаве я виявив, що якщо у видаленому боті чорного списку гістократа беруть участь, мої два боти рухаються до вершини рейтингу. :)
Джо.

6

Половина в

Цей бот завжди пропонує ставки половини того, що залишилося, за винятком фінального раунду, де він все пройде.

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

Я ніколи не програмую в Python, тому якщо ви бачите якісь помилки, дайте мені знати.


6

Грайліст

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

Натхненний поданням гістократом у чорний список , цей бот зберігає в пам’яті всі попередні виграшні ставки інших гравців, як співвідношення грошей, які вони роблять, порівняно з їхніми повними грошима, так і різницею між їх сумою ставки та повною сумою. Щоб уникнути програшу внічию (що, очевидно, насправді є великим фактором у цьому змаганні), тоді він уникає робити ставки на будь-яке число, яке могло б дати ті ж результати, враховуючи поточні кошти опонентів.

EDIT: як початкова вартість ставки зараз використовується мінімум між: її поточними грошима, на 1 більше, ніж грошима найбагатшого супротивника, X більше, ніж остання виграла ставка, або Y більше, ніж середні гроші його опонентів. X і Y - константи, які, ймовірно, будуть модифіковані до кінця змагань.


6

Середня мін

Цей гравець розраховує відсоток (ставка / загальна сума грошей) для переможця кожного раунду і подає свої ставки (загальна сума грошей * середній відсоток виграшу + 85), якщо у нього більше грошей, ніж у всіх інших гравців, то він пропонує ставки на 1 більше, ніж найвищий конкурент . Починає зі ставки 99,0% від початкової суми.

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

6

Ені Мені Морі

Цей гравець ідентичний Meanie, за винятком однієї змінної. Ця версія надає ставки більш агресивно і змушує деяких гравців витрачати більше, ніж Мені вважає, що аукціон вартий.

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])

5

Розподільник

Коли цей бот програє раунд, він розподіляє надлишки готівки між усіма наступними раундами. Він вкладає $ 499 в перший раунд, думаючи, що інші зв'язатимуться з 500 доларів і будуть ліквідовані.

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

1
Використання roundsзамість цього self.roundsпризведе до помилок. Те саме з money.
Джеремі Вейріх

5

Меані

Цей гравець бере загальну суму грошей, яка буде входити в гру, щоб отримати середню ставку для кількості гравців та решти раундів. Якщо цієї цілі більше, ніж всі інші гравці, які зараз утримуються, вона знижує свою ставку до балансу свого найбільшого конкурента плюс один. Якщо гравець не може дозволити собі ціль, він все-таки входить.

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])

5

Побийте Переможця

Ставте на 1 більше, ніж гравець із найбільшою кількістю перемог досі

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)

4
Ви m,wв правильному порядку?
Джо.

5

Мінус перший

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

5

Ставка вище

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

Ще вивчає пітон; ставка трохи вище, ніж останній переможець.


Ласкаво просимо до PPCG! Здається, що ваш бот отримує ще кращу оцінку, якщо ви перейдете inc = 100на inc = 101.
Steadybox

Я дійсно іду проти власних інтересів, але ви можете легко покращити свій рахунок, відслідковуючи повороти та пройшовши все-у фінальному раунді;)
Лев,

Дякую за пропозиції; Я додав розіграш в останньому раунді, тонко налаштував приріст і додав пару бот для
крилатих,

Привіт, я сподіваюся, що ви не заперечуєте, але я збирав тестовий стіл з усіма поточними поданнями, і я з’ясував, що ваш код іноді повертав недійсні значення в останньому раунді, тому я виправив помилку шляхом перестановки. замовити пару рядків. Вибачте, якщо я змінив щось, чого б у вас не було, не соромтесь повернути зміни та виправити помилку іншим способом!
Лев

@Leo: Без проблем, дякую, що зацікавився ..
rancid_banana

4

FiveFiveFive

Пропускає перший раунд і пропонує 555 доларів на решту раундів. В останньому раунді відбудеться все, якщо у двох інших ботів не буде такої ж кількості (і, мабуть, буде вилучено).

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

4

Майже всі в

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

Завжди ставки трохи менше, ніж у них.


4

Ескалація швидко

Кожен раунд збільшує частки своїх грошей (будь-ласка, повідомте мене про помилки, якийсь час я використовував Python)

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

4

Нижче середнього

Схожий на вище середнього, але йде трохи нижче

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)

4

HighHorse

Цей гравець пропонує всі свої гроші за мінусом поточного раунду, за винятком останнього раунду, куди він проходить все.

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

4

Зміна

Замінник між ставками одного під його максимум і тим, що йде все.

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

Я подумав, що мені потрібно знайти щось, що могло б перемогти мінус-одну Steadybox. :)


4

Модульний чорний список

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

Ставить найвищу суму, яка не відповідає модулі 500, для будь-яких цифр, які вони бачили раніше.

Відредаговано, щоб не застосовувати чорний список, коли він може отримати гарантовану виграш.


Цікаво, але здається, що останнє оновлення вашого іншого бота негативно впливає на цей бот. Наразі blacklist_modп'яте місце в лідері лідерів , тоді blacklistяк на другому місці. Якщо blacklistзамість цього використовується старіша версія , вона blacklistпадає на шосте місце, але blacklist_mod займає лідируюче місце !
Steadybox

Викидання blacklistвзагалі, здається, дає blacklist_modнавіть більш солідний результат , але це є непереконливим.
Steadybox

О, дякую, це має сенс - вони наближаються до одного і того ж алгоритму рано без старої логіки спеціального випадку, тому вони наступають один на одного. Я думаю, що я просто видалю оригінальний бот; Я не можу придумати вагомих причин тримати це.
гістократ

4

Евристика

Heurist розглядає цю гру як один з повторюваних ймовірності, тому він знає , де провести межу.

Він також скупий, тому він призначає мінімальний мінімум, необхідний для виграшу, коли зможе.

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

Відмова: max_bidпідлягає зміні


4

bob_hater

Цей бот не любить Боба, і тому він завжди буде ставити 2 $, щоб виграти проти Боба.

class bob_hater:
    def play_round(bob,will,loose):
        return 2

4

Випендрюватися

Це той хлопець, який проявляє свої математичні здібності в ситуаціях, які справді не вимагають нічого такого складного. До останнього раунду (в який він проходить все-все) він використовує логістичну модель для визначення своєї заявки, тим більше, якщо у його ворогів залишиться більша частина їх грошей.

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)

Використана логістична крива - f (x) = 1 / (1 + e -8 (x-0,5) ), де x - відношення поточного ворога-грошей до загального потенційного ворога-грошей. Чим більше інших, тим більше він пропонує ставки. Це може отримати вигоду від того, що в першому раунді було майже 500, але не дуже 500 доларів.


3

AntiMaxer

Зрівняйте найвищу суму, яку ми можемо дозволити за всі гроші гравця. Викличе будь-якого бота, який збирається на all-in у цьому раунді.

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)    

3

Простий бот

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

Майже такий самий, як пацієнт Бот, але не такий терплячий. Хоча отримує набагато кращий результат, ніж його.


3

Wingman 2

Якщо один крилатий чоловік хороший, два повинні бути кращими?

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

Ваш код не буде працювати, тому що вам потрібні відступи для речей у класі
HyperNeutrino

Цікаво, що обоє ваших крилатих, здається, перемагають вашого оригінального бота (посилання із пастбіном містить посилання TIO, яке занадто довго для публікації в коментарі і навіть занадто довго для укорочення URL-адрес ...)
Steadybox

1
Я виявив, що результати були дуже чутливі до пулу інших ботів; незначні зміни величини приросту, здається, мають непропорційний результат.
rancid_banana
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.