Давайте поиграем в Reaper - закрыто для подачи заявок

13

ПРИМЕЧАНИЕ : победителем этого конкурса является Джек !!! Больше никаких заявок не будет принято.

Вот чат для этого испытания . Это мой первый, поэтому я открыт для предложений!

Жнец - это игровая концепция, разработанная «Искусством решения проблем», которая включает терпение и жадность. После внесения изменений в игру, чтобы она соответствовала конкурсу в стиле KOTH (спасибо @NathanMerrill и @dzaima за ваши предложения и улучшения), вот задача.

Игра работает следующим образом: у нас есть значение, известное как Reap, которое умножается на данную константу каждый тик. После каждого тика каждый бот имеет возможность «пожинать», что означает добавление текущего значения Reap к своему счету и уменьшение Reap до 1.

Тем не менее, есть фиксированное количество тиков, которые бот должен ждать между «жатками», и фиксированное количество очков, необходимое для победы в игре.

Достаточно просто? Вот ваши входные данные:

I / O

Вы должны написать функцию в Python 3, которая принимает 3 входа. Первый self, используется для ссылки на объекты класса (показано позже). Второе - это Reapтекущая стоимость Жатвы, которую вы заработаете, если будете «пожинать». Третий - prevReapсписок ботов, которые были получены во время предыдущего тика.

Другие объекты, к которым вы можете получить доступ в своей функции:

self.obj: An object for your use to store information between ticks.
self.mult: The multiplier that Reap is multiplied by each tick
self.win: The score you need to win
self.points: Your current set of points
self.waittime: The amount of ticks that you must wait between reaps during the game
self.time: The number of ticks since your last reap
self.lenBots: The number of bots (including you) in the game.
self.getRandom(): Use to produce a random number between 0 and 1.

Вы НЕ ДОЛЖНЫ редактировать содержимое этих объектов, за исключением self.obj.

Вы должны выводить, 1чтобы пожинать, и все остальное (или ничего), чтобы не пожать. Обратите внимание, что если вы пожнете, когда не дождетесь достаточно тиков, я проигнорирую тот факт, что вы решили пожинать.

правила

Параметры я буду использовать это winning_score=10000, multiplier=1.6-(1.2/(1+sqrt(x))), waittime = floor(1.5*x)где xэто количество ботов в Koth.

  • Игра заканчивается, когда игрок (или несколько) достигает выигрышного счета.
  • Когда несколько ботов просят пожинать одновременно, приоритет отдается ботам, которые ждали дольше (в случае связей, боты, которые ждали максимальное время, все могут пожинать и получать очки в Жатве)
  • Ваш бот должен занять в среднем не более 100 мс на 5 тиков.
  • Если вы хотите импортировать библиотеки, спросите! Я попытаюсь добавить любые библиотеки, которые смогу запустить на настольной версии Python (математика уже импортирована: не стесняйтесь ее использовать)
  • Все стандартные лазейки для KoTH, такие как боты-дубликаты, боты 1-го уровня и т. Д., Также запрещены.
  • Любые боты, которые используют любую случайность, должны использовать предоставленную getRandomмной функцию.

Вы можете найти контроллер в ссылке TIO ниже. Чтобы использовать его, добавьте имя вашей функции BotListв виде строки, а затем добавьте функцию в код. Изменить, multiplierчтобы изменить то, что Reap умножается на каждый тик, изменить, winning_scoreчтобы изменить количество очков, необходимое для завершения игры, и изменить, waittimeчтобы изменить количество тиков, ожидающих между повторениями.

Для вашего удобства, вот несколько примеров (и довольно глупых) ботов. Отправка ботов, подобных этим, не будет разрешена. Тем не менее, они демонстрируют, как работает контроллер.

def Greedybot(self,Reap, prevReap):
    return 1
def Randombot(self,Reap, prevReap):
    if self.obj == None:
        self.obj=[]
    self.obj.append(prevReap)
    if self.getRandom()>0.5:
        return 1

Для тех, кто заинтересован, вот Контроллер с 15 встроенными в него представлениями: Попробуйте онлайн

ЗАКЛЮЧИТЕЛЬНЫЕ РЕЗУЛЬТАТЫ

