Town and markets
The town of Harrison grows by settlers. Settlers create demand. Demand, split among sellers, sets what a player’s business earns. The player’s work is to find a market with few sellers and open a business in it.
Settlers and milestones
Section titled “Settlers and milestones”settlers(t) = min( SETTLER_MAX, SETTLER_START + floor( (t - founded) / SETTLER_EVERY ) )level(n) = the highest milestone whose "at" is <= nThe town is founded when the claim is created. The constants are SETTLER_START = 8, SETTLER_MAX = 60, and one new settler every 40 minutes.
| Level | Name | Settlers | Hours after founding | Markets opened |
|---|---|---|---|---|
| 0 | Founding | 0 | 0 | Saw filing, Freight hauling |
| 1 | A town of 15 settlers | 15 | 4.7 | Cedar shakes, Seedlings |
| 2 | A real town of 30 | 30 | 14.7 | General goods |
| 3 | The steamboat stops here | 45 | 24.7 | Room and board |
The count reaches its cap of 60 about 34.7 hours after founding. When the level rises, the ledger records “Town milestone” and lists the markets that opened. Every level up is recorded, including levels skipped over while the player was away.
Markets
Section titled “Markets”| Market | Business | Unit | Cost | Upkeep | K | D | P | Cogs | Comp | Unlock | Needs building |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Saw filing | Filing shop | saw | 600 | 45 | 4 | 0.25 | 30 | 10% | 1 | 0 | – |
| Freight hauling | Teamster stable | load | 1,200 | 100 | 3 | 0.12 | 90 | 25% | 2 | 0 | barn |
| Cedar shakes | Shake shed | bundle | 900 | 60 | 6 | 0.35 | 28 | 0% | 0 | 1 | – |
| Seedlings | Tree nursery | bundle | 800 | 60 | 3 | 0.1 | 60 | 20% | 0 | 1 | – |
| General goods | General store | order | 2,500 | 40 | 10 | 0.6 | 20 | 60% | 1 | 2 | – |
| Room and board | Boarding house | night | 3,000 | 70 | 8 | 0.25 | 35 | 40% | 0 | 3 | cabin |
Shake shed has no cost of goods share. It consumes redcedar logs instead: 0.25 of a log per bundle sold, taken first from the landing deck and then from the sawmill yard. Each market grants one perk to its owner.
| Business | Perk |
|---|---|
| Filing shop | Your own saws are filed free. |
| Teamster stable | Your own hauling to town mills costs half. |
| Shake shed | Splits redcedar logs from your landing or mill. No cedar, no shakes. |
| Tree nursery | Your own replanting is free. |
| General store | The busiest trade in a growing town. |
| Boarding house | Your crew rests 25% faster. |
The filing shop waives the saw filer’s fee, the stable halves hauling shares and Mercantile freight, the nursery waives replanting cost, and the boarding house multiplies crew rest by 0.75. The shake shed and the general store have no perk beyond their sales.
Demand, price and income
Section titled “Demand, price and income”demand = settlers * d units per hoursellers = competitors + (1 if the player owns the business)ratio = demand / max( sellers * k, 0.5 * k )price = round( p * clamp( ratio, 0.5, 1.8 ) ^ 0.7 )
yourSales = min( k, demand / sellers ) if you own it, else 0 then min( yourSales, cedarOnHand / 0.25 ) for the shake shednet per hour = yourSales * price * (1 - cogs) - upkeep (upkeep only if you own it)
status = locked if town level < unlock underserved if ratio > 1.3 balanced if ratio >= 0.8 crowded otherwiseIncome is integrated over time. Over each interval, lumber += net * hours, and lumber never drops below zero, so upkeep cannot make it negative. The amount is also added to earned[market], which is allowed to go negative and is not floored.
When the player has no cedar, yourSales is zero and the shake shed pays only its upkeep.
Competitors
Section titled “Competitors”Competitors are a count per market. They change in steps of at most 30 minutes, and only for markets the town has unlocked.
roll = hash01( floor(t / 30 minutes), len(id) * 7 + k ) a fixed pseudo-random number in [0,1)h = step length in hoursif ratio > 1.25 and roll < 0.10 * h * 2: competitors += 1else if ratio < 0.70 and competitors > 0 and roll > 1 - 0.12 * h * 2: competitors -= 1
hash01(a, b) = fractionalPart( sin( a * 12.9898 + b * 78.233 ) * 43758.5453 )For a full 30-minute step, h is 0.5, so entry has probability 0.10 and exit 0.12. For a shorter step the probability shrinks in proportion. The roll depends only on the clock and the market, not on the player, so two players at the same moment see the same roll.
Implementation note: while the page stays open a competitor almost never enters or leaves. Changes show up when the player returns after being away, because the update then runs in full 30-minute steps. The competitor rate depends on how often the page runs the update.
Opening a business
Section titled “Opening a business”requires: the market is unlocked (town level >= unlock) the player does not already own it the selected parcel is cleared, has no building, is not meadow, is not the landing the required building exists, if the market names one lumber >= costeffect: the town is brought up to date, lumber -= cost, parcel.building = "biz:" + id, town.biz[id] = { r, c, since: now }The placement check does not look for a field, so a business can be opened on a parcel that has one. There is no way to close or sell a business, and upkeep runs for as long as the claim exists. A business adds its cost to the appraisal.
Inputs, outputs and state
Section titled “Inputs, outputs and state”Inputs are the clock, the founding time, the player’s businesses, the landing deck and sawmill yard (for cedar) and the selected parcel. Outputs are lumber over time, the earned figures (read by the Merchant board), competitor counts and ledger lines. State: S.town = { founded, at, comp, earned, biz, level }, where at is the last update time.
For the shared game
Section titled “For the shared game”The prototype fakes a market economy from settler count: demand per settler, a hash standing in for other players’ decisions, and a count of competitors. In a shared game “sellers” should be the real businesses that exist, and “settlers” should be the real population or the server’s schedule of arrivals. A server must own the business registry (one record per player business), the pricing function, and one fixed update step for everyone, so that outcomes do not depend on how often a client polls. Milestones are the unlock schedule for the whole world, so they should be a world setting and not a per-player clock. If every player has a private founding date, as in the prototype, the milestone gates do not coordinate anyone.
Source: prototype/index.html · constants MARKETS, MILESTONES, SETTLER_EVERY, SETTLER_START, SETTLER_MAX in rules.json · logic settlers, townLevel, marketNow, updateTown, hash01, openBiz, takeCedar