The Rock, Paper, Kéo, Thằn lằn, Giải đấu Spock of Epicness


98

Bảng xếp hạng gần đây nhất @ 2014-08 / 02 12:00

| Pos # | Author               | Name                    | Language   | Score | Win   | Draw  | Loss  | Avg. Dec. Time |
+-------+----------------------+-------------------------+------------+-------+-------+-------+-------+----------------+
| 1st   | Emil                 | Pony                    | Python2    | 064   | 064   | 000   | 005   | 0026.87 ms     |
| 2nd   | Roy van Rijn         | Gazzr                   | Java       | 062   | 062   | 001   | 006   | 0067.30 ms     |
| 2nd   | Emil                 | Dienstag                | Python2    | 062   | 062   | 001   | 006   | 0022.19 ms     |
| 4th   | ovenror              | TobiasFuenke            | Python2    | 061   | 061   | 001   | 007   | 0026.89 ms     |
| 5th   | PhiNotPi             | BayesianBot             | Perl       | 060   | 060   | 000   | 009   | 0009.27 ms     |
| 6th   | Claudiu              | SuperMarkov             | Python2    | 058   | 058   | 001   | 010   | 0026.77 ms     |
| 7th   | histocrat            | Alternator              | Ruby       | 057   | 057   | 001   | 011   | 0038.53 ms     |
| 8th   | histocrat            | LeonardShelby           | Ruby       | 053   | 053   | 000   | 016   | 0038.55 ms     |
| 9th   | Stretch Maniac       | SmarterBot              | Java       | 051   | 051   | 002   | 016   | 0070.02 ms     |
| 9th   | Martin Büttner       | Markov                  | Ruby       | 051   | 051   | 003   | 015   | 0038.45 ms     |
| 11th  | histocrat            | BartBot                 | Ruby       | 049   | 049   | 001   | 019   | 0038.54 ms     |
| 11th  | kaine                | ExcitingishBot          | Java       | 049   | 049   | 001   | 019   | 0065.87 ms     |
| 13th  | Thaylon              | UniformBot              | Ruby       | 047   | 047   | 001   | 021   | 0038.61 ms     |
| 14th  | Carlos Martinez      | EasyGame                | Java       | 046   | 046   | 002   | 021   | 0066.44 ms     |
| 15th  | Stretch Maniac       | SmartBot                | Java       | 045   | 045   | 001   | 023   | 0068.65 ms     |
| 16th  | Docopoper            | RoboticOboeBotOboeTuner | Python2    | 044   | 044   | 000   | 025   | 0156.55 ms     |
| 17th  | Qwix                 | Analyst                 | Java       | 043   | 043   | 001   | 025   | 0069.06 ms     |
| 18th  | histocrat            | Analogizer              | Ruby       | 042   | 042   | 000   | 027   | 0038.58 ms     |
| 18th  | Thaylon              | Naan                    | Ruby       | 042   | 042   | 004   | 023   | 0038.48 ms     |
| 20th  | Thaylon              | NitPicker               | Ruby       | 041   | 041   | 000   | 028   | 0046.21 ms     |
| 20th  | bitpwner             | AlgorithmBot            | Python2    | 041   | 041   | 001   | 027   | 0025.34 ms     |
| 22nd  | histocrat            | WereVulcan              | Ruby       | 040   | 040   | 003   | 026   | 0038.41 ms     |
| 22nd  | Ourous               | QQ                      | Cobra      | 040   | 040   | 003   | 026   | 0089.33 ms     |
| 24th  | Stranjyr             | RelaxedBot              | Python2    | 039   | 039   | 001   | 029   | 0025.40 ms     |
| 25th  | JoshDM               | SelfLoathingBot         | Java       | 038   | 038   | 001   | 030   | 0068.75 ms     |
| 25th  | Ourous               | Q                       | Cobra      | 038   | 038   | 001   | 030   | 0094.04 ms     |
| 25th  | Ourous               | DejaQ                   | Cobra      | 038   | 038   | 001   | 030   | 0078.31 ms     |
| 28th  | Luis Mars            | Botzinga                | Java       | 037   | 037   | 002   | 030   | 0066.36 ms     |
| 29th  | kaine                | BoringBot               | Java       | 035   | 035   | 000   | 034   | 0066.16 ms     |
| 29th  | Docopoper            | OboeBeater              | Python2    | 035   | 035   | 002   | 032   | 0021.92 ms     |
| 29th  | Thaylon              | NaanViolence            | Ruby       | 035   | 035   | 003   | 031   | 0038.46 ms     |
| 32nd  | Martin Büttner       | SlowLizard              | Ruby       | 034   | 034   | 004   | 031   | 0038.32 ms     |
| 33rd  | Kyle Kanos           | ViolentBot              | Python3    | 033   | 033   | 001   | 035   | 0032.42 ms     |
| 34th  | HuddleWolf           | HuddleWolfTheConqueror  | .NET       | 032   | 032   | 001   | 036   | 0029.86 ms     |
| 34th  | Milo                 | DogeBotv2               | Java       | 032   | 032   | 000   | 037   | 0066.74 ms     |
| 34th  | Timmy                | DynamicBot              | Python3    | 032   | 032   | 001   | 036   | 0036.81 ms     |
| 34th  | mccannf              | YAARBot                 | JS         | 032   | 032   | 002   | 035   | 0100.12 ms     |
| 38th  | Stranjyr             | ToddlerProof            | Java       | 031   | 031   | 010   | 028   | 0066.10 ms     |
| 38th  | NonFunctional User2..| IHaveNoIdeaWhatImDoing  | Lisp       | 031   | 031   | 002   | 036   | 0036.26 ms     |
| 38th  | john smith           | RAMBOBot                | PHP        | 031   | 031   | 002   | 036   | 0014.53 ms     |
| 41st  | EoinC                | SimpleRandomBot         | .NET       | 030   | 030   | 005   | 034   | 0015.68 ms     |
| 41st  | Martin Büttner       | FairBot                 | Ruby       | 030   | 030   | 006   | 033   | 0038.23 ms     |
| 41st  | Docopoper            | OboeOboeBeater          | Python2    | 030   | 030   | 006   | 033   | 0021.93 ms     |
| 44th  | undergroundmonorail  | TheGamblersBrother      | Python2    | 029   | 029   | 000   | 040   | 0025.55 ms     |
| 45th  | DrJPepper            | MonadBot                | Haskel     | 028   | 028   | 002   | 039   | 0008.23 ms     |
| 46th  | Josef E.             | OneBehind               | Java       | 027   | 027   | 007   | 035   | 0065.87 ms     |
| 47th  | Ourous               | GitGudBot               | Cobra      | 025   | 025   | 001   | 043   | 0053.35 ms     |
| 48th  | ProgramFOX           | Echo                    | .NET       | 024   | 024   | 004   | 041   | 0014.81 ms     |
| 48th  | JoshDM               | SelfHatingBot           | Java       | 024   | 024   | 005   | 040   | 0068.88 ms     |
| 48th  | Trimsty              | Herpetologist           | Python3    | 024   | 024   | 002   | 043   | 0036.93 ms     |
| 51st  | Milo                 | DogeBot                 | Java       | 022   | 022   | 001   | 046   | 0067.86 ms     |
| 51st  | William Barbosa      | StarWarsFan             | Ruby       | 022   | 022   | 002   | 045   | 0038.48 ms     |
| 51st  | Martin Büttner       | ConservativeBot         | Ruby       | 022   | 022   | 001   | 046   | 0038.25 ms     |
| 51st  | killmous             | MAWBRBot                | Perl       | 022   | 022   | 000   | 047   | 0016.30 ms     |
| 55th  | Mikey Mouse          | LizardsRule             | .NET       | 020   | 020   | 007   | 042   | 0015.10 ms     |
| 55th  | ja72                 | BlindForesight          | .NET       | 020   | 020   | 001   | 048   | 0024.05 ms     |
| 57th  | robotik              | Evolver                 | Lua        | 019   | 019   | 001   | 049   | 0008.19 ms     |
| 58th  | Kyle Kanos           | LexicographicBot        | Python3    | 018   | 018   | 003   | 048   | 0036.93 ms     |
| 58th  | William Barbosa      | BarneyStinson           | Lua        | 018   | 018   | 005   | 046   | 0005.11 ms     |
| 60th  | Dr R Dizzle          | BartSimpson             | Ruby       | 017   | 017   | 001   | 051   | 0038.22 ms     |
| 60th  | jmite                | IocainePowder           | Ruby       | 017   | 017   | 003   | 049   | 0038.50 ms     |
| 60th  | ArcticanAudio        | SpockOrRock             | PHP        | 017   | 017   | 001   | 051   | 0014.19 ms     |
| 60th  | Dr R Dizzle          | BetterLisaSimpson       | Ruby       | 017   | 017   | 000   | 052   | 0038.23 ms     |
| 64th  | Dr R Dizzle          | LisaSimpson             | Ruby       | 016   | 016   | 002   | 051   | 0038.29 ms     |
| 65th  | Martin Büttner       | Vulcan                  | Ruby       | 015   | 015   | 001   | 053   | 0038.26 ms     |
| 65th  | Dr R Dizzle          | Khaleesi                | Ruby       | 015   | 015   | 005   | 049   | 0038.29 ms     |
| 67th  | Dr R Dizzle          | EdwardScissorHands      | Ruby       | 014   | 014   | 002   | 053   | 0038.21 ms     |
| 67th  | undergroundmonorail  | TheGambler              | Python2    | 014   | 014   | 002   | 053   | 0025.47 ms     |
| 69th  | cipher               | LemmingBot              | Python2    | 011   | 011   | 002   | 056   | 0025.29 ms     |
| 70th  | Docopoper            | ConcessionBot           | Python2    | 007   | 007   | 000   | 062   | 0141.31 ms     |
+-------+----------------------+-------------------------+------------+-------+-------+-------+-------+----------------+
Total Players: 70
Total Matches Completed: 2415
Total Tourney Time: 06:00:51.6877573

