feat(packages): ludic.gear - kinds of kit with tiers bought flat through a purse port once the standing is there, the kind's item following, per-tier values and mults, stack limits, the hand and charges that burn by the game hour, facts for a tier bought and a charge run out, a save section by key

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-25 07:45:29 +03:00
parent 79ed7a335b
commit cc930a114f
11 changed files with 569 additions and 0 deletions

View file

@ -0,0 +1,163 @@
# gear_test.ludic - tiers bought with a fake purse once the standing is there, the item that follows,
# values by tier, the stack's room, a hand whose charges burn down and run out, the save by key
import "ludic.gear"
import "ludic.base"
program GearTest {
numbers float
const IT_ROD: int = 3
const IT_TORCH: int = 5
const IT_LAMP: int = 6
def GearKinds rod { tiers: 3, names: ["Rod", "Reel", "Guide's rod"], cost: [30, 100, 300], rep: [0, 10, 40], item: IT_ROD }
def GearKinds camera { tiers: 2, names: ["Camera", "Zoom"], cost: [0, 150], rep: [0, 20], start: 1 }
def GearKinds pack { tiers: 3, names: ["Pack", "Frame", "Hauler"], cost: [20, 60, 120], rep: [0, 0, 0], mult: [1.0, 1.3, 1.7, 2.2] }
def GearValues bite { gear: GEAR_ROD, at: [1.0, 1.0, 0.75, 0.55] }
def GearValues drain { gear: GEAR_CAMERA, at: [14.0, 14.0, 8.0] }
def GearCharges torch { item: IT_TORCH, full: 60.0, per_hour: 60.0 }
def GearCharges lamp { item: IT_LAMP, full: 100.0, rate: GV_DRAIN }
def GearCharges radio { item: 9, full: 100.0, per_hour: 5.0, hand: false }
var money: int = 0
var rep: int = 0
var pack: []int = null
var hide_pack: bool = false
function purse_money() -> int { return money }
function purse_spend(n: int) -> bool {
if n > money { return false }
money -= n
return true
}
function purse_rep() -> int { return rep }
function pack_count(it: int) -> int { return pack[it] }
function pack_add(it: int, n: int) -> int {
pack[it] = pack[it] + n
return n
}
function hidden(k: int) -> bool { return hide_pack and k == GEAR_PACK }
bind GearPurse { money: fn purse_money, spend: fn purse_spend, rep: fn purse_rep }
bind GearPack { count: fn pack_count, add: fn pack_add }
bind GearWorld { hidden: fn hidden }
function fresh() -> void {
money = 0
rep = 0
hide_pack = false
pack = new []int
for i in 0 .. 12 { push(pack, 0) }
gear_reset()
}
function ran_out() -> int {
let fs = q_drain(gear_facts())
var n = -1
for i in 0 .. len(fs) { if fs[i].what == GEAR_RAN_OUT { n = fs[i].charge } }
return n
}
test "a new trip starts where the kinds say" {
fresh()
expect_eq(gear_level(GEAR_ROD), 0)
expect_eq(gear_level(GEAR_CAMERA), 1)
expect(gear_next_name(GEAR_CAMERA) == "Zoom")
expect_eq(gear_next_cost(GEAR_ROD), 30)
}
test "bought with money once the standing is there, and the item follows" {
fresh()
expect(not gear_buy(GEAR_ROD))
money = 200
expect(gear_buy(GEAR_ROD))
expect_eq(money, 170)
expect_eq(pack[IT_ROD], 1)
expect(not gear_can_buy(GEAR_ROD))
rep = 10
expect(gear_buy(GEAR_ROD))
expect_eq(pack[IT_ROD], 1)
let fs = q_drain(gear_facts())
expect_eq(len(fs), 2)
expect_eq(fs[1].what, GEAR_BOUGHT)
expect_eq(fs[1].level, 2)
expect_eq(fs[1].cost, 100)
}
test "the best tier is the end, and a hidden kind is not for sale" {
fresh()
money = 1000
rep = 50
for i in 0 .. 5 { gear_buy(GEAR_PACK) }
expect(gear_best(GEAR_PACK))
expect_eq(gear_level(GEAR_PACK), 3)
fresh()
money = 100
hide_pack = true
expect(not gear_buy(GEAR_PACK))
expect_eq(len(gear_kinds_at(-1)), 2)
}
test "a tier decides a value and a mult, and the stack's room follows" {
fresh()
expect_eq(gear_value(GV_BITE), 1.0)
gear_set_level(GEAR_ROD, 3)
expect_eq(gear_value(GV_BITE), 0.55)
expect_eq(gear_mult(GEAR_PACK), 1.0)
gear_set_level(GEAR_PACK, 2)
expect_eq(gear_mult(GEAR_PACK), 1.7)
expect_eq(gear_stack_limit(10, gear_mult(GEAR_PACK)), 17)
expect_eq(gear_stack_limit(1, 3.0), 1)
expect_eq(gear_stack_limit(4, 0.1), 1)
expect_eq(gear_mult(GEAR_ROD), 1.0)
}
test "a carried item counts as the first tier" {
fresh()
pack[IT_ROD] = 1
gear_sync()
expect_eq(gear_level(GEAR_ROD), 1)
}
test "a held charge runs only in the hand, burns by the hour and runs out" {
fresh()
let t = CHARGE_TORCH
expect(not gear_run(t, true))
gear_set_hand(IT_TORCH)
expect(gear_run(t, true))
expect(gear_lit())
gear_system().tick(tick_new(0.1, 1, 0.5))
expect_eq(gear_charge(t), 30.0)
gear_system().tick(tick_new(0.1, 2, 0.6))
expect_eq(gear_charge(t), 0.0)
expect(not gear_lit())
expect_eq(ran_out(), t)
expect(not gear_run(t, true))
}
test "a charge's rate can be its tier's, and a new hand puts the light out" {
fresh()
gear_set_hand(IT_LAMP)
gear_run(CHARGE_LAMP, true)
gear_system().tick(tick_new(0.1, 1, 1.0))
expect_eq(gear_charge(CHARGE_LAMP), 86.0)
gear_set_level(GEAR_CAMERA, 2)
gear_system().tick(tick_new(0.1, 2, 1.0))
expect_eq(gear_charge(CHARGE_LAMP), 78.0)
gear_run(CHARGE_RADIO, true)
gear_set_hand(-1)
expect(not gear_running(CHARGE_LAMP))
expect(gear_running(CHARGE_RADIO))
}
test "levels and charges are saved by key" {
fresh()
gear_set_level(GEAR_ROD, 2)
gear_charge_set(CHARGE_TORCH, 12.5)
let v = gear_save()
fresh()
gear_load(v, 1)
expect_eq(gear_level(GEAR_ROD), 2)
expect_eq(gear_level(GEAR_CAMERA), 1)
expect_eq(gear_charge(CHARGE_TORCH), 12.5)
expect_eq(gear_charge(CHARGE_LAMP), 100.0)
}
}