INT minesweeper

A forum for topics that don't fit elsewhere. Introduce yourselves to other members of the forums, discuss how your name evolves when written out in the Game of Life, or just tell us how you found it. Forum rules still apply.
Post Reply
User avatar
dl-rs
Posts: 247
Joined: April 11th, 2022, 12:14 am
Location: I was just a block until a glider crashes with me and I tumbled onto Earth surface in LWSS form.
Contact:

INT minesweeper

Post by dl-rs »

INT minesweeper - this awesome idea that me and yyh_baboon came up with. It's mostly about making isotripic non-totalistic rulespace into a minesweeper game. Anyway, here's the source code:

Code: Select all

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Custom Minesweeper</title>
    <style>
        * {
            box-sizing: border-box;
            font-family: 'Courier New', monospace;
        }
        
        body {
            background-color: #f0f0f0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            padding: 20px;
        }
        
        .game-container {
            background-color: #c0c0c0;
            border: 2px solid #808080;
            border-radius: 5px;
            padding: 15px;
            box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
            max-width: 100%;
        }
        
        .header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            padding: 5px 10px;
            background-color: #c0c0c0;
            border: 2px inset #c0c0c0;
        }
        
        .controls {
            display: flex;
            gap: 10px;
            margin-bottom: 15px;
            flex-wrap: wrap;
        }
        
        .controls input {
            width: 60px;
            padding: 5px;
        }
        
        button {
            background-color: #c0c0c0;
            border: 2px outset #c0c0c0;
            padding: 5px 10px;
            cursor: pointer;
            font-weight: bold;
        }
        
        button:hover {
            background-color: #d0d0d0;
        }
        
        .game-board {
            display: grid;
            gap: 1px;
            background-color: #808080;
            border: 2px inset #c0c0c0;
            margin-bottom: 15px;
            overflow: auto;
            max-width: 100%;
        }
        
        .cell {
            width: 30px;
            height: 30px;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #c0c0c0;
            border: 2px outset #c0c0c0;
            font-weight: bold;
            cursor: pointer;
            user-select: none;
        }
        
        .cell.revealed {
            border: 1px solid #808080;
            background-color: #e0e0e0;
        }
        
        .cell.mine {
            background-color: #ff0000;
        }
        
        .cell.flagged::after {
            content: "🚩";
        }
        
        .status {
            text-align: center;
            font-weight: bold;
            margin-top: 10px;
            height: 24px;
        }
        
        .pixel-font {
            font-family: 'Courier New', monospace;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div class="game-container">
        <div class="header">
            <div class="controls">
                <div>
                    <label>Width:</label>
                    <input type="number" id="width" min="5" max="30" value="10">
                </div>
                <div>
                    <label>Height:</label>
                    <input type="number" id="height" min="5" max="30" value="10">
                </div>
                <div>
                    <label>Mines:</label>
                    <input type="number" id="mines" min="1" max="100" value="15">
                </div>
                <button id="new-game">New Game</button>
            </div>
        </div>
        
        <div class="game-board" id="board"></div>
        
        <div class="status" id="status">Click to start</div>
    </div>

    <script>
        // The provided rulekeys array
        const rulekeys = [
            "", "c", "e", "a", "c", "c", "a", "i",
            "e", "k", "e", "j", "a", "n", "a", "a",
            "c", "n", "k", "q", "c", "c", "n", "n",
            "a", "q", "j", "w", "i", "n", "a", "a",
            "e", "k", "i", "r", "k", "y", "r", "t",
            "e", "k", "e", "j", "j", "k", "r", "n",
            "a", "q", "r", "z", "n", "y", "i", "r",
            "a", "q", "r", "q", "a", "j", "i", "a",
            "c", "c", "k", "n", "n", "c", "q", "n",
            "k", "y", "k", "k", "q", "y", "q", "j",
            "c", "c", "y", "y", "c", "c", "y", "e",
            "n", "y", "k", "k", "n", "e", "j", "e",
            "a", "n", "r", "i", "q", "y", "z", "r",
            "j", "k", "j", "y", "w", "k", "q", "k",
            "i", "n", "t", "r", "n", "e", "r", "i",
            "a", "j", "n", "k", "a", "e", "a", "e",
            "e", "a", "e", "a", "k", "n", "j", "a",
            "i", "r", "e", "r", "r", "i", "r", "i",
            "k", "q", "k", "q", "y", "y", "k", "j",
            "r", "z", "j", "q", "t", "r", "n", "a",
            "e", "j", "e", "r", "k", "k", "j", "n",
            "e", "j", "e", "c", "j", "y", "c", "c",
            "j", "w", "j", "q", "k", "k", "y", "k",
            "r", "q", "c", "n", "n", "k", "c", "c",
            "a", "i", "j", "a", "q", "n", "w", "a",
            "r", "t", "j", "n", "z", "r", "q", "a",
            "n", "n", "k", "j", "y", "e", "k", "e",
            "i", "r", "y", "k", "r", "i", "k", "e",
            "a", "a", "r", "i", "q", "j", "q", "a",
            "r", "n", "c", "c", "q", "k", "n", "c",
            "a", "a", "n", "a", "j", "e", "k", "e",
            "i", "a", "c", "c", "a", "e", "c", "8"
        ];

        // Game state variables
        let grid = [];
        let revealed = [];
        let flagged = [];
        let gameOver = false;
        let firstClick = true;
        let width = 10;
        let height = 10;
        let mines = 15;

        // DOM elements
        const boardElement = document.getElementById('board');
        const statusElement = document.getElementById('status');
        const widthInput = document.getElementById('width');
        const heightInput = document.getElementById('height');
        const minesInput = document.getElementById('mines');
        const newGameButton = document.getElementById('new-game');

        // Initialize the game
        function initGame() {
            width = parseInt(widthInput.value) || 10;
            height = parseInt(heightInput.value) || 10;
            mines = parseInt(minesInput.value) || 15;
            
            // Validate input
            if (width < 5) width = 5;
            if (width > 30) width = 30;
            if (height < 5) height = 5;
            if (height > 30) height = 30;
            const maxMines = Math.floor(width * height * 0.3);
            if (mines < 1) mines = 1;
            if (mines > maxMines) mines = maxMines;
            
            // Update input values
            widthInput.value = width;
            heightInput.value = height;
            minesInput.value = mines;
            
            // Reset game state
            grid = Array(height).fill().map(() => Array(width).fill(0));
            revealed = Array(height).fill().map(() => Array(width).fill(false));
            flagged = Array(height).fill().map(() => Array(width).fill(false));
            gameOver = false;
            firstClick = true;
            
            // Update status
            statusElement.textContent = "Click to start";
            
            // Render the board
            renderBoard();
        }

        // Place mines after first click to ensure first cell is safe
        function placeMines(firstRow, firstCol) {
            let minesPlaced = 0;
            
            while (minesPlaced < mines) {
                const row = Math.floor(Math.random() * height);
                const col = Math.floor(Math.random() * width);
                
                // Skip if it's the first clicked cell or adjacent cells
                if (Math.abs(row - firstRow) <= 1 && Math.abs(col - firstCol) <= 1) {
                    continue;
                }
                
                // Skip if there's already a mine
                if (grid[row][col] === -1) {
                    continue;
                }
                
                // Place mine
                grid[row][col] = -1;
                minesPlaced++;
            }
            
            // Calculate numbers for non-mine cells
            for (let row = 0; row < height; row++) {
                for (let col = 0; col < width; col++) {
                    if (grid[row][col] !== -1) {
                        grid[row][col] = calculateRuleIndex(row, col);
                    }
                }
            }
        }

        // Calculate the rule index for a cell
        function calculateRuleIndex(row, col) {
            let index = 0;
            let weight = 1;
            
            // Check all 8 neighbors in the specified order
            const neighbors = [
                [row-1, col-1], [row-1, col], [row-1, col+1],
                [row, col+1], [row+1, col+1], [row+1, col],
                [row+1, col-1], [row, col-1]
            ];
            
            for (let i = 0; i < neighbors.length; i++) {
                const [r, c] = neighbors[i];
                // Check if the neighbor is within bounds and is a mine
                if (r >= 0 && r < height && c >= 0 && c < width && grid[r][c] === -1) {
                    index += weight;
                }
                weight *= 2;
            }
            
            return index;
        }

        // Reveal a cell
        function revealCell(row, col) {
            if (gameOver || revealed[row][col] || flagged[row][col]) {
                return;
            }
            
            // First click - place mines and ensure safety
            if (firstClick) {
                firstClick = false;
                placeMines(row, col);
                // Recalculate the rule index for the first cell after mines are placed
                grid[row][col] = calculateRuleIndex(row, col);
            }
            
            revealed[row][col] = true;
            
            // Check if it's a mine
            if (grid[row][col] === -1) {
                gameOver = true;
                statusElement.textContent = "Game Over!";
                revealAllMines();
                return;
            }
            
            // If it's a zero, reveal adjacent cells
            if (grid[row][col] === 0) {
                revealAdjacentCells(row, col);
            }
            
            // Check for win
            if (checkWin()) {
                gameOver = true;
                statusElement.textContent = "You Win!";
                return;
            }
            
            renderBoard();
        }

        // Reveal adjacent cells for zeros
        function revealAdjacentCells(row, col) {
            const directions = [
                [-1, -1], [-1, 0], [-1, 1],
                [0, -1], [0, 1],
                [1, -1], [1, 0], [1, 1]
            ];
            
            for (const [dr, dc] of directions) {
                const newRow = row + dr;
                const newCol = col + dc;
                
                if (newRow >= 0 && newRow < height && newCol >= 0 && newCol < width) {
                    if (!revealed[newRow][newCol] && !flagged[newRow][newCol]) {
                        revealed[newRow][newCol] = true;
                        
                        if (grid[newRow][newCol] === 0) {
                            revealAdjacentCells(newRow, newCol);
                        }
                    }
                }
            }
        }

        // Toggle flag on a cell
        function toggleFlag(row, col) {
            if (gameOver || revealed[row][col]) {
                return;
            }
            
            flagged[row][col] = !flagged[row][col];
            renderBoard();
        }

        // Check if the player has won
        function checkWin() {
            for (let row = 0; row < height; row++) {
                for (let col = 0; col < width; col++) {
                    // If there's a non-mine cell that hasn't been revealed, game is not won
                    if (grid[row][col] !== -1 && !revealed[row][col]) {
                        return false;
                    }
                }
            }
            return true;
        }

        // Reveal all mines when game is lost
        function revealAllMines() {
            for (let row = 0; row < height; row++) {
                for (let col = 0; col < width; col++) {
                    if (grid[row][col] === -1) {
                        revealed[row][col] = true;
                    }
                }
            }
            renderBoard();
        }

        // Render the game board
        function renderBoard() {
            // Clear the board
            boardElement.innerHTML = '';
            
            // Set grid template
            boardElement.style.gridTemplateColumns = `repeat(${width}, 30px)`;
            boardElement.style.gridTemplateRows = `repeat(${height}, 30px)`;
            
            // Create cells
            for (let row = 0; row < height; row++) {
                for (let col = 0; col < width; col++) {
                    const cell = document.createElement('div');
                    cell.className = 'cell';
                    cell.dataset.row = row;
                    cell.dataset.col = col;
                    
                    if (revealed[row][col]) {
                        cell.classList.add('revealed');
                        
                        if (grid[row][col] === -1) {
                            cell.classList.add('mine');
                            cell.textContent = "💣";
                        } else {
                            const ruleIndex = grid[row][col];
                            cell.textContent = rulekeys[ruleIndex] || '';
                        }
                    } else if (flagged[row][col]) {
                        cell.classList.add('flagged');
                    }
                    
                    // Add click events
                    cell.addEventListener('click', () => {
                        revealCell(row, col);
                    });
                    
                    cell.addEventListener('contextmenu', (e) => {
                        e.preventDefault();
                        toggleFlag(row, col);
                    });
                    
                    boardElement.appendChild(cell);
                }
            }
        }

        // Event listeners
        newGameButton.addEventListener('click', initGame);
        
        // Initialize the game
        initGame();
    </script>
</body>
</html>

Edit 1:

The game can be played online at https://nd-zyth.github.io/int-minesweeper!
Roaming OCA randomly.

Code: Select all

x = 23, y = 11, rule = B2n3-jknr4ky5-eqry6ik7c8/S234cktwz5ai6-ci7c
2bo2b3o2bo7bo2bo$b2ob5ob2o6b2ob2o$2bo2b3o2bo7bo2bo4$10b2o$b3o5bobo$2o
b2o4b3o$b3o5bobo$10b2o!
hotdogPi
Moderator
Posts: 2203
Joined: August 12th, 2020, 8:22 pm

Re: INT minesweeper

Post by hotdogPi »

I've thought of a similar idea for Minesweeper, but for Life specifically. There would be numbers as usual, but the mines must form a still life (or several).
User:HotdogPi/My discoveries

Periods discovered:

All evens ≤128 except 52,58,78,82,92,94,98,104,118,122

5-15,㉕-㉛,㉟㊺,51,63,65,73,75
1㊳㊵㊹㊼㊽,54,56,72,74,80,90,92
217,240,300,486,576

Guns: 20,21,32,54,55,57,114,117,124,126
SKOPs: 32,74,76,102,196
User avatar
pifricted
Posts: 968
Joined: May 25th, 2024, 10:26 am
Location: Behind The Great Internet Wall

Re: INT minesweeper

Post by pifricted »

4r and 3r always look same:

Code: Select all

 x = 15, y = 9, rule = B/S012345678History
12.BAB$12.BDA$8.E3.B2A$BFB6.E$BDF2.6E$B2F6.E$8.E3.BAB$12.BDF$12.B2A!
pifricted's rules & pifricted's Sandbox User:Pifricted
Ehhh…
I’m not a guy good at rule exploration, right?
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

Tactics I noticed:

Code: Select all

@ is mine

ce
 @

caa
e@

ec
@i@
EDIT:
Rare event (as of November 30th 2025) of four "k"s:
Screenshot_20251130-174134.png
Screenshot_20251130-174134.png (14.56 KiB) Viewed 1975 times
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

Reviving this thread with suggestion of a timer as present in original minesweeper.
Also, I proposed pull request for a fix of the final board state not rendering after a win.

EDIT: Updated again so the title is "INT Minesweeper" instead of "Custom Minesweeper".
User avatar
wwei47
Posts: 2273
Joined: February 18th, 2021, 11:18 am

Re: INT minesweeper

Post by wwei47 »

Out of curiosity, what does a B8 cell look like in this game?
Currently trying to reduce the big P6 double sparker.
Replicator thread: viewtopic.php?f=11&t=6769
Fractal thread: viewtopic.php?f=12&t=6675

:3c
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

wwei47 wrote: December 22nd, 2025, 8:18 pm Out of curiosity, what does a B8 cell look like in this game?
It just looks like 8 according to the source code.

EDIT: here is my modification of the source.

EDIT 2: there's no license in the repository, therefore it would be illegal to release derivatives. @dl-rs it would help a lot if you added a license, even a permissive one such as MIT license (it doesn't make your repository being associated with MIT).
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