WOO ОНИ НАКОНЕЦ ЗДЕСЬ! Проверьте ссылку TIO выше, чтобы увидеть, какой код я использовал для генерации итоговых результатов. Результаты не очень интересные. За 1000 прогонов, которые я сделал с разными случайными семенами, результаты были

1000 wins - Jack
0 wins - everyone else

Поздравляем победителя Баунти Джека! (он же @Renzeee)

Дон Тысяча
источник
Допустим, два бота пожинают одновременно, и побеждает тот, у кого больше времени ожидания. Будет ли у другого бота также включено время ожидания, несмотря на то, что он не смог на самом деле пожинать этот раунд, тратя впустую свой «пожинать»? И что происходит, когда два бота пожинают одновременно, с одинаковым временем ожидания?
Кевин Круйссен
1
Это разрешено использовать len(BotList)?
Renzeee
1
@Renzeee Ooo не думал об этом! Я сделаю быструю модификацию.
Дон Тысяча
1
@Renzeee О, это, конечно, что-то полезное для рассмотрения. Мог бы сделать второго бота, похожего на мой Every 50, но с фактическими вычислениями в самом боте, вместо того, что я делал в своем описании на основе 25ботов в игре. Однако сначала нужно немного подождать, чтобы увидеть ботов других людей. Рашабх Мехта , будет ли крайний срок / окончательная дата, когда будут запущены все боты и определен победитель?
Кевин Круйссен
1
@Rushabh Мехта Gotcha, я воздержусь. Я просто спросил b / c, что самостоятельно отслеживаю счет и время ожидания других ботов, чтобы их отстреливать, и мне лень. :)
Триггернометрия

Ответы:

9

Нерешительный Twitchy Mess

def mess(self, Reap, prevReap):
    if not hasattr(self.obj, "start"):
            self.obj.start = False
    if self.time < self.waittime:
        return 0
    if self.points + Reap >= self.win:
            return 1
    if Reap >= self.waittime / (self.lenBots + 2):
        self.obj.start = True
    if self.obj.start:
        return 1 if self.getRandom() > 0.2 else 0
    return 1 if self.getRandom() > 0.8 else 0

Этот бот сначала выполняет обычные проверки (Могу ли я пожинать, могу ли я выиграть?), А затем ищет целевое значение, прежде чем оно получит. Тем не менее, он нерешителен, поэтому, когда он достигает цели, он задается вопросом, сколько еще может ждать, и не пожинает сразу. Кроме того, он дергается, поэтому может случайно «нажать на кнопку» и пожать раньше цели.

Интересный факт: именно так я и играю в жнец как человек.

Quintec
источник
Хороший бот +1. Я немного подробнее расскажу об этом. Присоединяйтесь к чату, если вы еще этого не сделали
Дон Тысяча
@RushabhMehta Теперь с меньшей нерешительностью; p
Quintec
Я добавлю ваши изменения, когда смогу!
Дон Тысяча
9

снайпер

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

РЕДАКТИРОВАТЬ:

  • Если пожинает, чтобы выиграть, пожинать.
  • Если никто не> = 70% выигравшего счета:

    • Если у всех остальных время восстановления, подождите, пока пожнет последний момент.
    • Если кто-то еще выиграет, пожав текущее значение, и они активны сейчас или будут активны в следующем ходу, пожинать.
    • Если по крайней мере половина других пользователей перезаряжается, попытайтесь пожать. Это затрудняет нацеливание на конкретных противников и поэтому было удалено.
    • В противном случае, пожинайте 25% времени (по сути, чтобы гарантировать, что этот бот действительно пожинает ИНОГДА, на тот случай, если случится что-то странное, как будто все ждут несколько ходов).
  • Если кто-то>> 70% выигравшего счета:

    • Если Снайпер может выиграть тай-брейк, и следующий раунд будет выше среднего значения Reap для противника с наибольшим количеством очков, пожинать
    • Если на следующий ход противник с наибольшим количеством очков оставит время восстановления, пожнитесь.
