KOTH - โหลด RPS


12

การประกวดเปิดอย่างถาวร - อัปเดต 10 สิงหาคม 2560

แม้ว่าในวันที่ 5 มิถุนายน 2017 ฉันประกาศผู้ชนะ (ใครจะถูกเก็บไว้เป็นคำตอบที่ดีที่สุด) ฉันจะได้รับบอทใหม่และอัปเดตผลลัพธ์

ผล 5 มิถุนายน

ขอแสดงความยินดีกับผู้ใช้1502040

เนื่องจากไม่มีความสัมพันธ์ฉันจะแสดงเฉพาะ% ของการแข่งขันที่ชนะ

Statistician2- 95.7%
Fitter- 89.1%
Nash- 83.9%
Weigher- 79.9%
ExpectedBayes- 76.4%
AntiRepeater- 72.1%
Yggdrasil-
AntiGreedy64.1 % - 64.1%
Reactor- 59.9%
NotHungry- 57.3%
NashBot- 55.1%
Blodsocer- 48.1%
BestOfBothWorlds- 48.4%
GoodWinning- 40.9
Rockstar%
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- 16.2%

ฉันสร้าง Google ชีตด้วยตารางผลลัพธ์ของการจับคู่แต่ละครั้ง: https://docs.google.com/spreadsheets/d/1KrMvcvWMkK-h1Ee50w0gWLh_L6rCFOgLhTN_QlEXHyk/edit?usp=sharing


ขอบคุณPetri Dilemmaฉันพบว่าตัวเองสามารถรับมือกับ King of the Hill นี้ได้

เกม

เกมนี้เป็น "Rock-Paper-Scissors" แบบง่าย ๆ พร้อมการบิด: คะแนนที่ได้รับจากชัยชนะเพิ่มขึ้นระหว่างการแข่งขัน (โหลด R, P หรือ S ของคุณ)

  • กระดาษชนะร็อค
  • กรรไกรชนะกระดาษ
  • ร็อคชนะกรรไกร

ผู้ชนะจะได้รับคะแนนมากที่สุดเท่าที่เขาเล่น

ผู้แพ้จะเพิ่มขึ้น 1 เมื่อเล่นของเขา

ในกรณีที่เสมอกันผู้เล่นแต่ละคนจะเพิ่มภาระในการเล่นของเขา 0.5

หลังจากเล่นไปแล้ว 100 ครั้งผู้ที่มีคะแนนมากกว่าจะเป็นผู้ชนะ

เช่น: P1 โหลด [10,11,12] (หิน, กระดาษ, กรรไกร) และ P2 [7,8,9] P1 เล่น R, P2 เล่น P. P2 ชนะและได้รับ 8 คะแนน การโหลด P1 กลายเป็น [11,11,12] การโหลด P2 ยังคงเหมือนเดิม

ข้อมูลจำเพาะของความท้าทาย

โปรแกรมของคุณต้องเขียนด้วย Python (ขออภัยฉันไม่ทราบวิธีจัดการอย่างอื่น) คุณต้องสร้างฟังก์ชั่นที่ใช้ตัวแปรแต่ละตัวเหล่านี้เป็นอาร์กิวเมนต์ในแต่ละการประมวลผล:

my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history

points - คะแนนปัจจุบัน (ของคุณและของคุณ opp)

loaded- อาร์เรย์พร้อมโหลด (ตามลำดับ RPS) (ของคุณและของคุณ opp)

history- สตริงที่มีการเล่นทั้งหมดตัวละครตัวสุดท้ายคือการเล่นครั้งสุดท้าย (คุณและคุณ opp)

คุณจะต้องกลับ"R", หรือ"P" "S"หากคุณจะคืนสิ่งที่แตกต่างออกไปมันจะเป็นการสูญเสียการแข่งขันโดยอัตโนมัติ

กฎระเบียบ

คุณไม่สามารถเปลี่ยนฟังก์ชั่นในตัว

การทดสอบ

ฉันจะอัปเดต Git ด้วยรหัสและบอททั้งหมดที่มีการคำนวณ: https://github.com/Masclins/LoadedRPS

การตัดสิน

ผู้ชนะจะได้รับการตัดสินโดยการเลือกบุคคลที่มีการแข่งขันมากที่สุดหลังการแข่งขันครบ 1,000 รอบ ความสัมพันธ์จะถูกทำลายโดยการแข่งขันที่ผูกไว้ กำลังเล่นการแข่งขันมากกว่า 1,000 รายการมากกว่าหนึ่งรายการเนื่องจากฉันคาดว่าจะมีการสุ่มจำนวนมากและวิธีการสุ่มนั้นมีความเกี่ยวข้องน้อยกว่า

