代码不全,但是函数可以复用
--
-- Author: baiyufei
-- Date: 2022-07-13
-- 跑得快AI
--
local commonfunc = require('lua.base.commonfunc')
require('lua.game.AI.dz')
require('lua.base.bit')
local Poker = require('lua.game.paodekuai.poker')
local aipaodekuai = class("aipaodekuai")
local TIME_SPACE = 1
local OVER_TIME = 10
local TUO_GUANG_TIMES = 2 --超时进入托管次数
function aipaodekuai:ctor(Table)
self.gameId = Table.mAction:getId()
self.base_gameId = GET_BASE_GAMEID(self.gameId)
self.Table = Table
self.upTime = os.time() + 5
self.stateTime = 0
self.lastPlayer = 0
end
function aipaodekuai:run()
local tmNow = os.time()
if(tmNow < self.upTime)then
return
end
local Table = self.Table
local playerOperator = Table:getOperator()
if(playerOperator and playerOperator:getRobot())then
TIME_SPACE = math.random(1,2)
else
TIME_SPACE = 1
end
self.upTime = tmNow + TIME_SPACE
--根据桌子的状态,判断机器人行为
local state = self.Table.mState:getState().state
print("-------j机器人----------- androidServiceMgr:run() --------- %, %, %, %", self.gameId, state, self.lastPlayer, self.stateTime)
--如果卡住了,就强制结束吧
if(Table.START <= state and playerOperator ~= nil)then
if(self.lastPlayer == playerOperator:getId())then
self.stateTime = self.stateTime + TIME_SPACE
else
self.stateTime = 0
self.lastPlayer = playerOperator:getId()
end
if(60 <= self.stateTime)then
--return Table:onFin()
end
end
--准备阶段
if(state == Table.START)then
self:ready()
return
end
if(not playerOperator or not self:checkAuto(playerOperator))then
return
end
--托管时间随机延迟
if not playerOperator:getRobot() and playerOperator:getTuoGuan() and self.stateTime < math.random(1,2) then
return
end
--玩家打牌阶段
if(state == Table.OPERATION)then
self:OnOPERATION(playerOperator)
return
end
end
--托管超时判断
function aipaodekuai:playerOutTime(player)
local Table = self.Table
LOGD("player out times-----------------------------table[%] [%] [%] [%] [%]", Table:getOnlyIdStr(), player:getId(), player:getRobot(), player:getTuoGuan(), self.stateTime)
if not player:getRobot() and player:getTuoGuan() ~= true then
if OVER_TIME <= self.stateTime then
if(not player.tickOutTimes)then
player.tickOutTimes = 1
else
player.tickOutTimes = player.tickOutTimes + 1
if(TUO_GUANG_TIMES <= player.tickOutTimes)then
self.Table:onChangeTuoGuanState(player:getSession(), {tuoGuan=true})
player.tickOutTimes = 0
end
end
LOGD("player out times-----------------------------table[%] [%] [%]", Table:getOnlyIdStr(), player:getId(), player.tickOutTimes)
return true
end
end
return false
end
function aipaodekuai:checkAuto(player)
print("-------机器人直接代打-----aipaodekuai:checkAuto(player)-----% % --------------",player:getSession(), player:getRobot())
--机器人直接代打
if(player:getRobot())then
return true
else
if(player:getTuoGuan() == true or self:playerOutTime(player))then
return true
end
end
return false
end
--统计相同牌
function aipaodekuai:AnalysebCardData(cbCardData, AnalyseResult)
local cbCardCount = #cbCardData
local cbTempCardData = commonfunc.deepcopy2(cbCardData)
--扑克分析
for i=1, cbCardCount do
local cbLogicValue = ddzGetCardValue(cbTempCardData[i])
if(AnalyseResult[cbLogicValue] == nil)then
AnalyseResult[cbLogicValue] = {}
end
table.insert(AnalyseResult[cbLogicValue], cbTempCardData[i])
end
print("--------------统计相同牌-----% % ------------", cbCardData, AnalyseResult)
end
--先手
function aipaodekuai:before(player, oPtion)
--强调:炸弹永远不会成为第一手出牌选择,任何情况下,不拆除炸弹,只作为炸弹出牌
print("主动出牌~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
local handCards = player:getCards()
oPtion.op = Poker.OpOut
oPtion.card = {handCards[#handCards]}
local table = self.Table
local cbHandCardData = commonfunc.deepcopy2(handCards)
--若只有一手牌全出
local cardType = table.mPoker:getCardsType(cbHandCardData)
if cardType ~= Poker.ErrorType then
oPtion.card = commonfunc.deepcopy2(cbHandCardData)
return
end
local AnalyseResult = {}
self:AnalysebCardData(cbHandCardData, AnalyseResult)
--想出的牌,出牌后手数
local outCards, minHands = {}, 100
--如果没有单牌,或者单牌很大,打对子
local minSingle ,minDouble = 100, 100
for i = 3, 14 do
local tmpOutCards = {}
if minDouble == 100 and AnalyseResult[i] and 2 == #AnalyseResult[i] then
minDouble = AnalyseResult[i][1]
tmpOutCards = AnalyseResult[i]
local hands = self:getHands(handCards, tmpOutCards)
if(hands < minHands)then
minHands = hands
outCards = tmpOutCards
logd("---minDouble---outCards----%, %",minHands, outCards)
end
end
if minSingle == 100 and AnalyseResult[i] and 1 == #AnalyseResult[i] then
minSingle = AnalyseResult[i][1]
tmpOutCards = AnalyseResult[i]
local hands = self:getHands(handCards, tmpOutCards)
if(hands <= minHands and minSingle < minDouble)then
minHands = hands
outCards = tmpOutCards
logd("----minSingle--outCards----%, %",minHands, outCards)
end
end
end
--iii.第三步:在不具明面统治牌权情况下,判断出牌一次性,一次能出最多张数的牌型
--是否有顺子
local first = 0 -- 顺子第一个位置
local last = 0 -- 顺子最长位置
for i = 3, 14 do
if AnalyseResult[i] then
if first == 0 then
first = i
end
last = i
else
if first > 0 and 4 <= last - first then
local tmpOutCards = {}
for j = first, last do
--顺子最后一张是对子,不拆
if(j == last and 2 <= #AnalyseResult[j] and 5 <= #tmpOutCards)then
break
end
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][1]
end
local hands = self:getHands(handCards, tmpOutCards)
if(hands <= minHands and #outCards < #tmpOutCards)then
minHands = hands
outCards = tmpOutCards
logd("----顺子--outCards----%, %",minHands, outCards)
end
break
end
first = 0
last = 0
end
end
first = 0
last = 0
--是否有连队
for i = 3, 14 do
--不拆炸弹
if AnalyseResult[i] and 2<= #AnalyseResult[i] and #AnalyseResult[i] <= 3 then
if first == 0 then
first = i
end
last = i
else
if first > 0 and 1 <= last - first then
local tmpOutCards = {}
for j = first, last do
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][1]
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][2]
end
local hands = self:getHands(handCards, tmpOutCards)
if(hands <= minHands and #outCards < #tmpOutCards)then
minHands = hands
outCards = tmpOutCards
logd("----连队--outCards----%, %",minHands, outCards)
end
break
end
first = 0
last = 0
end
end
first = 0
last = 0
--是否有飞机,是否有三代2
for i = 3, 14 do
--不拆炸弹
if AnalyseResult[i] and #AnalyseResult[i] == 3 then
if first == 0 then
first = i
end
last = i
else
if first > 0 then
local tmpOutCards = {}
for j = first, last do
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][1]
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][2]
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][3]
end
local adds = {}
local bAdd = self:getAdds(handCards, AnalyseResult, adds, last - first + 1)
if(bAdd and adds)then
commonfunc.copyAdd(tmpOutCards, adds)
local hands = self:getHands(handCards, tmpOutCards)
if(hands <= minHands and #outCards < #tmpOutCards)then
minHands = hands
outCards = tmpOutCards
logd("----飞机--outCards----%, %",minHands, outCards)
end
end
break
end
first = 0
last = 0
end
end
if(#outCards == 1)then
--下家只有一张牌时,只能出最大的单排
local opInfo = { uid = player:getId(), op = Poker.OpOut, opCards = oPtion.card }
if table.show:checkIsNeedOutMaxValueCardAllCard(player,opInfo) then
oPtion.card = {handCards[1]}
return
end
end
if(0 < #outCards)then
oPtion.card = outCards
end
logd("-------------outCards--oPtion--------%, %", outCards, oPtion)
end
--计算手
function aipaodekuai:getHands(handCards, outCards)
local cbHandCardData = commonfunc.deepcopy2(handCards)
--先把要出的牌剔除
for _, card in pairs(outCards) do
for k, v in pairs(cbHandCardData) do
if(card == v)then
table.remove(cbHandCardData, k)
break
end
end
end
--顺子也剔除
local AnalyseResult = {}
self:AnalysebCardData(cbHandCardData, AnalyseResult)
local first = 0 -- 顺子第一个位置
local last = 0 -- 顺子最长位置
local tmpOutCards = {}
for i = 3, 14 do
if AnalyseResult[i] then
if first == 0 then
first = i
end
last = i
else
if first > 0 and 4 <= last - first then
for j = first, last do
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][1]
end
break
end
first = 0
last = 0
end
end
for _, card in pairs(tmpOutCards) do
for k, v in pairs(cbHandCardData) do
if(card == v)then
table.remove(cbHandCardData, k)
break
end
end
end
AnalyseResult = {}
self:AnalysebCardData(cbHandCardData, AnalyseResult)
local hand = 0
for k, v in pairs(AnalyseResult) do
if(#v < 3)then
hand = hand + 1
end
end
return hand
end
--获得飞机的翅膀, 只能带2个单牌
function aipaodekuai:getAdds(handCards, AnalyseResult, cardsLlist, count)
logd("----------------%,%,%,%",handCards, AnalyseResult, cardsLlist, count)
--要获得多张单牌
local singleList = {}
for i = 3, 14 do
if(AnalyseResult[i] and 1 == #AnalyseResult[i] and AnalyseResult[i][1])then
table.insert(cardsLlist, AnalyseResult[i][1])
if(count*2 <= #cardsLlist)then
return true
end
end
end
logd("-----------cardsLlist----------%", cardsLlist)
return false
end
--后手
function aipaodekuai:after(player, Table, oPtion, canOutCards)
oPtion.op = Poker.OpOut
oPtion.card = canOutCards[1]
--下家只有一张牌时,只能出最大的单排
local opInfo = { uid = player:getId(), op = Poker.OpOut, opCards = oPtion.card }
local handCards = player:getCards()
if Table.show:checkIsNeedOutMaxValueCardAllCard(player,opInfo) then
oPtion.op = Poker.OpOut
oPtion.card = {handCards[1]}
return
end
--找一个出牌后手数最少的
local index, minhand, count = 1, 100, 1
for k, v in pairs(canOutCards) do
local hand = aipaodekuai:getHands(handCards, v)
if(hand < minhand)then
minhand = hand
count = #v
index = k
elseif(hand == minhand and count < #v)then
minhand = hand
count = #v
index = k
end
end
--[[
炸弹必炸
--单牌太多炸弹不拆
local cardType = Table.mPoker:getCardsType(canOutCards[index])
if cardType == Poker.ZhaDan then
local hand = aipaodekuai:getHands(handCards, canOutCards[index])
if(aipaodekuai:getHands(handCards, {}) + 2 <= hand)then
oPtion.op = Poker.OpGiveUp
return
end
end
]]
oPtion.card = canOutCards[index]
logd("-------oPtion---------%", oPtion)
end
--是否有方块3
function aipaodekuai:hasFangkuai3(cards)
for k, card in pairs(cards) do
if(card == 63)then
return true
end
end
return false
end
--第一次出牌
function aipaodekuai:onFirst(player, oPtion)
--强调:炸弹永远不会成为第一手出牌选择,任何情况下,不拆除炸弹,只作为炸弹出牌
print("主动出牌~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
local handCards = player:getCards()
local table = self.Table
local cbHandCardData = commonfunc.deepcopy2(handCards)
--若只有一手牌全出
local cardType = table.mPoker:getCardsType(cbHandCardData)
if cardType ~= Poker.ErrorType then
oPtion.card = commonfunc.deepcopy2(cbHandCardData)
return
end
local AnalyseResult = {}
self:AnalysebCardData(cbHandCardData, AnalyseResult)
--想出的牌,出牌后手数
local outCards, minHands = {}, 100
--如果没有单牌,或者单牌很大,打对子
local minSingle ,minDouble = 100, 100
for i = 3, 14 do
if(not AnalyseResult[3] or not self:hasFangkuai3(AnalyseResult[3]))then
break
end
local tmpOutCards = {}
if minDouble == 100 and AnalyseResult[i] and 2 == #AnalyseResult[i] then
minDouble = AnalyseResult[i][1]
tmpOutCards = AnalyseResult[i]
local hands = self:getHands(handCards, tmpOutCards)
if(hands < minHands and self:hasFangkuai3(tmpOutCards))then
minHands = hands
outCards = tmpOutCards
logd("---minDouble---outCards----%, %",minHands, outCards)
end
end
if minSingle == 100 and AnalyseResult[i] and 1 == #AnalyseResult[i] then
minSingle = AnalyseResult[i][1]
tmpOutCards = AnalyseResult[i]
local hands = self:getHands(handCards, tmpOutCards)
if(hands <= minHands and minSingle < minDouble and self:hasFangkuai3(tmpOutCards))then
minHands = hands
outCards = tmpOutCards
logd("----minSingle--outCards----%, %",minHands, outCards)
end
end
end
--iii.第三步:在不具明面统治牌权情况下,判断出牌一次性,一次能出最多张数的牌型
--是否有顺子
local first = 0 -- 顺子第一个位置
local last = 0 -- 顺子最长位置
for i = 3, 14 do
if(not AnalyseResult[3] or not self:hasFangkuai3(AnalyseResult[3]))then
break
end
if AnalyseResult[i] then
if first == 0 then
first = i
end
last = i
else
if first > 0 and 4 <= last - first then
local tmpOutCards = {}
for j = first, last do
--顺子最后一张是对子,不拆
if(j == last and 2 <= #AnalyseResult[j] and 5 <= #tmpOutCards)then
break
end
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][1]
end
local hands = self:getHands(handCards, tmpOutCards)
if(hands <= minHands and self:hasFangkuai3(tmpOutCards))then
minHands = hands
outCards = tmpOutCards
logd("----顺子--outCards----%, %",minHands, outCards)
end
break
end
first = 0
last = 0
end
end
first = 0
last = 0
--是否有连队
for i = 3, 14 do
if(not AnalyseResult[3] or not self:hasFangkuai3(AnalyseResult[3]))then
break
end
--不拆炸弹
if AnalyseResult[i] and 2<= #AnalyseResult[i] and #AnalyseResult[i] <= 3 then
if first == 0 then
first = i
end
last = i
else
if first > 0 and 1 <= last - first then
local tmpOutCards = {}
for j = first, last do
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][1]
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][2]
end
local hands = self:getHands(handCards, tmpOutCards)
if(hands < minHands and self:hasFangkuai3(tmpOutCards))then
minHands = hands
outCards = tmpOutCards
logd("----连队--outCards----%, %",minHands, outCards)
end
break
end
first = 0
last = 0
end
end
first = 0
last = 0
--是否有飞机, 是否有三代2
for i = 3, 14 do
if(not AnalyseResult[3] or not self:hasFangkuai3(AnalyseResult[3]))then
break
end
--不拆炸弹
if AnalyseResult[i] and #AnalyseResult[i] == 3 then
if first == 0 then
first = i
end
last = i
else
if first > 0 then
local tmpOutCards = {}
for j = first, last do
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][1]
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][2]
tmpOutCards[#tmpOutCards+1] = AnalyseResult[j][3]
end
local adds = {}
local bAdd = self:getAdds(handCards, AnalyseResult, adds, last - first + 1)
if(bAdd and adds)then
commonfunc.copyAdd(tmpOutCards, adds)
local hands = self:getHands(handCards, tmpOutCards)
if(hands < minHands and self:hasFangkuai3(tmpOutCards))then
minHands = hands
outCards = tmpOutCards
logd("----飞机--outCards----%, %",minHands, outCards)
end
end
break
end
first = 0
last = 0
end
end
if(0 < #outCards)then
oPtion.card = outCards
end
end
--出牌
function aipaodekuai:OnOPERATION(player)
local wMeChairID = player:getSeatId()
local Table = self.Table
--是否首次出牌
local op = player.allowedOp.op
print("AAAAAA getCircleCount=% getCurrentSubCircleId=% op=%",Table.show:getCircleCount(),Table.show:getCurrentSubCircleId(),op)
local oPtion = {op=op,card={}}
if Table.show:getCurrentSubCircleId() == 1 and Table.show:getCircleCount() == 1 and Table:getBanker():getId() == player:getId() then
print("首次出牌```````````````````````````````````````````````")
oPtion = {op = op, card = {63}}
self:onFirst(player, oPtion)
else
if btBit.AND(Poker.OpOut, op) ~= 0 then
print("非首次出牌··········································")
local circle = Table.show:getLastCircle()
local canOutCards = player:getLargerWeightCardList2(circle.lastOutCards, circle.lastOutCardsType)
print("canOutCards=============== %",canOutCards)
if canOutCards[1] and circle.lastOutCardsType ~= Poker.ErrorType then
self:after(player, Table, oPtion, canOutCards)
else
self:before(player, oPtion)
end
end
end
local bReslt = Table:onOperation(player:getSession(), oPtion, true)
--LOGI("do auto card player[%] handcards[%] op[%] sub[%]", player:getId(), player:getCards(), player:getAllowedOp(), player:getSubmitOp())
if(bReslt and 0 < bReslt)then
LOGE("gameId=% oPtion=% ERROR,[%]", self.gameId, oPtion, debug.traceback())
--player:clearAllowedOp()
--Table:setOperator(Table:findNext(player))
--Table.mState:change(Table.TURN)
for _, p in pairs(self.Table:getPlayers()) do
LOGE("EEEEEEEEEEEEEEEEEEEE player[%] op[%] sub[%]", p:getId(), p.allowedOp, p.submitOp)
end
end
end
--自动准备
function aipaodekuai:ready()
local Table = self.Table
for _, player in pairs(Table:getPlayers()) do
--不处理玩家操作
if(player:getRobot() and not player:getReady() or OVER_TIME <= self.stateTime)then
Table:UpdateDataOnTable(player:getSession(),"GoldCount",player:getGoldCount())
Table:onReady(player:getSession())
player:setTuoGuan(false)
if(Table:isAllReady() == true)then
Table.mState:change(Table.DEAL)
break
end
end
end
end
return aipaodekuai