PageSourceSearch

https://ilmenit.github.io/pressure/js/tutorial-steps.js

js ilmenit.github.io collected 2026-10-03 09:20:34 UTC 14,011 bytes, 331 lines download raw bytes

1/**
2 * tutorial-steps.js
3 * Manages tutorial step definitions and validation logic
4 * SIMPLIFIED VERSION: Remove reliance on capture events
5 */
6class TutorialStepManager {
7    constructor(tutorialService) {
8        this.tutorialService = tutorialService;
9        this.game = tutorialService.game;
10        this.board = tutorialService.board;
11        this.events = tutorialService.events;
12        
13        // Current expected action
14        this.expectedActionIndex = 0;
15        this.stepCompleted = false;
16        this.isRetrying = false;
17        
18        // Track if a move has been made
19        this.movePerformed = false;
20        
21        // Step definitions
22        this.steps = this.defineSteps();
23    }
24    
25    /**
26     * Define all tutorial steps
27     */
28    defineSteps() {
29        return [
30            // Step 1: Basic Movement
31            {
32                id: "basic-movement",
33                title: "Basic Movement",
34                instructions: "You can move tokens in two ways: Click to select and click again to move, or drag and drop. Try moving your white token to an adjacent space.",
35                boardSetup: [
36                    { row: 2, col: 2, color: 'white' }
37                ],
38                initialHighlights: [{ row: 2, col: 2 }],
39                expectedActions: [
40                    {
41                        type: 'select',
42                        position: { row: 2, col: 2 },
43                        nextInstructions: "Now click on a highlighted cell to move your token.",
44                        highlightPositions: [
45                            { row: 1, col: 2 }, // Up
46                            { row: 3, col: 2 }, // Down
47                            { row: 2, col: 1 }, // Left
48                            { row: 2, col: 3 }  // Right
49                        ]
50                    },
51                    {
52                        type: 'move',
53                        validDestinations: [
54                            { row: 1, col: 2 }, { row: 3, col: 2 }, 
55                            { row: 2, col: 1 }, { row: 2, col: 3 }
56                        ],
57                        nextInstructions: "Great! You can move to any adjacent empty space."
58                        // Note: completesStep removed - handled by tutorialService
59                    }
60                ]
61            },
62            
63            // Step 2: Turn Alternation
64            {
65                id: "turn-alternation",
66                title: "Taking Turns",
67                instructions: "In Pressure, players take turns. Make a move with your white token.",
68                boardSetup: [
69                    { row: 2, col: 1, color: 'white' },
70                    { row: 4, col: 3, color: 'black' }
71                ],
72                initialHighlights: [{ row: 2, col: 1 }],
73                expectedActions: [
74                    {
75                        type: 'select',
76                        position: { row: 2, col: 1 },
77                        nextInstructions: "Select a destination for your token."
78                    },
79                    {
80                        type: 'move',
81                        nextInstructions: "Now the black player (AI) will take their turn."
82                        // onComplete removed - handled by tutorialService
83                    }
84                ]
85            },
86            
87            // Step 3: Basic Pushing
88            {
89                id: "basic-pushing",
90                title: "Basic Pushing",
91                instructions: "You can push tokens if there's an empty space at the end of the line. Try pushing the black token by moving right.",
92                boardSetup: [
93                    { row: 2, col: 1, color: 'white' },
94                    { row: 2, col: 2, color: 'black' }
95                    // Empty space at 2,3
96                ],
97                initialHighlights: [{ row: 2, col: 1 }],
98                expectedActions: [
99                    {
100                        type: 'select',
101                        position: { row: 2, col: 1 },
102                        nextInstructions: "To push the black token, move your white token to the right into the black token's position.",
103                        highlightPositions: [{ row: 2, col: 2 }]
104                    },
105                    {
106                        type: 'move',
107                        validDestinations: [{ row: 2, col: 2 }],
108                        errorMessage: "Please push the black token to the right. Try again.",
109                        nextInstructions: "Pushed opponent tokens become inactive for their next turn (marked with red dot)."
110                        // onComplete removed - handled by tutorialService
111                    }
112                ]
113            },
114            
115            // Step 4: Multi-Token Pushing
116            {
117                id: "multi-token-pushing",
118                title: "Multi-Token Pushing",
119                instructions: "You can push multiple tokens at once. Try pushing this line of tokens to the right.",
120                boardSetup: [
121                    { row: 2, col: 0, color: 'white' },
122                    { row: 2, col: 1, color: 'black' },
123                    { row: 2, col: 2, color: 'white' },
124                    { row: 2, col: 3, color: 'black' }
125                    // Empty space at 2,4
126                ],
127                initialHighlights: [{ row: 2, col: 0 }],
128                expectedActions: [
129                    {
130                        type: 'select',
131                        position: { row: 2, col: 0 },
132                        nextInstructions: "Now push the line of tokens by moving to the right into the black token's position.",
133                        highlightPositions: [{ row: 2, col: 1 }]
134                    },
135                    {
136                        type: 'move',
137                        validDestinations: [{ row: 2, col: 1 }],
138                        errorMessage: "Please push the tokens to the right. Try again.",
139                        nextInstructions: "Pushed opponent tokens become inactive after being pushed. Opponent cannot move them the next turn."
140                        // onComplete removed - handled by tutorialService
141                    }
142                ]
143            },
144            
145            // Step 5: Token Capture
146            {
147                id: "token-capture",
148                title: "Token Capture",
149                instructions: "When a token is surrounded on all four sides, it's captured. Move your token to 
149surround the black token, to capture it.",
150                boardSetup: [
151                    { row: 2, col: 1, color: 'white' }, // Left of target
152                    { row: 1, col: 2, color: 'white' }, // Above target
153                    { row: 3, col: 2, color: 'white' }, // Below target
154                    { row: 2, col: 2, color: 'black' }, // Target for capture
155                    { row: 2, col: 4, color: 'white' }  // Player's token to move
156                ],
157                initialHighlights: [{ row: 2, col: 4 }],
158                expectedActions: [
159                    {
160                        type: 'select',
161                        position: { row: 2, col: 4 },
162                        nextInstructions: "Move your token left to capture the black token.",
163                        highlightPositions: [{ row: 2, col: 3 }]
164                    },
165                    {
166                        type: 'move',
167                        validDestinations: [{ row: 2, col: 3 }],
168                        errorMessage: "Please move your token left to complete the capture. Try again.",
169                        nextInstructions: "Captured tokens turn blue and cannot be moved directly, but they can still be pushed."
170                        // No onComplete or validateCapture - handled by tutorialService
171                    }
172                ]
173            },
174            
175            // Step 6: Edge Capture Strategy
176            {
177                id: "edge-capture",
178                title: "Edge Capture Strategy",
179                instructions: "Board edges count as surroundings too! Position your token to complete the capture using fewer pieces.",
180                boardSetup: [
181                    { row: 4, col: 1, color: 'black' },  // Target for edge capture (moved to bottom)
182                    { row: 4, col: 0, color: 'white' },  // Left of target
183                    { row: 3, col: 1, color: 'white' },  // Above target
184                    { row: 4, col: 3, color: 'white' }   // Player's token to move
185                ],
186                initialHighlights: [{ row: 4, col: 3 }],
187                expectedActions: [
188                    {
189                        type: 'select',
190                        position: { row: 4, col: 3 },
191                        nextInstructions: "Move your token left to capture the black token using the board edge.",
192                        highlightPositions: [{ row: 4, col: 2 }]
193                    },
194                    {
195                        type: 'move',
196                        validDestinations: [{ row: 4, col: 2 }],
197                        errorMessage: "Please move your token left to complete the edge capture. Try again.",
198                        nextInstructions: "Using the board edges makes capturing easier - only 3 tokens needed at an edge, and just 2 in a corner!"
199                        // No onComplete or validateCapture - handled by tutorialService
200                    }
201                ]
202            },
203            
204            // Step 7: Victory Conditions - updated for pushing multiple tokens upward
205            {
206                id: "victory-conditions",
207                title: "Victory Conditions",
208                instructions: "To capture token you may also surround it with opponent tokens.",
209                boardSetup: [
210                    // New setup for pushing tokens upward
211                    { row: 4, col: 2, color: 'white' },  // Player's token at bottom
212                    { row: 3, col: 2, color: 'black' },  // Token above player
213                    { row: 2, col: 2, color: 'black' },  // One more above
214                    { row: 1, col: 1, color: 'black' },  // Token to capture
215                    { row: 0, col: 1, color: 'white' },  // Above black
216                    { row: 1, col: 0, color: 'white' },  // Left of black
217                    { row: 2, col: 1, color: 'white' },  // Under of black
218                ],
219                initialHighlights: [{ row: 4, col: 2 }],
220                expectedActions: [
221                    {
222                        type: 'select',
223                        position: { row: 4, col: 2 },
224                        nextInstructions: "Try pushing multiple tokens upward to make the final capture.",
225                        highlightPositions: [{ row: 3, col: 2 }]
226                    },
227                    {
228                        type: 'move',
229                        validDestinations: [{ row: 3, col: 2 }],
230                        errorMessage: "Please push upward. Try again.",
231                        nextInstructions: "Great!"
232                        // No onComplete or validateCapture - handled by tutorialService
233                    }
234                ]
235            }
236        ];
237    }
238    
239    /**
240     * Get a specific step by index
241     */
242    getStep(index) {
243        if (index < 0 || index >= this.steps.length) {
244            return null;
245        }
246        return this.steps[index];
247    }
248    
249    /**
250     * Get the total number of steps
251     */
252    getTotalSteps() {
253        return this.steps.length;
254    }
255    
256    /**
257     * Handle token selection
258     */
259    handleTokenSelected(data) {
260        // Don't allow actions if move has already been performed
261        if (this.movePerformed) return;
262        
263        if (!data || !data.position) return;
264        
265        const step = this.getStep(this.tutorialService.currentStepIndex);
266        if (!step) return;
267        
268        const expectedAction = step.expectedActions[this.expectedActionIndex];
269        
270        // If we're not expecting a selection, ignore this event
271        if (expectedAction.type !== 'select') {
272            return;
273        }
274        
275        // Get the selected token
276        const token = this.board.getTokenAt(data.position.row, data.position.col);
277        if (!token || token.color !== 'white' || token.isCaptured) {
278            // Invalid selection
279            return;
280        }
281        
282        // Check if this is the expected token
283        if (expectedAction.position && 
284            (data.position.row !== expectedAction.position.row || 
285             data.position.col !== expectedAction.position.col)) {
286            // Wrong token, highlight the correct one
287            this.tutorialService.applyHighlights([expectedAction.position]);
288            return;
289        }
290        
291        // Valid selection - update instructions
292        if (expectedAction.nextInstructions) {
293            this.tutorialService.uiManager.showInstructions(
294                step.title, 
295                expectedAction.nextInstructions,
296                this.tutorialService.currentStepIndex + 1,
297                this.getTotalSteps()
298            );
299        }
300        
301        // Apply new highlights if specified
302        if (expectedAction.highlightPositions) {
303            this.tutorialService.applyHighlights(expectedAction.highlightPositions);
304        }
305        
306        // Advance to next expected action
307        this.expectedActionIndex++;
308    }
309    
310    /**
311     * Reset the current step to try again
312     */
313    retryCurrentStep() {
314        // Reset flags
315        this.isRetrying = false;
316        this.movePerformed = false;
317        
318        // Reset to the beginning of the current step
319        this.tutorialService.loadStep(this.tutorialService.currentStepIndex);
320    }
321    
322    /**
323     * Reset the expected action index
324     */
325    resetExpectedAction() {
326        this.expectedActionIndex = 0;
327        this.isRetrying = false;
328        this.movePerformed = false;
329        this.stepCompleted = false;
330    }
331}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.