คุณสามารถส่งได้ถึง 5 บอท

การประกวดสิ้นสุดในวันที่กรกฏาคม 4 มิถุนายน (ที่จะเป็นวันสุดท้ายที่ผมจะยอมรับคำตอบใด ๆ ) และกรกฏาคม 5 มิถุนายนผมจะโพสต์ stadings สุดท้าย (อาจพยายามที่จะโพสต์ advancemnt ก่อน)


เนื่องจากนี่เป็น KOTH แรกของฉันฉันเปิด 100% เพื่อเปลี่ยนแปลงทุกอย่างเพื่อการปรับปรุงเช่นจำนวนการแข่งขันที่เล่นกับบอทแต่ละตัว

แก้ไขไปแล้ว 1,000 แมทช์เนื่องจากฉันเห็นว่ามีส่วนเกี่ยวข้องค่อนข้างสุ่ม


ด้วยบอตแบบสุ่มคุณต้องการสร้างหลายเกมหลายรอบ
Destructible Lemon

@DestructibleLemon ฉันคิดเกี่ยวกับการทำให้ bot แต่ละตัวเล่นสามครั้งกับ bot อื่น ๆ มากกว่าหนึ่งครั้ง เมื่อเห็นคุณคิดในทำนองเดียวกันฉันจะทำเช่นนั้น
Masclins

1
(จริงๆคุณต้องมีจำนวนมากที่เป็นธรรมตั้งแต่probabilitésบางคนจริงๆขยายมากกว่าหลายแมตช์ดูบอทของฉันที่มันจะได้รับคู่แข่งขัน แต่มีแนวโน้มว่าจะไม่ได้อยู่กับจำนวนเงินที่ยุติธรรมของการแข่งขัน.)
ทำลายมะนาว

1
ฉันดีใจที่คำถามของฉันช่วยให้คุณสามารถเรียกใช้ @AlbertMasclans!
Gryphon

2
@AlbertMasclans คุณสามารถโพสต์ข้อความทดสอบฉบับเต็ม (รวมถึงruncodeและbots) ได้ไหม
CalculatorFeline

คำตอบ:


8

สถิติ (ไม่เล่นอีกต่อไป)

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)]

สลับระหว่างกลยุทธ์ง่ายๆสองสามตัวตามประสิทธิภาพที่คาดหวังในอดีต

สถิติ 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]

แนช

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]

คำนวณสมดุลของแนชโดยประมาณโดยการไล่ระดับสี


1
ฉันชอบวิธีนี้มากและสามารถเข้าใจได้ว่าทำไมคุณถึงต้องการรักษาสถานะระหว่างรอบ แม้ว่าฉันจะเห็นว่ามันเป็นปัญหาใหญ่ที่จะเปลี่ยนมันตามจำนวนที่ส่ง ฉันจะคำนึงถึงความท้าทายต่อไป (ซึ่งฉันคาดว่าจะทำเมื่อเสร็จสิ้น)
Masclins

5

ชั่ง

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

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))]

ซาตาน

อาจจะถูกตัดสิทธิ์เนื่องจากเป็นการโกงและทำให้มีข้อสันนิษฐานเกี่ยวกับฟังก์ชั่นการทดสอบ (ต้องมีฟังก์ชั่นของฝ่ายตรงข้ามในตัวแปรในกรอบสแต็ค) แต่มันไม่ได้ทำลายกฎทางเทคนิคในปัจจุบัน - กำหนดใหม่หรือเขียนใหม่อะไรก็ได้ มันใช้เวทย์มนตร์ดำเพื่อสั่งงานฟังก์ชั่นของฝ่ายตรงข้ามเพื่อดูว่าพวกเขาทำอะไรได้บ้าง มันไม่สามารถจัดการกับการสุ่ม แต่บอทที่กำหนดได้จะไม่มีโอกาสเอาชนะซาตาน

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

ไม่ต้องสงสัยเลยว่าสิ่งที่ดีที่สุดในแง่ของความเรียบง่าย - ผลลัพธ์
Masclins

