feat(rithmomachia): enhance Pieces section with visual examples and pyramid details

- Added example values for each piece type (Circle, Triangle, Square) with visual renderings
- Expanded Pyramid subsection showing both Black and White pyramids with their face values
- Corrected piece counts (25 total per side: 12 circles, 6 triangles, 6 squares, 1 pyramid)
- Simplified movement descriptions for clarity
- Updated English and German translations with new keys

Pyramid values:
- Black: 36, 25, 16, 4
- White: 64, 49, 36, 25

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2025-10-31 16:53:54 -05:00
parent d42bcff0d9
commit 55aff829f4
3 changed files with 179 additions and 63 deletions

View File

@@ -678,30 +678,33 @@ function OverviewSection({ useNativeAbacusNumbers }: { useNativeAbacusNumbers: b
function PiecesSection({ useNativeAbacusNumbers }: { useNativeAbacusNumbers: boolean }) {
const { t } = useTranslation()
const pieces: { type: PieceType; name: string; movement: string; count: number }[] = [
const pieces: {
type: PieceType
name: string
movement: string
count: number
exampleValues: number[]
}[] = [
{
type: 'C',
name: t('guide.pieces.circle', 'Circle'),
movement: t('guide.pieces.circleMove', 'Diagonal (like a bishop)'),
count: 8,
movement: t('guide.pieces.circleMove', 'Moves diagonally'),
count: 12,
exampleValues: [3, 5, 7, 9],
},
{
type: 'T',
name: t('guide.pieces.triangle', 'Triangle'),
movement: t('guide.pieces.triangleMove', 'Straight lines (like a rook)'),
count: 8,
movement: t('guide.pieces.triangleMove', 'Moves in straight lines'),
count: 6,
exampleValues: [12, 16, 20, 30],
},
{
type: 'S',
name: t('guide.pieces.square', 'Square'),
movement: t('guide.pieces.squareMove', 'Any direction (like a queen)'),
count: 7,
},
{
type: 'P',
name: t('guide.pieces.pyramid', 'Pyramid'),
movement: t('guide.pieces.pyramidMove', 'One step any way (like a king)'),
count: 1,
movement: t('guide.pieces.squareMove', 'Moves in any direction'),
count: 6,
exampleValues: [25, 28, 45, 66],
},
]
@@ -715,20 +718,20 @@ function PiecesSection({ useNativeAbacusNumbers }: { useNativeAbacusNumbers: boo
mb: '16px',
})}
>
{t('guide.pieces.title', 'Your Pieces (24 total)')}
{t('guide.pieces.title', 'Your Pieces (25 total)')}
</h3>
<p className={css({ fontSize: '15px', mb: '24px', color: '#374151' })}>
{t('guide.pieces.description', 'Each piece has a number value and moves differently:')}
{t(
'guide.pieces.description',
'Each side has 25 pieces with different movement patterns. The shape tells you how it moves:'
)}
</p>
<div className={css({ display: 'flex', flexDirection: 'column', gap: '20px' })}>
<div className={css({ display: 'flex', flexDirection: 'column', gap: '24px' })}>
{pieces.map((piece) => (
<div
key={piece.type}
className={css({
display: 'flex',
alignItems: 'center',
gap: '16px',
p: '16px',
bg: '#f9fafb',
borderRadius: '8px',
@@ -736,60 +739,165 @@ function PiecesSection({ useNativeAbacusNumbers }: { useNativeAbacusNumbers: boo
})}
>
<div
className={css({
width: { base: '60px', md: '80px' },
height: { base: '60px', md: '80px' },
flexShrink: 0,
})}
className={css({ display: 'flex', alignItems: 'center', gap: '12px', mb: '12px' })}
>
<PieceRenderer
type={piece.type}
color="W"
value={piece.type === 'P' ? 'P' : 64}
size={80}
useNativeAbacusNumbers={useNativeAbacusNumbers}
/>
</div>
<div className={css({ flex: 1 })}>
<h4
<div
className={css({
fontSize: '18px',
fontWeight: 'bold',
color: '#111827',
mb: '4px',
width: '60px',
height: '60px',
flexShrink: 0,
})}
>
{piece.name}
</h4>
<p className={css({ fontSize: '14px', color: '#6b7280', mb: '2px' })}>
{piece.movement}
</p>
<p className={css({ fontSize: '13px', color: '#9ca3af', fontStyle: 'italic' })}>
{t('guide.pieces.count', 'Count')}: {piece.count}
<PieceRenderer
type={piece.type}
color="W"
value={piece.exampleValues[0]}
size={60}
useNativeAbacusNumbers={useNativeAbacusNumbers}
/>
</div>
<div className={css({ flex: 1 })}>
<h4
className={css({
fontSize: '18px',
fontWeight: 'bold',
color: '#111827',
mb: '4px',
})}
>
{piece.name} ({piece.count} per side)
</h4>
<p className={css({ fontSize: '14px', color: '#6b7280' })}>{piece.movement}</p>
</div>
</div>
{/* Example values */}
<div className={css({ mt: '12px' })}>
<p
className={css({
fontSize: '13px',
color: '#9ca3af',
mb: '8px',
fontStyle: 'italic',
})}
>
{t('guide.pieces.exampleValues', 'Example values')}:
</p>
<div className={css({ display: 'flex', gap: '12px', flexWrap: 'wrap' })}>
{piece.exampleValues.map((value) => (
<div
key={value}
className={css({
width: '48px',
height: '48px',
})}
>
<PieceRenderer
type={piece.type}
color="W"
value={value}
size={48}
useNativeAbacusNumbers={useNativeAbacusNumbers}
/>
</div>
))}
</div>
</div>
</div>
))}
</div>
{/* Pyramid section */}
<div
className={css({
mt: '24px',
p: '16px',
mt: '32px',
p: '20px',
bg: 'rgba(251, 191, 36, 0.1)',
borderLeft: '4px solid #f59e0b',
borderRadius: '4px',
})}
>
<p className={css({ fontSize: '14px', fontWeight: 'bold', color: '#92400e', mb: '8px' })}>
<h4 className={css({ fontSize: '18px', fontWeight: 'bold', color: '#92400e', mb: '12px' })}>
{t('guide.pieces.pyramidTitle', '⭐ Pyramids are special')}
</p>
<p className={css({ fontSize: '14px', color: '#78350f', lineHeight: '1.6' })}>
</h4>
<p className={css({ fontSize: '14px', color: '#78350f', lineHeight: '1.6', mb: '16px' })}>
{t(
'guide.pieces.pyramidDescription',
'Pyramids have 4 face values. When capturing, you choose which face to use.'
'Each side has 1 Pyramid. Pyramids have 4 face values - when capturing, you choose which value to use. They move one step in any direction.'
)}
</p>
<div className={css({ display: 'flex', gap: '32px', flexWrap: 'wrap', mt: '16px' })}>
{/* Black Pyramid */}
<div>
<p
className={css({
fontSize: '13px',
fontWeight: 'bold',
color: '#92400e',
mb: '8px',
textAlign: 'center',
})}
>
{t('guide.pieces.blackPyramid', 'Black Pyramid')}
</p>
<div className={css({ width: '80px', height: '80px' })}>
<PieceRenderer
type="P"
color="B"
value="P"
size={80}
useNativeAbacusNumbers={useNativeAbacusNumbers}
/>
</div>
<p
className={css({
fontSize: '12px',
color: '#78350f',
mt: '8px',
textAlign: 'center',
fontStyle: 'italic',
})}
>
{t('guide.pieces.pyramidValues', 'Values')}: 36, 25, 16, 4
</p>
</div>
{/* White Pyramid */}
<div>
<p
className={css({
fontSize: '13px',
fontWeight: 'bold',
color: '#92400e',
mb: '8px',
textAlign: 'center',
})}
>
{t('guide.pieces.whitePyramid', 'White Pyramid')}
</p>
<div className={css({ width: '80px', height: '80px' })}>
<PieceRenderer
type="P"
color="W"
value="P"
size={80}
useNativeAbacusNumbers={useNativeAbacusNumbers}
/>
</div>
<p
className={css({
fontSize: '12px',
color: '#78350f',
mt: '8px',
textAlign: 'center',
fontStyle: 'italic',
})}
>
{t('guide.pieces.pyramidValues', 'Values')}: 64, 49, 36, 25
</p>
</div>
</div>
</div>
</div>
)

View File

@@ -34,19 +34,23 @@
"step5": "Gewinnen Sie durch eine Progression, die eine Runde übersteht!"
},
"pieces": {
"title": "Ihre Spielfiguren (24 insgesamt)",
"description": "Jede Figur hat einen Zahlenwert und bewegt sich anders:",
"title": "Ihre Spielfiguren (25 insgesamt)",
"description": "Jede Seite hat 25 Figuren mit unterschiedlichen Bewegungsmustern. Die Form zeigt, wie sie sich bewegt:",
"count": "Anzahl",
"circle": "Kreis",
"circleMove": "Diagonal (wie ein Läufer)",
"circleMove": "Bewegt sich diagonal",
"triangle": "Dreieck",
"triangleMove": "Geradeaus (wie ein Turm)",
"triangleMove": "Bewegt sich in geraden Linien",
"square": "Quadrat",
"squareMove": "In alle Richtungen (wie eine Dame)",
"squareMove": "Bewegt sich in alle Richtungen",
"pyramid": "Pyramide",
"pyramidMove": "Ein Feld in alle Richtungen (wie ein König)",
"exampleValues": "Beispielwerte",
"blackPyramid": "Schwarze Pyramide",
"whitePyramid": "Weiße Pyramide",
"pyramidValues": "Werte",
"pyramidTitle": "⭐ Pyramiden sind besonders",
"pyramidDescription": "Pyramiden haben 4 Seitenwerte. Beim Schlagen wählen Sie, welche Seite Sie verwenden."
"pyramidDescription": "Jede Seite hat 1 Pyramide. Pyramiden haben 4 Seitenwerte - beim Schlagen wählen Sie, welchen Wert Sie verwenden. Sie bewegen sich einen Schritt in jede Richtung."
},
"capture": {
"title": "Wie man schlägt",

View File

@@ -50,20 +50,24 @@
]
},
"pieces": {
"title": "Your Pieces (24 total)",
"description": "Each piece has a number value and moves differently:",
"title": "Your Pieces (25 total)",
"description": "Each side has 25 pieces with different movement patterns. The shape tells you how it moves:",
"intro": "Each piece has a <strong>number value</strong> and moves differently:",
"count": "Count",
"circle": "Circle",
"circleMove": "Diagonal (like a bishop)",
"circleMove": "Moves diagonally",
"triangle": "Triangle",
"triangleMove": "Straight lines (like a rook)",
"triangleMove": "Moves in straight lines",
"square": "Square",
"squareMove": "Any direction (like a queen)",
"squareMove": "Moves in any direction",
"pyramid": "Pyramid",
"pyramidMove": "One step any way (like a king)",
"exampleValues": "Example values",
"blackPyramid": "Black Pyramid",
"whitePyramid": "White Pyramid",
"pyramidValues": "Values",
"pyramidTitle": "⭐ Pyramids are special",
"pyramidDescription": "Pyramids have 4 face values. When capturing, you choose which face to use.",
"pyramidDescription": "Each side has 1 Pyramid. Pyramids have 4 face values - when capturing, you choose which value to use. They move one step in any direction.",
"pieceTypes": {
"circle": {
"name": "Circle",