ludic/examples/offline_rewards.ludic
Orkuncakilkaya b5455cd550
Some checks are pending
docs / build-and-deploy (push) Waiting to run
feat(stdlib): DateTime format/parse + simulated Clock — completes #9
Finish issue #9 by adding the two remaining acceptance items on top of the
calendar/clock core, still pure-integer and deterministic:

  DateTime.format(dt, pattern) -> string   render an instant via a token
                                           pattern (YYYY/YY/MM/DD/HH/mm/ss;
                                           other chars pass through)
  DateTime.parse(text, pattern) -> int     read an instant back; -1 on a
                                           non-digit where one is expected
  Clock.now/set/advance/reset              a game-controlled simulated clock
                                           (the @L_clock global) that never
                                           touches the wall clock, so gameplay
                                           reading Clock.now() is replay-safe

format/parse take a string-LITERAL pattern and are expanded at compile time
(field offsets are then constant), folding @fn_str_concat over literal runs and
two small runtime helpers: @fn_dt_pad0 (zero-padded field) and @fn_dt_rd
(fixed-width digit reader that stops at the terminator and flags malformed
input). Clock is a universal i32 global declared in emit_head, so it works in
entry and game programs alike.

Adds examples/offline_rewards.ludic — the issue's worked "you were away N hours"
example, driven from its own entry and asserted in the regression suite — plus
selfhost/tests/datetime2.ludic (format/parse round-trip, parse failure, clock),
docs (Clock section + 4 pages, DateTime.format/parse pages), inventory and LSP
hover. Reseeded; C-free fixpoint holds; all suites green (27 self-host / 46
regression / 29 tools); check.py (366 symbols), check-impl.py (218 ns-methods)
and validate.py OK.

With this, #9's scope is fully delivered: DateTime/Date/Duration + core ops,
format/parse, a deterministic simulated clock, docs + offline-rewards example,
and tests. (v1 stays UTC-only, no leap seconds, i32 epoch valid through 2038.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 03:51:48 +03:00

29 lines
1.4 KiB
Text

# offline_rewards.ludic — issue #9's worked example: an idle/farming game grants
# "you were away for N hours" rewards on load, using the Time/Date/Duration and
# the deterministic Clock. Everything is integer seconds, so the result replays
# identically — no wall clock, no floating point.
#
# bin/ludic examples/offline_rewards.ludic # prints 13 / 650 / 2026-08-30 / 0
program OfflineRewards {
entry {
# A save records when the player last quit. It is hardcoded here so the demo
# is deterministic; a real game writes Time.now() (or Clock.now()) at save.
let last_seen = DateTime.from(2026, 8, 29, 18, 30, 0)
# On load, set the game clock to "now". We drive it explicitly (rather than
# Time.now) so gameplay stays replay-safe and this sample is reproducible.
Clock.set(DateTime.from(2026, 8, 30, 7, 45, 0))
let away = Clock.now() - last_seen # a Duration in seconds (47700)
let hours = Duration.as_hours(away) # whole hours away
# Reward: 50 coins per full hour, capped at a day's worth.
let capped = Math.min(hours, 24)
let coins = capped * 50
print(hours) # 13
print(coins) # 650
print(DateTime.format(Clock.now(), "YYYY-MM-DD")) # 2026-08-30 (the day they returned)
print(DateTime.weekday(Clock.now())) # 0 = Sunday
}
}