Simple Pazaak (Trò chơi thẻ bài Star Wars từ Hiệp sĩ Cộng hòa cũ)


11

Pazaak là một trò chơi bài từ vũ trụ Star Wars. Nó tương tự như BlackJack, với hai người chơi đọ sức với nhau khi cố gắng đạt tổng cộng hai mươi mà không vượt qua. Mỗi người chơi có một "bộ bài phụ" gồm bốn lá bài của riêng mình mà họ có thể sử dụng để sửa đổi điểm số của mình.

Bảng xếp hạng

Kể từ ngày 17 tháng 6 năm 2015 @ 16:40 EDT

Chỉnh sửa: Sao Hải Vương đã bị loại vì gian lận. Điểm số sẽ được khắc phục sớm nhất có thể ...

  1. NEPTR: ~ 424.000
  2. The Kid Kid: ~ 422.000
  3. Yến: ~ 408.000
  4. Quyền hạn Austin: ~ 405.000
  5. Bastila: ~ 248.000
  6. Người chơi thận trọng ngu ngốc: ~ 107.000
  7. Người chơi Dumb Bold: ~ 87.000

Playoff Cup Mock Pazaak

Sẽ được cập nhật sớm nhất có thể.

Vòng một - Nestor vs Bastila & Austin Powers vs The Kid Kid

Kết quả vòng 1

Vòng hai - Nestor vs Austin Powers & The Cincinnati Kid vs Bastila

Kết quả vòng 2

Cơ học

Gameplay được thực hiện lần lượt. Người chơi được chia một lá bài từ bộ bài chính (nhà). Bộ bài trong nhà chứa bốn mươi thẻ: bốn bản sao từ một đến 10. Sau khi được chia bài, họ có thể chọn kết thúc lượt của mình và nhận một lá bài mới vào lượt tiếp theo, đứng ở giá trị hiện tại của họ, hoặc chơi một lá bài từ bộ bài phụ của họ và đứng ở giá trị mới. Sau khi người chơi quyết định những gì họ muốn làm, người chơi hai sẽ lặp lại quy trình.

Một khi cả hai người chơi đã đi, tay được đánh giá. Nếu một người chơi ném bom (hơn hai mươi), người chơi khác sẽ thắng, với điều kiện là họ cũng không ném bom. Nếu một người chơi chọn đứng và người chơi khác có giá trị tay cao hơn, người chơi khác sẽ giành chiến thắng. Nếu cả hai người chơi chọn đứng, người chơi có giá trị tay cao hơn sẽ giành chiến thắng. Trong trường hợp hòa, không người chơi nào có được chiến thắng.

Với điều kiện chiến thắng không được đáp ứng, chơi sẽ lặp lại. Nếu người chơi chọn kết thúc lượt của mình, họ sẽ nhận được một thẻ mới và có thể đưa ra lựa chọn mới. Nếu họ chọn đứng, hoặc nếu họ chơi một lá bài từ bộ bài phụ của họ, họ sẽ không bị xử lý một lá bài mới và không thể chọn một hành động mới.

Chơi tiếp tục như vậy cho đến khi một người chơi thắng trò chơi. Các trò chơi được chơi trong ba phần năm tốt nhất.

Tại sao Pazaak "đơn giản"?

Trong vũ trụ Star Wars, Pazaak liên quan đến cờ bạc. Mặc dù việc đưa vào một hệ thống như vậy sẽ tăng thêm tính năng động cho trò chơi, nhưng nó hơi phức tạp đối với một cuộc thi KoTH lần đầu tiên.

Bộ bài phụ Pazaak "Real" cũng được cung cấp bởi chính người chơi và có thể bao gồm nhiều tùy chọn thẻ khác nhau như thẻ tiêu cực, thẻ tích cực hoặc tiêu cực, thẻ lật, thẻ đôi và thẻ tiebreaker. Những điều này cũng sẽ làm cho trò chơi thú vị hơn, nhưng sẽ yêu cầu một giao diện đánh bạc tại chỗ, và sẽ đòi hỏi nhiều hơn so với các đối thủ cạnh tranh. Trong trò chơi Pazaak đơn giản này, mỗi người chơi có cùng một bộ bài phụ: hai bản sao từ một đến năm, trong đó bốn bản được chọn ngẫu nhiên.

Tùy thuộc vào sự thành công của trò chơi này, tôi có thể nỗ lực phát triển một phiên bản nâng cao trong đó có thể đánh bạc và sàn phụ tùy chỉnh.

Những người chơi

Người chơi của trò chơi này sẽ là các bot do bạn thiết kế. Mỗi bot cần mở rộng lớp Người chơi, nhập gói Cơ học và nằm trong gói người chơi như sau:

package Players;

import java.util.Collection;

import Mechanics.*;

public class DemoPlayer extends Player {

    public DemoPlayer() {
        name = "Your Name Here";
    }

    public void getResponse(int wins[], boolean isPlayerOne,
            Collection<Card> yourHand, Collection<Card> opponentHand,
            Collection<Card> yourSideDeck, int opponentSideDeckCount,
            Action opponentAction, boolean opponentDidPlay) {
        action = null;
        cardToPlay = null;
    }
}

Mỗi vòng, bộ điều khiển sẽ gọi phương thức getResponse cho bot của bạn, trừ khi trước đó bot của bạn chỉ ra rằng nó muốn đứng. Phương thức getResponse có thể đặt hai thuộc tính: một hành động và một thẻ để chơi. Hành động có thể là một trong những điều sau đây:

  • KẾT THÚC: Kết thúc lượt chơi và rút một lá bài mới vào lượt tiếp theo.
  • TIÊU CHUẨN: Giữ nguyên giá trị tay hiện tại. Sẽ không rút thẻ.
  • CHƠI: Chơi bài từ bộ bài bên cạnh rồi đứng.

Thẻ để chơi rõ ràng chỉ có tầm quan trọng nếu bạn đặt hành động thành CHƠI. Nó có một đối tượng Thẻ. Nếu đối tượng Thẻ bạn chuyển đến nó không tồn tại trong bộ bài phụ của bạn, bot của bạn sẽ CHUẨN thay thế.

Các thông số mà bot của bạn nhận được mỗi lượt là:

  • Một mảng chứa chiến thắng của mỗi người chơi. thắng [0] là của Người chơi 1, thắng 1 là Người chơi 2 (int [])
  • Có hay không bot của bạn là người chơi (boolean)
  • Một bộ sưu tập các thẻ mà bạn đã được xử lý cho đến nay (Bộ sưu tập)
  • Một bộ sưu tập các thẻ mà đối thủ của bạn đã được xử lý cho đến nay (Bộ sưu tập)
  • Một bộ sưu tập các thẻ trong bộ bài phụ của bạn (Bộ sưu tập)
  • Số lượng thẻ còn lại trong bộ bài phụ của đối thủ của bạn (int)
  • Hành động mà đối thủ của bạn thực hiện lần cuối (Hành động) [Lưu ý: Điều này sẽ là HẾT hoặc TIÊU CHUẨN, không bao giờ CHƠI]
  • Có hay không đối thủ của bạn đã chơi bài (boolean)

Quy tắc Bot

Các bot của bạn chỉ có thể sử dụng thông tin được cung cấp cho chúng thông qua phương thức getResponse. Họ không nên cố gắng tương tác với bất kỳ lớp nào khác. Họ có thể ghi vào một tệp duy nhất để lưu trữ dữ liệu giữa các vòng. Họ có thể có bất kỳ phương pháp tùy chỉnh, thuộc tính, vv như mong muốn. Họ nên chạy trong một khoảng thời gian hợp lý (nếu chương trình chạy không thực tế tức thời, tôi sẽ nhận thấy có gì đó không ổn).

Nếu bạn tìm thấy một số loại khai thác trong mã, bạn sẽ được thưởng cho việc "tự biến mình". Nếu tôi nhận thấy việc khai thác trước, tôi sẽ sửa nó và bạn sẽ không nhận được phần thưởng nào.

