@@ -12,6 +12,9 @@ export class Renderer {
12
12
private heatmap : Heatmap | null = null ;
13
13
private drawBestMoves = false ;
14
14
private alwaysDrawBestMoves = false ;
15
+ private teachBestMoves = false ;
16
+ private autoFlag = false ;
17
+ private autoOpen = false ;
15
18
16
19
constructor ( game : Game , minefieldContainer : HTMLElement ) {
17
20
this . game = game ;
@@ -93,8 +96,23 @@ export class Renderer {
93
96
this . isMouseCaptured = false ;
94
97
95
98
if ( this . mouseDownCell ) {
96
- if ( this . game . tryOpen ( this . mouseDownCell . x , this . mouseDownCell . y ) )
97
- this . afterMove ( ) ;
99
+ if ( this . game . canOpen ( this . mouseDownCell . x , this . mouseDownCell . y ) ) {
100
+ let skipMove = false ;
101
+
102
+ if ( this . teachBestMoves && ! this . drawBestMoves && this . heatmap !== null ) {
103
+ const loseLikelihood = this . heatmap . getBombLikelihood ( this . mouseDownCell . x , this . mouseDownCell . y ) ;
104
+ if ( loseLikelihood !== undefined && loseLikelihood > this . getBestMoveLoseLikelihood ( ) ! ) {
105
+ this . drawBestMoves = true ;
106
+ skipMove = true ;
107
+ }
108
+ }
109
+
110
+ if ( ! skipMove ) {
111
+ this . game . tryOpen ( this . mouseDownCell . x , this . mouseDownCell . y ) ;
112
+ this . afterMove ( ) ;
113
+ }
114
+ }
115
+
98
116
this . mouseDownCell = null ;
99
117
this . render ( ) ;
100
118
}
@@ -112,39 +130,60 @@ export class Renderer {
112
130
this . drawBestMoves = this . alwaysDrawBestMoves ;
113
131
this . render ( ) ;
114
132
break ;
133
+ case 't' :
134
+ this . teachBestMoves = ! this . teachBestMoves ;
135
+ break ;
136
+ case 'a' :
137
+ this . autoFlag = ! this . autoFlag ;
138
+ this . automate ( ) ;
139
+ break ;
140
+ case 'A' :
141
+ this . autoOpen = ! this . autoOpen ;
142
+ this . automate ( ) ;
143
+ break ;
115
144
}
116
145
}
117
146
118
147
private afterMove ( ) {
119
148
if ( ! this . alwaysDrawBestMoves ) this . drawBestMoves = false ;
120
149
121
- const autoFlag = false ;
122
- const autoOpen = false ;
150
+ this . heatmap = Heatmap . compute ( this . game ) ;
151
+ this . automate ( ) ;
152
+ }
123
153
124
- let anyCellOpened ;
125
- do {
126
- anyCellOpened = false ;
154
+ private automate ( ) {
155
+ if ( this . heatmap === null ) return ;
127
156
128
- this . heatmap = Heatmap . compute ( this . game ) ;
157
+ let needsRender = false ;
129
158
130
- if ( autoFlag ) {
159
+ while ( true ) {
160
+ let anyCellOpened = false ;
161
+
162
+ if ( this . autoFlag ) {
131
163
for ( const candidate of this . heatmap . candidates ) {
132
164
if ( candidate . bombLikelihood === 1 ) {
133
165
this . game . tryToggleMark ( candidate . x , candidate . y ) ;
166
+ needsRender = true ;
134
167
}
135
168
}
136
169
}
137
170
138
- if ( autoOpen ) {
171
+ if ( this . autoOpen ) {
139
172
for ( const candidate of this . heatmap . candidates ) {
140
173
if ( candidate . bombLikelihood === 0 ) {
141
174
this . game . tryOpen ( candidate . x , candidate . y ) ;
175
+ needsRender = true ;
142
176
anyCellOpened = true ;
143
177
}
144
178
}
145
179
}
180
+
181
+ if ( ! anyCellOpened ) break ;
182
+
183
+ this . heatmap = Heatmap . compute ( this . game ) ;
146
184
}
147
- while ( anyCellOpened ) ;
185
+
186
+ if ( needsRender ) this . render ( ) ;
148
187
}
149
188
150
189
private onDoubleClick ( ev : MouseEvent ) {
@@ -218,13 +257,11 @@ export class Renderer {
218
257
let drawBestMovesAtLoseLikelihood : number | null = null ;
219
258
220
259
if ( this . heatmap !== null ) {
221
- const fullCertainty = this . heatmap . candidates . some ( c => c . bombLikelihood === 0 || c . bombLikelihood === 1 ) ;
222
- drawHeatmap = alwaysShowHeatmap || ! fullCertainty ;
260
+ const bestMoveLoseLikelihood = this . getBestMoveLoseLikelihood ( ) ! ;
261
+ drawHeatmap = alwaysShowHeatmap || bestMoveLoseLikelihood > 0 ;
223
262
224
263
if ( this . drawBestMoves && this . game . conclusion === null ) {
225
- drawBestMovesAtLoseLikelihood = fullCertainty ? 0 : Math . min (
226
- ...this . heatmap . candidates . map ( c => c . bombLikelihood ) ,
227
- ...( this . heatmap . bombLikelihoodElsewhere !== undefined ? [ this . heatmap . bombLikelihoodElsewhere ] : [ ] ) ) ;
264
+ drawBestMovesAtLoseLikelihood = bestMoveLoseLikelihood ;
228
265
}
229
266
}
230
267
@@ -235,6 +272,17 @@ export class Renderer {
235
272
}
236
273
}
237
274
275
+ private getBestMoveLoseLikelihood ( ) {
276
+ if ( this . heatmap === null ) return null ;
277
+
278
+ if ( this . heatmap . candidates . some ( c => c . bombLikelihood === 0 || c . bombLikelihood === 1 ) )
279
+ return 0 ;
280
+
281
+ return Math . min (
282
+ ...this . heatmap . candidates . map ( c => c . bombLikelihood ) ,
283
+ ...( this . heatmap . bombLikelihoodElsewhere !== undefined ? [ this . heatmap . bombLikelihoodElsewhere ] : [ ] ) ) ;
284
+ }
285
+
238
286
private drawCell ( coords : CellCoords , cellBounds : Rectangle , cellSize : number , drawHeatmap : boolean , drawBestMovesAtLoseLikelihood : number | null ) {
239
287
const { x, y } = coords ;
240
288
0 commit comments