feat(packages): ludic.jobs - written jobs gated by standing and story, boards of posts rolled by the day on their own dice, progress counted from events and read back from state, handing in, rewards through a port, facts, a save section per scope

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-25 07:35:45 +03:00
parent e146c7a337
commit 411206e45a
14 changed files with 984 additions and 0 deletions

View file

@ -0,0 +1,96 @@
# jobs.ludic - the written jobs: offered by standing and story, taken, readied, handed in and paid
export function jobs_ok(i: int) -> bool { return i >= 0 and i < JOB_COUNT }
export function jobs_state(i: int) -> int {
jobs__ensure()
return jobs__st[i]
}
export function jobs_have(i: int) -> int {
jobs__ensure()
return jobs__hv[i]
}
export function jobs_ready_now(i: int) -> bool { return jobs_state(i) == JOBS_READY }
# taken and not yet paid
export function jobs_under_way(i: int) -> bool {
let s = jobs_state(i)
return s == JOBS_ACTIVE or s == JOBS_READY
}
# on offer: not taken, the scope's standing and the story far enough, and the game allowing it
export function jobs_offered(i: int) -> bool {
let d = Jobs[i]
if jobs_state(i) != JOBS_OFFERED { return false }
return JobsWorld.rep(d.scope) >= d.minrep and JobsWorld.stage() >= d.minstage and JobsWorld.open(i)
}
export function jobs_take(i: int) -> bool {
if not jobs_ok(i) or jobs_state(i) != JOBS_OFFERED { return false }
jobs__st[i] = JOBS_ACTIVE
jobs__hv[i] = 0
jobs__recheck_one(i)
return true
}
# a count has moved: a job with a need is ready when it is met
function jobs__moved(i: int, was: int) -> void {
let d = Jobs[i]
if d.need > 0 and jobs__hv[i] > d.need { jobs__hv[i] = d.need }
if jobs__hv[i] > was { jobs__fact(JOBS_F_PROGRESSED, i, -1, -1, jobs__hv[i], d.need) }
if jobs__st[i] == JOBS_ACTIVE and d.need > 0 and jobs__hv[i] >= d.need { jobs_ready(i) }
}
# the game's own play: a step counter, a mask of targets met
export function jobs_set_have(i: int, v: int) -> void {
let was = jobs_have(i)
jobs__hv[i] = v
jobs__moved(i, was)
}
export function jobs_add_have(i: int, n: int) -> void { jobs_set_have(i, jobs_have(i) + n) }
export function jobs_mark(i: int, bit: int) -> void { jobs_set_have(i, jobs_have(i) | (1 << bit)) }
# everything in hand
export function jobs_ready(i: int) -> void {
if jobs_state(i) != JOBS_ACTIVE { return }
jobs__st[i] = JOBS_READY
jobs__fact(JOBS_F_COMPLETED, i, -1, -1, jobs__hv[i], Jobs[i].need)
}
export function jobs_hand_in(i: int) -> bool {
if not jobs_ok(i) or jobs_state(i) != JOBS_READY { return false }
let d = Jobs[i]
jobs__st[i] = JOBS_DONE
if d.group >= 0 and d.group < JOBS_GROUPS { jobs__done_n[d.group] += 1 }
JobsPay.reward(d.scope, d.money, d.rep)
jobs__fact(JOBS_F_HANDED_IN, i, -1, -1, jobs__hv[i], d.need)
return true
}
# finished and paid in one go, whatever the count says
export function jobs_complete(i: int) -> bool {
if not jobs_ok(i) or not jobs_under_way(i) { return false }
jobs_ready(i)
return jobs_hand_in(i)
}
# the state outright: the host's word for a party job, a test
export function jobs_set(i: int, state: int, have: int) -> void {
jobs__ensure()
jobs__st[i] = state
jobs__hv[i] = have
}
export function jobs_done(group: int) -> int {
jobs__ensure()
if group < 0 or group >= JOBS_GROUPS { return 0 }
return jobs__done_n[group]
}
export function jobs_set_done(group: int, n: int) -> void {
jobs__ensure()
if group >= 0 and group < JOBS_GROUPS { jobs__done_n[group] = n }
}