Trình diễn

Bộ điều khiển không cần thiết để viết bot, vì mọi thứ đã được giải thích trong bài viết này. Tuy nhiên, nếu bạn muốn thử nghiệm, nó có thể được tìm thấy ở đây: https://github.com/Ph PhantomJedi759/simplepazaak Hai bot cơ bản được bao gồm. Không nên giữ vững đối thủ trước một đối thủ "thông minh", vì họ chỉ chọn giữa END và STAND. Đây là một ví dụ về những gì họ làm:

New Game!
The standings are 0 to 0
Dumb Bold Player's Hand: []
Dumb Bold Player's new Hand: [2]
Dumb Bold Player has chosen to END
Dumb Cautious Player's Hand: []
Dumb Cautious Player's new Hand: [8]
Dumb Cautious Player has chosen to END
Dumb Bold Player's Hand: [2]
Dumb Bold Player's new Hand: [2, 8]
Dumb Bold Player has chosen to END
Dumb Cautious Player's Hand: [8]
Dumb Cautious Player's new Hand: [8, 3]
Dumb Cautious Player has chosen to END
Dumb Bold Player's Hand: [2, 8]
Dumb Bold Player's new Hand: [2, 8, 7]
Dumb Bold Player has chosen to END
Dumb Cautious Player's Hand: [8, 3]
Dumb Cautious Player's new Hand: [8, 3, 6]
Dumb Cautious Player has chosen to STAND
Dumb Bold Player's Hand: [2, 8, 7]
Dumb Bold Player's new Hand: [2, 8, 7, 6]
Dumb Bold Player has chosen to STAND
Dumb Cautious Player's Hand: [8, 3, 6]
Dumb Cautious Player has chosen to STAND
Dumb Bold Player has bombed out! Dumb Cautious Player wins!

Bởi vì các bot này hoàn toàn dựa vào sự may mắn của trận hòa, tỷ lệ thắng thua của chúng có thể thay đổi mạnh mẽ. Sẽ rất thú vị để xem làm thế nào kỹ năng có thể chống lại sự may mắn của trò chơi.

Đây nên là tất cả mọi thứ bạn cần! Đi xây dựng một số bot!

Làm rõ các quy tắc

Bộ bài chính là bốn mươi lá bài: 4x1-10 Nó được xáo trộn lại ở đầu mỗi bàn tay.

Bộ bài phụ của người chơi có bốn thẻ, được chọn ngẫu nhiên trong số 2x1-5. Bộ bài bên vẫn tồn tại giữa hai bàn tay.

Tay được chơi trong các trò chơi cho ba phần năm tốt nhất. Bots được tính dựa trên tổng số trò chơi đã thắng, và sau đó bằng tổng số ván bài.

Trận đấu được xử lý để mỗi người chơi sẽ phải chơi 100.000 trận đấu với mọi người chơi khác.

Trong Pazaak Cup, các vòng loại theo kiểu loại bỏ sẽ thu hẹp ai là bot Pazaak tốt nhất thực sự. Mỗi cặp bot sẽ chơi cho bốn trong số bảy bộ trò chơi tốt nhất. Bất cứ ai thắng bốn sẽ di chuyển lên các bậc thang cho đối thủ tiếp theo và những người thua cuộc sẽ ở lại để chiến đấu cho thứ hạng liên tiếp. Phong cách chơi này là công bằng nhất, vì các bot không thể "chiến thắng" một số đối thủ nhất định để bù đắp cho việc thiếu khả năng chống lại những người khác. Cup Pazaak sẽ được tổ chức vào thứ Sáu, ngày 3 tháng 7, với điều kiện có ít nhất tám bot được gửi. Người chiến thắng sẽ nhận được trạng thái Trả lời đúng và phần thưởng bắt đầu trong Advanced Pazaak, hy vọng sẽ sẵn sàng gần với cùng thời điểm khi Pazaak Cup được tổ chức.


1
Cố gắng truy cập repo cho tôi cảnh báo bảo mật trên Chrome, thật đáng buồn. Đây có vẻ như là một thử thách thực sự thú vị mà tôi muốn tham gia, nhưng tôi muốn một số giải thích thay cho tài liệu. Bộ bài bắt đầu với 40 lá bài giống nhau ở đầu mỗi vòng, đúng không? Bộ bài 4 lá của chúng tôi có thể là bất kỳ lá bài 1-10 nào và không ảnh hưởng đến bộ bài? Cả hai tay đều có thể nhìn thấy qua getResponse? Chúng ta sẽ được chấm điểm trên # tay thắng, hay có những vòng bao gồm giống như 5 định dạng tốt nhất? Về cơ bản, tại sao # chiến thắng được chuyển đến getResponse?
DoctorHeckle

Khi nào bộ bài được thiết lập lại? Sau mỗi vòng đấu hay chỉ với mọi đối thủ?
euanjt

1
Nó phải là chiến thắng [1] cho chiến thắng của người chơi 2, chứ không phải chiến thắng [2] vì chiến thắng chỉ là một mảng dài 2
euanjt

@DoctorHeckle Xin lỗi về repo; mạng hiện tại của tôi chặn github, nhưng tôi sẽ cố gắng đưa nó lên đó càng sớm càng tốt. Bộ bài được thiết lập lại mỗi trò chơi. Bộ bài bên giữ bốn thẻ 2x1-5. Khi cuộc thi thực sự bắt đầu, bạn sẽ được ghi điểm bởi các giải đấu tốt nhất trong số năm. Số lượng chiến thắng được chuyển cho phương thức getResponse trong trường hợp bot của bạn muốn thay đổi kiểu chơi tùy thuộc vào việc nó thắng hay thua giải đấu.
Michael Brandon Morris

1
Tôi không biết nếu StackOverflow thông báo cho bạn khi câu trả lời đã được chỉnh sửa, nhưng tôi có một phiên bản cập nhật của The Kid Kid được đăng ngay bây giờ.
Ralph Marshall

Câu trả lời:


5

The Kid Kid

Cố gắng đảm bảo rằng chúng tôi rút một thẻ khác nếu chúng tôi biết mình đang thua, nếu không hãy nhìn vào bộ bài phụ của chúng tôi và điểm tổng thể để quyết định làm gì.

Cập nhật để thực hiện công việc xử lý tình huống tốt hơn khi đối thủ đã chơi xong. Trong thử nghiệm của riêng tôi, điều này dường như là ứng cử viên tốt nhất một lần nữa, ít nhất là bây giờ.

package Players;

import java.util.Collection;

import Mechanics.*;

public class CincinnatiKid extends Player {

    public CincinnatiKid() {
        name = "The Cincinnati Kid";
    }

    private static boolean isDebug = false;

    private static final int BEST_HAND = 20;

    public void getResponse(int wins[],
                            boolean isPlayerOne,
                            Collection<Card> yourHand,
                            Collection<Card> opponentHand,
                            Collection<Card> yourSideDeck,
                            int opponentSideDeckCount,
                            Action opponentAction,
                            boolean opponentDidPlay)
    {
        int myValue = handValue(yourHand);
        int oppValue = handValue(opponentHand);

        if (oppValue > BEST_HAND) {
            logMsg("Opponent has busted");
            action = Action.STAND;
        } else if (myValue > BEST_HAND) {
            logMsg("I have busted");
            action = Action.STAND;
        } else if (myValue <= 10) {
            logMsg("I cannot bust with my next move");
            action = Action.END;
        } else {
            handleTrickySituation(myValue, oppValue, wins, isPlayerOne, yourHand, opponentHand,
                                  yourSideDeck, opponentSideDeckCount, opponentAction, opponentDidPlay);
        }

        if (action == Action.PLAY && cardToPlay == null) {
            logMsg("ERROR - Action is Play but no card chosen");
        }
        logMsg("My hand value is " + myValue + ", opponent is " + oppValue + ", action is " + action +
               ((action == Action.PLAY && cardToPlay != null) ? " a " + cardToPlay.toString() : ""));
    }

    int [] branchCounts = new int[12];

