sorcery  Artifact [f67589c567]

Artifact f67589c567cd5462cdf72ebc9081609d5c2eae41e039a8b5bb4c8cc8268a33e9:

  • File calendar.lua — part of check-in [3f6a913e4e] at 2020-09-29 12:40:28 on branch trunk — * remove former hacky registration system, replace with consistent and flexible API; rewrite metal/gem generation to take advantage of this new API; tweaks to init system to enable world-local tweaks to lore and sorcery behavior * initial documentation commit * initial steps towards calendar - add default date format, astrolabe; prepare infra for division/melding/transmutation spells, various tweaks and fixes (user: lexi, size: 2475) [annotate] [blame] [check-ins using]

if not sorcery then
	sorcery = { data = {
		calendar = dofile('data/calendar.lua');
		signs = dofile('data/signs.lua');
	} }
end

sorcery.calendar = {}

sorcery.calendar.stats = function(style)
	if not style then style = sorcery.data.calendar.default end
	local s = sorcery.data.calendar.styles[style]
	local days, moons, weeks = s.days, s.moons, s.weeks

	return {
		days_in_year = #moons * #weeks * #days;
		days_in_week = #days;
		days_in_moon = #days * #weeks;
		weeks_in_moon = #weeks;
		weeks_in_year = #weeks * #moons;
		moons_in_year = #moons;
	}
end

sorcery.calendar.date = function(day,style)
	local s = sorcery.calendar.stats(style)

	local day_of_year = day % s.days_in_year;
	local day_of_moon = day_of_year % s.days_in_moon;
	local day_of_week = day_of_moon % s.days_in_week;

	return {
		day_of_year = 1 + day_of_year;
		day_of_moon = 1 + day_of_moon;
		day_of_week = 1 + day_of_week;
		week_of_moon = 1 + math.floor(day_of_moon / s.days_in_week);
		week_of_year = 1 + math.floor(day_of_year / s.days_in_week);
		moon_of_year = 1 + math.floor(day_of_year / s.days_in_moon);
		year = math.floor(day / s.days_in_year);
		moons_passed = math.floor(day / s.days_in_moon);
		weeks_passed = math.floor(day / s.days_in_week);
	}
end

sorcery.calendar.stars = function(day,style)
	local periods = math.floor(day / sorcery.data.calendar.days_per_stellar_cycle)

	local elapsed = 0
	local cycle = 1
	while true do
		for _, c in pairs(sorcery.data.signs) do
			if c.cycle then
				if cycle % c.cycle ~= 0 then goto skip end
			end
			elapsed = elapsed + c.duration
			if elapsed >= periods then
				return {
					sign = c;
					cycle = cycle;
				}
			end
		::skip::end
		cycle = cycle + 1
	end
end

sorcery.calendar.longdate = function(day)
	if not style then style = sorcery.data.calendar.default end
	return sorcery.data.calendar.styles[style].longdate(sorcery.calendar.date(day))
end

sorcery.calendar.shortdate = function(day,style)
	if not style then style = sorcery.data.calendar.default end
	return sorcery.data.calendar.styles[style].shortdate(sorcery.calendar.date(day))
end

sorcery.calendar.stardate = function(day)
	local s = sorcery.calendar.stars(day)
	return string.format('sign of the %s, stellar cycle %u', s.sign.patron, s.cycle)
end

-- math.randomseed(os.time())
-- local d = math.random(500,256000)
-- print(string.format('%s :: %s in the %s',
-- 	sorcery.calendar.shortdate(d),
-- 	sorcery.calendar.longdate(d),
-- 	sorcery.calendar.stardate(d)))