anvilsign in

collin/mahjong · 3af57839

A wall tile is a hand tile

Collin Richards · 2026-08-21 22:16 UTC · 3af5783941e43ba5286e71083eaa274c619d0c5f · parent 9ebe1624 · browse files

modifiedsrc/game/wall.ts+6 −1
⋯ 165 unchanged lines
166166 const sharp = Math.min(a, 180 - a);
167167 // What it takes to close the corner, less the daylight asked for. Under a
168168 // tile of it, always: a whole one and the walls have stopped meeting.
169+ //
170+ // Negative is the other way — the walls laid further over each other than the
171+ // corner needs, which pulls the four corners in and takes the opening down
172+ // with them. That is the only lever on how much middle the square leaves,
173+ // since its sides are eighteen stacks whatever else happens.
169174 const tile = len / STACKS_PER_SIDE;
170175 const shut = thick / Math.tan(rad(sharp) / 2);
171- const lap = Math.max(0, shut - Math.min(0.99, Math.max(0, gap)) * tile);
176+ const lap = Math.max(0, shut - Math.min(0.99, Math.max(-STACKS_PER_SIDE / 3, gap)) * tile);
172177 // Corner to corner. The wall is longer than this by the overrun.
173178 const edge = Math.max(thick, len - lap);
174179
⋯ 103 unchanged lines
modifiedsrc/styles.css+8 −5
⋯ 661 unchanged lines
662662 `.wall-ring` is the opening, not the outside: the sides hang off its edges,
663663 so the square encloses the pool the way it does on a table. */
664664 .wall-ring {
665- /* A stack's short side. Set from ui/WallRing, not from here and not from the
666- hand's tile: the square is eighteen stacks a side whatever the window is,
667- so it is the *tile* that gives, and how much it gives is arithmetic on the
668- middle. The fallback is only for the frame before the first measure. */
665+/* A stack's short side — the same tile that is in a hand, because on a table
666+ it is the same tile. The square is then eighteen of them a side and comes
667+ out bigger than the middle between the strips; where it goes from there is
668+ `--wall-angle`, `--wall-turn` and `--wall-gap`, not a smaller tile. */
669669 --ws: var(--tile-w);
670670 --wd: calc(var(--ws) * 1.375);
671671 /* How far round the whole square is set. Four walls built the same way round
⋯ 15 unchanged lines
687687 --wall-angle: 90;
688688 /* The daylight left where two walls meet, in tiles. Nought is the corner shut
689689 tight; a whole tile is the walls no longer meeting at all, so it is held
690- under one. */
690+ under one. Negative is the walls laid further over each other than the
691+ corner needs, which pulls the corners in and is the only thing that makes
692+ the opening in the middle smaller — the sides are eighteen stacks whatever
693+ happens. */
691694 --wall-gap: 0;
692695 position: absolute;
693696 top: 50%;
⋯ 1611 unchanged lines
modifiedsrc/tuneWall.tsx+1 −1
⋯ 39 unchanged lines
4040 const KNOBS: Knob[] = [
4141 { key: 'angle', label: 'Corner', min: 20, max: 160, step: 1, note: '° — 90 is the square', unit: 'deg' },
4242 { key: 'turn', label: 'Turn', min: 0, max: 360, step: 1, note: '° clockwise', unit: 'deg' },
43- { key: 'gap', label: 'Corner gap', min: 0, max: 0.95, step: 0.05, note: 'tiles of daylight', unit: '' },
43+ { key: 'gap', label: 'Corner gap', min: -6, max: 0.95, step: 0.05, note: 'tiles — under 0 is overlap', unit: '' },
4444 ];
4545
4646 /** Where the hand has got to, so the square can be seen whole and eaten away. */
⋯ 191 unchanged lines
modifiedsrc/ui/WallRing.tsx+7 −9
⋯ 46 unchanged lines
4747 ({
4848 width: opening.w,
4949 height: opening.h,
50- '--ws': `${cell}px`,
5150 // A side is its stacks and nothing else, so there is no sum for
5251 // the corners to come out of by a pixel.
5352 '--wall-len': `${RING.h * cell}px`,
⋯ 185 unchanged lines
239238 const turn = parseFloat(style.getPropertyValue('--wall-turn')) || 0;
240239 const gap = parseFloat(style.getPropertyValue('--wall-gap')) || 0;
241240
242- const from = `${middle.clientWidth}x${middle.clientHeight}/${ratio}/${angle}/${turn}/${gap}`;
241+ // A wall tile is the same tile as a hand tile, so the stack is whatever
242+ // size CSS made it and there is nothing to solve for. The square comes out
243+ // as big as eighteen of them a side comes to, which is bigger than the
244+ // middle — where it then *goes* is a separate question, and not this
245+ // function's.
246+ const s = box.width;
247+ const from = `${middle.clientWidth}x${middle.clientHeight}/${s}/${ratio}/${angle}/${turn}/${gap}`;
243248 if (from === last) return;
244249 last = from;
245250
246- // Everything about the shape is linear in the stack, so it is asked for
247- // once at a stack of one and the answer scaled to the middle there is.
248- const unit = rhombus(STACKS_PER_SIDE, ratio, angle, turn, gap);
249- const s = Math.max(
250- 1,
251- Math.min(middle.clientWidth / unit.box.w, middle.clientHeight / unit.box.h),
252- );
253251 const shape = rhombus(STACKS_PER_SIDE * s, ratio * s, angle, turn, gap);
254252 setSquare({ opening: { w: shape.open.w, h: shape.open.h }, cell: s, shape });
255253 };
⋯ 22 unchanged lines