def Sniper(self, Reap, prevReap):
    # initialize opponents array
    if not hasattr(self.obj, "opponents"):
        self.obj.opponents = {}

    # initialize previous Reap value
    if not hasattr(self.obj, "lastReap"):
        self.obj.lastReap = 0

    # increment all stored wait times to see who will be "active" this turn
    for opponent in self.obj.opponents:
        self.obj.opponents[opponent]["time"] += 1

    # update opponents array
    for opponent in prevReap:
        # don't track yourself, since you're not an opponent
        if opponent != "Sniper":
            # initialize opponent
            if opponent not in self.obj.opponents:
                self.obj.opponents[opponent] = {"time": 0, "points": 0, "num_reaps": 0, "avg": 0}
            self.obj.opponents[opponent]["time"] = 0
            self.obj.opponents[opponent]["points"] += self.obj.lastReap
            self.obj.opponents[opponent]["num_reaps"] += 1
            self.obj.opponents[opponent]["avg"] = self.obj.opponents[opponent]["points"] / self.obj.opponents[opponent]["num_reaps"]

    # done "assigning" points for last round, update lastReap
    self.obj.lastReap = Reap

    # get current 1st place(s) (excluding yourself)
    winner = "" if len(self.obj.opponents) == 0 else max(self.obj.opponents, key=lambda opponent:self.obj.opponents[opponent]["points"])

    # you are ready now
    if self.time >= self.waittime:
        # current Reap is sufficient for you to win
        if self.points + Reap >= self.win:
            return 1

        if (
                # a 1st place exists
                winner != ''
                # if current 1st place is close to winning
                and self.obj.opponents[winner]["points"] / self.win >= .7
        ):
            if (
                    # next round's Reap value will be above opponent's average Reap
                    (Reap * self.mult >= self.obj.opponents[winner]["avg"])
                    # we have been waiting at least as long as our opponent (tiebreaker)
                    and self.time >= self.obj.opponents[winner]["time"]
            ):
                return 1

                # current 1st place opponent will be active next round
            if self.obj.opponents[winner]["time"] + 1 >= self.waittime:
                return 1

        else:
            if (
                    # everyone is waiting for their cooldown
                    all(values["time"] < self.waittime for key, values in self.obj.opponents.items())
                    # and we're tracking ALL opponents
                    and len(self.obj.opponents) == self.lenBots - 1
                    # at least one person will be ready next turn
                    and any(values["time"] + 1 >= self.waittime for key, values in self.obj.opponents.items())
            ):
                return 1

            if (
                    # opponent will be active next round
                    any( (values["time"] + 1 >= self.waittime)
                         # current Reap value would allow opponent to win
                         and (values["points"] + Reap >= self.win) for key, values in self.obj.opponents.items())
            ):
                return 1

            if (
                    # a 1st place exists
                    winner != ''
                    # current 1st place opponent will be active next round
                    and (self.obj.opponents[winner]["time"] + 1 >= self.waittime)
                    # next round's Reap value will be above their average Reap
                    and (Reap * self.mult >= self.obj.opponents[winner]["avg"])

            ):
                return 1

            # # at least half of opponents are waiting for their cooldown
            # if sum(values["time"] < self.waittime for key, values in self.obj.opponents.items()) >= (self.lenBots - 1) / 2:
            #     return 1

            # 25% of the time
            if self.getRandom() <= .25:
                return 1

    # default return: do not snipe
    return 0

Скучать

Просто для забавы, этот бот был привезен другом и на самом деле не хочет быть здесь. Они бросают d16 до тех пор, пока не получат число от 1 до 9, затем они пытаются пожинать всякий раз, когда число содержит выбранную цифру. (Поиск d10 нарушил бы игру, что грубо, а 0 слишком просто!)

def Bored(self, Reap, prevReap):
    # if this is the first round, determine your fav number
    if not hasattr(self.obj, "fav_int"):
        r = 0

        while r == 0:
            # 4 bits are required to code 1-9 (0b1001)
            for i in range(0, 4):
                # flip a coin. Puts a 1 in this bit place 50% of the time
                if self.getRandom() >= .50:
                    r += 2**i
            # if your random bit assigning has produced a number outside the range 1-9, try again
            if not (0 < r < 10):
                r = 0

        self.obj.fav_int = r

    # you are ready now
    if self.time >= self.waittime:
        # current Reap is sufficient for you to win
        if self.points + Reap >= self.win:
            return 1
        # do you like this value?
        if str(self.obj.fav_int) in str(Reap):
            return 1
        # do you like your wait time?
        if self.time % int(self.obj.fav_int) == 0:
            return 1

    # default return: do not reap
    return 0