@dl-rs is it okay to fork the game (since you didn't attach a license)? If nothing I'll start to improve and maintain a fork of it myself.
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

I've made significant changes in my fork of the game.
It's not finished yet, but I'm making it as similar as it could be to actual Minesweeper.
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

I've released the first complete version of my fork of INT minesweeper at https://github.com/T6970/INT-Minesweepe ... tag/v1.0.0.
Fixed bugs:
  • The grid does not update upon winning
New features:
  • Replaced the status text with a "smiley" as in real Minesweeper
  • Predefined difficulty
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

I'm writing the v1.1.0.

However I need people to suggest how to complete the how to play page:
Screenshot_20260214-140345.png
Screenshot_20260214-140345.png (20.43 KiB) Viewed 1734 times
It's all about how to play Minesweeper, plus the changes introduced by using Hensel notation.
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

No one posting here??

Here's a table of all possible configurations of 3 letters, so that non-CA enthusiasts can memorize them easier instead of the Hensel notation table:

Code: Select all

C
#-- #-# #-# #-# -#- -#- -##
-@- -@- -@- -@- #@# #@# #@#
--- --- --# #-# ##- ### ###

E
-#- -#- -#- -#- #-# #-# #-#
-@- #@- #@# #@# -@- -@# #@#
--- --- --- -#- ### ### ###

A
##- ##- ### --# --#
-@- #@- #@- -@# #@#
--- --- --- ### ###
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

The complete list:

Code: Select all

# = mine
- = nothing
@ = center cell


C
#-- #-# #-# #-# -#- -#- -##
-@- -@- -@- -@- #@# #@# #@#
--- --- --# #-# ##- ### ###

E
-#- -#- -#- -#- #-# #-# #-#
-@- #@- #@# #@# -@- -@# #@#
--- --- --- -#- ### ### ###

A
##- ##- ### --# --#
-@- #@- #@- -@# #@#
--- --- --- ### ###

K
#-- #-- #-- -## -##
-@# -@# -@# #@- #@-
--- -#- ##- #-# ###

I
-#- ### #-# --- #-#
-@- -@- #@# #@# #@#
-#- --- --- ### #-#

N
#-- #-# #-# -#- -##
-@- -@# -@# #@- #@#
--# --- --# ### ##-

J
##- ##- --#
-@# -@# #@-
--- -#- ###

Q
##- ##- --#
-@- #@- #@#
--# --# ##-

R
--- --- ###
#@# #@# -@-
#-- ##- -##

Y
#-# #-# -#-
-@- -@- #@#
-#- ##- #-#

T
###
-@-
-#-

W
#--
#@-
-##

Z
##-
-@-
-##
User avatar
dl-rs
Posts: 247
Joined: April 11th, 2022, 12:14 am
Location: I was just a block until a glider crashes with me and I tumbled onto Earth surface in LWSS form.
Contact:

Re: INT minesweeper

Post by dl-rs »

@b-engine
Umm... due to network problems, I haven't been on github for a long time(and neither conwaylife forums), but I would like to help complete the how to play page:

In this Minesweeper variant, the game is played on a standard two-dimensional square grid where each tile has eight neighbors (the Moore neighborhood). Mines are hidden beneath some tiles. When a player clicks on a tile, the behavior depends on the number of mines in the eight surrounding cells:

If the tile has zero neighboring mines, it triggers the standard cascade or "expansion" behavior, revealing a contiguous area of tiles that also have zero neighboring mines.

If the tile has one or more neighboring mines, instead of displaying a simple numerical count of those mines, the tile displays a letter.

This letter is not arbitrary; it is derived from Hensel notation, a system used to describe cellular automata rules that depend on the specific arrangement of neighboring cells, not just their total count. In this context, each possible configuration of mines in the eight neighboring positions corresponds to a specific letter code. Therefore, the letter shown on a revealed tile encodes the precise spatial arrangement of the mines surrounding it, providing more detailed information than a mere total count would.

(here, the image on Hensel notation explanation page). I think this suffices to be a good explanation.
Roaming OCA randomly.

Code: Select all

x = 23, y = 11, rule = B2n3-jknr4ky5-eqry6ik7c8/S234cktwz5ai6-ci7c
2bo2b3o2bo7bo2bo$b2ob5ob2o6b2ob2o$2bo2b3o2bo7bo2bo4$10b2o$b3o5bobo$2o
b2o4b3o$b3o5bobo$10b2o!
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

The definition of what mine permutations corresponds to what letter is actually an array, as well as the colors of letters which I defined.
I'm planning to turn this mechanic into loadable "rules" so it could turn into "regular" Minesweeper as well.
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

I've moved the INT Minesweeper page along with my entire website to https://t6970.codeberg.page/INT-Minesweeper due to the recent decisions of GitHub.

Technical changes:
  • Split the rulekeys into a separate file, as the first step of mods and refactors.
User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: INT minesweeper

Post by b-engine »

A dump of addition requests I asked on r/Minesweeper on Reddit:
concuso1 wrote: I have been playing this version for quite a while now. It works out very nicely, probably the cleanest variant I have tried even without any adjustment

As for anything I want to change, maybe you should keep the density a bit higher than normal minesweeper. The clues is actually more informative with the Hensel notation up to the point where I can play 30% density boards with ease (I usually play 35% density…). Another thing would be addressing the 50/50 in this variant because it is more common and much harder to really get yourself out of it. Those 50/50 usually appears around the edge of the board so I suggest changing the algorithm so that no mine can spawn on the edges.

That’s pretty much it for me. Don’t add a chord function pls, not needed. Instead, when we click a letter, it should show all the possible configuration of that letter, maybe on the top or something, so player have the arrangements right on the screen to compare.
T6970 wrote:I'm trying to faithfully reproduce the behavior (and look) of original Minesweeper, and keeping the density low makes me easier to solve it without 50/50 ending the game.
TheLlamaOverlord wrote: Similar to what other guy said. Need to have a way to see what the letters correspond to at the same time as playing. I've never used Hensel notation so had to have a link for it on the side and constantly reference it. Also beginner is mispelled and the help page for the game isn't very useful because it's too small (tiny scrolling box, maybe designed for mobile but you should make this responsive). The patterns on help page aren't useful either because you cant see them whilst playing and they are misaligned and would be better as images.

I do like that it is a new variant though, haven't played anything like this before.
TheLlamaOverlord wrote:Just to add to this. I played some more and have now won my first expert. Was surprised how quickly I picked up the notation. I do like this variant, just would be really good to clean it up as much as possible before doing anything new. Like the smiley should probably be an image instead of an emoji so it looks less generic (possibly the same with the flags and bombs, can't tell if those are an emoji or not). Also it looks like the grid looks slightly janky sometimes, like the squares don't line up right or they don't overlap right with the background behind them. Sometimes the game/help menus don't seem to be clickable and I don't know why. Also it would be nice if the flag counter went negative instead of blocking you from placing extra flags.
(Note: nested quotes means replies of comments instead of what it usually means)
Post Reply