Skip to content

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

Deed and proving up

A player can use all 160 acres from the first minute. The deed is what makes the claim theirs to keep. It is earned by finishing five goals.

Deed goals. All five must be true at the same time.
#GoalTestCounter
1Build a cabinbuilt.cabin is setbuilt.cabin
2Clear 10 acres (4 parcels)cleared >= 4cleared
3Build a barnbuilt.barn is setbuilt.barn
4Replant 2 parcelsreplanted >= 2replanted
5Produce 10,000 bd ftproduced >= 10000produced

DEED_WORK is 10000 bd ft.

cleared is incremented once for every cut, including a cut that clears seedlings. It counts events, not different parcels. A parcel that is cut, replanted and cleared again adds 2.

replanted is incremented once for every replant, with the same event-counting rule.

produced is a running total of bd ft. It is increased by two things and only these:

produced += wagon.net when a wagon is settled at a town mill
produced += sawn bd ft of logs that are not "mx" in the player's own mill

Wagon income includes logs bought from the Forest Reserve and later hauled. It excludes farm income, business income, and the mixed logs bought from neighbors at the player’s own mill. The goal text says “from your own timber”, which is narrower than what the counter counts.

checkProveUp(): if provedUp is empty and all five goals are true:
provedUp = now
ledger: "Claim proved up..."

The check runs every time the game commits a change (most player actions, and a wagon settling). The mill and business loops raise produced over time without committing, so a deed can be earned a moment after the goal is actually met, on the next commit. Once set, provedUp is never cleared except by starting a new claim.

The land office appraisal is computed from the current claim. It is not stored.

claimValue =
sum over parcels: stageLogs * value(species) * 0.6 (standing timber, seedlings are 0)
+ 200 if the parcel has a road (the landing counts)
+ 400 if it has a field, 900 if the crop is apples
+ 1500 if a cabin exists
+ 2500 if a barn exists
+ 500 per woodshed built
+ 4000 / 7000 / 13000 for a sawmill of level 1 / 2 / 3 (cumulative cost)
+ the cost of each business owned
claimValue = round(claimValue)

Lumber on hand, logs, produce and the Reserve are not part of it. A new claim already holds 200 for the landing road, and its timber value depends on the seeding.

After the deed, the claim can be listed.

list: listing = { price: claimValue(), at: now } the price cannot be edited
unlist: listing = null

A listing only records a price. There is no marketplace, offers or sale in the prototype. The listing price is the appraisal at the moment of listing and does not change later. Before the deed the buttons do nothing: the click handler returns when provedUp is empty.

Inputs are the five counters and the claim. Outputs are provedUp (a timestamp), the appraisal and the listing. State: provedUp, listing = { price, at }, cleared, replanted, produced.

The deed gates ownership, so it needs a server record that cannot be written by a client. The five counters are the evidence, and every one of them is client-computed in the prototype. The server should derive each counter from logged actions, count distinct parcels if the intent is parcels, and decide whether Reserve resale and farm income should count toward the work goal. The appraisal should be calculated by the server. In the prototype the listing button only records a price on the claim.

Source: prototype/index.html · constants DEED_WORK in rules.json · logic goals, checkProveUp, claimValue, settleWagon, updateOwn