Euchre bot (permainan kartu)


10

Gagasan tantangan ini sederhana: buat bot untuk memainkan permainan kartu Euchre.

Bagi Anda yang belum mengenal mereka, saya telah menulis aturan untuk Euchre di sini karena mereka berkaitan dengan tantangan ini.

Saya sarankan menggunakan python atau sesuatu yang serupa, tetapi satu-satunya batasan nyata adalah itu harus kompatibel dengan kode pengontrol

Memasukkan:

Bot euchre Anda akan mendapatkan berbagai jenis input tergantung pada fase permainan atau putaran saat ini. Secara umum, Anda akan mendapatkan fase permainan pada baris pertama diikuti oleh koma dan jumlah poin yang dimiliki tim Anda, dan kemudian data yang relevan pada baris berikut.

Secara kronologis, bot Anda akan mendapatkan input dalam urutan berikut:

Ordering Trump:
    js,ah,qc,ts,jc  // the cards in your hand
    2               // number of points your team has
    0               // number of tricks your team has taken
    ordering        // the phase of the game
    th              // the turned up card
    p,p             // each previous player’s decision

Naming Trump:
    js,ah,qc,ts,jc  // the cards in your hand
    2               // number of points your team has
    0               // number of tricks your team has taken
    naming          // the phase of the game
    p               // each previous player’s decision

Dealer Discarding:
    js,ah,qc,ts,jc  // the cards in your hand
    2               // number of points your team has
    0               // number of tricks your team has taken
    discard         // the phase of the game
    th              // the card you will pick up

Going alone:
    js,ah,qc,ts,jc  // the cards in your hand
    2               // number of points your team has
    0               // number of tricks your team has taken
    alone           // the phase of the game
    h               // the trump suit
    n,n             // each previous player’s decision

Your turn:
    js,ah,qc,ts,jc  // the cards in your hand
    2               // number of points your team has
    0               // number of tricks your team has taken
    turn            // the phase of the game
    h               // the trump suit
    td,8h,p         // each previous player’s card

Trick data:
                    // the cards in your hand (none, since this happens at the end of a trick)
    2               // number of points your team has
    1               // number of tricks your team has taken
    trick           // the phase of the game
    0               // the index of the following list that is your card
    js,tc,4d,js     // the cards played during the trick in the order they were played

Keluaran:

Bot euchre Anda akan memiliki output yang berbeda tergantung pada fase permainan atau ronde saat ini.

Ordering Trump:
    p   //for pass
    OR
    o   //for order up

Naming Trump:
    p           //for pass
    OR ANY OF
    c,s,h,d     //the suit you want to name

Going alone:
    n   // no
    OR
    y   // yes

Your turn:
    js  //the card you want to play

Mencetak:

Skor bot Anda adalah jumlah total permainan yang dimenangkannya.

Bot Anda akan bermain melawan setiap bot lainnya, dan bot itu akan selalu bermitra dengan salinannya sendiri.

Catatan:

Inilah templat sederhana di python2.7:

#!/usr/bin/python2.7
import sys

data = sys.stdin.readlines()

hand = data[0].strip().split(',')   # Hand as a list of strings
points = int(data[1])       # Number of points
tricks = int(data[2])       # Number of tricks

out = ''

if data[3] == 'ordering':
    card = data[4]              # The upturn card
    prev = data[5].strip().split(',')   # The previous player's decisions as a list
    # Ordering logic
    out =       # 'o' or 'p'
elif data[3] == 'naming':
    prev = data[4].strip().split(',')   # The previous player's decisions as a list
    # Naming logic
    out =       # 'p', 'h', 's', 'c', or 'd'
elif data[3] == 'discard':
    card = data[4]              # The card you'll take
    # Discarding logic
    out =       # The card you want to discard
elif data[3] == 'alone':
    trump = data[4]             # The trump suit
    prev = data[5].strip().split(',')   # The previous player's decisions as a list
    # Alone logic
    out =       # 'y' for yes, 'n' for no
elif data[3] == 'turn':
    trump = data[4]             # The trump suit
    prev = data[5].strip().split(',')
    # Turn logic
    out =       # The card you want to play
elif data[3] == 'trick':
    trump = data[5]
    cards = data[6].strip().split(',')
    my_card = cards[int(data[4])]
    # Data logic

