Những nhà thám hiểm trong di tích


27

Trình điều khiển thử nghiệmThảo luận về thử tháchGửi nhà thám hiểm

Phòng kho báu ( Nguồn hình ảnh )

Một số nhà thám hiểm đối thủ đang đột kích vào đống đổ nát để tìm kho báu, nhưng họ chỉ có thể mang theo rất nhiều tại một thời điểm và có giới hạn chịu đựng. Họ muốn có được kho báu quý giá nhất và thoát ra trước khi họ quá mệt mỏi để tiếp tục. Họ đang cố gắng trở nên giàu có nhất có thể từ các shenanigans cướp bóc của họ.

Trò chơi

Mỗi nhà thám hiểm bắt đầu trong căn phòng đầu tiên của ngục tối với 1000 điểm sức chịu đựng và 50kg không gian trong ba lô của họ.

Trò chơi vận hành theo kiểu lần lượt, với tất cả người chơi giải quyết lần lượt đồng thời. Mỗi lượt, bạn có thể thực hiện một trong các hành động sau:

  • Chuyển đến phòng tiếp theo.
  • Di chuyển đến phòng trước.
  • Trả giá để có một kho báu.
  • Thả một kho báu.

Di chuyển giữa các phòng cần 10 sức chịu đựng, cộng thêm 1 cho mỗi 5kg hiện tại trong ba lô của bạn, làm tròn lên. Chẳng hạn, một nhà thám hiểm mang 3kg kho báu cần 11 sức chịu đựng để di chuyển và một người mang 47kg cần 20 sức chịu đựng để di chuyển.

Đánh rơi kho báu cần 1 sức chịu đựng bất kể kho báu bị rơi.

Khi thoát khỏi đống đổ nát, người chơi sẽ không quay đầu nữa.

Nếu người chơi không thể thực hiện bất kỳ hành động nào trong số này (do thiếu sức chịu đựng hoặc không có kho báu), nhà thám hiểm của họ chết vì kiệt sức, làm đổ kho báu bị giữ của họ vào căn phòng hiện đang bị chiếm đóng. Tương tự, nếu người chơi cố gắng thực hiện một hành động không hợp lệ, nhà thám hiểm của họ sẽ bị giết bởi một cái bẫy thay vào đó, dẫn đến sự cố tràn kho báu tương tự.

Đấu thầu

Giá thầu tối thiểu cho một kho báu là 1 sức chịu đựng trên 1kg mà kho báu nặng. Bạn cũng có thể trả giá các điểm sức chịu đựng bổ sung để có nhiều khả năng có được kho báu hơn. Sức chịu đựng được trả giá được tiêu thụ bất kể kết quả là gì.

Trong trường hợp nhiều người chơi trả giá để nhận cùng một kho báu, người chơi trả giá cao nhất sẽ nhận được kho báu. Nếu có nhiều hơn một người chơi thực hiện giá thầu cao nhất, không ai trong số họ sẽ nhận được kho báu.

Điều kiện thắng

Người chơi có tổng giá trị kho báu lớn nhất là người chiến thắng. Trong trường hợp không thể có của một chiếc cà vạt, cà vạt sẽ có tổng trọng lượng nhỏ nhất, sau đó là số lượng báu vật nhỏ nhất, sau đó là giá trị của kho báu quý giá nhất, thứ hai có giá trị nhất, thứ ba ... cho đến khi chiếc cà vạt bị phá vỡ. Trong trường hợp gần như không thể có sự ràng buộc tại thời điểm này, người lái xe kiểm tra nói "vặn nó" và do đó người chiến thắng được xác định tùy ý.

Trong bối cảnh của giải đấu, người chơi sẽ được xếp hạng với vị trí thứ nhất nhận được 10 điểm, vị trí thứ hai với 9 điểm, vị trí thứ ba với 8 điểm, v.v ..., với những người chơi và nhà thám hiểm đã chết không có kho báu ghi 0 điểm.

Về di tích

  • Mỗi phòng ban đầu chứa từ r3+3r2+5báu vật. (Trong đórlà số phòng)
  • Có rất nhiều phòng tùy ý, chỉ giới hạn bởi sức chịu đựng của các nhà thám hiểm và sẵn sàng khám phá.
  • Mỗi kho báu sẽ có một giá trị tiền tệ (tính bằng $) và trọng lượng (tính theo kg).
    • Kho báu có xu hướng có giá trị và phong phú hơn khi bạn đi sâu hơn vào đống đổ nát.
  • Các công thức cụ thể để tạo kho báu như sau: (sử dụng ký hiệu xdy cho cuộn súc sắc)
    • Trọng lượng được tạo ra đầu tiên bằng cách sử dụng công thức 2d62 (tối thiểu là 1)
    • Giá trị kho báu sau đó được tạo thông qua (trong đó là số phòng và là trọng lượng)1d[10w]+2d[5r+10]rw

Thông tin hiển thị cho người chơi

Ở mỗi lượt, người chơi nhận được thông tin sau:

  • Số lượng phòng họ hiện đang ở. Đây là 1 chỉ mục, vì vậy về mặt khái niệm lối ra là "phòng 0"
  • Một danh sách các kho báu hiện đang ở trong phòng
  • Một danh sách những người chơi khác hiện đang ở trong phòng.
  • Kho báu vật hiện tại của bạn
  • Mức độ sức chịu đựng hiện tại của bạn

Mã hóa

Trình điều khiển thử nghiệm có thể được tìm thấy ở đây .

Bạn nên triển khai một lớp con của Adventurerlớp này :

class Adventurer:
    def __init__(self, name, random):
        self.name = name
        self.random = random

    def get_action(self, state):
        raise NotImplementedError()

    def enter_ruins(self):
        pass

Bạn chỉ cần ghi đè get_actionphương thức. enter_ruinsđược chạy trước khi trò chơi bắt đầu và là cơ hội để bạn chuẩn bị bất cứ điều gì bạn muốn để sẵn sàng cho trò chơi. Bạn không cần ghi đè __init__, và bạn thực sự không nên . Nếu bạn __init__gặp sự cố, bạn sẽ bị loại.

get_actionnhận được một đối số duy nhất là namedtuplevới các trường sau (theo thứ tự này, nếu bạn muốn hủy bỏ):

  • room: số phòng bạn hiện đang ở
  • treasures: danh sách các báu vật trong phòng
  • players: danh sách những người chơi khác trong phòng. Bạn chỉ nhận được tên người chơi theo cách này, vì vậy bạn không biết bot nào đang kiểm soát họ hoặc kho / sức chịu đựng của họ.
  • inventory: danh sách các báu vật trong ba lô của bạn
  • stamina: mức độ sức chịu đựng hiện tại của bạn

Đối tượng này cũng cung cấp hai thuộc tính tiện ích:

  • carry_weight: tổng trọng lượng của tất cả các báu vật bạn đang mang
  • total_value: tổng giá trị của tất cả các báu vật bạn đang mang

Các danh sách treasuresinventorychứa namedtuples với các thuộc tính sau:

  • name: tên của kho báu (cho mục đích thẩm mỹ)
  • value: giá trị tiền tệ của kho báu tính bằng $.
  • weight: trọng lượng của kho báu tính bằng kg

get_action sẽ trả về một trong các giá trị / mẫu sau:

  • 'next'hoặc 'previous'để chuyển đến phòng tiếp theo / trước
  • 'take', <treasure index>, <bid>(vâng, như một tuple, mặc dù bất kỳ chuỗi nào cũng sẽ hoạt động về mặt kỹ thuật) để đấu giá kho báu theo chỉ số đã cho trong danh sách kho báu của phòng. Cả hai đối số nên là số nguyên. Phao sẽ được làm tròn xuống.
  • 'drop', <inventory index>để thả kho báu mang theo được tìm thấy ở chỉ số nhất định. Chỉ số nên (tự nhiên) là một số nguyên.

Những hạn chế khác

  • Bạn chỉ có thể sử dụng ví dụ ngẫu nhiên được cung cấp cho bạn trong quá trình khởi tạo cho giả danh.
    • Bất cứ điều gì khác có thể giới thiệu chủ nghĩa không điều kiện hành vi đều không được phép. Mục đích ở đây là làm cho các bot hoạt động giống hệt nhau khi được cung cấp cùng một hạt giống để hỗ trợ kiểm tra các bot mới (và có khả năng xảy ra lỗi trong trình điều khiển thử nghiệm). Chỉ bức xạ vũ trụ nên gây ra bất kỳ sai lệch / không phá hủy.
    • Hãy nhớ rằng mã băm được chọn ngẫu nhiên trong Python 3, vì vậy hashkhông được phép sử dụng cho mọi quyết định. dicts vẫn ổn ngay cả khi sử dụng thứ tự lặp cho các quyết định vì đơn hàng đã được đảm bảo nhất quán kể từ Python 3.6.
  • Bạn không được phá vỡ trình điều khiển kiểm tra bằng cách sử dụng ctypeshack hoặc inspectstack voodoo (hoặc bất kỳ phương pháp nào khác). Có một số điều đáng sợ ấn tượng bạn có thể làm với các mô-đun. Xin đừng.
    • Mỗi bot được đóng hộp hợp lý thông qua các bản sao phòng thủ và tính bất biến tự nhiên của namedtuples, nhưng có một số lỗ hổng / khai thác không thể so sánh được.
    • Các chức năng khác từ inspectctypescó thể được sử dụng miễn là không được sử dụng để phá vỡ chức năng của bộ điều khiển.
    • Bất kỳ phương pháp lấy các phiên bản của các bot khác trong trò chơi hiện tại của bạn đều không được phép.
  • Bots nên hoạt động một mình và không được phối hợp với bất kỳ bot nào khác cho bất kỳ mục đích nào. Điều này bao gồm việc tạo ra hai bot với các mục tiêu khác nhau sao cho một người hy sinh bản thân vì thành công của người kia. Khi có hơn 10 đối thủ cạnh tranh, bạn thực sự sẽ không được đảm bảo có hai bot trong cùng một trò chơi và tên nhà thám hiểm không đưa ra bất kỳ dấu hiệu nào của lớp bot, vì vậy dù sao các loại chiến lược này cũng bị hạn chế.
  • Hiện tại không có hạn chế cứng về thời gian thực hiện, tuy nhiên tôi bảo lưu quyền hạn chế cứng trong tương lai nếu các giải đấu bắt đầu mất quá nhiều thời gian. Hãy hợp lý và cố gắng tiếp tục xử lý lần lượt dưới 100ms , vì tôi không lường trước được việc cần phải hạn chế dưới ngưỡng đó. (Các giải đấu sẽ diễn ra trong khoảng 2 giờ nếu tất cả các bot mất khoảng 100ms mỗi lượt.)
  • Lớp bot của bạn phải được đặt tên duy nhất trong số tất cả các bài nộp.
  • Bạn có thể không nhớ bất cứ điều gì giữa các trò chơi. (Tuy nhiên, bạn có thể nhớ mọi thứ giữa các lượt )
    • Đừng chỉnh sửa sys.modules. Bất cứ điều gì bên ngoài các biến thể hiện nên được coi là một hằng số.
  • Bạn không thể sửa đổi bất kỳ mã bot nào theo chương trình, bao gồm cả mã của bạn.
    • Điều này bao gồm xóa và khôi phục mã của bạn. Điều này là để làm cho việc gỡ lỗi và các giải đấu được sắp xếp hợp lý hơn.
  • Bất kỳ mã nào khiến bộ điều khiển gặp sự cố sẽ bị loại ngay lập tức. Trong khi hầu hết các trường hợp ngoại lệ sẽ bị bắt, một số có thể trượt qua và segfaults là không thể so sánh được. (Có, bạn có thể segfault trong Python nhờ ctypes)

