Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

Forest Reserve

The Forest Reserve is timber owned by the land office. It has 40 stands that grow, are sold by the stand, and regrow after being cut. A player buys a mature stand with lumber and receives logs at the landing.

The Reserve has RESERVE_N = 40 stands. Each stand has an id (R1 to R40), a species, a haul band and a planting time.

Haul bands. Each stand is assigned one band at random when the Reserve is created. Loss is the share of logs lost hauling the stand to your landing.
BandHaul loss
08%
112%
216%
320%
425%

Created once per claim from a generator seeded with the claim’s creation time:

species = one of [wp, wp, df, df, l, l, rc, pp, gf, wh, lp], each equally likely
(so white pine, Douglas-fir and larch each have 2 in 11)
band = random integer 0 to 4
planted = now - (6 + rand() * 50) hours real hours, so 6 to 56

Stands use the same species and stage rules as player timber (see timber and growth).

ready(stand) = the stand's stage yields 12 or more logs (mature or old growth)
index = clamp( 0.5 + 0.5 * (1 - readyCount / 40) ^ 1.3, 0.5, 1.0 )
price = round( stageLogs * value(species) * index ) bd ft

With no stand ready, the index is 1.0. With all 40 ready, it is 0.5. A mature stand has 12 logs and an old-growth stand has 16.

A stand that is not ready is not for sale. The interface lists up to four ready stands, ordered by value * (1 - loss) from highest to lowest.

requires: the stand is ready, one crew-day available, lumber >= price
lumber -= price
saw sharpness = max(0, sharpness - 0.20)
crew-day recorded
logs = round( stageLogs * sawYield * (1 - loss) )
deck[species] += logs the landing deck
stand.planted = now it regrows from seedling
sold += 1; soldToYou += 1; revenue += price

The purchase does not pass through the skidding path, so the claim’s roads do not matter. It does not increase cleared, and it is not counted in produced when bought. When those logs are later sold to a mill, the wagon payout does count toward produced (see town mills).

Other settlers buy ready stands as the town grows. The Reserve is brought up to date in steps of at most 30 minutes:

demand = settlers(t) * 0.04 * (step hours) stands
buys = floor(demand) + (1 if hash01( floor(t / 30 min), 91 ) < frac(demand))
repeat buys times:
pick a ready stand by hash01( t / 1000, readyCount )
revenue += price at t; sold += 1; stand.planted = t

The expected rate is settlers times 0.04 stands per hour. As with the town markets, the roll is fixed for each 30-minute bucket, and the page runs the update about every second. In a one-second step the fractional demand is tiny, so a purchase fires only when the bucket’s roll is below that tiny number, and then fires on every call until the ready stands run out. The long-run average matches the stated rate, but sales arrive in rare bursts while the page is open and in regular amounts after an absence.

Inputs are lumber, a crew-day, the saw, the settler count and the clock. Outputs are logs at the landing, lumber spent, a dulled saw and a regrowing stand. State: S.reserve = { stands: [{ id, sp, band, planted }], at, sold, soldToYou, revenue }. Revenue is recorded and never displayed or spent.

This is the system most improved by being shared. One set of 40 stands, with a price that reacts to how many all players have bought, is the scarcity mechanism the design describes. A server must own the stand list, the ready check, the purchase transaction (price, payment and the stand’s reset as one step) and the update step. Two players cannot buy the same stand, so purchases need to be serialized per stand. The simulated settlers can stay as background demand, but they should run on a fixed schedule on the server. The price lets a buyer pay as little as half of log value, with haul losses of 8 to 25 percent.

Source: prototype/index.html · constants RESERVE_N, RESERVE_LOSS in rules.json · logic reserveInit, standReady, reserveIndex, standPrice, updateReserve, buyStand