Triggernometry
источник
Хороший бот! +1. Будет интересно посмотреть, как это происходит.
Дон Тысяча
1
Я думаю, что вы должны использовать self.obj.opponents[opponent]["time"] += 1в первом цикле for и self.obj.lastReapв конце второго цикла for. Кроме того, хорошие идеи. Мне любопытно, как это сработает против многих других ботов. Когда я использую много жадных и случайных ботов, он будет пожинать как можно скорее, потому что большую часть времени половина ботов не может пожать. Но, конечно, это не реалистичные конкуренты.
Renzeee
@Triggernometry Вы должны присоединиться к чату. Кроме того, проверьте изменения, которые я отправил. Пожалуйста, убедитесь, что изменения, которые я внес в ваш бот, верны.
Дон Тысяча
7

разъем

Это простой бот с 4 правилами:

  • Не пожинайте, когда он ничего не делает
  • Всегда пожинайте, когда пожинаете, мы можем выиграть
  • Также пожинайте, когда не было собрано 3 галочки
  • В противном случае ничего не делать

Я оптимизировал 3 тика по сравнению с текущими существующими ботами (Sniper, grim_reaper, Every50, mess, BetterRandom, Averager и некоторые другие).

def Jack(self, Reap, prevReap):
    if self.time < self.waittime:
        return 0
    if self.win - self.points < Reap:
        return 1
    if self.mult ** 3 <= Reap:
        return 1
    return 0

Я пытался остаться со своим старым решением (5 тиков), но также пожинаю плоды, если вы не пожинаете дольше, чем X тиков, а затем пожинаете после того, как во время непроигрыша прошло меньше тиков (то есть 5, если вы ждали дольше, чем я) .waittime + 5, также пожинать, если не получено 4 галочки). Но это не улучшилось, просто всегда пожиная после 4 тиков вместо 5.

Renzeee
источник
5

Каждые 50

Эти боты будут пожинать каждый раз, когда Reapсумма превышает 50.

Почему 50?

Если я сделаю предположение, что в игре будет 25 ботов, это означает, что multiplier = 1.6-(1.2/(1+sqrt(25))) = 1.4и waittime = floor(1.5*25) = 37. Поскольку Reapначинается в 1, он будет расти так:

Round: 1  2    3     4      5      6      7      8       9       10      11      12      13      14      15       16       17       18       19       20       etc.
Reap:  1  1.4  1.96  2.744  ~3.84  ~5.39  ~7.53  ~10.54  ~14.76  ~20.66  ~28.92  ~40.50  ~56.69  ~79.37  ~111.12  ~155.57  ~217.79  ~304.91  ~426.88  ~597.63  etc.

Как вы можете видеть, он достигает уровня выше 50 после 13 тиков. Так как Reapбудет сброшен на 1 каждый раз , когда бот жмет, а waittimeдля робота , который жмет на 37, вероятность того, бот жмет раньше , чем позже довольно высоко, особенно с ботами , похожими на пример GreedyBot, который будет жать , как только их waittimeIS снова доступно Сначала я хотел сделать 200, что является 17-м тактом, что-то посередине из 37 тиков времени ожидания, но при условии, что в игре 25 ботов, есть довольно высокий шанс, что кто-то другой выхватит Reapдо меня. Поэтому я понизил его до 50. Это все еще хорошее округленное число, но особенно потому, что это 13-й тик (с 25 ботами), а 13 и «жатва» также вписываются в тот же «злой» жанр.

Код:

Код смехотворно тривиален ..

def Every50(self, Reap, prevReap):
  return int(Reap > 50)

Примечания:

Этот бот довольно плохой с небольшим количеством ботов в игре. Пока я оставлю это, и я мог бы сделать лучшего бота, фактически вычисляющего лучшее время Reap. С очень низким количеством ботов в игре, waittimeконечно, также намного меньше, так что даже он GreedyBotможет легко выиграть от этого бота, если waittimeон достаточно низок.