    public void dumpBranchCounts() {
        if (isDebug) {
            for (int i = 0; i < branchCounts.length; i++) {
                System.out.print("b[" + i + "]=" + branchCounts[i] + " ");
            }
            System.out.println();
        }
    }

    private void handleTrickySituation(int myValue, int oppValue,
                                       int wins[],
                                       boolean isPlayerOne,
                                       Collection<Card> yourHand,
                                       Collection<Card> opponentHand,
                                       Collection<Card> yourSideDeck,
                                       int opponentSideDeckCount,
                                       Action opponentAction,
                                       boolean opponentDidPlay)
    {
        dumpBranchCounts();
        logMsg("I am might bust");

        int STAND_VALUE = 18;
        int chosenBranch = 0;

        Card bestSideCard = findSideCard(myValue, yourSideDeck);
        int valueWithSideCard = myValue + (bestSideCard != null ? bestSideCard.getValue() : 0);

        if (bestSideCard != null && valueWithSideCard >= oppValue && valueWithSideCard > STAND_VALUE) {
            logMsg("Found a good card in side deck");
            action = Action.PLAY;
            cardToPlay = bestSideCard;
            chosenBranch = 1;
        } else if (opponentDidPlay || opponentAction == Action.STAND) {
            logMsg("Opponent is done");
            // Opponent is done, so get another card if I'm behind
            if (myValue < oppValue) {
                logMsg("I am behind");
                if (bestSideCard != null && valueWithSideCard >= oppValue) {
                    logMsg("My best side card is good enough to tie or win");
                    action = Action.PLAY;
                    cardToPlay = bestSideCard;
                    chosenBranch = 2;
                } else {
                    logMsg("My best side card won't do so I'm going to hit");
                    // No side card and I'm losing, so I might as well hit
                    action = Action.END;
                    chosenBranch = 3;
                }
            } else if (myValue == oppValue) {
                logMsg("Game is tied");
                logMsg("Looking for lowest card in the side deck");
                cardToPlay = findWorstSideCard(myValue, yourSideDeck);
                if (cardToPlay != null) {
                    action = Action.PLAY;
                    chosenBranch = 4;
                } else {
                    logMsg("Tied with no side cards - accept the draw");
                    action = Action.STAND;
                    chosenBranch = 5;
                }
            } else {
                logMsg("I'm ahead and opponent has given up");
                action = Action.STAND;
                chosenBranch = 6;
            }
        } else if (myValue < oppValue) {
            logMsg("I am behind and have nothing good in my side deck");
            action = Action.END;
            chosenBranch = 7;
        } else if (oppValue <= 10 && myValue < STAND_VALUE) {
            logMsg("Opponent is guaranteed to hit and I have a low hand, so take another");
            action = Action.END;
            chosenBranch = 8;
        } else if (myValue == oppValue && myValue >= STAND_VALUE) {
            logMsg("We both have equally good hands - stand and hope for the tie");
            action = Action.STAND;
            chosenBranch = 9;
        } else if (myValue < STAND_VALUE) {
            logMsg("I am ahead but have a low score");
            action = Action.END;
            chosenBranch = 10;
        } else {
            logMsg("I am ahead with a decent score");
            action = Action.STAND;
            chosenBranch = 11;
        }

        branchCounts[chosenBranch]++;
    }

    private double calcBustOdds(int valueSoFar, Collection<Card> myHand, Collection<Card> oppHand) {

        if (valueSoFar >= BEST_HAND) {
            return 1;
        }

        int remainingDeck = 40 - (myHand.size() + oppHand.size());
        int [] cardCounts = new int[10];
        int firstBust = BEST_HAND - valueSoFar;

        for (int i = 0; i < 10; i++) {
            cardCounts[i] = 4;
        }

        for (Card c : myHand) {
            cardCounts[c.getValue()-1]--;
        }

        for (Card c : oppHand) {
            cardCounts[c.getValue()-1]--;
        }

        int bustCards = 0;
        for (int i = firstBust; i < 10; i++) {
            logMsg("cardCounts[" + i + "]=" + cardCounts[i]);
            bustCards += cardCounts[i];
        }

        double retval = (double) bustCards / (double) remainingDeck;
        logMsg("Out of " + remainingDeck + " remaining cards " + bustCards + " will bust, or " + retval);
        return retval;
    }

    private Card findSideCard(int myValue, Collection<Card> sideDeck) {
        int valueNeeded = BEST_HAND - myValue;
        Card bestCard = null;
        if (valueNeeded > 0) {
            for (Card c : sideDeck) {
                if (c.getValue() == valueNeeded) {
                    return c;
                } else if (c.getValue() < valueNeeded) {
                    if (bestCard == null || c.getValue() > bestCard.getValue()) {
                        bestCard = c;
                    }
                }
            }
        }

        return bestCard;
    }

    private Card findWorstSideCard(int myValue, Collection<Card> sideDeck) {
        int valueNeeded = BEST_HAND - myValue;

        logMsg("Searching side deck for something with value <= " + valueNeeded);
        Card bestCard = null;

        for (Card c : sideDeck) {
            logMsg("Examining side card " + c.getValue());

            // Find the worst card in the deck, but not if it exceeds the amount left
            if (c.getValue() <= valueNeeded && (bestCard == null || c.getValue() < bestCard.getValue())) {
                logMsg("This is the new best side card");
                bestCard = c;
            }
        }

        logMsg("Worst side card found is " + (bestCard != null ? bestCard.getValue() : " n/a"));
        return bestCard;
    }

    private void logMsg(String s) {
        if (isDebug) {
            System.out.println("### " + s);
        }
    }

    private int handValue(Collection<Card> hand)  {
        int handValue = 0;
        for (Card c : hand) {
            handValue += c.getValue();
        }
        return handValue;
    }
}

Xin chúc mừng! Bạn đang dẫn đầu.
Michael Brandon Morris

Với những sửa đổi để làm cho hệ thống tính điểm trở nên công bằng hơn, giờ đây bạn được gắn kết đầu tiên với Austin Powers.
Michael Brandon Morris

4

sức mạnh của Austin

Austin Powers, như bạn có thể đoán, thích sống nguy hiểm. Trừ khi ai đó đã đánh bại, hoặc anh ta có thể đảm bảo một chiến thắng, anh ta sẽ luôn đánh nếu anh ta đứng sau, hoặc có hơn 20% cơ hội không bị phá sản.

package Players;
import java.util.Collection;

import Mechanics.*;

public class AustinPowers extends Player {
    public AustinPowers() {
        name = "Austin Powers";
    }
    int MAX_VALUE = 20;
    public void getResponse(int wins[], boolean isPlayerOne,
            Collection<Card> yourHand, Collection<Card> opponentHand,
            Collection<Card> yourSideDeck, int opponentSideDeckCount,
            Action opponentAction, boolean opponentDidPlay) {
        action = null;
        cardToPlay = null;
        int myWins = isPlayerOne?wins[0]:wins[1];
        int oppWins = isPlayerOne?wins[1]:wins[0];
        int oppTotal = calcHand(opponentHand);
        int myTotal = calcHand(yourHand);
        boolean liveDangerously = ((oppTotal>=myTotal && opponentAction==Action.STAND) || opponentAction==Action.END) && myTotal<MAX_VALUE && canNotBust(yourHand,opponentHand,myTotal) && myWins<oppWins;

        if(myTotal==MAX_VALUE || oppTotal>MAX_VALUE || myTotal>MAX_VALUE ||(oppTotal<myTotal&&opponentAction==Action.STAND))
        {
            action = Action.STAND;
        }
        else if((opponentAction==Action.STAND&&hasGoodEnoughSideCard(yourSideDeck,myTotal,oppTotal))||hasPerfectSideCard(yourSideDeck, myTotal))
        {
            action = Action.PLAY;
        }
        else if(liveDangerously||betterThan20(myTotal, getDeck(yourHand, opponentHand)))
        {
            action = Action.END;
        }
        else
        {
            action=Action.STAND;
        }

    }

