Module:DiceUtils: Difference between revisions
Jump to navigation
Jump to search
(Lua module test for dice damage calculation with multiple dice/damage types) |
No edit summary |
||
(18 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
function p. | -- For internal use only | ||
function p._parseDiceInfo(diceStr) | |||
local dice = string.gmatch(diceStr, "([^,]+)") | |||
local result = {} | |||
for die in dice do | |||
-- Search for modifier info | |||
local modIdx = string.find(die, "+") or string.find(die, "-") | |||
local dieMod = modIdx and tonumber(string.sub(die, modIdx)) or 0 | |||
local die_ = modIdx and string.sub(die, 1, modIdx - 1) or die | |||
local idx = string.find(die_, "d") | |||
local dieCount = string.sub(die_, 1, idx - 1) -- Holds the value before 'd' (die count) | |||
local dieType = string.sub(die_, idx + 1) -- Holds the value after 'd' (die type) | |||
local info = { | |||
count = dieCount, | |||
type_ = dieType, | |||
mod_ = dieMod | |||
} | |||
table.insert(result, info) | |||
end | |||
return result | |||
end | |||
-- For internal use only | |||
function p._average(diceInfo, modifier) | |||
local minDamage = 0 | |||
local maxDamage = 0 | |||
for i, info in ipairs(diceInfo) do | |||
-- Minimum damage cannot be below 0 | |||
if ((info.count + info.mod_) > 0) then | |||
minDamage = minDamage + info.count + info.mod_ | |||
end | |||
maxDamage = maxDamage + info.count * info.type_ + info.mod_ | |||
end | |||
if ((minDamage + modifier) < 0) then | |||
minDamage = 0 | |||
else | |||
minDamage = minDamage + modifier | |||
end | |||
if ((maxDamage + modifier) < 0) then | |||
maxDamage = 0 | |||
else | |||
maxDamage = maxDamage + modifier | |||
end | |||
return string.format("(%d~%d)", minDamage, maxDamage) | |||
end | |||
-- For internal use only | |||
function p._diceInfoText(diceInfo, modifier) | |||
local diceText = "" | |||
local modText = "" | |||
for i, info in ipairs(diceInfo) do | |||
if diceText == "" then | |||
diceText = info.count .. "d" .. info.type_ | |||
else | |||
diceText = diceText .. " + " .. info.count .. "d" .. info.type_ | |||
end | |||
local modText_ = (info.mod_ == 0) and | |||
"" or ((info.mod_ > 0 and " + " or " - ") .. math.abs(info.mod_)) | |||
if modText == "" then | |||
modText = modText_ | |||
else | |||
modText = modText .. modText_ | |||
end | |||
end | |||
if not (modText == "") then | |||
diceText = diceText .. modText | |||
end | |||
return diceText .. ((modifier == 0) and | |||
"" or ((modifier > 0 and " + " or " - ") .. math.abs(modifier))) | |||
end | |||
function p.average(frame) | |||
local args = frame.args | |||
local dice = args.dice | |||
local modifier = tonumber(args.modifier) or 0 | |||
if dice == nil then return "" end | |||
local diceInfo = p._parseDiceInfo(dice) | |||
return p._average(diceInfo, modifier) | |||
end | |||
function p.diceInfoText(frame) | |||
local args = frame.args | |||
local dice = args.dice | |||
local modifier = tonumber(args.modifier) or 0 | |||
if dice == nil then return "" end | |||
local diceInfo = p._parseDiceInfo(dice) | |||
return p._diceInfoText(diceInfo, modifier) | |||
end | |||
function p.diceInfoTextWithAvg(frame) | |||
local args = frame.args | |||
local dice = args.dice | |||
local modifier = tonumber(args.modifier) or 0 | |||
if dice == nil then return "" end | |||
local diceInfo = p._parseDiceInfo(dice) | |||
return p._diceInfoText(diceInfo, modifier) .. " " .. p._average(diceInfo, modifier) | |||
end | end | ||
return p | return p |
Latest revision as of 06:33, 21 July 2023
Documentation for this module may be created at Module:DiceUtils/doc
local p = {}
-- For internal use only
function p._parseDiceInfo(diceStr)
local dice = string.gmatch(diceStr, "([^,]+)")
local result = {}
for die in dice do
-- Search for modifier info
local modIdx = string.find(die, "+") or string.find(die, "-")
local dieMod = modIdx and tonumber(string.sub(die, modIdx)) or 0
local die_ = modIdx and string.sub(die, 1, modIdx - 1) or die
local idx = string.find(die_, "d")
local dieCount = string.sub(die_, 1, idx - 1) -- Holds the value before 'd' (die count)
local dieType = string.sub(die_, idx + 1) -- Holds the value after 'd' (die type)
local info = {
count = dieCount,
type_ = dieType,
mod_ = dieMod
}
table.insert(result, info)
end
return result
end
-- For internal use only
function p._average(diceInfo, modifier)
local minDamage = 0
local maxDamage = 0
for i, info in ipairs(diceInfo) do
-- Minimum damage cannot be below 0
if ((info.count + info.mod_) > 0) then
minDamage = minDamage + info.count + info.mod_
end
maxDamage = maxDamage + info.count * info.type_ + info.mod_
end
if ((minDamage + modifier) < 0) then
minDamage = 0
else
minDamage = minDamage + modifier
end
if ((maxDamage + modifier) < 0) then
maxDamage = 0
else
maxDamage = maxDamage + modifier
end
return string.format("(%d~%d)", minDamage, maxDamage)
end
-- For internal use only
function p._diceInfoText(diceInfo, modifier)
local diceText = ""
local modText = ""
for i, info in ipairs(diceInfo) do
if diceText == "" then
diceText = info.count .. "d" .. info.type_
else
diceText = diceText .. " + " .. info.count .. "d" .. info.type_
end
local modText_ = (info.mod_ == 0) and
"" or ((info.mod_ > 0 and " + " or " - ") .. math.abs(info.mod_))
if modText == "" then
modText = modText_
else
modText = modText .. modText_
end
end
if not (modText == "") then
diceText = diceText .. modText
end
return diceText .. ((modifier == 0) and
"" or ((modifier > 0 and " + " or " - ") .. math.abs(modifier)))
end
function p.average(frame)
local args = frame.args
local dice = args.dice
local modifier = tonumber(args.modifier) or 0
if dice == nil then return "" end
local diceInfo = p._parseDiceInfo(dice)
return p._average(diceInfo, modifier)
end
function p.diceInfoText(frame)
local args = frame.args
local dice = args.dice
local modifier = tonumber(args.modifier) or 0
if dice == nil then return "" end
local diceInfo = p._parseDiceInfo(dice)
return p._diceInfoText(diceInfo, modifier)
end
function p.diceInfoTextWithAvg(frame)
local args = frame.args
local dice = args.dice
local modifier = tonumber(args.modifier) or 0
if dice == nil then return "" end
local diceInfo = p._parseDiceInfo(dice)
return p._diceInfoText(diceInfo, modifier) .. " " .. p._average(diceInfo, modifier)
end
return p