SOURCE / PINNED RELEASE
Made of little things.
Browser Side Quest
- Release
- b9d42f5768e4…
- Author-recorded commit
- c267690145fa…
- License
- LICENSE
- Author’s source reference
- nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.shakespeare.diy%2F/browser-side-quest
Archive hash verified: 6d4b90b8a5f328f7…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
// Port of BrowserQuest server/js/utils.js (MPL-2.0).
import { Orientations, type Orientation } from './gametypes.js';
export const random = (range: number): number => Math.floor(Math.random() * range);
export const randomRange = (min: number, max: number): number => min + Math.random() * (max - min);
export const randomInt = (min: number, max: number): number =>
min + Math.floor(Math.random() * (max - min + 1));
export const clamp = (min: number, max: number, value: number): number =>
value < min ? min : value > max ? max : value;
export function randomOrientation(): Orientation {
switch (random(4)) {
case 0:
return Orientations.LEFT;
case 1:
return Orientations.RIGHT;
case 2:
return Orientations.UP;
default:
return Orientations.DOWN;
}
}
/** Chebyshev distance, as used by the original server. */
export function distanceTo(x: number, y: number, x2: number, y2: number): number {
const distX = Math.abs(x - x2);
const distY = Math.abs(y - y2);
return distX > distY ? distX : distY;
}
const ESCAPES: Record<string, string> = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
};
/**
* The original server stripped unsafe tags and HTML-escaped player text.
* Text is rendered with textContent in this port, so we only strip tags,
* control characters and surrounding whitespace.
*/
export function sanitize(value: string): string {
return value
.replace(/<[^>]*>/g, '')
.replace(/[\u0000-\u001f\u007f]/g, '')
.trim();
}
export function escapeHtml(value: string): string {
return value.replace(/[&<>"']/g, (c) => ESCAPES[c]);
}
/** 1-based tile index to grid position, exactly as in the original maps. */
export function tileIndexToGridPosition(tileNum: number, width: number): { x: number; y: number } {
const getX = (num: number, w: number): number => {
if (num === 0) return 0;
return num % w === 0 ? w - 1 : (num % w) - 1;
};
tileNum -= 1;
return { x: getX(tileNum + 1, width), y: Math.floor(tileNum / width) };
}
export function gridPositionToTileIndex(x: number, y: number, width: number): number {
return y * width + x + 1;
}