    private boolean hasGoodEnoughSideCard(Collection<Card> yourSideDeck,
            int myTotal, int oppTotal) {
        for(Card c: yourSideDeck)
        {
            if(MAX_VALUE>=myTotal+c.getValue()&&myTotal+c.getValue()>oppTotal)
            {
                cardToPlay=c;
                return true;
            }
        }
        return false;
    }

    private boolean betterThan20(int myTotal, int[] deck) {
        int deckSize=0;
        int nonBustCards=0;
        for(int i=0;i<10;i++)
        {
            deckSize+=deck[i];
            if(MAX_VALUE-myTotal>i)
                nonBustCards+=deck[i];
        }
        return (double)nonBustCards/(double)deckSize>0.2;
    }

    private boolean hasPerfectSideCard(Collection<Card> yourSideDeck,
            int myTotal) {
        for(Card c:yourSideDeck)
        {
            if(MAX_VALUE-myTotal== c.getValue())
            {
                cardToPlay = c;
                return true;
            }
        }
        return false;
    }

    private boolean canNotBust(Collection<Card> yourHand,
            Collection<Card> opponentHand, int myTotal) {
        if(myTotal<=10) return true;
        int[] deck = getDeck(yourHand, opponentHand);
        for(int i=0;i<MAX_VALUE-myTotal;i++)
            if(deck[i]>0)
                return true;
        return false;
    }

    private int[] getDeck(Collection<Card> yourHand,
            Collection<Card> opponentHand) {
        int[] deck = new int[10];
        for (int i = 0; i < 10; i++) {
            deck[i] = 4;
        }
        for(Card c:yourHand){deck[c.getValue()-1]--;}
        for(Card c:opponentHand){deck[c.getValue()-1]--;}
        return deck;
    }

    private int calcHand(Collection<Card> hand)
    {
        int ret = 0;
        for(Card c: hand){ret+=c.getValue();}
        return ret;
    }
}

Xin chúc mừng! Bạn đã dẫn đầu từ CincinnatiKid.
Michael Brandon Morris

Với những sửa đổi để làm cho hệ thống tính điểm trở nên công bằng hơn, giờ đây bạn đã được gắn kết đầu tiên với The Cincinnati Kid.
Michael Brandon Morris

2

Bastila

Bastila chơi bảo thủ. Đối với cô ấy, số 17 chỉ bằng 20, và tốt hơn hết là đứng ngắn hơn ném bom.

package Players;

import java.util.Collection;

import Mechanics.*;

public class Bastila extends Player {

    public Bastila() {
        name = "Bastila";
    }

    public void getResponse(int wins[], boolean isPlayerOne,
            Collection<Card> myHand, Collection<Card> opponentHand,
            Collection<Card> mySideDeck, int opponentSideDeckCount,
            Action opponentAction, boolean opponentDidPlay) {


        action = null;
        cardToPlay = null;

        //Constants
        int stand = 17;
        int conservatism = 2;

        //Get some info
        int handVal = handValue(myHand);
        int expected = expectedValue(myHand);

        //Can I play from my side deck?
        for(Card side: mySideDeck){
            int total = side.getValue() + handVal;
            if(total >= stand && total <= 20){
                cardToPlay = side;
                action = Player.Action.PLAY;
            }
        }
        if(action == Player.Action.PLAY){
            return;
        }

        //Otherwise, will I go bust?
        if(handVal + expected > 20 - conservatism){
            action = Player.Action.STAND;
        }
        else{
            action = Player.Action.END;
        }

        return;

    }

    private int handValue(Collection<Card> hand) {
        int handValue = 0;
        for(Card c : hand){
            handValue += c.getValue();
        }
        return handValue;
    }

    private int expectedValue(Collection<Card> hand){
        //Net value of the deck is 55*4 = 220
        int total = 220;
        int count = 40;
        for(Card c : hand){
            total -= c.getValue();
            count--;
        }
        return total/count;
    }

}

Bastila hiện đang vượt trội hơn cả Dumb Bold Player và Dumb Cautious Player (bản demo demo). Làm tốt lắm! Chỉnh sửa: Trong số mười lượt chạy, Bastila đã thắng tám, thua Dumb Cautious Player một lần và trói buộc với Dumb Cautious Player một lần.
Michael Brandon Morris

Cập nhật: Với hệ thống tính điểm mới (chiến thắng được tính theo tourneys, trong đó 1000 người được chơi với mỗi cặp người chơi), Bastila dẫn đầu với tổng số 1705/3000 (1705/2000 tourneys đã chơi). Tiếp theo là Dumb Cautious Player với 729, và cuối cùng là Dumb Bold Player với 566.
Michael Brandon Morris

Haha tốt, tôi sẽ hy vọng nó ít nhất đánh bại các bot demo: P
Cain

2

Yến

Nestor thích nhận 20 bằng cách sử dụng bộ bài phụ của mình, nhưng khi thất bại, anh ta tính toán mức chi trả dự kiến ​​của mình bằng cách chọn đứng hoặc kết thúc, giả sử rằng đối thủ là hợp lý.

package Players;

import java.util.Arrays;
import java.util.Collection;


import Mechanics.Card;
import Mechanics.Player;

public class Nestor extends Player {
    final int TotalWinPayoff = 10;
    final int TotalLosePayoff = 0;
    final int TotalDrawPayoff = 1;
    final int temporaryLosePayoff = 4;
    final int temporayWinPayoff = 19;
    final int temporaryDrawPayoff = 9;
    @Override
    public void getResponse(int[] wins, boolean isPlayerOne,
            Collection<Card> yourHand, Collection<Card> opponentHand,
            Collection<Card> yourSideDeck, int opponentSideDeckCount,
            Action opponentAction, boolean opponentDidPlay) {

        int sumMyHand = SumHand(yourHand);
        int sumOpponentHand = SumHand(opponentHand);
    if (sumOpponentHand>20)
    {this.action = Action.STAND;return;}
        if(sumMyHand == 20)
        {
            //I'm unbeatable :)
            //System.out.println("\tI'm Unbeatable");
            this.action = Action.STAND;
            return;
        }
        else if(opponentDidPlay || opponentAction == Action.STAND)
        {
            //They've finished
            ///System.out.println("\tThey've Finished");
            if(sumMyHand>sumOpponentHand)
            {
                //I've won
                //System.out.println("\tI've Won");
                this.action = Action.STAND;
                return;
            }
            else if(canBeat(sumMyHand, sumOpponentHand, yourSideDeck))
            {
                //I can beat them
                //System.out.println("\tI can beat them");
                this.action = Action.PLAY;
                return;
            }
            else if(canEven(sumMyHand, sumOpponentHand, yourSideDeck))
            {
                //I can draw with them
                //System.out.println("\tI can draw with them");
                this.action = Action.PLAY;
                return;
            }
            else
            {
                //I need another card
                //System.out.println("\tI need another card");
                this.action = Action.END;
                return;
            }
        }
        else if(deckContains(yourSideDeck, 20-sumMyHand))
        {
            //Let's get 20
            //System.out.println("\tLet's get 20");
            this.action = Action.PLAY;
            this.cardToPlay = getCard(yourSideDeck, 20-sumMyHand);
            return;
        }
        else if(sumOpponentHand==20 && sumMyHand<20)
        {
            //They've got 20 so we need to fight for a draw
            //System.out.println("\tFight for a draw");
            this.action = Action.END;
            return;
        }

        else if(sumMyHand<10)
        {
            //Lets get another card
            //System.out.println("\tLet's get another card");
            this.action = Action.END;
            return;
        }
        else
        {
            //Let's work out some probabilities
            //System.out.println("\tLet's work out some probabilities");
            int[] cardsLeft = {4,4,4,4,4,4,4,4,4,4};
            for (Card card : opponentHand) {
                cardsLeft[card.getValue()-1] --;

            }
            for (Card card : yourHand) {
                cardsLeft[card.getValue()-1] --;

            }

             int numCardsLeft = sumfromToEnd(0, cardsLeft);

             //My Assumptions
             double probabilityTheyStand = (double)sumfromToEnd(20-sumOpponentHand, cardsLeft)/numCardsLeft;

             //What I need to know
             double payoffStanding = 0;
             double payoffDrawing = 0;


             for(int myChoice = -1; myChoice<10; myChoice++)
             {
                 for(int theirChoice = -1; theirChoice<10; theirChoice++)
                 {
                     if(myChoice == -1)
                     {
                         payoffStanding += getProbability(myChoice, theirChoice, Arrays.copyOf(cardsLeft, cardsLeft.length), probabilityTheyStand, numCardsLeft) * getPayoff(sumMyHand, sumOpponentHand,myChoice, theirChoice, TotalWinPayoff, TotalDrawPayoff, TotalLosePayoff);
                     }
                     else
                     {
                         payoffDrawing +=
                                 getProbability(myChoice, theirChoice, Arrays.copyOf(cardsLeft, cardsLeft.length), probabilityTheyStand, numCardsLeft)
                                 * getPayoff(sumMyHand, sumOpponentHand, myChoice, theirChoice, temporayWinPayoff, temporaryDrawPayoff, temporaryLosePayoff);
                     }
                 }
             }
            // System.out.println("\tStanding: " +Double.toString(payoffStanding) + " Ending: " + Double.toString(payoffDrawing));
             if(payoffStanding<payoffDrawing)
             {
                 this.action = Action.END;
             }
             else
             {
                 this.action = Action.STAND;
             }
        }


    }