Đệ trình

Để hỗ trợ trả lời cào, hãy cho biết tên bot của bạn ở đầu câu trả lời bằng một #Header1và đảm bảo câu trả lời của bạn bao gồm ít nhất một khối mã (chỉ câu đầu tiên trong câu trả lời của bạn sẽ được sử dụng). Bạn không cần bao gồm bất kỳ nhập khẩu hoặc tài liệu nào, vì chúng sẽ được thêm vào tự động bởi bộ cạp.

Tôi sẽ nghiêng về các câu trả lời hơn với các giải thích chi tiết và dễ hiểu. Những người khác có khả năng cư xử như vậy.

Nói một cách đơn giản, câu trả lời của bạn nên được định dạng như thế này:

# Name of Bot
Optional blurb

    #imports go here

    class BotName(Adventurer):
        #implementation

Explanation of bot algorithm, credits, etc...

(hiển thị dưới dạng)

Tên của Bot

Tùy chọn blurb

#imports go here

class BotName(Adventurer):
    #implementation

Giải thích về thuật toán bot, tín dụng, v.v ...

Chạy trình điều khiển thử nghiệm cục bộ

Bạn sẽ cần Python 3.7+ và tôi khuyên bạn cũng nên cài đặt tabulatequa pip. Quét trang này để gửi thêm yêu cầu lxmlrequests. Bạn cũng nên sử dụng một thiết bị đầu cuối có hỗ trợ thoát màu ANSI để có kết quả tốt nhất. Thông tin về cách thiết lập tính năng này trong Windows 10 có thể được tìm thấy ở đây .

Thêm bot của bạn vào một tệp trong thư mục con trong cùng thư mục với ruins.py( ruins_botstheo mặc định) và chắc chắn để thêm from __main__ import Adventurervào đầu mô-đun. Điều này được thêm vào các mô-đun khi trình cạp tải xuống trình của bạn và trong khi nó chắc chắn là hack, đây là cách đơn giản nhất để đảm bảo bot của bạn có quyền truy cập đúng Adventurer.

Tất cả các bot trong thư mục đó sẽ được tải động khi chạy, do đó không cần thay đổi gì thêm.

Giải đấu

Người chiến thắng cuối cùng sẽ được xác định trong một loạt các trò chơi với tối đa 10 bot trong mỗi trò chơi. Nếu có hơn 10 tổng số lần gửi, 10 bot hàng đầu sẽ được xác định bằng cách phân chia chúng một cách có hệ thống thành các nhóm 10 cho đến khi mỗi bot đã chơi (chính xác) 20 trò chơi. 10 bot hàng đầu sẽ được chọn từ nhóm này với điểm đặt lại và sẽ chơi trò chơi cho đến khi bot đầu tiên đạt được 50 điểm so với bot thứ hai hoặc cho đến khi 500 trò chơi được chơi.

Cho đến khi có ít nhất 10 lần gửi, các ô trống sẽ được lấp đầy bằng "Người say rượu", đi lang thang ngẫu nhiên qua đống đổ nát và lấy (và đôi khi thả) kho báu ngẫu nhiên cho đến khi hết sức chịu đựng và phải đi ra khỏi lối thoát.

Các giải đấu sẽ được tổ chức lại hàng tuần nếu có bài nộp mới. Đây là một thử thách KOTH mở không có ngày kết thúc.

Bảng xếp hạng

Từ chạy vào ngày 4 tháng 5 năm 2019 lúc 4:25 PM MDT: (2019-05-04 4:25 -6: 00)

Seed: K48XMESC
 Bot Class    |   Score |   Mean Score
--------------+---------+--------------
 BountyHunter |     898 |        7.301
 Scoundrel    |     847 |        6.886
 Accountant   |     773 |        6.285
 Ponderer     |     730 |        5.935
 Artyventurer |     707 |        5.748
 PlanAhead    |     698 |        5.675
 Sprinter     |     683 |        5.553
 Accomodator  |     661 |        5.374
 Memorizer    |     459 |        3.732
 Backwards    |     296 |        2.407

Cập nhật - 15 tháng 4: một vài cập nhật / làm rõ quy tắc

Cập nhật - 17 tháng 4: cấm một vài trường hợp đáng chú ý về các hành động bất chính như sửa đổi mã của các bot khác.

Cập nhật - 4 tháng 5: Bounty trao cho Sleafar vì đã tiêu diệt hoàn toàn Backwards. Xin chúc mừng!


1
Cuối cùng cũng đến rồi! Đoán tôi sẽ phải bắt đầu làm bot của tôi bây giờ.
Belhenix

12
Tại sao giới hạn cho một bot? Tôi có một vài ý tưởng loại trừ lẫn nhau, và tôi không cần phải đưa ra một bot hoàn toàn tốt mỗi khi tôi đưa ra một ý tưởng mới.

@Mnemonic, chủ yếu là để ngăn chặn việc gửi bài mới bằng cách sử dụng nhiều bot gần giống nhau. Lý do khác là để ngăn các bot làm việc cùng nhau, nhưng dù sao thì điều đó cũng bị cấm rõ ràng. Tôi sẽ xem xét cho phép nó. Những người ủng hộ cho phép nhiều bài nộp, nêu lên nhận xét của Mnemonic ở trên.
Beefster

1
@ Draco18s Nếu bạn đã pipcài đặt và bật PATH(mặc định cho các cài đặt mới hơn AFAIK) thì từ các cửa sổ, bạn có thể chạy pip install modulenametrong dấu nhắc lệnh. Đối với các trường hợp khác (mà tôi không biết), hãy truy cập pip , tìm kiếm mô-đun cần thiết và chọn một tùy chọn.
Artemis hỗ trợ Monica

1
Tôi đoán đây sẽ là 'không', nhưng chúng ta có được phép lưu thông tin qua giải đấu không? (ví dụ: khi một giá thầu hoạt động)
Artemis hỗ trợ Monica

Câu trả lời:


5

Viên kế toán

import math

class Accountant (Adventurer):
    def enter_ruins(self):
        self.goal = 5000
        self.diving = True

    def expected_rooms_left(self, state):
        if not self.diving:
            return state.room

        else:
            return (state.stamina - (50 - state.carry_weight)) / 14

    def ratio(self, state, treasure):
        stamina_cost = treasure.weight * (1 + 1/5 * self.expected_rooms_left(state)) + bool(state.players)
        ratio = (treasure.value / (self.goal - state.total_value)) / (stamina_cost / state.stamina)

        return ratio

    def get_action(self, state):
        room, treasures, players, inventory, stamina = state

        if stamina < room * (math.ceil(state.carry_weight / 5) + 10) + 40:
            self.diving = False
            return 'previous'

        worthwhile = []
        for i, treasure in enumerate(treasures):
            ratio = self.ratio(state, treasure)
            if ratio >= 1 and state.carry_weight + treasure.weight <= 50:
                worthwhile.append((ratio, i))

        if worthwhile:
            ratio, index = sorted(worthwhile, reverse=True)[0]
            treasure = treasures[index]
            return 'take', index, treasures[index].weight + bool(players)

        return 'next'

Kế toán là một người rất sợ rủi ro. Anh ấy thích chắc chắn rằng những gì anh ấy làm thực sự là lựa chọn tốt nhất trong tình huống nhất định. Vì vậy, anh ta đặt cho mình một mục tiêu và chỉ nhận được kho báu nếu tính toán của anh ta cho thấy điều này đưa anh ta đi đúng hướng đến mục tiêu đó. Tuy nhiên, anh ta rất quan liêu và không thích làm rơi đồ mà anh ta đã quyết định muốn; bất kỳ nỗ lực nào để dạy anh ta làm như vậy cho đến nay đã dẫn đến việc Kế toán bỏ một món đồ, và sau đó chọn lại nó ngay sau đó.

Có thể được tiếp tục.


1
Công việc tốt đẹp xác định giá trị kho báu. Tôi chắc chắn đã có ý định viết ra một số mã tốt hơn "có đáng không", nhưng vẫn chưa đến đó. Kẻ vô lại đang đến với điểm mấu chốt của kế toán, mặc dù ...
Draco18s

"Bất kỳ nỗ lực nào để dạy anh ta làm như vậy cho đến nay đã dẫn đến việc Kế toán bỏ một món đồ, và sau đó chọn lại nó ngay sau đó." Bạn có thể khắc phục điều này bằng cách giữ một bộ tên kho báu bị rơi. Tôi có cảm giác rằng tên kho báu sẽ có ích (mặc dù chúng chỉ được đánh số ngay bây giờ)
Beefster

