Simple Pazaak (เกมการ์ด Star Wars จาก Knights of the Old Republic)


11

Pazaakเป็นเกมไพ่จากจักรวาล Star Wars มันคล้ายกับ BlackJack โดยมีผู้เล่นสองคนต่อสู้กันเพื่อพยายามเข้าถึงจำนวนยี่สิบโดยไม่ผ่าน ผู้เล่นแต่ละคนมี "เด็คฝั่ง" ของไพ่สี่ใบของตนเองที่พวกเขาสามารถใช้เพื่อปรับเปลี่ยนคะแนนของพวกเขา

ลีดเดอร์บอร์ด

ตั้งแต่ 6/17/2015 @ 16:40 EDT

แก้ไข: Neptor ถูกตัดสิทธิ์เนื่องจากการโกง คะแนนจะได้รับการแก้ไขโดยเร็วที่สุด ...

  1. NEPTR: ~ 424,000
  2. The Cincinnati Kid: ~ 422,000
  3. Nestor: ~ 408,000
  4. มหาอำนาจออสติน: ~ 405,000
  5. Bastila: ~ 248,000
  6. ใบ้ผู้เล่นที่ระมัดระวัง: ~ 107,000
  7. ผู้เล่นใบ้ตัวหนา: ~ 87,000

รอบตัดเชือกจำลอง Pazaak

จะได้รับการอัปเดตโดยเร็วที่สุด

Round One - Nestor vs Bastila และ Austin Powers กับ The Cincinnati Kid

ผลการแข่งขันรอบที่ 1

Round Two - Nestor vs Austin Powers & The Cincinnati Kid กับ Bastila

ผลการแข่งขันรอบที่ 2

กลศาสตร์

เกมเพลย์ทำเสร็จแล้ว ผู้เล่นคนหนึ่งแจกไพ่จากเด็คหลัก (เฮ้าส์) สำรับไพ่ในบ้านมีสี่สิบใบ: สี่ใบต่อ 10 ใบหลังจากแจกไพ่พวกเขาสามารถเลือกที่จะจบเทิร์นและรับไพ่ใบใหม่ในเทิร์นถัดไปยืนตามมูลค่าปัจจุบันหรือเล่นการ์ดจากเด็คข้างและ ยืนที่ค่าใหม่ หลังจากผู้เล่นคนหนึ่งตัดสินใจสิ่งที่พวกเขาต้องการจะทำผู้เล่นสองคนจะทำซ้ำกระบวนการ

เมื่อผู้เล่นทั้งสองได้ไปมือจะถูกประเมิน หากผู้เล่นวางระเบิด (เกินยี่สิบ) ผู้เล่นคนอื่นจะชนะหากว่าพวกเขายังไม่ระเบิด หากผู้เล่นเลือกที่จะยืนและผู้เล่นอื่นมีมูลค่ามือที่สูงกว่าผู้เล่นอื่นจะชนะ หากผู้เล่นทั้งสองเลือกที่จะยืนผู้เล่นที่มีมูลค่ามือที่สูงกว่าจะชนะ ในกรณีที่เสมอกันผู้เล่นจะไม่ชนะ

หากไม่มีเงื่อนไขในการชนะการเล่นจะทำซ้ำ หากผู้เล่นเลือกที่จะจบเทิร์นของพวกเขาพวกเขาจะได้รับการ์ดใหม่และสามารถสร้างทางเลือกใหม่ หากพวกเขาเลือกที่จะยืนหรือถ้าพวกเขาเล่นไพ่จากดาดฟ้าด้านข้างพวกเขาจะไม่ได้รับไพ่ใหม่และไม่สามารถเลือกการกระทำใหม่ได้

การเล่นจะดำเนินต่อไปเช่นนี้จนกระทั่งผู้เล่นคนหนึ่งชนะเกม เกมที่เล่นในชุดที่ดีที่สุดสามในห้า

ทำไมต้อง "Simple" Pazaak

