/** * Egyptian Agent Faces for Claw3D 🏛️👁️ * Custom canvas-drawn Egyptian god heads for each AI agent */ export type EgyptianAgentType = | 'horus' | 'cleopatra' | 'anubis' | 'thoth' | 'ptah' | 'seshat' | 'sekhmet' | 'maat'; interface EgyptianFaceConfig { name: string; skinColor: string; accentColor: string; eyeColor: string; crownColor: string; specialFeature: string; } export const EGYPTIAN_AGENTS: Record = { horus: { name: 'Horus', skinColor: '#DAA520', accentColor: '#1E90FF', eyeColor: '#FFD700', crownColor: '#FFFFFF', specialFeature: 'falcon' }, cleopatra: { name: 'Cleopatra', skinColor: '#CD853F', accentColor: '#9B59B6', eyeColor: '#000000', crownColor: '#FFD700', specialFeature: 'queen' }, anubis: { name: 'Anubis', skinColor: '#1a1a1a', accentColor: '#FFD700', eyeColor: '#FFD700', crownColor: '#1a1a1a', specialFeature: 'jackal' }, thoth: { name: 'Thoth', skinColor: '#FFFFFF', accentColor: '#40E0D0', eyeColor: '#000000', crownColor: '#40E0D0', specialFeature: 'ibis' }, ptah: { name: 'Ptah', skinColor: '#F5DEB3', accentColor: '#FFD700', eyeColor: '#000000', crownColor: '#F5DEB3', specialFeature: 'mummy' }, seshat: { name: 'Seshat', skinColor: '#DEB887', accentColor: '#228B22', eyeColor: '#000000', crownColor: '#228B22', specialFeature: 'scribe' }, sekhmet: { name: 'Sekhmet', skinColor: '#D2691E', accentColor: '#B22222', eyeColor: '#FFD700', crownColor: '#B22222', specialFeature: 'lioness' }, maat: { name: 'Maat', skinColor: '#FFE4C4', accentColor: '#40E0D0', eyeColor: '#000000', crownColor: '#FFFFFF', specialFeature: 'feather' } }; export function drawEgyptianFace( ctx: CanvasRenderingContext2D, agentType: EgyptianAgentType, x: number, y: number, size: number ) { const config = EGYPTIAN_AGENTS[agentType]; ctx.save(); ctx.translate(x, y); switch (agentType) { case 'horus': drawHorusFace(ctx, size, config); break; case 'cleopatra': drawCleopatraFace(ctx, size, config); break; case 'anubis': drawAnubisFace(ctx, size, config); break; case 'thoth': drawThothFace(ctx, size, config); break; case 'ptah': drawPtahFace(ctx, size, config); break; case 'seshat': drawSeshatFace(ctx, size, config); break; case 'sekhmet': drawSekhmetFace(ctx, size, config); break; case 'maat': drawMaatFace(ctx, size, config); break; } ctx.restore(); } function drawHorusFace(ctx: CanvasRenderingContext2D, size: number, config: EgyptianFaceConfig) { const s = size / 64; ctx.fillStyle = config.skinColor; ctx.beginPath(); ctx.ellipse(32 * s, 32 * s, 24 * s, 28 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#FFFFFF'; ctx.beginPath(); ctx.ellipse(32 * s, 28 * s, 14 * s, 8 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#000000'; ctx.beginPath(); ctx.ellipse(34 * s, 28 * s, 5 * s, 5 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.strokeStyle = '#000000'; ctx.lineWidth = 2 * s; ctx.beginPath(); ctx.moveTo(18 * s, 28 * s); ctx.lineTo(8 * s, 24 * s); ctx.moveTo(46 * s, 28 * s); ctx.lineTo(56 * s, 28 * s); ctx.stroke(); ctx.fillStyle = '#FFD700'; ctx.beginPath(); ctx.moveTo(32 * s, 32 * s); ctx.lineTo(38 * s, 38 * s); ctx.lineTo(32 * s, 40 * s); ctx.closePath(); ctx.fill(); ctx.fillStyle = config.crownColor; ctx.beginPath(); ctx.moveTo(12 * s, 8 * s); ctx.lineTo(20 * s, 0 * s); ctx.lineTo(32 * s, 8 * s); ctx.lineTo(44 * s, 0 * s); ctx.lineTo(52 * s, 8 * s); ctx.lineTo(52 * s, 16 * s); ctx.lineTo(12 * s, 16 * s); ctx.closePath(); ctx.fill(); ctx.fillStyle = config.accentColor; ctx.fillRect(14 * s, 8 * s, 36 * s, 4 * s); } function drawCleopatraFace(ctx: CanvasRenderingContext2D, size: number, config: EgyptianFaceConfig) { const s = size / 64; ctx.fillStyle = config.skinColor; ctx.beginPath(); ctx.ellipse(32 * s, 34 * s, 20 * s, 24 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#FFFFFF'; ctx.beginPath(); ctx.ellipse(24 * s, 28 * s, 8 * s, 5 * s, -0.2, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.ellipse(40 * s, 28 * s, 8 * s, 5 * s, 0.2, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = config.eyeColor; ctx.beginPath(); ctx.arc(25 * s, 28 * s, 3 * s, 0, Math.PI * 2); ctx.arc(41 * s, 28 * s, 3 * s, 0, Math.PI * 2); ctx.fill(); ctx.strokeStyle = '#000000'; ctx.lineWidth = 1.5 * s; ctx.beginPath(); ctx.moveTo(16 * s, 26 * s); ctx.lineTo(10 * s, 24 * s); ctx.moveTo(48 * s, 26 * s); ctx.lineTo(54 * s, 24 * s); ctx.stroke(); ctx.fillStyle = '#8B4513'; ctx.beginPath(); ctx.ellipse(32 * s, 44 * s, 6 * s, 3 * s, 0, 0, Math.PI); ctx.fill(); ctx.fillStyle = config.crownColor; ctx.fillRect(14 * s, 4 * s, 36 * s, 12 * s); ctx.fillStyle = '#00FF00'; ctx.beginPath(); ctx.ellipse(32 * s, 2 * s, 4 * s, 6 * s, 0, 0, Math.PI * 2); ctx.fill(); } function drawAnubisFace(ctx: CanvasRenderingContext2D, size: number, config: EgyptianFaceConfig) { const s = size / 64; ctx.fillStyle = config.skinColor; ctx.beginPath(); ctx.ellipse(32 * s, 36 * s, 18 * s, 22 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.moveTo(24 * s, 38 * s); ctx.lineTo(8 * s, 42 * s); ctx.lineTo(24 * s, 46 * s); ctx.closePath(); ctx.fill(); ctx.fillStyle = config.eyeColor; ctx.beginPath(); ctx.arc(26 * s, 30 * s, 5 * s, 0, Math.PI * 2); ctx.arc(38 * s, 30 * s, 5 * s, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = 'rgba(255, 215, 0, 0.3)'; ctx.beginPath(); ctx.arc(26 * s, 30 * s, 8 * s, 0, Math.PI * 2); ctx.arc(38 * s, 30 * s, 8 * s, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = config.skinColor; ctx.beginPath(); ctx.moveTo(18 * s, 20 * s); ctx.lineTo(14 * s, 4 * s); ctx.lineTo(24 * s, 16 * s); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.moveTo(46 * s, 20 * s); ctx.lineTo(50 * s, 4 * s); ctx.lineTo(40 * s, 16 * s); ctx.closePath(); ctx.fill(); ctx.fillStyle = config.accentColor; ctx.fillRect(18 * s, 50 * s, 28 * s, 6 * s); } function drawThothFace(ctx: CanvasRenderingContext2D, size: number, config: EgyptianFaceConfig) { const s = size / 64; ctx.fillStyle = config.skinColor; ctx.beginPath(); ctx.ellipse(32 * s, 32 * s, 18 * s, 20 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#000000'; ctx.beginPath(); ctx.moveTo(32 * s, 34 * s); ctx.quadraticCurveTo(50 * s, 36 * s, 58 * s, 30 * s); ctx.quadraticCurveTo(50 * s, 38 * s, 32 * s, 38 * s); ctx.fill(); ctx.fillStyle = '#FFFFFF'; ctx.beginPath(); ctx.ellipse(24 * s, 26 * s, 6 * s, 4 * s, 0, 0, Math.PI * 2); ctx.ellipse(40 * s, 26 * s, 6 * s, 4 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.strokeStyle = '#000000'; ctx.lineWidth = 1 * s; ctx.beginPath(); ctx.moveTo(18 * s, 26 * s); ctx.lineTo(10 * s, 24 * s); ctx.moveTo(46 * s, 26 * s); ctx.lineTo(54 * s, 24 * s); ctx.stroke(); ctx.fillStyle = config.accentColor; ctx.beginPath(); ctx.arc(32 * s, 8 * s, 8 * s, Math.PI, 0); ctx.fill(); } function drawPtahFace(ctx: CanvasRenderingContext2D, size: number, config: EgyptianFaceConfig) { const s = size / 64; ctx.fillStyle = config.skinColor; ctx.beginPath(); ctx.ellipse(32 * s, 32 * s, 20 * s, 24 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.strokeStyle = '#DEB887'; ctx.lineWidth = 3 * s; for (let i = 0; i < 6; i++) { ctx.beginPath(); ctx.moveTo(12 * s, (20 + i * 8) * s); ctx.lineTo(52 * s, (20 + i * 8) * s); ctx.stroke(); } ctx.fillStyle = '#FFFFFF'; ctx.beginPath(); ctx.ellipse(24 * s, 28 * s, 6 * s, 4 * s, 0, 0, Math.PI * 2); ctx.ellipse(40 * s, 28 * s, 6 * s, 4 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = config.accentColor; ctx.beginPath(); ctx.arc(24 * s, 28 * s, 2 * s, 0, Math.PI * 2); ctx.arc(40 * s, 28 * s, 2 * s, 0, Math.PI * 2); ctx.fill(); } function drawSeshatFace(ctx: CanvasRenderingContext2D, size: number, config: EgyptianFaceConfig) { const s = size / 64; ctx.fillStyle = config.skinColor; ctx.beginPath(); ctx.ellipse(32 * s, 34 * s, 18 * s, 22 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#FFFFFF'; ctx.beginPath(); ctx.ellipse(24 * s, 30 * s, 6 * s, 4 * s, 0, 0, Math.PI * 2); ctx.ellipse(40 * s, 30 * s, 6 * s, 4 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#000000'; ctx.beginPath(); ctx.arc(25 * s, 30 * s, 2 * s, 0, Math.PI * 2); ctx.arc(41 * s, 30 * s, 2 * s, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = config.crownColor; const cx = 32 * s, cy = 8 * s, spikes = 7, outerR = 6 * s, innerR = 3 * s; let rot = Math.PI / 2 * 3; ctx.beginPath(); ctx.moveTo(cx, cy - outerR); for (let i = 0; i < spikes; i++) { ctx.lineTo(cx + Math.cos(rot) * outerR, cy + Math.sin(rot) * outerR); rot += Math.PI / spikes; ctx.lineTo(cx + Math.cos(rot) * innerR, cy + Math.sin(rot) * innerR); rot += Math.PI / spikes; } ctx.lineTo(cx, cy - outerR); ctx.closePath(); ctx.fill(); ctx.fillStyle = '#000000'; ctx.fillRect(48 * s, 36 * s, 8 * s, 20 * s); } function drawSekhmetFace(ctx: CanvasRenderingContext2D, size: number, config: EgyptianFaceConfig) { const s = size / 64; ctx.fillStyle = config.skinColor; ctx.beginPath(); ctx.ellipse(32 * s, 34 * s, 22 * s, 24 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = config.accentColor; for (let i = 0; i < 12; i++) { const angle = (i / 12) * Math.PI * 2; ctx.beginPath(); ctx.arc(32 * s + Math.cos(angle) * 26 * s, 34 * s + Math.sin(angle) * 28 * s, 6 * s, 0, Math.PI * 2); ctx.fill(); } ctx.fillStyle = '#FFFFFF'; ctx.beginPath(); ctx.ellipse(24 * s, 28 * s, 7 * s, 5 * s, 0, 0, Math.PI * 2); ctx.ellipse(40 * s, 28 * s, 7 * s, 5 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = config.eyeColor; ctx.beginPath(); ctx.arc(25 * s, 28 * s, 3 * s, 0, Math.PI * 2); ctx.arc(41 * s, 28 * s, 3 * s, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = config.accentColor; ctx.beginPath(); ctx.moveTo(10 * s, 16 * s); ctx.lineTo(32 * s, 4 * s); ctx.lineTo(54 * s, 16 * s); ctx.lineTo(54 * s, 24 * s); ctx.lineTo(10 * s, 24 * s); ctx.closePath(); ctx.fill(); } function drawMaatFace(ctx: CanvasRenderingContext2D, size: number, config: EgyptianFaceConfig) { const s = size / 64; ctx.fillStyle = config.skinColor; ctx.beginPath(); ctx.ellipse(32 * s, 36 * s, 18 * s, 20 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#FFFFFF'; ctx.beginPath(); ctx.ellipse(24 * s, 32 * s, 5 * s, 3 * s, 0, 0, Math.PI * 2); ctx.ellipse(40 * s, 32 * s, 5 * s, 3 * s, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#000000'; ctx.beginPath(); ctx.arc(24 * s, 32 * s, 2 * s, 0, Math.PI * 2); ctx.arc(40 * s, 32 * s, 2 * s, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = config.crownColor; ctx.beginPath(); ctx.moveTo(32 * s, 0 * s); ctx.quadraticCurveTo(40 * s, 8 * s, 32 * s, 20 * s); ctx.quadraticCurveTo(24 * s, 8 * s, 32 * s, 0 * s); ctx.fill(); ctx.strokeStyle = config.accentColor; ctx.lineWidth = 1 * s; ctx.beginPath(); ctx.moveTo(32 * s, 4 * s); ctx.lineTo(32 * s, 16 * s); ctx.stroke(); }