โดยวิธีการใช้my_loadedคุณสามารถเพิ่มน้ำหนักที่ให้ความสำคัญกับการย้ายที่จะสูญเสียเมื่อเทียบกับการย้ายครั้งล่าสุดของคุณ นั่นเหมือนกับการสมมติว่าคู่ต่อสู้ของคุณจะทำสิ่งที่คล้ายกับสิ่งที่คุณทำและลงโทษเขาเพราะสมมติว่าคุณจะเล่นต่อไป สิ่งที่ต้องการ:for i, m in enumerate(reversed(my_history[-3:])): sc[(idx[m]+1)%3] += (K / (1 + i))
Masclins

@AlbertMasclans เพิ่มโซลูชันอื่น
ชื่อที่แสดง

1
ฉันชอบซาตานจริงๆ แต่อย่างที่คุณพูดฉันเชื่อว่ามันไม่ควรมีคุณสมบัติ: แม้ว่ามันจะไม่ผิดกฎใด ๆ อย่างชัดเจน แต่มันก็ขัดกับจิตวิญญาณของเกม ยังคงขอแสดงความยินดีกับความคิดของคุณ!
Masclins

4

ช่างฟิต

บอทนี้ปรับปรุงรูปแบบและรวมกับนักเศรษฐศาสตร์ (รูปแบบและนักเศรษฐศาสตร์จะไม่เข้าร่วมอีกต่อไป)

การปรับปรุงรูปแบบคือตอนนี้บอทมองหาสองรูปแบบสองแบบ: คู่ต่อสู้มีปฏิกิริยากับการเล่นครั้งสุดท้ายของเขาและฝ่ายตรงข้ามโต้ตอบกับการเล่นครั้งสุดท้ายของฉัน จากนั้นประเมินการคาดคะเนทั้งสองเพื่อใช้อันที่เหมาะสมที่สุด

จากรูปแบบนั้นบอทมีความเป็นไปได้สำหรับ R, P และ S โดยคำนึงถึงและมูลค่าที่คาดหวังของการเล่นแต่ละครั้ง

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]

นี่คือรหัสเก่าสองรหัส

รูปแบบ (ไม่เล่น)

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

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]

นักเศรษฐศาสตร์ (ไม่เล่นอีกต่อไป)

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

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"])

4

Yggdrasil

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

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]})

โปรดลบความคิดเห็นที่ไม่ทำให้เข้าใจรหัสได้มากขึ้น
ชื่อที่แสดง

@SargeBorsch เสร็จแล้ว
PhiNotPi

1
@PhiNotPi ฉันรู้ว่าฉันโพสต์ไม่ จำกัด เวลา แต่ Yggdrasil ใช้เวลามากกว่าหนึ่งนาทีต่อคู่ต่อสู้แต่ละคน เป็นไปได้ไหมที่จะเพิ่มประสิทธิภาพสักเล็กน้อย?
Masclins

ใช่มันช้าเหลือทน
ชื่อที่แสดง

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

4

ต่อต้าน Repeater

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"

หยิบกระดาษในเทิร์นแรกหลังจากนั้นจะคืนสิ่งใดก็ตามที่คู่ต่อสู้ทำมากที่สุดโดยหยิบกระดาษในกรณีที่เสมอกัน

Copycat

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]

เพียงคัดลอกฝ่ายตรงข้ามที่ผ่านมา

ป้องกันต่อต้านโลภ

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"])

เลือกสิ่งที่สูญเสียไปกับทางเลือกที่หนักที่สุดของคู่ต่อสู้

ค่อนข้างหิว

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"])

3

ผู้ส่งสาร

def themessengerfunc (I, ทำ, ไม่, ต้องการ, สิ่งเหล่านี้, อาร์กิวเมนต์): return "P"

Rockstar

def rockstarfunc (I, ทำ, ไม่, ต้องการ, สิ่งเหล่านี้, อาร์กิวเมนต์): return "R"

ฆาตกร

def assassinfunc (I, ทำ, ไม่, ต้องการ, สิ่งเหล่านี้, อาร์กิวเมนต์): return "S"

คำอธิบาย

ตอนนี้คุณอาจคิดว่าบอทเหล่านี้โง่อย่างสิ้นเชิง

ไม่จริงทั้งหมดเหล่านี้ขึ้นอยู่กับความคิดของการสะสมโบนัสมากและศัตรูที่ทำผิดพลาดและได้รับการล้อมรอบ

ตอนนี้บอทเหล่านี้เล่นกันอย่างโลภมาก แต่ก็ง่ายกว่าและอย่าสุ่มเลือกจนกว่าพวกเขาจะได้รับอาวุธหนึ่งตัวพวกเขาติดอาวุธที่พวกเขาเลือก

