# jobs_test.ludic - written jobs gated by standing and story, counted by events and by state, readied # and paid through a fake purse; a board rolled from the day; the party's scope; the save by key import "ludic.jobs" import "ludic.base" program JobsTest { numbers float const K_FISH: int = 0 const K_PHOTO: int = 1 const K_WOOD: int = 2 def Jobs catch { group: 0, kind: K_FISH, need: 3, money: 30, rep: 5 } def Jobs deer { group: 0, kind: K_PHOTO, param: 4, need: 1, money: 20, rep: 2, minrep: 10 } def Jobs ten { group: 0, kind: K_FISH, need: 10, money: 70, rep: 12, scope: JOBS_PARTY } def Jobs still { group: 1, need: 0, money: 60, rep: 12, minstage: 2 } def JobBoards daily { slots: 3, keep: 1, auto: true, refill: false } def JobBoards ada { slots: 2, keep: 7, scope: JOBS_PARTY } state JobsTestState { rep: int = 0 stage: int = 0 day: int = 1 guest: bool = false fish: int = 0 # the state's count of fish paid: int = 0 paid_rep: int = 0 paid_scope: int = -1 } function world_rep(jobs_test_st: JobsTestState, sc: int) -> int { return jobs_test_st.rep } function world_stage(jobs_test_st: JobsTestState) -> int { return jobs_test_st.stage } function world_day(jobs_test_st: JobsTestState) -> int { return jobs_test_st.day } function world_owns(jobs_test_st: JobsTestState, sc: int) -> bool { return sc == JOBS_SELF or not jobs_test_st.guest } function world_evidence(jobs_test_st: JobsTestState, kind: int, param: int) -> int { if kind == K_FISH { return jobs_test_st.fish } return -1 } function world_roll(jobs_st: mut JobsState, b: int, s: int) -> void { let need = jobs_roll(jobs_st, 2, 4) if b == BOARD_DAILY { jobs_post(jobs_st, b, s, K_WOOD, -1, need, 7, 2) } else { jobs_post(jobs_st, b, s, K_FISH, -1, need, 9 * need, 3) } } function pay(jobs_test_st: mut JobsTestState, sc: int, money: int, r: int) -> void { jobs_test_st.paid += money jobs_test_st.paid_rep += r jobs_test_st.paid_scope = sc } bind JobsWorld { rep: fn world_rep, stage: fn world_stage, day: fn world_day, owns: fn world_owns, evidence: fn world_evidence, roll: fn world_roll } bind JobsPay { reward: fn pay } function fresh(jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) -> void { jobs_test_st.rep = 0 jobs_test_st.stage = 0 jobs_test_st.day = 1 jobs_test_st.guest = false jobs_test_st.fish = 0 jobs_test_st.paid = 0 jobs_test_st.paid_rep = 0 jobs_reset(jobs_st) jobs_party_reset(jobs_st) } function count_of(jobs_st: JobsState, what: int) -> int { let fs = q_drain(jobs_facts(jobs_st)) var n = 0 for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } } return n } test "the registry is the game's" { expect_eq(JOB_COUNT, 4) expect_eq(jobs_find("ten"), JOB_TEN) expect_eq(BOARD_COUNT, 2) } test "a gate of standing and story" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) expect(jobs_offered(jobs_st, JOB_CATCH)) expect(not jobs_offered(jobs_st, JOB_DEER)) jobs_test_st.rep = 10 expect(jobs_offered(jobs_st, JOB_DEER)) expect(not jobs_offered(jobs_st, JOB_STILL)) jobs_test_st.stage = 2 expect(jobs_offered(jobs_st, JOB_STILL)) expect_eq(len(jobs_at(jobs_st, 0, -1)), 3) } test "counted by events, readied, handed in and paid" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_count(jobs_st, K_FISH, 0, 1) expect_eq(jobs_have(jobs_st, JOB_CATCH), 0) expect(jobs_take(jobs_st, JOB_CATCH)) jobs_count(jobs_st, K_FISH, 0, 2) expect_eq(jobs_state(jobs_st, JOB_CATCH), JOBS_ACTIVE) jobs_count(jobs_st, K_FISH, 0, 5) expect_eq(jobs_have(jobs_st, JOB_CATCH), 3) expect(jobs_ready_now(jobs_st, JOB_CATCH)) expect_eq(count_of(jobs_st, JOBS_F_COMPLETED), 1) expect(jobs_hand_in(jobs_st, JOB_CATCH)) expect(not jobs_hand_in(jobs_st, JOB_CATCH)) expect_eq(jobs_test_st.paid, 30) expect_eq(jobs_test_st.paid_rep, 5) expect_eq(jobs_done(jobs_st, 0), 1) expect_eq(count_of(jobs_st, JOBS_F_HANDED_IN), 1) } test "the state already proves the work" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_test_st.fish = 2 jobs_take(jobs_st, JOB_CATCH) expect_eq(jobs_have(jobs_st, JOB_CATCH), 2) jobs_test_st.fish = 3 jobs_recheck(jobs_st) expect(jobs_ready_now(jobs_st, JOB_CATCH)) } test "a param narrows the count" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_test_st.rep = 10 jobs_take(jobs_st, JOB_DEER) jobs_count(jobs_st, K_PHOTO, 3, 1) expect_eq(jobs_have(jobs_st, JOB_DEER), 0) jobs_count(jobs_st, K_PHOTO, 4, 1) expect(jobs_ready_now(jobs_st, JOB_DEER)) } test "the game's own play readies a job with no need" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_take(jobs_st, JOB_STILL) jobs_mark(jobs_st, JOB_STILL, 2) expect_eq(jobs_have(jobs_st, JOB_STILL), 4) expect_eq(jobs_state(jobs_st, JOB_STILL), JOBS_ACTIVE) expect(jobs_complete(jobs_st, JOB_STILL)) expect_eq(jobs_test_st.paid, 60) expect_eq(jobs_done(jobs_st, 1), 1) } test "a guest counts its own and leaves the party's to the host" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_test_st.guest = true jobs_take(jobs_st, JOB_TEN) jobs_take(jobs_st, JOB_CATCH) jobs_count(jobs_st, K_FISH, 0, 2) expect_eq(jobs_have(jobs_st, JOB_TEN), 0) expect_eq(jobs_have(jobs_st, JOB_CATCH), 2) jobs_count_in(jobs_st, JOBS_PARTY, K_FISH, 0, 4) expect_eq(jobs_have(jobs_st, JOB_TEN), 4) expect_eq(jobs_have(jobs_st, JOB_CATCH), 2) } test "an offer is said once it opens, never for what was open at the reset" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_system().tick(tick_new(0.1, 1, 0.0)) expect_eq(count_of(jobs_st, JOBS_F_OFFERED), 0) jobs_test_st.rep = 10 jobs_system().tick(tick_new(0.1, 2, 0.0)) expect_eq(count_of(jobs_st, JOBS_F_OFFERED), 1) } test "a board rolled by the day, the same every time" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_test_st.day = 3 jobs_morning(jobs_st) expect_eq(len(jobs_posted(jobs_st, BOARD_DAILY)), 3) expect_eq(len(jobs_posted(jobs_st, BOARD_ADA)), 2) expect_eq(jobs_posted_count(jobs_st, BOARD_DAILY), 3) expect_eq(jobs_posted_count(jobs_st, BOARD_ADA), 2) let a = jobs_post_need(jobs_st, BOARD_DAILY, 0) * 100 + jobs_post_need(jobs_st, BOARD_DAILY, 1) * 10 + jobs_post_need(jobs_st, BOARD_DAILY, 2) fresh(jobs_st, jobs_test_st) jobs_test_st.day = 3 jobs_morning(jobs_st) let b = jobs_post_need(jobs_st, BOARD_DAILY, 0) * 100 + jobs_post_need(jobs_st, BOARD_DAILY, 1) * 10 + jobs_post_need(jobs_st, BOARD_DAILY, 2) expect_eq(a, b) expect(jobs_post_need(jobs_st, BOARD_DAILY, 0) >= 2 and jobs_post_need(jobs_st, BOARD_DAILY, 0) <= 4) } test "a daily pays the moment it is met and waits for the morning" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_test_st.day = 2 jobs_morning(jobs_st) let need = jobs_post_need(jobs_st, BOARD_DAILY, 1) jobs_count(jobs_st, K_WOOD, -1, need) expect_eq(jobs_post_state(jobs_st, BOARD_DAILY, 1), JOBS_DONE) expect(jobs_posts_done(jobs_st, BOARD_DAILY) >= 1) expect_eq(jobs_test_st.paid, 7 * jobs_posts_done(jobs_st, BOARD_DAILY)) jobs_morning(jobs_st) expect_eq(jobs_post_state(jobs_st, BOARD_DAILY, 1), JOBS_DONE) jobs_test_st.day = 3 jobs_morning(jobs_st) expect_eq(jobs_post_state(jobs_st, BOARD_DAILY, 1), JOBS_ACTIVE) } test "a post counts only what came after it went up, and is replaced when handed in" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_test_st.fish = 5 jobs_morning(jobs_st) let need = jobs_post_need(jobs_st, BOARD_ADA, 0) jobs_recheck(jobs_st) expect_eq(jobs_post_have(jobs_st, BOARD_ADA, 0), 0) jobs_test_st.fish = 5 + need jobs_recheck(jobs_st) expect_eq(jobs_post_state(jobs_st, BOARD_ADA, 0), JOBS_READY) expect(jobs_post_hand_in(jobs_st, BOARD_ADA, 0)) expect_eq(jobs_test_st.paid_scope, JOBS_PARTY) expect_eq(jobs_total(jobs_st, BOARD_ADA), 1) expect_eq(jobs_post_state(jobs_st, BOARD_ADA, 0), JOBS_ACTIVE) } test "a stale post comes down after its days" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_morning(jobs_st) jobs_test_st.day = 7 jobs_morning(jobs_st) expect_eq(jobs_post_day(jobs_st, BOARD_ADA, 0), 1) jobs_test_st.day = 8 jobs_morning(jobs_st) expect_eq(jobs_post_day(jobs_st, BOARD_ADA, 0), 8) } test "each scope saves its own, by key" (jobs_st: mut JobsState, jobs_test_st: mut JobsTestState) { fresh(jobs_st, jobs_test_st) jobs_take(jobs_st, JOB_CATCH) jobs_count(jobs_st, K_FISH, 0, 2) jobs_take(jobs_st, JOB_TEN) jobs_count(jobs_st, K_FISH, 0, 1) jobs_test_st.day = 2 jobs_morning(jobs_st) let body = jobs_save(jobs_st) let world = jobs_party_save(jobs_st) let need = jobs_post_need(jobs_st, BOARD_ADA, 1) fresh(jobs_st, jobs_test_st) jobs_load(jobs_st, body, 1) expect_eq(jobs_have(jobs_st, JOB_CATCH), 3) expect_eq(jobs_state(jobs_st, JOB_TEN), JOBS_OFFERED) jobs_party_load(jobs_st, world, 1) expect_eq(jobs_have(jobs_st, JOB_TEN), 1) expect_eq(jobs_post_need(jobs_st, BOARD_ADA, 1), need) expect_eq(jobs_post_day(jobs_st, BOARD_DAILY, 0), 2) } }