File size: 4,034 Bytes
2c94890
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// Plotwren town layout: one fixed map, every plot has a fixed tier and a fixed price. Pure data, shared by the Worker and
// the browser (build copies it to web/town.js). No auctions, no takeovers, no resale: a plot is sold once at its tier price.
// © 2026 CyberMax. All rights reserved.

export const WORLD = { w: 1536, h: 1024, tile: 16 };

// Prices in US cents. Featured is an optional monthly upgrade for any sold plot.
export const TIERS = {
  stall: { name: 'Market stall', price: 500, w: 32, h: 32, blurb: 'A pixel stall on Market Row with your logo, name and link.' },
  shop: { name: 'Shop', price: 1900, w: 48, h: 48, blurb: 'A shop on Maker Street with a big sign, your logo and a one-line pitch.' },
  billboard: { name: 'Billboard', price: 4900, w: 64, h: 48, blurb: 'A billboard on Launch Boulevard, the road everyone crosses.' },
  landmark: { name: 'Landmark', price: 14900, w: 96, h: 96, blurb: 'One of four landmark towers on Plotwren Square, the centre of town.' },
};
export const FEATURED = { name: 'Featured', price: 900, interval: 'month', blurb: 'Pinned to the Featured strip, a glowing outline on the map and first in the directory. Cancel any time.' };

export const DISTRICTS = {
  square: 'Plotwren Square',
  boulevard: 'Launch Boulevard',
  street: 'Maker Street',
  market: 'Market Row',
  yard: 'CyberMax Yard',
};

// Roads (world px rectangles) drawn by the renderer; plots never overlap them.
export const ROADS = [
  { x: 0, y: 448, w: 1536, h: 48 },   // Launch Boulevard (east-west)
  { x: 744, y: 0, w: 48, h: 1024 },   // North-south avenue
  { x: 64, y: 240, w: 640, h: 32 },   // Maker Street (west)
  { x: 832, y: 240, w: 640, h: 32 },  // Maker Street (east)
  { x: 64, y: 704, w: 640, h: 24 },   // Market Row lane (west)
  { x: 832, y: 704, w: 640, h: 24 },  // Market Row lane (east)
];
export const WATER = { x: 0, y: 960, w: 1536, h: 64 };
export const FOUNTAIN = { x: 744, y: 448, w: 48, h: 48 };

const pad = (n, l = 2) => String(n).padStart(l, '0');

function build() {
  const plots = [];
  const add = (id, tier, district, x, y) => plots.push({ id, tier, district, x, y, w: TIERS[tier].w, h: TIERS[tier].h });
  // Plotwren Square: four landmarks around the fountain crossing.
  add('L1', 'landmark', 'square', 636, 336); add('L2', 'landmark', 'square', 804, 336);
  add('L3', 'landmark', 'square', 636, 508); add('L4', 'landmark', 'square', 804, 508);
  // Launch Boulevard: 6 billboards each side of the square, north side of the road.
  let b = 1;
  for (let i = 0; i < 6; i++) add(`B${pad(b++)}`, 'billboard', 'boulevard', 72 + i * 92, 392);
  for (let i = 0; i < 6; i++) add(`B${pad(b++)}`, 'billboard', 'boulevard', 912 + i * 92, 392);
  // Maker Street: two rows of shops either side of each half of the street.
  let s = 1;
  for (const x0 of [72, 840]) {
    for (let i = 0; i < 10; i++) add(`H${pad(s++)}`, 'shop', 'street', x0 + i * 62, 184);
    for (let i = 0; i < 10; i++) add(`H${pad(s++)}`, 'shop', 'street', x0 + i * 62, 280);
  }
  // Market Row: stalls in two rows either side of each lane, south of the boulevard.
  let m = 1;
  for (const x0 of [72, 840]) {
    for (const y of [664, 736, 776]) for (let i = 0; i < 16; i++) add(`M${pad(m++, 3)}`, 'stall', 'market', x0 + i * 39, y);
  }
  return plots;
}

// CyberMax Yard: the house plots, north-west corner, never for sale (CyberMax's own products, clearly labelled).
export const YARD = [
  { id: 'Y1', x: 72, y: 56, w: 64, h: 64 }, { id: 'Y2', x: 152, y: 56, w: 64, h: 64 }, { id: 'Y3', x: 232, y: 56, w: 64, h: 64 },
  { id: 'Y4', x: 312, y: 56, w: 64, h: 64 }, { id: 'Y5', x: 392, y: 56, w: 64, h: 64 }, { id: 'Y6', x: 472, y: 56, w: 64, h: 64 },
  { id: 'Y7', x: 552, y: 56, w: 64, h: 64 }, { id: 'Y8', x: 632, y: 56, w: 64, h: 64 },
];

export const PLOTS = build();
export const PLOT_BY_ID = Object.fromEntries(PLOTS.map((p) => [p.id, p]));
export const priceOf = (id) => TIERS[PLOT_BY_ID[id]?.tier]?.price ?? null;
export const usd = (cents) => `$${(cents / 100).toFixed(cents % 100 ? 2 : 0)}`;