Ghi chú Tourney

  • WOO HOO 70 BOT
  • Emil vẫn còn KOTH Ponyvà bot mới của anh ấy Dienstagchiếm vị trí thứ 3
  • Xin chúc mừng Roy đã nhảy vào vị trí thứ 2 với Gazzrbot của anh ấy
  • William Barbosa giành giải thưởng Quick Draw cho bot của mìnhBarneyStinson
  • Và giải thưởng Slow Poke thuộc về Docopoper cho các bot của anh ấy R.O.B.O.TConcessionbotcả hai đều> 140ms mỗi tay

  • Nhật ký có sẵn @ https://github.com/eoincampbell/big-bang-game/blob/master/tTHERs/Touriga-2014-08-01-23-24-00.zip?raw=true

Bots loại trừ

  • BashRocksBot - vẫn không có niềm vui với .net thực thi các tập lệnh bash cygwin
  • CounterPreferenceBot - đang chờ sửa lỗi
  • Randomly Weighted - đang chờ sửa lỗi
  • CasinoShakespeare - bị loại trừ vì nó yêu cầu kết nối internet hoạt động

Câu hỏi được đăng ban đầu

Bạn đã xoay quanh nhà bạn bè của mình cho trận đấu quyết liệt nhất từng có của Rock, Paper, Kéo, Lizard, Spock. Trong phong cách mọt sách BigBang thực sự, không ai trong số những người chơi đang tự chơi mà đã tạo ra các bot điều khiển để chơi thay cho họ. Bạn rút chìa khóa USB ra và trao nó cho Sheldor the Conqueror để đưa vào trận đấu. Penny swoons. Hoặc có lẽ là Howard swoons. Chúng tôi không phán xét ở đây tại căn hộ của Leonard.

Quy tắc

Áp dụng quy tắc Rock, Giấy, Kéo, Thằn lằn, Spock tiêu chuẩn.

  • Kéo cắt giấy
  • Giấy bìa Rock
  • Đá nghiền nát Thằn lằn
  • Thằn lằn độc Spock
  • Spock đập kéo
  • Kéo chặt thằn lằn
  • Thằn lằn ăn giấy
  • Giấy từ chối Spock
  • Spock bốc hơi Rock
  • Đá nghiền kéo

Quy tắc RPSLV

Mỗi bot của người chơi sẽ chơi một trận đấu với bot khác trong giải đấu.

Mỗi trận đấu sẽ bao gồm 100 lần lặp lại của một trò chơi RPSLV.

Sau mỗi trận đấu, người chiến thắng là người chơi đã giành được nhiều trò chơi nhất trong số 100 trò chơi.

Nếu bạn thắng một trận đấu, bạn sẽ được chỉ định 1 điểm trong bảng đấu. Trong kết quả của trận hòa, không người chơi nào có được điểm.

Yêu cầu về Bot

Bot của bạn phải được chạy từ dòng lệnh.

Hộp * nix của Sheldor đã chết, vì vậy chúng tôi đang chạy nó trên Windows 8 Gaming Laptop để đảm bảo giải pháp được cung cấp của bạn có thể chạy trên windows. Sheldor đã ân cần đề nghị cài đặt bất kỳ thời gian chạy cần thiết nào (trong lý do) để có thể chạy giải pháp của bạn. (.NET, Java, Php, Python, Ruby, Powershell ...)

Đầu vào

Trong trò chơi đầu tiên của mỗi trận đấu, không có đối số nào được cung cấp cho bot của bạn. Trong mỗi trò chơi tiếp theo của mỗi trận đấu: - Arg1 sẽ chứa lịch sử của các tay / quyết định bot của bạn trong trận đấu này. - Arg2 sẽ chứa lịch sử bàn tay / quyết định của đối thủ của bạn trong trận đấu này.

Lịch sử sẽ được thể hiện bằng một chuỗi các chữ in hoa đơn đại diện cho các tay có thể bạn có thể chơi.

 | R | Rock     |
 | P | Paper    |
 | S | Scissors |
 | L | Lizard   |
 | V | Spock    |

Ví dụ

  • Trò chơi 1: MyBot.exe
  • Trò chơi 2: MyBot.exe SV
  • Trò chơi 3: MyBot.exe SS VL
  • Trò chơi 4: MyBot.exe SSR VLS

Đầu ra

Bot của bạn phải viết một phản hồi nhân vật duy nhất đại diện cho "bàn tay" của mình cho mỗi trò chơi. Kết quả nên được ghi vào STDOUT và bot sẽ thoát. Dưới đây là chữ cái viết hoa hợp lệ.

 | R | Rock     |
 | P | Paper    |
 | S | Scissors |
 | L | Lizard   |
 | V | Spock    |