Надеюсь, что больше людей добавят намного больше ботов. ;п

Кевин Круйссен
источник
def Every49(self, Reap, prevReap): return Reap > 49 Ваш ход.
Quintec
@ Quintec Хе-хе. С 25 ботами в игре это будет означать, что это все еще 13 тик, и мы оба выигрываем Рип, так что я не против поделиться победой с вами, лол. ; p
Кевин Круйссен,
Возможно, вы захотите intобойти неравенство, так как 1 - это настоящая команда
Дон Тысяча
@Quintec, я знаю, что ты шутишь, но я не позволю 1-го или дублирующим ботам
Дон Тысяча
@RushabhMehta Я не очень часто программирую на Python, поэтому уже сомневался, стоит ли мне добавлять приведение, чтобы сделать Trueявный 1. Я подумал, что True == 1проверка все равно вернется, если Trueмой бот добавит ее в списки Reapersвашей nextфункции, но я все равно добавил приведение к int, как вы и предлагали.
Кевин Круйссен,
5

усреднитель

def Averager(self,Reap,prevReap):
    returner = 0
    if not hasattr(self.obj,"last"):
        self.obj.last = Reap
        self.obj.total = 0
        self.obj.count = 0
        returner = 1
    else:
        if len(prevReap) > 0:
            self.obj.total += self.obj.last
            self.obj.count += 1
        self.obj.last = Reap
    if self.obj.count > 0 and Reap > self.obj.total / self.obj.count:
        returner = 1
    return returner

Этот бот пытается пожинать всякий раз, когда текущее значение Reap превышает среднее значение Reaped.

Джо.
источник
Очень хороший бот! +1
Дон Тысяча
Я очень раздражен и впечатлен тем, что такой простой алгоритм так легко побеждает всех. Прекрасная работа!
Триггонометрия
3

Смерть с косой

Этот бот сохраняет среднее значение всех предыдущих результатов, а также время ожидания каждого бота. Она пожинает, когда она ждала дольше, чем 3/4 других ботов, и пожинает, по крайней мере, 3/4 размера среднего жатвы, замеченного до сих пор. Цель состоит в том, чтобы получить много разумного размера, с низким риском пожинает плоды.

def grim_reaper(self, Reap, prevReap):
    if self.obj == None:
        self.obj = {}
        self.obj["reaps"] = []
        self.obj["prev"] = 1
        self.obj["players"] = {i:0 for i in range(math.ceil(self.waittime / 1.5))}
    if Reap == 1 and len(prevReap) > 0:
        self.obj["reaps"].append(self.obj["prev"])
        for player in prevReap:
            self.obj["players"][player] = 0

    retvalue = 0
    if (len(self.obj["reaps"]) > 0 
         and Reap > sum(self.obj["reaps"]) / len(self.obj["reaps"]) * 3. / 4.
         and sum([self.time >= i for i in self.obj["players"].values()]) >= len(self.obj["players"].values()) * 3 / 4):
        retvalue = 1

    for player in self.obj["players"]:
        self.obj["players"][player] += 1
    self.obj["prev"] = Reap
    return retvalue

Редактировать: Исправлены некоторые неловкие синтаксические ошибки.

Попробуйте онлайн

Захари Хлопок
источник
1
Вы должны использовать self.obj.reapsвместо self.reapsи self.objвместо self.objectи prevReapвместо prevLeapи добавить () после self.obj.players.valuesдважды. И я думаю, self.obj.reaps = []что не будет работать, если не self.objявляется объектом. Я не совсем уверен, что тогда все будет работать так, как задумано, и верно ли все, что я сказал, но после этих изменений и использования фиктивного объекта, self.objкогда его еще нет, ваш код компилируется для меня.
Рензи
@ZacharyColton Вам не нужно импортировать математику. Это уже импортировано
Дон Тысяча
@RushabhMehta Я добавил class Object(object):[newline] passсверху и использовал self.obj = Object()в if not hasattr(..)(если я правильно помню).
Рензи
@Renzeee ага
Дон Тысяча
@ZacharyCotton Вы должны присоединиться к чату.
Дон Тысяча
3

BetterRandom

def BetterRandom(self,reap,prevReap):
    return self.getRandom()>(reap/self.mult**self.waittime)**-0.810192835

