570 lines
27 KiB
Python
570 lines
27 KiB
Python
|
# -*- coding: utf-8 -*-
|
|||
|
# Created by: Raf
|
|||
|
# Modify by: Vincentzyx
|
|||
|
|
|||
|
import GameHelper as gh
|
|||
|
from GameHelper import GameHelper
|
|||
|
import os
|
|||
|
import sys
|
|||
|
import time
|
|||
|
import threading
|
|||
|
import pyautogui
|
|||
|
import win32gui
|
|||
|
from PIL import Image
|
|||
|
import multiprocessing as mp
|
|||
|
|
|||
|
from PyQt5 import QtGui, QtWidgets, QtCore
|
|||
|
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsItem, QGraphicsPixmapItem, QInputDialog, QMessageBox
|
|||
|
from PyQt5.QtGui import QPixmap, QIcon
|
|||
|
from PyQt5.QtCore import QTime, QEventLoop
|
|||
|
from MainWindow import Ui_Form
|
|||
|
|
|||
|
from douzero.env.game import GameEnv
|
|||
|
from douzero.evaluation.deep_agent import DeepAgent
|
|||
|
|
|||
|
import BidModel
|
|||
|
import LandlordModel
|
|||
|
import FarmerModel
|
|||
|
|
|||
|
EnvCard2RealCard = {3: '3', 4: '4', 5: '5', 6: '6', 7: '7',
|
|||
|
8: '8', 9: '9', 10: 'T', 11: 'J', 12: 'Q',
|
|||
|
13: 'K', 14: 'A', 17: '2', 20: 'X', 30: 'D'}
|
|||
|
|
|||
|
RealCard2EnvCard = {'3': 3, '4': 4, '5': 5, '6': 6, '7': 7,
|
|||
|
'8': 8, '9': 9, 'T': 10, 'J': 11, 'Q': 12,
|
|||
|
'K': 13, 'A': 14, '2': 17, 'X': 20, 'D': 30}
|
|||
|
|
|||
|
AllEnvCard = [3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
|
|||
|
8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12,
|
|||
|
12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 17, 17, 17, 17, 20, 30]
|
|||
|
|
|||
|
AllCards = ['rD', 'bX', 'b2', 'r2', 'bA', 'rA', 'bK', 'rK', 'bQ', 'rQ', 'bJ', 'rJ', 'bT', 'rT',
|
|||
|
'b9', 'r9', 'b8', 'r8', 'b7', 'r7', 'b6', 'r6', 'b5', 'r5', 'b4', 'r4', 'b3', 'r3']
|
|||
|
|
|||
|
helper = GameHelper()
|
|||
|
helper.ScreenZoomRate = 1.25 # 请修改屏幕缩放比
|
|||
|
|
|||
|
class MyPyQT_Form(QtWidgets.QWidget, Ui_Form):
|
|||
|
def __init__(self):
|
|||
|
super(MyPyQT_Form, self).__init__()
|
|||
|
self.setupUi(self)
|
|||
|
self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint | # 使能最小化按钮
|
|||
|
QtCore.Qt.WindowCloseButtonHint) # 窗体总在最前端 QtCore.Qt.WindowStaysOnTopHint
|
|||
|
self.setFixedSize(self.width(), self.height()) # 固定窗体大小
|
|||
|
# self.setWindowIcon(QIcon('pics/favicon.ico'))
|
|||
|
window_pale = QtGui.QPalette()
|
|||
|
# window_pale.setBrush(self.backgroundRole(), QtGui.QBrush(QtGui.QPixmap("pics/bg.png")))
|
|||
|
self.setPalette(window_pale)
|
|||
|
self.Players = [self.RPlayer, self.Player, self.LPlayer]
|
|||
|
self.counter = QTime()
|
|||
|
|
|||
|
# 参数
|
|||
|
self.MyConfidence = 0.95 # 我的牌的置信度
|
|||
|
self.OtherConfidence = 0.9 # 别人的牌的置信度
|
|||
|
self.WhiteConfidence = 0.95 # 检测白块的置信度
|
|||
|
self.LandlordFlagConfidence = 0.9 # # 检测地主标志的置信度
|
|||
|
self.ThreeLandlordCardsConfidence = 0.9 # 检测地主底牌的置信度
|
|||
|
self.PassConfidence = 0.85
|
|||
|
self.WaitTime = 1 # 等待状态稳定延时
|
|||
|
self.MyFilter = 40 # 我的牌检测结果过滤参数
|
|||
|
self.OtherFilter = 25 # 别人的牌检测结果过滤参数
|
|||
|
self.SleepTime = 0.1 # 循环中睡眠时间
|
|||
|
self.RunGame = False
|
|||
|
self.AutoPlay = False
|
|||
|
# 坐标
|
|||
|
self.MyHandCardsPos = (250, 764, 1141, 70) # 我的截图区域
|
|||
|
self.LPlayedCardsPos = (463, 355, 380, 250) # 左边截图区域
|
|||
|
self.RPlayedCardsPos = (946, 355, 380, 250) # 右边截图区域
|
|||
|
self.LandlordFlagPos = [(1281, 276, 110, 140), (267, 695, 110, 140), (424, 237, 110, 140)] # 地主标志截图区域(右-我-左)
|
|||
|
self.ThreeLandlordCardsPos = (763, 37, 287, 136) # 地主底牌截图区域,resize成349x168
|
|||
|
self.PassBtnPos = (686, 659, 419, 100)
|
|||
|
self.GeneralBtnPos = (616, 631, 576, 117)
|
|||
|
# 信号量
|
|||
|
self.shouldExit = 0 # 通知上一轮记牌结束
|
|||
|
self.canRecord = threading.Lock() # 开始记牌
|
|||
|
self.card_play_model_path_dict = {
|
|||
|
'landlord': "baselines/douzero_ADP/landlord.ckpt",
|
|||
|
'landlord_up': "baselines/douzero_ADP/landlord_up.ckpt",
|
|||
|
'landlord_down': "baselines/douzero_ADP/landlord_down.ckpt"
|
|||
|
}
|
|||
|
# cards = self.find_three_landlord_cards(self.ThreeLandlordCardsPos)
|
|||
|
# print(cards)
|
|||
|
# exit()
|
|||
|
|
|||
|
def init_display(self):
|
|||
|
self.WinRate.setText("评分")
|
|||
|
self.InitCard.setText("开始")
|
|||
|
self.UserHandCards.setText("手牌")
|
|||
|
self.LPlayedCard.setText("上家出牌区域")
|
|||
|
self.RPlayedCard.setText("下家出牌区域")
|
|||
|
self.PredictedCard.setText("AI出牌区域")
|
|||
|
self.ThreeLandlordCards.setText("地主牌")
|
|||
|
self.SwitchMode.setText("自动" if self.AutoPlay else "单局")
|
|||
|
for player in self.Players:
|
|||
|
player.setStyleSheet('background-color: rgba(255, 0, 0, 0);')
|
|||
|
|
|||
|
def switch_mode(self):
|
|||
|
self.AutoPlay = not self.AutoPlay
|
|||
|
self.SwitchMode.setText("自动" if self.AutoPlay else "单局")
|
|||
|
|
|||
|
def init_cards(self):
|
|||
|
self.RunGame = True
|
|||
|
GameHelper.Interrupt = False
|
|||
|
self.init_display()
|
|||
|
# 玩家手牌
|
|||
|
self.user_hand_cards_real = ""
|
|||
|
self.user_hand_cards_env = []
|
|||
|
# 其他玩家出牌
|
|||
|
self.other_played_cards_real = ""
|
|||
|
self.other_played_cards_env = []
|
|||
|
# 其他玩家手牌(整副牌减去玩家手牌,后续再减掉历史出牌)
|
|||
|
self.other_hand_cards = []
|
|||
|
# 三张底牌
|
|||
|
self.three_landlord_cards_real = ""
|
|||
|
self.three_landlord_cards_env = []
|
|||
|
# 玩家角色代码:0-地主上家, 1-地主, 2-地主下家
|
|||
|
self.user_position_code = None
|
|||
|
self.user_position = ""
|
|||
|
# 开局时三个玩家的手牌
|
|||
|
self.card_play_data_list = {}
|
|||
|
# 出牌顺序:0-玩家出牌, 1-玩家下家出牌, 2-玩家上家出牌
|
|||
|
self.play_order = 0
|
|||
|
|
|||
|
self.env = None
|
|||
|
|
|||
|
# 识别玩家手牌
|
|||
|
self.user_hand_cards_real = self.find_my_cards(self.MyHandCardsPos)
|
|||
|
self.UserHandCards.setText(self.user_hand_cards_real)
|
|||
|
self.user_hand_cards_env = [RealCard2EnvCard[c] for c in list(self.user_hand_cards_real)]
|
|||
|
# 识别三张底牌
|
|||
|
self.three_landlord_cards_real = self.find_three_landlord_cards(self.ThreeLandlordCardsPos)
|
|||
|
self.ThreeLandlordCards.setText("底牌:" + self.three_landlord_cards_real)
|
|||
|
self.three_landlord_cards_env = [RealCard2EnvCard[c] for c in list(self.three_landlord_cards_real)]
|
|||
|
for testCount in range(1, 5):
|
|||
|
if len(self.three_landlord_cards_env) > 3:
|
|||
|
self.ThreeLandlordCardsConfidence += 0.05
|
|||
|
elif len(self.three_landlord_cards_env) < 3:
|
|||
|
self.ThreeLandlordCardsConfidence -= 0.05
|
|||
|
else:
|
|||
|
break
|
|||
|
self.three_landlord_cards_real = self.find_three_landlord_cards(self.ThreeLandlordCardsPos)
|
|||
|
self.ThreeLandlordCards.setText("底牌:" + self.three_landlord_cards_real)
|
|||
|
self.three_landlord_cards_env = [RealCard2EnvCard[c] for c in list(self.three_landlord_cards_real)]
|
|||
|
# 识别玩家的角色
|
|||
|
self.user_position_code = self.find_landlord(self.LandlordFlagPos)
|
|||
|
if self.user_position_code is None:
|
|||
|
items = ("地主上家", "地主", "地主下家")
|
|||
|
item, okPressed = QInputDialog.getItem(self, "选择角色", "未识别到地主,请手动选择角色:", items, 0, False)
|
|||
|
if okPressed and item:
|
|||
|
self.user_position_code = items.index(item)
|
|||
|
else:
|
|||
|
return
|
|||
|
self.user_position = ['landlord_up', 'landlord', 'landlord_down'][self.user_position_code]
|
|||
|
for player in self.Players:
|
|||
|
player.setStyleSheet('background-color: rgba(255, 0, 0, 0);')
|
|||
|
self.Players[self.user_position_code].setStyleSheet('background-color: rgba(255, 0, 0, 0.1);')
|
|||
|
|
|||
|
# 整副牌减去玩家手上的牌,就是其他人的手牌,再分配给另外两个角色(如何分配对AI判断没有影响)
|
|||
|
for i in set(AllEnvCard):
|
|||
|
self.other_hand_cards.extend([i] * (AllEnvCard.count(i) - self.user_hand_cards_env.count(i)))
|
|||
|
self.card_play_data_list.update({
|
|||
|
'three_landlord_cards': self.three_landlord_cards_env,
|
|||
|
['landlord_up', 'landlord', 'landlord_down'][(self.user_position_code + 0) % 3]:
|
|||
|
self.user_hand_cards_env,
|
|||
|
['landlord_up', 'landlord', 'landlord_down'][(self.user_position_code + 1) % 3]:
|
|||
|
self.other_hand_cards[0:17] if (self.user_position_code + 1) % 3 != 1 else self.other_hand_cards[17:],
|
|||
|
['landlord_up', 'landlord', 'landlord_down'][(self.user_position_code + 2) % 3]:
|
|||
|
self.other_hand_cards[0:17] if (self.user_position_code + 1) % 3 == 1 else self.other_hand_cards[17:]
|
|||
|
})
|
|||
|
print("开始对局")
|
|||
|
print("手牌:",self.user_hand_cards_real)
|
|||
|
print("地主牌:",self.three_landlord_cards_real)
|
|||
|
# 生成手牌结束,校验手牌数量
|
|||
|
if len(self.card_play_data_list["three_landlord_cards"]) != 3:
|
|||
|
QMessageBox.critical(self, "底牌识别出错", "底牌必须是3张!", QMessageBox.Yes, QMessageBox.Yes)
|
|||
|
self.init_display()
|
|||
|
return
|
|||
|
if len(self.card_play_data_list["landlord_up"]) != 17 or \
|
|||
|
len(self.card_play_data_list["landlord_down"]) != 17 or \
|
|||
|
len(self.card_play_data_list["landlord"]) != 20:
|
|||
|
QMessageBox.critical(self, "手牌识别出错", "初始手牌数目有误", QMessageBox.Yes, QMessageBox.Yes)
|
|||
|
self.init_display()
|
|||
|
return
|
|||
|
# 得到出牌顺序
|
|||
|
self.play_order = 0 if self.user_position == "landlord" else 1 if self.user_position == "landlord_up" else 2
|
|||
|
|
|||
|
# 创建一个代表玩家的AI
|
|||
|
ai_players = [0, 0]
|
|||
|
ai_players[0] = self.user_position
|
|||
|
ai_players[1] = DeepAgent(self.user_position, self.card_play_model_path_dict[self.user_position])
|
|||
|
|
|||
|
self.env = GameEnv(ai_players)
|
|||
|
try:
|
|||
|
self.start()
|
|||
|
except:
|
|||
|
self.stop()
|
|||
|
|
|||
|
def sleep(self, ms):
|
|||
|
self.counter.restart()
|
|||
|
while self.counter.elapsed() < ms:
|
|||
|
QtWidgets.QApplication.processEvents(QEventLoop.AllEvents, 50)
|
|||
|
|
|||
|
def start(self):
|
|||
|
self.env.card_play_init(self.card_play_data_list)
|
|||
|
print("开始出牌\n")
|
|||
|
while not self.env.game_over:
|
|||
|
# 玩家出牌时就通过智能体获取action,否则通过识别获取其他玩家出牌
|
|||
|
if self.play_order == 0:
|
|||
|
self.PredictedCard.setText("...")
|
|||
|
action_message = self.env.step(self.user_position)
|
|||
|
# 更新界面
|
|||
|
self.UserHandCards.setText("手牌:" + str(''.join(
|
|||
|
[EnvCard2RealCard[c] for c in self.env.info_sets[self.user_position].player_hand_cards]))[::-1])
|
|||
|
|
|||
|
self.PredictedCard.setText(action_message["action"] if action_message["action"] else "不出")
|
|||
|
self.WinRate.setText("评分:" + action_message["win_rate"])
|
|||
|
print("\n手牌:", str(''.join(
|
|||
|
[EnvCard2RealCard[c] for c in self.env.info_sets[self.user_position].player_hand_cards])))
|
|||
|
print("出牌:", action_message["action"] if action_message["action"] else "不出", ", 胜率:",
|
|||
|
action_message["win_rate"])
|
|||
|
if action_message["action"] == "":
|
|||
|
helper.ClickOnImage("pass_btn", region=self.PassBtnPos)
|
|||
|
else:
|
|||
|
helper.SelectCards(action_message["action"])
|
|||
|
tryCount = 20
|
|||
|
result = helper.LocateOnScreen("play_card", region=self.PassBtnPos, confidence=0.85)
|
|||
|
while result is None and tryCount > 0:
|
|||
|
if not self.RunGame:
|
|||
|
break
|
|||
|
print("等待出牌按钮")
|
|||
|
self.detect_start_btn()
|
|||
|
tryCount -= 1
|
|||
|
result = helper.LocateOnScreen("play_card", region=self.PassBtnPos, confidence=0.85)
|
|||
|
self.sleep(100)
|
|||
|
helper.ClickOnImage("play_card", region=self.PassBtnPos, confidence=0.85)
|
|||
|
self.sleep(2200)
|
|||
|
self.detect_start_btn()
|
|||
|
self.play_order = 1
|
|||
|
elif self.play_order == 1:
|
|||
|
self.RPlayedCard.setText("...")
|
|||
|
pass_flag = helper.LocateOnScreen('pass',
|
|||
|
region=self.RPlayedCardsPos,
|
|||
|
confidence=self.PassConfidence)
|
|||
|
self.detect_start_btn()
|
|||
|
while self.RunGame and self.have_white(self.RPlayedCardsPos) == 0 and pass_flag is None:
|
|||
|
print("等待下家出牌")
|
|||
|
self.sleep(100)
|
|||
|
pass_flag = helper.LocateOnScreen('pass', region=self.RPlayedCardsPos,
|
|||
|
confidence=self.PassConfidence)
|
|||
|
self.detect_start_btn()
|
|||
|
self.sleep(200)
|
|||
|
# 未找到"不出"
|
|||
|
if pass_flag is None:
|
|||
|
# 识别下家出牌
|
|||
|
self.RPlayedCard.setText("等待动画")
|
|||
|
self.sleep(1200)
|
|||
|
self.RPlayedCard.setText("识别中")
|
|||
|
self.other_played_cards_real = self.find_other_cards(self.RPlayedCardsPos)
|
|||
|
print("下家出牌", self.other_played_cards_real)
|
|||
|
self.sleep(500)
|
|||
|
# 找到"不出"
|
|||
|
else:
|
|||
|
self.other_played_cards_real = ""
|
|||
|
print("\n下家出牌:", self.other_played_cards_real)
|
|||
|
self.other_played_cards_env = [RealCard2EnvCard[c] for c in list(self.other_played_cards_real)]
|
|||
|
self.env.step(self.user_position, self.other_played_cards_env)
|
|||
|
# 更新界面
|
|||
|
self.RPlayedCard.setText(self.other_played_cards_real if self.other_played_cards_real else "不出")
|
|||
|
self.play_order = 2
|
|||
|
self.sleep(500)
|
|||
|
elif self.play_order == 2:
|
|||
|
self.LPlayedCard.setText("...")
|
|||
|
self.detect_start_btn()
|
|||
|
pass_flag = helper.LocateOnScreen('pass', region=self.LPlayedCardsPos,
|
|||
|
confidence=self.PassConfidence)
|
|||
|
while self.RunGame and self.have_white(self.LPlayedCardsPos) == 0 and pass_flag is None:
|
|||
|
print("等待上家出牌")
|
|||
|
self.detect_start_btn()
|
|||
|
self.sleep(100)
|
|||
|
pass_flag = helper.LocateOnScreen('pass', region=self.LPlayedCardsPos,
|
|||
|
confidence=self.PassConfidence)
|
|||
|
self.sleep(200)
|
|||
|
# 不出
|
|||
|
# 未找到"不出"
|
|||
|
if pass_flag is None:
|
|||
|
# 识别上家出牌
|
|||
|
self.LPlayedCard.setText("等待动画")
|
|||
|
self.sleep(1200)
|
|||
|
self.LPlayedCard.setText("识别中")
|
|||
|
self.other_played_cards_real = self.find_other_cards(self.LPlayedCardsPos)
|
|||
|
# 找到"不出"
|
|||
|
else:
|
|||
|
self.other_played_cards_real = ""
|
|||
|
print("\n上家出牌:", self.other_played_cards_real)
|
|||
|
self.other_played_cards_env = [RealCard2EnvCard[c] for c in list(self.other_played_cards_real)]
|
|||
|
self.env.step(self.user_position, self.other_played_cards_env)
|
|||
|
self.play_order = 0
|
|||
|
# 更新界面
|
|||
|
self.LPlayedCard.setText(self.other_played_cards_real if self.other_played_cards_real else "不出")
|
|||
|
self.sleep(500)
|
|||
|
else:
|
|||
|
pass
|
|||
|
self.sleep(100)
|
|||
|
|
|||
|
print("{}胜,本局结束!\n".format("农民" if self.env.winner == "farmer" else "地主"))
|
|||
|
# QMessageBox.information(self, "本局结束", "{}胜!".format("农民" if self.env.winner == "farmer" else "地主"),
|
|||
|
# QMessageBox.Yes, QMessageBox.Yes)
|
|||
|
self.detect_start_btn()
|
|||
|
|
|||
|
def find_landlord(self, landlord_flag_pos):
|
|||
|
for pos in landlord_flag_pos:
|
|||
|
result = helper.LocateOnScreen("landlord_words", region=pos,
|
|||
|
confidence=self.LandlordFlagConfidence)
|
|||
|
if result is not None:
|
|||
|
return landlord_flag_pos.index(pos)
|
|||
|
return None
|
|||
|
|
|||
|
def detect_start_btn(self):
|
|||
|
result = helper.LocateOnScreen("change_player_btn", region=(667, 741, 934, 404))
|
|||
|
if result is not None:
|
|||
|
self.RunGame = False
|
|||
|
self.stop()
|
|||
|
result = helper.LocateOnScreen("yes_btn", region=(680, 661, 435, 225))
|
|||
|
if result is not None:
|
|||
|
helper.ClickOnImage("yes_btn", region=(680, 661, 435, 225))
|
|||
|
self.sleep(1000)
|
|||
|
result = helper.LocateOnScreen("get_award_btn", region=(680, 661, 435, 225))
|
|||
|
if result is not None:
|
|||
|
helper.ClickOnImage("get_award_btn", region=(680, 661, 435, 225))
|
|||
|
self.sleep(1000)
|
|||
|
result = helper.LocateOnScreen("yes_btn_sm", region=(669, 583, 468, 100))
|
|||
|
if result is not None:
|
|||
|
helper.ClickOnImage("yes_btn_sm", region=(669, 583, 468, 100))
|
|||
|
self.sleep(200)
|
|||
|
|
|||
|
|
|||
|
def find_three_landlord_cards(self, pos):
|
|||
|
img, _ = helper.Screenshot()
|
|||
|
img = img.crop((pos[0], pos[1], pos[0] + pos[2], pos[1] + pos[3]))
|
|||
|
img = img.resize((349, 168))
|
|||
|
three_landlord_cards_real = ""
|
|||
|
for card in AllCards:
|
|||
|
result = pyautogui.locateAll(needleImage=helper.Pics['o' + card], haystackImage=img,
|
|||
|
confidence=self.ThreeLandlordCardsConfidence)
|
|||
|
three_landlord_cards_real += card[1] * self.cards_filter(list(result), self.OtherFilter)
|
|||
|
if len(three_landlord_cards_real) > 3:
|
|||
|
three_landlord_cards_real = ""
|
|||
|
for card in AllCards:
|
|||
|
result = pyautogui.locateAll(needleImage=helper.Pics['o' + card], haystackImage=img,
|
|||
|
confidence=self.ThreeLandlordCardsConfidence + 0.05)
|
|||
|
three_landlord_cards_real += card[1] * self.cards_filter(list(result), self.OtherFilter)
|
|||
|
if len(three_landlord_cards_real) < 3:
|
|||
|
three_landlord_cards_real = ""
|
|||
|
for card in AllCards:
|
|||
|
result = pyautogui.locateAll(needleImage=helper.Pics['o' + card], haystackImage=img,
|
|||
|
confidence=self.ThreeLandlordCardsConfidence + 0.1)
|
|||
|
three_landlord_cards_real += card[1] * self.cards_filter(list(result), self.OtherFilter)
|
|||
|
return three_landlord_cards_real
|
|||
|
|
|||
|
def find_my_cards(self, pos):
|
|||
|
user_hand_cards_real = ""
|
|||
|
img, _ = helper.Screenshot()
|
|||
|
cards, _ = helper.GetCards(img)
|
|||
|
for c in cards:
|
|||
|
user_hand_cards_real += c[0]
|
|||
|
# for card in AllCards:
|
|||
|
# result = pyautogui.locateAll(needleImage=helper.Pics['m'+card], haystackImage=img, confidence=self.MyConfidence)
|
|||
|
# user_hand_cards_real += card[1] * self.cards_filter(list(result), self.MyFilter)
|
|||
|
return user_hand_cards_real
|
|||
|
|
|||
|
def find_other_cards(self, pos):
|
|||
|
other_played_cards_real = ""
|
|||
|
self.sleep(500)
|
|||
|
img, _ = helper.Screenshot(region=pos)
|
|||
|
for card in AllCards:
|
|||
|
result = pyautogui.locateAll(needleImage=helper.Pics['o' + card], haystackImage=img,
|
|||
|
confidence=self.OtherConfidence)
|
|||
|
other_played_cards_real += card[1] * self.cards_filter(list(result), self.OtherFilter)
|
|||
|
return other_played_cards_real
|
|||
|
|
|||
|
def cards_filter(self, location, distance): # 牌检测结果滤波
|
|||
|
if len(location) == 0:
|
|||
|
return 0
|
|||
|
locList = [location[0][0]]
|
|||
|
count = 1
|
|||
|
for e in location:
|
|||
|
flag = 1 # “是新的”标志
|
|||
|
for have in locList:
|
|||
|
if abs(e[0] - have) <= distance:
|
|||
|
flag = 0
|
|||
|
break
|
|||
|
if flag:
|
|||
|
count += 1
|
|||
|
locList.append(e[0])
|
|||
|
return count
|
|||
|
|
|||
|
def have_white(self, pos): # 是否有白块
|
|||
|
img, _ = helper.Screenshot()
|
|||
|
result = pyautogui.locate(needleImage=helper.Pics["white"], haystackImage=img,
|
|||
|
region=pos, confidence=self.WhiteConfidence)
|
|||
|
if result is None:
|
|||
|
return 0
|
|||
|
else:
|
|||
|
return 1
|
|||
|
|
|||
|
def stop(self):
|
|||
|
try:
|
|||
|
self.RunGame = False
|
|||
|
self.env.game_over = True
|
|||
|
self.env.reset()
|
|||
|
self.init_display()
|
|||
|
self.PreWinrate.setText("局前预估胜率:")
|
|||
|
self.BidWinrate.setText("叫牌预估胜率:")
|
|||
|
except AttributeError as e:
|
|||
|
pass
|
|||
|
if self.AutoPlay:
|
|||
|
play_btn = helper.LocateOnScreen("change_player_btn", region=(667, 741, 934, 404))
|
|||
|
while play_btn is None and self.AutoPlay:
|
|||
|
play_btn = helper.LocateOnScreen("change_player_btn", region=(667, 741, 934, 404))
|
|||
|
self.sleep(100)
|
|||
|
if play_btn is not None:
|
|||
|
helper.LeftClick((play_btn[0], play_btn[1]))
|
|||
|
self.beforeStart()
|
|||
|
|
|||
|
def beforeStart(self):
|
|||
|
GameHelper.Interrupt = True
|
|||
|
thresholds = [
|
|||
|
[75, 60],
|
|||
|
[85, 70]
|
|||
|
]
|
|||
|
while True:
|
|||
|
outterBreak = False
|
|||
|
jiaodizhu_btn = helper.LocateOnScreen("jiaodizhu_btn", region=(765, 663, 116, 50))
|
|||
|
qiangdizhu_btn = helper.LocateOnScreen("qiangdizhu_btn", region=(783, 663, 116, 50))
|
|||
|
jiabei_btn = helper.LocateOnScreen("jiabei_btn", region=self.GeneralBtnPos)
|
|||
|
self.detect_start_btn()
|
|||
|
while jiaodizhu_btn is None and qiangdizhu_btn is None and jiabei_btn is None:
|
|||
|
self.detect_start_btn()
|
|||
|
print("等待加倍或叫地主")
|
|||
|
self.sleep(100)
|
|||
|
jiaodizhu_btn = helper.LocateOnScreen("jiaodizhu_btn", region=(765, 663, 116, 50))
|
|||
|
qiangdizhu_btn = helper.LocateOnScreen("qiangdizhu_btn", region=(783, 663, 116, 50))
|
|||
|
jiabei_btn = helper.LocateOnScreen("jiabei_btn", region=self.GeneralBtnPos)
|
|||
|
if jiabei_btn is None:
|
|||
|
img, _ = helper.Screenshot()
|
|||
|
cards, _ = helper.GetCards(img)
|
|||
|
cards_str = "".join([card[0] for card in cards])
|
|||
|
win_rate = BidModel.predict(cards_str)
|
|||
|
print("预计叫地主胜率:", win_rate)
|
|||
|
self.BidWinrate.setText("叫牌预估胜率:" + str(round(win_rate, 2)) + "%")
|
|||
|
is_stolen = 0
|
|||
|
if jiaodizhu_btn is not None:
|
|||
|
if win_rate > 55:
|
|||
|
helper.ClickOnImage("jiaodizhu_btn", region=(765, 663, 116, 50), confidence=0.9)
|
|||
|
else:
|
|||
|
helper.ClickOnImage("bujiao_btn", region=self.GeneralBtnPos)
|
|||
|
elif qiangdizhu_btn is not None:
|
|||
|
is_stolen = 1
|
|||
|
if win_rate > 60:
|
|||
|
helper.ClickOnImage("qiangdizhu_btn", region=(783, 663, 116, 50), confidence=0.9)
|
|||
|
else:
|
|||
|
helper.ClickOnImage("buqiang_btn", region=self.GeneralBtnPos)
|
|||
|
else:
|
|||
|
pass
|
|||
|
else:
|
|||
|
llcards = self.find_three_landlord_cards(self.ThreeLandlordCardsPos)
|
|||
|
print("地主牌:", llcards)
|
|||
|
img, _ = helper.Screenshot()
|
|||
|
cards, _ = helper.GetCards(img)
|
|||
|
cards_str = "".join([card[0] for card in cards])
|
|||
|
if len(cards_str) == 20:
|
|||
|
win_rate = LandlordModel.predict(cards_str)
|
|||
|
self.PreWinrate.setText("局前预估胜率:" + str(round(win_rate, 2)) + "%")
|
|||
|
print("预估地主胜率:", win_rate)
|
|||
|
else:
|
|||
|
user_position_code = self.find_landlord(self.LandlordFlagPos)
|
|||
|
user_position = "up"
|
|||
|
while user_position_code is None:
|
|||
|
user_position_code = self.find_landlord(self.LandlordFlagPos)
|
|||
|
self.sleep(50)
|
|||
|
user_position = ['up', 'landlord', 'down'][user_position_code]
|
|||
|
win_rate = FarmerModel.predict(cards_str, llcards, user_position) - 5
|
|||
|
print("预估农民胜率:", win_rate)
|
|||
|
self.PreWinrate.setText("局前预估胜率:" + str(round(win_rate, 2)) + "%")
|
|||
|
if win_rate > thresholds[is_stolen][0]:
|
|||
|
chaojijiabei_btn = helper.LocateOnScreen("chaojijiabei_btn", region=self.GeneralBtnPos)
|
|||
|
if chaojijiabei_btn is not None:
|
|||
|
helper.ClickOnImage("chaojijiabei_btn", region=self.GeneralBtnPos)
|
|||
|
else:
|
|||
|
helper.ClickOnImage("jiabei_btn", region=self.GeneralBtnPos)
|
|||
|
elif win_rate > thresholds[is_stolen][1]:
|
|||
|
helper.ClickOnImage("jiabei_btn", region=self.GeneralBtnPos)
|
|||
|
else:
|
|||
|
helper.ClickOnImage("bujiabei_btn", region=self.GeneralBtnPos)
|
|||
|
outterBreak = True
|
|||
|
break
|
|||
|
if outterBreak:
|
|||
|
break
|
|||
|
|
|||
|
llcards = self.find_three_landlord_cards(self.ThreeLandlordCardsPos)
|
|||
|
while len(llcards) != 3:
|
|||
|
print("等待地主牌", llcards)
|
|||
|
self.sleep(100)
|
|||
|
llcards = self.find_three_landlord_cards(self.ThreeLandlordCardsPos)
|
|||
|
|
|||
|
self.sleep(4000)
|
|||
|
self.init_cards()
|
|||
|
|
|||
|
|
|||
|
if __name__ == '__main__':
|
|||
|
app = QtWidgets.QApplication(sys.argv)
|
|||
|
app.setStyleSheet("""
|
|||
|
QPushButton{
|
|||
|
text-align : center;
|
|||
|
background-color : white;
|
|||
|
font: bold;
|
|||
|
border-color: gray;
|
|||
|
border-width: 2px;
|
|||
|
border-radius: 10px;
|
|||
|
padding: 6px;
|
|||
|
height : 14px;
|
|||
|
border-style: outset;
|
|||
|
font : 14px;
|
|||
|
}
|
|||
|
QPushButton:hover{
|
|||
|
background-color : light gray;
|
|||
|
}
|
|||
|
QPushButton:pressed{
|
|||
|
text-align : center;
|
|||
|
background-color : gray;
|
|||
|
font: bold;
|
|||
|
border-color: gray;
|
|||
|
border-width: 2px;
|
|||
|
border-radius: 10px;
|
|||
|
padding: 6px;
|
|||
|
height : 14px;
|
|||
|
border-style: outset;
|
|||
|
font : 14px;
|
|||
|
padding-left:9px;
|
|||
|
padding-top:9px;
|
|||
|
}
|
|||
|
QComboBox{
|
|||
|
background:transparent;
|
|||
|
border: 1px solid rgba(200, 200, 200, 100);
|
|||
|
font-weight: bold;
|
|||
|
}
|
|||
|
QComboBox:drop-down{
|
|||
|
border: 0px;
|
|||
|
}
|
|||
|
QComboBox QAbstractItemView:item{
|
|||
|
height: 30px;
|
|||
|
}
|
|||
|
QLabel{
|
|||
|
background:transparent;
|
|||
|
font-weight: bold;
|
|||
|
}
|
|||
|
""")
|
|||
|
my_pyqt_form = MyPyQT_Form()
|
|||
|
my_pyqt_form.show()
|
|||
|
sys.exit(app.exec_())
|