Coder Social home page Coder Social logo

davidnhill / jsminesweeper Goto Github PK

View Code? Open in Web Editor NEW
91.0 4.0 16.0 3.68 MB

Minesweeper player, solver and analyser in javascript

Home Page: https://davidnhill.github.io/JSMinesweeper/

License: MIT License

JavaScript 95.07% HTML 3.68% CSS 1.25%
minesweeper javascript game playable solver

jsminesweeper's Introduction

JSMinesweeper

Play Minesweeper and analyse arbitrary positions at https://davidnhill.github.io/JSMinesweeper/

This readme explains how to use the software and what techniques the solver uses.

Overview

This is a rewrite of my Java minesweeper solver in javascript. All the processing runs on the local (your) machine. The purpose of the rewrite was to make the solver more accessable since there was reluctance to download a java executable. The trade off is that javascript is significantly slower than java to execute.

The Java solver has a 41% win rate on classic expert (30x16/99 safe start in a corner) and 54.3% on modern expert (30x16/99 open start at (3,3)). The Javascript version is slightly weaker.

How to use the player

The landing screen provides access to the Minesweeper player.

Landing screen

Basic Options:

  • Opening on start: Determines whether the first click is a guaranteed opening or only guaranteed safe.
  • No Guess: Attempts to generate a board which contains no guesses. The board is generated on your first click.
  • Beginner: 9x9/10.
  • Intermediate: 16x16/40.
  • Expert: 30x16/99.
  • Custom: Define your own board size with a maximum height and width of 200.

Advanced options:

  • Fast Mode: Trivial moves are played automatically, leaving only moves with logic to consider.
  • Style - Flagging: Put a flag on mines when the solver discovers them.
  • Style - No Flagging: Never place flags.
  • Style - Efficiency: This option allows the solver to use chording and flags are only placed in an attempt to minimize the number of clicks required to solve the game. This mode seriously impacts performance.
  • Style - NF Efficiency: The solver tries to minimise the number of clicks without chording. This involves clicking openings and avoiding tiles which are next to an opening. This mode seriously impacts performance and win rate.
  • Tile size: use this to select the tile size best suited for you.
  • Show hints: The solver will shadow your play and highlight safe plays and (if necessary) what it considers the best guess
  • Auto play: The solver will play the game for you until a guess is required.
  • Accept guesses: The solver will play the game until it is won or lost.

The analysis button can be used to force the solver to analyse the current games position. This is useful if you have turned off all the solver options.

The Play again button can be used to replay the same board. This is useful if you have made a no guess game you wish to replay without having to redo the generation step. If you don't start with the same tile you may blast or game may no longer be no guess.

Boards can be downloaded in mbf format to be stored locally or shared with friends. boards saved using MinesweeperX (mbf) or Arbitar (abf) can be loaded into the Player by dragging and dropping the file on the play area.

How to use the Analyser

To access the analyser press the button in the top left corner.

Empty Analysis screen

To start you are presented with a blank expert board which is all zeros. You can start with all hidden by selecting build all hidden and then reseting the board.

From here you can construct the position you wish to analyse. This is best done in the following order:

  1. Use the left mouse button (or 'h') to toggle a tile from hidden to revealed.
  2. Drag the mouse with the left mouse button down to toggle each tile the mouse passes over
  3. Use the right mouse button (or 'f') to place and remove flags. A flag is considered to be a mine by the solver, whether it is knowable from the position or not.
  4. Placing and removing a flag will automatically adjust the values of revealed tiles adjacent to it.
  5. Use the mousewheel to adjust the value of a revealed tile. Alternatively, use the 0-8 keys. The value is constrained to be a legal value based on the adjacent tiles.
  6. Use the mousewheel to adjust the mine count showing how many mines left to find. The value can be adjusted by 10s or 1s depending on which digit the mouse is over

If the board is valid the Analyse button will be enabled and pressing this (or the 'a' key) will start the analyser.

New: Positions can be saved and stored on a local disc. They can be reloaded by dropping them onto the board grid.

Analysis screen

The safe tiles are shown in green and the mines in red. If no certain move is available then the solver will highlight the move it considers best in yellow with a green centre. Other moves it considered but rejected are shown in yellow. Tiles highlighted in grey can have only one possible value and it is never correct to play these when there are other moves available.

If you are playing a game and using the analyser to provide assistance then you can keep the mine count in step by selecting "Lock mine count". Now every time a flag is placed the mine counter is reduced by one.

Using the Analyser to construct boards to keep

If you wish to construct a board to share with friends or to see how the solver would approach playing it, then place flags in the location of where the mines are and Download as MBF. Drop the downloaded file into the Minesweeper Player's play area to load the game.

High level components