Бот основан на предположении, что шанс пожать должен быть пропорционален размеру пожатия, потому что точка - это точка, независимо от того, когда она получена. Всегда есть очень маленький шанс пожать, это сохраняет поведение пригодным для использования. Сначала я подумал, что это будет прямо пропорционально, и предположил, что константа пропорциональности примерно равна 1/mult^waittime(максимальный доход при условии, что хотя бы один бот играет жадным образом), после запуска некоторых симуляций я обнаружил, что это действительно оптимальная константа. Но бот по-прежнему был лучше, чем рандом, поэтому я пришел к выводу, что отношение не было прямо пропорциональным, и добавил константу, чтобы вычислить, каково это отношение. После некоторых симуляций я обнаружил, что набор ботов для моего теста -1.5был оптимальным. Это на самом деле соответствует обратно пропорциональной зависимости между шансом пожинать иreap*sqrt(reap)что удивительно. Поэтому я подозреваю, что это сильно зависит от конкретных ботов, поэтому версия этого бота, которая вычисляет k во время игры, была бы лучше. (Но я не знаю, разрешено ли вам использовать данные предыдущих раундов).

РЕДАКТИРОВАТЬ: Я сделал программу, чтобы найти вид пропорциональности автоматически. На тестовом наборе ["myBot("+str(k)+")","Randombot","Greedybot","Every50","Jack","grim_reaper","Averager","mess"]я нашел новое значение.

fejfo
источник
я скоро добавлю новые статистические данные, используя вашего бота
Don Thousand
1
Похоже, (reap/self.mult**self.waittime)**-0.810192835всегда выше 1, то есть self.getRandom () никогда не выше.
Рензи
@fejfo вам также разрешено использовать данные предыдущих раундов. Вот для чего self.obj. Чтобы увидеть некоторые примеры того, как его использовать, посмотрите на некоторые другие боты, которые его используют.
Дон Тысяча
3

цель

def target(self,Reap,prevReap):
    if not hasattr(self.obj, "target_time"):
        self.obj.target_time = -1
        self.obj.targeting = False
        self.obj.target = None
    if self.obj.target_time >= 0:
        self.obj.target_time += 1

    if self.time < self.waittime:
            return 0
    if self.points + Reap >= self.win:
        return 1
    if len(prevReap) > 0:
        if not self.obj.targeting:
            self.obj.target_time = 0
            self.obj.target = prevReap[int(self.getRandom() * len(prevReap))]
            self.obj.targeting = True
    if self.waittime <= self.obj.target_time + 1:
        self.obj.targeting = False
        self.obj.target = None
        self.obj.target_time = -1
        return 1
    return 0

Мои шансы выиграть в беспорядке практически отсутствуют, поэтому самое время испортить всех остальных ботов как можно больше! :)

Этот бот функционирует подобно снайперу. Всякий раз, когда кто-то пожинает, он выбирает случайную цель от того, кто пожинает. Затем он просто ждет, пока та цель почти не сможет пожать снова, и выстрелит. Тем не менее, это не меняет фокус - как только вы были выбраны и заблокированы, вы не можете убежать :)

Quintec
источник
2

EveryN

Я думаю, пришло время для моего второго бота прямо перед крайним сроком.

Этот бот будет:

  • Пропустить, когда все еще в ожидании последнего пожинания
  • Пожинать, когда он может победить
  • Жать, когда никто не пожнет хотя бы nраундов, где nрассчитывается сn = 3 + ceil(self.waittime / self.lenBots)

Код:

def every_n(self, Reap, prevReap):
    # Initialize obj fields
    if not hasattr(self.obj, "roundsWithoutReaps"):
        self.obj.roundsWithoutReaps = 0

    # Increase the roundsWithoutReaps if no bots reaped last round
    if len(prevReap) < 1:
        self.obj.roundsWithoutReaps += 1
    else
        self.obj.roundsWithoutReaps = 0

    # Skip if you're still in your waiting time
    if self.time < self.waittime:
        return 0
    # Reap if you can win
    if self.win - self.points < Reap:
        return 1

    # i.e. 25 bots: 3 + ceil(37 / 25) = 5
    n = 3 + math.ceil(self.waittime / self.lenBots)

    # Only reap when no bots have reaped for at least `n` rounds
    if self.obj.roundsWithoutReaps >= n:
        self.obj.roundsWithoutReaps = 0
        return 1

    return 0

