KOTH - RPS yang dimuat

12

Kontes dibuka secara permanen - Diperbarui 10 Agustus 2017

Meskipun pada 5 Juni 2017 saya menyatakan pemenang (yang akan disimpan sebagai jawaban terbaik) saya akan menemukan bot baru dan memperbarui hasilnya.

Hasil 5 Juni

Selamat pengguna1502040

Karena tidak ada ikatan, saya hanya menunjukkan% pertandingan yang dimenangkan.

Statistician2- 95,7%
Fitter- 89,1%
Nash- 83,9%
Weigher- 79,9%
ExpectedBayes- 76,4%
AntiRepeater- 72,1%
Yggdrasil- 65,0%
AntiGreedy- 64,1%
Reactor- 59,9%
NotHungry- 57,3%
NashBot- 55,1%
Blodsocer- 48,6%
BestOfBothWorlds- 48,4%
GoodWinning- 43,9%
Rockstar- 40,5%
ArtsyChild- 40,4%
Assassin- 38,1 %
WeightedRandom- 37,7%
Ensemble- 37,4%
UseOpponents- 36,4%
GreedyPsychologist- 36,3%
TheMessenger- 33,9%
Copycat- 31,4%
Greedy- 28,3%
SomewhatHungry- 27,6%
AntiAntiGreedy- 21,0%
Cycler- 20,3%
Swap- 19,8%
RandomBot- 19,8% - 16,2%

Saya membuat Google Sheet dengan kisi hasil masing-masing pasangan: https://docs.google.com/spreadsheets/d/1KrMvcvWMkK-h1Ee50w0gWLh_L6rCFOgLhTN_QlEXHyk/edit?usp=sharing


Berkat Dilema Petri, saya menemukan diri saya mampu menangani Raja Bukit ini.

Permainan

Permainan ini sederhana "Rock-Paper-Scissors" dengan twist: Poin yang diperoleh dengan setiap peningkatan kemenangan selama pertandingan (R, P atau S Anda dimuat).

  • Kertas memenangkan Rock
  • Gunting memenangkan Kertas
  • Rock menang Gunting

Pemenang mendapat poin sebanyak bebannya pada permainannya.

Yang kalah bertambah dengan 1 beban pada permainannya.

Dalam kasus seri, masing-masing pemain menambah beban pada permainannya sebesar 0,5.

Setelah 100 drama, yang memiliki poin lebih banyak adalah pemenangnya.

misalnya: P1 memiliki banyak [10,11,12] (Rock, Paper, Gunting) dan P2 [7,8,9]. P1 memainkan R, P2 memainkan P. P2 menang dan mendapat 8 poin. Beban P1 menjadi [11,11,12], beban P2 tetap sama.

Spesifikasi tantangan

Program Anda harus ditulis dengan Python (maaf, saya tidak tahu bagaimana cara mengatasinya). Anda harus membuat fungsi yang mengambil masing-masing variabel ini sebagai argumen pada setiap eksekusi:

my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history

points - Poin saat ini (milik Anda dan lawan Anda)

loaded- Array dengan banyak (agar RPS) (milik Anda dan opp Anda)

history- String dengan semua permainan, karakter terakhir adalah permainan terakhir (milik Anda dan lawan Anda)

Anda harus kembali "R", "P"atau "S". Jika Anda akan mengembalikan sesuatu yang berbeda, itu akan menjadi kekalahan otomatis dari pertandingan.

Aturan

Anda tidak dapat mengubah fungsi bawaan.

Pengujian

Saya akan terus memperbarui Git dengan kode dan semua bot yang memenuhi: https://github.com/Masclins/LoadedRPS

Menilai

Pemenang akan ditentukan dengan memilih orang dengan pertandingan yang paling menang setelah 1000 round-robin penuh. Ikatan akan dipatahkan oleh pertandingan yang diikat. 1000 pertandingan dimainkan lebih dari satu karena saya mengharapkan banyak keacakan, dan dengan cara itu keacakan akan kurang relevan.

Anda dapat mengirim hingga 5 bot.

Kontes berakhir pada Juli 4 Jun (yang akan menjadi hari terakhir saya akan menerima jawaban apa pun), dan pada Juli 5 Jun Aku akan posting stadings akhir (mungkin mencoba untuk memposting advancemnt sebelumnya).


Karena ini adalah KOTH pertamaku, aku 100% terbuka untuk mengubah apa pun untuk peningkatan, seperti jumlah pertandingan yang dimainkan melawan setiap bot.

Diedit ke 1000 pertandingan, karena saya melihat benar-benar ada keacakan yang terlibat.

Masclins
sumber
dengan beberapa bot acak, Anda benar-benar ingin membuat beberapa game dari beberapa putaran
Destructible Lemon
@DestructibleLemon Saya berpikir untuk membuat setiap bot bermain tiga kali melawan satu sama lain bot daripada sekali. Melihatmu berpikir sama, aku akan melakukannya.
Masclins
1
(benar-benar Anda membutuhkan jumlah yang cukup besar, karena beberapa kemungkinan benar-benar memperpanjang lebih dari beberapa pertandingan. lihat bot saya, di mana bot itu dapat dihancurkan, tetapi kemungkinan tidak akan dengan jumlah pertandingan yang adil)
Destructible Lemon
1
Saya senang pertanyaan saya membantu Anda menjalankan ini, @AlbertMasclans!
Gryphon
2
@AlbertMasclans Bisakah Anda memposting naskah lengkap (termasuk runcodedan bots)?
CalculatorFeline

Jawaban:

8

Ahli statistik (tidak lagi bermain)

import random
import collections

R, P, S = moves = range(3)
move_idx = {"R": R, "P": P, "S": S}
name = "RPS"
beat = (P, S, R)
beaten = (S, R, P)

def react(_0, _1, _2, _3, _4, opp_history):
    if not opp_history:
        return random.randrange(0, 3)
    return beat[opp_history[-1]]

def anti_react(_0, _1, _2, _3, _4, opp_history):
    if not opp_history:
        return random.randrange(0, 3)
    return beaten[opp_history[-1]]

def random_max(scores):
    scores = [s + random.normalvariate(0, 1) for s in scores]
    return scores.index(max(scores))

