Remove use of submodules in favor of own solution
3
.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "src/LuaFunctional"]
|
||||
path = src/LuaFunctional
|
||||
url = https://github.com/BakersDozenBagels/LuaFunctional.git
|
||||
66
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"Lua.diagnostics.severity": {
|
||||
"ambiguity-1": "Error",
|
||||
"assign-type-mismatch": "Error",
|
||||
"await-in-sync": "Error",
|
||||
"cast-local-type": "Error",
|
||||
"cast-type-mismatch": "Error",
|
||||
"circle-doc-class": "Error",
|
||||
"close-non-object": "Error",
|
||||
"code-after-break": "Error",
|
||||
"codestyle-check": "Error",
|
||||
"count-down-loop": "Error",
|
||||
"deprecated": "Error",
|
||||
"different-requires": "Error",
|
||||
"discard-returns": "Error",
|
||||
"doc-field-no-class": "Error",
|
||||
"duplicate-doc-alias": "Error",
|
||||
"duplicate-doc-field": "Error",
|
||||
"duplicate-doc-param": "Error",
|
||||
"duplicate-index": "Error",
|
||||
"duplicate-set-field": "Error",
|
||||
"empty-block": "Error",
|
||||
"global-element": "Error",
|
||||
"global-in-nil-env": "Error",
|
||||
"incomplete-signature-doc": "Error",
|
||||
"inject-field": "Error",
|
||||
"invisible": "Error",
|
||||
"lowercase-global": "Error",
|
||||
"missing-fields": "Error",
|
||||
"missing-global-doc": "Error",
|
||||
"missing-local-export-doc": "Error",
|
||||
"missing-parameter": "Error",
|
||||
"missing-return": "Error",
|
||||
"missing-return-value": "Error",
|
||||
"name-style-check": "Error",
|
||||
"need-check-nil": "Error",
|
||||
"newfield-call": "Error",
|
||||
"newline-call": "Error",
|
||||
"no-unknown": "Error",
|
||||
"not-yieldable": "Error",
|
||||
"param-type-mismatch": "Error",
|
||||
"redefined-local": "Error",
|
||||
"redundant-parameter": "Error",
|
||||
"redundant-return": "Error",
|
||||
"redundant-return-value": "Error",
|
||||
"redundant-value": "Error",
|
||||
"return-type-mismatch": "Error",
|
||||
"spell-check": "Error",
|
||||
"trailing-space": "Error",
|
||||
"unbalanced-assignments": "Error",
|
||||
"undefined-doc-class": "Error",
|
||||
"undefined-doc-name": "Error",
|
||||
"undefined-doc-param": "Error",
|
||||
"undefined-env-child": "Error",
|
||||
"undefined-field": "Error",
|
||||
"undefined-global": "Error",
|
||||
"unknown-cast-variable": "Error",
|
||||
"unknown-diag-code": "Error",
|
||||
"unknown-operator": "Error",
|
||||
"unreachable-code": "Error",
|
||||
"unused-function": "Error",
|
||||
"unused-label": "Error",
|
||||
"unused-local": "Error",
|
||||
"unused-vararg": "Error",
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 5cd6766468f04e36a5b25f0d55b82f5eeb164b56
|
||||
12
src/back.lua
|
|
@ -1,4 +1,4 @@
|
|||
local f, q = unpack(... or require "src.functional")
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
|
||||
local function save(ret)
|
||||
q(save_run)
|
||||
|
|
@ -47,7 +47,7 @@ local back = (function()
|
|||
key = key,
|
||||
pos = tbl.pos,
|
||||
atlas = "back",
|
||||
config = tbl.config and f(tbl.config):into() or nil,
|
||||
config = tbl.config and f(tbl.config):table() or nil,
|
||||
loc_vars = function(self, ...)
|
||||
local ret = tbl.loc_vars and tbl.loc_vars(self, ...) or {}
|
||||
ret.key = self:is_alt() and self.key .. "_alt" or self.key
|
||||
|
|
@ -102,7 +102,7 @@ back {
|
|||
q {
|
||||
delay = 0.4,
|
||||
func = function()
|
||||
SMODS.calculate_effect({message = localize("ph_boss_disabled")}, card)
|
||||
SMODS.calculate_effect({message = localize "ph_boss_disabled"}, card)
|
||||
G.GAME.blind:wiggle()
|
||||
play_sound "timpani"
|
||||
delay(0.4)
|
||||
|
|
@ -140,7 +140,7 @@ back {
|
|||
ease_dollars(-G.GAME.dollars)
|
||||
|
||||
attention_text {
|
||||
text = localize("k_nope_ex"),
|
||||
text = localize "k_nope_ex",
|
||||
backdrop_colour = G.C.MONEY,
|
||||
offset = {x = 0, y = 0},
|
||||
silent = true,
|
||||
|
|
@ -176,9 +176,9 @@ function create_card(_type, ...)
|
|||
return orig_create_card(swapper[_type] or _type, ...)
|
||||
end
|
||||
|
||||
local type = f(SMODS.ConsumableTypes):keys():filter(function(v)
|
||||
local type = f(SMODS.ConsumableTypes):keys():where(function(v)
|
||||
return v ~= _type
|
||||
end):into()
|
||||
end):table()
|
||||
|
||||
local has_type = SMODS.ConsumableTypes[_type]
|
||||
return orig_create_card(has_type and pseudorandom_element(type, pseudoseed "Roland_alt_swapper_deck") or _type, ...)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local f, q = unpack(... or require "src.functional")
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
|
||||
local blind = (function()
|
||||
local y = 0
|
||||
|
|
@ -35,9 +35,9 @@ local function common_rank()
|
|||
--- Tallies up a card area's cards.
|
||||
---@param card_area CardArea
|
||||
local function tally_up(card_area)
|
||||
f(card_area.cards):filter(function(v)
|
||||
f(card_area.cards):where(function(v)
|
||||
return not SMODS.has_no_rank(v)
|
||||
end):foreach(function(v)
|
||||
end):each(function(v)
|
||||
local id = v:get_id()
|
||||
to_name[id] = v.base.value
|
||||
tally[id] = (tally[id] or 0) + 1
|
||||
|
|
@ -48,7 +48,7 @@ local function common_rank()
|
|||
tally_up(G.hand)
|
||||
tally_up(G.discard)
|
||||
|
||||
local max_key = f(tally):reduce({-1 / 0, -1 / 0}, function(a, v, k)
|
||||
local max_key = f(tally):fold({-1 / 0, -1 / 0}, function(a, v, k)
|
||||
if v > a[1] or k > a[2] and v == a[1] then
|
||||
return {v, k}
|
||||
end
|
||||
|
|
@ -124,7 +124,7 @@ blind {
|
|||
return false
|
||||
end
|
||||
|
||||
f(G.hand.cards, ipairs):take(self.config.draw):foreach(function(v)
|
||||
f(G.hand.cards, ipairs):take(self.config.draw):each(function(v)
|
||||
G.hand:add_to_highlighted(v, true)
|
||||
end)
|
||||
|
||||
|
|
@ -149,7 +149,7 @@ blind {
|
|||
pronouns = "any_all",
|
||||
disable = function()
|
||||
q(function()
|
||||
f(G.hand.cards):foreach(function(v, i)
|
||||
f(G.hand.cards):each(function(v, i)
|
||||
draw_card(G.hand, G.deck, i / #G.hand.cards * 100, "up", false, v)
|
||||
end)
|
||||
end)
|
||||
|
|
@ -191,11 +191,11 @@ blind {
|
|||
return
|
||||
end
|
||||
|
||||
f(G.discard.cards):take(count):foreach(function(v, i)
|
||||
f(G.discard.cards):take(count):each(function(v, i)
|
||||
draw_card(G.discard, G.hand, i / count * 100, "up", false, v, nil, nil, true)
|
||||
end)
|
||||
|
||||
f(G.discard.cards):take(count):foreach(function(v, i)
|
||||
f(G.discard.cards):take(count):each(function(v, i)
|
||||
draw_card(G.hand, G.deck, i / count * 100, "up", false, v)
|
||||
end)
|
||||
end)
|
||||
|
|
@ -231,7 +231,7 @@ blind {
|
|||
local cards_added = {}
|
||||
local count = #G.hand.highlighted
|
||||
|
||||
f(G.hand.highlighted, ipairs):take(count):foreach(function(v, i)
|
||||
f(G.hand.highlighted, ipairs):take(count):each(function(v, i)
|
||||
local copy = copy_card(v)
|
||||
copy:add_to_deck()
|
||||
table.insert(G.hand, copy)
|
||||
|
|
@ -277,8 +277,10 @@ blind {
|
|||
|
||||
local needs_text_change
|
||||
|
||||
---comment
|
||||
---@param card_area CardArea|{cards: Card[]}
|
||||
local function process(card_area)
|
||||
f(card_area.cards):foreach(function(v)
|
||||
f(card_area.cards):each(function(v)
|
||||
local debuff = v.debuff
|
||||
v:set_debuff(self:recalc_debuff(v, false))
|
||||
needs_text_change = needs_text_change or debuff ~= v.debuff
|
||||
|
|
@ -327,7 +329,7 @@ end
|
|||
|
||||
function SMODS.current_mod:calculate(context)
|
||||
---@diagnostic disable-next-line: undefined-global
|
||||
local _ = type(G.calc) == "function" and G.calc(f(context):keys():conjoin(", "))
|
||||
local _ = type(G.calc) == "function" and G.calc(f(context):keys():string())
|
||||
local improbable, orig = G.GAME.modifiers.Roland_improbable, G.GAME.probabilities
|
||||
|
||||
-- Normally unreachable since we set it to nil ourselves,
|
||||
|
|
@ -462,7 +464,7 @@ local venerable_visage = blind {
|
|||
|
||||
delay(1)
|
||||
|
||||
f(G.playing_cards):foreach(function(v)
|
||||
f(G.playing_cards):each(function(v)
|
||||
q {
|
||||
trigger = "before",
|
||||
delay = speed,
|
||||
|
|
@ -475,7 +477,7 @@ local venerable_visage = blind {
|
|||
|
||||
delay(1)
|
||||
|
||||
f(G.P_CARDS):foreach(function(v)
|
||||
f(G.P_CARDS):each(function(v)
|
||||
q {
|
||||
delay = speed,
|
||||
func = function()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local f, q = unpack(... or require "src.functional")
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
local jokerful = {banned_cards = {}}
|
||||
local pastries = {banned_cards = {}, banned_tags = {}, banned_other = {}}
|
||||
-- local surgery = {banned_other = {}}
|
||||
|
|
@ -58,7 +58,7 @@ q(function()
|
|||
{G.P_BLINDS, is_banned_from_pastry, pastries.banned_other},
|
||||
{G.P_CENTERS, is_center_banned_from_pastry, pastries.banned_cards},
|
||||
-- {G.P_BLINDS, is_blind_banned_from_surgery, surgery.banned_other},
|
||||
}:foreach(function(v)
|
||||
f(v[1]):filter(v[2]):foreach(adder(v[3]))
|
||||
}:each(function(v)
|
||||
f(v[1]):where(v[2]):each(adder(v[3]))
|
||||
end)
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local f, q = unpack(... or require "src.functional")
|
||||
local _, q = unpack(... or require "lib.shared")
|
||||
local mod = SMODS.current_mod
|
||||
|
||||
SMODS.Atlas {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local f, q, u = unpack(... or require "src.functional")
|
||||
local f, q, u = unpack(... or require "lib.shared")
|
||||
|
||||
local joker = (function()
|
||||
local z = 0
|
||||
|
|
@ -63,7 +63,7 @@ local function level_up(hand, by, card)
|
|||
if hand == "all" or hand == "allhands" or hand == "all_hands" then
|
||||
update(localize "k_all_hands", "...", "...", "")
|
||||
|
||||
f(G.GAME.hands):keys():foreach(function(k)
|
||||
f(G.GAME.hands):keys():each(function(k)
|
||||
level_up_hand(card, k, nil, by)
|
||||
end)
|
||||
elseif hand_obj then
|
||||
|
|
@ -132,15 +132,15 @@ joker {
|
|||
return "DEBUFFED"
|
||||
end
|
||||
|
||||
return #G.GAME.tags == 0 and not f(G.consumeables.cards):filter(destructible):any() and
|
||||
f(G.jokers.cards):filter(is_mergeable_with(card)):any() and "FUSE" or "ESCAPE"
|
||||
return #G.GAME.tags == 0 and not f(G.consumeables.cards):any(destructible) and
|
||||
f(G.jokers.cards):any(is_mergeable_with(card)) and "FUSE" or "ESCAPE"
|
||||
end,
|
||||
Bakery_use_joker = function(_, card)
|
||||
if card.debuff then
|
||||
return
|
||||
end
|
||||
|
||||
local consumables = f(G.consumeables.cards):filter(destructible):into()
|
||||
local consumables = f(G.consumeables.cards):where(destructible):table()
|
||||
local consumable_count = #consumables
|
||||
local tag_count = #G.GAME.tags
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ joker {
|
|||
local level_sum, sell_sum = 0, 0
|
||||
local any_carbon = is_carbon(card)
|
||||
|
||||
f(G.jokers.cards):filter(is_mergeable_with(card)):foreach(function(v)
|
||||
f(G.jokers.cards):where(is_mergeable_with(card)):each(function(v)
|
||||
any_carbon = any_carbon or is_carbon(v)
|
||||
level_sum = level_sum + v.ability.extra.hands * (v.getEvalQty and v:getEvalQty() or 1)
|
||||
sell_sum = sell_sum + v.sell_cost * (v.getEvalQty and v:getEvalQty() or 1)
|
||||
|
|
@ -187,7 +187,7 @@ joker {
|
|||
local trigger = #G.GAME.tags >= 30 and "immediate" or "before"
|
||||
local delay = #G.GAME.tags >= 30 and 0 or 1 / #G.GAME.tags
|
||||
|
||||
f(G.GAME.tags):foreach(function(v)
|
||||
f(G.GAME.tags):each(function(v)
|
||||
q {
|
||||
trigger = trigger,
|
||||
blocking = #G.GAME.tags < 30,
|
||||
|
|
@ -198,19 +198,19 @@ joker {
|
|||
destroyed = destroyed + 1
|
||||
end)
|
||||
else
|
||||
f(consumables):foreach(function(v)
|
||||
f(consumables):each(function(v)
|
||||
v:start_dissolve({HEX "57ecabff"}, nil, 1.6)
|
||||
destroyed = destroyed + 1
|
||||
end)
|
||||
end
|
||||
|
||||
local hands = f(G.GAME.hands):filter(f "visible"):keys():into()
|
||||
local hands = f(G.GAME.hands):where(f "visible"):keys():table()
|
||||
|
||||
pseudoshuffle(hands, pseudoseed "RolandEscapey")
|
||||
local levels = destroyed * card.ability.extra.hands
|
||||
level_up("all", math.floor(levels / #hands), card)
|
||||
|
||||
f(hands):take(levels % #hands):foreach(function(v)
|
||||
f(hands):take(levels % #hands):each(function(v)
|
||||
level_up(v, 1, card)
|
||||
end)
|
||||
end,
|
||||
|
|
@ -372,7 +372,7 @@ joker {
|
|||
card.getting_sliced = true
|
||||
|
||||
q(function()
|
||||
local scored_cards = f(G.play.cards):filter(f "highlighted"):into()
|
||||
local scored_cards = f(G.play.cards):where(f "highlighted"):each()
|
||||
local copied = {}
|
||||
|
||||
for _ = 1, extra.times do
|
||||
|
|
|
|||
443
src/lib/funky.lua
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
---@author Emik
|
||||
---@copyright (c) 2026 Emik
|
||||
---@license MPL-2.0
|
||||
---@version 1.0.0
|
||||
---
|
||||
---@class F
|
||||
local f = {}
|
||||
|
||||
if not f then
|
||||
---@generic K, V
|
||||
---@param self F | { [K]: V }
|
||||
---@return K?, V?
|
||||
function f:next()
|
||||
error()
|
||||
end
|
||||
end
|
||||
|
||||
--- Always returns nil.
|
||||
---@return nil
|
||||
function f.noop()
|
||||
end
|
||||
|
||||
--- Always returns false.
|
||||
---@return false
|
||||
function f.fals()
|
||||
return false
|
||||
end
|
||||
|
||||
--- Always returns true.
|
||||
---@return true
|
||||
function f.tru()
|
||||
return true
|
||||
end
|
||||
|
||||
---@generic T
|
||||
---@param v T
|
||||
---@return fun(): T
|
||||
---@nodiscard
|
||||
function f.const(v)
|
||||
if v == true then
|
||||
return f.tru
|
||||
elseif v == false then
|
||||
return f.fals
|
||||
elseif v == nil then
|
||||
return f.noop
|
||||
end
|
||||
|
||||
return function()
|
||||
return v
|
||||
end
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param v K
|
||||
---@return fun(x: { [K]: V }): V
|
||||
---@nodiscard
|
||||
function f.index(v)
|
||||
return function(x)
|
||||
return x[v]
|
||||
end
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param fnext? fun(): K?, V?
|
||||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f.new(fnext)
|
||||
local ret = {next = fnext or f.noop}
|
||||
|
||||
for k, v in pairs(f) do
|
||||
ret[k] = v
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param tbl table<K, V>
|
||||
---@param fpairs? fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): K, V)
|
||||
---@return fun(tbl: table<K, V>, key: K): K, V
|
||||
---@return K
|
||||
---@return V
|
||||
local function autopairs(tbl, fpairs)
|
||||
return (fpairs or tbl[#tbl] and ipairs or pairs)(tbl)
|
||||
end
|
||||
|
||||
---@generic K, V, U
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func F|fun(v: V, k: K): U
|
||||
---@return F|{ [K]: U }
|
||||
---@nodiscard
|
||||
function f:map(func)
|
||||
return f.new(function()
|
||||
local k, v = self:next()
|
||||
|
||||
if k ~= nil then
|
||||
return k, func(v, k)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@generic K, V, U
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func F|fun(v: V, k: K): { [any]: U }
|
||||
---@param fpairs? fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): K, V)
|
||||
---@return F|{ [K]: U }
|
||||
---@nodiscard
|
||||
function f:flatmap(func, fpairs)
|
||||
-- local i = 0
|
||||
local vt, vk, vv, vp
|
||||
|
||||
return f.new(function()
|
||||
if vk then
|
||||
vk, vv = vp(vt, vk)
|
||||
|
||||
if vk ~= nil then
|
||||
-- i = i + 1
|
||||
-- return i, vv
|
||||
return vk, vv
|
||||
end
|
||||
end
|
||||
|
||||
while true do
|
||||
local k, v = self:next()
|
||||
|
||||
if k == nil then
|
||||
return
|
||||
end
|
||||
|
||||
v = func(v, k)
|
||||
|
||||
if type(v) ~= "table" then
|
||||
-- i = i + 1
|
||||
-- return i, v
|
||||
return k, v
|
||||
end
|
||||
|
||||
vp, vt, vk = autopairs(v, fpairs)
|
||||
vk, vv = vp(vt, vk)
|
||||
|
||||
if vk ~= nil then
|
||||
-- i = i + 1
|
||||
-- return i, vv
|
||||
return vk, vv
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f:where(func)
|
||||
local i = 0
|
||||
|
||||
return f.new(function()
|
||||
local k, v
|
||||
|
||||
while true do
|
||||
k, v = self:next()
|
||||
|
||||
if k == nil then
|
||||
return
|
||||
end
|
||||
|
||||
if func(v, k) then
|
||||
i = i + 1
|
||||
return i, v
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@return F|{ [integer]: K }
|
||||
---@nodiscard
|
||||
function f:keys()
|
||||
local i = 0
|
||||
|
||||
return f.new(function()
|
||||
local k = self:next()
|
||||
|
||||
if k ~= nil then
|
||||
i = i + 1
|
||||
return i, k
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@return F|{ [integer]: V }
|
||||
---@nodiscard
|
||||
function f:values()
|
||||
local i = 0
|
||||
|
||||
return f.new(function()
|
||||
local k, v = self:next()
|
||||
|
||||
if k ~= nil then
|
||||
i = i + 1
|
||||
return i, v
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param skip? integer
|
||||
---@param take? integer
|
||||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f:slice(skip, take)
|
||||
if (not skip or skip <= 0) and not take then
|
||||
return self
|
||||
end
|
||||
|
||||
local i = 0
|
||||
|
||||
return f.new(function()
|
||||
if take and take <= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
while skip and skip > 0 do
|
||||
skip = skip - 1
|
||||
self:next()
|
||||
end
|
||||
|
||||
local k, v = self:next()
|
||||
|
||||
if k ~= nil and (not take or i < take) then
|
||||
i = i + 1
|
||||
return i, v
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param n? integer
|
||||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f:skip(n)
|
||||
return self:slice(n)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param n? integer
|
||||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f:take(n)
|
||||
return self:slice(0, n)
|
||||
end
|
||||
|
||||
---@generic K, V, A
|
||||
---@param self F|{ [K]: V }
|
||||
---@param seed A
|
||||
---@param func fun(a: A, v: V, k: K): A
|
||||
---@return A
|
||||
---@overload fun(self: F|{ [K]: V }, seed: fun(a: A, v: V, k: K): A): A
|
||||
---@nodiscard
|
||||
function f:fold(seed, func)
|
||||
local k, v
|
||||
|
||||
if not func then
|
||||
func = seed
|
||||
k, seed = self:next()
|
||||
|
||||
if k == nil then
|
||||
return seed
|
||||
end
|
||||
end
|
||||
|
||||
while true do
|
||||
k, v = self:next()
|
||||
|
||||
if k == nil then
|
||||
return seed
|
||||
end
|
||||
|
||||
seed = func(seed, v, k)
|
||||
end
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@return boolean|V
|
||||
---@nodiscard
|
||||
function f:any(func)
|
||||
for k, v in self.next do
|
||||
if not func or func(v, k) then
|
||||
return v or true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@return boolean|V
|
||||
---@nodiscard
|
||||
function f:all(func)
|
||||
for k, v in self.next do
|
||||
if not func or not func(v, k) then
|
||||
return v and false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@return integer
|
||||
---@nodiscard
|
||||
function f:count(func)
|
||||
local ret = 0
|
||||
|
||||
for k, v in self.next do
|
||||
if not func or func(v, k) then
|
||||
ret = ret + 1
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@return string
|
||||
---@nodiscard
|
||||
function f:string()
|
||||
local k, v = self:next()
|
||||
|
||||
if k == nil then
|
||||
return "{}"
|
||||
end
|
||||
|
||||
local ret = "{" .. (type(k) == "number" and "" or tostring(k) .. ": ") .. tostring(v)
|
||||
|
||||
while true do
|
||||
k, v = self:next()
|
||||
|
||||
if k == nil then
|
||||
return ret .. "}"
|
||||
end
|
||||
|
||||
ret = ret .. ", " .. (type(k) == "number" and tostring(v) or tostring(k) .. ": " .. tostring(v))
|
||||
end
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@return { [K]: V }
|
||||
---@nodiscard
|
||||
function f:table()
|
||||
local ret = {}
|
||||
|
||||
for k, v in self.next do
|
||||
ret[k] = v
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func? F|fun(v: V, k: K)
|
||||
function f:each(func)
|
||||
for k, v in self.next do
|
||||
if func then
|
||||
func(v, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local none = f.new()
|
||||
|
||||
--- Creates an enumeration.
|
||||
---@generic K, V
|
||||
---@param tbl table<K, V>
|
||||
---@param fpairs? fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): K?, V?)
|
||||
---@param step? nil
|
||||
---@return F | { [K]: V }
|
||||
---@overload fun(tbl: number, fpairs?: number, step?: number): F | { [number]: number }
|
||||
---@overload fun(tbl: string|K): fun(table: { [string|K]: V }): V
|
||||
---@overload fun(tbl: false): fun(): false
|
||||
---@overload fun(tbl: true): fun(): true
|
||||
---@overload fun(tbl: nil): F
|
||||
return function(tbl, fpairs, step)
|
||||
if tbl == true then
|
||||
return f.tru
|
||||
elseif tbl == false then
|
||||
return f.fals
|
||||
elseif tbl == nil then
|
||||
return none
|
||||
end
|
||||
|
||||
local tbl_type = type(tbl)
|
||||
|
||||
if tbl_type == "string" then
|
||||
return f.index(tbl)
|
||||
elseif tbl_type == "number" then
|
||||
local ik = 0
|
||||
local start = fpairs and tbl or 1
|
||||
|
||||
local stop = not fpairs and tbl or
|
||||
(type(fpairs) == "number") and fpairs or error("Invalid argument type for 'fpairs': " .. type(fpairs))
|
||||
|
||||
if step ~= 0 and ((step < 0) == (start < stop)) then
|
||||
return none
|
||||
end
|
||||
|
||||
return f.new(function()
|
||||
local iv = tbl + ik * (step or 1)
|
||||
ik = ik + 1
|
||||
|
||||
if start > stop and iv >= stop or
|
||||
start < stop and iv <= stop or
|
||||
start == stop and iv == stop then
|
||||
return ik, iv
|
||||
end
|
||||
end)
|
||||
elseif tbl_type ~= "table" then
|
||||
error("Invalid argument type for 'tbl': " .. type(tbl))
|
||||
end
|
||||
|
||||
local next, context, k, v = autopairs(tbl, fpairs)
|
||||
|
||||
return f.new(function()
|
||||
k, v = next(context, k)
|
||||
return k, v
|
||||
end)
|
||||
end
|
||||
|
|
@ -23,10 +23,7 @@ local function protect_ev(fun)
|
|||
return fun
|
||||
end
|
||||
|
||||
local origf = F
|
||||
local luaf = assert(SMODS.load_file "src/LuaFunctional/functional.lua")() or require "src.LuaFunctional.functional"
|
||||
F = origf -- We do not condone globals as side effects!
|
||||
|
||||
-- This exists to remove the @deprecated warning.
|
||||
if false then
|
||||
---Returns the elements from the given `list`. This function is equivalent to
|
||||
---```lua
|
||||
|
|
@ -58,36 +55,7 @@ if false then
|
|||
end
|
||||
end
|
||||
|
||||
---@class Query<K, V>: metatable
|
||||
local _ = luaf._proto
|
||||
|
||||
--- Creates a non-numerically-indexed query from the given table.
|
||||
---@param obj table?
|
||||
---@param f_pairs? fun(t: table): unknown
|
||||
---@param numeric boolean?
|
||||
---@return Query
|
||||
---@overload fun(obj: string): (fun(any): any)
|
||||
-- ---@overload fun(obj: true): (fun(): true)
|
||||
-- ---@overload fun(obj: false): (fun(): false)
|
||||
local function f(obj, f_pairs, numeric)
|
||||
if obj == true then
|
||||
return luaf.tru
|
||||
elseif obj == false then
|
||||
return luaf.fals
|
||||
elseif obj == nil then
|
||||
return luaf.pairs {}
|
||||
elseif type(obj) == "string" then
|
||||
return luaf.index(obj)
|
||||
elseif type(obj) ~= "table" then
|
||||
error("Invalid argument type for f's obj: " .. type(obj))
|
||||
elseif f_pairs then
|
||||
return luaf.from(obj, f_pairs, numeric ~= false)
|
||||
elseif obj[#obj] then
|
||||
return luaf.ipairs(obj)
|
||||
else
|
||||
return luaf.pairs(obj)
|
||||
end
|
||||
end
|
||||
local f = assert(SMODS.load_file "src/lib/funky.lua")() or require "lib.funky"
|
||||
|
||||
--- Queues an event to be run.
|
||||
--- Note that events added this way implicitly `return true` unless you explicitly `return false`, unlike the vanilla ones.
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
local qol = assert(SMODS.load_file "src/functional.lua")() or require "src.functional"
|
||||
local qol = assert(SMODS.load_file "lib/shared.lua")() or require "lib.shared"
|
||||
|
||||
qol[1] {"challenge", "spectral", "tweaks", "blind", "charm", "joker", "back", "seal"}:foreach(function(v)
|
||||
qol[1] {"challenge", "spectral", "tweaks", "blind", "charm", "joker", "back", "seal"}:each(function(v)
|
||||
assert(SMODS.load_file("src/" .. v .. ".lua"))(qol)
|
||||
end)
|
||||
|
||||
if Balatest then
|
||||
qol[1] {"joker", "blind", "spectral"}:foreach(function(v)
|
||||
qol[1] {"joker", "blind", "spectral"}:each(function(v)
|
||||
assert(SMODS.load_file("src/tests/" .. v .. ".tests.lua"))(qol)
|
||||
end)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local f, q = unpack(... or require "src.functional")
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
|
||||
SMODS.Atlas {
|
||||
px = 71,
|
||||
|
|
@ -23,7 +23,7 @@ SMODS.Seal {
|
|||
local tag = Tag(get_next_tag_key "Roland_glass")
|
||||
|
||||
if tag.name == "Orbital Tag" then
|
||||
local hands = f(G.GAME.hands):filter(f "visible"):keys():into()
|
||||
local hands = f(G.GAME.hands):where(f "visible"):keys():table()
|
||||
tag.ability.orbital_hand = pseudorandom_element(hands, pseudoseed "Roland_glass")
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local f, q, u = unpack(... or require "src.functional")
|
||||
local f, q, u = unpack(... or require "lib.shared")
|
||||
|
||||
local spectral = (function()
|
||||
local x = 0
|
||||
|
|
@ -47,7 +47,7 @@ spectral {
|
|||
return u() and card.ability.extra.amount == #Bakery_API.get_highlighted()
|
||||
end,
|
||||
use = function(_, card)
|
||||
f(Bakery_API.get_highlighted()):foreach(function(v)
|
||||
f(Bakery_API.get_highlighted()):each(function(v)
|
||||
q {
|
||||
delay = 0.1,
|
||||
func = function()
|
||||
|
|
@ -78,10 +78,10 @@ spectral {
|
|||
return u() and #G.hand.cards > 0
|
||||
end,
|
||||
use = function(_, card, _)
|
||||
local cards = f(G.hand.cards, ipairs):into()
|
||||
local cards = f(G.hand.cards, ipairs):table()
|
||||
pseudoshuffle(cards, pseudoseed "RolandDual")
|
||||
|
||||
f(cards):take(card.ability.extra.amount):foreach(function(v)
|
||||
f(cards):take(card.ability.extra.amount):each(function(v)
|
||||
local seal
|
||||
|
||||
for _ = 1, 31 do
|
||||
|
|
@ -109,7 +109,7 @@ spectral {
|
|||
return u() and #Bakery_API.get_highlighted() == card.ability.extra.amount
|
||||
end,
|
||||
use = function(_, _, _)
|
||||
f(Bakery_API.get_highlighted()):foreach(function(v)
|
||||
f(Bakery_API.get_highlighted()):each(function(v)
|
||||
v:set_seal "Roland_glass"
|
||||
end)
|
||||
end,
|
||||
|
|
@ -128,7 +128,7 @@ local void = spectral {
|
|||
return {vars = {card.ability.extra.amount}}
|
||||
end,
|
||||
can_use = function()
|
||||
return #G.playing_cards > 1 and u()
|
||||
return #G.playing_cards > 1 and not not u()
|
||||
end,
|
||||
use = function(_, card)
|
||||
local function destructible(v)
|
||||
|
|
@ -145,14 +145,14 @@ local void = spectral {
|
|||
end
|
||||
|
||||
local function void()
|
||||
local cards = f(G.playing_cards):filter(destructible):into()
|
||||
local cards = f(G.playing_cards):where(destructible):table()
|
||||
|
||||
local function calculate_joker(v)
|
||||
v:calculate_joker {remove_playing_cards = true, removed = cards}
|
||||
end
|
||||
|
||||
f(cards):foreach(destroy)
|
||||
f(G.jokers.cards):foreach(calculate_joker)
|
||||
f(cards):each(destroy)
|
||||
f(G.jokers.cards):each(calculate_joker)
|
||||
|
||||
for _ = 1, card.ability.extra.amount do
|
||||
local cryptid = create_card(nil, G.consumeables, nil, nil, nil, nil, "c_cryptid", "void")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local f = unpack(... or require "src.functional")
|
||||
local f = unpack(... or require "lib.shared")
|
||||
|
||||
if not Balatest then
|
||||
return
|
||||
|
|
@ -26,7 +26,7 @@ Balatest.TestPlay {
|
|||
deck = {cards = {{s = "S", r = "2", e = "m_lucky"}, {s = "S", r = "3"}}},
|
||||
execute = function()
|
||||
Balatest.play_hand {"2S"}
|
||||
Balatest.next_round("bl_small")
|
||||
Balatest.next_round "bl_small"
|
||||
Balatest.play_hand {"2S"}
|
||||
end,
|
||||
assert = function()
|
||||
|
|
@ -141,7 +141,7 @@ Balatest.TestPlay {
|
|||
Balatest.wait_for_input()
|
||||
end,
|
||||
assert = function()
|
||||
f(G.hand.cards):foreach(function(v, k)
|
||||
f(G.hand.cards):each(function(v, k)
|
||||
local message = v.debuff and
|
||||
"Card " .. k .. " should not be debuffed" or
|
||||
"Card " .. k .. " should be debuffed"
|
||||
|
|
@ -166,7 +166,7 @@ Balatest.TestPlay {
|
|||
Balatest.play_hand {"2S"}
|
||||
end,
|
||||
assert = function()
|
||||
f(G.hand.cards):foreach(function(v, k)
|
||||
f(G.hand.cards):each(function(v, k)
|
||||
local message = v.debuff and
|
||||
"Card " .. k .. " should not be debuffed" or
|
||||
"Card " .. k .. " should be debuffed"
|
||||
|
|
@ -185,7 +185,7 @@ Balatest.TestPlay {
|
|||
Balatest.wait_for_input()
|
||||
end,
|
||||
assert = function()
|
||||
f(G.hand.cards):foreach(function(v, k)
|
||||
f(G.hand.cards):each(function(v, k)
|
||||
Balatest.assert(not v.debuff, "Card " .. k .. " should not be debuffed")
|
||||
end)
|
||||
end,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local _, q = unpack(... or require "src.functional")
|
||||
local _, q = unpack(... or require "lib.shared")
|
||||
|
||||
SMODS.Joker:take_ownership("joker", {cost = 1}, true)
|
||||
local orig_can_highlight = CardArea.can_highlight
|
||||
|
|
|
|||