ในจักรวาลสตาร์วอร์ส Pazaak เกี่ยวข้องกับการพนัน ในขณะที่การรวมระบบดังกล่าวจะเพิ่มความมีชีวิตชีวาให้กับเกมมากขึ้น แต่มันค่อนข้างซับซ้อนสำหรับการแข่งขัน KoTH เป็นครั้งแรก

"ของจริง" ดาดฟ้าด้าน Pazaak ก็มีให้โดยผู้เล่นเองและอาจรวมถึงตัวเลือกการ์ดที่แตกต่างกันมากมายเช่นบัตรเชิงลบบัตรบวกหรือลบบัตรพลิกการ์ดไพ่คู่และบัตร tiebreaker สิ่งเหล่านี้จะทำให้เกมน่าสนใจยิ่งขึ้น แต่จะต้องมีอินเทอร์เฟซการพนันในสถานที่และจะต้องการคู่แข่งออกไปอีกมาก ในเกม Simple Pazaak นี้ผู้เล่นแต่ละคนจะได้รับไพ่เด็คข้างเดียวกัน: สำเนาสองชุดของหนึ่งถึงห้าจากที่สี่ถูกสุ่มเลือก

ขึ้นอยู่กับความสำเร็จของเกมนี้ฉันอาจใช้ความพยายามในการพัฒนาเวอร์ชั่นขั้นสูงซึ่งการเล่นการพนันและการตกแต่งด้านข้างแบบกำหนดเองเป็นไปได้

ผู้เล่น

ผู้เล่นของเกมนี้จะเป็นบอทที่ออกแบบโดยคุณ บอทแต่ละตัวต้องขยายคลาสผู้เล่นนำเข้าแพ็คเกจกลไกและอยู่ในแพ็คเกจผู้เล่นดังนี้:

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;
    }
}

ในแต่ละรอบผู้ควบคุมจะเรียกใช้เมธอด getResponse สำหรับบอทของคุณเว้นแต่ว่าบอทของคุณก่อนหน้านี้ระบุว่าต้องการให้ยืน เมธอด getResponse สามารถตั้งค่าคุณสมบัติสองอย่าง: การกระทำและการ์ดเพื่อเล่น การดำเนินการสามารถเป็นหนึ่งในสิ่งต่อไปนี้:

  • END: จบเทิร์นและดึงการ์ดใบใหม่เทิร์นถัดไป
  • STAND: พักที่ค่ามือปัจจุบัน จะไม่จั่วไพ่
  • PLAY: เล่นการ์ดจากเด็คข้างแล้วยืน

เห็นได้ชัดว่าการ์ดที่เล่นมีความสำคัญเท่านั้นหากคุณตั้งค่าการกระทำเป็นเล่น ใช้วัตถุการ์ด หากวัตถุการ์ดที่คุณส่งไปยังวัตถุนั้นไม่มีอยู่ในเด็คข้างของคุณบอทของคุณจะยืนแทน

พารามิเตอร์ที่บอทของคุณได้รับคือ:

  • อาร์เรย์ที่มีชัยชนะของผู้เล่นแต่ละคน ชนะ [0] คือผู้เล่น 1 คนชนะ1คือผู้เล่น 2 (int [])
  • บ็อตของคุณเป็นผู้เล่นคนหนึ่งหรือไม่ (บูลีน)
  • คอลเล็กชันของการ์ดที่คุณได้รับแจกจนถึงปัจจุบัน (คอลเลกชัน)
  • คอลเลกชันของการ์ดฝ่ายตรงข้ามของคุณได้รับการจัดการป่านนี้ (ชุด)
  • คอลเลกชันของการ์ดในเด็คของคุณ
  • จำนวนไพ่ที่เหลือในเด็คฝั่งคู่ต่อสู้ของคุณ (int)
  • การกระทำที่ฝ่ายตรงข้ามทำล่าสุด (การกระทำ) [หมายเหตุ: นี่จะเป็น END หรือ STAND, ไม่เคยเล่น]
  • ฝ่ายตรงข้ามของคุณเล่นไพ่หรือไม่ (บูลีน)

กฎ ธ ปท