Cảm ơn, nhưng tôi đã tìm ra lý do tại sao nó xảy ra. Mặc dù không biết liệu tôi có sửa nó ngay lập tức không, vì anh ấy hiếm khi sử dụng nó khi tôi thử đặt nó vào.
ArBo

2

Máy chủ

Dựa một cách lỏng lẻo vào bot Lightweight khác của tôi. Nơi bot nhẹ rất đơn giản, bot này là phức tạp hơn nhiều để chứa các tương tác với chương trình khác: cả lành tính và deliberatly distruptive.

Bot này trước tiên sẽ chạy nước rút đến một phòng được chỉ định ngẫu nhiên và sau đó sẽ cố gắng đấu giá kho báu tỷ lệ giá trị / trọng lượng tốt nhất, nếu có bất kỳ người chơi nào khác trong phòng sau đó cho rằng họ cũng sẽ trả giá để thay vào đó là đấu giá kho báu tốt thứ hai. Nếu giá thầu đó không thành công thì đến lượt đấu giá tiếp theo cho kho báu tốt nhất tiếp theo.

Khi giá thầu thành công, hãy lặp lại đặt giá thầu tốt nhất / secondbest cho đến khi không còn kho báu nào tồn tại trong phòng sau đó di chuyển sâu hơn vào đống đổ nát

Đối với mỗi phòng, hãy tham gia đấu thầu lặp lại với giá tốt nhất / secondbest cho đến khi không còn kho báu nào tồn tại trong phòng sau đó di chuyển sâu hơn vào đống đổ nát hoặc nếu chúng tôi phát hiện ra rằng chúng tôi không thể tiến sâu hơn nữa thì chuyển sang trạng thái 'Thoát' và bắt đầu giảm xuống kho báu cho đến khi chúng ta có thể đảm bảo rằng chúng ta có thể thoát khỏi đống đổ nát còn sống.

Khi ở trạng thái thoát, chúng tôi sẽ kiểm tra xem liệu chúng tôi có thể thêm 1kg kho báu hay không và vẫn còn tồn tại, nếu vậy chúng tôi sẽ cố gắng trả giá cho kho báu 1kg, nếu không thì chúng tôi sẽ đến phòng trước.

Hiệu suất của nó khá thay đổi ... tuy nhiên thông thường sẽ là một trong ba bot hàng đầu.

import math

class Accomodator(Adventurer):
    def enter_ruins(self):
        self.bidValue = -1
        self.bidWeight = -1
        self.exiting = False
        self.sprintToRoom = self.random.randrange(25,27)
        pass

    def get_action(self, state):
        move_cost = 10 + int(math.ceil(state.carry_weight / 5))
        move_cost_extra_kg = 10 + int(math.ceil((state.carry_weight+1) / 5))

        worstMyTreasure = None
        worstMyTreasureId = -1

        # find our worst treasure
        i=0
        for treasure in state.inventory:
            if (worstMyTreasure is None or treasure.value/treasure.weight < worstMyTreasure.value/worstMyTreasure.weight):
                worstMyTreasure = treasure
                worstMyTreasureId=i
            i+=1

        # are we travelling back to the exit?
        if (self.exiting == True):
          # are we overweight to get back alive?
          if (state.stamina / move_cost < state.room):
            # drop most worthless treasure
            self.bidValue = -1
            self.bidWeight = -1
            return 'drop',worstMyTreasureId

          # would adding one kg cause exhaustion?
          if (state.stamina / move_cost_extra_kg <= state.room ):
            # head back to the exit
            self.bidValue = -1
            self.bidWeight = -1
            return 'previous'

        # sprint if not yet at desired sprintToRoom
        elif (state.room < self.sprintToRoom):
            return 'next'

        # are we now at the limit of stamina to still get back alive?
        if (state.stamina / move_cost <= state.room ):
              self.exiting = True
              # head back to the exit
              self.bidValue = -1
              self.bidWeight = -1
              return 'previous'

        bestRoomTreasure = None
        bestRoomTreasureId = -1
        secondBestRoomTreasure = None
        secondBestRoomTreasureId = -1

        # find the best room treasure
        i=0
        for treasure in state.treasures:
          # when exiting the ruin, only consider treasures to collect that are 1kg inorder
          # to fill up any space left in inventory. Normally consider all treasures
          if (self.exiting == False or treasure.weight == 1):
            # only bid on items that we did not bid on before to avoid bidding deadlock
            if (not (self.bidValue == treasure.value and self.bidWeight == treasure.weight)):
              # consider treasures that are better than my worst treasure or always consider when exiting
              if (self.exiting == True or (worstMyTreasure is None or treasure.value/treasure.weight > worstMyTreasure.value/worstMyTreasure.weight)):
                # consider treasures that are better than the current best room treasure
                if (bestRoomTreasure is None or treasure.value/treasure.weight > bestRoomTreasure.value/bestRoomTreasure.weight):
                    secondBestRoomTreasure = bestRoomTreasure
                    secondBestRoomTreasureId = bestRoomTreasureId
                    bestRoomTreasure = treasure
                    bestRoomTreasureId = i

                    # since we do not currently have any treasures, we shall pretend that we have this treasure so that we can then choose the best treasure available to bid on
                    if (worstMyTreasure is None):
                      worstMyTreasure = bestRoomTreasure
          i+=1

        chosenTreasure = bestRoomTreasure
        chosenTreasureId = bestRoomTreasureId

        # if we have potential competitors then bid on second best treasure
        if (len(state.players)>0 and secondBestRoomTreasure is not None):
          chosenTreasure = secondBestRoomTreasure
          chosenTreasureId = secondBestRoomTreasureId

        # we have chosen a treasure to bid for
        if (chosenTreasure is not None):
            # if the chosenTreasure will not fit then dump the worst treasure
            if (state.carry_weight + chosenTreasure.weight > 50):
              # dump the worst treasure
              self.bidValue = -1
              self.bidWeight = -1
              return 'drop',worstMyTreasureId

            # otherwise lets bid for the treasure!
            self.bidValue = chosenTreasure.value
            self.bidWeight = chosenTreasure.weight
            return 'take',chosenTreasureId,chosenTreasure.weight

        # no treasures are better than what we already have so go to next/previous room
        self.bidValue = -1
        self.bidWeight = -1
        if (self.exiting == False):
          return 'next'
        else:
          return 'previous'

Ấn tượng! Đây là một trong những thống trị giải đấu trong khoảng 50 vòng.
Beefster

2

Người chạy nước rút

Tương tự như Diver, Sprinter đi sâu và nhặt những vật phẩm tốt nhất trên đường trở về.

import math


class Sprinter(Adventurer):
    class __OnlyOne:
        __name = None

        def __init__(self, name):
            self.__name = name

        @property
        def name(self):
            return self.__name

        @name.setter
        def name(self, name):
            if self.__name is None:
                self.__name = name
            if self.__name is name:
                self.__name = None

    instance = None

    def set(self, instance):
        if self.instance is not None:
            raise Exception("Already set.")
        self.instance = instance

    def __init__(self, name, random):
        super(Sprinter, self).__init__(name, random)
        if not self.instance:
            self.instance = Sprinter.__OnlyOne(name)

        # else:
        # raise Exception('bye scoundriel')

    def get_action(self, state):
        self.instance.name = self.name
        move_cost = 10 + int(math.ceil(state.carry_weight / 5))
        if state.stamina // move_cost <= state.room + 1:
            return 'previous'
        if state.room < 30 and state.carry_weight < 1:
            return 'next'

        # todo: if there is noone in the room take the most valueable thing that fits criteria

        topVal = 0
        topValIndex = 0
        for t in state.treasures:
            val = t.value / t.weight
            if val > topVal:
                if t.weight + state.carry_weight < 50:
                    topVal = val
                    topValIndex = state.treasures.index(t)

        if len(state.treasures) > topValIndex:
            treasure = state.treasures[topValIndex]
            if treasure.weight + state.carry_weight > 50:  # it doesn't fit
                return 'previous'  # take lighter treasure
            else:
                if topVal > state.room * 2:
                    return 'take', topValIndex, treasure.weight + (self.random.randrange(2, 8) if state.players else 0)

        if state.carry_weight > 0:
            return 'previous'
        else:
            return 'next'

    def enter_ruins(self):
        if self.instance is None or self.name != self.instance.name:
            raise Exception('Hi Scoundrel')

Sprinter đi sâu vào sau đó tính điểm cho mỗi kho báu và nhặt bất cứ thứ gì vượt quá ngưỡng nhất định. Ngưỡng này phụ thuộc vào căn phòng anh ta hiện đang ở vì chi phí cao hơn để lấy các vật phẩm từ các phòng sâu hơn trong đống đổ nát.

Tôi vẫn còn 2 điều tối ưu về "chiến đấu vì kho báu" được lên kế hoạch cho những ngày tiếp theo.

17.04.: Scoundrel trở nên quá thông minh, Sprinter quyết định đẩy anh ta vào một cái bẫy ban đầu, tôi muốn giết bất kỳ bot nào cố gắng gọi Sprinter nhưng người kiểm tra không may xử lý các trường hợp ngoại lệ xảy ra trên init. Vì vậy, bản sửa lỗi tiếp theo cho Scoundrel khá dễ dàng ...


Giết người vô lại đang được tiến hành ...
AKroell

2

Lên kế hoạch trước

import math