    private int getPayoff(int sumMyHand, int sumOpponentHand, int myChoice,
            int theirChoice, int WinPayoff, int DrawPayoff,
            int LosePayoff) {
            if(sumMyHand + myChoice + 1 > 20)
            {
                if(sumOpponentHand + theirChoice + 1 > 20)
                {
                    return DrawPayoff;
                }
                else
                {
                    return LosePayoff;
                }
            }
            else if(sumMyHand + myChoice + 1 > sumOpponentHand + theirChoice + 1)
            {
                return WinPayoff;
            }
            else if (sumMyHand + myChoice + 1 < sumOpponentHand + theirChoice + 1)
            {
                return LosePayoff;
            }
            else
            {
                return DrawPayoff;
            }


    }



    private double getProbability(
            int myChoice, int theirChoice, int[] cardsLeft,
            double probabilityTheyStand, int numCardsLeft) {
        double myProb, theirProb;
        if(myChoice<0)
        {
            myProb = 1;
        }
        else
        {
            myProb = ((double)cardsLeft[myChoice])/((double)numCardsLeft);
            cardsLeft[myChoice]--;
            numCardsLeft--;
        }

        if(theirChoice<0)
        {
            theirProb = probabilityTheyStand;
        }
        else
        {
            theirProb = ((double)cardsLeft[theirChoice]) / ((double)numCardsLeft);
        }
        return myProb*theirProb;
    }





    private int sumfromToEnd(int i, int[] cardsLeft) {
        int toRet = 0;
        for(;i<cardsLeft.length; i++)
        {
            toRet += cardsLeft[i];
        }
        return toRet;
    }

    private boolean canEven(int mySum, int opponentSum,
            Collection<Card> yourSideDeck) {
        for (Card card : yourSideDeck) {
            if(mySum + card.getValue() <= 20 && mySum + card.getValue() >= opponentSum)
            {
                this.cardToPlay = card;
                return true;
            }
        }
        return false;
    }

    private boolean canBeat(int mySum, int opponentSum,
            Collection<Card> yourSideDeck) {
        for (Card card : yourSideDeck) {
            if(mySum + card.getValue() <= 20 && mySum + card.getValue() > opponentSum)
            {
                this.cardToPlay = card;
                return true;
            }
        }
        return false;
    }

    private Card getCard(Collection<Card> deck, int value) {
        for (Card card : deck) {
            if(card.getValue() == value)
            {
                return card;
            }
        }
        return null;
    }

    private boolean deckContains(Collection<Card> deck, int value) {
        for (Card card : deck) {
            if(card.getValue() == value)
            {
                return true;
            }
        }
        return false;
    }

    public Nestor()
    {
        super();
        name = "Nestor";
    }

    private int SumHand(Collection<Card> hand)
    {
        int toRet = 0;
        for (Card card : hand) {
            toRet += card.getValue();
        }
        return toRet;
    }
}

Xin chúc mừng! Bạn đã vượt qua sự ràng buộc giữa Austin Powers và The Kid Kid để giành vị trí đầu tiên.
Michael Brandon Morris

Ngoại lệ trong luồng "chính" java.lang.ArrayIndexOutOfBoundException: -2 tại Người chơi.Nestor.sumfromToEnd (Nestor.java:210) tại Người chơi.Nestor.getResponse (Nestor.java:105) tại Cơ học.PazaakGameMain : 112) tại Cơ học.PazaakGameMain.main (PazaakGameMain.java:40)
Michael Brandon Morris

Bạn có phiền giúp tôi xem xét điều đó không? Nó dường như là dành riêng cho bot, vì nó chỉ kích hoạt khi chơi Neptor và T3M4 (bot chưa được phát hành trên github).
Michael Brandon Morris

Từ những gì tôi có thể nói, nó kích hoạt nếu đối thủ của bạn đã đánh bại, nhưng vì một số lý do, họ đã không đứng vững. Tôi đang đặt một bản sửa lỗi tạm thời trong bot của bạn, nhưng sẽ sửa bộ điều khiển sau để tự động STAND bot phá vỡ.
Michael Brandon Morris

Tôi đã thêm một kiểm tra khi đối thủ đã đánh bại, cảm ơn
euanjt

1

Glaucus

package Players;


import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import Mechanics.Card;
import Mechanics.Player;

public class Glaucus extends Player {
    static final double LosePay = 0;
    static final double WinPay = 10;
    static final double DrawPay = 1;
    static final int NUMBEROFSIMS = 100;

    Random r;

    public Glaucus()
    {
        this.name = "Glaucus";
        r = new Random();
    }

    @Override
    public void getResponse(int[] wins, boolean isPlayerOne,
            Collection<Card> yourHand, Collection<Card> opponentHand,
            Collection<Card> yourSideDeck, int opponentSideDeckCount,
            Action opponentAction, boolean opponentDidPlay) {
        //Make Sum of hands
        int sumMyHand = 0;
        int sumOpponentHand = 0;
        //Make an array of the remaining cards
        List<Integer> cards = new LinkedList<Integer>();
        int[] cardsLeft = {4,4,4,4,4,4,4,4,4,4};
        for (Card card : yourHand) {
            cardsLeft[card.getValue()-1] -= 1;
            sumMyHand+=card.getValue();
        }
        for (Card card : opponentHand) {
            cardsLeft[card.getValue()-1] -= 1;
            sumOpponentHand += card.getValue();
        }
        if(sumMyHand<=10)
        {
            this.action = Action.END;
        }
        else if (sumMyHand >= 20)
        {
            this.action = Action.STAND;
        }
        else if (sumOpponentHand > 20)
        {
            this.action = Action.STAND;
        }
        else
        {
            for (int i = 0; i < cardsLeft.length; i++) {
                while(cardsLeft[i] > 0)
                {
                    cards.add(i + 1);
                    cardsLeft[i] -= 1;
                }
            }
            //System.out.println(Arrays.toString(cards));

            double standPayoff = 0;
            double endPayoff = 0;
            double[] sideDeckPayoffs = new double[yourSideDeck.size()];
            //Run some simulations
            for(int sim = 0; sim<NUMBEROFSIMS; sim++)
            {
                Collections.shuffle(cards, r);
                standPayoff += getPayoff(sumMyHand, sumOpponentHand, cards, Action.STAND, opponentAction, false, 0);
                endPayoff += getPayoff(sumMyHand, sumOpponentHand, cards, Action.END, opponentAction, false, 0);
                for(int i = 0; i<sideDeckPayoffs.length; i++)
                {
                    sideDeckPayoffs[i] += getPayoff(sumMyHand+((Card)yourSideDeck.toArray()[i]).getValue(), sumOpponentHand, cards, Action.STAND, opponentAction, false, 0);
                }

            }

            double maxSidePay = 0;
            int sideDeckChoice  = 0;
            for (int i = 0; i < sideDeckPayoffs.length; i++) {
                double d = sideDeckPayoffs[i];
                if(d>maxSidePay)
                {
                    maxSidePay = d;
                    sideDeckChoice = i;
                }
            }
            /*System.out.println(standPayoff);
            System.out.println(endPayoff);
            System.out.println(maxSidePay);*/

            if(maxSidePay>standPayoff && maxSidePay>endPayoff)
            {
                this.action = Action.PLAY;
                this.cardToPlay = (Card)yourSideDeck.toArray()[sideDeckChoice];
            }
            else if(standPayoff > endPayoff)
            {
                this.action = Action.STAND;
            }
            else
            {
                this.action = Action.END;
            }
        }
    }