print(out)
  1. Akan selalu ada 4 total tanggapan. Jika seseorang pergi sendiri, maka respons pasangannya akan "p" pada gilirannya.

  2. Saya mencoba untuk mengurangi jumlah input yang berlebihan, sehingga menjadi sangat jelas:

    2a. Posisi Anda relatif terhadap dealer / pemimpin dan kartu yang dimainkan pasangan Anda dapat ditentukan oleh jumlah output sebelumnya. Ada 1 pemain antara Anda dan pasangan. Di sana Misalnya, jika Anda mendapatkan "td, 8h, p" sebagai baris terakhir pada giliran Anda, Anda dapat melihat bahwa pasangan Anda memainkan 8 jam, dan tim lain memiliki pemain yang pergi sendiri.

  3. Jika Anda penasaran, kesepakatan dilakukan dengan cara tradisional (dalam dua putaran paket bolak-balik 2 dan 3 kartu) tetapi itu tidak benar-benar relevan dengan bot Anda, jadi ...

  4. Jika pemain kedua memutuskan untuk memesan di fase truf, fase itu akan berlanjut, tetapi output mereka akan diabaikan. Dengan kata lain, siapa pun yang memesan terlebih dahulu ada di tim Namers terlepas dari output lainnya.

  5. Berikut ini adalah default untuk berbagai fase game. Jika Anda tidak menghasilkan respons yang valid untuk putaran itu, maka respons Anda diubah menjadi apa di bawah ini.

    Ordering Trump: p

    Naming Trump: p

    Membuang: (kartu pertama di tangan Anda)

    Going Alone: ​​n

    Giliran Anda: (kartu legal pertama di tangan Anda)

  6. Inilah kode pengontrol untuk tujuan pengujian Anda.

    6a. Perhatikan bahwa Anda dapat memasukkan 2 atau 4 nama bot, jika Anda memberikannya 4 bot maka mereka akan bermitra secara acak, dan dengan 2 mereka bermitra dengan salinan diri mereka sendiri.

    6b. Anda memerlukan direktori 'bot' di direktori yang sama dengan kode controller, dan kode bot Anda harus ada di direktori bot.

  7. Bagi mereka yang ingin bot mereka mengingat kartu apa yang dimainkan, Anda diberikan kesempatan selama fase "trik", yang memberi tahu bot Anda kartu mana yang dimainkan. Anda dapat menulis ke file di direktori bot asalkan file tersebut tidak melebihi 1kb.

Papan angka:

Old Stager:  2
Marius:      1
Random 8020: 0

2
Saya akan merekomendasikan memasukkan sampel bot untuk mempermudah orang menulis bot mereka.
Nathan Merrill

3
Posting sebagai kiriman. Namun, masalah dengan bot acak itu adalah ia mengabaikan sebagian besar input yang Anda berikan. Orang-orang suka menyalin / menempelkan (kemudian memodifikasi) kode, jadi semakin komprehensif bot awal Anda, semakin banyak pengiriman (dan pengiriman yang lebih baik) yang akan Anda terima.
Nathan Merrill

1
Apakah saya berhak berasumsi bahwa kecuali bot adalah pemain terakhir dari belokan, ia tidak memiliki cara untuk mengetahui apa yang dimainkan pada belokan terakhir?
plannapus

1
@Leafar dengan baik jika ada cara untuk mengetahui apa yang dimainkan selama belokan saat ini, bot bisa menulisnya ke file, untuk melacak.
plannapus

1
@NotthatCharles Saya telah memperbarui aturan untuk secara eksplisit mengizinkan penulisan ke file
The Beanstalk

Jawaban:


2

Marius

Saya menulis bot itu di R. Saya melakukan beberapa tes dengan controller Anda dan mereka tampaknya berkomunikasi dengan benar.

#!/usr/bin/Rscript
options(warn=-1)
infile = file("stdin")
open(infile)
input = readLines(infile,5)
hand = strsplit(input[1],",")[[1]]
phase = input[4]
if(!phase%in%c("discard","naming")) input = c(input,readLines(infile,1))
other_o = c("a","k","q","j","t","9")
alone = "n"
ord = "p"
trumpify = function(color){
    tr_suit = switch(color,
            "c" = c("c","s",rep("c",5)),
            "s" = c("s","c",rep("s",5)),
            "h" = c("h","d",rep("h",5)),
            "d" = c("d","h",rep("d",5)))
    paste(c("j","j","a","k","q","t","9"),tr_suit,sep="")
    }

if(phase%in%c("ordering","alone")){
    flip = input[5]
    if(phase=="ordering") trump = trumpify(substr(flip,2,2))
    if(phase=="alone") trump = trumpify(flip)
    hand_value = sum((7:1)[trump%in%c(hand,flip)])
    if(hand_value>13) ord = "o"
    if(hand_value>18) alone = "y"
    if(phase=="alone") cat(alone)
    if(phase=="ordering") cat(ord)
    }