There are three high level components

  • The Minesweeper game - this generates the board and is sent moves by the GUI.
  • The GUI - gets moves from the Player or the Solver and sends them to the Minesweeper game, who returns the result of the move which is rendered. It also renders information the solver has calculated.
  • The Solver - The GUI passes the board state to the solver which calculates a play and returns the move(s) to the GUI, which passes them onto the Minesweeper game.

How the solver determines the best play

The solver has a number of techniques it uses to solve the board:

  • Trivial analysis
  • Probability engine
  • 50/50 and pseudo-50/50 detection
  • Guessing logic
  • Brute force analysis

Trivial Analysis

This is used to quickly find any moves which are trivially discovered:

  • A satisfied tile has it's remaining adjacent tiles cleared
  • A tile with space only for the remaining mines has the mines identified. Depending on the play style they may not be flagged.

If plays are discovered then processing ends at this stage. Further analysis might find other options, but equally they might be found trivially in the next iteration of the solver.

Probability engine

The probability engine calculates the chance that a tile is a mine for every hidden tile on the board. The calculation is 100% accurate, but this comes at the price of exponential processing cost based on the number of revealed tiles which can be strung together. This means as the board gets larger and has a higher mine density performance suffers. For example 50x50/500 should be fine, 100x100/2500 might struggle.

As part of the probability engine some tiles can be discovered that are either mines or have only one possible value. These are refered to as dead tiles and it is never correct to choose a dead tile unless all the tiles left in the game are dead. In which case the game has no more information to be discovered and the result is down to luck.

Probability engine

50/50 and pseudo-50/50 detection

A 2-tile 50/50 is a pair of tiles which share 1 mine where one of the tiles can never receive information without the other tile also receiving the same information. In this situation there is no way to differentiate between the two tiles and they must be (and always will be) an unavoidable guess with 50% chance of being correct. Since the 50/50 will never change it is always correct to guess these at the earliest opportunity, since they might provide information to their neighbouring tiles. In practice this processing has a dependency on the probability engine and so the solver can only find these after that has run.

The solver can discover:

  • Arbitrarily extended 2-tile 50/50s.
  • Enclosed 2x2/2 boxes

Solver 50/50

A pseudo-50/50 is a situation where a set of tiles is either safe or part of a 50/50. If it is part of a 50/50 then it is correct to guess immediately. If it is safe it is also correct to guess immediately.

The solver can discover

  • 2-tile pseuso-50/50s
  • 4-tile 2x2 pseudo-50/50s

Solver pseudo 50/50

It is unable to discover extended pseudo-50/50s.

Guessing logic

If the probabilty engine has run and there are no certain plays and no 50/50s then a guess has to be made which isn't a 50/50 punt. At this stage the solver's guessing logic is used.

Each tile within 10% of the safest guess (e.g. safest is 80%, then the cutoff is 80% * 90% = 72%) is analysed to find:

  • Progress percentage - This is the chance that this move will lead to 100% safe moves being available next move.
  • Secondary safety - This is the likelihood of surviving not only the current move, but also the next move.

The progress percentage and the secondary safety are blended together to create a final score. The idea here is that 1) a tile with 90% safety and 10% progress isn't as good as a move with 85% safety and 85% progress and 2) When you don't make progress is there a good guess to follow. This method is not perfect but has been emperically shown to provide better results than merely picking the safest tile.

An interesting statistic is that to win a classic expert game of minesweeper the solver is required, on average, to make 3.3 guesses. From this we can see that once the game has opened up it is common to be a able to make significant progress before a guess is needed again. For higher density boards the number of guesses required goes up and the value of looking for progress diminishes. For this reason the guessing heuristic may not be optimal for high density boards.

Brute force analysis

The brute force analysis takes a board and (conceptionally) plays every combination of move against every combination of mines and determines the best way to play to maximise the chance of winning. This algorithm finds a perfect path to play the game, but is hugely processor intensive. The solver will attempt to use this method when the number of solutions remaining is 750 or less. If it is successful then we can be certain that the solver has played (one of) the best paths to victory. It also allows the solver to say precisely how likely the game is to be won with best play.

Brute force screen

jsminesweeper's People

Contributors

davidnhill avatar trungnt2910 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

jsminesweeper's Issues

Question About Extracting Solver Script

The algorithm and overall functionality work wonderfully. However, I need the solver script to be separate from the visual code. I want to work on automation using my own board and different technologies. How can I extract the solver script so I can input my board and get the optimal moves and mines as output in pure JavaScript? Do you have any plans to write a standalone solver algorithm without the visual component?

Progress chance calculations ?

