ユーカーボット(カードゲーム)


10

この課題のアイデアは単純です。カードゲームユーカーをプレイするボットを作成します。

それらをまだ知らない皆さんのために、私はここでユーカーにこの挑戦に関係するルールを書き留めました

私はpythonまたは類似のものを使用することをお勧めしますが、唯一の実際の制限は、コントローラーコードと互換性がある必要があることです。

入力:

ユーカーボットは、ゲームまたはラウンドの現在のフェーズに応じて、さまざまな種類の入力を取得します。一般的に言えば、最初の行にゲームフェーズが表示され、その後にコンマとチームのポイント数が続き、その後に関連するデータが次の行に表示されます。

年代順に、ボットは次の順序で入力を受け取ります。

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

出力:

ユーカーボットは、ゲームまたはラウンドの現在のフェーズに応じて、異なる出力を生成します。

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

得点:

ボットのスコアは、ボットが勝ったゲームの総数です。

ボットは他のすべてのボットと対戦し、常に自分自身のコピーと提携します。

ノート:

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. 常に4つの合計回答があります。誰かが一人で行く場合、パートナーの応答は自分のターンで「p」になります。

  2. 私は余分な入力の量を削減しようとしたので、さらに明確にするために:

    2a。ディーラー/リーダーに対する相対的なあなたの位置とあなたのパートナーがプレイしたカードの両方は、以前のアウトプットの数によって決定できます。あなたとあなたのパートナーの間に1人のプレーヤーがいます。たとえば、ターンの最後の行として「td、8h、p」が表示された場合、パートナーが8時間プレーしていて、他のチームには単独でプレーするプレーヤーがいることがわかります。

  3. 興味があれば、取引は従来の方法で行われます(2ラウンドのパケットを2枚と3枚のカードに交互に入れます)が、ボットとはあまり関係がないので...

  4. 2番目のプレーヤーが切り札フェーズで注文することを決定した場合、そのフェーズは続行されますが、それらの出力はほとんど無視されます。つまり、他の出力に関係なく、最初に注文した人はすべてNamersチームに所属します。

  5. 以下は、さまざまなゲームフェーズのデフォルトです。そのラウンドの有効な応答を出力しない場合、応答は以下のように変更されます。

    トランプの注文:p

    トランプの命名:p

    破棄:(あなたの手札の最初のカード)

    一人で行く:n

    あなたの番:(あなたの手札の最初の合法カード)

  6. ここだ、あなたのテストの目的で、コントローラのコードは。

    6a。2つまたは4つのボット名を渡すことができることに注意してください。4つのボットを指定すると、ランダムにパートナーになり、2つのボットは自分のコピーとパートナーになります。

    6b。コントローラーコードと同じディレクトリに「bots」ディレクトリが必要であり、ボットコードがbotsディレクトリにある必要があります。

  7. どのカードがプレイされたかをボットに記憶させたい場合は、「トリック」フェーズ中に機会が与えられ、どのカードがプレイされたかをボットに知らせます。ボットディレクトリ内のファイルに書き込むことができるのは、そのファイルが1kbを超えない限りです。

スコアボード:

Old Stager:  2
Marius:      1
Random 8020: 0

2
ボットを簡単に作成できるように、サンプルボットを含めることをお勧めします。
Nathan Merrill、2015

3
投稿として投稿してください。ただし、そのランダムボットの問題は、提供する入力の大部分を無視することです。人々はコードをコピー/貼り付け(そして変更)するのが好きなので、最初のボットがより包括的であるほど、より多くのサブミッション(そしてより良いサブミッション)を受け取ります。
Nathan Merrill

1
ボットがターンの最後のプレイヤーでない限り、ボットが最後のターンで何がプレイされたかを知る方法がないと私は思いますか?
plannapus

1
@Sleafar現在のターン中に何がプレイされたかを知る方法があったら、ボットは追跡するためにそれをファイルに書き込むことができます。
plannapus

1
@NotthatCharlesファイルへの書き込みを明示的に許可するようにルールを更新しました
Beanstalk

回答:


2

マリウス

私はそのボットをRで記述しました。コントローラーでいくつかのテストを行いましたが、それらは正しく通信しているようです。

#!/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)   
}

ボットが防御しているときの「ターン」ロジックを実装しなかったので、後で変更する可能性がありますが、他のボットがテストできるように、ここで投稿します。

現時点では、エース、トランプ、またはその他のハイカードでリードするなど、非常に基本的な戦略のみを実装しています。可能な場合はより高いカードをフォローし、そうでない場合は最も価値の低いカードをプレイする 手の価値が高いときに並べ替え、その手の価値が最も高かった色に名前を付けます。手が非常に高い価値があるときに一人で行く。各カードの「値」は非常に単純に計算されます。切り札の値は、最初のジャックの7から始まり、切り札に沿って減少します。


1

古いステージャー

このボットは、彼に長い間役立ったいくつかの単純なルールに従います。

  • 各カードに直感的にスコアを割り当てる
  • ハンドスコアが十分であればトランプを選択してください
  • 一人で本当に良いハンドプレーの場合
  • 最初にプレイするときに最高のカードを選択してください
  • 相手が勝っている場合は、相手よりも良いカードを選ぶ
  • パートナーが勝っている場合、または勝つことができない場合は、最悪のカードを選択します

コントローラーでテストするために、ターゲットスコアを10から100に増やしました。結果はまだ非常にランダムですが、以前よりもはるかに安定しています。

#!/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

ランダム8020

時間の80%を通過する単純なランダムボット。最後の行のコメントを解除して、(クリアされた)入力と出力を確認します。

#!/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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.