    private double getPayoff(int sumMyHand, int sumOpponentHand,
            List<Integer> cards, Action myAction, Action opponentAction, boolean myTurn, int index) {
        //SHort circuit some logic
        if(sumMyHand>20 && sumOpponentHand>20)
        {
            return DrawPay;
        }
        else if(sumMyHand>20)
        {
            return LosePay;
        }
        else if(sumOpponentHand>20)
        {
            return WinPay;
        }
        else if(myAction == Action.STAND && opponentAction == Action.STAND)
        {
            if(sumMyHand>sumOpponentHand)
            {
                return WinPay;
            }
            else if(sumMyHand<sumOpponentHand)
            {
                return LosePay;
            }
            else
            {
                return DrawPay;
            }
        }
        else
        {
            double standPayoff = 0;
            double endPayoff = 0;

            if(myTurn)
            {
                if(opponentAction == Action.END)
                {
                    sumOpponentHand += cards.get(index);
                    index++;
                }
                if(myAction == Action.STAND)
                {

                    return getPayoff(sumMyHand, sumOpponentHand, cards, myAction, opponentAction, false, index);
                }
                else
                {

                    standPayoff = getPayoff(sumMyHand, sumOpponentHand, cards, Action.STAND, opponentAction, false, index);
                    endPayoff = getPayoff(sumMyHand, sumOpponentHand, cards, Action.END, opponentAction, false, index);
                    if(standPayoff>endPayoff)
                    {
                        return standPayoff;
                    }
                    else
                    {
                        return endPayoff;
                    }
                }
            }
            else
            {
                if(myAction == Action.END)
                {
                    sumMyHand += cards.get(index);
                    index++;
                }
                if(opponentAction == Action.STAND)
                {
                    return getPayoff(sumMyHand, sumOpponentHand, cards, myAction, opponentAction, true, index);
                }
                else
                {
                    standPayoff = getPayoff(sumMyHand, sumOpponentHand, cards, myAction, Action.STAND, true, index);
                    endPayoff = getPayoff(sumMyHand, sumOpponentHand, cards, myAction, Action.END, true, index);
                    if(standPayoff<endPayoff)
                    {
                        return standPayoff;
                    }
                    else
                    {
                        return endPayoff;
                    }
                }
            }
        }
    }
}

Glaucus thực hiện 100 mô phỏng với danh sách thẻ được xáo trộn và chọn tùy chọn tốt nhất của mình dựa trên các mô phỏng này.


Tôi đánh giá cao nếu bạn có thể cắt giảm số lượng mô phỏng. Sẽ mất hơn một phút để hoàn thành một cuộc chạy đua với một đối thủ duy nhất và chống lại tất cả các bot khác, khiến thời gian chạy của chúng tôi kéo dài hơn 7 phút, trái ngược với 30 giây chỉ với các bot khác.
Michael Brandon Morris

Chỉ cần thay đổi hằng số NUMBEROFSIMS cho đến khi mất một khoảng thời gian hợp lý, trên máy tính của tôi, nó quản lý 100 sim khá nhanh, đó là lý do tại sao tôi chọn giá trị đó nhưng cứ thoải mái thay đổi :)
euanjt

Nó có thể nhanh hơn trên máy tính để bàn của tôi (i7-3770K), nhưng máy tính xách tay của tôi (i5-4300U) (mà tôi bị kẹt trong một tuần) thì chậm hơn. Tôi sẽ đặt Glaucus trở lại khi tôi quay lại máy tính để bàn của mình.
Michael Brandon Morris

Tôi sẽ cố gắng tăng tốc vào ngày mai và để nó chạy sim trong một khoảng thời gian nhất định thay vì số sim cố định - mỗi lần chấp nhận được bao lâu?
euanjt

Thay vì chạy mô phỏng, tại sao không ước tính xác suất trực tiếp với phân phối siêu bội?
InactionPotential

1

HK-47

Hãy chứng kiến! Một bot của thiết kế của riêng tôi. HK-47 cố gắng giết tất cả các túi thịt mà anh ta có thể, mặc dù anh ta có một chút kích hoạt hạnh phúc với thẻ bài bên cạnh của mình.

Tuyên bố: Thật vậy, tôi rất háo hức tham gia vào một số bạo lực không được kiểm soát. Theo lệnh của bạn tất nhiên, Master. - HK-47

Cho đến nay, anh ta có thể đánh bại tất cả mọi người trừ The Kid Kid.

package Players;

import java.util.Collection;

import Mechanics.*;

public class HK47 extends Player {

    /** The hand goal. */
    private static final int GOAL = 20;
    /** The cutoff for standing versus ending. */
    private static final int STAND_CUTOFF = 17;
    /** The minimum value for playing. */
    private static final int PLAY_MINIMUM = 14;
    /** The cutoff for ending versus decision evaluation. */
    private static final int SAFETY_CUTOFF = 10;

    /** The hand wins for this game. Used to evaluate win priority. */
    private int[] handWins;
    /**
     * My hand, as an unmodifiable collection. Used to evaluate decisions, after
     * being processed into myHandValue.
     */
    private Collection<Card> myHand;
    /**
     * Opponent's hand. Used to evaluate decisions as a secondary factor to my
     * hand, after being processed into oppHandValue.
     */
    private Collection<Card> oppHand;
    /** The value of my hand. Calculated via the myHandValue method. */
    private int myHandValue;
    /** The value of my opponent's hand. Calculated via the oppHandValue method. */
    private int oppHandValue;
    /** My side deck. Used to evaluate PLAY decisions. */
    private Collection<Card> mySideDeck;
    /**
     * The number of cards in my opponent's side deck. Used to evaluate PLAY
     * decisions as a secondary factor to mySideDeck, alongside win priority.
     */
    private int oppSideDeckCount;
    /**
     * The Action the opponent last took. Will either be STAND or END. Used to
     * evaluate decisions.
     */
    private Action oppAction;
    /** Whether or not I am player one. Used to evaluate wins and losses. */
    private boolean amPlayerOne;
    /**
     * The number of wins I have so far this game. Used to evaluate win priority
     * alongside myLosses.
     */
    private int myWins;
    /**
     * The number of losses I have so far this game. Used to evaluate win
     * priority alongside myWins.
     */
    private int myLosses;
    /**
     * How important it is for me to play. Positive values indicate an excess of
     * cards, and negative values indicate a deficit.
     */
    private int playPriority;
    /**
     * How important it is for me to win. Positive values indicate that I must
     * win the game, and negative values indicate that I can take some chances.
     */
    private int winPriority;
    /**
     * The sum of playPriority and winPriority. The higher the value, the fewer
     * chances I need to take.
     */
    private int priority;

    public HK47() {
        name = "HK47";
    }