if(phase=="naming"){
    name = "p"
    colors = unique(substr(hand,2,2))
    col_values = sapply(colors,function(x)sum((7:1)[trumpify(x)%in%hand]))
    if(any(col_values>13)){name = colors[which.max(col_values)]}
    cat(name)
    }

if(phase=="discard"){
    flip = input[5]
    new_hand = c(hand,flip)
    trump = trumpify(substr(flip,2,2))
    discardables = new_hand[!new_hand%in%trump]
    if(length(discardables)){
        val = sapply(substr(discardables,1,1),function(x)(6:1)[other_o==x])
        d = discardables[which.min(val)]
    }else{d = tail(trump[trump%in%new_hand],1)}
    cat(d)
    }

if(phase=="turn"){
    trump = trumpify(input[5])
    fold = strsplit(gsub("[[:punct:]]","",input[6]),",")[[1]]
    if(length(fold)&!any(is.na(fold))){
        fold_c = substr(fold[1],2,2)
        f_suit = if(fold_c!=input[5]){paste(other_o,fold_c,sep="")}else{trump}
        l = length(f_suit)
        current = (l:1)[f_suit%in%fold]
        if(any(hand%in%f_suit)){
            playable = hand[hand%in%f_suit]
            val = sapply(playable,function(x)(l:1)[f_suit==x])
            if(all(max(val)>current)){
                play = playable[which.max(val)]
            }else{play = playable[which.min(val)]}
        }else if(any(hand%in%trump)){
            playable = hand[hand%in%trump]
            val = sapply(playable,function(x)(7:1)[trump==x])
            if(!any(fold%in%trump)){
                play = playable[which.min(val)]
            }else{
                trumped = fold[fold%in%trump]
                val_o = max((7:1)[trump%in%trumped])
                play = ifelse(any(val>val_o), playable[which.min(val[val>val_o])], playable[which.min(val)])
            }
        }else{
            val = sapply(substr(hand,1,1),function(x)(6:1)[other_o==x])
            play = hand[which.min(val)]
            }
    }else{
        col = c("c","s","h","d")
        non_tr = col[col!=input[5]]
        aces = paste("a",non_tr,sep="")
        if(any(hand%in%aces)){
            play = hand[hand%in%aces][1]
        }else if(any(hand%in%trump)){
            playable = hand[hand%in%trump]
            val = sapply(playable,function(x)(7:1)[trump==x])
            play = playable[which.max(val)]
        }else{
            val = sapply(substr(hand,1,1),function(x)(6:1)[other_o==x])
            play = hand[which.max(val)]
        }
    }
    cat(play)   
}

Saya mungkin akan memodifikasinya nanti karena saya tidak menerapkan logika "turn" ketika bot membela, tapi saya mempostingnya sekarang sehingga orang memiliki bot lain untuk diuji.

Untuk saat ini, itu hanya menerapkan strategi yang sangat mendasar seperti memimpin dengan kartu as, kartu truf atau kartu tinggi lainnya; mengikuti dengan kartu yang lebih tinggi bila memungkinkan atau memainkan kartu dengan nilai terendah jika tidak; memesan ketika tangan memiliki nilai tinggi dan memberi nama warna di mana tangan akan memiliki nilai tertinggi; pergi sendiri ketika tangan memiliki nilai yang sangat tinggi. "Nilai" dari masing-masing kartu dihitung dengan sangat sederhana: nilai kartu truf dimulai dari 7 untuk jack pertama dan berkurang di sepanjang kartu truf.


1

Stager Tua

Bot ini mengikuti beberapa aturan sederhana yang melayaninya dengan baik untuk waktu yang lama:

  • Menetapkan skor secara intuitif untuk setiap kartu
  • Pilih truf jika skor tangan cukup baik
  • Dalam kasus bermain tangan yang benar-benar bagus sendirian
  • Pilih kartu terbaik saat bermain pertama
  • Pilih kartu yang lebih baik daripada lawan jika mereka menang
  • Pilih kartu terburuk jika mitra menang atau jika menang tidak mungkin

Saya meningkatkan skor target dari 10 menjadi 100 untuk pengujian di controller. Hasilnya masih sangat acak, tetapi jauh lebih stabil dari sebelumnya.

#!/usr/bin/python2.7
from __future__ import print_function
import sys, re, math

base = 1.2
playThreshold = 27.0
aloneThreshold = 36.0
sameColor = { 'd' : 'h', 'h' : 'd', 's' : 'c', 'c' : 's' , '' : '', 'n' : 'n' }
cardValue = { 'p' : 0, '9' : 1, 't' : 2, 'j' : 3, 'q' : 4, 'k' : 5, 'a' : 6 }