def greedy_margin(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    scores = [my_loaded[move] - opp_loaded[beat[move]] for move in moves]
    return random_max(scores)

def anti_greedy(my_points, opp_pints, my_loaded, opp_loaded, my_history, opp_history):
    scores = [-my_loaded[move] for move in moves]
    return random_max(scores)

def recent_stats(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    opp_history = opp_history[-10:-1]
    counts = collections.Counter(opp_history)
    scores = [(counts[beaten[move]] + 1) * my_loaded[move] - 
              (counts[beat[move]] + 1) * opp_loaded[move] for move in moves]
    return random_max(scores)

def statistician(_0, _1, _2, _3, my_history, opp_history):
    m1 = []
    o1 = []
    my_loaded = [0] * 3
    opp_loaded = [0] * 3
    my_points = 0
    opp_points = 0
    strategies = [react, anti_react, greedy_margin, anti_greedy, recent_stats]
    strategy_scores = [0 for _ in strategies]
    for i, (mx, ox) in enumerate(zip(my_history, opp_history)):
        mx = move_idx[mx]
        ox = move_idx[ox]
        for j, strategy in enumerate(strategies):
            strategy_scores[j] *= 0.98
            move = strategy(my_points, opp_points, my_loaded, opp_loaded, m1, o1)
            if move == beat[ox]:
                strategy_scores[j] += my_loaded[move]
            elif move == beaten[ox]:
                strategy_scores[j] -= opp_loaded[ox]
        m1.append(mx)
        o1.append(ox)
        if mx == beat[ox]:
            opp_loaded[ox] += 1
            my_points += my_loaded[mx]
        elif mx == beaten[ox]:
            my_loaded[mx] += 1
            opp_points += opp_loaded[ox]
        else:
            my_loaded[mx] += 0.5
            opp_loaded[ox] += 0.5
    strategy = strategies[random_max(strategy_scores)]
    return name[strategy(my_points, opp_points, my_loaded, opp_loaded, m1, o1)]

Beralih di antara beberapa strategi sederhana berdasarkan kinerja masa lalu yang diharapkan

Ahli Statistik 2

import random
import collections
import numpy as np

R, P, S = moves = range(3)
move_idx = {"R": R, "P": P, "S": S}
names = "RPS"
beat = (P, S, R)
beaten = (S, R, P)

def react(my_loaded, opp_loaded, my_history, opp_history):
    if not opp_history:
        return random.randrange(0, 3)
    counts = [0, 0, 0]
    counts[beat[opp_history[-1]]] += 1
    return counts

def random_max(scores):
    scores = [s + random.normalvariate(0, 1) for s in scores]
    return scores.index(max(scores))

def argmax(scores):
    m = max(scores)
    return [s == m for s in scores]

def greedy_margin(my_loaded, opp_loaded, my_history, opp_history):
    scores = [my_loaded[move] - opp_loaded[beat[move]] for move in moves]
    return argmax(scores)

recent_counts = None

def best_move(counts, my_loaded, opp_loaded):
    scores = [(counts[beaten[move]] + 0.5) * my_loaded[move] - 
              (counts[beat[move]] + 0.5) * opp_loaded[move] for move in moves]
    return argmax(scores)

def recent_stats(my_loaded, opp_loaded, my_history, opp_history):
    if len(opp_history) >= 10:
        recent_counts[opp_history[-10]] -= 1
    recent_counts[opp_history[-1]] += 1
    return best_move(recent_counts, my_loaded, opp_loaded)

order2_counts = None

def order2(my_loaded, opp_loaded, my_history, opp_history):
    if len(my_history) >= 2:
        base0 = 9 * my_history[-2] + 3 * opp_history[-2]
        order2_counts[base0 + opp_history[-1]] += 1
    base1 = 9 * my_history[-1] + 3 * opp_history[-1]
    counts = [order2_counts[base1 + move] for move in moves]
    return best_move(counts, my_loaded, opp_loaded)

def nash(my_loaded, opp_loaded, my_history, opp_history):
    third = 1.0 / 3
    p = np.full(3, third)
    q = np.full(3, third)
    u = np.array(my_loaded)
    v = np.array(opp_loaded)
    m0 = np.zeros(3)
    m1 = np.zeros(3)
    lr = 0.2
    for _ in range(10):
        de0 = u * np.roll(q, 1) - np.roll(v * q, 2)
        de1 = v * np.roll(p, 1) - np.roll(u * p, 2)
        m0 = 0.9 * m0 + 0.1 * de0
        m1 = 0.9 * m1 + 0.1 * de1
        p += lr * m0
        q += lr * m1
        p[p < 0] = 0
        q[q < 0] = 0
        tp, tq = np.sum(p), np.sum(q)
        if tp == 0 or tq == 0:
            return np.full(3, third)
        p /= tp
        q /= tq
        lr *= 0.9
    return p

strategies = [react, greedy_margin, recent_stats, order2, nash]

predictions = strategy_scores = mh = oh = None

def statistician2func(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    global strategy_scores, history, recent_counts, mh, oh, predictions, order2_counts
    if not opp_history:
        strategy_scores = [0 for _ in strategies]
        recent_counts = collections.Counter()
        order2_counts = collections.Counter()
        mh, oh = [], []
        predictions = None
        return random.choice(names)
    my_move = move_idx[my_history[-1]]
    opp_move = move_idx[opp_history[-1]]
    if predictions is not None:
        for j, p in enumerate(predictions):
            good = beat[opp_move]
            bad = beaten[opp_move]
            strategy_scores[j] += (my_loaded[good] * p[good] - opp_loaded[opp_move] * p[bad]) / sum(p)
    mh.append(my_move)
    oh.append(opp_move)
    predictions = [strategy(my_loaded, opp_loaded, mh, oh) for strategy in strategies]
    strategy = random_max(strategy_scores)
    p = predictions[strategy]
    r = random.random()
    for i, pi in enumerate(p):
        r -= pi
        if r <= 0:
            break
    return names[i]

Nash

import numpy as np
import random

def nashfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    third = 1.0 / 3
    p = np.full(3, third)
    q = np.full(3, third)
    u = np.array(my_loaded)
    v = np.array(opp_loaded)
    m0 = np.zeros(3)
    m1 = np.zeros(3)
    lr = 0.2
    for _ in range(10):
        de0 = u * np.roll(q, 1) - np.roll(v * q, 2)
        de1 = v * np.roll(p, 1) - np.roll(u * p, 2)
        m0 = 0.9 * m0 + 0.1 * de0
        m1 = 0.9 * m1 + 0.1 * de1
        p += lr * m0
        q += lr * m1
        p[p < 0] = 0
        q[q < 0] = 0
        tp, tq = np.sum(p), np.sum(q)
        if tp == 0 or tq == 0:
            return random.choice("RPS")
        p /= tp
        q /= tq
        lr *= 0.9
    r = random.random()
    for i, pi in enumerate(p):
        r -= pi
        if r <= 0:
            break
    return "RPS"[i]

Menghitung ekuilibrium Nash perkiraan dengan gradien descent.

pengguna1502040
sumber
1
Saya sangat menyukai pendekatan ini, dan dapat memahami mengapa Anda ingin dapat menjaga keadaan di antara putaran. Meskipun saya melihatnya masalah besar untuk mengubahnya mengingat jumlah pengiriman. Saya akan memperhitungkannya untuk tantangan lebih lanjut (yang saya harapkan akan lakukan ketika ini selesai).
Masclins
5

Timbangan

Saya kehilangan jejak penalaran saat bereksperimen dengan kode, tetapi ide dasarnya adalah memperkirakan probabilitas gerakan lawan dengan 3 gerakan terakhir menggunakan beberapa bobot dan mengalikannya dengan bobot lain yang tergantung pada beban. Saya berpikir bahwa saya entah bagaimana dapat menggunakan my_loadedjuga, tetapi saya tidak dapat memutuskan bagaimana, jadi tinggalkan saja.

def weigher(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    idx = {"R": 0, "P": 1, "S": 2}
    sc = [0, 0, 0]
    for i, m in enumerate(reversed(opp_history[-3:])):
        sc[idx[m]] += (1 / (1 + i))

    for i in range(3):
        sc[i] *= (opp_loaded[i] ** 2)

    return "PSR"[sc.index(max(sc))]

Setan

Mungkin akan didiskualifikasi, karena itu semacam kecurangan dan membuat beberapa asumsi tentang fungsi pengujian (harus memiliki fungsi lawan dalam variabel pada kerangka tumpukannya), tetapi secara teknis tidak melanggar aturan apa pun saat ini - tidak mendefinisikan kembali atau menulis ulang apa pun. Itu hanya menggunakan ilmu hitam untuk menjalankan fungsi lawan untuk melihat apa yang dilakukan / akan mereka lakukan. Itu tidak bisa berurusan dengan keacakan, tetapi bot deterministik tidak memiliki kesempatan untuk mengalahkan Setan.

def satan(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    import inspect, types
    f = inspect.currentframe()
    s = f.f_code.co_name
    try:
        for v in f.f_back.f_locals.values():
            if isinstance(v, types.FunctionType) and v.__name__ != s:
                try:
                    return "PSR"[{"R": 0, "P": 1, "S": 2}[
                        v(opp_points, my_points, opp_loaded, my_loaded, opp_history, my_history)]]
                except:
                    continue
    finally:
        del f
Nama tampilan
sumber
Tanpa keraguan yang terbaik dalam hal Kesederhanaan-Hasil
Masclins
Ngomong-ngomong, untuk menggunakan my_loadedAnda bisa menambahkan bobot yang menghargai gerakan yang akan kalah terhadap langkah terakhir Anda. Itu seperti mengasumsikan lawan Anda akan melakukan sesuatu yang mirip dengan yang Anda lakukan, dan karenanya menghukumnya karena menganggap Anda akan terus bermain sama. Sesuatu seperti:for i, m in enumerate(reversed(my_history[-3:])): sc[(idx[m]+1)%3] += (K / (1 + i))
Masclins
@AlbertMasclans menambahkan solusi lain
Nama Tampilan
1
Saya sangat suka Setan. Tapi seperti yang Anda katakan, saya percaya itu tidak boleh memenuhi syarat: Bahkan jika itu tidak melanggar aturan eksplisit, itu jelas bertentangan dengan semangat permainan. Namun, selamat atas ide Anda!
Masclins
4

Instalatur

Bot ini meningkatkan Pola dan menggabungkannya dengan Economist (Pattern and Economist tidak akan lagi berpartisipasi)

Peningkatan Pola adalah bahwa Bot sekarang mencari dua jenis pola: Lawan bereaksi terhadap permainan terakhirnya dan lawan bereaksi terhadap permainan terakhir saya. Kemudian evaluasi kedua prediksi untuk menggunakan prediksi yang paling cocok.

Dari pola itu Bot sekarang memiliki probabilitas untuk R, P dan S. Dengan memperhitungkannya dan nilai yang diharapkan dari setiap permainan (seperti yang dilakukan oleh Economist), Bot memainkan salah satu yang memberikan nilai paling besar.

import random
import numpy as np
def fitterfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        t = len(opp_history)
        RPS = ["R","P","S"]
        if t <= 2:
                return RPS[t]
        elif t == 3:
                return random.choice(RPS)

        def n(c): return RPS.index(c)

        total_me = np.zeros(shape=(3,3))
        total_opp= np.zeros(shape=(3,3))
        p_me = np.array([[1/3]*3]*3)
        p_opp = np.array([[1/3]*3]*3)

        for i in range(1, t):
                total_me[n(my_history[i-1]), n(opp_history[i])] += 1
                total_opp[n(opp_history[i-1]), n(opp_history[i])] += 1
        for i in range(3):
                if np.sum(total_me[i,:]) != 0:
                        p_me[i,:] = total_me[i,:] / np.sum(total_me[i,:])
                if np.sum(total_opp[i,:]) != 0:
                        p_opp[i,:] = total_opp[i,:] / np.sum(total_opp[i,:])

        error_me = 0
        error_opp = 0

        for i in range(1, t):
                diff = 1 - p_me[n(my_history[i-1]), n(opp_history[i])]
                error_me += diff * diff
                diff = 1 - p_opp[n(opp_history[i-1]), n(opp_history[i])]
                error_opp += diff * diff

        if error_me < error_opp:
                p = p_me[n(my_history[-1]),:]
        else:
                p = p_opp[n(opp_history[-1]),:]


# From here, right now I weight values, though not 100% is the best idea, I leave the alternative in case I'd feel like changing it
        value = [(p[2]*my_loaded[0] - p[1]*opp_loaded[1], "R"), (p[0]*my_loaded[1] - p[2]*opp_loaded[2], "P"), (p[1]*my_loaded[2] - p[0]*opp_loaded[0], "S")]
        value.sort()

        if value[-1][0] > value[-2][0]:
                return value[-1][1]
        elif value[-1][0] > value[-3][0]:
                return random.choice([value[-1][1], value[-2][1]])
        else:
                return random.choice(RPS)

#       idx = p.tolist().index(max(p))
#       return ["P", "S", "R"][idx]

Berikut adalah dua kode lama

Pola (tidak lagi bermain)

Pola berusaha menemukan pola pada lawannya. Itu terlihat seperti apa yang telah dimainkan lawan setelah permainan terakhir yang dilakukannya (memberikan bobot lebih untuk drama terakhir). Melalui itu, ia menebak apa yang akan dimainkan lawan, dan memainkan serangan balasan untuk itu.

import random
import numpy as np
def patternfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        if len(opp_history) == 0:
                return random.choice(["R","P","S"])
        elif len(opp_history) == 1:
                if opp_history == "R":
                        return "P"
                elif opp_history == "P":
                        return "S"
                elif opp_history == "S":
                        return "R"

        p = np.array([1/3]*3)
        c = opp_history[-1]
        for i in range(1, len(opp_history)):
                c0 = opp_history[i-1]
                c1 = opp_history[i]
                if c0 == c:
                        p *= .9
                        if c1 == "R":
                                p[0] += .1
                        elif c1 == "P":
                                p[1] += .1
                        elif c1 == "S":
                                p[2] += .1

        idx = p.tolist().index(max(p))
        return ["P", "S", "R"][idx]

Ekonom (tidak lagi bermain)

The Economist melakukan yang berikut: Menebak probabilitas setiap permainan oleh lawan dengan menonton apa yang telah ia mainkan dalam 9 putaran terakhir. Dari itu, menghitung manfaat yang diharapkan dari setiap permainan dan berjalan dengan yang memiliki nilai harapan terbaik.

import random
def economistfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        if len(opp_history) == 0:
                return random.choice(["R","P","S"])
        if len(opp_history) > 9:
                opp_history = opp_history[-10:-1]
        p = [opp_history.count("R"), opp_history.count("P"), opp_history.count("S")]

        value = [(p[2]*my_loaded[0] - p[1]*opp_loaded[1], "R"), (p[0]*my_loaded[1] - p[2]*opp_loaded[2], "P"), (p[1]*my_loaded[2] - p[0]*opp_loaded[0], "S")]
        value.sort()

        if value[-1][0] > value[-2][0]:
                return value[-1][1]
        elif value[-1][0] > value[-3][0]:
                return random.choice([value[-1][1], value[-2][1]])
        else:
                return random.choice(["R","P","S"])
Masclins
sumber
4

Yggdrasil

Ini dinamai "Yggdrasil" karena terlihat di depan di pohon permainan. Bot ini tidak melakukan prediksi lawan, ia hanya mencoba mempertahankan keunggulan statistik jika diberikan satu (dengan menyeimbangkan keuntungan saat ini dan masa depan). Ini menghitung strategi campuran sekitar ideal, dan mengembalikan langkah yang dipilih secara acak dengan bobot tersebut. Jika bot ini sempurna (yang bukan, karena fungsi penilaian negara sangat buruk dan tidak terlihat terlalu jauh ke depan), maka tidak mungkin mengalahkan bot ini lebih dari 50% dari waktu. Saya tidak tahu seberapa baik bot ini dalam praktiknya.

def yggdrasil(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    cache = {}
    def get(turn, ml, ol):
        key = str(turn) + str(ml) + str(ol)
        if not key in cache:
            cache[key] = State(turn, ml, ol)
        return cache[key]

    def wrand(opts):
        total = sum(abs(w) for c,w in opts.items())
        while True:
            r = random.uniform(0, total)
            for c, w in opts.items():
                r -= abs(w)
                if r < 0:
                    return c
            print("error",total,r)

    class State():
        turn = 0
        ml = [1,1,1]
        ol = [1,1,1]
        val = 0
        strat = [1/3, 1/3, 1/3]
        depth = -1
        R = 0
        P = 1
        S = 2
        eps = 0.0001
        maxturn = 1000

        def __init__(self, turn, ml, ol):
            self.turn = turn
            self.ml = ml
            self.ol = ol
        def calcval(self, depth):
            if depth <= self.depth:
                return self.val
            if turn >= 1000:
                return 0
            a = 0
            b = -self.ol[P]
            c = self.ml[R]
            d = self.ml[P]
            e = 0
            f = -self.ol[S]
            g = -self.ol[R]
            h = self.ml[S]
            i = 0
            if depth > 0:
                a += get(self.turn+1,[self.ml[R]+1,self.ml[P],self.ml[S]],[self.ol[R]+1,self.ol[P],self.ol[S]]).calcval(depth-1)
                b += get(self.turn+1,[self.ml[R]+2,self.ml[P],self.ml[S]],[self.ol[R],self.ol[P],self.ol[S]]).calcval(depth-1)
                c += get(self.turn+1,[self.ml[R],self.ml[P],self.ml[S]],[self.ol[R],self.ol[P],self.ol[S]+2]).calcval(depth-1)
                d += get(self.turn+1,[self.ml[R],self.ml[P],self.ml[S]],[self.ol[R]+2,self.ol[P],self.ol[S]]).calcval(depth-1)
                e += get(self.turn+1,[self.ml[R],self.ml[P]+1,self.ml[S]],[self.ol[R],self.ol[P]+1,self.ol[S]]).calcval(depth-1)
                f += get(self.turn+1,[self.ml[R],self.ml[P]+2,self.ml[S]],[self.ol[R],self.ol[P],self.ol[S]]).calcval(depth-1)
                g += get(self.turn+1,[self.ml[R],self.ml[P],self.ml[S]+2],[self.ol[R],self.ol[P],self.ol[S]]).calcval(depth-1)
                h += get(self.turn+1,[self.ml[R],self.ml[P],self.ml[S]],[self.ol[R],self.ol[P]+2,self.ol[S]]).calcval(depth-1)
                i += get(self.turn+1,[self.ml[R],self.ml[P],self.ml[S]+1],[self.ol[R],self.ol[P],self.ol[S]+1]).calcval(depth-1)
            self.val = -9223372036854775808
            for pr in range(0,7):
                for pp in range(0,7-pr):
                    ps = 6-pr-pp
                    thisval = min([pr*a+pp*d+ps*g,pr*b+pp*e+ps*h,pr*c+pp*f+ps*i])
                    if thisval > self.val:
                        self.strat = [pr,pp,ps]
                        self.val = thisval
            self.val /= 6


            if depth == 0:
                self.val *= min(self.val, self.maxturn - self.turn)
            return self.val

    turn = len(my_history)
    teststate = get(turn, [x * 2 for x in my_loaded], [x * 2 for x in opp_loaded])
    teststate.calcval(1)
    return wrand({"R":teststate.strat[R],"P":teststate.strat[P],"S":teststate.strat[S]})
PhiNotPi
sumber
harap hapus komentar yang tidak membuat kode lebih dimengerti
Nama Tampilan
@SargeBorsch selesai
PhiNotPi
1
@PhiNotPi Saya sadar bahwa saya tidak memposting batasan waktu, tetapi Yggdrasil mengambil lebih dari satu menit melawan setiap lawan. Apakah mungkin untuk mengoptimalkannya sedikit?
Masclins
ya lambat sekali
Nama Tampilan
@AlbertMasclans per menit per lawan, maksud Anda total 1 menit untuk semua pertandingan melawan lawan? Saya juga dapat mencoba mempercepatnya tetapi saya tidak benar-benar tahu bagaimana melakukannya, hanya terlihat saya bergerak maju seperti apa adanya.
PhiNotPi
4

Anti-Pengulang

from random import choice
def Antirepeaterfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    s = opp_history.count("S")
    r = opp_history.count("R")
    p = opp_history.count("P")

    if s>p and s>r:
        return "R"
    elif p>s and p>r:
        return "S"
    else:
        return "P"

Pilih kertas pada belokan pertama, setelah itu mengembalikan apa pun yang mengalahkan apa yang paling banyak dilakukan lawan, mengambil kertas jika ada dasi.

Peniru

import random
def copycatfunc(I,dont,care,about,these,enmoves):
    if not enmoves:
        return random.choice(["R","P","S"])
    else:
        return enmoves[len(enmoves)-1]

Cukup salin langkah terakhir lawan.

Anti-Anti-Serakah

from random import choice
def antiantigreedy(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    if opp_loaded[0] > opp_loaded[1] and opp_loaded[0] > opp_loaded[2]:
        return "S"
    if opp_loaded[1] > opp_loaded[0] and opp_loaded[1] > opp_loaded[2]:
        return "R"
    if opp_loaded[2] > opp_loaded[0] and opp_loaded[2] > opp_loaded[1]:
        return "P"
    else:
        return choice(["R","P","S"])

Pilihan apa pun yang kalah dari pilihan lawan yang paling berat.

Agak Lapar

from random import choice
def somewhathungryfunc(blah, blah2, load, blah3, blah4, blah5):
    if load[0] > load[1] and load[0] < load[2] or load[0] < load[1] and load[0] > load[2]:
        return "R"
    if load[1] > load[0] and load[1] < load[2] or load[1] < load[0] and load[1] > load[2]:
        return "P"
    if load[2] > load[1] and load[2] < load[0] or load[2] < load[1] and load[2] > load[0]:
        return "S"
    else:
        return choice(["R","P","S"])
Gryphon
sumber
3

Utusan

def themessengerfunc (saya, lakukan, tidak, perlu, ini, argumen): return "P"

Rockstar

def rockstarfunc (I, do, not, need, this, arguments): return "R"

Pembunuh

def assassinfunc (I, do, not, need, this, arguments): return "S"

Penjelasan

Sekarang, Anda mungkin berpikir bahwa bot ini sepenuhnya bodoh.

tidak sepenuhnya benar, ini sebenarnya didasarkan pada ide, dari mengumpulkan bonus besar, dan musuh membuat kesalahan langkah dan dipukuli dengannya.

sekarang, bot ini bermain sangat mirip dengan serakah, namun, mereka lebih sederhana, dan tidak memilih secara acak sampai mereka mendapatkan beban pada satu senjata, mereka tetap dengan senjata pilihan mereka.

Hal lain yang perlu diperhatikan: masing-masing akan mengalahkan rakus sekitar setengah waktu, menarik sepertiga dari waktu, dan kehilangan seperenam waktu ketika mereka menang, mereka cenderung menang banyak. kenapa ini?

Serakah, sampai dia kalah satu ronde, akan secara acak memilih senjata. ini berarti bahwa ketika dia tidak memenangkan ronde, dia akan memilih senjata secara acak lagi, yang bisa menjadi senjata yang menang lagi. jika serakah imbang atau kalah, dia bertahan dengan senjata itu. jika serakah menang setidaknya satu putaran, lalu pilih senjata yang sama dengan bot, serakah menang. jika serakah mengambil senjata yang hilang di beberapa titik, bot kami menang, karena beban pada senjata kami akan lebih tinggi dari skor serakah.

Dengan asumsi serakah tidak selalu hanya mengambil senjata yang menang melalui kesempatan besar, ini berarti bahwa kemungkinannya adalah:

1/3: {1/2 win (total 1/6). 1/2 kalah (total 1/6). }

1/3 imbang

1/3 menang

jadi: 1/3 kesempatan untuk seri, 1/6 peluang dari kerugian, 1/2 peluang untuk menang.

ini mungkin menunjukkan bahwa Anda perlu melakukan banyak permainan dari beberapa babak

ini terutama untuk mendapatkan tantangan bergulir

Lemon dirusak
sumber
3

Reaktor

Buat drama yang akan memenangkan putaran sebelumnya.

import random
def reactfunc(I, dont, need, all, these, opp_history):
    if not opp_history:
        return random.choice(["R","P","S"])
    else:
        prev=opp_history[len(opp_history)-1]
        if prev == "R":
            return "P"
        if prev == "P":
            return "S"
        else:
            return "R"
KSmarts
sumber
1
Anda bisa menggantinya opp_history[len(opp_history)-1]dengan opp_history[-1].
CalculatorFeline
3

Anak Berseni

Bot ini bertindak seperti anak kecil yang bermain seni dan kerajinan, akan mulai dengan kertas dan menggunakan kertas atau gunting baik secara acak, tetapi tidak akan menggunakan gunting setelah batu atau gunting karena dia perlu menggunakan gunting di atas kertas. Akan melempar batu kembali pada siapa pun yang melempar batu padanya.

import random
def artsychildfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    if len(opp_history) == 0:
            return "P"
    elif opp_history[-1] == "R":
            return "R"
    elif my_history[-1] != "P":
            return "P"
    else:
            return random.choice(["P", "S"])
TitusLucretius
sumber
2

Berikut tiga Bot yang saya buat untuk pengujian:


RandomBot

import random
def randombotfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        return random.choice(["R","P","S"])

Serakah

Cukup pilih opsi yang paling banyak dimuatnya.

import random
def greedyfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        if my_loaded[0] > my_loaded[1]:
                if my_loaded[0] > my_loaded[2]:
                        return "R"
                elif my_loaded[0] < my_loaded[2]:
                        return "S"
                else:
                        return random.choice(["R","S"])
        elif my_loaded[0] < my_loaded[1]:
                if my_loaded[1] > my_loaded[2]:
                        return "P"
                elif my_loaded[1] < my_loaded[2]:
                        return "S"
                else:
                        return random.choice(["P","S"])
        else:
                if my_loaded[0] > my_loaded[2]:
                        return random.choice(["R","P"])
                elif my_loaded[0] < my_loaded[2]:
                        return "S"
                else:
                        return random.choice(["R","P","S"])

Antigreedy

Diasumsikan lawan akan bermain serakah dan memainkan alternatif yang menang.

import random
def antigreedyfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        if opp_loaded[0] > opp_loaded[1]:
                if opp_loaded[0] > opp_loaded[2]:
                        return "P"
                elif opp_loaded[0] < opp_loaded[2]:
                        return "R"
                else:
                        return "R"
        elif opp_loaded[0] < opp_loaded[1]:
                if opp_loaded[1] > opp_loaded[2]:
                        return "S"
                elif opp_loaded[1] < opp_loaded[2]:
                        return "R"
                else:
                        return "S"
        else:
                if opp_loaded[0] > opp_loaded[2]:
                        return "P"
                elif opp_loaded[0] < opp_loaded[2]:
                        return "R"
                else:
                        return random.choice(["R","P","S"])
Masclins
sumber
1

Tidak lapar

def nothungryfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    if my_loaded[0] < my_loaded[1]:
            if my_loaded[0] < my_loaded[2]:
                    return "R"
            elif my_loaded[0] > my_loaded[2]:
                    return "S"
            else:
                    return random.choice(["R","S"])
    elif my_loaded[0] > my_loaded[1]:
            if my_loaded[1] < my_loaded[2]:
                    return "P"
            elif my_loaded[1] > my_loaded[2]:
                    return "S"
            else:
                    return random.choice(["P","S"])
    else:
            if my_loaded[0] < my_loaded[2]:
                    return random.choice(["R","P"])
            elif my_loaded[0] > my_loaded[2]:
                    return "S"
            else:
                    return random.choice(["R","P","S"])

Ini benar-benar kebalikan dari Greedy, ia memilih opsi poin terendah yang tersedia.

Pelican teal
sumber
1

Gunakan Favorit Lawan

from collections import Counter
import random
def useopponents(hi, my, name, is, stephen, opp_history):
  if opp_history:
    data = Counter(opp_history)
    return data.most_common(1)[0][0]
  else:
    return random.choice(["R","P","S"])

Untuk belokan pertama, pilih item acak. Untuk setiap belokan lainnya, gunakan pilihan lawan yang paling umum. Jika ada dasi, itu default ke pilihan paling umum paling awal.

// Aku mencuri kode dari sini


Menang itu Bagus

import random
def goodwinning(no, yes, maybe, so, my_history, opp_history):
  if opp_history:
    me = my_history[len(my_history)-1]
    you = opp_history[len(opp_history)-1]
    if you == me:
      return goodwinning(no, yes, maybe, so, my_history[:-1], opp_history[:-1])
    else:
      if me == "R":
        if you == "P":
          return "P"
        else:
          return "R"
      elif me == "P":
        if you == "S":
          return "S"
        else:
          return "R"
      else:
        if you == "R":
          return "R"
        else:
          return "P"
  else:
    return random.choice(["R","P","S"])

Mengembalikan pilihan pemenang babak sebelumnya. Jika ronde sebelumnya adalah seri, periksa ronde sebelumnya secara rekursif. Jika itu hanya ikatan, atau itu adalah babak pertama, mengembalikan pilihan acak.

Stephen
sumber
1

Terbaik dari Kedua Dunia

Bot ini pada dasarnya menggabungkan Anti-Serakah dan Serakah (karenanya namanya).

def bobwfunc(a, b, my_loaded, opp_loaded, c, d):
    opp_max = max(opp_loaded)
    opp_play = "PSR"[opp_loaded.index(opp_max)]

    my_max = max(my_loaded)
    my_play = "RPS"[my_loaded.index(my_max)]

    if opp_play == my_play:
        return opp_play
    else:
        return my_play if opp_max < my_max else opp_play
clismique
sumber
Ini adalah Antigreedy, sudah diposting sebagai contoh.
Masclins
@AlbertMasclans Mengubahnya ke bot lain.
clismique
finduntuk string. my_loadeddan opp_loadedkeduanya daftar. indexharus baik untuk apa yang Anda inginkan.
Masclins
@AlbertMasclans Whoops, perbaiki sekarang. Terima kasih atas tangkapannya! Saya harap ini bukan dup lain ... Saya tidak ingin menghapus posting ini lagi.
clismique
Ini ok, terima kasih sudah bermain
Masclins
1

NashBot

import random
def nashbotfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    r = opp_loaded[0] * opp_loaded[2]
    p = opp_loaded[0] * opp_loaded[1]
    s = opp_loaded[1] * opp_loaded[2]
    q = random.uniform(0, r + p + s) - r
    return "R" if q < 0 else "P" if q < p else "S"

Secara acak memilih antara tiga opsi sedemikian rupa sehingga lawan secara statistik tidak memiliki preferensi antara gerakan berkaitan dengan berapa banyak skornya; dengan kata lain, Greedy dan Not Hungry harus memiliki skor rata-rata yang diharapkan yang sama dengannya.

Neil
sumber
1

Perkiraan waktu

Sunting: Peringkat yang Diperbarui

Ini adalah peringkat teratas baru setelah dimasukkannya Expectedbayes:

  • statistik2fungsi 91,89%
  • fungsi fitter 85,65%
  • nashfunc 80,40%
  • fungsi penimbangan 76,39%
  • Fungsi yang diharapkan dari 73,33%
  • fungsi antirepeater 68,52%
  • ...

Penjelasan

(NB: pengajuan pos 05/06/2017)

Bot ini mencoba memaksimalkan nilai yang diharapkan dari langkah selanjutnya dengan:

  • Menghitung probabilitas untuk setiap kemungkinan langkah lawan selanjutnya
  • Menggunakan angka itu dan beban untuk menghitung nilai yang diharapkan untuk masing-masing R, P dan S
  • Memilih langkah yang memiliki nilai harapan tertinggi
  • Memilih nilai secara acak jika prediksi gagal

Peluang diperbarui setiap sepuluh langkah. Jumlah gerakan terakhir yang digunakan untuk menghitung probabilitas telah ditetapkan ke 10 untuk setiap bot (jadi 20 fitur secara keseluruhan). Ini mungkin overfitting data, tetapi saya tidak mencoba untuk memeriksa lebih jauh.

Itu bergantung pada pustaka scikit untuk menghitung probabilitas gerakan lawan (saya katakan kalau-kalau saya salah membaca aturan dan itu sebenarnya tidak diizinkan).

Dengan mudah menang melawan bot yang selalu membuat pilihan yang sama. Anehnya, ini cukup efektif terhadap bot acak dengan tingkat kemenangan 93% (saya percaya ini karena fakta bahwa itu membatasi jumlah poin yang bisa didapatkan lawannya sambil memaksimalkan jumlah poin yang memungkinkan untuk setiap putaran).

Saya melakukan percobaan cepat dengan 100 putaran dan hanya sejumlah bot, dan inilah yang saya dapat dari result_standing:

  • randombotfunc, 35
  • nashbotfunc, 333
  • fungsi serakah, 172
  • fungsi antigreedy, 491
  • themessengerfunc, 298
  • rockstarfunc, 200
  • statistician2func, 748
  • fungsi fitter, 656
  • Fungsi yang diharapkan, 601

Yang tidak seburuk itu!

from sklearn.naive_bayes import MultinomialNB
import random

#Number of past moves used to compute the probability of next move
#I did not really try to make such thing as a cross-validation, so this number is purely random
n_data = 10

#Some useful data structures
choices = ['R','P','S']
choices_dic = {'R':0,'P':1,'S':2}
point_dic = {(0,0):0,(1,1):0,(2,2):0, #Same choices
             (0,1):-1,(0,2):1, #me = rock
             (1,0):1,(1,2):-1, #me = paper
             (2,0):-1,(2,1):1} #me = scissor

def compute_points(my_choice,opp_choice,my_load,opp_load):
    """
    Compute points
    @param my_choice My move as an integer
    @param opp_choice Opponent choice as an integer
    @param my_load my_load array
    @param opp_load opp_load array
    @return A signed integer (+ = points earned, - = points losed)
    """
    points = point_dic[(my_choice,opp_choice)] #Get -1, 0 or 1
    if points > 0:
        return points*my_load[my_choice] 
    else:
        return points*opp_load[opp_choice]

#This use to be a decision tree, before I changed it to something else. Nevertheless, I kept the name
class Decision_tree:
    def __init__(self):
        self.dataX = []
        self.dataY = []
        self.clf = MultinomialNB()

    def decide(self,my_load,opp_load,my_history,opp_history):
        """
        Returns the decision as an integer

        Done through a try (if a prediction could be made) except (if not possible)
        """
        try:
            #Let's try to predict the next move
            my_h = list(map(lambda x: choices_dic[x],my_history[-n_data:-1]))
            opp_h = list(map(lambda x: choices_dic[x],opp_history[-n_data:-1]))
            pred = self.clf.predict_proba([my_h+opp_h])
            #We create a points array where keys are the available choices
            pts = []
            for i in range(3):
                #We compute the expected gain/loss for each choice
                tmp = 0
                for j in range(3):
                    tmp += compute_points(i,j,my_load,opp_load)*pred[0][j]
                pts.append(tmp)
            return pts.index(max(pts)) #We return key for the highest expected value
        except:
            return random.choice(range(3))

    def append_data(self,my_history,opp_history):
        if my_history == "":
            self.clf = MultinomialNB()
        elif len(my_history) < n_data:
            pass
        else:
            my_h = list(map(lambda x: choices_dic[x],my_history[-n_data:-1]))
            opp_h = list(map(lambda x: choices_dic[x],opp_history[-n_data:-1]))
            self.dataX = self.dataX + [my_h+opp_h]
            self.dataY = self.dataY + [choices_dic[opp_history[-1:]]]

            if len(self.dataX) >= 10:
                self.clf.partial_fit(self.dataX,self.dataY,classes=[0,1,2])

                self.dataX = []
                self.dataY = []


#Once again, this is not actually a decision tree
dt = Decision_tree()

#There we go:
def expectedbayesfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    dt.append_data(my_history,opp_history)
    choice = choices[dt.decide(my_loaded,opp_loaded,my_history,opp_history)]
    return choice
lesibius
sumber
Selamat datang di PPCG, dan posting pertama yang bagus!
Zacharý
Terima kasih banyak! Saya ingin berpartisipasi dalam PPCG untuk waktu yang lama. Sekarang sudah diperbaiki!
lesibius
0

Pengendara sepeda

def cycler(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    return "RPS"[len(myhistory)%3]

0

CalculatorFeline
sumber
0

Ansambel

from random import *
def f(I):
    if I==0:return "R"
    if I==1:return "P"
    return "S"
def b(I):
    if I=="R":return 0
    if I=="P":return 1
    return 2
def Ensemble(mp,op,ml,ol,mh,oh):
    A=[0]*3
    B=[0]*3
    if(len(oh)):
        k=b(oh[-1])
        A[k-2]+=0.84
        A[k]+=0.29
        for x in range(len(oh)):
            g=b(oh[x])
            B[g-2]+=0.82
            B[g]+=0.22
        s=sum(B)
        for x in range(len(B)):
            A[x]+=(B[x]*1.04/s)
        r=max(A)
    else:
        r=randint(0,3)
    return f(r)

Beberapa algoritma yang bersaing memberikan suara untuk solusi terbaik.

Menukar

from random import *
def f(I):
    if I==0:return "R"
    if I==1:return "P"
    return "S"
def b(I):
    if I=="R":return 0
    if I=="P":return 1
    return 2
def Swap(mp,op,ml,ol,mh,oh):
    A=[0]*3
    B=[0]*3
    if(len(mh)):
        r=(b(mh[-1])+randint(1,2))%3
    else:
        r=randint(0,3)
    return f(r)

Apakah langkah acak, tetapi tanpa mengulangi langkah terakhir itu.

Magenta
sumber
0

blodsocer

socery

Saya memberikannya perbaikan, jadi mungkin seharusnya berfungsi sekarang saya harap

Saya mengacaukan sesuatu lagi sehingga saya menghapus dan membatalkan penghapusan. Saya membuat banyak kekacauan.

def blodsocerfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    import random
    # tuned up an ready to go hopeful
    # s o c e r y
    if len(my_history) > 40 and len(set(opp_history[-30:])) == 1:
        if opp_history[-1] == "S":
            return "R"
        elif opp_history[-1] == "R":
            return "P"
        else:
            return "S"
        # against confused bots that only do one thing most of the time.
    elif len(my_history)>30 and min(opp_history.count(i) for i in "RPS")/max(opp_history.count(i) for i in "RPS") >0.8:
        return "RPS"[my_loaded.index(max(my_loaded))] # This is so if the other bot is acting errratic
                                                      # the max bonus is used for advantage
    elif len(my_history) < 10:
        if len(my_history) > 2 and all(i == "S" for i in opp_history[1:]):
            if len(my_history) > 5: return "S"
            return "P"
        return "S" # Be careful, because scissors are SHARP
    elif len(set(opp_history[1:10])) == 1 and len(my_history) < 20:
        if opp_history[1] == "S":
            return "R"
        elif opp_history[1] == "R":
            return "R"
        else:
            return "P"
    elif len(opp_history) -  max(opp_history.count(i) for i in "RPS") < 4 and len(my_history) < 30:
        if opp_history.count("R") > max(opp_history.count(i) for i in "PS"):
            return "P"
        if opp_history.count("P") > max(opp_history.count(i) for i in "RS"):
            return "S"
        if opp_history.count("S") > max(opp_history.count(i) for i in "RP"):
            return "R"
    elif len(my_history) < 15:
        if max(opp_loaded)<max(my_loaded):
            return "RPS"[len(my_history)%3]
        else:
            return "RPS"[(my_loaded.index(max(my_loaded))+len(my_history)%2)%3]
    elif len(my_history) == 15:
        if max(opp_loaded)<max(my_loaded):
            return "RPS"[(len(my_history)+1)%3]
        else:
            return "RPS"[(my_loaded.index(max(my_loaded))+ (len(my_history)%2)^1)%3]
    else:
        if max(opp_loaded)<max(my_loaded):
            return random.choice("RPS")
        else:
            return "RPS"[(my_loaded.index(max(my_loaded))+ (random.randint(0,1)))%3]
Lemon dirusak
sumber
1
if opp_history[1] == "S": return "R" elif opp_history[1] == "R": return "R" else: return "P"jenis socery apa ini?
Robert Fraser
@DestructibleLemon Ini dibagi dengan 0:elif min(opp_history.count(i) for i in "RPS")/max(opp_history.count(i) for i in "RPS") >0.8 and len(my_history)>30:
Masclins
@AlbertMasclans Saya memperbaikinya.
Lemon Destructible
@RobertFraser, apa sebenarnya yang menonjol dari cuplikan kode itu?
Destructible Lemon
@DestructibleLemon Saya tidak sepenuhnya yakin apa yang ingin Anda lakukan di sini: "RPS"[my_loaded.index(max(my_loaded))+len(my_history)%2]tetapi terlihat di luar jangkauan (dan begitu juga garis selanjutnya).
Masclins
0

Acak tertimbang

Seperti RandomBot, tetapi hanya mengambil 2 untuk membuang setiap kali dipanggil. Terkadang akan mengalahkan Rockstar atau Assassin, tetapi akan memompa skor yang lain (misalnya, jika mengalahkan Rockstar, itu memberi Assassin poin peningkatan).

import random

selection_set = ["R", "P", "S"]
selection_set.pop(random.randint(0,2))
def weightedrandombotfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    return random.choice(selection_set)
Andrew U Baker
sumber
0

Psikolog serakah

Dinamakan demikian karena default untuk serakah, tetapi jika tidak bisa memutuskan, itu melawan apa pun yang lawan lakukan jika mereka menggunakan strategi serakah. Jika masih belum bisa memutuskan, ia pergi secara acak.

from random import choice

def greedypsychologistfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    greedy = get_my_move(my_loaded)
    combined = list(set(greedy) & set(get_opp_counter(opp_loaded)))

    if len(combined) == 0:
        return choice(greedy)
    return choice(combined)

def get_indexes(lst, value):
    return [i for i,x in enumerate(lst) if x == value]

def get_my_move(my_loaded):
    return ["RPS"[i] for i in get_indexes(my_loaded, max(my_loaded))]

def get_opp_counter(opp_loaded):
    return ["PSR"[i] for i in get_indexes(opp_loaded, max(opp_loaded))]
Solomon Ucko
sumber