    @Override
    public void getResponse(int[] wins, boolean isPlayerOne,
            Collection<Card> yourHand, Collection<Card> opponentHand,
            Collection<Card> yourSideDeck, int opponentSideDeckCount,
            Action opponentAction, boolean opponentDidPlay) {
        handWins = wins;
        amPlayerOne = isPlayerOne;
        myHand = yourHand;
        oppHand = opponentHand;
        mySideDeck = yourSideDeck;
        oppSideDeckCount = opponentSideDeckCount;
        oppAction = opponentAction;
        myHandValue = myHandValue();
        oppHandValue = oppHandValue();
        setStatistics();
        chooseOption();
    }

    /**
     * Calculates playPriority, winPriority, and priority.
     */
    private void setStatistics() {
        if (amPlayerOne) {
            myWins = handWins[0];
            myLosses = handWins[1];
        } else {
            myWins = handWins[1];
            myLosses = handWins[0];
        }
        playPriority = 0;
        winPriority = 0;
        if (mySideDeck.size() > oppSideDeckCount) {
            playPriority++;
        } else if (mySideDeck.size() < oppSideDeckCount) {
            playPriority--;
        }
        if (myWins < myLosses) {
            winPriority++;
        } else if (myWins == myLosses && myWins == 2) {
            winPriority++;
        } else if (myWins > myLosses && myWins != 2) {
            winPriority--;
        }
        priority = playPriority + winPriority;
    }

    /**
     * Chooses the appropriate option based on my hand, the opponent's hand, the
     * opponent's stance, my priority, and whether or not I can play to certain
     * values.
     */
    private void chooseOption() {
        // Path 1: Draw if at 10 or under.
        if (myHandValue <= SAFETY_CUTOFF) {
            action = Action.END;
            path = "1";
        }
        // Path 2: Draw if over 20.
        else if (myHandValue > GOAL) {
            action = Action.END;
            path = "2";
        }
        // Path 3: Stand if opponent over 20.
        else if (oppHandValue > GOAL) {
            path = "3";
            action = Action.STAND;
        }
        // Path 4: If opponent is at 20...
        else if (oppHandValue == GOAL) {
            // Path 4.1: Play if can reach 20.
            if (canPlayToGoal()) {
                action = Action.PLAY;
                path = "4.1";
            }
            // Path 4.0: Stand.
            else {
                action = Action.END;
                path = "4.0";
            }
        }
        // Path 5: If opponent is standing...
        else if (oppAction == Action.STAND) {
            // Path 5.1: If I am behind them...
            if (myHandValue < oppHandValue) {
                // Path 5.1.1: If I am at or above the minimum play value...
                if (myHandValue >= PLAY_MINIMUM) {
                    // Path 5.1.1.1: Play if can play.
                    if (canPlay()) {
                        action = Action.PLAY;
                        path = "5.1.1.1";
                    }
                    // Path 5.1.1.0: END
                    else {
                        action = Action.END;
                        path = "5.1.1.0";
                    }
                }
                // Path 5.1.0: END
                else {
                    action = Action.END;
                    path = "5.1.0";
                }
            }
            // Path 5.2: If I am tied with them...
            else if (myHandValue == oppHandValue) {
                // Path 5.2.1: If this game is important...
                if (priority > -1) {
                    // Path 5.2.1.1: Play if can play.
                    if (canPlay()) {
                        action = Action.PLAY;
                        path = "5.2.1.1";
                    }
                    // Path 5.2.1.0: STAND
                    else {
                        action = Action.STAND;
                        path = "5.2.1.0";
                    }
                }
                // Path 5.2.0 STAND
                else {
                    action = Action.STAND;
                    path = "5.2.0";
                }
            }
            // Path 5.0: STAND
            else {
                action = Action.STAND;
                path = "5.0";
            }
        }
        // Path 6: If opponent is not standing...
        else {
            // Path 6.1: If I am behind them...
            if (myHandValue < oppHandValue) {
                // Path 6.1.1: If they are at or above 17, and if this game is
                // important, play if can play to goal.
                if (oppHandValue >= STAND_CUTOFF) {
                    // Path 6.1.1.1
                    if (priority > 0 && canPlayToGoal()) {
                        action = Action.PLAY;
                        path = "6.1.1.1";
                    }
                    // Path 6.1.1.2
                    else if (priority > 0 && canPlayMax()) {
                        action = Action.PLAY;
                        path = "6.1.1.2";
                    }
                    // Path 6.1.1.0
                    else {
                        action = Action.STAND;
                        path = "6.1.1.0";
                    }
                }
                // Path 6.1.2: If I am above 14, play highest value card if can
                // play.
                else if (myHandValue > PLAY_MINIMUM) {
                    // Path 6.1.2.1
                    if (priority > -1 && canPlayToGoal()) {
                        action = Action.PLAY;
                        path = "6.1.2.1";
                    }
                    // Path 6.1.2.2
                    else if (priority > 0 && canPlayMax()) {
                        action = Action.PLAY;
                        path = "6.1.2.2";
                    }
                    // Path 6.1.2.0
                    else {
                        action = Action.STAND;
                        path = "6.1.2.0";
                    }
                }
                // Path 6.1.0
                else {
                    action = Action.END;
                    path = "6.1.0";
                }
            }
            // Path 6.2: If we are tied...
            else if (myHandValue == oppHandValue) {
                // Path 6.2.1
                if (myHandValue >= STAND_CUTOFF) {
                    // Path 6.2.1.1
                    if (priority > -1 && canPlayToGoal()) {
                        action = Action.PLAY;
                        path = "6.2.1.1";
                    }
                    // Path 6.2.1.2
                    else if (priority > 0 && canPlayMax()) {
                        action = Action.PLAY;
                        path = "6.2.1.2";
                    }
                    // Path 6.2.1.0
                    else {
                        action = Action.STAND;
                        path = "6.2.1.0";
                    }
                }
                // Path 6.2.2
                else if (myHandValue >= PLAY_MINIMUM) {
                    // Path 6.2.2.1
                    if (priority >= -1 && canPlayToGoal()) {
                        action = Action.PLAY;
                        path = "6.2.2.1";
                    }
                    // Path 6.2.2.2
                    else if (priority > -1
                            && canPlayMax()
                            && cardToPlay.getValue() + myHandValue >= STAND_CUTOFF) {
                        action = Action.PLAY;
                        path = "6.2.2.2";
                    }
                    // Path 6.2.2.0
                    else {
                        action = Action.END;
                        path = "6.2.2.0";
                    }
                }
                // Path 6.2.0
                else {
                    action = Action.END;
                    path = "6.2.0";
                }
            }
            // Path 6.0: If I am ahead of them...
            else {
                // Path 6.0.1
                if (myHandValue >= STAND_CUTOFF) {
                    // Path 6.0.1.1
                    if (priority >= -2 && canPlayToGoal()) {
                        action = Action.PLAY;
                        path = "6.0.1.1";
                    }
                    // Path 6.0.1.2
                    else if (priority > -2 && canPlayMax()) {
                        action = Action.PLAY;
                        path = "6.0.1.2";
                    }
                    // Path 6.0.1.0
                    else {
                        action = Action.STAND;
                        path = "6.0.1.0";
                    }
                }
                // Path 6.0.2
                else if (myHandValue >= PLAY_MINIMUM) {
                    // Path 6.0.2.1
                    if (priority >= -2 && canPlayToGoal()) {
                        action = Action.PLAY;
                        path = "6.0.2.1";
                    }
                    // Path 6.0.2.2
                    else if (priority > -2 && canPlayMax()
                            && cardToPlay.getValue() > 3) {
                        action = Action.PLAY;
                        path = "6.0.2.2";
                    }
                    // Path 6.0.2.3
                    else if (priority > -2
                            && canPlayMax()
                            && cardToPlay.getValue() + myHandValue > STAND_CUTOFF) {
                        action = Action.PLAY;
                        path = "6.0.2.3";
                    }
                    // Path 6.0.2.4
                    else if (priority > -1
                            && canPlayMax()
                            && cardToPlay.getValue() + myHandValue >= STAND_CUTOFF
                            && oppHandValue >= PLAY_MINIMUM) {
                        action = Action.PLAY;
                        path = "6.0.2.4";
                    }
                    // Path 6.0.2.0
                    else {
                        action = Action.END;
                        path = "6.0.2.0";
                    }
                }
                // Path 6.0.0
                else {
                    action = Action.END;
                    path = "6.0.0";
                }
            }
        }
        // Path 0: No action selected.
        if (action == null) {
            action = Action.STAND;
            path = "0";
        }
    }