บอทของคุณสามารถใช้ข้อมูลที่ได้รับจากวิธีการ getResponse เท่านั้น พวกเขาไม่ควรพยายามโต้ตอบกับชั้นเรียนอื่น ๆ พวกเขาอาจเขียนเป็นไฟล์เดียวเพื่อเก็บข้อมูลระหว่างรอบ พวกเขาอาจมีวิธีการที่กำหนดเองคุณสมบัติ ฯลฯ ตามที่ต้องการ พวกเขาควรรันในเวลาที่เหมาะสม (หากการรันโปรแกรมไม่ได้เกิดขึ้นทันทีฉันจะสังเกตเห็นว่ามีอะไรผิดปกติ)

หากคุณพบการโกงในโค้ดคุณจะได้รับรางวัล "เปิดตัวเอง" ถ้าฉันสังเกตเห็นการหาประโยชน์ก่อนฉันจะแก้ไขและคุณจะไม่ได้รับรางวัล

สาธิตการใช้งาน

คอนโทรลเลอร์ไม่จำเป็นต้องเขียนบอทเนื่องจากทุกอย่างได้อธิบายไว้แล้วในโพสต์นี้ อย่างไรก็ตามหากคุณต้องการทดสอบสามารถพบได้ที่นี่: https://github.com/PhantomJedi759/simplepazaak รวม สองบอทพื้นฐาน ไม่ควรสู้กับคู่แข่งที่ "ฉลาด" ได้ดีเพราะพวกเขาเลือกได้เฉพาะระหว่าง END และ STAND นี่คือตัวอย่างการรันของสิ่งที่พวกเขาทำ:

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!

เนื่องจากบอทเหล่านี้พึ่งพาโชคของการเสมอสัดส่วนการชนะที่ขาดทุนอาจแตกต่างกันอย่างมาก มันจะน่าสนใจเพื่อดูว่าทักษะสามารถต่อสู้กับโชคของเกมได้อย่างไร

นี่ควรเป็นทุกสิ่งที่คุณต้องการ! ไปสร้างบอทกัน!

ชี้แจงกฎ

สำรับหลักคือไพ่สี่สิบใบ: 4x1-10 มันถูกเปลี่ยนใหม่ในตอนเริ่มต้นของแต่ละมือ

เด็คฝั่งผู้เล่นมีไพ่สี่ใบเลือกสุ่มจาก 2x1-5 ดาดฟ้าด้านข้างยังคงอยู่ระหว่างมือ

มือจะเล่นในเกมที่ดีที่สุดสามในห้า บอตจะได้คะแนนตามจำนวนเกมทั้งหมดที่ชนะและจากจำนวนทั้งหมดของมือ

การจับคู่ถูกจัดการเพื่อให้ผู้เล่นแต่ละคนจะต้องเล่น 100,000 เกมกับผู้เล่นคนอื่น ๆ

ใน Pazaak Cup รอบการกำจัดสไตล์จะแคบลงว่าใครเป็นบอท Pazaak ที่ดีที่สุดจริงๆ การจับคู่บอตแต่ละคู่จะเล่นให้ดีที่สุดถึงสี่ชุดจากทั้งหมดเจ็ดเกมจำนวน 100,000 เกม ผู้ชนะสี่คนจะเลื่อนขึ้นบันไดไปยังคู่ต่อสู้คนถัดไปและผู้แพ้จะอยู่ในการต่อสู้เพื่อการจัดอันดับต่อเนื่อง รูปแบบการเล่นเกมนี้มีความยุติธรรมที่สุดเนื่องจากบอทไม่สามารถ "ชนะฟาร์ม" คู่ต่อสู้บางรายเพื่อชดเชยการขาดความสามารถกับผู้อื่น Pazaak Cup จะจัดขึ้นในวันศุกร์ที่ 3 กรกฎาคมหากมีบอทที่ส่งอย่างน้อยแปด ผู้ชนะจะได้รับสถานะคำตอบที่ถูกต้องและโบนัสเริ่มต้นใน Advanced Pazaak ซึ่งหวังว่าจะพร้อมในเวลาเดียวกันกับที่ Pazaak Cup จัดขึ้น