class PlanAhead(Adventurer):    
    def get_action(self, state):
        if state.inventory:
            ivals = {}
            for i in range(len(state.inventory)):
                itm = state.inventory[i]
                ivals[i] = itm.value / itm.weight
            worstiind = min(ivals, key=lambda x: ivals[x])
            worsti = (worstiind,
                      state.inventory[worstiind].value,
                      state.inventory[worstiind].weight)
        else:
            worsti = None
        if self.drop_worst:
            self.drop_worst = False
            return 'drop', worsti[0]
        if self.seenItems:
            ivals = {}
            for i in range(len(self.seenItems)):
                itm = self.seenItems[i][0]
                v = itm.value
                if self.seenItems[i][1] >= state.room:
                    v = 0
                if v / itm.weight > 250: #very likely to get picked up already
                    v = 0
                ivals[i] = v / itm.weight
            bestIiind = max(ivals, key=lambda x: ivals[x])
            bestIi = (bestIiind,
                      self.seenItems[bestIiind][0].value,
                      self.seenItems[bestIiind][0].weight)
        else:
            bestIi = None

        stamCarry = state.carry_weight/5
        stamToExit = state.room * (10 + math.ceil(stamCarry))
        if state.room > self.max_room:
            self.max_room = state.room
        if stamToExit > state.stamina and worsti:
            return 'drop', worsti[0]
        if state.treasures:
            tvals = {}
            for i in range(len(state.treasures)):
                itm = state.treasures[i]
                v = itm.value
                tvals[i] = v / itm.weight
                self.seenItems.append((itm,state.room))
            besttind = max(tvals, key=lambda x: tvals[x])
            bestt = (besttind,
                     state.treasures[besttind].value,
                     state.treasures[besttind].weight)
            if len(state.players) > 0 and not self.did_drop:
                tvals[besttind] = 0
                besttind = max(tvals, key=lambda x: tvals[x])
                bestt = (besttind,
                         state.treasures[besttind].value,
                         state.treasures[besttind].weight)
        else:
            bestt = None

        if not self.retreat and stamToExit + (12 + stamCarry)*2 + state.room + (state.room/5*state.room) <= state.stamina:
            return 'next'
        if not self.retreat and stamToExit + 10 > state.stamina:
            self.retreat = True
            return 'previous'
        if bestt:
            if state.carry_weight + state.treasures[besttind].weight > 50 or (not self.did_drop and (worsti and (state.treasures[besttind].value-state.treasures[besttind].weight*20) > worsti[1] and state.treasures[besttind].weight <= worsti[2])):
                if worsti:
                    if len(state.players) > 0:
                        return 'previous'

                    if stamToExit <= state.stamina and math.ceil((state.carry_weight - (worsti[2] - state.treasures[besttind].weight))/5)*state.room >= state.treasures[besttind].weight:
                        return 'previous'
                    self.did_drop = True
                    return 'drop', worsti[0]
                else:
                    self.retreat = True
                    return 'previous'
            bid = state.treasures[besttind].weight
            if bid > 8 and state.room >= self.max_room-5:
                return 'previous'
            if not self.did_drop and state.stamina - bid < state.room * (10 + math.ceil(stamCarry+(bid/5))):
                if worsti:
                    if state.treasures[besttind].weight <= worsti[2]:
                        if state.treasures[besttind].value >= worsti[1]:
                            if state.treasures[besttind].weight == worsti[2]:
                                if state.treasures[besttind].value/state.treasures[besttind].weight >= worsti[1]/worsti[2] * (1+(0.05*worsti[2])):
                                    self.drop_worst = True
                                    return 'take', bestt[0], bid
                if not self.retreat:
                    self.retreat = True
                cost = math.ceil((state.carry_weight+bid)/5) - math.ceil(state.carry_weight/5)
                if state.room <= 10 and state.carry_weight > 0 and (state.stamina - stamToExit) >= bid + cost*state.room and bestt:
                    return 'take', bestt[0], bid
                return 'previous'
            self.did_drop = False

            if bestIi[1]/bestIi[2] * 0.3 > bestt[1]/bestt[2] and state.carry_weight > 0:
                return 'previous'
            self.seenItems = list(filter(lambda x: x[0] != state.treasures[besttind], self.seenItems))
            return 'take', bestt[0], bid
        if stamToExit + (12 + stamCarry + state.room)*2 <= state.stamina:
            return 'next'
        else:
            self.did_drop = False
            self.retreat = True
            return 'previous'
    def enter_ruins(self):
        self.retreat = False
        self.max_room = 0
        self.did_drop = False
        self.seenItems = []
        self.drop_worst = False
        pass

Tôi đã sử dụng những người tính toán tốt nhất / tồi tệ nhất từ câu trả lời của Artemis Fowl , nhưng logic lựa chọn hoàn toàn là thiết kế của riêng tôi và từ đó đã được sửa đổi để bao gồm một vài yếu tố bổ sung, như kho báu được nhìn thấy trong các phòng trước đó (để giảm thiểu nhặt kho báu, chỉ để quay lại, thả nó, và nhặt một cái gì đó khác).

Bot mạo hiểm sâu như nó nghĩ là an toàn hợp lý để làm như vậy (tính toán này hoạt động hiệu quả để lặn đến một độ sâu cụ thể, nhưng có tính linh hoạt xử lý các giá trị sức chịu đựng ban đầu khác), thu thập các tạo tác (ưu tiên chi phí cao và trọng lượng thấp), sau đó bắt đầu rút lui một khi nó xác định rằng nó không thể mang thêm được nữa.

Trên đường ra, nó sẽ nhặt bất kỳ báu vật bổ sung nào mà nó thấy rằng nó xác định nó vẫn có thể mang theo một cách an toàn đến lối ra. Nó thậm chí sẽ bỏ các cổ vật đã được giữ nếu cái mới là một thỏa thuận tốt hơn và sẽ không dẫn đến kiệt sức. Nếu nó có chỗ trong ba lô, nó sẽ nhặt kho báu mới lên trước khi bỏ cái chất lượng thấp hơn, giảm thiểu chiến đấu với các bot khác.


Huh, khi bạn mô tả nó giống như của tôi. Tôi sẽ loay hoay với những con số của mình ... Lưu ý: __init__chức năng đã được triển khai, bạn không cần ghi đè lên nó.
Artemis hỗ trợ Monica


2

Luật sư

Đánh bại người say rượu khoảng 1000 đô la! Không thể nghĩ ra một cái tên sáng tạo, nhưng đây là:

import math, sys, inspect, ntpath, importlib


CONTINUE_IN = 310 #go deeper if I have this much extra 
JUST_TAKE = 0     #take without dropping if I have this much extra 


