Refine Dogs and Bunny puzzle

Improve edge label spacing and add varied conditions.
This commit is contained in:
gpt-engineer-app[bot] 2025-08-10 05:53:01 +00:00
parent f33b2bfa4f
commit 5e095857fe

View file

@ -73,6 +73,7 @@ const DogsBunnyPuzzle: React.FC<DogsBunnyPuzzleProps> = ({
// Generate edges with conditions based on difficulty // Generate edges with conditions based on difficulty
const edges: Edge[] = []; const edges: Edge[] = [];
const locationTypes = ['carrot', 'bone', 'flower', 'well', 'bunny', 'dog']; const locationTypes = ['carrot', 'bone', 'flower', 'well', 'bunny', 'dog'];
const conditionPrefixes = ['SOMEBODY AT', 'NOBODY AT'];
// Connect all locations with conditional edges // Connect all locations with conditional edges
for (let i = 0; i < locations.length; i++) { for (let i = 0; i < locations.length; i++) {
@ -82,7 +83,8 @@ const DogsBunnyPuzzle: React.FC<DogsBunnyPuzzleProps> = ({
for (let k = 0; k < numConditions; k++) { for (let k = 0; k < numConditions; k++) {
const conditionType = locationTypes[Math.floor(rng() * locationTypes.length)]; const conditionType = locationTypes[Math.floor(rng() * locationTypes.length)];
conditions.push(`SOMEBODY AT ${conditionType.toUpperCase()}`); const prefix = conditionPrefixes[Math.floor(rng() * conditionPrefixes.length)];
conditions.push(`${prefix} ${conditionType.toUpperCase()}`);
} }
edges.push({ edges.push({
@ -137,16 +139,18 @@ const DogsBunnyPuzzle: React.FC<DogsBunnyPuzzleProps> = ({
const parts = condition.split(' AT '); const parts = condition.split(' AT ');
if (parts.length !== 2) return false; if (parts.length !== 2) return false;
const isNobody = parts[0] === 'NOBODY';
const targetType = parts[1].toLowerCase(); const targetType = parts[1].toLowerCase();
// Check if somebody is at the specified location type const hasCharacterAtType = puzzleState.characters.some(char => {
return puzzleState.characters.some(char => {
const location = puzzleState.locations.find(loc => loc.id === char.locationId); const location = puzzleState.locations.find(loc => loc.id === char.locationId);
return location && ( return location && (
location.type === targetType || location.type === targetType ||
char.type === targetType char.type === targetType
); );
}); });
return isNobody ? !hasCharacterAtType : hasCharacterAtType;
}); });
}; };
@ -290,6 +294,27 @@ const DogsBunnyPuzzle: React.FC<DogsBunnyPuzzleProps> = ({
} }
}; };
// Get condition icon
const getConditionIcon = (condition: string) => {
if (condition.includes('CARROT')) return '🥕';
if (condition.includes('BONE')) return '🦴';
if (condition.includes('FLOWER')) return '🌸';
if (condition.includes('WELL')) return '🪣';
if (condition.includes('BUNNY')) return '🐰';
if (condition.includes('DOG')) return '🐕';
return '❓';
};
// Format condition text for tooltip
const formatCondition = (condition: string) => {
const parts = condition.split(' AT ');
if (parts.length !== 2) return condition;
const prefix = parts[0] === 'NOBODY' ? 'Nobody at' : 'Someone at';
const target = parts[1].toLowerCase();
return `${prefix} ${target}`;
};
if (!puzzleState) return <div>Loading...</div>; if (!puzzleState) return <div>Loading...</div>;
return ( return (
@ -344,17 +369,52 @@ const DogsBunnyPuzzle: React.FC<DogsBunnyPuzzleProps> = ({
strokeWidth={isValid ? "3" : "1"} strokeWidth={isValid ? "3" : "1"}
strokeDasharray={isValid ? "none" : "5,5"} strokeDasharray={isValid ? "none" : "5,5"}
/> />
{/* Condition labels */} {/* Condition icons */}
<text {edge.conditions.slice(0, 2).map((condition, condIndex) => (
x={(fromLoc.x + toLoc.x) / 2 + 20} <g key={condIndex}>
y={(fromLoc.y + toLoc.y) / 2 + 15} <circle
fontSize="10" cx={(fromLoc.x + toLoc.x) / 2 + 20 + (condIndex - 0.5) * 16}
fill="hsl(var(--foreground))" cy={(fromLoc.y + toLoc.y) / 2 + 20}
textAnchor="middle" r="8"
className="pointer-events-none" fill="hsl(var(--background))"
> stroke="hsl(var(--border))"
{edge.conditions.length > 0 && edge.conditions[0].replace('SOMEBODY AT ', '')} strokeWidth="1"
</text> />
<text
x={(fromLoc.x + toLoc.x) / 2 + 20 + (condIndex - 0.5) * 16}
y={(fromLoc.y + toLoc.y) / 2 + 25}
fontSize="10"
textAnchor="middle"
className="pointer-events-none"
>
{condition.includes('NOBODY') ? '❌' : ''}
{getConditionIcon(condition)}
</text>
<title>{formatCondition(condition)}</title>
</g>
))}
{edge.conditions.length > 2 && (
<g>
<circle
cx={(fromLoc.x + toLoc.x) / 2 + 20 + 16}
cy={(fromLoc.y + toLoc.y) / 2 + 20}
r="6"
fill="hsl(var(--muted))"
stroke="hsl(var(--border))"
strokeWidth="1"
/>
<text
x={(fromLoc.x + toLoc.x) / 2 + 20 + 16}
y={(fromLoc.y + toLoc.y) / 2 + 24}
fontSize="8"
textAnchor="middle"
className="pointer-events-none"
>
+{edge.conditions.length - 2}
</text>
<title>{edge.conditions.slice(2).map(formatCondition).join(', ')}</title>
</g>
)}
</g> </g>
); );
})} })}