endless-mines/index.html

1494 lines
58 KiB
HTML
Raw Permalink Normal View History

2015-02-28 15:40:37 +00:00
<!DOCTYPE html>
<html>
2015-03-18 14:14:27 +00:00
<head>
<title>endless mines</title>
<style type="text/css">
@font-face {
font-family: Helsinki;
src: url('helsinki.eot');
src: url('helsinki.eot?#iefix') format('embedded-opentype'),
url('helsinki.woff2') format('woff2'),
url('helsinki.woff') format('woff'),
url('helsinki.ttf') format('truetype'),
url('helsinki.svg#helsinkiregular') format('svg');
font-weight: normal;
font-style: normal;
}
* {
box-sizing: border-box;
font-family: Helsinki;
}
html {
background-color: #272822;
margin: 0;
height: 10em; /* fallback */
height: 100vh;
width: 10em; /* fallback */
width: 100vw;
overflow: hidden;
-moz-user-select: none;
2023-02-07 08:45:23 +00:00
-webkit-user-select: none;
2015-03-18 14:14:27 +00:00
-ms-user-select: none;
user-select: none;
}
body {
height: 10em; /* fallback */
height: 100vh;
margin: 0 auto;
width: 10em; /* fallback */
width: 100vmin;
}
@keyframes scrollLeft {
from {left: 0;}
to {
left: -720em; /* fallback */
left: -7200vmin;
}
}
@-webkit-keyframes scrollLeft {
from {left: 0;}
to {
left: -720em; /* fallback */
left: -7200vmin;
}
}
@keyframes bounce {
0% {top: 0; left: 0;}
50% {
top: 1.2em; /* fallback */
top: 12vmin;
left: 0.2em; /* fallback */
left: 2vmin;
}
100% {top: 0; left: 0;}
}
@-webkit-keyframes bounce {
0% {top: 0; left: 0;}
50% {
top: 1.2em; /* fallback */
top: 12vmin;
left: 0.2em;
left: 2vmin;
}
100% {top: 0; left: 0;}
}
@keyframes rainbow {
0% {color: #c6fe7a;}
33% {color: #7ac5fe;}
67% {color: #fe7ac6;}
100% {color: #c6fe7a;} /* back to start */
}
@-webkit-keyframes rainbow {
0% {color: #c6fe7a;}
33% {color: #7ac5fe;}
67% {color: #fe7ac6;}
100% {color: #c6fe7a;} /* back to start */
}
#cracktro {
color: #c6fe7a;
font-size: 0.4em; /* fallback */
font-size: 6vmin;
height: 2em; /* fallback */
height: 20vmin;
margin: 0.4em 0; /* fallback */
margin: 4vmin 0;
overflow: hidden;
white-space: nowrap;
width: 720em;
width: 7200vmin;
position: relative;
animation: scrollLeft 420s linear infinite;
-webkit-animation: scrollLeft 420s linear infinite;
}
#cracktro span {
margin-right: 0.1em; /* fallback */
margin-right: 1vmin;
position: relative;
animation: bounce 4s infinite ease-in-out,rainbow 5s infinite;
-webkit-animation: bounce 4s infinite ease-in-out,rainbow 5s infinite;
text-shadow: 0.5vmin 0.5vmin black;
}
#cracktro span:nth-child(10n+1) {
animation-delay: 0.4s;
-webkit-animation-delay: 0.4s;
}
#cracktro span:nth-child(10n+2) {
animation-delay: 0.8s;
-webkit-animation-delay: 0.8s;
}
#cracktro span:nth-child(10n+3) {
animation-delay: 1.2s;
-webkit-animation-delay: 1.2s;
}
#cracktro span:nth-child(10n+4) {
animation-delay: 1.6s;
-webkit-animation-delay: 1.6s;
}
#cracktro span:nth-child(10n+5) {
animation-delay: 2s;
-webkit-animation-delay: 2s;
}
#cracktro span:nth-child(10n+6) {
animation-delay: 2.4s;
-webkit-animation-delay: 2.4s;
}
#cracktro span:nth-child(10n+7) {
animation-delay: 2.8s;
-webkit-animation-delay: 2.8s;
}
#cracktro span:nth-child(10n+8) {
animation-delay: 3.2s;
-webkit-animation-delay: 3.2s;
}
#cracktro span:nth-child(10n+9) {
animation-delay: 3.6s;
-webkit-animation-delay: 3.6s;
}
2015-03-18 14:14:27 +00:00
#game {
background-color: #1b1c17;
float: left;
margin: 0 auto;
height: 100%;
overflow: hidden;
}
#stats {
height: 1em; /* fallback */
height: 10vmin;
width: 10em; /* fallback */
width: 100vmin;
float: left;
background: #768087;
background: -moz-linear-gradient(top, #768087 0%, #53595e 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #768087), color-stop(100%, #53595e));
background: -webkit-linear-gradient(top, #768087 0%,#53595e 100%);
background: -o-linear-gradient(top, #768087 0%,#53595e 100%);
background: -ms-linear-gradient(top, #768087 0%,#53595e 100%);
background: linear-gradient(to bottom, #768087 0%,#53595e 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#768087', endColorstr='#53595e',GradientType=0 );
}
#stats button {
margin: 0.1em; /* fallback */
margin: 1vmin;
float: right;
font-size: 0.3em; /* fallback */
font-size: 3vmin;
border-radius: 0.2em; /* fallback */
border-radius: 2vmin;
padding: 0.175em; /* fallback */
padding: 1.75vmin;
box-shadow: 0.05em 0.05em 0 #000; /* fallback */
box-shadow: 0.5vmin 0.5vmin 0 #000;
border: 0.4vmin solid #454e52;
position: relative;
top: auto;
left: auto;
}
#stats div {
float: left;
font-size: 0.54em; /* fallback */
font-size: 5.4vmin;
margin: 0.2em; /* fallback */
margin: 2vmin;
width: auto;
}
#gameOver, #setup, #tutorial {
background-color: rgba(0, 0, 0, 0.6);
2015-03-18 14:14:27 +00:00
width: 10em; /* fallback */
width: 100vmin;
height: 10em; /* fallback */
height: 100vh;
overflow: hidden;
position: absolute;
}
#gameOver .score {
margin-right: 1.2em;
margin-right: 12vmin;
2015-03-18 14:14:27 +00:00
}
#setup h2 {
margin-top: 0;
}
2023-02-07 08:45:23 +00:00
#setup h2,
2015-03-18 14:14:27 +00:00
#setup label {
margin: 0.4em 0.35em; /* fallback */
margin: 4vmin 3.5vmin;
font-size: 0.6em; /* fallback */
font-size: 6vmin;
color: #fe7ac6;
text-shadow: 0.05em 0.05em 0 #a4f4b4; /* fallback */
text-shadow: 0.5vmin 0.5vmin 0 #a4f4b4; /* x y blur-radius colour */
}
#tutorial .gameBoard {
float: left;
padding: 0.5em; /* fallback */
padding: 5vmin;
padding-top: 0;
}
#tutorial p {
padding: 0 0.5em; /* fallback */
padding: 0 5vmin;
}
2015-03-18 17:45:50 +00:00
.centre {
clear: both;
2015-03-18 17:45:50 +00:00
margin-top: 0.2em; /* fallback */
margin-top: 2vmin;
text-align: center;
2015-03-18 14:14:27 +00:00
}
.subtitle {
text-align: center;
2015-03-18 14:14:27 +00:00
}
button {
font-size: 0.6em; /* fallback */
font-size: 6vmin;
border-radius: 0.2em; /* fallback */
border-radius: 2vmin;
padding: 0.2em; /* fallback */
padding: 2vmin;
margin: 0 auto;
box-shadow: 0.1em 0.1em 0 #000; /* fallback */
box-shadow: 1vmin 1vmin 0 #000;
border: none;
background: #768087;
background: -moz-linear-gradient(top, #768087 0%, #53595e 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#768087), color-stop(100%,#53595e));
background: -webkit-linear-gradient(top, #768087 0%,#53595e 100%);
background: -o-linear-gradient(top, #768087 0%,#53595e 100%);
background: -ms-linear-gradient(top, #768087 0%,#53595e 100%);
background: linear-gradient(to bottom, #768087 0%,#53595e 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#768087', endColorstr='#53595e',GradientType=0 );
}
button.cancel {
right: 2em;
right: 20vmin;
left: auto;
}
button.donate {
background: #ffefa7;
background: -moz-linear-gradient(top, #ffefa7 0%, #feae27 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffefa7), color-stop(100%,#feae27));
background: -webkit-linear-gradient(top, #ffefa7 0%,#feae27 100%);
background: -o-linear-gradient(top, #ffefa7 0%,#feae27 100%);
background: -ms-linear-gradient(top, #ffefa7 0%,#feae27 100%);
background: linear-gradient(to bottom, #ffefa7 0%,#feae27 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffefa7', endColorstr='#feae27',GradientType=0 );
}
2023-02-07 08:45:23 +00:00
button.mastodon {
background: #51aaea;
background: -moz-linear-gradient(top, #51aaea 0%, #3375a6 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#51aaea), color-stop(100%,#3375a6));
background: -webkit-linear-gradient(top, #51aaea 0%,#3375a6 100%);
background: -o-linear-gradient(top, #51aaea 0%,#3375a6 100%);
background: -ms-linear-gradient(top, #51aaea 0%,#3375a6 100%);
background: linear-gradient(to bottom, #51aaea 0%,#3375a6 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#51aaea', endColorstr='#3375a6',GradientType=0 );
}
form {
display: inline;
}
2015-03-18 14:14:27 +00:00
h1, h2 {
text-align: center;
}
h1 {
color: #a4f4b4;
font-size: 1.2em; /* fallback */
font-size: 12vmin;
margin-top: 0.6em; /* fallback */
margin-top: 6vmin;
margin-bottom: 0.6em; /* fallback */
margin-bottom: 6vmin;
text-shadow: 0.1em 0..1em 0 #fe7ac6; /* fallback */
text-shadow: 1vmin 1vmin 0 #fe7ac6; /* x y blur-radius colour */
}
h2 {
color: #7ac5fe;
font-size: 0.6em; /* fallback */
font-size: 6vmin;
}
2015-03-18 14:14:27 +00:00
ul {
float: left;
clear: both;
height: 1em; /* fallback */
height: 10vmin;
2015-03-18 14:14:27 +00:00
list-style-type: none;
padding: 0;
margin: 0;
overflow: hidden;
}
li {
color: white;
font-size: 0.8em; /* fallback */
font-size: 8vmin;
padding: 0.1em; /* fallback */
padding: 1vmin;
padding-top: 0.05em; /* fallback */
padding-top: 0.5vmin;
padding-bottom: 0.15em; /* fallback */
padding-bottom: 1.5vmin;
text-align: center;
vertical-align: middle;
float: left;
height: 1em; /* fallback */
height: 10vmin;
width: 1em; /* fallback */
width: 10vmin;
background-color: #454e52;
border-radius: 0.2em; /* fallback */
border-radius: 2vmin;
cursor: default;
}
li.revealed {
background-color: #1b1c17;
}
li:not(.revealed):hover {
background-color: #a0a9af;
}
li.flagged {
background-color: #b5fe52;
background-image: url("images/flag.png");
background-size: 100% 100%;
2015-03-18 14:14:27 +00:00
}
li.flagged:hover {
background-color: #c6fe7a;
}
li.highlighted {
border: 0.1em solid #fe7ac6; /* fallback */
border: 1vmin solid #fe7ac6;
padding: 0;
}
2015-03-18 14:14:27 +00:00
li.mine.revealed {
background-color: #d23000;
background-image: url("images/skull.png");
background-size: 100% 100%;
2015-03-18 14:14:27 +00:00
}
li.mines1 {
color: #c6fe7a;
}
li.mines2 {
color: #7ac5fe;
}
li.mines3 {
color: #fe7ac6;
}
li.mines4 {
color: #b17afe;
}
li.mines5 {
color: #feb27a;
}
li.mines6 {
color: #7afeb2;
}
li.mines7 {
color: #d74600;
}
li.mines8 {
color: #8c4600;
}
p {
color: #fff;
font-size: 0.43em; /* fallback */
font-size: 4.3vmin;
padding: 0 1em; /* fallback */
padding: 0 10vmin;
}
strong {
color: #fe7ac6;
}
table {
color: #fe7ac6;
font-size: 4vmin;
margin: 0 auto;
text-align: center;
}
th, td {
width: 50%;
}
td {
color: #fff;
font-size: 8vmin;
}
2015-03-18 14:14:27 +00:00
</style>
<script src="jquery-2.1.3.min.js"></script>
<script>
var gameBoardWidth = 10;
var gameBoardHeight = 9;
var score = 0;
var firstClick = true;
var difficulty = "normal";
var mineChance = 0.2; //normal
var clickholdMs = 200;
var mouseHeld = false;
2015-03-18 14:14:27 +00:00
var timeout; //hold timer
var viewportSizingAvailable = ($('#game').height == $(window).height()); // only run once
var tutorialPages = [];
2015-03-18 14:14:27 +00:00
$(document).ready(function() {
function drawGameBoard() {
$('#game').html("");
$('#tutorial .gameBoard').html("");
2015-03-18 14:14:27 +00:00
gameBoardWidth = 10;
2023-02-07 08:45:23 +00:00
2015-03-18 14:14:27 +00:00
//determine aspect ratio so as to fit the screen
gameBoardHeight = determineGameBoardHeight();
2015-03-18 14:14:27 +00:00
for (var i = 0; i < gameBoardHeight; i++) {
$('#game').append(newRow());
}
}
function determineGameBoardHeight() {
return Math.max(
Math.floor((1 / getAspectRatio()) * 10) - 1,
9 //minimum
);
}
2015-03-18 14:14:27 +00:00
function newTile() {
if (Math.random() < mineChance) {
return '<li class="mine"></li>';
} else {
return '<li></li>';
}
}
function newRow() {
var row = '<ul>';
for (var i = 0; i < gameBoardWidth; i++) {
row += newTile();
};
row += '</ul>';
return row;
}
function saveGame() {
if (typeof(Storage) == "undefined") {
return;
}
//variables
localStorage.setItem("score", score);
2015-03-18 14:14:27 +00:00
localStorage.setItem("mineChance", mineChance);
//game board
localStorage.setItem("gameBoard", $('#game').html());
}
function loadGame() {
//check if storage available and if saved game exists
if (typeof(Storage) == "undefined" || localStorage.getItem("gameBoard") == null) {
drawGameBoard();
return;
}
//variables
score = parseInt(localStorage.getItem("score"));
2015-03-18 14:14:27 +00:00
mineChance = parseFloat(localStorage.getItem("mineChance"));
firstClick = false;
2015-03-18 14:14:27 +00:00
//game board
$('#game').html(localStorage.getItem("gameBoard"));
gameBoardHeight = determineGameBoardHeight();
// add rows if there is empty space
while ($('ul').length < gameBoardHeight) {
$('#game').append(newRow());
}
//remove any rows the screen cannot display
$('#game ul:gt(' + (gameBoardHeight - 1) + ')').remove();
refreshMineCounts();
updateScore();
updateMinesLeft();
//click blank tiles
$('li.revealed:not(.mine):empty').mouseup();
2015-03-18 14:14:27 +00:00
$('#setup').hide();
}
$.fn.check = function() {
//unclicked tiles
if ($(this).filter('li:not(.revealed):not(.flagged)').length > 0) {
return false;
}
//incorrectly flagged tiles
if ($(this).filter('li.flagged:not(.mine)').length > 0) {
return false;
}
//clicked mines
if ($(this).filter('li.revealed.mine').length > 0) {
return false;
}
return true;
}
$.fn.checkRow = function() {
return $(this).children().check();
}
$.fn.checkColumn = function() {
return $(this).column().check();
}
window.removeClearedRows = function() {
var rowsToRemove = $('ul:not(.removing)').filter(function() {
2015-03-18 14:14:27 +00:00
return $(this).checkRow();
});
if (rowsToRemove.length > 0) {
suddenDeath();
}
rowsToRemove.each(function() {
score += $(this).children('.mine').length;
$(this).addClass("removing");
$(this).slideUp("slow", function() {
//add new row on bottom
$(this).closest("div").append(newRow());
$(this).remove();
2015-03-18 14:14:27 +00:00
refreshMineCounts();
//click blank tiles
$('li.revealed:not(.mine):empty').mouseup();
});
});
}
window.removeClearedColumns = function() {
var columnsToRemove = $('ul:not(.removing):eq(0) li:not(.removing)').filter(function() {
return $(this).checkColumn();
});
if (columnsToRemove.length > 0) {
suddenDeath();
}
columnsToRemove.each(function() {
score += $(this).column().filter('.mine').length;
$(this).column().addClass("removing");
//animation for top row + deletion of column
$(this).animate({width: 0, borderRadius: 0, padding: 0}, "slow", function() {
$(this).column().remove();
2015-03-18 14:14:27 +00:00
$('ul').each(function() {
$(this).append(newTile());
});
refreshMineCounts();
//click blank tiles
$('li.revealed:not(.mine, .removing):empty').mouseup();
});
//then just animation for others
$(this).column().animate({width: 0, borderRadius: 0, padding: 0}, "slow");
});
}
function refreshMineCounts() {
$('ul:not(.removing) li.revealed:not(.mine, .removing)').each(function() {
var mineCount = $(this).countMinesText();
2023-02-07 08:45:23 +00:00
2015-03-18 14:14:27 +00:00
$(this).text(mineCount);
//remove "mines1" etc
$(this).attr(
2023-02-07 08:45:23 +00:00
'class',
2015-03-18 14:14:27 +00:00
$(this).attr('class').replace(
/mines[0-9]/, "mines" + mineCount
)
);
$(this).removeClass("mines mines0");
});
}
function updateScore() {
$('#score').text("Score: " + score);
}
function isGameOver() {
return $('ul').has('.mine.revealed').length == gameBoardHeight
&& $('ul').first().children().filter(function() {
return $(this).column().filter('.mine.revealed').length > 0;
}).length == gameBoardWidth;
}
function checkGameOver() {
if (isGameOver()) {
$('#gameOver').show();
2023-02-07 08:45:23 +00:00
2015-03-18 20:41:42 +00:00
var currentHiScore = 0;
if ($.isNumeric(localStorage.getItem("hiscore"))) {
currentHiScore = parseInt(localStorage.getItem("hiscore"));
}
if (score > currentHiScore) {
currentHiScore = score;
}
$('#gameOver .score').text(score);
$('#gameOver .hiscore').text(currentHiScore);
2015-03-18 18:41:17 +00:00
//clear saved game
localStorage.clear();
2015-03-18 20:41:42 +00:00
localStorage.setItem("hiscore", currentHiScore);
2015-03-18 14:14:27 +00:00
}
}
function checkTutorial() {
if ($('#tutorial').is(':hidden')) {
return;
}
var currentPage = $('#tutorial div:visible');
if (
currentPage.find('.toFlag' ).length == currentPage.find('.toFlag.flagged' ).length
&& currentPage.find('.toClick').length == currentPage.find('.toClick.revealed' ).length
&& (currentPage.find('.flagAny' ).length == 0 || currentPage.find('.flagAny.flagged' ).length > 0)
&& (currentPage.find('.clickAny').length == 0 || currentPage.find('.clickAny.revealed').length > 0)
) {
currentPage.nextPage();
}
}
$.fn.nextPage = function() {
$('.gameBoard').html("");
$(this).hide();
if ($(this).is(':last-child')) {
//end of tutorial!
$('#tutorial').hide();
$('#setup, #game, #stats').show();
$('#setup button.cancel').hide();
gameBoardWidth = 10;
gameBoardHeight = determineGameBoardHeight();
} else {
$(this).next().show();
$(this).next().children().show();
var nextPage = parseInt($(this).attr('id').replace("page", ""));
$(this).next().children('.gameBoard').html(tutorialPages[nextPage]);
if ($(this).next().children('.gameBoard').hasClass("clearRowsColumns")) {
removeClearedRows();
removeClearedColumns();
}
}
}
2015-03-18 14:14:27 +00:00
function updateMinesLeft() {
//unflagged mines - revealed mines - flagged not-mines
$('#mines').text(
2023-02-07 08:45:23 +00:00
"Mines left: "
2015-03-18 14:14:27 +00:00
+ ($('.mine:not(.flagged)').length
- $('.mine.revealed').length
- $('li:not(.mine).flagged').length)
);
}
function getAspectRatio() {
return $(window).width() / $(window).height();
}
function resizeToWindow() {
if (!viewportSizingAvailable) {
$('html').css('font-size', Math.min($(window).width(), $(window).height()) / 10);
}
}
function isPortrait() {
return getAspectRatio() > 1;
}
$.fn.updateMineCount = function() {
$(this).text(
$(this).countMinesText
);
}
$.fn.rowScore = function() {
return $(this).children('.mine').length;
}
$.fn.rowAbove = function() {
return $(this).parent('ul').prev();
}
$.fn.rowBelow = function() {
return $(this).parent('ul').next();
}
$.fn.column = function() {
var x = $(this).getX();
var column = $('');
$('ul').each(function() {
column = column.add($(this).children().eq(x));
});
return column;
}
window.oneColumnLeft = function() {
return $('ul').first().children().filter(function() {
return $(this).column().filter('.mine:not(.revealed, .flagged)').length == 0;
}).length >= (gameBoardWidth - 1)
}
window.oneRowLeft = function() {
return $('ul').filter(function() {
return $(this).children('.mine:not(.revealed, .flagged)').length == 0;
}).length >= (gameBoardHeight - 1);
}
window.isSuddenDeath = function() {
return oneRowLeft() && oneColumnLeft();
}
window.suddenDeath = function() {
if (isSuddenDeath()) {
mineChance += 0.03;
2015-03-18 14:14:27 +00:00
//don't want the chance to get to 100% because that's completely predictable
2015-04-22 21:45:46 +00:00
// 2/3rds chance is the most likely to create an unsolveable repeating pattern (xxoxxoxxo, etc.)
if (mineChance > 0.666) {
mineChance = 0.666;
2015-03-18 14:14:27 +00:00
}
}
}
$.fn.getX = function() {
return $(this).index();
}
$.fn.getY = function() {
return $(this).parent('ul').index();
}
$.fn.isMine = function() {
return $(this).hasClass("mine");
}
$.fn.countMinesAdjacent = function() {
return $(this).getAdjacentTiles().filter('.mine').length;
}
$.fn.getAdjacentTiles = function() {
var adjacentTiles = $('');
var x = $(this).getX();
var y = $(this).getY();
if (y > 0) {
var tileAbove = $(this).rowAbove().children().eq(x);
adjacentTiles = adjacentTiles.add(tileAbove.prev());
adjacentTiles = adjacentTiles.add(tileAbove );
adjacentTiles = adjacentTiles.add(tileAbove.next());
}
adjacentTiles = adjacentTiles.add($(this).prev());
adjacentTiles = adjacentTiles.add($(this).next());
if (y < (gameBoardHeight - 1)) {
var tileBelow = $(this).rowBelow().children().eq(x);
adjacentTiles = adjacentTiles.add(tileBelow.prev());
adjacentTiles = adjacentTiles.add(tileBelow );
adjacentTiles = adjacentTiles.add(tileBelow.next());
}
return adjacentTiles;
}
$.fn.countMinesText = function() {
return $(this).countMinesAdjacent().toString().replace("0", "");
}
function detachTutorials() {
//can't have several game boards in play at the same time
//because it messes with mine counts, row counts, etc.
tutorialPages = [];
$('#tutorial .gameBoard').each(function() {
tutorialPages.push($(this).html());
$(this).html("");
});
}
$.fn.cracktro = function() {
//trim long whitespaces to 1 space, remove line breaks, split to individual chars
var text = $(this).html().replace(/ +/g, " ").replace(/(\r\n|\n|\r)/gm, "").replace("&amp;", "&").split("");
var cracktro = "";
for (var i = 0; i < text.length; i++) {
cracktro += "<span>" + text[i].replace(" ", "&nbsp;") + "</span>";
}
$(this).html(cracktro);
}
2015-03-18 14:14:27 +00:00
$('#gameOver button').on("click", function() {
drawGameBoard();
$('#gameOver').hide();
$('button.cancel').hide();
$('button.start').removeAttr('style');
$('#setup').show();
});
$('button.reset').on("click", function() {
//prompt user with setup screen
$('#setup').show();
$('button.cancel').show();
$('button.start').css('left', '20vmin');
});
$('button.cancel').on("click", function() {
//prompt user with setup screen
$('#setup').hide();
$('button.cancel').hide();
$('button.start').removeAttr('style');
});
$('button.start').on("click", function() {
drawGameBoard();
//reset stats
firstClick = true;
//set difficulty
if ($(this).hasClass("easy")) {
mineChance = 0.13;
} else if ($(this).hasClass("normal")) {
mineChance = 0.2;
} else if ($(this).hasClass("hard")) {
mineChance = 0.285;
}
2015-03-18 14:14:27 +00:00
score = 0;
updateScore();
updateMinesLeft();
$('#setup').hide();
});
$('button.tutorial').on("click", function() {
$('#tutorial').show();
$('#tutorial').siblings().hide();
$('#page1').show();
$('#page1 *').show();
$('#page1').siblings('div').hide();
$('#page1 .gameBoard').html(tutorialPages[0]);
$('#game').html("");
gameBoardWidth = 5;
gameBoardHeight = 5;
});
2015-03-18 14:14:27 +00:00
$.fn.leftClick = function(automated) {
if (!automated) automated = false;
//don't want first click to be a mine
if (firstClick) {
var x = $(this).getX();
x = (x >= 1) ? x : 1;
x = (x <= gameBoardWidth - 2) ? x : gameBoardWidth - 2;
var y = $(this).getY();
y = (y >= 1) ? y : 1;
y = (y <= gameBoardHeight - 2) ? y : gameBoardHeight - 2;
$('ul').eq(y - 1).children().slice(x - 1).filter(':lt(3)').removeClass("mine");
$('ul').eq(y ).children().slice(x - 1).filter(':lt(3)').removeClass("mine");
$('ul').eq(y + 1).children().slice(x - 1).filter(':lt(3)').removeClass("mine");
firstClick = false;
}
if ($(this).hasClass("flagged")) {
return;
}
if ($(this).isMine()) {
$(this).addClass("revealed");
} else if (!automated && parseInt($(this).text()) === $(this).getAdjacentTiles().filter('.flagged, .revealed.mine').length) {
//already clicked; use middle click reveal functionality
2023-02-07 08:45:23 +00:00
2015-03-18 14:14:27 +00:00
//number of flags matches number of adjacent mines
$(this).getAdjacentTiles().filter(':not(.flagged, .revealed)').mouseup();
} else {
$(this).addClass("revealed");
$(this).updateMineCount();
$(this).addClass("mines" + $(this).countMinesAdjacent());
//if no mines adjacent, cascade!
if ($(this).countMinesAdjacent() == 0) {
$(this).getAdjacentTiles().filter(':not(.revealed)').mouseup();
}
}
firstClick = false;
}
$.fn.middleClick = function() {
//number of flags matches number of adjacent mines
if (parseInt($(this).text()) === $(this).getAdjacentTiles().filter('.flagged, .revealed.mine').length) {
$(this).getAdjacentTiles().filter(':not(.flagged, .revealed)').mouseup();
}
}
$.fn.rightClick = function() {
if (!$(this).hasClass("revealed")) {
$(this).toggleClass("flagged");
}
clearTimeout(timeout);
}
$(document).on("contextmenu", "body", function(event) {
event.preventDefault();
});
$(document).on("mousedown touchstart", "li", function(event) {
var x = $(this).getX();
var y = $(this).getY();
timeout = setTimeout(function() {
$('ul:eq(' + y + ') li:eq(' + x + ')').rightClick();
mouseHeld = true;
}, clickholdMs);
});
$(document).on("mouseleave", "li", function(event) {
clearTimeout(timeout);
});
$(document).on("mouseup touchend", "li", function(event) {
event.preventDefault();
clearTimeout(timeout);
if (mouseHeld) {
mouseHeld = false;
//rightClick has already been called in a callback, so nothing to do here
} else {
switch (event.which) {
case 3:
$(this).rightClick();
break;
case 2:
$(this).middleClick();
break;
case 1:
$(this).leftClick();
break;
default:
$(this).leftClick(true); //automated
break;
}
}
checkTutorial();
2015-03-18 14:14:27 +00:00
if ($('#tutorial').is(':hidden')) {
removeClearedRows();
removeClearedColumns();
saveGame();
checkGameOver();
updateScore();
updateMinesLeft();
}
2015-03-18 14:14:27 +00:00
});
$(window).resize(function() {
resizeToWindow();
});
resizeToWindow();
detachTutorials();
2015-03-18 14:14:27 +00:00
//instantiate the game
loadGame(); //loadGame will draw the game board if no saved game is found
$('#gameOver').hide();
$('#tutorial').hide();
2015-03-18 14:14:27 +00:00
$('button.cancel').hide();
$('#cracktro').cracktro();
2015-03-18 14:14:27 +00:00
});
</script>
</head>
<body>
<div id="stats">
<div id="score">Score: 0</div>
<div id="mines">Mines left: 0</div>
<button class="reset">reset</button>
</div>
<div id="game"></div>
<div id="gameOver">
<h1>game over</h1>
<table>
<thead>
<tr>
<th>score</th><th>personal best</th>
</tr>
</thead>
<tbody>
<tr>
<td class="score"></td><td class="hiscore"></td>
</tr>
</tbody>
</table>
<div id="cracktro">
......................................................................
a game by max bradbury
......................................................................
inspired by minesweeper, tetris and 2048
......................................................................
2023-02-07 08:45:23 +00:00
gratz 'n' greetz go out to mum and dad, guy, titas, dan, nick, enrico,
ahona, robin, arielle, isy, thom, tom, olu, lovely dave, jen, ed,
david, andy, rachel, isaac, rory, 'partay' pat, al, ant, zoe, john,
charlie, wilkie, george
......................................................................
2023-02-07 08:45:23 +00:00
HELLO's fly out to some cool game devs: porpentine, merritt kopas,
zoe quinn, aniwey, orteil
......................................................................
i listened to a lot of keygenjukebox while coding this
......................................................................
more games coming soon... keep your eyes peeled... peace!
......................................................................
......................................................................
......................................................................
2023-02-07 08:45:23 +00:00
this story is dedicated to all those cyberpunks who fight against
injustice and corruption every day of their lives
......................................................................
</div>
2015-03-18 17:45:50 +00:00
<div class="centre">
2023-02-07 08:45:23 +00:00
<form action="https://timetheft.social/@tinybird" method="post" target="_blank">
<button class="mastodon">say hi</button>
</form>
</div>
<div class="centre">
<button>play again</button>
2015-03-18 17:45:50 +00:00
</div>
2015-03-18 14:14:27 +00:00
</div>
<div id="setup">
<h1>endless mines</h1>
2015-04-22 21:50:28 +00:00
<p class="subtitle">ruin 2015</p>
2023-02-07 08:45:23 +00:00
2015-03-22 18:50:43 +00:00
<p>
<strong>left click</strong> or <strong>tap</strong> to clear a tile. <br>
<strong>right click</strong> or <strong>hold</strong> to flag a mine. <br>
rows and columns with <strong>exploded mines</strong> cannot be cleared.
</p>
2015-03-18 14:14:27 +00:00
<h2>Start game</h2>
2015-03-18 14:14:27 +00:00
<div class="centre">
<button class="start easy">easy</button>
<button class="start normal">normal</button>
<button class="start hard">hard</button>
2015-03-18 14:14:27 +00:00
</div>
2023-02-07 08:45:23 +00:00
2015-03-18 14:14:27 +00:00
<div class="centre">
<button class="tutorial">tutorial</button>
2015-03-18 14:14:27 +00:00
<button class="cancel">cancel</button>
</div>
</div>
<div id="tutorial">
<h2>tutorial</h2>
<div id="page1">
<div class="gameBoard">
<ul>
<li class="mine"></li><li></li><li></li><li></li><li></li>
</ul>
<ul>
<li></li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="mine toFlag"></li><li></li>
</ul>
<ul>
<li></li><li class="revealed mines1">1</li><li class="revealed mines2 highlighted">2</li><li class="revealed mines2">2</li><li></li>
</ul>
<ul>
<li></li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="mine toFlag"></li><li></li>
</ul>
<ul>
<li class="mine"></li><li></li><li></li><li></li><li></li>
</ul>
</div>
<p>take a look at the <strong>highlighted tile</strong>.</p>
<p>the <strong>2</strong> means there are <strong>2 mines</strong> next to it.</p>
<p>there are only <strong>2 tiles</strong> next to it, so we know they are both mines.</p>
<p><strong>right-click</strong> or <strong>press and hold</strong> to flag these mines.</p>
</div>
<div id="page2">
<div class="gameBoard">
<ul>
<li class="mine"></li><li></li><li></li><li></li><li></li>
</ul>
<ul>
<li></li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="mine flagged"></li><li class="toClick"></li>
</ul>
<ul>
<li></li><li class="revealed mines1">1</li><li class="revealed mines2">2</li><li class="revealed mines2 highlighted">2</li><li class="toClick"></li>
</ul>
<ul>
<li></li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="mine flagged"></li><li class="toClick"></li>
</ul>
<ul>
<li class="mine"></li><li></li><li></li><li></li><li></li>
</ul>
</div>
<p>take a look at the next <strong>highlighted tile</strong>.</p>
<p>this also has <strong>2 mines</strong> next to it- but we already know which ones are mines.</p>
<p><strong>click</strong> or <strong>tap</strong> the other adjacent tiles to clear them.</p>
</div>
<div id="page3">
<div class="gameBoard">
<ul>
<li class="mine"></li><li class="toClick"></li><li class="toClick"></li><li class="toClick"></li><li class="toClick"></li>
</ul>
<ul>
<li></li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="mine flagged"></li><li class="revealed mines1">1</li>
</ul>
<ul>
<li></li><li class="revealed mines1">1</li><li class="revealed mines2">2</li><li class="revealed mines2">2</li><li class="revealed mines2">2</li>
</ul>
<ul>
<li></li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="mine flagged"></li><li class="revealed mines1">1</li>
</ul>
<ul>
<li class="mine"></li><li class="toClick"></li><li class="toClick"></li><li class="toClick"></li><li class="toClick"></li>
</ul>
</div>
<p>there are some more tiles that are definitely not mines. clear these too.</p>
<p>if you <strong>click or tap</strong> a <strong>number</strong>, any unflagged adjacent tiles will be clicked.</p>
<p>this can save you a lot of time!</p>
</div>
<div id="page4">
<div class="gameBoard">
<ul>
<li class="mine"></li><li class="revealed mines1 highlighted">1</li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="revealed mines1">1</li>
</ul>
<ul>
<li></li><li class="revealed mines1 highlighted">1</li><li class="revealed mines1">1</li><li class="mine flagged"></li><li class="revealed mines1">1</li>
</ul>
<ul>
<li class="toClick"></li><li class="revealed mines1">1</li><li class="revealed mines2">2</li><li class="revealed mines2">2</li><li class="revealed mines2">2</li>
</ul>
<ul>
<li></li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="mine flagged"></li><li class="revealed mines1">1</li>
</ul>
<ul>
<li class="mine"></li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="revealed mines1">1</li>
</ul>
</div>
<p>look at these 2 <strong>highlighted</strong> tiles.</p>
<p>the <strong>first</strong> has 1 mine next to it.</p>
<p>the <strong>second</strong> also has 1 mine next to it.</p>
<p>however, the <strong>second</strong> spans the same tiles as the <strong>first</strong>, plus one extra.</p>
<p>the extra tile the <strong>second</strong> tile spans cannot be a mine. clear it!</p>
</div>
<div id="page5">
<div class="gameBoard">
<ul>
<li class="mine toFlag"></li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="revealed mines1">1</li>
</ul>
<ul>
<li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="mine flagged"></li><li class="revealed mines1">1</li>
</ul>
<ul>
<li class="revealed"></li><li class="revealed mines1">1</li><li class="revealed mines2">2</li><li class="revealed mines2">2</li><li class="revealed mines2">2</li>
</ul>
<ul>
<li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="mine flagged"></li><li class="revealed mines1">1</li>
</ul>
<ul>
<li class="mine toFlag"></li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="revealed mines1">1</li><li class="revealed mines1">1</li>
</ul>
</div>
<p>when you clear a tile with <strong>no adjacent mines</strong>, the surrounding tiles will all clear as well.</p>
<p>flag the <strong>remaining mines</strong>.</p>
</div>
<div id="page6">
<div class="gameBoard">
<ul>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed mines2">2</li>
<li class="mine"></li>
</ul>
<ul>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed mines3">3</li>
<li class="mine"></li>
</ul>
<ul>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed mines3">3</li>
<li class="mine toFlag highlighted"></li>
</ul>
<ul>
<li class="revealed mines2">2</li>
<li class="revealed mines3">3</li>
<li class="revealed mines3">3</li>
<li class="revealed mines4">4</li>
<li class="mine"></li>
</ul>
<ul>
<li class="mine"></li>
<li class="mine"></li>
<li class="mine"></li>
<li class="mine"></li>
<li class="revealed mines2">2</li>
</ul>
</div>
<p>in this tutorial so far, the game board has been static.</p>
<p>but in <strong>endless mines</strong>, <strong>rows</strong> and <strong>columns</strong> slide away when cleared!</p>
<p>flag the <strong>highlighted</strong> tile to continue.</p>
</div>
<div id="page7">
<div class="gameBoard clearRowsColumns">
<ul>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed mines2">2</li>
<li class="mine"></li>
</ul>
<ul>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed mines3">3</li>
<li class="mine"></li>
</ul>
<ul>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed mines3">3</li>
<li class="mine flagged"></li>
</ul>
<ul>
<li class="revealed mines2">2</li>
<li class="revealed mines3">3</li>
<li class="revealed mines3">3</li>
<li class="revealed mines4">4</li>
<li class="mine"></li>
</ul>
<ul>
<li class="mine"></li>
<li class="mine"></li>
<li class="mine"></li>
<li class="mine"></li>
<li class="revealed mines2">2</li>
</ul>
</div>
<p>in this tutorial so far, the game board has been static.</p>
<p>but in <strong>endless mines</strong>, <strong>rows</strong> and <strong>columns</strong> slide away when cleared!</p>
<p>flag the <strong>highlighted</strong> tile to continue.</p>
</div>
<div id="page8">
<div class="gameBoard">
<ul>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed mines2">2</li>
<li class="mine toFlag"></li>
</ul>
<ul>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed"></li>
<li class="revealed mines3">3</li>
<li class="mine toFlag"></li>
</ul>
<ul>
<li class="revealed mines2">2</li>
<li class="revealed mines3">3</li>
<li class="revealed mines3">3</li>
<li class="revealed mines4">4</li>
<li class="mine toFlag"></li>
</ul>
<ul>
<li class="mine toFlag"></li>
<li class="mine toFlag"></li>
<li class="mine toFlag"></li>
<li class="mine toFlag"></li>
<li class="revealed mines2">2</li>
</ul>
<ul>
<li></li><li></li><li></li><li></li><li></li>
</ul>
</div>
<p>a <strong>new row</strong> has appeared at the bottom.</p>
<p>notice how you can't clear any columns now!</p>
<br>
<p><strong>flag</strong> the <strong>remaining mines</strong> to continue.</p>
</div>
<div id="page9">
<div class="gameBoard clearRowsColumns">
<ul><li></li><li></li><li></li><li></li><li></li></ul>
<ul><li class="mine"></li><li></li><li class="mine"></li><li class="mine"></li><li class="mine"></li></ul>
<ul><li class="revealed mines2">2</li><li class="revealed mines4">4</li><li class="revealed mines4">4</li><li class="highlighted revealed mines7">7</li><li class="mine toFlag"></li></ul>
<ul><li class="mine"></li><li></li><li class="mine"></li><li class="mine"></li><li class="mine"></li></ul>
<ul><li></li><li></li><li></li><li></li><li></li></ul>
</div>
<p>look at the <strong>highlighted</strong> tile.</p>
<p>it has 7 adjacent mines and 7 adjacent tiles.</p>
<p>flag the 7 <strong>adjacent mines</strong>.</p>
</div>
<div id="page10">
<div class="gameBoard clearRowsColumns">
<ul><li></li><li></li><li></li><li></li><li></li></ul>
<ul><li class="mine"></li><li></li><li class="mine"></li><li class="mine"></li><li class="mine"></li></ul>
<ul><li class="revealed mines2">2</li><li class="revealed mines4">4</li><li class="revealed mines4">4</li><li class="revealed mines7">7</li><li class="mine highlighted flagged"></li></ul>
<ul><li class="mine"></li><li></li><li class="mine"></li><li class="mine"></li><li class="mine"></li></ul>
<ul><li></li><li></li><li></li><li></li><li></li></ul>
</div>
<p>oh no! we've lost all our hints!</p>
<p>sometimes it's best to wait before clearing a row.</p>
<br>
<p>the best we can do is guess now.</p>
<p>click <strong>any tile</strong> to continue.</p>
</div>
<div id="page11">
<div class="gameBoard clearRowsColumns">
<ul><li></li><li></li><li></li><li></li><li></li></ul>
<ul><li></li><li class="revealed mines1">1</li><li></li><li class="revealed mines1">1</li><li></li></ul>
<ul><li></li><li></li><li></li><li></li><li></li></ul>
<ul><li></li><li class="revealed mines3">3</li><li class="revealed mines3">3</li><li class="revealed mines3">3</li><li></li></ul>
<ul><li></li><li></li><li class="revealed mines3">3</li><li></li><li></li></ul>
</div>
<p>sorry! I feel bad leading you into a trap like that!</p>
<p>but I think mistakes are a good way to learn.</p>
<p>this is the end of the <strong>tutorial</strong> for now. I hope it has helped in some way.</p>
<p>have fun!</p>
</div>
</div>
2015-03-18 14:14:27 +00:00
</body>
2023-02-07 08:45:23 +00:00
</html>