1
ความพยายามที่จะเข้าถึง repo ทำให้ฉันได้รับคำเตือนเกี่ยวกับความปลอดภัยใน Chrome อย่างน่าเศร้า ดูเหมือนว่าจะเป็นความท้าทายที่สนุกมากที่ฉันชอบป้อน แต่ฉันต้องการคำชี้แจงแทนเอกสาร ดาดฟ้าของบ้านเริ่มต้นด้วยไพ่ 40 ใบเหมือนกันในตอนเริ่มต้นของแต่ละรอบใช่มั้ย เด็คฝั่งไพ่ 4 ใบของเราสามารถเป็นการ์ดใดก็ได้ 1-10 และไม่ส่งผลต่อเด็คเฮ้าส์ มือทั้งสองมองเห็นได้ผ่าน getResponse ไหม? เราจะได้คะแนนจากจำนวนมือที่ชนะหรือมีรอบที่ประกอบด้วยรูปแบบที่ดีที่สุด 5 รูปแบบหรือไม่? โดยพื้นฐานแล้วทำไม # ของผู้ชนะถึงได้รับใน getResponse
DoctorHeckle

เด็คจะได้รับการรีเซ็ตเมื่อใด หลังจากทุกรอบหรือเพียงแค่กับฝ่ายตรงข้ามทุกคน?
euanjt

1
มันควรจะเป็นชัยชนะ [1] สำหรับผู้เล่นที่ชนะ 2 ไม่ใช่ชนะ [2] เนื่องจากชัยชนะเป็นเพียงความยาวของอาร์เรย์ 2
euanjt

@DoctorHeckle ขอโทษเกี่ยวกับ repo; เครือข่ายปัจจุบันของฉันบล็อก GitHub แต่ฉันจะพยายามทำให้มันอยู่ที่นั่นโดยเร็วที่สุด เด็คจะถูกรีเซ็ตทุกเกม สำรับด้านข้างถือไพ่สี่ใบจำนวน 2x1-5 เมื่อการแข่งขันเริ่มต้นขึ้นจริงคุณจะได้คะแนนจาก tourneys ที่ดีที่สุดจากห้ารายการ จำนวนชนะจะถูกส่งผ่านไปยังวิธีการ getResponse ในกรณีที่บอทของคุณต้องการเปลี่ยนสไตล์การเล่นขึ้นอยู่กับว่าชนะหรือแพ้ Tourney หรือไม่
Michael Brandon Morris

1
ฉันไม่ทราบว่า StackOverflow แจ้งเตือนคุณเมื่อคำตอบถูกแก้ไข แต่ฉันมี The Cincinnati Kid เวอร์ชันอัปเดตที่โพสต์ทันที
Ralph Marshall

คำตอบ:


5

The Cincinnati Kid

พยายามทำให้แน่ใจว่าเราจั่วการ์ดอีกใบถ้าเรารู้ว่าเราแพ้มิฉะนั้นให้ดูที่เด็คฝั่งและคะแนนโดยรวมเพื่อตัดสินใจว่าจะทำอย่างไร

อัปเดตเพื่อให้ทำงานได้ดีขึ้นในการจัดการสถานการณ์ที่คู่ต่อสู้เล่นเสร็จแล้ว ในการทดสอบของฉันตอนนี้ดูเหมือนว่าจะเป็นผู้สมัครที่ดีที่สุดอีกครั้งอย่างน้อยตอนนี้

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;
    }
}

ขอแสดงความยินดี! คุณเป็นผู้นำ
Michael Brandon Morris

ด้วยการปรับเปลี่ยนเพื่อให้ระบบการให้คะแนนมีความยุติธรรมมากขึ้นตอนนี้คุณจะเชื่อมโยงกับ Austin Powers ก่อน
Michael Brandon Morris

4

มหาอำนาจออสติน

อย่างที่คุณคิดว่า Austin Powers ชอบที่จะมีชีวิตที่เป็นอันตราย ถ้าไม่มีใครถูกจับหรือเขาสามารถรับประกันชัยชนะเขาจะตีถ้าเขาอยู่ข้างหลังหรือมีโอกาสที่ดีกว่า 20% ที่จะไม่ถูกจับ

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;
    }
}