สิ่งอื่นที่ควรทราบ: สิ่งเหล่านี้จะเอาชนะความโลภประมาณครึ่งเวลาวาดหนึ่งในสามของเวลาและเสียหนึ่งในหกของเวลา เมื่อพวกเขาชนะพวกเขาจะชนะมาก ทำไมนี้

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

สมมติว่าโลภไม่ได้แค่หยิบอาวุธที่ชนะผ่านโอกาสที่ยิ่งใหญ่เสมอไปซึ่งหมายความว่าโอกาสคือ:

1/3: {1/2 ชนะ (รวมทั้งหมด 1/6) 1/2 สูญเสีย (รวม 1/6) }

1/3 วาด

1/3 ชนะ

ดังนั้น: 1/3 โอกาสในการวาด, 1/6 โอกาสในการขาดทุน, 1/2 โอกาสในการชนะ

นี่อาจแสดงให้เห็นว่าคุณต้องทำหลายเกมหลายรอบ

สิ่งเหล่านี้ส่วนใหญ่จะได้รับความท้าทายกลิ้ง


3

เครื่องปฏิกรณ์

ทำให้การเล่นที่จะได้รับรางวัลในรอบก่อนหน้า

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"

1
คุณสามารถแทนที่ด้วยopp_history[len(opp_history)-1] opp_history[-1]
CalculatorFeline

3

เด็ก Artsy

บอทนี้ทำตัวเหมือนเด็กที่เล่นศิลปะและงานฝีมือจะเริ่มต้นด้วยกระดาษและใช้กระดาษหรือกรรไกรอย่างสุ่ม แต่จะไม่ใช้กรรไกรหลังจากหินหรือกรรไกรเพราะเธอต้องการใช้กรรไกรบนกระดาษ จะขว้างก้อนหินใส่ใครก็ตามที่ขว้างก้อนหินใส่เธอ

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"])

2

ที่นี่สามบอทฉันได้สร้างสำหรับการทดสอบ:


RandomBot

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

โลภ

เพียงเลือกตัวเลือกที่โหลดมากที่สุดของเขา

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

สมมติว่าฝ่ายตรงข้ามจะเล่นโลภและเล่นทางเลือกที่ชนะ

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"])

1

ไม่หิว

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"])

นี่คือการผกผันของโลภอย่างแท้จริงมันเลือกตัวเลือกจุดต่ำสุดที่มีอยู่


1

ใช้สิ่งที่ชื่นชอบของฝ่ายตรงข้าม

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"])

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

// ฉันขโมยรหัสจากที่นี่


การชนะนั้นดี

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"])

ส่งกลับทางเลือกของผู้ชนะของรอบก่อนหน้า หากรอบก่อนหน้านั้นเสมอกันให้ทำการตรวจสอบรอบก่อนหน้าซ้ำ ถ้ามันเป็นความสัมพันธ์เท่านั้นหรือเป็นรอบแรกส่งคืนตัวเลือกแบบสุ่ม


1

สุดยอดของทั้งสองโลก

บอทนี้โดยทั่วไปจะรวม Anti-Greedy และ Greedy (ด้วยเหตุนี้ชื่อ)

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

นี่คือ Antigreedy ซึ่งโพสต์เป็นตัวอย่างแล้ว
Masclins

@AlbertMasclans เปลี่ยนเป็น bot อื่น
clismique

findสำหรับสตริง my_loadedและopp_loadedเป็นทั้งสองรายการ indexควรจะดีสำหรับสิ่งที่คุณต้องการ
Masclins

@AlbertMasclans อ๊ะคงตอนนี้แล้ว ขอบคุณสำหรับการจับ! ฉันหวังว่านี่จะไม่ใช่รายการที่ซ้ำกัน ... ฉันไม่ต้องการลบโพสต์นี้อีก
clismique

ไม่เป็นไรขอบคุณสำหรับการเล่น
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"

สุ่มเลือกระหว่างสามตัวเลือกในลักษณะที่สถิติของฝ่ายตรงข้ามไม่มีความชอบระหว่างการเคลื่อนไหวโดยคำนึงถึงคะแนนเท่าใด กล่าวอีกนัยหนึ่งโลภและไม่หิวควรมีคะแนนที่คาดหวังโดยเฉลี่ยเท่ากัน


1

Expectedbayes

