game = {
let flags = [];
let gamestarted = false;
svg.node().innerHTML = '';
svg.append('g').attr('id', 'board');
svg.append('g').attr('id', 'mask');
svg.append('g').attr('id', 'uilayer');
let cells = svg.select('#board').selectAll('path')
.data(grid.flat())
cells.enter()
.append('path')
.merge(cells)
.attr('d', hexpath)
.attr('transform', d => {
let h = hexpos(d.position);
return `matrix(${hexwidth/2} 0 0 ${hexwidth/2} ${h})`
})
.style('fill', d => d.is_mine ? 'white' : theme.cmap(d.count / 4))
.style('stroke', 'lightgray')
.style('stroke-width', '0.1')
.on('mouseover', (e, d) => rendercursor(d.position))
let text = svg.select('#board').selectAll('.label')
.data(grid.flat().filter(c => c.count > 0))
.join('text')
.attr('class', 'label')
.text(d => d.count)
.attr('transform', d => `matrix(1 0 0 1 ${hexpos(d.position)})`)
.style('text-anchor', 'middle')
.style('alignment-baseline', 'middle')
.style('font-family', 'monospace')
.style('font-size', '20pt')
.style('pointer-events', 'none')
let initmask = () => {
svg.select('#mask').selectAll('.mask')
.on('click', (e, d) => {
if (grid[d.position[0]][d.position[1]].is_mine) {
losescreen();
} else {
revealfrom(d.position);
flags = flags.filter(f => !grid[eval(f)[0]][eval(f)[1]].revealed);
renderflags(flags);
rendermask(initmask);
}
})
.on('contextmenu', (e, d) => {
e.preventDefault();
let ps_str = `[${d.position.toString()}]`;
if (flags.includes(ps_str)) {
flags = flags.filter(f => f != ps_str)
} else {
flags.push(ps_str);
}
renderflags(flags);
})
}
rendermask(initmask);
return svg.node();
}