ขอแสดงความยินดี! คุณได้เป็นผู้นำจาก CincinnatiKid
Michael Brandon Morris

ด้วยการดัดแปลงเพื่อให้ระบบการให้คะแนนมีความยุติธรรมมากขึ้นตอนนี้คุณจะถูกผูกไว้กับ The Cincinnati Kid ก่อน
Michael Brandon Morris

2

Bastila

Bastila เล่นอย่างอนุรักษ์นิยม สำหรับเธอแล้ว 17 คนนั้นดีพอ ๆ กับ 20 และจะดีกว่าถ้าจะยืนให้สั้นกว่าระเบิด

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 ปัจจุบันมีประสิทธิภาพดีกว่าทั้ง Dumb Bold Player และ Dumb Cautious Player (บอตสาธิต) เยี่ยมมาก! แก้ไข: จากสิบวิ่ง Bastila ชนะแปดแพ้ให้กับ Dumb Cautious Player หนึ่งครั้งและผูกกับ Dumb Cautious Player หนึ่งครั้ง
Michael Brandon Morris

อัปเดต: ด้วยระบบการให้คะแนนใหม่ (ชนะโดยการนับจำนวนทัวร์นาเม้นท์ที่มีการเล่น 1,000 คู่กับผู้เล่นแต่ละคู่) บาสทิลาเป็นผู้นำโดยมี 1705/3000 ทั้งหมด (1705/2000 ทัวร์นาเมนท์ที่เล่น) ถัดไปคือผู้เล่นใบ้ที่มีผู้เล่น 729 คนและในที่สุดก็เป็นผู้เล่นใบ้ตัวหนาที่มี 566 คน
Michael Brandon Morris

ฮ่าฮ่าดีฉันหวังว่าอย่างน้อยเต้นบอทสาธิต: P
Cain

2

เนสเตอร์

เนสเตอร์รักที่จะได้รับ 20 โดยใช้เด็คของเขา แต่เมื่อล้มเหลวเขาจะคำนวณผลตอบแทนที่คาดหวังของเขาโดยเลือกขาตั้งหรือจบสมมติว่าฝ่ายตรงข้ามมีเหตุผล

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;
    }
}

ขอแสดงความยินดี! คุณจับผ่านความสัมพันธ์ระหว่าง Austin Powers และ The Cincinnati Kid
Michael Brandon Morris

ข้อยกเว้นในเธรด "main" java.lang.ArrayIndexOutOfBoundsException: -2 ที่ Players.Nestor.sumfromToEnd (Nestor.java:210) ที่ Players.Nestor.getResponse (Nestor.java:105) ที่ Mechanics.PazaakGameMain.playGame (PazaakGGameMain : 112) ที่ Mechanics.PazaakGameMain.main (PazaakGameMain.java:40)
Michael Brandon Morris

คุณจะช่วยฉันดูด้วยไหม ดูเหมือนว่าจะเป็นบอตเฉพาะเพราะมันเป็นเพียงจุดเริ่มต้นในการเล่น Neptor และ T3M4 (บอทที่ยังไม่เผยแพร่บน github)
Michael Brandon Morris

จากสิ่งที่ฉันสามารถบอกได้มันเป็นต้นเหตุถ้าคู่ต่อสู้ของคุณถูกจับ แต่ด้วยเหตุผลบางอย่างที่พวกเขาไม่ยืน ฉันกำลังวางโปรแกรมฟิกซ์ชั่วคราวในบอทของคุณ แต่จะแก้ไขคอนโทรลเลอร์ในภายหลังเพื่อบ็อต STAND ที่หยุดทำงานโดยอัตโนมัติ
Michael Brandon Morris

ฉันได้เพิ่มการตรวจสอบเมื่อศัตรูถูกจับขอบคุณ
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 สร้างแบบจำลอง 100 รายการโดยมีรายการไพ่ที่สับแล้วและเลือกตัวเลือกที่ดีที่สุดตามแบบจำลองเหล่านี้