แก้ไข: อัปเดตการจัดอันดับ

นี่คือการจัดอันดับสูงสุดใหม่หลังจากรวม Expectedbayes:

  • สถิติ 2func 91.89%
  • fitterfunc 85.65%
  • nashfunc 80.40%
  • weigherfunc 76.39%
  • คาดว่าจะได้รับ 73.33%
  • antirepeaterfunc 68.52%
  • ...

คำอธิบาย

(NB: โพสต์วันที่ 5/6/2560)

บอทนี้พยายามที่จะเพิ่มมูลค่าที่คาดหวังของการย้ายครั้งต่อไปโดย:

  • คำนวณความน่าจะเป็นสำหรับการเคลื่อนไหวในครั้งต่อไปของคู่ต่อสู้
  • ใช้ตัวเลขนั้นและโหลดเพื่อคำนวณค่าที่คาดไว้สำหรับ R, P และ S แต่ละตัว
  • การเลือกการเคลื่อนไหวที่มีค่าสูงสุดที่คาดไว้
  • สุ่มเลือกค่าหากการทำนายล้มเหลว

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

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

มันชนะอย่างง่ายดายต่อบ็อตที่มักจะเป็นตัวเลือกเดียวกัน น่าแปลกที่มันค่อนข้างมีประสิทธิภาพกับบอทสุ่มที่มีอัตราการชนะ 93% (ฉันเชื่อว่านี่เป็นเพราะความจริงที่ว่ามัน จำกัด จำนวนคะแนนของคู่ต่อสู้ของเขาที่จะได้รับในขณะที่เพิ่มจำนวนคะแนนที่เป็นไปได้ในแต่ละรอบ)

ฉันได้ลองอย่างรวดเร็วด้วยการเลี้ยว 100 ครั้งและบอทในจำนวน จำกัด เท่านั้นและนี่คือสิ่งที่ฉันได้รับจาก result_standing:

  • randombotfunc 35
  • nashbotfunc 333
  • greedyfunc 172
  • antigreedyfunc 491
  • themessengerfunc 298
  • rockstarfunc 200
  • statistician2func 748
  • fitterfunc 656
  • expectedbayesfunc, 601

ซึ่งไม่เลวนั่น!

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

ยินดีต้อนรับสู่ PPCG และโพสต์แรกที่ดี!
Zacharý

ขอบคุณมาก! ฉันต้องการเข้าร่วม PPCG เป็นเวลานาน ตอนนี้มันได้รับการแก้ไข!
lesibius


0

ทั้งมวล

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)

อัลกอริทึมการแข่งขันจำนวนมากลงคะแนนในทางออกที่ดีที่สุด

แลกเปลี่ยน

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)

ทำการสุ่มย้ายโดยไม่ต้องทำซ้ำการย้ายครั้งสุดท้าย


0

blodsocer

socery

ฉันให้การแก้ไขกับมันดังนั้นจึงน่าจะได้ผลในขณะนี้ฉันหวังว่า

ฉันทำบางสิ่งบางอย่างยุ่งอีกครั้งดังนั้นฉันจึงลบและยกเลิกการลบ ฉันทำให้ยุ่งมาก

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]

1
if opp_history[1] == "S": return "R" elif opp_history[1] == "R": return "R" else: return "P"นี่เป็นสังคมแบบไหน?
Robert Fraser

@DestructibleLemon สิ่งนี้หารด้วย 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 ฉันคงที่
เลมอนที่ถูกทำลายได้

@RobertFraser มีความโดดเด่นตรงไหนเกี่ยวกับข้อมูลโค้ดนั้น
เลมอนที่ถูกทำลายได้

@DestructibleLemon ฉันไม่แน่ใจว่าสิ่งที่คุณต้องการทำที่นี่: "RPS"[my_loaded.index(max(my_loaded))+len(my_history)%2]แต่มันมองออกไปจากช่วง
Masclins

0

ถ่วงน้ำหนักแบบสุ่ม

เช่นเดียวกับ RandomBot แต่เลือกเพียง 2 ครั้งในการโยนแต่ละครั้งที่เรียกใช้ บางครั้งจะเอาชนะ Rockstar หรือ Assassin แต่จะเพิ่มคะแนนของอีกฝ่ายหนึ่ง (เช่นถ้ามันตี Rockstar มันจะทำให้ Assassin เพิ่มระดับ)

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)

0

นักจิตวิทยาโลภ

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

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))]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.