class Artyventurer(Adventurer): 
    def enter_ruins(self):
        self.drop = False 

    def get_extra(self, state, take=0, drop=0): 
        w = state.carry_weight + take - drop 
        return state.stamina - ((10 + math.ceil(w/5)) * state.room) 

    def get_action(self, state):
        self.fail = 'draco' in ''.join(ntpath.basename(i.filename) for i in inspect.stack())
        if self.fail: 
            return 'previous'
        if state.inventory:
            ivals = {}
            for i in range(len(state.inventory)):
                itm = state.inventory[i]
                ivals[i] = itm.value / (itm.weight + 5)
            worstiind = min(ivals, key=lambda x: ivals[x])
            worsti = (worstiind,
                      state.inventory[worstiind].value,
                      state.inventory[worstiind].weight)
        else:
            worsti = None
        if self.drop and worsti:
            self.drop = False
            return 'drop', worsti[0]
        if state.treasures:
            tvals = {}
            for i in range(len(state.treasures)):
                itm = state.treasures[i]
                if itm.weight > (int(state.room/10) or 2):
                    continue
                tvals[i] = itm.weight#(itm.value * (36-state.room)) / (itm.weight * (state.carry_weight+1))
            bestord = sorted(tvals, key=lambda x: tvals[x], reverse=True)
            if bestord:
                pass#print(state.treasures[bestord[0]], '\n', *state.treasures, sep='\n')
            topt = []
            for i in bestord:
                topt.append((i,
                             state.treasures[i].value,
                             state.treasures[i].weight))
        else:
            topt = None
        extra = self.get_extra(state)
        if extra > CONTINUE_IN: 
            return 'next'
        if extra < 0 and worsti:
            return 'drop', worsti[0]
        if extra < state.room:
            return 'previous'
        if extra > JUST_TAKE and topt:
            choose = topt[:len(state.treasures)//3+1]
            for t in choose:
                bid = int(bool(len(state.players)))*3 + t[2]
                if self.get_extra(state, t[2]) - bid >= 0:
                    if t[2] + state.carry_weight <= 50:
                        return 'take', t[0], bid
        if topt and worsti:
            for t in topt[:len(state.treasures)//3+1]:
                if t[1] > worsti[1] or t[2] < worsti[2]:
                    bid = int(bool(len(state.players)))*3 + t[2]
                    if self.get_extra(state, t[2], worsti[2]) - 1 - bid >= 0:
                        print('a', '+weight:', t[2], '; cweight:', state.carry_weight, '; stamina:', state.stamina)
                        if bid < state.stamina and t[2] + state.carry_weight <= 50:
                            print('o')
                            self.drop = True
                            return 'take', t[0], bid
        return 'previous'

Đôi khi hầu hết các mã ở đây không bao giờ làm bất cứ điều gì (ít nhất là khi tôi kiểm tra nó với Drunkards), chương trình chỉ (cố gắng) tìm cách di chuyển tốt nhất, bao gồm cả xử lý các tình huống mà nó cố gắng không đặt vào. Một số trong số đó không bao giờ có thể chạy, nó chỉ ở đó để tôi có thể tìm hiểu về các con số, có thể vẫn có thể được cải thiện.

Giải trình

  • if state.inventory ... worsti = None
    Tìm mặt hàng 'tệ nhất' trong kho, nghĩa là mặt hàng có tỷ lệ giá trị thấp nhất so với trọng lượng. Nó lưu trữ worsti, chứa chỉ số của nó, đó là giá trị và trọng lượng của nó, như một tuple hoặc Nonenếu không có vật phẩm nào trong kho.

  • if self.drop ... return 'drop', worsti[0]
    Nếu tôi bảo nó bỏ lượt này lần cuối (xem bên dưới), và có thể, hãy bỏ mục 'tệ nhất' như đã tính ở trên.

  • extra = ... * state.room
    Tính toán sức chịu đựng của nó sẽ còn lại bao nhiêu nếu tôi bảo nó đi thẳng trở lại bây giờ.

  • if extra > CONTINUE_IN:\ return 'next'
    Nếu nó nhiều hơn TIẾP TỤC, hãy trả lại 'next'.

  • if extra < 0 and worsti:\ return 'drop', worsti[0]
    Nếu nó ít hơn 0, hãy bỏ đi món đồ tồi tệ nhất.

  • if extra < state.room:\ return 'previous'
    Nếu nó ít hơn số phòng (không thể mang thêm bất kỳ kho báu nào) hãy quay lại.

  • if state.treasures: ... bestt = None
    Tìm ra kho báu tốt nhất để lấy, tương tự như vật phẩm tồi tệ nhất trong kho đồ ở trên. Lưu trữ nó trong bestt.

  • if extra > 0 and bestt: ... return 'take', bestt[0], bid
    Với những con số hiện tại, điều này thực thi bất cứ khi nào chúng ta đạt được điều này và có kho báu có sẵn. Nếu an toàn để lấy kho báu 'tốt nhất', nó sẽ làm như vậy. Giá thầu của nó là tối thiểu, hoặc nhiều hơn thế nếu có ai có mặt.

  • if bestt and worsti: ... return 'take', bestt[0], bid
    Với các số hiện tại, khối mã này sẽ không bao giờ thực thi, vì khối mã trước đó có điều kiện rộng hơn. Điều này thực thi nếu chúng ta đã có được điều này đến nay và có cả kho báu / s trong kho của tôi và phòng. Nếu kho báu 'tốt nhất' trong phòng có giá trị hơn kho báu 'tệ nhất' trong kho của tôi, và sẽ an toàn khi trao đổi chúng trong hai lượt tiếp theo, thì nó sẽ như vậy.

  • return 'previous'
    Nếu không có điều này xảy ra, chỉ cần quay lại.

Cập nhật 16/04/19:

Các biện pháp chống vô lại. Điều này sẽ trở thành một cuộc chiến đấu thầu :(

Cập nhật thêm 16/04/19:

Hoàn nguyên trước đó, thay vào đó ngẫu nhiên chuyển đổi mọi yếu tố khác khi tìm thấy tốt nhất, ví dụ. [1, 2, 3, 4, 5, 6] → [2, 1, 3, 4, 6, 5]. Nên khó sao chép hơn :).

Cập nhật 17/04/19:

Hoàn nguyên trước đó, thay vào đó nó xóa sạch mã nguồn của chính nó . Nó thực hiện điều này trong __init__đó sẽ luôn luôn là trước đây Scoundrel.enter_ruinsvà do đó sẽ ngăn Scoundrel tải nó. Nó thay thế mã của nó khi get_actionđược gọi lần đầu tiên, để nó sẽ sẵn sàng cho lần tiếp theo. CỐ ĐỊNH, Scoundrel bây giờ chết khi đến nơi.

Cập nhật thêm 17/04/19:

Hoàn nguyên trước đó, thay vào đó, nó thay thế sys.modulesmục nhập của nó bằng mô-đun toán học, để khi Scoundrel cố tải nó, nó sẽ tải mô-đun toán học thay thế. :)
Ngoài ra, tôi chỉ nhận ra rằng sức chịu đựng di chuyển là 10 + trọng lượng / 5 , vì vậy đã cố gắng khắc phục điều đó.

Cập nhật thêm 17/04/19:

Bây giờ bao gồm tỏi từ cả hai bản cập nhật trước.

Cập nhật 18/04/19:

Đấu tranh với các con số và tính toán, giờ nhận được $ 2000 - $ 3000.

Cập nhật thêm 18/04/19:

Loại bỏ tỏi xóa tập tin vì nó đã bị cấm, thêm tỏi mới mà đảm bảo 'draco'không chịu trách nhiệm cho nó chạy, nếu nó chỉ trở lại previoustrong lượt đầu tiên của nó. Kết quả đã đưa ra một lần lặn bí ẩn đến $ 1200- $ 1800, mà tôi đang tìm kiếm.


Có vẻ rất hiệu quả đối với Drunkards, tôi muốn xem giá vé như thế nào khi các bot khác tham gia cuộc đột kích :)
Moogie

@Moogie Đánh bại Diver khoảng 100 đô la khi có 8 Drunkards.
Artemis hỗ trợ Monica

2

Kẻ vô lại

import math, importlib

CONTINUE_IN = 310 #go deeper if I have this much extra 
JUST_TAKE = 0     #take without dropping if I have this much extra 