ฉันจะขอบคุณถ้าคุณสามารถลดจำนวนการจำลอง ใช้เวลาในการดำเนินการกับฝ่ายตรงข้ามเพียงหนึ่งนาทีและต่อบ็อตอื่นทั้งหมดทำให้เวลารันของเรานานกว่า 7 นาทีซึ่งตรงข้ามกับ 30 วินาทีกับบอทอื่น
Michael Brandon Morris

เพียงแค่เปลี่ยนค่าคงที่ NUMBEROFSIMS จนกว่ามันจะใช้เวลาพอสมควรบนคอมพิวเตอร์ของฉันมันจัดการ 100 ซิมได้อย่างรวดเร็วซึ่งเป็นสาเหตุที่ฉันเลือกค่านั้น แต่อย่าลังเลที่จะเปลี่ยน :)
euanjt

มันอาจเร็วกว่าบนเดสก์ท็อปของฉัน (i7-3770K) แต่แล็ปท็อปของฉัน (i5-4300U) (ซึ่งฉันติดอยู่กับที่เป็นเวลาหนึ่งสัปดาห์) นั้นช้ากว่า ฉันจะเอา Glaucus กลับมาเมื่อฉันกลับไปที่เดสก์ท็อปของฉัน
Michael Brandon Morris

ฉันจะพยายามเร่งความเร็วในวันพรุ่งนี้และเรียกใช้ซิมส์ตามระยะเวลาที่กำหนดแทนที่จะเป็นซิมส์ที่กำหนดจำนวนหนึ่ง - นานแค่ไหนที่ยอมรับได้ต่อเทิร์น?
euanjt

แทนที่จะใช้การจำลองสถานการณ์ทำไมไม่ประมาณความน่าจะเป็นโดยตรงกับการแจกแจง hypergeometric
InactionPotential

1

HK-47

ดูเถิด! บอทของการออกแบบของฉันเอง HK-47 พยายามฆ่าถุงเนื้อทั้งหมดที่เขาสามารถทำได้แม้ว่าเขาจะมีความสุขเล็กน้อยกับไพ่สำรับด้านข้างของเขา

ถ้อยแถลง: แน่นอนฉันกระตือรือร้นที่จะมีส่วนร่วมในความรุนแรงที่ไม่บริสุทธิ์ ตามคำสั่งของคุณแน่นอนอาจารย์ - HK-47

จนถึงตอนนี้เขาสามารถเอาชนะทุกคนได้ แต่ The Cincinnati 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

(หุ่นยนต์ขว้างปาไม่สิ้นสุด)

Neptor ขออภัย Neptor ถูกโกง Neptor กำลังจะมาทำความสะอาดเขาแค่อยากสนุกก่อน :(

 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;
    }
}


ลงคะแนนในการสร้างรหัสที่น่ารำคาญในการอ่านตามวัตถุประสงค์ นอกจากนี้เมื่อสังเกตด้านข้างชื่อบ็อตของคุณนั้นใกล้เคียงกับชื่อที่มีอยู่แล้วซึ่งน่ารำคาญที่จะอ่านเช่นกัน
mbomb007

ก็พอแล้วนั่นคือสิ่งที่ฉันได้รับจากการเล่นรอบ ๆ ฮ่าฮ่า ๆ มากเกินไป: P การเห็นชื่อบอทอื่น ๆ นั้นเป็นสิ่งที่สร้างแรงบันดาลใจให้กับธีมการตั้งชื่อทั้งหมดของฉัน
Cain

มันทำให้ฉันหิวด้วย ...
mbomb007

2
May Zeus ผู้ถูกฟ้าผ่าและเจ้าหน้าที่รักษาความปลอดภัยของเมฆโจมตีคุณเพื่อกล้าที่จะดูถูกวีรบุรุษผู้ยิ่งใหญ่ของเขา Nestor, หัวหน้ารถม้า :)
euanjt

2
อืม, บอทนี้กำลังโกง, โดยสมมติว่าการมอบหมายPazaakGameMain.HAND_GOAL = ingredients; //Trololo, you caught me, sorry! นั้นใช้งานได้จริง
Ralph Marshall
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.