Trong trường hợp bot của bạn không trả về một tay hợp lệ (nghĩa là 1 trong 5 chữ cái viết hoa đơn ở trên, sau đó bạn sẽ tự động bị mất bàn tay đó và trận đấu tiếp tục.

Trong trường hợp cả hai bot không trả lại một ván bài hợp lệ, thì trò chơi được coi là một trận hòa và trận đấu tiếp tục.

Định dạng phù hợp

Mỗi bot được gửi sẽ chơi một trận đấu với bot khác trong giải đấu.

Mỗi trận đấu sẽ kéo dài đúng 100 trận.

Các trận đấu sẽ được chơi ẩn danh, bạn sẽ không có kiến ​​thức nâng cao về bot cụ thể mà bạn đang chơi, tuy nhiên bạn có thể sử dụng bất kỳ và tất cả thông tin bạn có thể thu thập từ quyết định của anh ấy trong lịch sử của trận đấu hiện tại để thay đổi chiến lược của bạn chống lại phản đối. Bạn cũng có thể theo dõi lịch sử của các trò chơi trước đó để xây dựng mô hình / phương pháp phỏng đoán, v.v ... (Xem quy tắc bên dưới)

Trong một trò chơi, công cụ điều phối sẽ chạy bot của bạn và bot đối thủ của bạn cách nhau 100 mili giây và sau đó so sánh kết quả để tránh mọi va chạm PRNG trong cùng ngôn ngữ / thời gian chạy. (điều này thực sự đã xảy ra với tôi trong quá trình thử nghiệm).

Đánh giá & ràng buộc

Tiến sĩ Sheldon Cooper trong vỏ bọc của Sheldor the Conqueror đã đề nghị giám sát việc điều hành giải đấu. Sheldor the Conqueror là một người giám sát công bằng và công bằng (chủ yếu). Tất cả các quyết định của Sheldor là cuối cùng.

Chơi game sẽ được tiến hành một cách công bằng và đúng đắn:

  • Tập lệnh / chương trình bot của bạn sẽ được lưu trữ trong công cụ điều phối dưới thư mục con Players\[YourBotName]\
  • Bạn có thể sử dụng thư mục con Players\[YourBotName]\datađể ghi lại bất kỳ dữ liệu hoặc lịch sử trò chơi nào từ giải đấu hiện tại khi nó diễn ra. Thư mục dữ liệu sẽ bị xóa khi bắt đầu mỗi giải đấu.
  • Bạn không thể truy cập vào thư mục Người chơi của người chơi khác trong giải đấu
  • Bot của bạn không thể có mã cụ thể nhắm vào hành vi bot cụ thể khác
  • Mỗi người chơi có thể gửi nhiều hơn một bot để chơi miễn là họ không tương tác hoặc hỗ trợ lẫn nhau.

Chỉnh sửa - Ràng buộc bổ sung

  • Về tiền giả, họ sẽ không được hỗ trợ. Bot của bạn phải chơi một trong 5 tay hợp lệ. Tôi sẽ kiểm tra từng bot bên ngoài giải đấu với một số dữ liệu ngẫu nhiên để đảm bảo rằng chúng hoạt động. Bất kỳ bot nào gây ra lỗi (ví dụ như lỗi giả) sẽ được loại trừ khỏi tourney cho đến khi chúng được sửa lỗi.
  • Bots có thể là phái sinh miễn là chúng khác biệt ngắn gọn trong hành vi của chúng. Các bot (bao gồm cả các ngôn ngữ khác) thực hiện chính xác hành vi tương tự như một bot hiện có sẽ bị loại
  • Đã có các bot spam cho các mục sau, vì vậy vui lòng không gửi lại
    • Rock - BartSimpson
    • Giấy - LisaSimpson
    • Cắt kéo - EdwardScissorhands
    • Spock - Vulcan
    • Thằn lằn - Khaleesi
    • Giả ngẫu nhiên - SimpleRandomBot & FairBot
    • Psuedo RPS ngẫu nhiên - ConservativeBot
    • Psuedo Ngẫu nhiên LV - Barney Stinson
  • Bots không được gọi ra các dịch vụ bên thứ 3 hoặc tài nguyên web (hoặc bất cứ điều gì khác làm chậm đáng kể thời gian đưa ra quyết định / tốc độ của các trận đấu). CasinoShakespearelà ngoại lệ duy nhất vì bot đã được gửi trước khi ràng buộc này được thêm vào.

Sheldor sẽ cập nhật câu hỏi này thường xuyên nhất có thể với kết quả Giải đấu, khi nhiều bot được gửi.

Chương trình phối hợp / điều khiển

Chương trình phối hợp, cùng với mã nguồn cho mỗi bot có sẵn trên github.

https://github.com/eoincampbell/big-bang-game

Chi tiết nộp

Trình của bạn nên bao gồm

  • Tên Bot của bạn
  • Ma cua ban
  • Một lệnh để
    • thực thi bot của bạn từ shell, vd
    • ruby myBot.rb
    • python3 myBot.py
    • HOẶC LÀ
    • đầu tiên biên dịch cả hai của bạn và sau đó thực hiện nó. ví dụ
    • csc.exe MyBot.cs
    • MyBot.exe

Gửi mẫu

BotName: SimpleRandomBot
Compile: "C:\Program Files (x86)\MSBuild\12.0\Bin\csc.exe" SimpleRandomBot.cs
Run:     SimpleRandomBot [Arg1] [Arg2]

Mã số:

using System;
public class SimpleRandomBot
{
    public static void Main(string[] args)
    {
        var s = new[] { "R", "P", "S", "L", "V" };
        if (args.Length == 0)
        {
            Console.WriteLine("V"); //always start with spock
            return;
        }
        char[] myPreviousPlays = args[0].ToCharArray();
        char[] oppPreviousPlays = args[1].ToCharArray();
        Random r = new Random();
        int next = r.Next(0, 5);
        Console.WriteLine(s[next]);
    }
}

Làm rõ

Bất kỳ câu hỏi, hỏi trong các ý kiến ​​dưới đây.


7
Lịch sử trông như thế nào khi một người chơi bị mất tay?
lịch sử

1
Tôi sẽ làm tất cả với một cách tiếp cận phân tích, nhưng hầu hết các bot ở đây đủ ngu ngốc để đánh bại AI thông minh.
fluffy

1
Chỉ vì tôi chưa bao giờ đứng đầu trong bất kỳ thử thách nào của KotH mà tôi đã tham gia, tôi đã chụp ảnh màn hình như một vật kỷ niệm.
Kyle Kanos

3
Tôi sẽ chạy một tourney khác vào tối nay và đăng kết quả trận đấu đầy đủ trên pastebin ... đợt tiếp theo sẽ có khoảng 450 trò chơi nhưng sẽ nhanh hơn một chút khi tôi thực hiện một số công cụ song song trong chương trình kiểm soát
Eoin Campbell

3
Nếu tôi không nhầm, dường như có một lỗi nghiêm trọng trong kịch bản phối hợp: Lịch sử của người chơi 1 và 2 luôn được truyền cho các bot như là đối số thứ nhất và thứ hai, trong khi theo quy tắc, các bot sẽ luôn nhận được lịch sử riêng trước. Bây giờ người chơi 2 đang cố gắng tự đánh bại mình một cách hiệu quả. (Tôi có một chút nghi ngờ vì bot của tôi đã thắng mọi trận đấu trong đó là người chơi 1 trong khi thua một nửa các trận đấu khác.)
Emil

Câu trả lời:


26

Ngựa vằn (Python 2)

Điều này dựa trên bot bot kéo giấy mà tôi đã viết cách đây một thời gian cho một thử thách lập trình ở cuối lớp trực tuyến Udacity . Tôi đã thay đổi nó để bao gồm Spock và thằn lằn và thực hiện một số cải tiến.

Chương trình có 11 chiến lược đơn giản khác nhau, mỗi chiến lược có 5 biến thể. Nó chọn trong số này dựa trên mức độ họ sẽ thể hiện tốt như thế nào trong các vòng trước.

Tôi đã loại bỏ một chiến lược dự phòng chỉ chơi ngẫu nhiên trước các đối thủ mạnh hơn. Tôi đoán nó vui hơn thế này.

import sys

# just play Spock for the first two rounds
if len(sys.argv)<2 or len(sys.argv[1])<2: print 'V'; sys.exit()

# initialize and translate moves to numbers for better handling:
my_moves, opp_moves = sys.argv[1], sys.argv[2]
moves = ('R', 'P', 'S', 'V', 'L')   
history = zip([moves.index(i) for i in my_moves],
              [moves.index(i) for i in opp_moves])

# predict possible next moves based on history
def prediction(hist):
    N = len(hist)    

    # find longest match of the preceding moves in the earlier history
    cand_m = cand_o = cand_b = range(N-1)
    for l in xrange(1,min(N, 20)):
        ref = hist[N-l]
        cand_m = ([c for c in cand_m if c>=l and hist[c-l+1][0]==ref[0]]
                  or cand_m[-1:])
        cand_o = ([c for c in cand_o if c>=l and hist[c-l+1][1]==ref[1]]
                  or cand_o[-1:])
        cand_b = ([c for c in cand_b if c>=l and hist[c-l+1]==ref]
                  or cand_b[-1:])

    # analyze which moves were used how often
    freq_m, freq_o = [0]*5, [0]*5
    for m in hist:
        freq_m[m[0]] += 1
        freq_o[m[1]] += 1

    # return predictions
    return ([hist[-i][p] for i in 1,2 for p in 0,1]+   # repeat last moves
            [hist[cand_m[-1]+1][0],     # history matching of my own moves
             hist[cand_o[-1]+1][1],     # history matching of opponent's moves
             hist[cand_b[-1]+1][0],     # history matching of both
             hist[cand_b[-1]+1][1],
             freq_m.index(max(freq_m)), # my most frequent move
             freq_o.index(max(freq_o)), # opponent's most frequent move
             0])                        # good old rock (and friends)


# what would have been predicted in the last rounds?
pred_hist = [prediction(history[:i]) for i in xrange(2,len(history)+1)]

# how would the different predictions have scored?
n_pred = len(pred_hist[0])
scores = [[0]*5 for i in xrange(n_pred)]
for pred, real in zip(pred_hist[:-1], history[2:]):
    for i in xrange(n_pred):
        scores[i][(real[1]-pred[i]+1)%5] += 1
        scores[i][(real[1]-pred[i]+3)%5] += 1
        scores[i][(real[1]-pred[i]+2)%5] -= 1
        scores[i][(real[1]-pred[i]+4)%5] -= 1

# return best counter move
best_scores = [list(max(enumerate(s), key=lambda x: x[1])) for s in scores]
best_scores[-1][1] *= 1.001   # bias towards the simplest strategy    
if best_scores[-1][1]<0.4*len(history): best_scores[-1][1] *= 1.4
strat, (shift, score) = max(enumerate(best_scores), key=lambda x: x[1][1])
print moves[(pred_hist[-1][strat]+shift)%5]

Chạy như:

python Pony.py

Chỉnh sửa : Tôi đã thực hiện một thay đổi nhỏ bằng cách đặt thành kiến ​​về chiến lược đơn giản nhất (nghĩa là luôn chơi cùng một động tác) trong các trường hợp không chắc chắn. Điều này giúp một chút để không cố gắng tìm các mẫu quá phức tạp ở những nơi không có, ví dụ như trong các bot như ConservativeBot.

Lưu ý : Tôi đã cố gắng giải thích chiến lược khớp lịch sử cơ bản mà bot này sử dụng trong bài đăng cho bot khác của tôi là dienstag .


3
Tỷ lệ thắng 96 phần trăm là nổi bật.
AndoDaan

Rất đẹp. Bạn có thể thích Iocaine Powder , nếu bạn chưa nhìn thấy nó.
wchargein

@WChargin, tất nhiên. :) Khi tôi viết mã gốc của mình, tôi đã đọc về Iocaine Powder vài năm trước và mơ hồ nhớ ra ý tưởng chung. Vì vậy, Pony thực sự được truyền cảm hứng từ nó, nếu không nói là rất trực tiếp. Hóa ra, chúng rất giống nhau. Tôi nghĩ rằng tôi có nhiều chiến lược hơn trong khi Iocaine Powder có mức độ lý luận meta-meta thông minh mà tôi không bao gồm.
Emil

20

Markov, Ruby

Nhìn vào hai động tác cuối cùng của đối thủ và xác định khả năng theo dõi có thể (và rất có thể). Nếu sự kết hợp chưa được chọn trước đó, anh ta chỉ sử dụng tất cả các động tác của đối thủ (cho đến nay). Sau đó, anh ta thu thập tất cả các phản ứng có thể cho những điều này và chọn một phản ứng ngẫu nhiên.

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0 || (history = ARGV[1]).length < 3
    choices = ['R','P','S','L','V']
else
    markov = Hash.new []
    history.chars.each_cons(3) { |chars| markov[chars[0..1].join] += [chars[2]] }

    choices = []
    likely_moves = markov.key?(history[-2,2]) ? markov[history[-2,2]] : history.chars
    likely_moves.each { |move| choices += responses[move] }
end

puts choices.sample

Chạy như

markov.rb

Và sau đó tôi sử dụng chương trình này để xác định động thái khả thi nhất mà tôi sẽ làm tiếp theo sau đó tìm hiểu những gì bạn sẽ làm và cuối cùng tìm cách đánh bại những gì bạn sẽ làm và lặp đi lặp lại toàn bộ mọi thứ.
Jamie

@Jamie Ý bạn là thích anh chàng này? codegolf.stackexchange.com/a353295/8478
Martin Ender

bạn đoán nó (bình luận không đủ dài để đăng)
Jamie

19

Bảo thủBot, Ruby

Những điều mới là những điều xấu.

puts ['R','P','S'].sample

Chạy như

ruby conservative.rb

Phiên bản OG là phiên bản tốt nhất.
maxywb

13

Fan hâm mộ chiến tranh giữa các vì sao - Ruby

Đánh lừa bạn

puts ['R','P','L','S'].sample

Chạy nó như:

ruby starwarsfan.rb

Đã thêm vào Trình điều khiển
Eoin Campbell

bạn có thể quay lại bằng cách chỉnh sửa câu trả lời - Tôi sẽ chỉ nhận xét ở đây khi tôi thêm chúng.
Eoin Campbell

Tại sao R và S? : P
cjfaure

@mardavi Đây là một người hâm mộ Star Wars vì nó không sử dụng Spock.
William Barbosa

ah, bạn đúng (tất nhiên). Tôi đọc nó quá nhanh, lỗi của tôi (nhưng không có hậu quả may mắn)
mardavi

13

Barney Stinson - Lua

Tôi chỉ có một quy tắc: Mới luôn tốt hơn. Bắt vít Jo Ken Po cũ hoặc bất cứ điều gì bạn gọi nó.

math.randomseed(os.time())
print(math.random() > 0.5 and "V" or "L")

Chạy nó như:

lua legenwaitforitdary.lua

8

Bored Bot (Java)

Ông cho rằng tất cả mọi người luôn chơi cùng một thứ và kế hoạch phù hợp. Anh ta thường chọn đá trong một mối quan hệ mặc dù vậy vì những người khác phải không?

public class BoringBot
{
    public static void main(String[] args)
    {
        int Rock=0;
        int Paper=0;
        int Scissors=0;
        int Lizard=0;
        int Spock=0;

        if (args.length == 0)
        {
            System.out.print("P");
            return;
        }

        char[] oppPreviousPlays = args[1].toCharArray();

        for (int j=0; j<oppPreviousPlays.length; j++) {
            switch(oppPreviousPlays[j]){
                case 'R': Rock++; break;
                case 'P': Paper++; break;
                case 'S': Scissors++; break;
                case 'L': Lizard++; break;
                case 'V': Spock++;
            }
        }

        int Best = Math.max(Math.max(Lizard+Scissors-Spock-Paper,
                                     Rock+Spock-Lizard-Scissors),
                            Math.max(Math.max(Paper+Lizard-Spock-Rock,
                                              Paper+Spock-Rock-Scissors),
                                     Rock+Scissors-Paper-Lizard));

        if (Best== Lizard+Scissors-Spock-Paper){
            System.out.print("R"); return;
        } else if (Best== Rock+Spock-Lizard-Scissors){
            System.out.print("P"); return;
        } else if (Best== Paper+Lizard-Spock-Rock){
            System.out.print("S"); return;
        } else if(Best== Paper+Spock-Rock-Scissors){
            System.out.print("L"); return;
        } else {
            System.out.print("V"); return;
        }
    }
}