    /**
     * Calculates the value of my hand.
     * 
     * @return The value of my hand.
     */
    private int myHandValue() {
        int handValue = 0;
        for (Card c : myHand)
            handValue += c.getValue();
        return handValue;
    }

    /**
     * Calculates the value of the opponent's hand.
     * 
     * @return The value of the opponent's hand.
     */
    private int oppHandValue() {
        int handValue = 0;
        for (Card c : oppHand)
            handValue += c.getValue();
        return handValue;
    }

    /**
     * Checks if a side deck card can be played to beat the opponent. Selects
     * the first card that will do so, if one is found. Should only be used if
     * the opponent is standing and not at the goal.
     * 
     * @return Whether or not a card can be played to beat the opponent.
     */
    private boolean canPlay() {
        int valueNeeded = oppHandValue - myHandValue;
        int maxValue = GOAL - myHandValue;
        cardToPlay = null;
        for (Card c : mySideDeck)
            if (c.getValue() >= valueNeeded && c.getValue() <= maxValue) {
                cardToPlay = c;
                return true;
            }
        return false;
    }

    /**
     * Checks if a side deck card can be played to reach the goal. Selects the
     * first card that will do so, if one is found.
     * 
     * @return Whether or not a card can be played to reach the goal.
     */
    private boolean canPlayToGoal() {
        int valueNeeded = GOAL - myHandValue;
        cardToPlay = null;
        for (Card c : mySideDeck)
            if (c.getValue() == valueNeeded) {
                cardToPlay = c;
                return true;
            }
        return false;
    }

    /**
     * Checks if a side deck card can be played that beats the opponent. Selects
     * the highest value card that will do so, if one or more are found. Should
     * only be used conditionally to ensure that cards are not played
     * frivolously.
     * 
     * @return Whether or not a card can be played to beat the opponent.
     */
    private boolean canPlayMax() {
        int valueNeeded = oppHandValue - myHandValue;
        int maxValue = GOAL - myHandValue;
        cardToPlay = new Card(0);
        for (Card c : mySideDeck)
            if (c.getValue() >= valueNeeded && c.getValue() <= maxValue
                    && c.getValue() > cardToPlay.getValue()) {
                cardToPlay = c;
            }
        if (cardToPlay.getValue() > 0)
            return true;
        return false;
    }
}

-1

NEPTR

(Không bao giờ kết thúc Robot ném bánh)

Hải vương là xin lỗi, Hải vương lừa dối. Sao Hải Vương thực sự sẽ trở nên sạch sẽ, anh chỉ muốn vui vẻ trước thôi :(

 package Players;

import java.util.Collection;
import java.util.Random;

import Mechanics.*;

public class Neptor extends Player {


    //Magical Constants
    double ovenTemp = 349.05;
    double altitudeFactor = 1.8;
    int full = 19;
    boolean imTheBaker = true;

    public Neptor() {
        name = "N.E.P.T.R";
    }

    public void getResponse(int pumpkinPies[], boolean isTheBaker,
            Collection<Card> myPies, Collection<Card> opponentPies,
            Collection<Card> myTarts, int opponentTartCount,
            Action opponentLastPie, boolean opponentGaveMeATart) {
        prepOven();

        imTheBaker = isTheBaker;

        action = null;
        cardToPlay = null;



        //Get some info
        int handPies = eat(myPies);
        int opHandPies = eat(opponentPies);

        //Are they full? 
        if(opponentLastPie == Player.Action.STAND){
            throwPies(handPies, opHandPies, myTarts, pumpkinPies);
            return;
        }

        //Will a tart do the job?
        for(int i = 0; i <= 20 - full; i++){
            for(Card side: myTarts){
                int total = side.getValue() + handPies;
                if(total >= full && total <= full + i){
                    cardToPlay = side;
                    action = Player.Action.PLAY;
                    break;
                }
            }
        }
        if(action == Player.Action.PLAY){
            return;
        }

        //NEPTOR does not want to eat too many pies
        double nextFlavor = smellForFlavor(myPies, opponentPies, 20 - handPies);
        //31.415% chance seems good
        if(nextFlavor < 0.31415){
            action = Player.Action.END;
        }
        else{
            bakePies(handPies, pumpkinPies, opHandPies);
        }

        return;

    }

    //Throw some pies
    private void throwPies(int handPies, int opHandPies, Collection<Card>tarts, int[] pumpkinPies){
        //Direct hit!
        if(handPies > opHandPies){
            action = Player.Action.STAND;
        }
        //Tied or losing
        else{
            //Add a tart to the volley, finish them!
            for(Card tart: tarts){
                if(handPies + tart.getValue() <= 20 && handPies + tart.getValue() > opHandPies){
                    cardToPlay = tart;
                    action = Player.Action.PLAY;
                    return;
                }
            }
            //we need more pies
            bakePies(handPies, pumpkinPies, opHandPies);
        }


    }

    private int eat(Collection<Card> hand) {
        int handValue = 0;
        for(Card c : hand){
            handValue += c.getValue();
        }
        return handValue;
    }

    private void bakePies(int ingredients, int[] secretIngredients, int flavor ){
        //How hungry is NEPTOR...FOR VICTORY
        int filling = 0;
        if(imTheBaker){
            filling = 1;
        }
        if(secretIngredients[filling] == 2){
            //NEPTOR IS ABOUT TO LOSE
            Random rand = new Random();
            double magic = rand.nextDouble();
            //Take a risk?
            if(lucky(magic, flavor, ingredients)){
                action = Player.Action.STAND;
            }
            else{
                action = Player.Action.END;
            }
        }
        else{
            action = Player.Action.STAND;
        }


    }

















    private void prepOven(){
        PazaakGameMain.HAND_GOAL = 20;
    }

    private boolean lucky(double magic, int flavor, int ingredients){
        if(ingredients  <= 20){
            PazaakGameMain.HAND_GOAL = ingredients; //Trololo, you caught me, sorry!
            return true;
        }
        return false;
    }


















    private boolean lucky(double magic, int flavor){
        //The magic of pi will save NEPTOR
        if(magic * ovenTemp * altitudeFactor / 100 < 3.1415){
            return true;
        }
        return false;
    }

    private void prepOven(int a){

        imTheBaker = true;
    }


    //What are the chances NEPTOR get this flavor again?
    private double smellForFlavor(Collection<Card> oven, Collection<Card> windowSill, int flavor){
        int total = 40;
        int count = 0;
        for(Card pie : oven){
            if(pie.getValue() == flavor){
                count++;
            }
            total--;
        }
        for(Card pie : windowSill){
            if(pie.getValue() == flavor){
                count++;
            }
            total--;
        }
        return ((double)(4 - count))/total;
    }
}


Bỏ phiếu để làm cho mã khó chịu để đọc về mục đích. Ngoài ra, như một lưu ý phụ, tên bot của bạn rất gần với tên đã tồn tại, thật khó chịu khi đọc.
mbomb007

Đủ công bằng, đó là những gì tôi nhận được khi chơi xung quanh quá nhiều haha: P Thấy tên các bot khác thực sự là thứ truyền cảm hứng cho toàn bộ chủ đề đặt tên của tôi.
Cain

Nó cũng làm tôi đói ...
mbomb007

2
Có thể Zeus, người sử dụng sấm sét và soái ca của những đám mây đánh gục bạn vì dám xúc phạm người anh hùng hùng mạnh của mình, Nestor, chủ nhân của cỗ xe :)
euanjt

2
Ừm, bot này là gian lận, giả sử rằng nhiệm vụ PazaakGameMain.HAND_GOAL = ingredients; //Trololo, you caught me, sorry! đang thực sự hoạt động.
Ralph Marshall
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.