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 | |||
| 166 | 166 | const sharp = Math.min(a, 180 - a); | |
| 167 | 167 | // What it takes to close the corner, less the daylight asked for. Under a | |
| 168 | 168 | // 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. | |
| 169 | 174 | const tile = len / STACKS_PER_SIDE; | |
| 170 | 175 | 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); | |
| 172 | 177 | // Corner to corner. The wall is longer than this by the overrun. | |
| 173 | 178 | const edge = Math.max(thick, len - lap); | |
| 174 | 179 | ||
| ⋯ 103 unchanged lines | |||
modifiedsrc/styles.css+8 −5
| ⋯ 661 unchanged lines | |||
| 662 | 662 | `.wall-ring` is the opening, not the outside: the sides hang off its edges, | |
| 663 | 663 | so the square encloses the pool the way it does on a table. */ | |
| 664 | 664 | .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. */ | |
| 669 | 669 | --ws: var(--tile-w); | |
| 670 | 670 | --wd: calc(var(--ws) * 1.375); | |
| 671 | 671 | /* How far round the whole square is set. Four walls built the same way round | |
| ⋯ 15 unchanged lines | |||
| 687 | 687 | --wall-angle: 90; | |
| 688 | 688 | /* The daylight left where two walls meet, in tiles. Nought is the corner shut | |
| 689 | 689 | 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. */ | |
| 691 | 694 | --wall-gap: 0; | |
| 692 | 695 | position: absolute; | |
| 693 | 696 | top: 50%; | |
| ⋯ 1611 unchanged lines | |||
modifiedsrc/tuneWall.tsx+1 −1
| ⋯ 39 unchanged lines | |||
| 40 | 40 | const KNOBS: Knob[] = [ | |
| 41 | 41 | { key: 'angle', label: 'Corner', min: 20, max: 160, step: 1, note: '° — 90 is the square', unit: 'deg' }, | |
| 42 | 42 | { 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: '' }, | |
| 44 | 44 | ]; | |
| 45 | 45 | ||
| 46 | 46 | /** 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 | |||
| 47 | 47 | ({ | |
| 48 | 48 | width: opening.w, | |
| 49 | 49 | height: opening.h, | |
| 50 | - | '--ws': `${cell}px`, | |
| 51 | 50 | // A side is its stacks and nothing else, so there is no sum for | |
| 52 | 51 | // the corners to come out of by a pixel. | |
| 53 | 52 | '--wall-len': `${RING.h * cell}px`, | |
| ⋯ 185 unchanged lines | |||
| 239 | 238 | const turn = parseFloat(style.getPropertyValue('--wall-turn')) || 0; | |
| 240 | 239 | const gap = parseFloat(style.getPropertyValue('--wall-gap')) || 0; | |
| 241 | 240 | ||
| 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}`; | |
| 243 | 248 | if (from === last) return; | |
| 244 | 249 | last = from; | |
| 245 | 250 | ||
| 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 | - | ); | |
| 253 | 251 | const shape = rhombus(STACKS_PER_SIDE * s, ratio * s, angle, turn, gap); | |
| 254 | 252 | setSquare({ opening: { w: shape.open.w, h: shape.open.h }, cell: s, shape }); | |
| 255 | 253 | }; | |
| ⋯ 22 unchanged lines | |||