Skip to content

Commit 67d21ca

Browse files
committed
added reset to initial board option
1 parent f13871d commit 67d21ca

File tree

5 files changed

+84
-37
lines changed

5 files changed

+84
-37
lines changed

frontend/src/components/puzzles/GameControls.tsx

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
import { Button } from "@heroui/button";
2-
import { Play, Pause, ChevronRight, ChevronLeft, Lightbulb, Target, X } from "lucide-react";
2+
import {
3+
Play,
4+
Pause,
5+
ChevronRight,
6+
ChevronLeft,
7+
Lightbulb,
8+
Target,
9+
RotateCcw,
10+
Trash2,
11+
} from "lucide-react";
312
import { Tooltip } from "@heroui/tooltip";
413

514
interface GameControlsProps {
@@ -10,6 +19,7 @@ interface GameControlsProps {
1019
onNext: () => void;
1120
onPrevious: () => void;
1221
onClear: () => void;
22+
onResetToInitial: () => void;
1323
showHints?: boolean;
1424
showGoals?: boolean;
1525
onToggleHints?: () => void;
@@ -25,6 +35,7 @@ export function GameControls({
2535
onNext,
2636
onPrevious,
2737
onClear,
38+
onResetToInitial,
2839
showHints = false,
2940
showGoals = false,
3041
onToggleHints,
@@ -33,34 +44,53 @@ export function GameControls({
3344
}: GameControlsProps) {
3445
return (
3546
<div className="flex flex-col items-center gap-4">
36-
<div className="flex gap-6 items-center">
37-
<button
38-
onClick={onPrevious}
39-
disabled={!canUndo}
40-
className="w-10 h-10 sm:w-12 sm:h-12 rounded-full bg-gray-200 hover:bg-gray-300 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center transition-colors"
41-
>
42-
<ChevronLeft className="w-5 h-5 sm:w-6 sm:h-6 text-gray-600" />
43-
</button>
44-
<button
45-
onClick={isPlaying ? onPause : onPlay}
46-
className="flex items-center gap-1.5 sm:gap-2 p-3 sm:p-5 rounded-full bg-linera-primary hover:bg-linera-primary-dark text-white transition-colors shadow-lg"
47-
>
48-
{isPlaying ? (
49-
<>
50-
<Pause className="w-4 h-4 sm:w-5 sm:h-5 fill-white" />
51-
</>
52-
) : (
53-
<>
54-
<Play className="w-4 h-4 sm:w-5 sm:h-5 ml-0.5 fill-white" />
55-
</>
56-
)}
57-
</button>
58-
<button
59-
onClick={onNext}
60-
className="w-10 h-10 sm:w-12 sm:h-12 rounded-full bg-gray-200 hover:bg-gray-300 flex items-center justify-center transition-colors"
61-
>
62-
<ChevronRight className="w-5 h-5 sm:w-6 sm:h-6 text-gray-600" />
63-
</button>
47+
<div className="flex gap-3 items-center">
48+
<Tooltip content="Previous generation">
49+
<button
50+
onClick={onPrevious}
51+
disabled={!canUndo}
52+
className="w-10 h-10 rounded-full bg-gray-200 hover:bg-gray-300 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center transition-colors"
53+
>
54+
<ChevronLeft className="w-5 h-5 text-gray-600" />
55+
</button>
56+
</Tooltip>
57+
<Tooltip content={isPlaying ? "Pause" : "Play"}>
58+
<button
59+
onClick={isPlaying ? onPause : onPlay}
60+
className="p-3 rounded-full bg-linera-primary hover:bg-linera-primary-dark text-white transition-colors shadow-lg"
61+
>
62+
{isPlaying ? (
63+
<Pause className="w-5 h-5 fill-white" />
64+
) : (
65+
<Play className="w-5 h-5 ml-0.5 fill-white" />
66+
)}
67+
</button>
68+
</Tooltip>
69+
<Tooltip content="Next generation">
70+
<button
71+
onClick={onNext}
72+
className="w-10 h-10 rounded-full bg-gray-200 hover:bg-gray-300 flex items-center justify-center transition-colors"
73+
>
74+
<ChevronRight className="w-5 h-5 text-gray-600" />
75+
</button>
76+
</Tooltip>
77+
<div className="w-px h-8 bg-gray-300 mx-2" /> {/* Divider */}
78+
<Tooltip content="Reset to generation 0">
79+
<button
80+
onClick={onResetToInitial}
81+
className="w-10 h-10 rounded-full bg-gray-200 hover:bg-gray-300 flex items-center justify-center transition-colors"
82+
>
83+
<RotateCcw className="w-5 h-5 text-gray-600" />
84+
</button>
85+
</Tooltip>
86+
<Tooltip content="Clear all cells">
87+
<button
88+
onClick={onClear}
89+
className="w-10 h-10 rounded-full bg-gray-200 hover:bg-gray-300 flex items-center justify-center transition-colors"
90+
>
91+
<Trash2 className="w-5 h-5 text-gray-600" />
92+
</button>
93+
</Tooltip>
6494
</div>
6595
<div className="flex gap-3 items-center flex-wrap justify-center">
6696
{hasConditions && (
@@ -91,14 +121,6 @@ export function GameControls({
91121
</Button>
92122
</>
93123
)}
94-
<Button
95-
variant="flat"
96-
onPress={onClear}
97-
className="bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium text-xs sm:text-base px-4 py-2 sm:px-6 sm:py-2.5 min-w-[120px] sm:min-w-[140px] rounded-full flex items-center gap-2"
98-
>
99-
<X className="w-4 h-4 sm:w-5 sm:h-5" />
100-
Reset Generations
101-
</Button>
102124
</div>
103125
</div>
104126
);

frontend/src/components/puzzles/GamePlayingView.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ interface GamePlayingViewProps {
3131
onNext: () => void;
3232
onPrevious: () => void;
3333
onClear: () => void;
34+
onResetToInitial: () => void;
3435
onSubmit: () => void;
3536
onNextPuzzle?: () => void;
3637
onPreviousPuzzle?: () => void;
@@ -55,6 +56,7 @@ export function GamePlayingView({
5556
onNext,
5657
onPrevious,
5758
onClear,
59+
onResetToInitial,
5860
onSubmit,
5961
onNextPuzzle,
6062
onPreviousPuzzle,
@@ -217,6 +219,7 @@ export function GamePlayingView({
217219
onNext={onNext}
218220
onPrevious={onPrevious}
219221
onClear={onClear}
222+
onResetToInitial={onResetToInitial}
220223
showHints={showInitialConditions}
221224
showGoals={showFinalConditions}
222225
onToggleHints={() => setShowInitialConditions(!showInitialConditions)}

frontend/src/components/puzzles/PuzzleGame.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export function PuzzleGame() {
5151
onNext={game.next}
5252
onPrevious={game.previous}
5353
onClear={game.clear}
54+
onResetToInitial={game.resetToInitial}
5455
onSubmit={game.submitSolution}
5556
onNextPuzzle={game.loadNextPuzzle}
5657
onPreviousPuzzle={game.loadPreviousPuzzle}

frontend/src/lib/game-of-life/hooks/useGameOfLife.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,18 @@ export function useGameOfLife(options: UseGameOfLifeOptions) {
103103
updateCells();
104104
}, [board, updateCells]);
105105

106+
const resetToInitial = useCallback(() => {
107+
// Go back to generation 0 without clearing
108+
if (board.hasInitialState()) {
109+
// Reset to the first state in history
110+
while (board.canUndo()) {
111+
board.undo();
112+
}
113+
setGeneration(0);
114+
updateCells();
115+
}
116+
}, [board, updateCells]);
117+
106118
const play = useCallback(() => {
107119
setIsPlaying(true);
108120
}, []);
@@ -179,6 +191,7 @@ export function useGameOfLife(options: UseGameOfLifeOptions) {
179191
next,
180192
previous,
181193
clear,
194+
resetToInitial,
182195
play,
183196
pause,
184197
setSpeed,

frontend/src/lib/game-of-life/hooks/usePuzzleGame.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,13 @@ export function usePuzzleGame() {
202202
setValidationResult(null);
203203
}, [originalClear]);
204204

205+
const originalResetToInitial = game.resetToInitial;
206+
const resetToInitial = useCallback(() => {
207+
originalResetToInitial();
208+
setStepCount(0);
209+
setValidationResult(null);
210+
}, [originalResetToInitial]);
211+
205212
const backToPuzzleList = useCallback(() => {
206213
setShowPuzzleList(true);
207214
setCurrentPuzzleId(null);
@@ -250,6 +257,7 @@ export function usePuzzleGame() {
250257
next,
251258
previous,
252259
clear,
260+
resetToInitial,
253261
currentPuzzle: currentPuzzle || null,
254262
currentPuzzleId,
255263
isPuzzleLoading,

0 commit comments

Comments
 (0)