123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- -- local utils_bt_grid = require("servers.battle.lib.utils_bt_grid")
- -- require("lib.lualib.luaext")
- local utils_bt_grid = require("utils_bt_grid")
- local battleAdapt = require "adapt.battleAdapt"
- local battleConst = require "battle.battleConst"
- local root = {}
- local function log2Client(core, logStr)
- if not core then
- print(logStr)
- return
- end
- core:notifyClientLog(logStr)
- end
- -- 色块补充。grids里,x:0~4,y:0~9
- function root:supply_grids(core, seat, grids, supplyType, is2v2)
- -- 每个颜色的数量
- local colorCountMap = {0, 0, 0, 0}
- local hasUpdate = false
- for _, v in ipairs(grids) do
- local color = v.color
- if color >= 1 and color <= 4 then
- colorCountMap[color] = colorCountMap[color] + 1
- elseif color == 0 then
- hasUpdate = true
- end
- end
- if not hasUpdate then
- -- 无需色块补充
- return
- end
- self:_drop(seat, grids)
- local colorMap = utils_bt_grid:grids_to_color_map(grids)
- -- 判断A类和B类是否启用,不启动的话,需要替换成L类
- if string.find(supplyType, "A") == 1 or string.find(supplyType, "B") == 1 then
- local linkInfo5 = self:_get_link_len_info(seat, colorMap, 5)
- local more5, count5 = linkInfo5.moreLen, linkInfo5.countLen
- local msg = string.format("色块补充日志:补充前状态 连线长度为5的数量: %d, 是否有长度超过5的连线: %s", count5, more5)
- log2Client(core, msg)
- if string.find(supplyType, "A") == 1 then
- if not (more5 or count5 >= 2) then
- -- A类色块补充,替换为L类色块补充
- supplyType = string.gsub(supplyType, "A", "L")
- else
- supplyType = "A"
- end
- else
- if not (more5 or count5 >= 1) then
- -- B类色块补充,替换为L类色块补充
- supplyType = string.gsub(supplyType, "B", "L")
- else
- supplyType = "B"
- end
- end
- end
- log2Client(core, string.format("色块补充日志:色块补充方案: %s", supplyType))
- -- updateList里,x:1~5,y:1~10
- local updateList
- if supplyType == "A" or supplyType == "B" then
- updateList = self:_supply_ab(core, seat, colorMap, colorCountMap, supplyType)
- elseif string.find(supplyType, "L") == 1 then
- updateList = self:_supply_l(core, seat, colorMap, colorCountMap, supplyType)
- elseif string.find(supplyType, "W") == 1 or string.find(supplyType, "R") == 1 then
- updateList = self:_supply_wr(core, seat, colorMap, colorCountMap, supplyType)
- else
- print("ERROR: 非法色块补充方案")
- end
- if updateList and #updateList > 0 then
- for _, v in ipairs(updateList) do
- local x, y = v.x - 1, v.y - 1
- self:_set_color(grids, x, y, v.color)
- end
- -- 补充万能色块的逻辑
- local colorMap2 = utils_bt_grid:grids_to_color_map(grids)
- local linkInfo4 = self:_get_link_len_info(seat, colorMap2, 4)
- local more4, count4 = linkInfo4.moreLen, linkInfo4.countLen
- local msg = string.format("色块补充日志:补充后状态 连线长度为4的数量: %d, 是否有长度超过4的连线: %s", count4, more4)
- log2Client(core, msg)
- local maxCount4 = is2v2 and 2 or 1
- if count4 <= maxCount4 and not more4 then
- local pos = updateList[math.random(#updateList)]
- local x, y = pos.x - 1, pos.y - 1
- self:_set_color(grids, x, y, battleConst.COLOR_TYPE.ALL)
- local msg = string.format("色块补充日志:符合变万能色块逻辑 (%d, %d) 变为万能色块", x, y)
- log2Client(core, msg)
- end
- end
- end
- -- 色块掉落。grids里,x:0~4,y:0~9
- function root:_drop(seat, grids)
- --[[
- seat: 当前回合操作的座位
- 1:下方操作,色块往下掉落,该列非空色块的y -1
- 2:上方操作,色块往上掉落,该列非空色块的y +1
- ]]
- local tempGridMap = {}
- local maxX = 0
- local maxY = 0
- for _, v in ipairs(grids) do
- local row, col = v.y + 1, v.x + 1
- if not tempGridMap[row] then
- tempGridMap[row] = {}
- end
- tempGridMap[row][col] = v
- maxX = math.max(maxX, col)
- maxY = math.max(maxY, row)
- end
- local w, h = maxX, maxY
- local startY, endY, stepY
- if seat == 1 then
- startY, endY, stepY = 1, h, 1
- else
- startY, endY, stepY = h, 1, -1
- end
- for col = 1, w do
- local emptyCount = 0
- for row = startY, endY, stepY do
- local grid = tempGridMap[row][col]
- if grid.color == 0 then
- emptyCount = emptyCount + 1
- -- 例如:第2格空的,补充到倒数第2行。y=10-1*(2-1)
- grid.y = endY - stepY * (emptyCount - 1) - 1
- else
- -- 例如:第9行往下掉2格。y=9-1*2
- grid.y = grid.y - stepY * emptyCount
- end
- end
- end
- end
- --[[ 判断“当前操作的敌方”可连线长度的情况
- moreLen: 连线长度为 len 的数量
- countLen: 是否有长度超过 len 的连线
- ]]
- function root:_get_link_len_info(seat, colorMap, len)
- local otherSeat = seat == 1 and 2 or 1
- local links = utils_bt_grid:get_map_max_link_list(otherSeat, colorMap)
- local countLen = 0
- local moreLen = false
- for _, v in ipairs(links) do
- if #v > len then
- moreLen = true
- break
- elseif #v == len then
- countLen = countLen + 1
- end
- end
- return {countLen = countLen, moreLen = moreLen}
- end
- -- L类色块补充,半场均衡。x:1~4,y:1~10
- function root:_supply_l(core, seat, colorMap, colorCountMap, supplyType)
- local ret = {}
- -- 特殊补充色块一方:当前操作的我方。随机补充
- local supplyPosList2 = self:_get_supply_pos_list(seat, colorMap)
- for _, v in ipairs(supplyPosList2) do
- local color = math.random(1, 4)
- table.insert(ret, {x = v.x, y = v.y, color = color})
- end
- -- 正常补充色块一方:当前操作的敌方。按方案补充
- local otherSeat = seat == 1 and 2 or 1
- local halfMap = utils_bt_grid:get_half_map(otherSeat, colorMap)
- local supplyPosList1 = self:_get_supply_pos_list(otherSeat, colorMap)
- -- 半场每个颜色的数量记录
- local halfCountMap = {0, 0, 0, 0}
- for _, v in ipairs(halfMap) do
- for _, vv in ipairs(v) do
- if vv >= 1 and vv <= 4 then
- halfCountMap[vv] = halfCountMap[vv] + 1
- end
- end
- end
- -- 排序一下
- table.sort(
- supplyPosList1,
- function(a, b)
- if a.y ~= b.y then
- if otherSeat == 1 then
- return a.y > b.y
- else
- return a.y < b.y
- end
- else
- return a.x < b.x
- end
- end
- )
- for _, v in ipairs(supplyPosList1) do
- local x, y = v.x, v.y
- local okColorList = {1, 2, 3, 4}
- local okColorWeightList = {}
- for _, v in ipairs(okColorList) do
- local allCount = halfCountMap[v]
- local weight = battleAdapt:getColorWeight(allCount, supplyType)
- table.insert(okColorWeightList, {v, weight})
- end
- local tempColor = self:random_with_weight(okColorWeightList)
- local msg = string.format("色块补充日志:L类色块补充权重: %s, 色块补充颜色: %s", tostring(okColorWeightList), tempColor)
- log2Client(core, msg)
- halfCountMap[tempColor] = halfCountMap[tempColor] + 1
- halfMap[y][x] = tempColor
- table.insert(ret, {x = x, y = y, color = tempColor})
- end
- return ret
- end
- -- L类色块补充,全场均衡。x:1~4,y:1~10
- function root:_supply_wr(core, seat, colorMap, colorCountMap, supplyType)
- local ret = {}
- -- 每个颜色补充的数量记录
- local suppleCountMap = {0, 0, 0, 0}
- -- 特殊补充色块一方:当前操作的我方。随机补充
- local supplyPosList2 = self:_get_supply_pos_list(seat, colorMap)
- for _, v in ipairs(supplyPosList2) do
- local color = math.random(1, 4)
- table.insert(ret, {x = v.x, y = v.y, color = color})
- suppleCountMap[color] = suppleCountMap[color] + 1
- end
- -- 正常补充色块一方:当前操作的敌方。按方案补充
- local otherSeat = seat == 1 and 2 or 1
- local halfMap = utils_bt_grid:get_half_map(otherSeat, colorMap)
- local supplyPosList1 = self:_get_supply_pos_list(otherSeat, colorMap)
- -- 排序一下
- table.sort(
- supplyPosList1,
- function(a, b)
- if a.y ~= b.y then
- if otherSeat == 1 then
- return a.y > b.y
- else
- return a.y < b.y
- end
- else
- return a.x < b.x
- end
- end
- )
- for _, v in ipairs(supplyPosList1) do
- local x, y = v.x, v.y
- local okColorList = {1, 2, 3, 4}
- local okColorWeightList = {}
- for _, v in ipairs(okColorList) do
- local allCount = colorCountMap[v] + suppleCountMap[v]
- local weight = battleAdapt:getColorWeight(allCount, supplyType)
- table.insert(okColorWeightList, {v, weight})
- end
- local tempColor = self:random_with_weight(okColorWeightList)
- local msg = string.format("色块补充日志:WR类色块补充权重: %s, 色块补充颜色: %s", tostring(okColorWeightList), tempColor)
- log2Client(core, msg)
- suppleCountMap[tempColor] = suppleCountMap[tempColor] + 1
- halfMap[y][x] = tempColor
- table.insert(ret, {x = x, y = y, color = tempColor})
- end
- return ret
- end
- -- A类、B类色块补充,全场均衡。x:1~4,y:1~10
- function root:_supply_ab(core, seat, colorMap, colorCountMap, supplyType)
- local ret = {}
- -- 每个颜色补充的数量记录
- local suppleCountMap = {0, 0, 0, 0}
- -- 特殊补充色块一方:当前操作的我方。随机补充
- local supplyPosList2 = self:_get_supply_pos_list(seat, colorMap)
- for _, v in ipairs(supplyPosList2) do
- local color = math.random(1, 4)
- table.insert(ret, {x = v.x, y = v.y, color = color})
- suppleCountMap[color] = suppleCountMap[color] + 1
- end
- -- 正常补充色块一方:当前操作的敌方。按方案补充
- local otherSeat = seat == 1 and 2 or 1
- local halfMap = utils_bt_grid:get_half_map(otherSeat, colorMap)
- local supplyPosList1 = self:_get_supply_pos_list(otherSeat, colorMap)
- -- 排序一下
- table.sort(
- supplyPosList1,
- function(a, b)
- if a.y ~= b.y then
- if otherSeat == 1 then
- return a.y > b.y
- else
- return a.y < b.y
- end
- else
- return a.x < b.x
- end
- end
- )
- for _, v in ipairs(supplyPosList1) do
- local x, y = v.x, v.y
- local okColorList = {}
- local maxLen = 4
- for color = 1, 4 do
- halfMap[y][x] = color
- local sameList = {}
- local nextPos = {x = x, y = y}
- self:_find_same_color_list(halfMap, sameList, nextPos, color)
- if #sameList <= maxLen then
- table.insert(okColorList, color)
- end
- end
- if #okColorList == 0 then
- okColorList = {1, 2, 3, 4}
- end
- local okColorWeightList = {}
- for _, v in ipairs(okColorList) do
- local allCount = colorCountMap[v] + suppleCountMap[v]
- local weight = battleAdapt:getColorWeight(allCount, supplyType)
- table.insert(okColorWeightList, {v, weight})
- end
- local tempColor = self:random_with_weight(okColorWeightList)
- local msg = string.format("色块补充日志:AB类色块补充权重: %s, 色块补充颜色: %s", tostring(okColorWeightList), tempColor)
- log2Client(core, msg)
- suppleCountMap[tempColor] = suppleCountMap[tempColor] + 1
- halfMap[y][x] = tempColor
- table.insert(ret, {x = x, y = y, color = tempColor})
- end
- return ret
- end
- function root:_get_supply_pos_list(seat, colorMap)
- local maxH = #colorMap
- local minY, maxY
- if seat == 1 then
- minY, maxY = 1, maxH / 2
- else
- minY, maxY = maxH / 2 + 1, maxH
- end
- local ret = {}
- for y = minY, maxY do
- local oneRow = colorMap[y]
- for x, color in ipairs(oneRow) do
- if color == 0 then
- table.insert(ret, {x = x, y = y})
- end
- end
- end
- return ret
- end
- function root:_find_same_color_list(map, sameList, nextPos, color)
- local x1 = nextPos.x
- local y1 = nextPos.y
- for _, v in ipairs(sameList) do
- if v.x == x1 and v.y == y1 then
- -- 已经添加过了,跳过
- return
- end
- end
- table.insert(sameList, nextPos)
- -- 九宫格示例
- -- 1 2 3
- -- 4 x 6
- -- 7 8 9
- local deltaList = {
- {dx = -1, dy = 1},
- {dx = 0, dy = 1},
- {dx = 1, dy = 1},
- {dx = -1, dy = 0},
- {dx = 1, dy = 0},
- {dx = -1, dy = -1},
- {dx = 0, dy = -1},
- {dx = 1, dy = -1}
- }
- for _, v in ipairs(deltaList) do
- local x2 = x1 + v.dx
- local y2 = y1 + v.dy
- if map[y2] and map[y2][x2] and (map[y2][x2] == color or map[y2][x2] == 5) then
- self:_find_same_color_list(map, sameList, {x = x2, y = y2}, color)
- end
- end
- end
- function root:_set_color(grids, x, y, color)
- for _, v in ipairs(grids) do
- if x == v.x and y == v.y then
- v.color = color
- break
- end
- end
- end
- function root:_get_weight(count, supplyType)
- if count > 15 then
- return 0
- else
- return 15 - count
- end
- end
- function root:random_index_with_weights(list)
- local sum = 0
- for _, v in ipairs(list) do
- sum = sum + v
- end
- local ret = 1
- if sum > 0 then
- local r = math.random(1, sum)
- local didSum = 0
- for i, v in ipairs(list) do
- didSum = didSum + v
- if r <= didSum then
- ret = i
- break
- end
- end
- end
- return ret
- end
- -- data: {{3,10},{4,10},{5,10},{6,10},{7,10}}
- function root:random_with_weight(data)
- local weights = {}
- for _, v in ipairs(data) do
- table.insert(weights, v[2])
- end
- local index = self:random_index_with_weights(weights)
- return data[index][1]
- end
- function root:test()
- local seat = 1
- local grids = {}
- local supplyType = "A"
- for x = 0, 4 do
- for y = 0, 9 do
- table.insert(grids, {x = x, y = y, color = math.random(1, 5)})
- end
- end
- local list = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
- for _, v in ipairs(list) do
- grids[v].color = 0
- end
- local colorMap = utils_bt_grid:grids_to_color_map(grids)
- utils_bt_grid:print_map("===1 %s", colorMap)
- self:supply_grids(nil, seat, grids, supplyType, false)
- local colorMap = utils_bt_grid:grids_to_color_map(grids)
- utils_bt_grid:print_map("===2 %s", colorMap)
- end
- -- root:test()
- return root
|