When starting an Expert game and clicking analyse, the corner tiles are marked as having a 39.57% chance of progress. If my understanding is correct, it is the probability none of the adjacent tiles are mines, which should be approx 79^3=50% ?
I also have a question about the way the engine choses its move when guessing. In the file I send along with this post, the engine recommends I play (0,5) which is insane considering the engine thinks it has worse safety, secondary safety and progress than (1,2).
Something else that confuses me : if you for example replace the bottom left corner's 2 by a 1, the engine will stop calculating the secondary safety and progress of (0,5) despite it being shown in yellow and being within the 10% cutoff range (83.33%*0.9=75% and (0,5) has a safety of 79.48).

I am using the solver through the link on the github.
Maybe these issues are related, so I throw them together.
Hopefully I expressed myself clearly enough. Thanks for the great tool.

the board position (image since can't send .mine) :
image

making inputs a little easier in Analysis mode

love the solver so far, especially the JS one, I would appreciate if we can make setting up boards in Analysis mode a little easier. i have come up with 2 small suggestions for now:

  1. instead of left-clicking each and every cell i would love to be able to keep the left click pressed so we fill out larger patches more quickly

  2. [an option so that] mousewheel down to set the cell's minecount at first does not take into account flags and mines around it (i.e. first mousewheel down always sets a 1). left click is still there doing it normally then.

i dont know if i missed out on any keyboard hotkeys, i dont think i have found any. would love a hotkey for the "Analyze" button for example.

Obviously these are not github issues but I didnt wanna dig to deep for direct contact possibilities.

Thank you.

[Board solver] Error: Uncaught (in promise) TypeError: commonClears is null

Steps

  1. Go to https://davidnhill.github.io/JSMinesweeper/
  2. Uncheck analyses mode
  3. Check use seed , set it to 3297235678736273
  4. Check opening on start
  5. Uncheck fast mode
  6. Select custom game, set it to 10 width , 19 height , 71 mines
  7. Select new game
  8. Check "show hints"
  9. Check "Auto play"
  10. Check "Accept guesses"
  11. Now click 2,2 in the grid

Expected

I would expect the solver (to try) to solve the grid, and guess tiles, like it has done flawlessly for many other seeds

Actual

This seed combination causes the solver to error out, locking out the game canvas

afbeelding

Reprocebility:

Always on Firefox 89.0.2 on Ubuntu x64
Always on Chromium 91.0.4472.114 on Ubuntu x64

Error traces:

Firefox 89.0.2:

Uncaught (in promise) TypeError: commonClears is null
    secondarySafetyAnalysis https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/solver_main.js:1024
    tieBreak https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/solver_main.js:518
    doSolve https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/solver_main.js:456
    solver https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/solver_main.js:52
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1238
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1278
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1278
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    setTimeout handler*sendActionsMessage https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:1267
    on_click https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:907
    startup https://davidnhill.github.io/JSMinesweeper/Minesweeper/client/main.js:152

Chromium 91.0.4472.114:

Uncaught (in promise) TypeError: Cannot read property 'length' of null
    at secondarySafetyAnalysis (solver_main.js:1024)
    at tieBreak (solver_main.js:518)
    at doSolve (solver_main.js:456)
    at solver (solver_main.js:52)
    at sendActionsMessage (main.js:1238)
    at main.js:1278

massive bug re. invalid state in analyser

TL;DR: i THINK analyzer breaks when leftclicking/leftdragging THROUGH cells that have a mine in

finds board is in invalid state when it absolutely isn't. says tile is invalid
sometimes even just refreshing the tab corrects the problem with the same exact state of the board

i do hope the invalid state "pinpointer" stays but right now it is overdoing it

edit: it suffices to say the necessary leftclick/leftdragging to rebuild analyzing situations is still easily the weakest point (UX-wise) of this otherwise monumental MS tool at this point :)

instances of efficiency mode not doing a free chord

might be related to that last update?

ive encountered this several times now.

reproducible if u recreate the board in the img (web js version)

sorry if this is not a bug but an efficiency trick i do not know about...
edit: yea i think it only does that if it is 100% sure clicking then chording is definitely not gonna take more clicks...i still think these are new occurences and haven't appeared until recently.
chrome_2021-07-04_02-38-15

Efficiency mode broken?

Maybe I'm doing something wrong, but playing efficiency mode with hints on, I can't figure out how to use chording. Also, after placing a mine the game seems to freeze up and not let me click anything. Please help, thank you

[enhancement] webassembly for more performance

first, it's an amazing tool, best among what i've found and seen yet, also like what i always wanted to create! (but took few action)
then title says it all.
btw the code smells like translated by hands? you might consider using haxe language (which looks like js/ts (when not doing weird things and deep customization) and compiles to js, but also c/c++/c#/more!) to port the solver core into many languages.
although, it's always harder to port into webassembly....

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.