123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612 |
- local skynet = require "skynet"
- local battleConst = require "battle.battleConst"
- local battleLog = require "battle.battleLog"
- local battleUtils = require "battle.battleUtils"
- local battleAdapt = require "adapt.battleAdapt"
- local battleDefine = require "battle.battleDefine"
- local battleAiUtils = require "battleAiUtils"
- local utils_bt_supply = require "utils_bt_supply"
- local root = {}
- local Total_Weight = {2, 8, 11, 9, 7, 3}
- local Grid_Color_Weights = {
- {num = 7, colors = {{p1 = 4, p2 = 3}, {p1 = 3, p2 = 4}}},
- {num = 8, colors = {{p1 = 4, p2 = 4}}},
- {num = 9, colors = {{p1 = 5, p2 = 4}, {p1 = 4, p2 = 5}}},
- {num = 10, colors = {{p1 = 5, p2 = 5}}},
- {num = 11, colors = {{p1 = 5, p2 = 6}, {p1 = 6, p2 = 5}, {p1 = 7, p2 = 4}, {p1 = 4, p2 = 7}}},
- {num = 12, colors = {{p1 = 6, p2 = 6}, {p1 = 7, p2 = 5}, {p1 = 5, p2 = 7}}},
- {num = 13, colors = {{p1 = 7, p2 = 6}, {p1 = 6, p2 = 7}, {p1 = 8, p2 = 5}, {p1 = 5, p2 = 8}}},
- {num = 14, colors = {{p1 = 7, p2 = 7}, {p1 = 8, p2 = 6}, {p1 = 6, p2 = 8}}},
- {num = 15, colors = {{p1 = 8, p2 = 7}, {p1 = 7, p2 = 8}, {p1 = 9, p2 = 6}, {p1 = 6, p2 = 9}}},
- {num = 16, colors = {{p1 = 8, p2 = 8}, {p1 = 9, p2 = 7}, {p1 = 7, p2 = 9}}},
- {num = 17, colors = {{p1 = 9, p2 = 8}}},
- {num = 18, colors = {{p1 = 9, p2 = 9}}},
- {num = 19, colors = {{p1 = 10, p2 = 9}}},
- {num = 20, colors = {{p1 = 10, p2 = 10}}}
- }
- -----------------------------------------------
- ------------------色块生成逻辑------------------
- --[[ 生成50个色块
- ]]
- function root:initGrid(core)
- self:printToConsole("-->initGrid...")
- local needColorData1, needColorData2 = self:getGridTotalColorNum(core)
- local grids1 = self:createGridColor(core, 0, needColorData1) or {}
- local grids2 = self:createGridColor(core, 1, needColorData2) or {}
- self:printToConsole(string.format("结果1:%s", table.concat(grids1, ", ")))
- self:printToConsole(string.format("结果2:%s", table.concat(grids2, ", ")))
- return self:tableConcat(grids1, grids2)
- -- {3, 2, 3, 2, 4, 1, 4, 3, 2, 4, 2, 1, 4, 1, 1, 2, 3, 2, 3, 2, 3, 3, 2, 3, 3, 3, 2, 3, 2, 4, 1, 4, 3, 2, 4, 2, 1, 4, 1, 1, 2, 3, 2, 3, 2, 3, 3, 2, 3, 3}
- end
- -- 获取双方 四种颜色总数
- function root:getGridTotalColorNum(core)
- local totalWeight = Total_Weight
- local totalStartIndex = 9
- local gridColorWeights = Grid_Color_Weights
- local totalRedIndex = self:randomWeightToIndex(totalWeight)
- local totalRed = totalStartIndex + totalRedIndex
- local totalGreenIndex = self:randomWeightToIndex(totalWeight)
- local totalGreen = totalStartIndex + totalGreenIndex
- local totalBlueIndex = self:randomWeightToIndex(totalWeight)
- local totalBlue = totalStartIndex + totalBlueIndex
- local total = core.areaW * core.areaH * 2
- local totalYellow = total - totalRed - totalGreen - totalBlue
- -- self:printToConsole( string.format("totalRed=%d, totalGreen=%d, totalBlue=%d, totalYellow=%d", totalRed, totalGreen, totalBlue, totalYellow) )
- local needColorData1 = {red = 0, green = 0, blue = 0, yellow = 0}
- local needColorData2 = {red = 0, green = 0, blue = 0, yellow = 0}
- local colorNum = self:getGridColorNumByColor(gridColorWeights, totalRed)
- needColorData1.red = colorNum.p1
- needColorData2.red = colorNum.p2
- colorNum = self:getGridColorNumByColor(gridColorWeights, totalGreen)
- needColorData1.green = colorNum.p1
- needColorData2.green = colorNum.p2
- colorNum = self:getGridColorNumByColor(gridColorWeights, totalBlue)
- needColorData1.blue = colorNum.p1
- needColorData2.blue = colorNum.p2
- colorNum = self:getGridColorNumByColor(gridColorWeights, totalYellow)
- needColorData1.yellow = colorNum.p1
- needColorData2.yellow = colorNum.p2
- -- self:printToConsole( string.format("needColorData1=%d,%d,%d,%d", needColorData1.red, needColorData1.yellow, needColorData1.green, needColorData1.blue) );
- -- self:printToConsole( string.format("needColorData2=%d,%d,%d,%d", needColorData2.red, needColorData2.yellow, needColorData2.green, needColorData2.blue) );
- return needColorData1, needColorData2
- end
- function root:getGridColorNumByColor(gridColorWeights, totalNum)
- for i, v in ipairs(gridColorWeights) do
- if v.num == totalNum then
- local randomIndex = math.random(1, #v.colors)
- local colorObj = v.colors[randomIndex]
- return colorObj
- end
- end
- return {p1 = 0, p2 = 0}
- end
- -- 创建格子颜色(1红,2黄,3绿,4蓝)
- function root:createGridColor(core, castleIndex, needColorData)
- local gridColorList = {}
- local printGridCount = {0, 0, 0, 0}
- local colorWeights = {10, 10, 10, 10}
- local isCanLink = false
- local total = core.areaW * core.areaH
- for i = 1, total do
- colorWeights[1] = needColorData.red > 0 and 10 or 0
- colorWeights[2] = needColorData.yellow > 0 and 10 or 0
- colorWeights[3] = needColorData.green > 0 and 10 or 0
- colorWeights[4] = needColorData.blue > 0 and 10 or 0
- local tempColorWeights
- if not isCanLink and i >= total - 2 then
- colorWeights = {10, 0, 0, 0}
- if i == total then
- self:printToConsole("-------- 强制生成三块红色 --------")
- end
- else
- tempColorWeights = self:checkNearGridColor(gridColorList, colorWeights)
- end
- if colorWeights[1] == 0 and colorWeights[2] == 0 and colorWeights[3] == 0 and colorWeights[4] == 0 then
- -- self:printToConsole("重新初始化权重")
- colorWeights = {10, 10, 10, 10}
- if
- tempColorWeights[1].w == 0 and tempColorWeights[2].w == 0 and tempColorWeights[3].w == 0 and
- tempColorWeights[4].w == 0
- then
- -- self:printToConsole('### 相邻色块都超过5 ###')
- else
- for j = 1, 4 do
- if tempColorWeights[j].w == 0 then
- colorWeights[j] = 0
- end
- end
- end
- end
- local colorType = self:randomWeightToIndex(colorWeights)
- table.insert(gridColorList, colorType)
- printGridCount[colorType] = printGridCount[colorType] + 1
- if colorType == 1 then
- needColorData.red = needColorData.red - 1
- elseif colorType == 2 then
- needColorData.yellow = needColorData.yellow - 1
- elseif colorType == 3 then
- needColorData.green = needColorData.green - 1
- elseif colorType == 4 then
- needColorData.blue = needColorData.blue - 1
- end
- if tempColorWeights and tempColorWeights[colorType].n >= 3 then
- isCanLink = true
- end
- end
- -- self:printToConsole( string.format("玩家%d:红-%d, 黄-%d,绿-%d, 蓝-%d", castleIndex, printGridCount[1], printGridCount[2], printGridCount[3], printGridCount[4]) )
- return gridColorList
- end
- -- 找出相邻4种色块长度
- function root:checkNearGridColor(gridColorList, colorWeights)
- local tempColorWeights = {{w = 10, n = 0}, {w = 10, n = 0}, {w = 10, n = 0}, {w = 10, n = 0}}
- if #gridColorList < 4 then
- return tempColorWeights
- end
- for i = 1, 4 do
- local nearGridColorCount = self:getNearGridColorCount(gridColorList, i)
- if nearGridColorCount > 5 then
- colorWeights[i] = 0
- tempColorWeights[i].w = 0
- -- self:printToConsole( string.format(" %d 相邻色块超过5,把权重调0", #gridColorList) )
- end
- tempColorWeights[i].n = nearGridColorCount
- end
- return tempColorWeights
- end
- -- 找出某种色块相邻长度
- function root:getNearGridColorCount(gridColorList, color, index)
- local gridIndex = index ~= nil and index or #gridColorList
- local list = {gridIndex}
- local index = 1
- while index <= #list do
- local checkIndex = list[index]
- index = index + 1
- local gridX = checkIndex % 5
- local gridY = math.floor(checkIndex / 5)
- for i = -1, 1 do
- for j = -1, 1 do
- if (i ~= 0 or j ~= 0) and (gridX + i) >= 0 and (gridY + j) >= 0 and (gridX + i < 5) and (gridY + j < 5) then
- local tempIndex = self:getGridIndexByXY(gridX + i, gridY + j)
- local tempColor = gridColorList[tempIndex + 1]
- if
- tempColor and self:checkIsSameColor(tempColor, color) and
- self:findGridIndex(list, tempIndex) <= 0
- then
- table.insert(list, tempIndex)
- if color == battleConst.COLOR_TYPE.ALL then
- color = tempColor
- end
- end
- end
- end
- end
- end
- -- self:printToConsole( string.format("[%d] color=%d, data=%s, list=%s", gridIndex, color, table.concat(gridColorList, "," ), table.concat(list, "," )) )
- return #list
- end
- -- 判断色块是否相同,5是万能色块
- function root:checkIsSameColor(tempColor, color)
- return tempColor == battleConst.COLOR_TYPE.ALL or color == battleConst.COLOR_TYPE.ALL or tempColor == color
- end
- function root:findGridIndex(list, tempIndex)
- for i, v in ipairs(list) do
- if tempIndex == v then
- return i
- end
- end
- return 0
- end
- function root:getGridIndexByXY(gridX, gridY)
- return gridY * 5 + gridX
- end
- local function log2Client(core, logStr)
- if not logStr then
- return
- end
- battleLog:logClient(logStr)
- core:notifyClientLog(logStr)
- end
- -----------------------------------------------
- ------------------色块补充逻辑------------------
- function root:supplyGrids(core, actionCastle)
- local grids = core.map
- local curRound = core:getCurRound()
- -- 将需要补充的色块,重置颜色为0
- for _, block in ipairs(grids) do
- if block.status == battleConst.BLOCK_STATUS.NEEDUPDATE then
- block.color = battleConst.COLOR_TYPE.INVAILD
- block:clear()
- end
- end
- local enemyCastle = core:getEnemyCastle(actionCastle)
- local supplyRound = enemyCastle.supplyRound
- local supplyWeight1 = enemyCastle.supplyWeight1
- local supplyWeight2 = enemyCastle.supplyWeight2
- local supplyWeight = curRound <= supplyRound and supplyWeight1 or supplyWeight2
- local supplyType = getRandomWithWeight(supplyWeight)
- supplyType = "A57"
- local seat = actionCastle.seat
- local is2v2 = core.is2v2
- utils_bt_supply:supply_grids(core, seat, grids, supplyType, is2v2)
- end
- -- 根据权重随机下标
- function root:randomWeightToIndex(list)
- if list == nil or #list == 0 then
- return 1
- end
- local sum = 0
- for i, weight in ipairs(list) do
- sum = sum + weight
- end
- if sum <= 0 then
- return 1
- end
- local ret = 1
- local r = math.random(1, sum)
- local didSum = 0
- for index, q in ipairs(list) do
- didSum = didSum + q
- if r <= didSum then
- ret = index
- break
- end
- end
- return ret
- end
- -- 获取可连线选择的龙
- local function getOptionLinks(core, actionCastle)
- local allLinks = battleUtils:getAllLinkBlocks2(core, core.map, actionCastle.seat)
- table.sort(
- allLinks,
- function(a, b)
- return #a.linkIds > #b.linkIds
- end
- )
- for i = #allLinks, 1, -1 do
- for j = 1, i - 1 do
- local member = true
- for _, v in ipairs(allLinks[i].linkIds) do
- if not table.member(allLinks[j].linkIds, v) then
- member = false
- break
- end
- end
- if member then
- table.remove(allLinks, i)
- break
- end
- end
- end
- return allLinks
- end
- local link = class("link")
- function link:ctor()
- self.ids = {}
- self.size = 0
- self.lastY = 0
- end
- local function createLink(core, actionCastle, linkIds, isFool)
- local l = link.new()
- l.ids = battleUtils:reverse(core.map, actionCastle.seat, linkIds, isFool)
- l.size = #linkIds
- local lastBlock = battleUtils:getColorBlockByID(core.map, l.ids[l.size])
- l.lastY = lastBlock.y
- return l
- end
- local function findGridSuppressRoute(core, actionCastle)
- local nowTime = skynet.time()
- local allLinks = getOptionLinks(core, actionCastle)
- if table.empty(allLinks) then
- battleLog:logInfo(string.format("findGridSuppressRoute empty links error, uid %s", actionCastle.uid))
- return
- end
- local result = {}
- local exceptLinks = {}
- local enableExSkill = core:getEnableExSkill(actionCastle)
- for _, v in ipairs(allLinks) do
- local ret, exSkillGridId, except =
- battleAiUtils:getLongEvaluate(core, actionCastle, v.linkIds, v.color, false, enableExSkill)
- if ret >= 1000000 then
- battleLog:logInfo(string.format("findGridSuppressRoute time cost %s", skynet.time() - nowTime))
- return v.linkIds, exSkillGridId
- end
- if except then
- table.link(
- exceptLinks,
- battleUtils:getLinkBlocksWithoutExceptBlocks(
- core,
- core.map,
- actionCastle.seat,
- except.blocks,
- except.exceptBlocks
- )
- )
- end
- table.insert(result, {ids = v.linkIds, size = #v.linkIds, allPower = ret, exSkillGridId = exSkillGridId})
- local linkIds = table.reverse(v.linkIds)
- ret, exSkillGridId = battleAiUtils:getLongEvaluate(core, actionCastle, linkIds, v.color, true, enableExSkill)
- if ret >= 1000000 then
- battleLog:logInfo(string.format("findGridSuppressRoute time cost %s", skynet.time() - nowTime))
- return linkIds, exSkillGridId
- end
- table.insert(result, {ids = linkIds, size = #linkIds, allPower = ret, exSkillGridId = exSkillGridId})
- end
- for _, v in ipairs(exceptLinks) do
- local ret, exSkillGridId =
- battleAiUtils:getLongEvaluate(core, actionCastle, v.linkIds, v.color, true, enableExSkill)
- if ret >= 1000000 then
- battleLog:logInfo(string.format("findGridSuppressRoute time cost %s", skynet.time() - nowTime))
- return v.linkIds, exSkillGridId
- end
- table.insert(result, {ids = v.linkIds, size = #v.linkIds, allPower = ret, exSkillGridId = exSkillGridId})
- local linkIds = table.reverse(v.linkIds)
- ret, exSkillGridId = battleAiUtils:getLongEvaluate(core, actionCastle, linkIds, v.color, true, enableExSkill)
- if ret >= 1000000 then
- battleLog:logInfo(string.format("findGridSuppressRoute time cost %s", skynet.time() - nowTime))
- return linkIds, exSkillGridId
- end
- table.insert(result, {ids = linkIds, size = #linkIds, allPower = ret, exSkillGridId = exSkillGridId})
- end
- table.sort(
- result,
- function(a, b)
- if a.allPower ~= b.allPower then
- return a.allPower > b.allPower
- end
- return a.size > b.size
- end
- )
- battleLog:logInfo(string.format("findGridSuppressRoute time cost %s", skynet.time() - nowTime))
- return result[1].ids, result[1].exSkillGridId
- end
- local function findGridCommonRoute(core, actionCastle)
- local nowTime = skynet.time()
- local allLinks = getOptionLinks(core, actionCastle)
- if table.empty(allLinks) then
- battleLog:logInfo(string.format("findGridCommonRoute empty links error, uid %s", actionCastle.uid))
- return
- end
- local result = {}
- for _, v in ipairs(allLinks) do
- table.insert(result, createLink(core, actionCastle, v.linkIds, false))
- end
- table.sort(
- result,
- function(a, b)
- if a.size ~= b.size then
- return a.size > b.size
- end
- if actionCastle.seat == battleConst.BATTLE_SEAT.DOWN then
- return a.lastY < b.lastY
- else
- return a.lastY > b.lastY
- end
- end
- )
- local ids = result[1].ids
- local exSkillGridId
- local enableExSkill = core:getEnableExSkill(actionCastle)
- if enableExSkill then
- exSkillGridId = battleAiUtils:getNormatlExSkillGridId(core, actionCastle, ids)
- end
- battleLog:logInfo(string.format("findGridCommonRoute time cost %s", skynet.time() - nowTime))
- return ids, exSkillGridId
- end
- -- 笨笨的连线AI
- local function findGridFoolRoute(core, actionCastle)
- local nowTime = skynet.time()
- -- 获取全部连线
- local allLinks = getOptionLinks(core, actionCastle)
- if table.empty(allLinks) then
- battleLog:logInfo(string.format("findGridFoolRoute empty links error, uid %s", actionCastle.uid))
- return
- end
- -- 愚蠢取落点低的规则:对手(真人)游戏局数小于5局,或者30%概率
- local enemyCastle = core:getEnemyCastle(actionCastle)
- local mainPlayer = enemyCastle:getMainPlayer()
- local isFool = false
- if mainPlayer.battleCount < 5 then
- isFool = true
- else
- isFool = math.random(100) <= 30
- end
- -- 全部连线结构化
- local result = {}
- for _, v in ipairs(allLinks) do
- table.insert(result, createLink(core, actionCastle, v.linkIds, isFool))
- end
- -- 连线排序:优先长度,其次落点
- table.sort(
- result,
- function(a, b)
- if a.size ~= b.size then
- return a.size > b.size
- end
- if isFool then
- if actionCastle.seat == battleConst.BATTLE_SEAT.UP then
- return a.lastY < b.lastY
- else
- return a.lastY > b.lastY
- end
- else
- if actionCastle.seat == battleConst.BATTLE_SEAT.UP then
- return a.lastY > b.lastY
- else
- return a.lastY < b.lastY
- end
- end
- end
- )
- -- 获取长度最长的连线
- local linkIds = result[1].ids
- -- 10%的概率漏连。漏连数量在 BattleCommonConfig 配置
- if math.random(100) <= 10 then
- local lessWeights = battleAdapt:getLessLinkWeights()
- local lessCount = RandomWithWeight(lessWeights)
- for i = 1, lessCount do
- if #linkIds == battleDefine.MIN_LINK_BLOCK then
- break
- end
- table.remove(linkIds, 1)
- end
- end
- local ids = linkIds
- local exSkillGridId
- local enableExSkill = core:getEnableExSkill(actionCastle)
- if enableExSkill then
- exSkillGridId = battleAiUtils:getNormatlExSkillGridId(core, actionCastle, ids)
- end
- battleLog:logInfo(string.format("findGridFoolRoute time cost %s", skynet.time() - nowTime))
- return ids, exSkillGridId
- end
- local function findGridStupidRoute(core, actionCastle)
- local nowTime = skynet.time()
- -- 获取全部连线
- local allLinks = getOptionLinks(core, actionCastle)
- if table.empty(allLinks) then
- battleLog:logInfo(string.format("findGridStupidRoute empty links error, uid %s", actionCastle.uid))
- return
- end
- local isFool = true
- -- 全部连线结构化
- local result = {}
- for _, v in ipairs(allLinks) do
- table.insert(result, createLink(core, actionCastle, v.linkIds, isFool))
- end
- local ids
- local exSkillGridId = nil
- -- 随机一条连线
- local linkIds = result[math.random(#result)].ids
- if #linkIds > 3 then
- ids = {}
- for i = 1, 3 do
- table.insert(ids, linkIds[i])
- end
- else
- ids = linkIds
- end
- battleLog:logInfo(string.format("findGridStupidRoute time cost %s", skynet.time() - nowTime))
- return ids, exSkillGridId
- end
- -----------------------------------------------
- ------------------色块寻路逻辑------------------
- --[[寻找最长的路线
- ]]
- function root:findGridLongRoute(core, actionCastle, aiLinkType)
- if not aiLinkType then
- log.error("findGridLongRoute aiLinkType is nil")
- return
- end
- -- if aiLinkType == "W" and math.random(100) <= 20 then
- -- aiLinkType = "R"
- -- elseif aiLinkType == "R" and math.random(100) <= 20 then
- -- aiLinkType = "W"
- -- end
- -- aiLinkType = "R"
- log2Client(core, string.format("当前回合%s aiLinkType=%s", core:getCurRound(), aiLinkType))
- if aiLinkType == "W" then
- return findGridSuppressRoute(core, actionCastle)
- elseif aiLinkType == "R" then
- return findGridCommonRoute(core, actionCastle)
- elseif aiLinkType == "L" then
- return findGridFoolRoute(core, actionCastle)
- elseif aiLinkType == "S" then
- return findGridStupidRoute(core, actionCastle)
- end
- battleLog:logInfo(string.format("findGridLongRoute error aiLinkType = %s", aiLinkType))
- end
- -- 数组拷贝
- function root:tableConcat(dest, src)
- local begin = #dest + 1
- local len = #src
- for i = 0, len - 1 do
- dest[i + begin] = src[i + 1]
- end
- return dest
- end
- -------------------------
- function root:printToConsole(str)
- battleLog:logInfo(str)
- end
- return root
|