/** * This file is part of the SplendidBear Websites' projects. * * Copyright (c) 2026 @ www.splendidbear.org * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ import React from 'react'; export const ROWS = 16; export const COLS = 16; export const IMG = '/images/'; export const WAVES = { 1: 'bg-wave-1-outbg.png', 2: 'bg-wave-1-outbg.png', 3: 'bg-wave-2-outbg.png', }; export const IMAGES = { target: `${IMG}bg-target-outbg.png`, bomb: `${IMG}bg-bomb-outbg.png`, bombDisabled: `${IMG}bg-bomb-disabled-outbg.png`, bombExploded: `${IMG}bg-bomb-exploded-outbg.png`, bombEmpty: `${IMG}bg-bomb-empty-outbg.png`, leftMine: `${IMG}bg-left-mine-outbg.png`, cursor: color => `${IMG}bg-cursor-${color}-outbg.png`, figure: color => `${IMG}bg-figure-${color}-outbg.png`, flag: player => `${IMG}bg-flag-${player}-outbg.png`, last: color => `${IMG}bg-last-${color}-outbg.png`, wave: n => `${IMG}${WAVES[n]}`, bombPos: (hor, vert) => `${IMG}bg-bomb-${hor}-${vert}-outbg.png`, }; export const BONUS_STATS_DEF = { blindHits: 0, chainBest: 0, chainCurrent: 0, lastMineHits: 0, edgeMines: 0, biggestReveal: 0, }; export const BONUS_LABELS = { blindHits: { label: 'Blind hits', desc: 'Mines clicked with no revealed number nearby' }, chainBest: { label: 'Best chain', desc: 'Longest streak of consecutive mine-clicks' }, chainCurrent: { label: 'Current chain', desc: 'Active consecutive mine-click streak' }, lastMineHits: { label: 'Endgame mines', desc: 'Mines clicked while few remain on the board' }, edgeMines: { label: 'Edge mines', desc: 'Mines clicked on the board boundary' }, biggestReveal: { label: 'Biggest reveal', desc: 'Largest number of safe cells revealed in one click' }, }; export const PLAYER_DEF = { name: '...', desc: '', active: false, mines: 0, haveBomb: true, enabledBomb: true, registered: false, avatar: null, bonusPoints: 0, bonusStats: { ...BONUS_STATS_DEF }, }; export const DESC = { buddy:
Your buddy is
making a
move.
, you:
It is your turn!
Make a move.
, }; export const BOMB_SYMBOLS = [ [null, null], [0, 0], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2], [1, 2], [2, 2], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], ]; export const bombRadius = (row, col, rows, cols) => { const centre = 1 < row && row < rows - 2 && 1 < col && col < cols - 2; if (!centre) { col = Math.max(2, Math.min(col, cols - 3)); row = Math.max(2, Math.min(row, rows - 3)); } return [ [row, col], [row - 2, col - 2], [row - 2, col], [row - 2, col + 2], [row, col - 2], [row, col + 2], [row + 2, col - 2], [row + 2, col], [row + 2, col + 2], [row - 2, col + 1], [row - 2, col - 1], [row - 1, col - 2], [row - 1, col - 1], [row - 1, col], [row - 1, col + 1], [row - 1, col + 2], [row, col - 1], [row, col + 1], [row + 1, col - 2], [row + 1, col - 1], [row + 1, col], [row + 1, col + 1], [row + 1, col + 2], [row + 2, col - 1], [row + 2, col + 1], ]; }; export const patchCells = (prev, patches) => { const next = prev.map(r => [...r]); for (const { row, col, ...rest } of patches) { next[row][col] = { ...next[row][col], ...rest }; } return next; }; export const initCells = () => Array.from({ length: ROWS }, () => Array.from({ length: COLS }, () => ({ currentImage: IMAGES.wave(Math.floor(Math.random() * 3) + 1), currentObj: 'w', active: false, lastClickedRed: false, lastClickedBlue: false, bombTargetArea: null, })), );