class Scoundrel(Adventurer):
    def my_import(self, name):
        components = name.split('.')
        mod = __import__(components[0])
        for comp in components[1:]:
            mod = getattr(mod, comp)
        return mod

    def get_action(self, state):
        if self.following == 0:
            return self.sprinter(state)
        if self.following == 1:
            return self.arty(state)
        if self.following == 2:
            return self.account(state)
        return 'next'

    def enter_ruins(self):
        _weights=[17,0,13]
        self.following = self.random.choices(population=[0,1,2],weights=_weights)[0]
        try:
            self.arty_clone = importlib.import_module('artemis_fowl__artyventurer').Artyventurer(self.name,self.random)
            self.arty_clone.enter_ruins()
        except:
            self.arty_clone = None
        self.sprinter_clone = self.my_import('akroell__sprinter').Sprinter(self.name,self.random)
        self.sprinter_clone.enter_ruins()
        self.account_clone = self.my_import('arbo__accountant').Accountant(self.name,self.random)
        self.account_clone.enter_ruins()
        self.drop = False
        pass

    def sprinter(self, state):
        raw_action = self.sprinter_clone.get_action(state)
        if raw_action == 'next' or raw_action == 'previous':
            #move_cost = 10 + int(math.ceil(state.carry_weight / 5))
            #if state.stamina // move_cost < state.room:
            #    print('wont make it!')
            return raw_action
        else:
            atype, *args = raw_action
            if atype == 'take':
                return self.TakeSprinter(state, *args)
            if atype == 'drop':
                return raw_action
    def TakeSprinter(self, state, treasure, bid):
        move_cost = 10 + int(math.ceil((state.carry_weight+state.treasures[treasure].weight) / 5))
        maxbid = state.stamina - move_cost*(state.room)
        bid = state.treasures[treasure].weight + (7 if state.players else 0)
        if maxbid < state.treasures[treasure].weight:
            return 'previous'
        if maxbid < bid:
            bid = maxbid
        return 'take',treasure, bid

    def arty(self, state):
        if self.arty_clone == None:
            try:
                self.arty_clone = importlib.import_module('artemis_fowl__artyventurer').Artyventurer(self.name,self.random)
                self.arty_clone.enter_ruins()
            except:
                self.arty_clone = None
        if self.arty_clone == None:
            raw_action = self.backup_arty(state)
        else:
            raw_action = self.arty_clone.get_action(state)
        if raw_action == 'previous' and state.carry_weight < 1:
            self.arty_clone.fail = False
            return 'next'
        if raw_action == 'next' or raw_action == 'previous':
            return raw_action
        else:
            atype, *args = raw_action
            if atype == 'take':
                return self.TakeArty(*args)
            if atype == 'drop':
                return raw_action
    def TakeArty(self, treasure, bid):
        return 'take', treasure, bid + self.random.randrange(0, 2)

    def account(self, state):
        raw_action = self.account_clone.get_action(state)
        if raw_action == 'next' or raw_action == 'previous':
            return raw_action
        else:
            atype, *args = raw_action
            if atype == 'take':
                return self.TakeAcc(*args)
            if atype == 'drop':
                return raw_action
    def TakeAcc(self, treasure, bid):
        return 'take',treasure,bid + self.random.randrange(0, 2)

    def get_extra(self, state, take=0, drop=0):
        w = state.carry_weight + take - drop
        return state.stamina - ((10 + math.ceil(w/5)) * state.room)
    def backup_arty(self, state):
        if state.inventory:
            ivals = {}
            for i in range(len(state.inventory)):
                itm = state.inventory[i]
                ivals[i] = itm.value / (itm.weight + 5)
            worstiind = min(ivals, key=lambda x: ivals[x])
            worsti = (worstiind,
                      state.inventory[worstiind].value,
                      state.inventory[worstiind].weight)
        else:
            worsti = None
        if self.drop and worsti:
            self.drop = False
            return 'drop', worsti[0]
        if state.treasures:
            tvals = {}
            for i in range(len(state.treasures)):
                itm = state.treasures[i]
                if itm.weight > (int(state.room/12) or 2):
                    continue
                tvals[i] = (itm.value * (25-state.room)) / (itm.weight * (state.carry_weight+1))
            bestord = sorted(tvals, key=lambda x: tvals[x])
            topt = []
            for i in bestord:
                topt.append((i,
                             state.treasures[i].value,
                             state.treasures[i].weight))
        else:
            topt = None
        extra = self.get_extra(state)
        if extra > CONTINUE_IN: 
            return 'next'
        if extra < 0 and worsti:
            return 'drop', worsti[0]
        if extra < state.room:
            return 'previous'
        if extra > JUST_TAKE and topt:
            choose = topt[:len(state.treasures)//3+1]
            for t in choose:
                bid = int(bool(len(state.players)))*3 + t[2]
                if self.get_extra(state, t[2]) - bid >= 0:
                    if t[2] + state.carry_weight <= 50:
                        return 'take', t[0], bid
        if topt and worsti:
            for t in topt[:len(state.treasures)//3+1]:
                if t[1] > worsti[1] or t[2] < worsti[2]:
                    bid = int(bool(len(state.players)))*3 + t[2]
                    if self.get_extra(state, t[2], worsti[2]) - 1 - bid >= 0:
                        if bid < state.stamina and t[2] + state.carry_weight <= 50:
                            self.drop = True
                            return 'take', t[0], bid
        return 'previous'

Scoundrel chủ yếu hoạt động để can thiệp vào các thí sinh khác. Hiện tại, nó can thiệp vào Sprinter, Artyventurer và Kế toán (danh sách này sẽ phát triển theo thời gian với điều kiện là nó nằm trong lợi ích tốt nhất của Scoundrel). Nó thực hiện điều này bằng cách bắt chước các bot khác và sau đó đấu thầu, cắt giảm hoặc đấu tranh với các di tích. Như vậy, không có khả năng mục này sẽ thống trị bảng xếp hạng và thay vào đó hoạt động như một lực lượng hư hỏng. Sửa đổi hiện tại tại thời điểm đăng bài này đặt nó ở vị trí thứ 2 với điểm trung bình khoảng 7.

Scoundrel cho phép các nỗ lực của bot khác tự sửa đổi để chống lại Scoundrel bằng cách trực tiếp thực thi mã của những người tham gia khác như một bản sao không thể phân biệt được. Các vấn đề với nhập khẩu dẫn đến những người tham gia trùng lặp đã được giải quyết thông qua việc tạo bản sao thông qua Reflection (chỉnh sửa các cuộc chiến liên quan đến chi tiết xác định toán học là không mong muốn theo quan điểm Stack Exchange, nhưng sẽ dẫn đến kết quả tương tự). Thử thách KOTH cũng có một lịch sử cho phép điều này.

Scoundrel thay thế các Teamsters để giữ các Teamsters vì mục đích thú vị. Sau lần chỉnh sửa này, Teamsters không còn bị điều khiển bởi bộ điều khiển nữa.

Cập nhật 17/8/2019: tiếp tục các biện pháp đối phó.

The Teamsters (kết xuất bất hợp pháp)

Nhưng hãy thoải mái chạy địa phương nơi không có hơn 8 thí sinh khác!

class TeamsterA(Adventurer):
    def get_action(self, state):
        if state.room < 25 and state.carry_weight == 0:
            return 'next'
        if state.room == 25 and len(state.players) == 0 and len(state.inventory) <= 1:
            if state.treasures and len(state.inventory) == 0:
                tvals = {}
                for i in range(len(state.treasures)):
                    itm = state.treasures[i]
                    if itm.weight == 1:
                        return 'take',i,1
                for i in range(len(state.treasures)):
                    itm = state.treasures[i]
                    if itm.weight == 2:
                        return 'take',i,2
            if state.carry_weight > 0 and len(state.inventory) == 1 and int(state.inventory[0].name.strip('Treasure #')) < 500:
                return 'drop',0
            return 'previous'
        if state.room >= 25:
            if (((state.carry_weight+4) / 5) + 10) * state.room >= state.stamina:
                return 'previous'
            if len(state.inventory) == 1 and int(state.inventory[0].name.strip('Treasure #')) < 500:
                return 'drop',0
            if state.treasures:
                tvals = {}
                for i in range(len(state.treasures)):
                    itm = state.treasures[i]
                    if int(itm.name.strip('Treasure #')) > 500:
                        if (((state.carry_weight+3+itm.weight) / 5) + 10) * state.room >= state.stamina:
                            return 'previous'
                        return 'take',i,itm.weight
                for i in range(len(state.treasures)):
                    itm = state.treasures[i]
                    if itm.weight == 1:
                        return 'take',i,1
                for i in range(len(state.treasures)):
                    itm = state.treasures[i]
                    if itm.weight == 2:
                        return 'take',i,2
                if len(state.inventory) > 0:
                    return 'previous'
                return 'next'
        return 'previous'

class TeamsterB(Adventurer):
    def get_action(self, state):
        if state.treasures:
            tvals = {}
            for i in range(len(state.treasures)):
                itm = state.treasures[i]
                w = itm.weight
                v = itm.value
                if w + state.carry_weight > self.max_total_weight or w > self.max_single_weight:
                    w = 100
                if v / w < state.room * self.min_value_ratio:
                    v = 0
                tvals[i] = v / w
            besttind = max(tvals, key=lambda x: tvals[x])
            bestt = (besttind,
                     state.treasures[besttind].value,
                     state.treasures[besttind].weight)
        else:
            bestt = None
        if state.room < self.max_dive_dist and state.carry_weight == 0:
            return 'next'
        if state.room > 25 and bestt and state.carry_weight + bestt[2] <= self.max_total_weight and bestt[1] > 0 and bestt[2] <= self.max_single_weight and len(state.players) == 0:
            return 'take',bestt[0],bestt[2]
        if state.carry_weight > 0 and state.room > 25 and len(state.players) == 0:
            return 'previous'
        if state.carry_weight > 0:
            return 'drop',0
        if state.carry_weight > 0:
            return 'take',bestt[0],bestt[2]
        return 'previous'
    def enter_ruins(self):
        self.max_single_weight = 3
        self.max_total_weight = 20
        self.min_value_ratio = 2.5
        self.max_dive_dist = 55
        pass

Thực tế, mục này (trong khi hiện tại không hợp lệ) thực tế là hai bot và bộ điều khiển sẽ vui vẻ cạo cả hai và thêm chúng vào danh sách thí sinh (vì Python hay sao?)

Giai đoạn 1:

  • TeamsterA đi xuống cấp 25 (ish) 1 và liên tục nhặt lên và làm rơi kho báu nhẹ nhất mà anh ta có thể tìm thấy. Điều này tốn một sức lực khổng lồ 1 lượt cho đến giai đoạn thứ hai.
  • TeamsterB đi xuống cấp 55 và nhặt tất cả các vật có giá trị đặt xung quanh và sau đó quay trở lại cấp 25 (ish). 2 Sau đó bắt đầu giai đoạn 2.

1. Nếu không có một kho báu nặng dưới 3 trên sàn, anh ta di chuyển xuống
2. Vì anh ta khá chắc chắn là nhà thám hiểm cuối cùng trở lại bề mặt, tất cả những gì anh ta phải làm là tìm ai đó.

Giai đoạn 2:

  • TeamsterB làm trống túi của mình trước khi bò ra để chết vì kiệt sức. Chúng tôi biết bạn có thể làm điều đó.
  • TeamsterA nghĩ rằng "đó là một số đồ trang sức sáng bóng, bạn thân của tôi!" và tải lên những kho báu quý giá hơn nhiều so với những thứ linh tinh khác trong phòng trước khi tiến đến lối ra, túi đầy vàng.

Tên của kho báu thực sự có ích để giúp logic không tải lên tầng 25 rác và rời đi sớm vì không có cách nào để liên lạc giữa hai bot (và TeamsterA sẽ luôn thấy mình ở trong phòng với người khác trước đó TeamsterB đã trở lại).

Kết luận hợp lý tiếp theo: Tạo ra một đội quân

Về lý thuyết, điều này có thể được sử dụng để làm giảm độ sâu và thu được kho báu từ sâu như Phòng 98, tuy nhiên, vì sẽ cần nhiều hơn 2 bot, logic bao gồm các bot đó sẽ ngày càng phức tạp và vì tôi chắc chắn rằng điều này là một đệ trình bất hợp pháp vì vi phạm quy tắc bất thành văn, vì vậy tôi sẽ không bận tâm.

Hiệu quả Achờ ở tuổi 30, Bđợi ở 50 ... nlặn đến 98, nhặt một kho báu, di chuyển đến 97, thả nó (và sau đó chết), n-1nhặt nó lên và di chuyển đến 96 ... Cthả nó (chết), Bnhặt nó lên và di chuyển đến 30, thả nó (chết), Anhặt nó lên và trở về lối ra.

Tôi ước tính rằng điều này sẽ mất 11 bot.

Tuy nhiên, điều đó không đáng làm trừ khi bạn có thể phục hồi khoảng 4 báu vật từ độ sâu đó để cạnh tranh với các mục như PlanAhead hoặc Artyventure, do sự thay đổi giữa chi phí sức chịu đựng để di chuyển và giá trị trung bình của kho báu.

Kết quả mẫu

Hiếm khi điểm số dưới $ 4000, đôi khi đạt $ 6000.

[Turn 141] Homer the Great (TeamsterA) exited the ruins with 286 stamina
    and 16 treasures, totaling $4900 in value.
[Game End] The game has ended!
[Game End] Homer the Great (TeamsterA) won the game

[Turn 145] Samwell Jackson DDS (TeamsterA) exited the ruins with 255 stamina
    and 20 treasures, totaling $6050 in value.
[Game End] The game has ended!
[Game End] Samwell Jackson DDS (TeamsterA) won the game

[Turn 133] Rob the Smuggler (TeamsterA) exited the ruins with 255 stamina
    and 12 treasures, totaling $3527 in value.
[Game End] The game has ended!
[Game End] Eliwood the Forgettable (PlanAhead) won the game

1
Tôi nghĩ rằng khi chỉ có một bot cho mỗi người thì không cần phải có quy tắc rõ ràng như vậy. Nhưng quy tắc về việc nhắm mục tiêu một bot cụ thể vì những lý do chính đáng không thực sự giống như việc không đồng ý nhiều bot cùng nhau. Vì vậy, một phán quyết rõ ràng từ OP là cần thiết.
Moogie

Vâng, đây sẽ là không từ tôi, dawg. Đây là loại điều tôi có trong đầu với các bot làm việc cùng nhau.
Beefster

1
@Beefster Đó là những gì tôi nghĩ. Tôi đã có niềm vui làm cho nó mặc dù. Tôi sẽ xử lý việc chỉnh sửa để ngăn chặn tối nay.
Draco18

Tôi sẽ xem xét cho phép điều này một khi có hơn 11 đối thủ cạnh tranh vì hiệu quả của nó sẽ tăng lên. Chủ yếu là vì tôi không muốn tạo mã để gửi autoban.
Beefster

Nếu bạn chỉ quét khối mã đầu tiên, tất cả những gì tôi phải làm là chỉnh sửa trong một bot khác ở trên cùng.
Draco18

2

Ngược

Bởi vì nó hoạt động ngược lại

import math

class Backwards (Adventurer):
    def enter_ruins(self):
        self.goal = 5000
        self.diving = True

    def expected_rooms_left(self, state):
        if not self.diving:
            return state.room
        else:
            return state.stamina / 18

    def ratio(self, state, treasure):
        stamina_cost = treasure.weight * (1 + 1/5 * self.expected_rooms_left(state)) + math.ceil(len(state.players)/2.9)
        ratio = (treasure.value / (self.goal - state.total_value)) / (stamina_cost / state.stamina)
        return ratio

    def get_action(self, state):
        room, treasures, players, inventory, stamina = state
        if stamina < room * (math.ceil(state.carry_weight / 5) + 10) + 40 or stamina < (room+2.976) * (math.ceil(state.carry_weight / 5) + 11):
            self.diving = False
        if stamina < (room+0.992) * (math.ceil(state.carry_weight / 5) + 10.825):
            return 'previous'

        worthwhile = []
        for i, treasure in enumerate(treasures):
            ratio = self.ratio(state, treasure)
            if ratio >= 1 and state.carry_weight + treasure.weight <= 50:
                worthwhile.append((ratio, i))

        if worthwhile:
            ratio, index = sorted(worthwhile, reverse=True)[0]
            treasure = treasures[index]
            bid = treasures[index].weight + math.ceil(len(players)/2.9)
            if (not self.diving or ratio > 2.8) and stamina >= bid + (room) * (math.ceil((state.carry_weight+treasures[index].weight) / 5) + 10):
                return 'take', index, bid
        return 'next' if self.diving else 'previous'

Tại sao lại gọi là Backwards?

Bởi vì tôi đã lấy Kế toán và cố gắng làm cho nó chạy logic của nó sao cho nó sẽ lặn sâu, sau đó nhặt được chiến lợi phẩm ưa thích của nó trên đường ra (ngược lại của Kế toán).

Cuối cùng, nó vẫn thu được nhiều giải thưởng trên đường đi (kéo chúng lên trước khi những người tìm kiếm thu thập truyền thống làm, hoạt động ngược lại với mọi người khác), nhưng nó chọn lọc hơn nhiều về những gì nó cần, mặc dù vậy nhặt những thứ trên đường trở ra.

Kết quả cuối cùng là sức chịu đựng được bảo tồn trên đường đi trong khi vẫn ưu tiên các báu vật có giá trị cao, sau đó tận dụng lợi thế của một vòng quay sâu và dễ dàng chọn lựa trên đường trở lại. Backwards đã được biết là thu thập kho báu từ tận phòng 41 (và trong quá trình phát triển sẽ vào, sau đó rời đi ngay lập tức, Phòng 42).


2

Thợ săn tiền thưởng

Phương pháp đơn giản là tốt nhất. Lấy kho báu có giá trị và ánh sáng trong khi đi càng sâu càng tốt. Lấy kho báu ít giá trị trên đường trở về.

import math

class BountyHunter(Adventurer):
    def move_cost(self, state, additional_weight):
        return 10 + int(math.ceil((state.carry_weight + additional_weight) / 5))

    def get_action(self, state):
        can_go_deeper = state.stamina > (state.room + 2) * self.move_cost(state, 0)
        if state.treasures:
            best_ratio = 0
            best_index = 0
            best_weight = 0
            for i, treasure in enumerate(state.treasures):
                ratio = treasure.value / treasure.weight
                if ratio > best_ratio:
                    best_ratio = ratio
                    best_index = i
                    best_weight = treasure.weight
            limit = 160 if can_go_deeper else 60
            bid = best_weight + 2 if len(state.players) >= 1 else best_weight
            if state.carry_weight + best_weight <= 50 and best_ratio >= limit and state.stamina >= bid + state.room * self.move_cost(state, best_weight):
                return 'take', best_index, bid
        if can_go_deeper:
            return 'next'
        else:
            return 'previous'

Có vẻ như bạn đang nhận được tiền thưởng. Điều này không chỉ hoạt động tốt hơn Backwards, mà thậm chí còn khiến Backwards tăng. Làm tốt.
Beefster

1

Ánh sáng

Một bot đơn giản mà vẫn thực hiện khá tốt.

Sau khi mạo hiểm vào đống đổ nát (hiện tại là 21 phòng), nó sẽ lấy được kho báu tốt nhất trong phòng chỉ còn 1kg (do đó là tên của bot) và có giá trị hơn kho báu ít giá trị nhất trong kho. Nếu hàng tồn kho đầy, thả kho báu ít giá trị nhất. Nếu không có hành động nào khác được chọn, di chuyển vào đống đổ nát. Nếu chúng ta ở giới hạn sức chịu đựng của mình để có thể thoát ra ngoài thì hãy đến lối ra

import math

class LightWeight(Adventurer):

    def get_action(self, state):
        move_cost = 10 + int(math.ceil(state.carry_weight / 5))

        # are we now at the limit of stamina to still get back alive?
        if (state.stamina / move_cost <= state.room + 3):
            # head back to the exit
            return 'previous'

        if (state.room < 21):
            return 'next'

        bestRoomTreasure = None
        bestRoomTreasureId = -1
        worstMyTreasure = None
        worstMyTreasureId = -1

        # find our worst treasure
        i=0
        for treasure in state.inventory:
            if (worstMyTreasure is None or treasure.value < worstMyTreasure.value):
                worstMyTreasure = treasure
                worstMyTreasureId=i
            i+=1

        # we have hit our carrying capacity... we are now going to dump least valuable treasure
        if (state.carry_weight==50):

            # dump the worst treasure
            return 'drop',worstMyTreasureId

        # find the best room treasure
        i=0
        for treasure in state.treasures:
            if (treasure.weight == 1 and (worstMyTreasure is None or treasure.value > worstMyTreasure.value)):
                if (bestRoomTreasure is None or treasure.value > bestRoomTreasure.value):
                    bestRoomTreasure = treasure
                    bestRoomTreasureId = i
            i+=1

        # we have found a treasure better than we already have!
        if (bestRoomTreasure is not None):
            return 'take',bestRoomTreasureId,1

        # no treasures are better than what we already have so go to next room
        return 'next'

Tôi khuyên bạn nên đưa dumpingvào enter_ruinsphương pháp. Điều này thực sự sẽ ghi nhớ nó giữa các trò chơi và sẽ không hoạt động trên trò chơi 2. Về mặt kỹ thuật không được phép, nhưng tôi đã thêm quy tắc ngay bây giờ (tôi đã quên nó trước đây nhưng đó là ý định của tôi), vì vậy tôi sẽ cắt giảm một chút. : P
Beefster

@Beefster Tôi đã gỡ bỏ cờ trạng thái bán phá giá, nó không cần thiết vì bot chỉ đổ một kho báu bây giờ. Nó được sử dụng để đổ một nửa kho báu của nó. Vì vậy, nên tương thích với quy tắc mới.
Moogie

1

Ghi nhớ

Tôi có thể gửi bot cho KotH của riêng mình, phải không?

from __main__ import Adventurer
import math
from collections import namedtuple

class TooHeavy(Exception):
    pass

TreasureNote = namedtuple(
    'TreasureNote',
    ['utility', 'cost', 'room', 'name', 'value', 'weight']
)

def find_treasure(treasures, name):
    for i, t in enumerate(treasures):
        if t.name == name:
            return i, t
    raise KeyError(name)

EXPLORE_DEPTH = 30
TRINKET_MINIMUM_VALUE = 60

class Memorizer(Adventurer):
    def enter_ruins(self):
        self.seen = []
        self.plan = []
        self.backups = []
        self.diving = True
        self.dive_grab = False

    def plan_treasure_route(self, state):
        self.plan = []
        self.backups = []
        weight = state.carry_weight
        for treasure in self.seen:
            if weight + treasure.weight <= 50:
                self.plan.append(treasure)
                weight += treasure.weight
            else:
                self.backups.append(treasure)
        room_utility = lambda t: (t.room, t.utility)
        self.plan.sort(key=room_utility, reverse=True)

    def iter_backups(self, state):
        names = {t.name for t in state.treasures}
        owned = {t.name for t in state.inventory}
        for treasure in self.backups:
            if (treasure.room == state.room
                    and treasure.name in names
                    and treasure.name not in owned):
                yield treasure

    def take(self, state, name):
        index, treasure = find_treasure(state.treasures, name)
        if state.carry_weight + treasure.weight > 50:
            raise TooHeavy(name)
        if state.players:
            bid_bonus = self.random.randrange(len(state.players) ** 2 + 1)
        else:
            bid_bonus = 0
        return 'take', index, treasure.weight + bid_bonus

    def get_action(self, state):
        take_chance = 0.9 ** len(state.players)

        if self.diving:
            if self.dive_grab:
                self.dive_grab = False
            else:
                self.seen.extend(
                    TreasureNote(
                        value / weight,
                        weight + math.ceil(weight / 5) * state.room,
                        state.room,
                        name, value, weight
                    )
                    for name, value, weight in state.treasures
                )
            if state.room < EXPLORE_DEPTH:
                if len(state.inventory) < 5:
                    trinkets = [
                        t for t in state.treasures
                        if t.weight == 1
                        and t.value >= TRINKET_MINIMUM_VALUE
                    ]
                    trinkets.sort(key=lambda t: t.value, reverse=True)
                    for candidate in trinkets:
                        if self.random.random() < 0.99 ** (len(state.players) * state.room):
                            try:
                                action = self.take(state, candidate.name)
                            except (KeyError, TooHeavy):
                                pass # WTF!
                            else:
                                self.dive_grab = True
                                return action
                return 'next'
            else:
                self.diving = False
                self.seen.sort(reverse=True)
                self.plan_treasure_route(state)

        carry_weight = state.carry_weight
        if carry_weight == 50:
            return 'previous'

        if self.plan:
            next_index = 0
            next_planned = self.plan[next_index]
            if state.room > next_planned.room:
                return 'previous'

            try:
                while state.room == next_planned.room:
                    if self.random.random() < take_chance:
                        try:
                            return self.take(state, next_planned.name)
                        except (KeyError, TooHeavy):
                            self.plan.pop(next_index)
                            next_planned = self.plan[next_index]
                    else:
                        next_index += 1
                        next_planned = self.plan[next_index]
            except IndexError:
                pass
        else:
            next_planned = TreasureNote(0, 0, 0, 0, 0, 0)

        for candidate in self.iter_backups(state):
            if candidate.utility * 2 > next_planned.utility and self.random.random() < take_chance:
                try:
                    return self.take(state, candidate.name)
                except (KeyError, TooHeavy):
                    pass

        return 'previous'

Bot này lặn đến phòng 30 và nhớ tất cả những kho báu mà nó đã thấy. Tại thời điểm đó, nó bắt đầu chuyến đi trở lại lối vào, cố gắng lấy những báu vật tốt mà nó nhớ được nhìn thấy trong các phòng trước đó.

Tôi hy vọng nó sẽ làm tốt hơn. Những cải tiến có thể có thể đến từ việc lập kế hoạch tốt hơn và năng động hơn về căn phòng mà nó dừng lặn và sẵn sàng khám phá các tùy chọn dự phòng.

Cập nhật: bây giờ lấy 1kg báu vật trị giá 60 đô la trở lên trên đường vào.


Tôi tưởng tượng tất cả những kho báu tốt đẹp đó đã biến mất vào thời điểm bot trở lại đó ... Có lẽ bạn có thể thử một combo nơi nó sẽ mang những thứ thực sự tốt trên đường đi, ghi nhớ kho báu tầm thường mà nó có thể nhặt được trên đường về?
ArBo

Nó có thể sẽ đi quá xa
Beefster

FYI, có vẻ như đôi khi tính toán sai nếu nó có đủ sức chịu đựng để trở lại: [Turn 072] Ryu Ridley (Memorizer) collapsed in the doorway to room #1 and died of exhaustion
Larkeith

1

Người suy ngẫm

Tôi nghĩ nó khá giống với Memorizer ở chỗ nó sử dụng kiến ​​thức về các phòng đã ghé thăm để chọn phòng và kho báu nào để thu thập trên đường trở về lối ra, tuy nhiên nó đã được dẫn xuất độc lập.

Bot này chạy nước rút cho đến khi một căn phòng sâu ngẫu nhiên ghi lại những kho báu được tìm thấy trên đường đi. Khi ở phòng mục tiêu, nó sẽ suy ngẫm về lựa chọn kho báu lý tưởng để tiếp tục quay trở lại lối ra. Mỗi lượt, nó sẽ suy ngẫm một lần nữa để xác định lựa chọn tốt nhất về kho báu cần thực hiện.

Hiện tại có một thuật toán đơn giản (sức mạnh nghịch đảo của số phòng) mang lại số lượng báu vật giả định đã lấy (hoặc sẽ được lấy khi bot này ghé thăm) cho mỗi phòng và vì vậy những kho báu này bị bỏ qua khi suy ngẫm về kho báu / phòng nào để lấy từ. Tôi có ý tưởng cho các thuật toán tiên tiến khác để mô hình hóa những kho báu còn lại. Nhưng tôi sẽ phải xem liệu lợi ích đó có xứng đáng hay không.

import math

class Ponderer(Adventurer):

  class PondererTreasure:
    def __init__(self):
        self.weight = 0
        self.value = 0
        self.id = -1
        pass

  class PondererRoom:
    def __init__(self):
        self.treasures = []
        pass

  def enter_ruins(self):
      self.exiting = False
      self.sprintToRoom = self.random.randrange(30,33)
      self.rooms = {}
      self.roomsToSkip = 0
      pass

  def getBestEstimatedFinalValue(self, roomId, carry_weight, stamina, action, valueCache):
    if (roomId<=0):
      return 0

    roomValueCache = valueCache.get(roomId)

    if (roomValueCache is None):
      roomValueCache = {}
      valueCache[roomId] = roomValueCache

    value = roomValueCache.get(carry_weight)
    if (value is None):
      room = self.rooms.get(roomId)

      bestTreasureValue = 0
      bestTreasure = None
      treasures = []
      treasures.extend(room.treasures)
      skipRoomTreasure = Ponderer.PondererTreasure()
      treasures.append(skipRoomTreasure)

      roomFactor = 0.075*roomId
      estimatedTreasuresTakenAtCurrentRoom =  int(min(0.5 * len(room.treasures), max(1, 0.5 * len(room.treasures)*(1.0/(roomFactor*roomFactor)))))

      j=0
      for treasure in treasures:
        if (j>=estimatedTreasuresTakenAtCurrentRoom):
          staminaAfterBid = stamina - treasure.weight
          carry_weightAfterBid = carry_weight + treasure.weight
          move_costAfterBid = 10 + int(math.ceil(carry_weightAfterBid/5))

          if (carry_weightAfterBid <=50 and (staminaAfterBid/move_costAfterBid > roomId+1)):
            bestAccumulativeValue = self.getBestEstimatedFinalValue(roomId-1, carry_weightAfterBid, staminaAfterBid - move_costAfterBid, None, valueCache)

            if (bestAccumulativeValue >= 0):
              bestAccumulativeValue += treasure.value
              if (bestTreasure is None or bestAccumulativeValue > bestTreasureValue):
                bestTreasureValue = bestAccumulativeValue
                bestTreasure = treasure
        j+=1

      if (bestTreasure == skipRoomTreasure):
        if (action is not None):
          newAction = []
          newAction.append('previous')
          action.append(newAction)
        value = 0

      elif (bestTreasure is not None):
        if (action is not None):
          newAction = []
          newAction.append('take')
          newAction.append(bestTreasure.id)
          newAction.append(bestTreasure.weight)
          action.append(newAction)
        value = bestTreasureValue

      else:
        if (action is not None):
          newAction = []
          newAction.append('previous')
          action.append(newAction)
        value = -1

      roomValueCache[carry_weight] = value
    return value

  def get_action(self, state):
    room = Ponderer.PondererRoom()

    i=0
    for treasure in state.treasures:
      pondererTreasure = Ponderer.PondererTreasure()
      pondererTreasure.weight = treasure.weight
      pondererTreasure.value = treasure.value
      pondererTreasure.id = i

      room.treasures.append(pondererTreasure)
      i+=1

    room.treasures.sort(key=lambda x: x.value/x.weight, reverse=True)

    self.rooms[state.room] = room

    if (self.exiting == False and state.room < self.sprintToRoom):
      return 'next'

    self.exiting = True

    action = []
    valueCache = {}

    self.getBestEstimatedFinalValue(state.room, state.carry_weight, state.stamina, action, valueCache)

    if (action[0][0] == 'take'):
      return 'take', action[0][1], action[0][2]

    return action[0][0]

1

Người tích trữ

import math

class Hoarder(Adventurer):
  def canGoOn(self, state):
    costToMove = 10 + math.ceil(state.carry_weight / 5)
    return (state.room + 2) * costToMove <= state.stamina

  def canTakeTreasure(self, state, treasure):
    costToMove = 10 + math.ceil(state.carry_weight / 5)
    treasureCost = treasure.weight + 1
    return treasureCost + state.room * costToMove <= state.stamina

  def get_action(self, state):
    if (len(state.treasures) == 0):
      if (self.canGoOn(state)):
        return "next"
      else:
        return "previous"
    else:
      bestTreasure = -1
      for i, treasure in enumerate(state.treasures):
        if self.canTakeTreasure(state, treasure):
          if (bestTreasure == -1):
            bestTreasure = i
          elif state.treasures[bestTreasure].value < state.treasures[i].value:
            bestTreasure = i
      if (bestTreasure == -1):
        return "previous"
      return "take", bestTreasure, state.treasures[bestTreasure].weight+1

Hoarder ở trong một căn phòng cho đến khi nó lấy hết tất cả các báu vật trong phòng (hoặc tính toán rằng nó không có đủ sức chịu đựng để tiếp tục di chuyển / tiếp tục). Khi tất cả các kho báu đã biến mất, nếu bot có thể di chuyển một cách an toàn thì nó sẽ tiếp tục quá trình lấy hết kho báu.


Điều này chết mọi trò chơi bằng cách lấp đầy ba lô của nó.
Beefster

như tôi trong Minecraft (͡ ° ͜ʖ °) Bot này sẽ cướp bóc, đi sâu hơn và sau đó tìm thấy những chiến lợi phẩm có giá trị. Vì vậy, nó sẽ bỏ đi những gì anh ta nghĩ là loot tốt trước đó. Đó là lý do tại sao Backwards's, Sprinter' s và Memorizer's công việc chiến lược; bởi vì họ biết giá trị tương đối của mọi kho báu mà họ nhìn thấy là gì.
V. Courtois

0

Thợ lặn

(Không thể kiểm tra tại thời điểm này, vì vậy hãy cho tôi biết nếu điều này bị hỏng.)

class Diver(Adventurer):
    def get_action(self, state):
        # Don't take anything on the way in.
        if state.stamina > 700:
            return 'next'

        # Take the most valuable thing we can take without dying.
        for treasure in sorted(state.treasures, key=lambda x: x.value, reverse=True):
            total = treasure.weight + state.carry_weight
            if total <= 50 and (10 + (total + 4) // 5) * state.room + treasure.weight <= state.stamina:
                return 'take', state.treasures.index(treasure), treasure.weight

        # If there's nothing else we can do, back out.
        return 'previous'

Kho báu tốt nhất nằm sâu hơn trong đống đổ nát, lặn sâu, sau đó lấy những gì chúng ta có thể trên đường ra.


Tôi không có nhiều kinh nghiệm với trăn, nhưng được divingđịnh nghĩa ở đâu?
Hiện thân của sự thiếu hiểu biết

1
@EmbodimentofIgnorance Trong enter_ruins (), được gọi trước khi trò chơi được chạy và các hành động được thực hiện.

Jacob the Orphan (Diver) was sliced in half by a swinging blade trap.Không chắc chắn những gì bạn đã làm sai, nhưng điều đó có nghĩa là 'trả lại không hợp lệ' AFAIK.
Artemis hỗ trợ Monica

@ArtemisFowl anh trả giá quá thấp cho kho báu. Nó tốn trọng lượng của kho báu để nhặt nó lên.
Beefster

@Beefster ơi.
Artemis hỗ trợ Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.