Lưu ý nếu đây là một chiến lược mà người khác đang sử dụng hãy cho tôi biết và tôi sẽ xóa. Nó chỉ cảm thấy như một điều hiển nhiên mà tôi đã không nhìn thấy.
kaine

đây là C #. bạn thuộc tính .length là sai. và không có phương pháp nàomax
Eoin Campbell

@EoinCampbell Đó là java, tôi đã chơi với cả hai và dường như quên mất những lệnh thuộc về cái nào.
kaine

ah tuyệt để lại cho tôi và tôi sẽ bao gồm nó.
Eoin Campbell

vẫn vỡ. chạy jre8 - java BoringBot.java - Lỗi: Không thể tìm thấy hoặc tải chính lớp D: \ My Software Dev \ lớn-bang-trò chơi \ BigBang.Orchestrator \ bin \ Debug \ Players \ BoringBot \ BoringBot.java -
Eoin Campbell

8

IocainePowder, Ruby

nhập mô tả hình ảnh ở đây

Dựa trên (không biết xấu hổ bị đánh cắp từ) chiến lược RPS ở đây . Bot có vẻ chọn một dự đoán giống hệt với bot Markov, nhưng sau đó giả định rằng đối thủ đã đoán được nó sẽ chọn cái gì, và chọn một động tác để đánh bại cái đó cho phù hợp.

Lưu ý rằng tôi vừa điều chỉnh ý tưởng cơ bản của chiến lược được liên kết, không tuân theo chi tiết.

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0 || (history = ARGV[1]).length < 3
    choices = ['R','P','S','L','V']
else
    markov = Hash.new []
    history.chars.each_cons(3) { |chars| markov[chars[0..1].join] += [chars[2]] }

    choices = []
    likely_moves = markov.key?(history[-2,2]) ? markov[history[-2,2]] : history.chars
    likely_moves.each { |move| choices += responses[move] }
end

myChoice = choices.sample 
theirChoice = responses[myChoice].sample
actualChoice = responses[theirChoice].sample
puts actualChoice

Chạy như

iocaine.rb

5
Bạn tiếp tục sử dụng từ đó. Tôi không nghĩ nó có nghĩa là những gì bạn nghĩ nó có nghĩa.
JoshDM

2
Sức mạnh thực sự của Iocaine Powder là sự chuyển đổi giữa việc sử dụng markov và beat-markov. Nó bắt đầu như một markov thông minh, nhưng một khi nó cảm thấy (bắt đầu thua), nó nhảy vào chế độ beat-markov. Nên dễ dàng để thêm.
Roy van Rijn

Ahh, thông minh! Không nói dối, tôi chỉ nghe Iocaine mô tả cho tôi, không thực sự nhìn vào nó một cách chi tiết. Vui lòng sửa đổi mã của tôi nếu bạn muốn hoặc gửi mã của riêng bạn và nhận tín dụng!
jmite

8

HuddleWolfTheConqueror - C #

HuddleWolf đã trở lại và tốt hơn bao giờ hết. Anh ta sẽ đánh bại Sheldor the Conqueror trong trò chơi ngớ ngẩn của chính mình. HuddleWolf đủ thông minh để xác định và chống lại spammerbots. Đối với các đối thủ thông minh hơn, HuddleWolf sử dụng kiến ​​thức về thống kê cơ bản của lớp 5 và sử dụng một cuộn súc sắc có trọng số dựa trên lịch sử các vở kịch của phe đối lập.

using System;
using System.Collections.Generic;
using System.Linq;

public class HuddleWolfTheConqueror
{

    public static readonly char[] s = new[] { 'R', 'P', 'S', 'L', 'V' };

    public static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine(pickRandom());
            return;
        }

        char[] myPlays = args[0].ToCharArray();
        char[] oppPlays = args[1].ToCharArray();

        char tryPredict = canPredictCounter(oppPlays);
        if (tryPredict != '^')
        {
            Console.WriteLine(tryPredict);
        }
        else
        {
            Console.WriteLine(pickRandom());
        }
        return;
    }


    public static char canPredictCounter(char[] history)
    {
        // don't predict if insufficient data
        if (history.Length < 5)
        {
            return '^';
        }

        // calculate probability of win for each choice
        Dictionary<char, double> dic = getBestProabability(history);

        // get item with highest probability of win
        List<char> maxVals = new List<char>();
        char maxVal = '^';
        double mostFreq = 0;
        foreach (var kvp in dic)
        {
            if (kvp.Value > mostFreq)
            {
                mostFreq = kvp.Value;
            }
        }
        foreach (var kvp in dic)
        {
            if (kvp.Value == mostFreq)
            {
                maxVals.Add(kvp.Key);
            }
        }

        // return error
        if (maxVals.Count == 0)
        {
            return maxVal;
        }

        // if distribution is not uniform, play best play
        if (maxVals.Count <= 3)
        {
            Random r = new Random(Environment.TickCount);
            return maxVals[r.Next(0, maxVals.Count)];
        }

        // if probability is close to uniform, use weighted dice roll
        if (maxVals.Count == 4)
        {
            return weightedRandom(dic);
        }

        // if probability is uniform, use random dice roll
        if (maxVals.Count >= 5)
        {
            return pickRandom();
        }

        // return error
        return '^';
    }

    public static Dictionary<char, double> getBestProabability(char[] history)
    {
        Dictionary<char, double> dic = new Dictionary<char, double>();
        foreach (char c in s)
        {
            dic.Add(c, 0);
        }
        foreach (char c in history)
        {
            if (dic.ContainsKey(c))
            {
                switch(c)
                {
                    case 'R' : 
                        dic['P'] += (1.0/(double)history.Length);
                        dic['V'] += (1.0/(double)history.Length);
                        break;
                    case 'P' : 
                        dic['S'] += (1.0/(double)history.Length);
                        dic['L'] += (1.0/(double)history.Length);
                        break;
                    case 'S' : 
                        dic['V'] += (1.0/(double)history.Length);
                        dic['R'] += (1.0/(double)history.Length);
                        break;
                    case 'L' : 
                        dic['R'] += (1.0/(double)history.Length);
                        dic['S'] += (1.0/(double)history.Length);
                        break;
                    case 'V' : 
                        dic['L'] += (1.0/(double)history.Length);
                        dic['P'] += (1.0/(double)history.Length);
                        break;
                    default : 
                        break;

                }
            }
        }
        return dic;
    }

    public static char weightedRandom(Dictionary<char, double> dic)
    {
        Random r = new Random(Environment.TickCount);
        int next = r.Next(0, 100);
        int curVal = 0;
        foreach (var kvp in dic)
        {
            curVal += (int)(kvp.Value*100);
            if (curVal > next)
            {
                return kvp.Key;
            }
        }
        return '^';
    }

    public static char pickRandom()
    {
        Random r = new Random(Environment.TickCount);
        int next = r.Next(0, 5);
        return s[next];
    }
}

8

Trẻ mới biết đi

Bot khá ngu ngốc này cho rằng nó đang chơi một đứa trẻ mới biết đi sẽ "đuổi theo" các bước di chuyển của nó, luôn cố gắng đánh bại bất cứ thứ gì được ném lần cuối. Nếu bot bị đánh nhiều lần liên tiếp, nó sẽ nhảy đến một điểm mới trong mẫu. Nó được dựa trên chiến lược của tôi cho luôn đánh đập tôi nhiều em trai. :)

EDIT :: Đã thay đổi độ dài của một vệt mất cần thiết để nhảy vào các cú ném ngẫu nhiên. Cũng sửa một lỗi lớn với bước nhảy ngẫu nhiên.

Lưu dưới dạng ToddlerProof.java, biên dịch, sau đó chạy vớijava ToddlerProof [me] [them]

import java.util.HashMap;
public class ToddlerProof
{
    char[] moves = new char[]{'R', 'P', 'S', 'L', 'V'};
    public static void main(String[] args)
    {
        if(args.length<1) //first Round
        {
            System.out.print('V');//Spock is best
            return;
        }
        else
        {
            String them = args[1];
            String me = args[0];
            int streak = 0;

            HashMap<Character, Character> nextMove = new HashMap<Character, Character>();
            //Next move beats things that beat my last move
            nextMove.put('L', 'V');
            nextMove.put('V', 'S');
            nextMove.put('S', 'P');
            nextMove.put('P', 'R');
            nextMove.put('R', 'L');
            //Check if last round was a tie or the opponent beat me
            int lastResult = winner(me.charAt(me.length()-1), them.charAt(them.length()-1));
            if(lastResult == 0)
            {
                //tie, so they will chase my last throw
                System.out.print(nextMove.get(me.charAt(me.length()-1)));

                return;
            }
            else if(lastResult == 1)
            {
                //I won, so they will chase my last throw
                System.out.print(nextMove.get(me.charAt(me.length()-1)));


                return;
            }

            else{
                //I lost
                //find streak
                for(int i = 0; i<me.length(); i++)
                {
                    int a = winner(me.charAt(i), them.charAt(i));
                    if(a >= 0) streak = 0;
                    else streak++;
                }
                //check lossStreak
                //If the streak is 2, then a rotation will make it even.
                //if it is >2, something bad has happened and I need to adjust.
                if(streak>2)
                {
                    //if they are on to me, do something random-ish
                    int r = (((them.length()+me.length()-1)*13)/7)%4;
                    System.out.print(move[r]);
                    return;
                }
                //otherwise, go on with the plan
                System.out.print(nextMove.get(me.charAt(me.length()-1)));
                return;
            }
        }
    }
    public static int winner(char me, char them)
    {
        //check for tie
        if(me == them) return 0;
        //check if they won
        if(me=='V' && (them == 'L' || them == 'P')) return -1;
        if(me=='S' && (them == 'V' || them == 'R')) return -1;
        if(me=='P' && (them == 'S' || them == 'L')) return -1;
        if(me=='R' && (them == 'P' || them == 'V')) return -1;
        if(me=='L' && (them == 'R' || them == 'S')) return -1;
        //otherwise, I won
        return 1;
    }
}