class Card(object):
    def __init__(self, name, trump):
        self.name = name
        self.value = cardValue[name[0:1]]
        self.suit = name[1:2]
        self.trump = False
        self.updateScore(trump)
    def updateScore(self, trump):
        self.score = self.value
        if self.suit == trump:
            self.trump = True
            self.score += 6
        if self.value == 3:
            if self.suit == trump:
                self.score = 14
            if self.suit == sameColor[trump]:
                self.trump = True
                self.score = 13

class Cards(object):
    def __init__(self, cards, trump):
        self.list = []
        self.score = 0.0
        if cards:
            for c in cards.split(','):
                self.append(Card(c, trump))
    def append(self, card):
        self.list.append(card)
        self.score += math.pow(base, card.score)
    def updateScore(self, trump):
        self.score = 0.0
        for card in self.list:
            card.updateScore(trump)
            self.score += math.pow(base, card.score)
    def best(self):
        card = self.list[0]
        for i in self.list[1:]:
            if i.score > card.score:
                card = i
        return card
    def worst(self):
        card = self.list[0]
        for i in self.list[1:]:
            if i.score < card.score:
                card = i
        return card
    def better(self, ref):
        card = None
        for i in self.list:
            if i.score > ref.score and (card is None or i.score < card.score):
                card = i
        return card

def ordering(hand, card, decisions):
    if len(decisions) == 3:
        hand.append(card)
    return 'o' if hand.score > playThreshold else 'p'

def naming(hand):
    result = 'p'
    score = playThreshold
    for trump in ['d', 'h', 's', 'c']:
        hand.updateScore(trump)
        if hand.score > score:
            result = trump
            score = hand.score
    return result

def turn(hand, decisions):
    bestIndex = -1
    for i, d in enumerate(decisions.list):
        if d.suit:
            bestIndex = i
            break
    if bestIndex == -1:
        return hand.best()
    else:
        suit = decisions.list[bestIndex].suit
        for i in range(2, len(decisions.list)):
            if (decisions.list[i].suit == suit or decisions.list[i].trump) and decisions.list[i].score > decisions.list[bestIndex].score:
                bestIndex = i
        matching = Cards('', '')
        for card in hand.list:
            if card.suit == suit:
                matching.append(card)
        if not matching.list:
            if bestIndex == len(decisions.list) - 2:
                return hand.worst()
            for card in hand.list:
                if card.trump:
                    matching.append(card)
            if not matching.list:
                return hand.worst()
        if bestIndex == len(decisions.list) - 2:
            return matching.worst()
        card = matching.better(decisions.list[bestIndex])
        if card:
            return card
        return matching.worst()

output = ''
input = re.split('\n', re.sub(r'[^a-z0-9,\n]+', '', sys.stdin.read()))

if input[3] == 'ordering':
    output = ordering(Cards(input[0], input[4][1:2]), Card(input[4], input[4][1:2]), input[5].split(','))
elif input[3] == 'naming':
    output = naming(Cards(input[0], 'n'))
elif input[3] == 'discard':
    output = Cards(input[0], input[4][1:2]).worst().name
elif input[3] == 'alone':
    output = 'y' if Cards(input[0], input[4]).score > aloneThreshold else 'n'
elif input[3] == 'turn':
    output = turn(Cards(input[0], input[4]), Cards(input[5], input[4])).name

print(output)

0

Acak 8020

Bot acak sederhana, yang akan melewati 80% dari waktu. Batalkan komentar pada baris terakhir untuk melihat input dan output (dibersihkan).

#!/usr/bin/python2.7
from __future__ import print_function
import sys, re, random

output = ''
input = re.split('\n', re.sub(r'[^a-z0-9,\n]+', '', sys.stdin.read()))
hand = input[0].split(',')

if input[3] == 'ordering':
    output = random.choice(['p', 'p', 'p', 'p', 'o'])
elif input[3] == 'naming':
    output = random.choice(['p', 'p', 'p', 'p', random.choice(hand)[1:2]])
elif input[3] == 'discard':
    output = random.choice(hand)
elif input[3] == 'alone':
    output = random.choice(['n', 'n', 'n', 'n', 'y'])
elif input[3] == 'turn':
    output =  random.choice(hand)
    if input[5]:
        suited = filter(lambda x: input[5][1:2] in x, hand)
        if suited:
            output = random.choice(suited)

print(output)
#print(input, " --> ", output, file=sys.stderr)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.