-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathMetaBoard.lua
112 lines (95 loc) · 3.45 KB
/
MetaBoard.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
local CovenantMissionHelper, CMH = ...
---@class MetaBoard
---@field baseBoard Board
local MetaBoard = {}
CMH.MetaBoard = MetaBoard
local function copy(obj, seen)
if type(obj) ~= 'table' then return obj end
if seen and seen[obj] then return seen[obj] end
local s = seen or {}
local res = setmetatable({}, getmetatable(obj))
s[obj] = res
for k, v in pairs(obj) do res[copy(k, s)] = copy(v, s) end
return res
end
local function get_subs(numbers)
local result = {}
if #numbers == 2 then return {{numbers[1], numbers[2]}, {numbers[2], numbers[1]}} end
for i, number in pairs(numbers) do
local new_numbers = {}
for _, n in pairs(numbers) do if n ~= number then table.insert(new_numbers, n) end end
local tmp = get_subs(new_numbers)
for _, v in pairs(tmp) do
table.insert(v, 1, number)
table.insert(result, v)
end
end
return result
end
local SUBS = get_subs({0, 1, 2, 3, 4})
---@return MetaBoard
function MetaBoard:new(missionPage, isCalcRandom)
local newObj = {
baseBoard = CMH.Board:new(missionPage, isCalcRandom)
}
self.__index = self
setmetatable(newObj, self)
return newObj
end
function MetaBoard:findBestDisposition(criteriaFunctionID)
criteriaFunctionID = criteriaFunctionID or 0
local criteria = 0
local bestBoard, bestCriteria = {}, 9999999
for board in self:findBestDispositionIterator() do
board:simulate()
if criteriaFunctionID == 0 then
criteria = board:getTotalLostHP(board:isWin())
elseif criteriaFunctionID == 1 then
criteria = board:getTotalRemainingPercentHP(board:isWin())
elseif criteriaFunctionID == 2 then
criteria = board:getMinLostHPPercent(board:isWin())
end
if board:isWin() then
if criteria < bestCriteria then
bestCriteria = criteria
bestBoard = board
end
end
wipe(CMH.Board.CombatLog)
wipe(CMH.Board.HiddenCombatLog)
wipe(CMH.Board.CombatLogEvents)
end
return next(bestBoard) ~= nil and bestBoard or self.baseBoard
end
function MetaBoard:findBestDispositionIterator()
-- unique subs only
local hash = {}
local subs = SUBS
return function ()
for _, sub in ipairs(subs) do
local unitIDs = ''
for _, boardIndex in ipairs(sub) do
unitIDs = self.baseBoard.units[boardIndex] == nil and unitIDs .. '-1|' or unitIDs .. self.baseBoard.units[boardIndex].ID .. '|'
end
if not hash[unitIDs] then
--print(unitIDs)
--print(table.concat(sub, ';'))
hash[unitIDs] = true
local newBoard = copy(self.baseBoard)
for newIndex, oldIndex in ipairs(sub) do
if self.baseBoard.units[oldIndex] ~= nil then
-- newIndex starts from 1
newBoard.units[newIndex-1] = copy(self.baseBoard.units[oldIndex])
newBoard.units[newIndex-1].boardIndex = newIndex-1
--print(newIndex-1 .. ', ' .. oldIndex .. ': ' .. newBoard.units[newIndex-1].name)
else
newBoard.units[newIndex-1] = nil
end
end
newBoard.isCalcRandom = false
return newBoard
end
end
return nil
end
end