Я не программирую на Python очень часто, поэтому, если вы видите какие-либо ошибки, дайте мне знать.

Кевин Круйссен
источник
Святое длинное имя переменной. (Также, PEP: python.org/dev/peps/pep-0008 )
Quintec,
@Quintec Изменен отступ в 2 пробела на 4; сократил subsequentRoundsWithoutReapsдо roundsWithoutReaps; используется строчная буква с подчеркиванием для имени метода; и убрал скобки в операторах if. Благодарю.
Кевин Круйссен
Нет проблем! (Технически это должен быть rounds_without_reaps, но на самом деле это не проблема, поскольку в этой задаче также используется mixedCamelCase, поэтому это не имеет значения)
Quintec
@ Quintec Ах, хорошо. Я посмотрел на prevReapи, lenBotsи такие и предполагаемые переменные, как camelCase, как в Java. ;) Ну, в любом случае, мы все равно должны работать. 2 вместо 4 пробелов с отступами, вероятно, вызвали бы некоторые проблемы, так что спасибо в любом случае.
Кевин Круйссен
2

Продолжается: Мой проект по расширению T4T до каждого открытого KOTH.

Синица для Тат

def t4t(self, r, p):
    if(not hasattr(self.obj,"last")): self.obj.last = self.win
    if(p):
        self.obj.last = r
        return 0

    # The usual checks
    if self.time < self.waittime:
        return 0
    if self.points + r >= self.win:
        return 1

    if(r >= self.obj.last):
        return 1

Око за п татов

def t4nt(self, r, p):
    n = 5 # Subject to change
    if(not hasattr(self.obj,"last")): self.obj.last = [self.win]*n

    if(p):
        self.obj.last.append(r)
        self.obj.last.pop(0)
        return 0

    # The usual checks
    if(self.time < self.waittime):
        return 0
    if(self.points + r >= self.win):
        return 1

    if(r >= self.obj.last[0]):
        return 1

Kevin

Просто чтобы держать тебя в тонусе.

def kevin(just, a, joke):
    return 0
SIGSTACKFAULT
источник
Убедитесь, что помните, self.lastэто не вещь, но вы можете сделать self.obj.lastвещь! В любом случае, я добавлю всех трех ваших ботов для мемов +1
Дон Тысяча
Да, я идиот. Исправлена.
SIGSTACKFAULT
@RushabhMehta Просто прошел и заставил их на самом деле работать. пожалуйста, отредактируйте.
SIGSTACKFAULT
звучит хорошо! Присоединяйтесь к GC, я выложу некоторые частичные результаты там
Don Thousand
1

Средний Джо

Я был вдохновлен Averager и создал бота, который вычисляет в среднем, сколько ходов требуется, прежде чем кто-то пожнет и попытается пожинать один ход до этого.

def average_joe(self, Reap, prevReap):

    if not hasattr(self.obj, "average_turns"):
        self.obj.turns_since_reap = 1
        self.obj.total_turns = 0
        self.obj.total_reaps = 0
        return 1

    if len(prevReap) > 0:
        self.obj.total_turns = self.obj.total_turns + self.obj.turns_since_reap
        self.obj.total_reaps += 1
        self.obj.turns_since_reap = 0
    else:
        self.obj.turns_since_reap += 1

    # Don't reap if you are in cooldown
    if self.time < self.waittime:
        return 0

    # Reap if you are going to win
    if self.win - self.points < Reap:
        return 1

    # Reap if it is one turn before average
    average_turns = self.obj.total_turns / self.obj.total_reaps

    if average_turns - 1 >= self.obj.turns_since_reap:
        return 1
    else:
        return 0
DobromirM
источник
Я добавлю это завтра.
Дон Тысяча
1

HARDCODED

Да, это так.

def HardCo(self,reap,prevReap):
    return reap > 2

Вместо усреднения по прошлым результатам используйте предварительно рассчитанное среднее значение для типичного прогона. В любом случае, со временем не станет лучше.

гигабайт
источник