feat(rithmomachia): enhance Pyramid section with comprehensive details

Add detailed pyramid information to PiecesSection:

**Content Enhancements:**
- Clarified that Pyramids have 4 face values (perfect squares)
- Added face values with perfect square notation: "36 (6²), 25 (5²), 16 (4²), 4 (2²)"
- Added "How face selection works" section with 4 detailed rules
- Added example showing multiple capture scenarios
- Added visual board example demonstrating 3 different capture options from a single position

**Visual Improvements:**
- Cropped board showing White Pyramid at H5 with capture options
- Demonstrates flexibility of face selection (64 for multiple, 49 for equality, 25 for equality)
- All options clearly listed with mathematical relations

**Translations:**
- Added 15+ new translation keys to en.json and de.json
- Full German translations for all new pyramid content

This provides players with a complete understanding of how Pyramids work and why they're special pieces with multiple strategic uses.

🤖 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 17:31:09 -05:00
parent f5558563ea
commit 9fde1ef9e7
3 changed files with 211 additions and 46 deletions

View File

@@ -1,6 +1,7 @@
import { useTranslation } from 'react-i18next'
import { css } from '../../../../../styled-system/css'
import { PieceRenderer } from '../PieceRenderer'
import { RithmomachiaBoard, } from '../RithmomachiaBoard'
import type { PieceType } from '../../types'
export function PiecesSection({ useNativeAbacusNumbers }: { useNativeAbacusNumbers: boolean }) {
@@ -145,16 +146,24 @@ export function PiecesSection({ useNativeAbacusNumbers }: { useNativeAbacusNumbe
})}
>
<h4 className={css({ fontSize: '18px', fontWeight: 'bold', color: '#92400e', mb: '12px' })}>
{t('guide.pieces.pyramidTitle', '⭐ Pyramids are special')}
{t('guide.pieces.pyramidTitle', '⭐ Pyramids: The Multi-Faced Pieces')}
</h4>
<p className={css({ fontSize: '14px', color: '#78350f', lineHeight: '1.6', mb: '16px' })}>
{t(
'guide.pieces.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.'
'guide.pieces.pyramidIntro',
'Unlike other pieces with a single value, Pyramids contain 4 face values representing perfect squares. When capturing an enemy piece, you choose which face to use for the mathematical relation.'
)}
</p>
<div className={css({ display: 'flex', gap: '32px', flexWrap: 'wrap', mt: '16px' })}>
<div
className={css({
display: 'flex',
gap: '32px',
flexWrap: 'wrap',
mt: '16px',
mb: '20px',
})}
>
{/* Black Pyramid */}
<div>
<p
@@ -166,9 +175,9 @@ export function PiecesSection({ useNativeAbacusNumbers }: { useNativeAbacusNumbe
textAlign: 'center',
})}
>
{t('guide.pieces.blackPyramid', 'Black Pyramid')}
{t('guide.pieces.blackPyramid', 'Black Pyramid Faces')}:
</p>
<div className={css({ width: '80px', height: '80px' })}>
<div className={css({ width: '80px', height: '80px', margin: '0 auto' })}>
<PieceRenderer
type="P"
color="B"
@@ -179,14 +188,14 @@ export function PiecesSection({ useNativeAbacusNumbers }: { useNativeAbacusNumbe
</div>
<p
className={css({
fontSize: '12px',
fontSize: '13px',
color: '#78350f',
mt: '8px',
textAlign: 'center',
fontStyle: 'italic',
fontWeight: 'bold',
})}
>
{t('guide.pieces.pyramidValues', 'Values')}: 36, 25, 16, 4
{t('guide.pieces.blackPyramidValues', '36 (6²), 25 (5²), 16 (4²), 4 (2²)')}
</p>
</div>
@@ -201,9 +210,9 @@ export function PiecesSection({ useNativeAbacusNumbers }: { useNativeAbacusNumbe
textAlign: 'center',
})}
>
{t('guide.pieces.whitePyramid', 'White Pyramid')}
{t('guide.pieces.whitePyramid', 'White Pyramid Faces')}:
</p>
<div className={css({ width: '80px', height: '80px' })}>
<div className={css({ width: '80px', height: '80px', margin: '0 auto' })}>
<PieceRenderer
type="P"
color="W"
@@ -214,17 +223,167 @@ export function PiecesSection({ useNativeAbacusNumbers }: { useNativeAbacusNumbe
</div>
<p
className={css({
fontSize: '12px',
fontSize: '13px',
color: '#78350f',
mt: '8px',
textAlign: 'center',
fontStyle: 'italic',
fontWeight: 'bold',
})}
>
{t('guide.pieces.pyramidValues', 'Values')}: 64, 49, 36, 25
{t('guide.pieces.whitePyramidValues', '64 (8²), 49 (7²), 36 (6²), 25 (5²)')}
</p>
</div>
</div>
{/* How face selection works */}
<div
className={css({
bg: 'white',
p: '16px',
borderRadius: '6px',
mb: '16px',
border: '1px solid #fbbf24',
})}
>
<p
className={css({
fontSize: '14px',
fontWeight: 'bold',
color: '#92400e',
mb: '12px',
})}
>
{t('guide.pieces.pyramidHowItWorks', 'How face selection works:')}
</p>
<ul
className={css({ fontSize: '13px', color: '#78350f', lineHeight: '1.8', pl: '20px' })}
>
<li>
{t(
'guide.pieces.pyramidRule1',
"When your Pyramid attempts a capture, you must declare which face value you're using before the relation is checked"
)}
</li>
<li>
{t(
'guide.pieces.pyramidRule2',
'The chosen face value becomes "your piece\'s value" for all mathematical relations (equality, multiple/divisor, sum, difference, product, ratio)'
)}
</li>
<li>
{t(
'guide.pieces.pyramidRule3',
'You can choose different faces for different captures—the Pyramid doesn\'t "lock in" to one value'
)}
</li>
<li>
{t(
'guide.pieces.pyramidRule4',
'This flexibility makes Pyramids excellent for creating unexpected capture opportunities and versatile helpers'
)}
</li>
</ul>
</div>
{/* Example */}
<div
className={css({
bg: 'rgba(146, 64, 14, 0.1)',
p: '12px',
borderRadius: '6px',
mb: '20px',
})}
>
<p className={css({ fontSize: '13px', color: '#78350f', lineHeight: '1.6' })}>
<strong>{t('guide.pieces.example', 'Example:')}</strong>{' '}
{t(
'guide.pieces.pyramidExample',
"White's Pyramid can capture Black's 16 using face 64 (multiple: 64÷16=4), face 36 (multiple: 36÷9=4, with Black's 9), or face 25 with equality if capturing Black's 25."
)}
</p>
</div>
{/* Visual Example */}
<div>
<h5
className={css({
fontSize: '15px',
fontWeight: 'bold',
color: '#92400e',
mb: '12px',
})}
>
{t(
'guide.pieces.pyramidVisualTitle',
"Visual Example: Pyramid's Multiple Capture Options"
)}
</h5>
<p className={css({ fontSize: '13px', color: '#78350f', mb: '12px', lineHeight: '1.6' })}>
{t(
'guide.pieces.pyramidVisualDesc',
"White's Pyramid (faces: 64, 49, 36, 25) is positioned to capture Black pieces. Notice the flexibility:"
)}
</p>
<div className={css({ display: 'flex', justifyContent: 'center', mb: '12px' })}>
<RithmomachiaBoard
pieces={[
// White Pyramid at H5
{ square: 'H5', type: 'P', color: 'W', value: 'P' },
// Black pieces that can be captured
{ square: 'I5', type: 'T', color: 'B', value: 16 },
{ square: 'H6', type: 'S', color: 'B', value: 49 },
{ square: 'G5', type: 'C', color: 'B', value: 25 },
]}
scale={0.4}
cropToSquares={['F4', 'J7']}
showLabels={true}
useNativeAbacusNumbers={useNativeAbacusNumbers}
/>
</div>
<div
className={css({
bg: 'white',
p: '12px',
borderRadius: '6px',
border: '1px solid #fbbf24',
})}
>
<p
className={css({
fontSize: '13px',
fontWeight: 'bold',
color: '#92400e',
mb: '8px',
})}
>
{t('guide.pieces.pyramidCaptureOptions', 'Capture options from H5:')}
</p>
<ul
className={css({ fontSize: '13px', color: '#78350f', lineHeight: '1.8', pl: '20px' })}
>
<li>
{t(
'guide.pieces.pyramidOption1',
'Move to I5: Choose face 64 → captures 16 by multiple (64÷16=4)'
)}
</li>
<li>
{t(
'guide.pieces.pyramidOption2',
'Move to H6: Choose face 49 → captures 49 by equality (49=49)'
)}
</li>
<li>
{t(
'guide.pieces.pyramidOption3',
'Move to G5: Choose face 25 → captures 25 by equality (25=25)'
)}
</li>
</ul>
</div>
</div>
</div>
</div>
)

View File

@@ -46,11 +46,25 @@
"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": "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."
"pyramidTitle": " Pyramiden: Die mehrfach-wertige Figuren",
"pyramidIntro": "Anders als andere Figuren mit einem einzigen Wert enthalten Pyramiden 4 Seitenwerte, die perfekte Quadrate darstellen. Beim Schlagen einer gegnerischen Figur wählen Sie, welche Seite Sie für die mathematische Beziehung verwenden.",
"blackPyramid": "Schwarze Pyramiden-Seiten",
"blackPyramidValues": "36 (6²), 25 (5²), 16 (4²), 4 (2²)",
"whitePyramid": "Weiße Pyramiden-Seiten",
"whitePyramidValues": "64 (8²), 49 (7²), 36 (6²), 25 (5²)",
"pyramidHowItWorks": "Wie die Seitenwahl funktioniert:",
"pyramidRule1": "Wenn Ihre Pyramide versucht zu schlagen, müssen Sie deklarieren, welchen Seitenwert Sie verwenden, bevor die Beziehung geprüft wird",
"pyramidRule2": "Der gewählte Seitenwert wird \"der Wert Ihrer Figur\" für alle mathematischen Beziehungen (Gleichheit, Vielfaches/Teiler, Summe, Differenz, Produkt, Verhältnis)",
"pyramidRule3": "Sie können für verschiedene Schlagzüge unterschiedliche Seiten wählen—die Pyramide \"verriegelt\" sich nicht auf einen Wert",
"pyramidRule4": "Diese Flexibilität macht Pyramiden ausgezeichnet für unerwartete Schlagmöglichkeiten und vielseitige Helfer",
"example": "Beispiel:",
"pyramidExample": "Weiße Pyramide kann schwarze 16 schlagen mit Seite 64 (Vielfaches: 64÷16=4), Seite 36 (Vielfaches: 36÷9=4, mit schwarzer 9), oder Seite 25 mit Gleichheit beim Schlagen von schwarzer 25.",
"pyramidVisualTitle": "Visuelles Beispiel: Mehrfache Schlagoptionen der Pyramide",
"pyramidVisualDesc": "Weiße Pyramide (Seiten: 64, 49, 36, 25) ist positioniert, um schwarze Figuren zu schlagen. Beachten Sie die Flexibilität:",
"pyramidCaptureOptions": "Schlagoptionen von H5:",
"pyramidOption1": "Zug nach I5: Wähle Seite 64 → schlägt 16 durch Vielfaches (64÷16=4)",
"pyramidOption2": "Zug nach H6: Wähle Seite 49 → schlägt 49 durch Gleichheit (49=49)",
"pyramidOption3": "Zug nach G5: Wähle Seite 25 → schlägt 25 durch Gleichheit (25=25)"
},
"capture": {
"title": "Wie man schlägt",

View File

@@ -63,11 +63,25 @@
"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": "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.",
"pyramidTitle": " Pyramids: The Multi-Faced Pieces",
"pyramidIntro": "Unlike other pieces with a single value, Pyramids contain 4 face values representing perfect squares. When capturing an enemy piece, you choose which face to use for the mathematical relation.",
"blackPyramid": "Black Pyramid Faces",
"blackPyramidValues": "36 (6²), 25 (5²), 16 (4²), 4 (2²)",
"whitePyramid": "White Pyramid Faces",
"whitePyramidValues": "64 (8²), 49 (7²), 36 (6²), 25 (5²)",
"pyramidHowItWorks": "How face selection works:",
"pyramidRule1": "When your Pyramid attempts a capture, you must declare which face value you're using before the relation is checked",
"pyramidRule2": "The chosen face value becomes \"your piece's value\" for all mathematical relations (equality, multiple/divisor, sum, difference, product, ratio)",
"pyramidRule3": "You can choose different faces for different captures—the Pyramid doesn't \"lock in\" to one value",
"pyramidRule4": "This flexibility makes Pyramids excellent for creating unexpected capture opportunities and versatile helpers",
"example": "Example:",
"pyramidExample": "White's Pyramid can capture Black's 16 using face 64 (multiple: 64÷16=4), face 36 (multiple: 36÷9=4, with Black's 9), or face 25 with equality if capturing Black's 25.",
"pyramidVisualTitle": "Visual Example: Pyramid's Multiple Capture Options",
"pyramidVisualDesc": "White's Pyramid (faces: 64, 49, 36, 25) is positioned to capture Black pieces. Notice the flexibility:",
"pyramidCaptureOptions": "Capture options from H5:",
"pyramidOption1": "Move to I5: Choose face 64 → captures 16 by multiple (64÷16=4)",
"pyramidOption2": "Move to H6: Choose face 49 → captures 49 by equality (49=49)",
"pyramidOption3": "Move to G5: Choose face 25 → captures 25 by equality (25=25)",
"pieceTypes": {
"circle": {
"name": "Circle",
@@ -89,28 +103,6 @@
"movement": "One step any way (like a king)",
"count": "Count: 1"
}
},
"pyramidSpecial": {
"title": "⭐ Pyramids: The Multi-Faced Pieces",
"intro": "Unlike other pieces with a single value, Pyramids contain <strong>4 face values</strong> representing perfect squares. When capturing an enemy piece, you choose which face to use for the mathematical relation.",
"blackFaces": "Black Pyramid Faces:",
"blackValues": "36 (6²), 25 (5²), 16 (4²), 4 (2²)",
"whiteFaces": "White Pyramid Faces:",
"whiteValues": "64 (8²), 49 (7²), 36 (6²), 25 (5²)",
"howItWorks": "How face selection works:",
"rules": [
"When your Pyramid attempts a capture, you must declare which face value you're using before the relation is checked",
"The chosen face value becomes \"your piece's value\" for all mathematical relations (equality, multiple/divisor, sum, difference, product, ratio)",
"You can choose different faces for different captures—the Pyramid doesn't \"lock in\" to one value",
"This flexibility makes Pyramids excellent for creating unexpected capture opportunities and versatile helpers"
],
"example": "<strong>Example:</strong> White's Pyramid can capture Black's 16 using face 64 (multiple: 64÷16=4), face 36 (multiple: 36÷9=4, with Black's 9), or face 25 with equality if capturing Black's 25.",
"visualTitle": "Visual Example: Pyramid's Multiple Capture Options",
"visualDesc": "White's Pyramid (faces: 64, 49, 36, 25) is positioned to capture Black pieces. Notice the flexibility:",
"captureOptions": "<strong>Capture options from H5:</strong>",
"option1": "Move to I5: Choose face <strong>64</strong> → captures 16 by multiple (64÷16=4)",
"option2": "Move to H6: Choose face <strong>49</strong> → captures 49 by equality (49=49)",
"option3": "Move to G5: Choose face <strong>25</strong> → captures 25 by equality (25=25)"
}
},
"capture": {