Improve funky.lua

This commit is contained in:
Emik 2026-06-15 17:13:54 +02:00
parent 645d073e17
commit 8effb33080
Signed by: emik
GPG key ID: 6B0CD72A5E503BDF
8 changed files with 148 additions and 32 deletions

View file

@ -3,7 +3,7 @@
"id": "Roland",
"name": "Roland",
"prefix": "Roland",
"version": "2.8.30",
"version": "2.8.31",
"badge_colour": "8BE9FD",
"display_name": "Roland",
"main_file": "src/main.lua",

View file

@ -141,7 +141,7 @@ back {
modifiers.Roland_swapper_deck = true
modifiers.Roland_alt_swapper_deck = modifiers.Roland_alt_swapper_deck or self:is_alt()
end,
calculate = f().noop,
calculate = f.noop,
}
local swapper = {Spectral = "Tarot", Tarot = "Spectral"}

View file

@ -67,7 +67,7 @@ SMODS.Challenge {
local spin_to_win = SMODS.Challenge {
key = "Spin_To_Win",
jokers = f(4):map(f().const {id = "j_joker", eternal = true}):table(),
jokers = f(4):map(f.const {id = "j_joker", eternal = true}):table(),
restrictions = {banned_cards = {{id = "c_Roland_coolheaded"}}},
pronouns = "they_them",
apply = function(self)
@ -91,7 +91,7 @@ SMODS.Challenge {
pronouns = "she_them",
}
local starting_jokers = f(5):map(f().const {id = "j_joker"}):table()
local starting_jokers = f(5):map(f.const {id = "j_joker"}):table()
SMODS.Challenge {
key = "Eternally_Amber",

View file

@ -161,7 +161,7 @@ function Card:calculate_joker(context, ...)
local key = "Roland_frozen_" .. v
ability[key] = ability[key] or ret[1][v]
return ability[key]
end):where(f().id):table()
end):where(f.id):table()
end
local orig_calculate_dollar_bonus = Card.calculate_dollar_bonus

View file

@ -701,7 +701,7 @@ joker {
card.Roland_amber_waiting = true
local cards = card.area.cards
local keys = f(cards):where(f().nq(card)):keys():table()
local keys = f(cards):where(f.nq(card)):keys():table()
if not next(keys) then
return
@ -849,7 +849,7 @@ joker {
return f(context.scoring_hand):any(function(x)
return x:is_suit(v.suit) and x.base.value == v.value
end) or {}
end):any(f().eq(context.other_card)) and {xmult = card.ability.extra.xmult} or nil
end):any(f.eq(context.other_card)) and {xmult = card.ability.extra.xmult} or nil
end,
Bakery_can_use = function(self, card)
local key = self:Roland_idle_status(card)

View file

@ -3,10 +3,91 @@
---@license MPL-2.0
---@version 1.0.0
---
---@alias FFrom (fun<K, V>(iter: table<K, V>, fpairs?: fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): K?, V?)): F | { [K]: V })|(fun(iter: number, fpairs?: number, step?: number): F | { [number]: number })|(fun<V>(iter: string): (fun(table: { [string]: V }): V))|(fun<V>(iter: string): (fun(table: { [string]: V }): V))|(fun<K, V>(iter: fun(): K, V): F | { [K]: V })|(fun(iter: false): fun(): false)|(fun(iter: true): fun(): true)|(fun(iter: nil): F)
---@class F
local f = {}
if not f then
---@generic I, O
---@param first fun(v: I): O
---@return fun(v: I): O
function f.chain(first)
error {first}
end
---@generic I, T, O
---@param first fun(v: I): T
---@param second fun(v: T): O
---@return fun(v: I): O
function f.chain(first, second)
error {first, second}
end
---@generic I, T1, T2, O
---@param first fun(v: I): T1
---@param second fun(v: T1): T2
---@param third fun(v: T2): O
---@return fun(v: I): O
function f.chain(first, second, third)
error {first, second, third}
end
---@generic I, T1, T2, T3, O
---@param first fun(v: I): T1
---@param second fun(v: T1): T2
---@param third fun(v: T2): T3
---@param fourth fun(v: T3): O
---@return fun(v: I): O
function f.chain(first, second, third, fourth)
error {first, second, third, fourth}
end
---@generic I, T1, T2, T3, T4, O
---@param first fun(v: I): T1
---@param second fun(v: T1): T2
---@param third fun(v: T2): T3
---@param fourth fun(v: T3): T4
---@param fifth fun(v: T4): O
---@return fun(v: I): O
function f.chain(first, second, third, fourth, fifth)
error {first, second, third, fourth, fifth}
end
---@generic I, O
---@param all {[1]: (fun(v: I): O)}
---@return fun(v: I): O
function f.chain(all)
error(all)
end
---@generic I, T, O
---@param all {[1]: (fun(v: I): T), [2]: (fun(v: T): O)}
---@return fun(v: I): O
function f.chain(all)
error(all)
end
---@generic I, T1, T2, O
---@param all {[1]: (fun(v: I): T1), [2]: (fun(v: T1): T2), [3]: (fun(v: T2): O)}
---@return fun(v: I): O
function f.chain(all)
error(all)
end
---@generic I, T1, T2, T3, O
---@param all {[1]: (fun(v: I): T1), [2]: (fun(v: T1): T2), [3]: (fun(v: T2): T3), [4]: (fun(v: T3): O)}
---@return fun(v: I): O
function f.chain(all)
error(all)
end
---@generic I, T1, T2, T3, T4, O
---@param all {[1]: (fun(v: I): T1), [2]: (fun(v: T1): T2), [3]: (fun(v: T2): T3), [4]: (fun(v: T3): T4), [4]: (fun(v: T4): O)}
---@return fun(v: I): O
function f.chain(all)
error(all)
end
---@generic K, V
---@param self F | { [K]: V }
---@return K?, V?
@ -137,32 +218,67 @@ function f.indices(v)
end
end
f[true and "chain"] = function(...)
for _, v in ipairs(...) do
if type(v) == "table" then
for _, vv in ipairs(v) do
ret = ret and function(...)
return vv(ret(...))
end or vv
end
else
ret = ret and function(...)
return v(ret(...))
end or v
end
end
return ret or f.noop
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
-- Iterating over `f` is far easier, but we do this for performance sake.
return {
all = f.all,
any = f.any,
chain = f.chain,
concat = f.concat,
const = f.const,
count = f.count,
eq = f.eq,
fals = f.fals,
flatmap = f.flatmap,
fold = f.fold,
from = f.from,
id = f.id,
index = f.index,
indices = f.indices,
map = f.map,
new = f.new,
next = fnext or f.noop,
noop = f.noop,
nq = f.nq,
tru = f.tru,
where = f.where,
each = f.each,
keys = f.keys,
pun = f.pun,
skip = f.skip,
slice = f.slice,
string = f.string,
swap = f.swap,
table = f.table,
take = f.take,
values = f.values,
}
end
--- Creates an enumeration.
---@generic K, V
---@param iter 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(iter: number, fpairs?: number, step?: number): F | { [number]: number }
---@overload fun(iter: string): (fun(table: { [string]: V }): V)
---@overload fun(iter: fun(): K, V): F | { [K]: V }
---@overload fun(iter: false): fun(): false
---@overload fun(iter: true): fun(): true
---@overload fun(iter: nil): F
---@type FFrom
function f.from(iter, fpairs, step)
if iter == nil then
return none
@ -207,7 +323,7 @@ function f.from(iter, fpairs, step)
end
end)
else
local next, context, k, v = autopairs(iter, fpairs)
local next, context, k, v = autopairs(iter, type(fpairs) == "function" and fpairs or nil)
return f.new(function()
k, v = next(context, k)
@ -650,5 +766,5 @@ function f:each(func)
end
none = f.new()
return f.from
local ret = (setmetatable or f.const(f.from))(f, {__call = f.from}) ---@type F|FFrom
return ret

View file

@ -69,7 +69,7 @@ SMODS.Tag {
if not tag.triggered and context.type == "Bakery_play_hand_late" and tag.ability.amount == 0 then
tag.triggered = true
tag:yep("X", G.C.RED, f().tru)
tag:yep("X", G.C.RED, f.tru)
end
if tag.triggered or

View file

@ -100,7 +100,7 @@ local orig_get_blind_amount = get_blind_amount
---@param ante number
---@return table|number
local function blind(ante)
return ante == 39 and 1e294 or (_G["to_number"] or f().id)(orig_get_blind_amount(ante))
return ante == 39 and 1e294 or (_G["to_number"] or f.id)(orig_get_blind_amount(ante))
end
local function no_harsh_ante_scaling()
@ -120,8 +120,8 @@ function get_blind_amount(ante, ...)
local big, rem = _G["Big"], tonumber(blind((ante % loop) + 1))
return ante / 15 >= loop and big:new(f(blind(ante - (loop * 15))):map(f().const(10)):table()) or
(ante / 9 >= loop and big:new(f(ante / loop - 8):map(f().const(10)):concat {rem}:table()) or
return ante / 15 >= loop and big:new(f(blind(ante - (loop * 15))):map(f.const(10)):table()) or
(ante / 9 >= loop and big:new(f(ante / loop - 8):map(f.const(10)):concat {rem}:table()) or
(ante / 2 >= loop and big:new {rem, ante / loop} or
(big.constants and big.constants.TEN or big:new {10}):pow(rem)))
end