1
Chúng ta nên sử dụng print hay println? ... Tôi không chắc chắn.
kaine

Hừm. Tôi sẽ tưởng tượng cả hai sẽ hoạt động, nhưng tôi có thể thấy println rối tung lên nếu chương trình điều khiển lấy dòng mới thay vì ký tự. Cảm ơn bạn đã chỉ ra điều đó, tôi sẽ chỉnh sửa mã của mình trong trường hợp
Stranjyr

@Stranjyr có một số lỗi trong lần chạy trước của bạn. Nó không đánh bom chương trình điều khiển nhưng nếu bạn tìm kiếm lịch sử cho "Trẻ mới biết chơi n" thì có vẻ như bot của bạn đã trả về null cho một số tay nhất định và sau đó tự động lấy tay. Trò chơi ví dụ là "Echo & kidProof" trong đó Echo chơi "LVSPRLV" trước khi bot của bạn bắt đầu tào lao.
Eoin Campbell

@Eion Campbell Cảm ơn bạn đã đề cập đến nó. Tôi đã thấy điều đó trước đó khi bạn đăng nhật ký từ tourney thất bại, và tôi nghĩ rằng tôi đã sửa nó. Nó đã gặp phải một lỗi trong đó nếu mất hơn 5 liên tiếp, thay vì nhảy sang một trò chơi ngẫu nhiên, nó chỉ ném một giá trị không hợp lệ. Và sau đó, vì điều đó làm cho nó mất, nó đã ném một giá trị không hợp lệ khác . Một chu kỳ luẩn quẩn.
Stranjyr

Mát mẻ. Có nó cập nhật trong prog kiểm soát bây giờ.
Eoin Campbell

8

Bart Simpson

"Đá cũ tốt! Không có gì đánh bại đá!"

puts 'R'

Chạy như

ruby DoTheBartman.rb

Lisa Simpson

"Tội nghiệp, Bart dễ đoán. Luôn chọn đá."

puts 'P'

Chạy như

ruby LisaSimpson.rb

Tốt hơn Lisa Simpson

Tôi cảm thấy tồi tệ khi khiến Lisa trở nên khá ngu ngốc, vì vậy tôi cho phép cô ấy chọn ngẫu nhiên giữa một trong hai tay sẽ đánh đá. Vẫn ngu ngốc, nhưng cô ấy là một Simpson sau tất cả. Có lẽ một cây bút chì đã bị mắc kẹt trong não của cô?

puts ['P','V'].sample

Chạy như

ruby BetterLisaSimpson.rb


@ MartinBüttner Chết tiệt, không nhận thấy điều đó. Các chương trình dường như vẫn làm những điều khác nhau - và ít nhất Lisa ở đây có thể cảm thấy vượt trội hơn bằng cách đánh bại hai phiên bản khác nhau của anh trai mình.
Dr R Dizzle

1
Sheldor đồng ý ... sẽ có BartBot và BartSimpson :)
Eoin Campbell

3
Chúng tôi chỉ có BortBot.
JoshDM

1
Những thứ này sẽ bị tàn sát bởi markov :)
Cruncher

7

Tiếng vọng

Viết bằng C #. Biên dịch với csc Echo.cs. Chạy như thế Echo.exe ARG1 ARG2.

Lần chạy đầu tiên, Echo có một tùy chọn ngẫu nhiên. Mỗi lần chạy sau lần đầu tiên, Echo chỉ cần lặp lại hành động mới nhất của đối thủ.

using System;

namespace Echo
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Random r = new Random();
                string[] options = new string[] { "R", "P", "S", "L", "V" };
                Console.WriteLine(options[r.Next(0, options.Length)]);
            }
            else if (args.Length == 2)
            {
                string opponentHistory = args[1];
                Console.WriteLine(opponentHistory[opponentHistory.Length - 1]);
            }
        }
    }
}

7

Vulcan, Ruby

Những ngón tay của tôi được dán lại với nhau.

puts 'V'

Chạy như

ruby vulcan.rb

(Tôi nghĩ rằng đây là chiến lược in-character duy nhất cho cài đặt nền của bạn.)


Cần nhìn lại các tập phim để xem có ai được sinh ra với lưỡi chẻ không. LizardMan FTW !!!
Eoin Campbell

3
Nhưng đây không phải là cách mọi người chơi vụ nổ lớn sao?
kaine

2
@anotherguest Đó là ý của tôi bởi "đây là chiến lược duy nhất trong tính cách".
Martin Ender

6

Tyrannosaurus, Godzilla, Barney ... Quy tắc của Thằn lằn. Thỉnh thoảng họ gặp rắc rối và cần gọi Spock hoặc ném đá

using System;
public class LizardsRule
{
    public static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine("L");
            return;
        }
        char[] oppPreviousPlays = args[1].ToCharArray();
        var oppLen = oppPreviousPlays.Length;
        if (oppPreviousPlays.Length > 2
            && oppPreviousPlays[oppLen - 1] == 'R'
            && oppPreviousPlays[oppLen - 2] == 'R'
            && oppPreviousPlays[oppLen - 3] == 'R')
        {
            //It's an avalance, someone call Spock
            Console.WriteLine("V");
            return;
        }

        if (oppPreviousPlays.Length > 2
                && oppPreviousPlays[oppLen - 1] == 'S'
                && oppPreviousPlays[oppLen - 2] == 'S'
                && oppPreviousPlays[oppLen - 3] == 'S')
        {
            //Scissors, Drop your tail and pick up a rock
            Console.WriteLine("R");
            return;
        }

        //Unleash the Fury Godzilla
        Console.WriteLine("L");     
    }
}

6

BayesianBot, Perl (bây giờ là v2!)

Trên hết, đây là một chương trình độc đáo. Trong đó, bạn sẽ thấy sự hợp nhất tuyệt vời của thống kê và hình thức lập trình khủng khiếp. Ngoài ra, bot này có thể phá vỡ nhiều quy tắc thống kê Bayes, nhưng cái tên nghe có vẻ hay hơn.

Bản chất cốt lõi của bot này là việc tạo ra 250 mô hình dự đoán khác nhau. Mỗi mô hình có dạng "Cho rằng tôi đã chơi rock lần cuối và đối thủ của tôi đã chơi kéo hai lượt trước, đây là phân phối xác suất cho bước di chuyển tiếp theo của đối thủ của tôi." Mỗi phân phối xác suất có dạng phân phối Dirichlet đa chiều.

Mỗi lượt, dự đoán của tất cả các mô hình áp dụng (thường là 10) được nhân với nhau để tạo thành một dự đoán tổng thể, sau đó được sử dụng để xác định di chuyển nào có mức chi trả dự kiến ​​cao nhất.

Chỉnh sửa 1: Trong phiên bản này, tôi đã thay đổi bản phân phối trước đó và làm cho bot trở nên ngẫu nhiên hơn khi nó bị mất.

Có một vài điều có thể cần cải thiện, chẳng hạn như số lượng mô hình (250 chỉ là số có 3 chữ số), lựa chọn phân phối trước (hiện là Dir (3,3,3,3,3)) và phương pháp hợp nhất dự đoán. Ngoài ra, tôi chưa bao giờ bận tâm đến việc bình thường hóa bất kỳ phân phối xác suất nào, hiện tại vẫn ổn vì tôi đang nhân chúng.

Tôi không có kỳ vọng quá cao, nhưng tôi hy vọng bot này sẽ có thể làm tốt.

my ($phist, $ohist) = @ARGV;

my %text2num = ('R',0,'V',1,'P',2,'L',3,'S',4);  #the RVPLS ordering is superior
my @num2text = ('R','V','P','L','S');

