Skip to content

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

Your sawmill

A player can build one sawmill on a cleared parcel. The mill saws logs from three sources: logs the player skids to it, logs moved from the landing, and logs bought from neighbors at a bid the player sets. It turns logs into lumber at a recovery rate that rises with level.

Mill levels. Eff is recovery: lumber made per bd ft of log value. Cap is milling speed in logs per hour. Cost is the price of reaching that level. Yard is the yard capacity in logs (cap times 8).
LevelNameRecoveryLogs/hrYard cap (logs)Cost (bd ft)Total spent
1Small steam sawmill80%6484,0004,000
2Headrig and edger95%10803,0007,000
3Band saw and planer110%161286,00013,000

The reference price of a mixed neighbor log is MARKET, which is 92 bd ft. The new mill’s bid is 70 bd ft per log, and the player may set it from 30 to 150 in steps of 5.

The sawmill is built like any other building (see buildings and roads) for 4,000 bd ft. That payment is the level 1 cost. Creating the mill sets level 1, an empty yard, bid = 70, and zero counters. Only one mill can exist. An upgrade to the next level costs the listed amount, first brings the mill up to date, and takes effect at once. Level 3 is the last.

The mill is brought up to date by stepping forward in pieces of at most 10 minutes. Each step first lets neighbors sell, then saws.

yardCap = level.cap * 8
milling step (dt, h = dt in hours):
-- neighbors sell
n = neighborSupply(t) * neighborShare(bid) * h
n = min( n,
max(0, yardCap - logsInYard),
max(0, lumber) / max(1, bid) )
if n > 0:
yard["mx"] += n (mixed logs)
lumber -= n * bid
bought += n; paid += n * bid
-- saw
room = level.cap * h
take = min(room, logsInYard)
for each species k in the yard:
part = yard[k] / logsInYard * take
yard[k] -= part
bdft = part * logValue(k) * level.eff
lumber += bdft; made += bdft
if k is not "mx": produced += bdft

logValue(k) is the species value, or MARKET for mixed logs. A species entry below 0.01 logs is removed. Mixed logs from neighbors add to made (the Top sawyer score) but not to produced (the deed goal and the Timber baron score).

neighborHaul = min(0.35, 0.04 + pathCost(landing -> mill parcel) * 0.008)
neighborNet = bid * (1 - neighborHaul)
neighborShare = clamp( (neighborNet - 0.6 * MARKET) / (0.3 * MARKET), 0, 1 )
neighborSupply(t) = (3 + 0.25 * settlers(t))
* (1 + 0.5 * sin( 2*pi * (t / 3600000) / 11 + 1.3 )) logs per hour

With MARKET = 92, share is 0 when the net bid is 55.2 or less and 1 when it is 82.8 or more. pathCost is the skidding path cost from the crew page. Neighbors never sell more than the yard has room for, and they do not sell if the player cannot pay for them.

The margin the interface shows is round(92 * recovery - bid) per bought log.

A cut can name the sawmill as its destination, and the player can move the landing deck to the mill.

cut to mill: loss = skidLoss(parcel -> mill)
move landing deck: loss = skidLoss(landing -> mill); every species count * (1 - loss)

Both add to the yard without checking the yard cap. The yard cap limits only neighbor sales. The interface offers the move only when the landing deck is not empty.

Inputs are the bid, the level, the settler count, the path cost, the mill’s lumber payments and the clock. Outputs are lumber, a higher produced, and counters. State: S.own = { r, c, level, deck, at, bid, bought, paid, made }, where at is the time the mill was last brought up to date.

The bid is the only lever a player has over a market that is currently simulated. The neighbor supply is a sine curve with a settler term, a placeholder for real players with logs to sell. In a shared game the supply should be actual offers from other players, and the server should settle each sale (lumber out, logs in) as a single transaction. The server must own the mill record and the mill update loop, because the amount of lumber produced feeds the deed goal and two leaderboards. Direct deliveries bypass the yard cap in the prototype; a server needs to choose whether that is intended.

What others can see of your mill in the valley

Section titled “What others can see of your mill in the valley”

Your mill’s output counts on the Top sawyer board and, when it saws your own logs, on the Timber board. Other players see those figures rounded (to the nearest 6,200) and only at the ten-minute tick, but a counter’s slope shows through rounding if someone watches long enough. A patient neighbor can work out your mill’s level and the species you feed it within a few days of watching the two boards: in a test where the reader already knew the mill’s level, 12 of 27 species cases were named after one day and 25 of 27 after three, and when the level was not known either, 7 of 27 after one day, 22 after three and 26 after seven. That was the easiest case: one species, nothing bought. A mill that buys the neighbors’ logs, which are mixed at a value of 92, or that runs dry, is harder to read, and ponderosa (also 92) cannot be told from bought logs. Nothing about your lumber balance, your bid or your ledger is shown. Mixing what you feed it hides which species you saw, not how fast the mill runs.

Source: prototype/index.html · constants OWN_LEVELS, MARKET in rules.json · logic updateOwn, neighborHaul, neighborShare, neighborSupply, upgradeMill, landingToMill, logValue