diff --git a/src/components/DogsBunnyPuzzle.tsx b/src/components/DogsBunnyPuzzle.tsx index 603b553..a63ec1c 100644 --- a/src/components/DogsBunnyPuzzle.tsx +++ b/src/components/DogsBunnyPuzzle.tsx @@ -76,15 +76,25 @@ const DogsBunnyPuzzle: React.FC = ({ const conditionPrefixes = ['SOMEBODY AT', 'NOBODY AT']; // Connect all locations with conditional edges + let edgeCount = 0; + const totalPossibleEdges = locations.length * (locations.length - 1); + const freeEdgePercentage = 0.33; // About 1/3 of edges will be free + for (let i = 0; i < locations.length; i++) { for (let j = i + 1; j < locations.length; j++) { - const numConditions = diff === 'easy' ? 1 : diff === 'medium' ? 2 : 3; - const conditions: string[] = []; + // Decide if this edge should be free (no conditions) + const shouldBeFree = edgeCount < totalPossibleEdges * freeEdgePercentage && rng() < 0.5; - for (let k = 0; k < numConditions; k++) { - const conditionType = locationTypes[Math.floor(rng() * locationTypes.length)]; - const prefix = conditionPrefixes[Math.floor(rng() * conditionPrefixes.length)]; - conditions.push(`${prefix} ${conditionType.toUpperCase()}`); + let conditions: string[] = []; + + if (!shouldBeFree) { + const numConditions = diff === 'easy' ? 1 : diff === 'medium' ? 2 : 3; + + for (let k = 0; k < numConditions; k++) { + const conditionType = locationTypes[Math.floor(rng() * locationTypes.length)]; + const prefix = conditionPrefixes[Math.floor(rng() * conditionPrefixes.length)]; + conditions.push(`${prefix} ${conditionType.toUpperCase()}`); + } } edges.push({ @@ -98,6 +108,8 @@ const DogsBunnyPuzzle: React.FC = ({ to: locations[i].id, conditions: conditions }); + + edgeCount += 2; } } @@ -339,14 +351,12 @@ const DogsBunnyPuzzle: React.FC = ({ -
- {/* Puzzle Area */} -
-
+ {/* Puzzle Area - Full Width */} +
{/* Edges */} {puzzleState.edges.map((edge, index) => { @@ -369,53 +379,55 @@ const DogsBunnyPuzzle: React.FC = ({ strokeWidth={isValid ? "3" : "1"} strokeDasharray={isValid ? "none" : "5,5"} /> - {/* Condition labels - simplified to show first condition only */} - - {edge.conditions.length === 1 ? ( - // Single condition - - ) : ( - // Multiple conditions - show as rounded rectangle with dots - c.includes('NOBODY')) ? "#ef4444" : "hsl(var(--border))"} - strokeWidth="2" - /> - )} - - {getConditionIcon(edge.conditions[0])} - - {edge.conditions.length > 1 && ( + {/* Condition labels - only show if edge has conditions */} + {edge.conditions.length > 0 && ( + + {edge.conditions.length === 1 ? ( + // Single condition + + ) : ( + // Multiple conditions - show as rounded rectangle + c.includes('NOBODY')) ? "#ef4444" : "hsl(var(--border))"} + strokeWidth="2" + /> + )} - +{edge.conditions.length - 1} + {getConditionIcon(edge.conditions[0])} - )} - {edge.conditions.map(formatCondition).join(' AND ')} - + {edge.conditions.length > 1 && ( + + +{edge.conditions.length - 1} + + )} + {edge.conditions.map(formatCondition).join(' AND ')} + + )} ); })} @@ -429,7 +441,7 @@ const DogsBunnyPuzzle: React.FC = ({ return (
= ({ }} onClick={() => isValidMove && handleMove(location.id)} > - + {getLocationIcon(location.type)} {/* Characters at this location */} {charactersHere.map((char, index) => (
{ e.stopPropagation(); @@ -469,11 +481,11 @@ const DogsBunnyPuzzle: React.FC = ({
); })} -
-
- - {/* Instructions & Controls */} -
+
+ + {/* Instructions & Controls - Below the graph */} +
+

How to Play:

    @@ -498,26 +510,25 @@ const DogsBunnyPuzzle: React.FC = ({
- - -
- - - - -
+
+ +
+ + + +