@phist = map($text2num{$_},split(//,$phist));
@ohist = map($text2num{$_},split(//,$ohist));

$lowerlimit = 0;
for($lowerlimit..~~@phist-3){$curloc=$_;
 $result = $ohist[$curloc+2];
 @moveset = ($ohist[$curloc],$ohist[$curloc+1],$phist[$curloc],$phist[$curloc+1]);
 for(0..3){$a=$_;
  for(0..$a){$b=$_;
   $predict[$a][$b][$moveset[$a]][$moveset[$b]][$result]++;
  }
 }
}

@recentmoves = ($ohist[-2],$ohist[-1],$phist[-2],$phist[-1]);

@curpred = (1,1,1,1,1);

for(0..3){$a=$_;
 for(0..$a){$b=$_;
  for(0..4){$move=$_;
   $curpred[$move] *= $predict[$a][$b][$recentmoves[$a]][$recentmoves[$b]][$move]/3+1;
  }
 }
}

@bestmove = (0,0,0,0,0);
for(0..4){
 $bestmove[$_] = $curpred[$_]/2+$curpred[$_-1]+$curpred[$_-2];
}

$max = 0;
for(0..4){
 if($bestmove[$_]>$max){
  $max = $bestmove[$_];
 }
}
@options=();
$offset=0;
if(($ohist[-1] - $phist[-1])%5 < 2 && ($ohist[-2] - $phist[-2])%5 < 2 && ($ohist[-3] - $phist[-3])%5 < 2){  #frequentist alert!
 $offset=int(rand(3));
}
for(0..4){
 if($bestmove[$_] == $max){
  push(@options,$num2text[($_+$offset)%5]);
 }
}
$outputb = $options[int(rand(~~@options))];

print "$outputb";

Tôi đã chạy chương trình này như vậy:

perl BayesianBot.plx

5

DynamicBot

Bot động hầu như luôn luôn thay đổi. Nó thực sự ghét lặp đi lặp lại

import sys, random
choices = ['L','V','S','P','R'] * 20
if len(sys.argv) > 1:
    my_history = sys.argv[1]
    [choices.remove(my_history[-1]) for i in range(15)]
print(choices[random.randrange(len(choices))])

Ngôn ngữ: Python 3.4.1

Lệnh: python dynamicbot.py <history>hoặc python3 dynamicbot.py <history>tùy thuộc vào hệ thống của bạn


Vâng, nghĩ về điều đó.
xem

5

SmartBot - Java

Mục đầu tiên của tôi cho bất cứ điều gì trên trang web này!

Mặc dù không phải là một cái tên rất sáng tạo ...

SmartBot tìm thấy các chuỗi di chuyển trong đó các bước di chuyển của đối thủ và / hoặc chính nó tương tự như các động tác được thực hiện lần cuối và lên kế hoạch tương ứng.

name = SmartBot

Tôi nghĩ để chạy nó, sửa tôi nếu tôi sai.

java -jar SmartBot.jar

import java.util.ArrayList;
public class SmartBot {
    public static void main(String[] args) {
        if(args.length ==0){
            System.out.print("L");
            return;
        }
        if(args[0].length()<3){
            String[] randLetter = new String[]{"R","P","S","L","V"};
            System.out.print(randLetter[(int) Math.floor(Math.random()*5)]);
            return;
        }
        String myHistory = args[0];
        String otherHistory = args[1];

        double rScore,pScore,sScore,lScore,vScore;//score - highest = highest probability of next opponent move
        rScore = pScore = sScore = lScore = vScore = 0;
        lScore = .001;
        ArrayList<ArrayList<Integer>> moveHits = new ArrayList<ArrayList<Integer>>();
        for(int g = 0;g<2;g++){
            for(int i=1;i<(myHistory.length() / 2) + 1;i++){
                if(g==0){
                    moveHits.add(findAll(myHistory.substring(myHistory.length() - i),myHistory));
                }
                else{
                    moveHits.add(findAll(otherHistory.substring(otherHistory.length() - i),otherHistory));
                }
            }
            for(int i = 0; i < moveHits.size();i++){
                int matchingMoves = i+1;
                ArrayList<Integer> moveIndexes = moveHits.get(i);
                for(Integer index:moveIndexes){
                    if(index+matchingMoves +1<= otherHistory.length()){
                        char nextMove = otherHistory.charAt(index + matchingMoves-1);
                        if(nextMove=='R'){rScore = rScore + matchingMoves;}
                        if(nextMove=='P'){pScore = pScore + matchingMoves;}
                        if(nextMove=='S'){sScore = sScore + matchingMoves;}
                        if(nextMove=='L'){lScore = lScore + matchingMoves;}
                        if(nextMove=='V'){vScore = vScore + matchingMoves;}
                    }
                }
            }
        }
        if(rScore >= pScore && rScore >= sScore && rScore >= lScore && rScore >= vScore){
            System.out.print("V");
            return;
        }
        if(pScore >= rScore && pScore >= sScore && pScore >= lScore && pScore >= vScore){
            System.out.print("L");
            return;
        }
        if(sScore >= pScore && sScore >= rScore && sScore >= lScore && sScore >= vScore){
            System.out.print("R");
            return;
        }
        if(vScore >= pScore && vScore >= sScore && vScore >= lScore && vScore >= rScore){
            System.out.print("L");
            return;
        }
        if(lScore >= pScore && lScore >= sScore && lScore >= rScore && lScore >= vScore){
            System.out.print("S");
        }
        return;
    }
    public static ArrayList<Integer> findAll(String substring,String realString){
        ArrayList<Integer> ocurrences = new ArrayList<Integer>();
        Integer index = realString.indexOf(substring);
        if(index==-1){return ocurrences;}
        ocurrences.add(index+1);
        while(index!=-1){
            index = realString.indexOf(substring,index + 1);
            if(index!=-1){
                ocurrences.add(index+1);
            }
        }
        return ocurrences;
    }
}

Nó chỉ định một số điểm cho mỗi lần di chuyển tiếp theo có thể bằng số lần các mẫu tương tự đã xảy ra.

Nó hơi thích thằn lằn.


Tôi tin rằng đó là cách bạn chạy nó nếu bạn sử dụng nó trước. Nếu bạn chỉ cần biên dịch nó trước, thì java ABotnên hoạt động (nhớ đặt tên tệp giống như lớp công khai)
Justin

Cảm ơn! Là một lập trình viên tương đối mới, tôi không nhận thức được điều này.
Căng thẳng điên cuồng

5

SpockOrRock - PHP

SpockOrRock

Khi chơi trong thế giới thực, hầu hết mọi người theo bản năng chọn kéo. Bot này chọn Spock hoặc Rock để đánh bại người chơi trung bình. Nó không bận tâm về các vòng trước.

chạy với php spockorrock.php

<?php

//Pick either Spock or Rock
if (rand(0,1) == 0)     echo("R\n");
else                    echo("V\n");


?>

4

SlowLizard, Ruby

Sau khi bắt đầu với Lizard, nó luôn chọn một nước đi ngẫu nhiên, đánh bại bước di chuyển trước đó của đối thủ.

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0
  puts 'L'
else
  puts responses[ARGV[1][-1]].sample
end

Chạy như

ruby slowlizard.rb

4

Thuật ngữ học

Bot này thích đặt hàng các chữ cái của anh ấy, vì vậy anh ấy sẽ chọn một phản hồi cao hơn 1 so với đối thủ của mình ở vòng trước - trừ khi đối thủ chọn Vulcan, sau đó anh ấy chọn ngẫu nhiên một phản hồi.

import sys
import random

choices = ["L", "P", "R", "S", "V"]

total = len(sys.argv)
if total==1:
    print("L")
    sys.exit()

opponent = sys.argv[2]
opponent_last = opponent[-1]

if opponent_last == choices[-1]:
    print(random.choice(choices))
else:
    next = choices.index(opponent_last)+1
    print(choices[next])

Điều này hy vọng tay đối thủ sẽ bị xử lý thứ hai:

                           me
                            v
python LexicographicBot.py SR RV
                              ^
                            opponent

@ MartinBüttner: Đã thêm lệnh! Tôi đã khá bận rộn trong công việc cố gắng để có được một cái gì đó được xuất bản, do đó biến mất.
Kyle Kanos

nghỉ trong lần chạy đầu tiên không có đối số. TracBack (cuộc gọi gần đây nhất vừa qua): Tệp "LexicographicBot \ LexicographicBot.py", dòng 10, trong <module> đối thủ = sys.argv [2] IndexError: liệt kê chỉ mục ra khỏi phạm vi
Eoin Campbell

@EoinCampbell: Tôi đã quên điều khoản thoát trong lần chạy đầu tiên, nó đã được thêm vào và sẽ hoạt động tốt ngay bây giờ.
Kyle Kanos

4

Ma sói - Ruby

Chạy như ruby werevulcan.rb

@rules = {

  'L' => %w[V P],
  'P' => %w[V R],
  'R' => %w[L S],
  'S' => %w[P L],
  'V' => %w[R S]
}

@moves = @rules.keys

def defeats?(move1, move2)
  @rules[move1].include?(move2)
end

def score(move1, move2)
  if move1 == move2
    0
  elsif defeats?(move1, move2)
    1
  else
    -1
  end
end

def move
  player, opponent = ARGV

  # For the first 30 rounds, pick a random move that isn't Spock
  if player.to_s.size < 30
    %w[L P R S].sample
  elsif opponent.chars.to_a.uniq.size < 5
    exploit(opponent)
  else
    # Pick a random move that's biased toward Spock and against lizards
    %w[L P P R R S S V V V].sample
  end

end

def exploit(opponent)
  @moves.shuffle.max_by{ |m| opponent.chars.map{|o| score(m,o) }.reduce(:+) }
end

puts move

Người sói trông bình thường vào ban ngày, nhưng khi mặt trăng mọc, đôi tai của nó phát triển nhọn và di chuyển của nó trở nên hợp lý hơn.


4

Bộ tương tự - Ruby

Chạy với ruby analogizer.rb. Tôi đã thực hiện một sửa lỗi logic cho mã, nhưng không biết tại sao có lỗi với điều này.

@rules = {

  'L' => %w[V P],
  'P' => %w[V R],
  'R' => %w[L S],
  'S' => %w[P L],
  'V' => %w[R S]
}

@moves = @rules.keys

def defeats?(move1, move2)
  @rules[move1].include?(move2)
end

def score(move1, move2)
  if move1 == move2
    0
  elsif defeats?(move1, move2)
    1
  else
    -1
  end
end

def move
  player, opponent = ARGV

  case player.to_s.size
  # Throw six lizards in the beginning to confuse opponent
  when 0..5
    'L'
  when 6
    'V'
  when 7
    'S'
  when 8
    'P'
  when 9
    'R'
  else
    analyze_history(player.chars.to_a, opponent.chars.to_a)
  end

end

def analyze_history(player, opponent)
  my_last_move = player.last
  predicted_moves = Hash.new {0}
  opponent_reactions = player.zip(opponent.drop(1))

  # Check whether opponent tended to make a move that would've beaten, lost, or tied my last move
  opponent_reactions.each do |my_move, reaction|
    score = score(reaction, my_move)
    analogous_moves = @moves.select { |move| score == score(move, my_last_move) }
    analogous_moves.each { |move| predicted_moves[move] += 1 }
  end

  # Assume if an opponent has never made a certain move, it never will
  @moves.each { |m| predicted_moves[m] = 0 unless opponent.include?(m) }

  # Pick the move with the best score against opponent's possible moves, weighted by their likelihood, picking randomly for ties
  @moves.shuffle.max_by{ |m| predicted_moves.map { |predicted, freq| score(m, predicted) * freq }.reduce(0,:+) }

end

puts move

Giả sử bot đối lập luôn phản ứng với động thái trước đó của tôi và chọn một thứ gì đó sẽ đánh bại nó, thứ gì đó sẽ thua nó hoặc cùng một động tác, có thể từ một loạt các động thái có thể bị hạn chế. Sau đó, nó chọn động thái tốt nhất cho giả định đó.

Ngoại trừ mười bước đầu tiên được mã hóa cứng: đầu tiên tôi giả vờ tôi chỉ biết thằn lằn, sau đó tôi cho rằng đối thủ của tôi luôn ném thứ gì đó để đánh bại thứ cuối cùng tôi ném cho đến khi tôi có đủ dữ liệu để phân tích chính xác.


4

Java - SelfLoathingBot

BotName: SelfLoathingBot
Compile: Save as 'SelfLoathingBot.java'; compile.
Run:     java SelfLoathingBot [me] [them]

Bot bắt đầu ngẫu nhiên, sau đó ~ 33% để đi ngẫu nhiên, hoặc ~ 33% để chơi chiến thuật chiến thắng trước một trong những lần chơi ngay trước đó, với 50% lựa chọn chiến thuật chiến thắng.

import java.util.Random;

public class SelfLoathingBot {

    static final Random RANDOM = new Random();

    private static char randomPlay() {

        switch (RANDOM.nextInt(5)) {

            case 0 : return 'R';

            case 1 : return 'P';

            case 2 : return 'S';

            case 3 : return 'L';

            default : return 'V';
        }
    }

    private static char antiPlay(String priorPlayString) {

        char[] priorPlays = priorPlayString.toCharArray();

        int choice = RANDOM.nextInt(2);

        switch (priorPlays[priorPlays.length - 1]) {

            case 'R' : return choice == 0 ? 'P' : 'V'; 

            case 'P' : return choice == 0 ? 'S' : 'L';

            case 'S' : return choice == 0 ? 'V' : 'R';

            case 'L' : return choice == 0 ? 'R' : 'S';

            default : return choice == 0 ? 'L' : 'P'; // V        
        }
    }

    public static void main(String[] args) {

        int choice = args.length == 0 ? 0 : RANDOM.nextInt(3);

        char play;

        switch (choice) {

            case 1 :

                // 33.3% chance Play myself
                play = antiPlay(args[0]);
                break;

            case 2 :

                // 33.3% chance Play opponent just in case opponent is screwy like that
                play = antiPlay(args[1]);
                break;

            default :

                // 33.3% chance 100% Random
                play = randomPlay();
        }

        System.out.print(play);
        return;
    }
}

4

Nhà phân tích

Nhà phân tích phân tích một số thứ và làm một số điều để cố gắng đánh bại bạn.

biên dịch với javac Analyst.javavà chạy nhưjava Analyst

import java.util.Random;

public class Analyst{
    public static void main(String[] args){
        char action = 'S';

        try{
            char[] enemyMoves = null, myMoves = null;

            //first move is random
            if(args.length == 0){
                System.out.print(randomMove());
                System.exit(0);
            //moves 2-3 will beat their last move
            }else if(args[0].length() < 8){
                System.out.print(counterFor(args[1].charAt(args[1].length()-1)));
                System.exit(0);
            //following moves will execute some analyzation stuff
            }else{
                //get previous moves
                myMoves = args[0].toCharArray();
                enemyMoves = args[1].toCharArray();
            }

            //test if they're trying to beat our last move
            if(beats(enemyMoves[enemyMoves.length-1], myMoves[myMoves.length-2])){
                action = counterFor(counterFor(myMoves[myMoves.length-1]));
            }
            //test if they're copying our last move
            else if(enemyMoves[enemyMoves.length-1] == myMoves[myMoves.length-2]){
                action = counterFor(myMoves[myMoves.length-1]);
            }
            //else beat whatever they've done the most of
            else{
                action = counterFor(countMost(enemyMoves));
            }

            //if they've beaten us for the first 40 moves, do the opposite of what ive been doing
            if(theyreSmarter(myMoves, enemyMoves)){
                action = counterFor(action);
            }

        //if you break my program do something random
        }catch (Exception e){
            action = randomMove();
        }

        System.out.print(action);
    }

    private static char randomMove(){
        Random rand = new Random(System.currentTimeMillis());
        int randomMove = rand.nextInt(5);

        switch (randomMove){
            case 0: return 'R';
            case 1: return 'P';
            case 2: return 'S';
            case 3: return 'L';
            default: return 'V';
        }
    }

    private static char counterFor(char move){
        Random rand = new Random(System.currentTimeMillis());
        int moveSet = rand.nextInt(2);

        if(moveSet == 0){
            switch (move){
                case 'R': return 'P'; 
                case 'P': return 'S'; 
                case 'S': return 'R'; 
                case 'L': return 'R'; 
                default: return 'P';
            }
        }else{
            switch (move){
                case 'R': return 'V'; 
                case 'P': return 'L'; 
                case 'S': return 'V'; 
                case 'L': return 'S'; 
                default: return 'L';
            }
        }
    }

    private static boolean beats(char move1, char move2){
        if(move1 == 'R'){
            if((move2 == 'S') || (move2 == 'L')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'P'){
            if((move2 == 'R') || (move2 == 'V')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'S'){
            if((move2 == 'L') || (move2 == 'P')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'L'){
            if((move2 == 'P') || (move2 == 'V')){
                return true;
            }else{
                return false;
            }
        }else{
            if((move2 == 'R') || (move2 == 'S')){
                return true;
            }else{
                return false;
            }
        }
    }

    private static char countMost(char[] moves){
        int[] enemyMoveList = {0,0,0,0,0};

        for(int i=0; i<moves.length; i++){
            if(moves[i] == 'R'){
                enemyMoveList[0]++;
            }else if(moves[i] == 'P'){
                enemyMoveList[1]++;
            }else if(moves[i] == 'S'){
                enemyMoveList[2]++;
            }else if(moves[i] == 'L'){
                enemyMoveList[3]++;
            }else if(moves[i] == 'V'){
                enemyMoveList[4]++;
            }
        }

        int max = 0, maxIndex = 0;
        for(int i=0; i<5; i++){
            if(enemyMoveList[i] > max){
                max = enemyMoveList[i];
                maxIndex = i;
            }
        }

        switch (maxIndex){
            case 0: return 'R';
            case 1: return 'P';
            case 2: return 'S';
            case 3: return 'L';
            default: return 'V';
        }
    }

    private static boolean theyreSmarter(char[] myMoves, char[] enemyMoves){
        int loseCounter = 0;

        if(enemyMoves.length >= 40){
            for(int i=0; i<40; i++){
                if(beats(enemyMoves[i],myMoves[i])){
                    loseCounter++;
                }
            }
        }else{
            return false;
        }

        if(loseCounter > 20){
            return true;
        }else{
            return false;
        }
    }
}

4

Con bạc - Python 2

import sys
import random

MODE = 1

moves = 'RSLPV'

def element_sums(a, b):
    return [a[i] + b[i] for i in xrange(len(a))]

def move_scores(p):
    def calc(to_beat):
        return ['LDW'.find('DLLWW'[moves.find(m)-moves.find(to_beat)]) for m in moves]

    return dict(zip(moves, element_sums(calc(p[0]), calc(p[1]))))

def move_chooser(my_history, opponent_history):
    predict = sorted(moves, key=opponent_history.count, reverse=MODE)[-2:]
    scores = move_scores(predict)
    return max(scores, key=lambda k:scores[k])

if __name__ == '__main__':
    if len(sys.argv) == 3:
        print move_chooser(*sys.argv[1:])
    elif len(sys.argv) == 1:
        print random.choice(moves)

Trái với tên, thời gian ngẫu nhiên duy nhất được sử dụng trong chương trình này là ở vòng đầu tiên, khi không có thông tin. Thay vào đó, nó được đặt tên theo ngụy biện của người đánh bạc, niềm tin rằng nếu một sự kiện ngẫu nhiên ít xảy ra trong quá khứ, thì nhiều khả năng nó sẽ xảy ra trong tương lai. Ví dụ: nếu bạn lật một đồng xu công bằng 20 lần và 15 người đầu tiên là người đứng đầu, ngụy biện của người đánh bạc nói rằng tỷ lệ của các lần lật còn lại là đuôi được tăng lên. Tất nhiên, điều này là không đúng sự thật; bất kể các lần lật trước, tỷ lệ cược của một đồng xu công bằng luôn luôn là 50%.

Chương trình này phân tích lịch sử của đối thủ, tìm ra 2 động tác mà nó đã sử dụng ít nhất từ ​​trước đến nay và cho rằng lần di chuyển của đối thủ lần này sẽ là một trong hai động tác đó. Chỉ định 2 cho một chiến thắng, 1 cho một trận hòa và 0 cho một trận thua, nó tìm thấy nước đi với số điểm tối đa so với hai nước đi được dự đoán này và ném nó.

The Gambler's Brother - Python 2

import sys
import random

MODE = 0

moves = 'RSLPV'

def element_sums(a, b):
    return [a[i] + b[i] for i in xrange(len(a))]

def move_scores(p):
    def calc(to_beat):
        return ['LDW'.find('DLLWW'[moves.find(m)-moves.find(to_beat)]) for m in moves]

    return dict(zip(moves, element_sums(calc(p[0]), calc(p[1]))))

def move_chooser(my_history, opponent_history):
    predict = sorted(moves, key=opponent_history.count, reverse=MODE)[-2:]
    scores = move_scores(predict)
    return max(scores, key=lambda k:scores[k])

if __name__ == '__main__':
    if len(sys.argv) == 3:
        print move_chooser(*sys.argv[1:])
    elif len(sys.argv) == 1:
        print random.choice(moves)

Bằng cách chuyển đổi MODEbiến thành 0, chương trình này sẽ hoạt động dựa trên sai lầm liên quan, đôi khi còn được gọi là sai lầm của người đánh bạc. Nó nói rằng nếu một sự kiện ngẫu nhiên đã xảy ra thường xuyên hơn trong quá khứ, nó có nhiều khả năng xảy ra trong tương lai. Ví dụ: nếu bạn lật một đồng xu 20 lần và 15 lần đầu tiên là người đứng đầu, sai lầm này nói rằng các lần lật còn lại có nhiều khả năng là người đứng đầu, vì hiện tại có một vệt. Ở chế độ 0, chương trình này hoạt động theo cùng một cách, ngoại trừ việc nó cho rằng đối thủ sẽ ném một trong hai động tác mà nó ném thường xuyên nhất cho đến nay.

Vì vậy, có, hai chương trình chỉ cách nhau một nhân vật. :)


Trên điều kiện nào TheGambler thay đổi MODE?
Dr R Dizzle

@DrRDizzle Không, có vẻ như đây là bản đệ trình của hai bot trong một.
Paŭlo Ebermann

2
Chương trình này sẽ không hiệu quả hơn nếu MODE chuyển đổi nếu bạn mất nhiều hơn một số lần nhất định liên tiếp?
Dr R Dizzle

4

Điện thoại (Python 2)

Mục nhập đầu tiên của tôi Pony dường như khá tốt với tất cả các lần đoán thứ hai (đoán ba lần, ...) và lý luận meta. Nhưng điều đó có cần thiết không?

Vì vậy, đây là dienstag, người bạn nhỏ của Pony, chỉ với một trong 55 chiến lược: Dự đoán động thái tiếp theo của đối thủ và đánh bại nó.

Về lâu dài, dienstag giành chiến thắng hoặc quan hệ với mọi Bot trong top 10 của bảng xếp hạng hiện tại. Ngoại trừ Pony.

import sys
if len(sys.argv)<2 or len(sys.argv[1])<2: print 'L'; sys.exit()
hist = [map('RPSVL'.index, p) for p in zip(sys.argv[1], sys.argv[2])]
N = len(hist)
cand = range(N-1)
for l in xrange(1,N):
    cand = ([c for c in cand if c>=l and hist[c-l+1]==hist[-l]] or cand[-1:])
print 'RPSVL'[(hist[cand[-1]+1][1]+(1,3)[N%2==0])%5]

Chạy như:

python Dienstag.py

Tôi thừa nhận rằng mã là một chút xáo trộn. Nếu ai quan tâm để biết thêm về nó, tôi có thể thêm giải thích.

Chỉnh sửa: Dưới đây là một ví dụ ngắn hướng dẫn để giải thích ý tưởng:

  • Chương trình lấy lịch sử của chính nó và di chuyển của đối thủ:

    sys.arg[1] = 'LLVLLVL', sys.arg[2] = 'RPSPSSP'

  • Lịch sử được kết hợp thành một danh sách các cặp và các bước di chuyển được dịch thành số (R = 0, ...):

    hist = [[4, 0], [4, 1], [3, 2], [4, 1], [4, 2], [3, 2], [4, 1]]

  • Số lượng vòng chơi cho đến nay được xác định:

    N = 7

  • Ý tưởng cơ bản bây giờ là tìm kiếm chuỗi dài nhất không bị phá vỡ chính xác của những bước đi cuối cùng trong lịch sử trước đó. Chương trình theo dõi nơi một chuỗi như vậy kết thúc trong danh sách cand(cho 'ứng cử viên'). Ban đầu, không cần kiểm tra, mọi vị trí trong lịch sử ngoại trừ vị trí cuối cùng đều được xem xét:

    cand = [0, 1, 2, 3, 4, 5]

  • Bây giờ độ dài của các chuỗi có thể được tăng lên từng bước. Đối với chiều dài chuỗi, l = 1nó tìm kiếm các lần xuất hiện trước của cặp di chuyển cuối cùng [4, 1]. Điều này có thể được tìm thấy ở vị trí lịch sử 13. Chỉ những thứ này được giữ trong canddanh sách:

    cand = [1, 3]

  • Tiếp theo, để l = 2kiểm tra xem ứng cử viên nào trong số các ứng cử viên có thể được đi trước cặp di chuyển thứ hai đến lần cuối [3, 2]. Đây chỉ là trường hợp cho vị trí 3:

    cand = [3]

  • Đối với l = 3nhiều hơn nữa, không có chuỗi trước đó có độ dài đó và candsẽ trống. Trong trường hợp này, phần tử cuối cùng candđược giữ:

    cand = [3]

  • Bot bây giờ giả định rằng lịch sử sẽ lặp lại. Lần cuối cùng [3, 2], [4, 1]xảy ra, nó đã được theo sau [4, 2]. Vì vậy, đối thủ đã chơi 2(kéo) có thể bị đánh bằng (2+1)%5 = 3(Spock) hoặc (2+3)%5 = 0(đá). Các câu trả lời bot, với sự thay thế thứ nhất hoặc thứ hai tùy thuộc vào việc Nlà số lẻ hay thậm chí chỉ để đưa ra một số phương sai.

  • Ở đây di chuyển 3được chọn mà sau đó được dịch lại:

    print 'V'

Lưu ý: dienstag có độ phức tạp thời gian O ( N 2 ) để quay lại nước đi tiếp theo sau N vòng. Pony có độ phức tạp thời gian O ( N 3 ). Vì vậy, trong khía cạnh này, họ có thể là tồi tệ hơn nhiều so với hầu hết các mục khác.


vui lòng làm. đây là một kinh nghiệm học tập tuyệt vời cho tôi Tôi thường sống ở vùng đất C # / Java nên tất cả sự điên rồ , ruby, trăn, haskell rất thú vị đối với tôi.
Eoin Campbell

Tôi cũng muốn thêm một ví dụ về Pony vào các trò chơi. Nó sẽ giống như bạn phải tự chiến đấu với tấm gương của mình ở cấp độ Chiến đấu sinh tử thứ 3 đến cuối cùng ;-)
Eoin Campbell

@EoinCampbell :-) Ít nhất trận đấu trực tiếp Pony vs Pony sẽ là một trận hòa hoàn hảo. Không có yếu tố ngẫu nhiên trong cả hai bot của tôi.
Emil

3

Đá Bash

Là Cygwin quá nhiều để hỏi như một thời gian chạy?

bashrocks.sh:

#!/bin/bash
HAND=(R P S L V)
RAND=`od -A n -t d -N 1 /dev/urandom | xargs`
echo ${HAND[ $RAND  % 5 ]}

và chạy nó như vậy:

sh bashrocks.sh

5
Sau khi đọc tiêu đề, tôi hơi thất vọng vì bạn làm bất cứ điều gì nhưng R. ;)
Martin Ender

@mccannf. có một số vấn đề với cái này ... Tôi đã cài đặt cygwin và sửa đổi tập lệnh của bạn với các đường dẫn đủ điều kiện thành C: \ Cygwin \ bin cho od.exe, xargs.exe & echo.exe. vẫn nhận được lỗi sau. C: / Cygwin / bin / xargs: echo: Không có lỗi cú pháp tệp hoặc thư mục% 5 "): toán hạng dự kiến ​​(mã thông báo lỗi là"
Eoin Campbell

@EoinCampbell - khi bạn tạo tệp trong windows, bạn có thể chạy dos2unixtệp đó trong cygwin trước khi thực hiện không?
mccannf

chắc chắn rồi. Tôi sẽ thử.
Eoin Campbell

Tôi nghĩ vấn đề có thể xảy ra với tuyên bố / dev / urandom
Eoin Campbell

3

Thuật toán

Một thuật toán cho lợi ích của việc có một.

Vì nó luôn cảm thấy an toàn hơn khi làm việc gì đó, càng phức tạp thì càng tốt.

Chưa thực hiện một số phép toán nghiêm túc, vì vậy thuật toán này có thể không hiệu quả.

import random, sys

if __name__ == '__main__':

    # Graph in adjacency matrix here
    graph = {"S":"PL", "P":"VR", "R":"LS", "L":"VP", "V":"SR"}
    try:
        myHistory = sys.argv[1]
        opHistory = sys.argv[2]
        choices = ""

        # Insert some graph stuff here. Newer versions may include advanced Math.
        for v in graph:
            if opHistory[-1] == v:
                for u in graph:
                    if u in graph[v]:
                        choices += graph[u]

        print random.choice(choices + opHistory[-1])

    except:
        print random.choice("RPSLV")

Chương trình Python 2: python algorithm.py


1
Tóm tắt thuật toán này: xem xét những gì đối thủ đã chơi lần cuối, và sau đó chơi ngẫu nhiên một trong hai động tác sẽ thua trước nước đi cuối cùng của đối thủ nếu họ chơi lại. Vì vậy, tốt hơn là chống lại các bot không chơi cùng một động tác hai lần liên tiếp.
Rory O'Kane

Haha. Tôi thực sự không biết nếu tôi đã làm theo cách đó. Nếu tôi không sai, thực ra đó chỉ là một cách dễ dàng để chọn ngẫu nhiên bất kỳ trong số 5 di chuyển. ;)
Vectorized

3

FairBot, Ruby

Hãy bắt đầu đơn giản.

puts ['R','P','S','L','V'].sample

Chạy như

ruby fairbot.rb

lỗi đánh máy nhỏ trên chữ 'V' cuối cùng đó. đã sửa nó trên myside nếu bạn muốn cập nhật cho đầy đủ
Eoin Campbell

@EoinCampbell cảm ơn, đã sửa!
Martin Ender

1
Điều thú vị là điều này có tỷ lệ thắng chính xác tương đương với TẤT CẢ các chiến lược.
Cruncher

3

Bạo lực

Bot này lựa chọn tùy chọn bạo lực nhất dựa trên lựa chọn trước đó của đối thủ:

import sys

choice_dict = {"L" : "S", "P" : "S", "R" : "V", "S" : "V", "V" : "L"}

total = len(sys.argv)
if total==1:
    print("L")
    sys.exit()

opponent = sys.argv[2]
opponent_last = opponent[-1]

print(choice_dict[opponent_last])

Chạy như

python ViolentBot.py (me) (opp)

nghỉ không có thông số. Traceback (cuộc gọi gần đây nhất cuối cùng): File "ViolentBot \ ViolentBot.py", dòng 9, trong <module> đối thủ = sys.argv [2] IndexError: chỉ số danh sách ra khỏi phạm vi
Eoin Campbell

nghỉ với params. TracBack (cuộc gọi gần đây nhất vừa qua): Tệp "ViolentBot \ ViolentBot.py", dòng 12, trong <mô-đun> in (select_dict [đối thủ_last]) KeyError: 'S'
Eoin Campbell

@EoinCampbell: Tôi đã thêm một mệnh đề thoát cho lần chạy đầu tiên, bạn sẽ có thể chạy nó ngay bây giờ.
Kyle Kanos

3

Haskell - MonadBot

Tôi không biết nếu ghc được coi là "trong lý do", nhưng hãy giả sử nó là như vậy. Chiến lược của bot này là để chống lại động thái phổ biến nhất của đối thủ.

Compile: ghc monadbot.hs
Run:     ./monadbot [Arg1] [Arg2]

Mã số:

import System.Environment
import Data.List
import Data.Ord

main :: IO ()
main = do
  args <- getArgs
  let moves = if not (null args) then args !! 1 else ""
      fave = if not (null moves) then head $ maximumBy (comparing length) (group $ sort moves) else 'V'
  putChar $ case fave of 'R' -> 'P'
                         'P' -> 'S'
                         'S' -> 'R'
                         'L' -> 'R'
                         'V' -> 'P'
                         _   -> 'V'
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.