UNPKG

advanced-games-library

Version:

Advanced Gaming Library for React Native - Four Complete Games with iOS Compatibility Fixes

794 lines (674 loc) 24.7 kB
import * as React from 'react'; /** * Advanced AI System for Games * Machine learning-powered opponents, adaptive difficulty, and intelligent game assistance */ export interface AIPlayerConfig { id: string; name: string; difficulty: 'easy' | 'medium' | 'hard' | 'expert' | 'adaptive'; personality: AIPersonality; learningEnabled: boolean; adaptationRate: number; // 0-1, how quickly AI adapts to player specializations: string[]; // Types of games this AI excels at } export interface AIPersonality { aggression: number; // 0-1, how aggressive the AI plays risk_tolerance: number; // 0-1, willingness to take risks pattern_recognition: number; // 0-1, ability to recognize player patterns creativity: number; // 0-1, tendency to try unconventional moves consistency: number; // 0-1, how consistent the AI's performance is adaptation_speed: number; // 0-1, how quickly AI adapts strategies } export interface GamePattern { type: 'move_sequence' | 'timing_pattern' | 'strategy_preference' | 'weakness'; pattern: any[]; confidence: number; frequency: number; effectiveness: number; lastSeen: Date; } export interface AIDecision { action: any; confidence: number; reasoning: string[]; alternatives: Array<{ action: any; score: number; reasoning: string }>; executionTime: number; patternsBased: string[]; } export interface PlayerProfile { playerId: string; skillLevel: number; // 0-100 preferredStrategies: string[]; identifiedWeaknesses: string[]; gamePatterns: Map<string, GamePattern>; playStyle: { speed: number; // Average move time accuracy: number; // Success rate consistency: number; // Performance variance adaptability: number; // How quickly player adapts to AI }; emotionalState: { frustration: number; // 0-1 engagement: number; // 0-1 confidence: number; // 0-1 }; } /** * Advanced AI Engine with machine learning capabilities */ export class AdvancedAIEngine { private static instance: AdvancedAIEngine; private aiPlayers = new Map<string, AIPlayerConfig>(); private playerProfiles = new Map<string, PlayerProfile>(); private gameHistory = new Map<string, GameHistoryEntry[]>(); private neuralNetwork?: SimpleNeuralNetwork; private patternRecognizer: PatternRecognizer; private difficultyAdapter: DifficultyAdapter; private isLearningEnabled = true; private constructor() { this.neuralNetwork = new SimpleNeuralNetwork(); this.patternRecognizer = new PatternRecognizer(); this.difficultyAdapter = new DifficultyAdapter(); this.initializeDefaultAI(); } static getInstance(): AdvancedAIEngine { if (!AdvancedAIEngine.instance) { AdvancedAIEngine.instance = new AdvancedAIEngine(); } return AdvancedAIEngine.instance; } /** * Create AI player with specified configuration */ createAIPlayer(config: Partial<AIPlayerConfig>): string { const aiId = `ai_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; const fullConfig: AIPlayerConfig = { id: aiId, name: config.name || `AI Player ${aiId.slice(-4)}`, difficulty: config.difficulty || 'medium', personality: config.personality || this.getDefaultPersonality(), learningEnabled: config.learningEnabled ?? true, adaptationRate: config.adaptationRate ?? 0.3, specializations: config.specializations || [] }; this.aiPlayers.set(aiId, fullConfig); return aiId; } /** * Get AI decision for game move */ async getAIDecision( aiId: string, gameState: any, availableActions: any[], opponentId?: string ): Promise<AIDecision> { const aiPlayer = this.aiPlayers.get(aiId); if (!aiPlayer) { throw new Error(`AI player ${aiId} not found`); } const startTime = performance.now(); // Get opponent profile for adaptive behavior const opponentProfile = opponentId ? this.playerProfiles.get(opponentId) : null; // Analyze current game state const stateAnalysis = this.analyzeGameState(gameState, aiPlayer, opponentProfile); // Generate possible moves with scores const actionScores = await this.evaluateActions( availableActions, gameState, aiPlayer, opponentProfile ); // Apply personality and difficulty modifiers const modifiedScores = this.applyPersonalityModifiers(actionScores, aiPlayer); // Select best action based on difficulty and personality const selectedAction = this.selectAction(modifiedScores, aiPlayer); const executionTime = performance.now() - startTime; // Create decision object const decision: AIDecision = { action: selectedAction.action, confidence: selectedAction.score, reasoning: selectedAction.reasoning.split(', '), alternatives: modifiedScores.slice(0, 3).map(score => ({ action: score.action, score: score.score, reasoning: score.reasoning })), executionTime, patternsBased: stateAnalysis.patternsUsed }; // Learn from this decision if learning is enabled if (aiPlayer.learningEnabled && this.isLearningEnabled) { this.recordDecision(aiId, gameState, decision, opponentId); } return decision; } /** * Update player profile based on game actions */ updatePlayerProfile(playerId: string, gameData: { action: any; gameState: any; result: 'success' | 'failure' | 'neutral'; timeSpent: number; }): void { let profile = this.playerProfiles.get(playerId); if (!profile) { profile = this.createPlayerProfile(playerId); this.playerProfiles.set(playerId, profile); } // Update play style metrics this.updatePlayStyle(profile, gameData); // Detect and update patterns this.patternRecognizer.updatePatterns(profile, gameData); // Update emotional state based on performance this.updateEmotionalState(profile, gameData.result, gameData.timeSpent); // Adapt AI difficulty if needed this.difficultyAdapter.updateDifficulty(profile, gameData); } /** * Get adaptive difficulty recommendation */ getAdaptiveDifficulty(playerId: string, gameType: string): { difficulty: string; reasoning: string; adjustments: Record<string, number>; } { const profile = this.playerProfiles.get(playerId); if (!profile) { return { difficulty: 'medium', reasoning: 'No player data available, using default difficulty', adjustments: {} }; } return this.difficultyAdapter.calculateDifficulty(profile, gameType); } /** * Analyze game state for patterns and opportunities */ private analyzeGameState(gameState: any, aiPlayer: AIPlayerConfig, opponentProfile?: PlayerProfile | null): { opportunities: string[]; threats: string[]; patterns: GamePattern[]; patternsUsed: string[]; } { const analysis = { opportunities: [] as string[], threats: [] as string[], patterns: [] as GamePattern[], patternsUsed: [] as string[] }; // Look for opponent patterns if available if (opponentProfile) { opponentProfile.gamePatterns.forEach((pattern, patternId) => { if (pattern.confidence > 0.7) { analysis.patterns.push(pattern); analysis.patternsUsed.push(patternId); // Convert patterns to opportunities or threats if (pattern.type === 'weakness') { analysis.opportunities.push(`Exploit opponent weakness: ${pattern.type}`); } else if (pattern.type === 'strategy_preference') { analysis.threats.push(`Counter opponent strategy: ${pattern.type}`); } } }); } return analysis; } /** * Evaluate available actions and assign scores */ private async evaluateActions( actions: any[], gameState: any, aiPlayer: AIPlayerConfig, opponentProfile?: PlayerProfile | null ): Promise<Array<{ action: any; score: number; reasoning: string }>> { const evaluatedActions: Array<{ action: any; score: number; reasoning: string }> = []; for (const action of actions) { let score = 0; const reasoning: string[] = []; // Base score from neural network if available if (this.neuralNetwork) { const networkScore = await this.neuralNetwork.evaluate(gameState, action); score += networkScore * 0.4; reasoning.push(`Neural network score: ${networkScore.toFixed(2)}`); } // Strategic value based on game state const strategicScore = this.calculateStrategicValue(action, gameState); score += strategicScore * 0.3; reasoning.push(`Strategic value: ${strategicScore.toFixed(2)}`); // Counter-opponent patterns if available if (opponentProfile) { const counterScore = this.calculateCounterValue(action, opponentProfile); score += counterScore * 0.2; reasoning.push(`Counter-pattern value: ${counterScore.toFixed(2)}`); } // Random factor for unpredictability const randomFactor = (Math.random() - 0.5) * 0.1; score += randomFactor; reasoning.push(`Randomization: ${randomFactor.toFixed(3)}`); evaluatedActions.push({ action, score: Math.max(0, Math.min(1, score)), reasoning: reasoning.join(', ') }); } return evaluatedActions.sort((a, b) => b.score - a.score); } /** * Apply AI personality modifiers to action scores */ private applyPersonalityModifiers( actionScores: Array<{ action: any; score: number; reasoning: string }>, aiPlayer: AIPlayerConfig ): Array<{ action: any; score: number; reasoning: string }> { const { personality } = aiPlayer; return actionScores.map(actionScore => { let modifiedScore = actionScore.score; const modificationReasons: string[] = []; // Apply aggression modifier if (this.isAggressiveAction(actionScore.action)) { const aggressionBonus = (personality.aggression - 0.5) * 0.2; modifiedScore += aggressionBonus; modificationReasons.push(`Aggression: ${aggressionBonus.toFixed(2)}`); } // Apply risk tolerance if (this.isRiskyAction(actionScore.action)) { const riskBonus = (personality.risk_tolerance - 0.5) * 0.15; modifiedScore += riskBonus; modificationReasons.push(`Risk tolerance: ${riskBonus.toFixed(2)}`); } // Apply creativity factor if (this.isCreativeAction(actionScore.action)) { const creativityBonus = personality.creativity * 0.1; modifiedScore += creativityBonus; modificationReasons.push(`Creativity: ${creativityBonus.toFixed(2)}`); } // Add consistency variation const consistencyVariation = (1 - personality.consistency) * (Math.random() - 0.5) * 0.2; modifiedScore += consistencyVariation; modificationReasons.push(`Consistency variation: ${consistencyVariation.toFixed(3)}`); return { ...actionScore, score: Math.max(0, Math.min(1, modifiedScore)), reasoning: actionScore.reasoning + (modificationReasons.length > 0 ? ` | Personality: ${modificationReasons.join(', ')}` : '') }; }); } /** * Select action based on difficulty and personality */ private selectAction( actionScores: Array<{ action: any; score: number; reasoning: string }>, aiPlayer: AIPlayerConfig ): { action: any; score: number; reasoning: string } { if (actionScores.length === 0) { throw new Error('No actions available for AI to choose from'); } // Difficulty-based selection strategy switch (aiPlayer.difficulty) { case 'easy': // 60% chance of suboptimal move return Math.random() < 0.6 ? actionScores[Math.floor(Math.random() * Math.min(3, actionScores.length))] : actionScores[0]; case 'medium': // 30% chance of suboptimal move return Math.random() < 0.3 ? actionScores[Math.floor(Math.random() * Math.min(2, actionScores.length))] : actionScores[0]; case 'hard': // 10% chance of suboptimal move return Math.random() < 0.1 ? actionScores[1] || actionScores[0] : actionScores[0]; case 'expert': // Always choose optimal move return actionScores[0]; case 'adaptive': // Dynamic selection based on opponent performance const selectionIndex = this.calculateAdaptiveSelection(actionScores, aiPlayer); return actionScores[selectionIndex] || actionScores[0]; default: return actionScores[0]; } } // Helper methods for AI decision making private calculateStrategicValue(action: any, gameState: any): number { // Simplified strategic evaluation - would be game-specific return Math.random() * 0.8 + 0.1; } private calculateCounterValue(action: any, opponentProfile: PlayerProfile): number { let counterValue = 0; opponentProfile.gamePatterns.forEach(pattern => { if (pattern.confidence > 0.6) { counterValue += pattern.confidence * 0.3; } }); return Math.min(1, counterValue); } private isAggressiveAction(action: any): boolean { return Math.random() < 0.3; // Placeholder } private isRiskyAction(action: any): boolean { return Math.random() < 0.2; // Placeholder } private isCreativeAction(action: any): boolean { return Math.random() < 0.15; // Placeholder } private calculateAdaptiveSelection( actionScores: Array<{ action: any; score: number; reasoning: string }>, aiPlayer: AIPlayerConfig ): number { const randomFactor = Math.random(); if (randomFactor < 0.7) return 0; if (randomFactor < 0.9) return 1; return 2; } // Player profile management private createPlayerProfile(playerId: string): PlayerProfile { return { playerId, skillLevel: 50, preferredStrategies: [], identifiedWeaknesses: [], gamePatterns: new Map(), playStyle: { speed: 0.5, accuracy: 0.5, consistency: 0.5, adaptability: 0.5 }, emotionalState: { frustration: 0, engagement: 0.7, confidence: 0.5 } }; } private updatePlayStyle(profile: PlayerProfile, gameData: any): void { const { timeSpent, result } = gameData; // Update speed const speedSample = Math.max(0, Math.min(1, 1 - (timeSpent / 10000))); profile.playStyle.speed = (profile.playStyle.speed * 0.9) + (speedSample * 0.1); // Update accuracy const accuracySample = result === 'success' ? 1 : (result === 'neutral' ? 0.5 : 0); profile.playStyle.accuracy = (profile.playStyle.accuracy * 0.9) + (accuracySample * 0.1); } private updateEmotionalState(profile: PlayerProfile, result: string, timeSpent: number): void { const { emotionalState } = profile; if (result === 'failure') { emotionalState.frustration = Math.min(1, emotionalState.frustration + 0.1); emotionalState.confidence = Math.max(0, emotionalState.confidence - 0.05); } else if (result === 'success') { emotionalState.frustration = Math.max(0, emotionalState.frustration - 0.05); emotionalState.confidence = Math.min(1, emotionalState.confidence + 0.1); } const engagementSample = timeSpent > 1000 ? 1 : 0.5; emotionalState.engagement = (emotionalState.engagement * 0.95) + (engagementSample * 0.05); } private recordDecision(aiId: string, gameState: any, decision: AIDecision, opponentId?: string): void { const historyEntry: GameHistoryEntry = { timestamp: new Date(), aiId, gameState, decision, opponentId, outcome: null }; if (!this.gameHistory.has(aiId)) { this.gameHistory.set(aiId, []); } this.gameHistory.get(aiId)!.push(historyEntry); // Keep only recent history const history = this.gameHistory.get(aiId)!; if (history.length > 1000) { history.splice(0, history.length - 1000); } } // Default configurations private getDefaultPersonality(): AIPersonality { return { aggression: 0.5, risk_tolerance: 0.5, pattern_recognition: 0.7, creativity: 0.3, consistency: 0.8, adaptation_speed: 0.4 }; } private initializeDefaultAI(): void { // Create default AI personalities this.createAIPlayer({ name: 'Rookie AI', difficulty: 'easy', personality: { aggression: 0.3, risk_tolerance: 0.2, pattern_recognition: 0.4, creativity: 0.6, consistency: 0.5, adaptation_speed: 0.3 } }); this.createAIPlayer({ name: 'Strategic AI', difficulty: 'hard', personality: { aggression: 0.4, risk_tolerance: 0.3, pattern_recognition: 0.9, creativity: 0.2, consistency: 0.9, adaptation_speed: 0.7 } }); this.createAIPlayer({ name: 'Adaptive AI', difficulty: 'adaptive', personality: { aggression: 0.5, risk_tolerance: 0.5, pattern_recognition: 0.8, creativity: 0.4, consistency: 0.6, adaptation_speed: 0.9 } }); } // Public API methods updateDecisionOutcome(aiId: string, decision: AIDecision, outcome: 'win' | 'loss' | 'draw'): void { const history = this.gameHistory.get(aiId); if (!history) return; const recentDecisions = history.slice(-10); const decisionEntry = recentDecisions.find(entry => entry.decision.action === decision.action && Math.abs(entry.timestamp.getTime() - Date.now()) < 60000 ); if (decisionEntry) { decisionEntry.outcome = outcome; if (this.neuralNetwork && this.isLearningEnabled) { this.neuralNetwork.trainFromDecision(decisionEntry); } } } getAIPlayer(aiId: string): AIPlayerConfig | undefined { return this.aiPlayers.get(aiId); } getAvailableAIPlayers(): AIPlayerConfig[] { return Array.from(this.aiPlayers.values()); } getPlayerProfile(playerId: string): PlayerProfile | undefined { return this.playerProfiles.get(playerId); } setLearningEnabled(enabled: boolean): void { this.isLearningEnabled = enabled; } exportLearningData(): any { return { aiPlayers: Array.from(this.aiPlayers.entries()), playerProfiles: Array.from(this.playerProfiles.entries()), gameHistory: Array.from(this.gameHistory.entries()), timestamp: new Date().toISOString() }; } } // Supporting classes class SimpleNeuralNetwork { private weights: number[][]; private biases: number[]; private learningRate = 0.01; constructor() { this.weights = this.initializeWeights(); this.biases = this.initializeBiases(); } async evaluate(gameState: any, action: any): Promise<number> { const input = this.stateToVector(gameState, action); return this.forward(input); } trainFromDecision(decisionEntry: GameHistoryEntry): void { if (!decisionEntry.outcome) return; const input = this.stateToVector(decisionEntry.gameState, decisionEntry.decision.action); const target = decisionEntry.outcome === 'win' ? 1 : (decisionEntry.outcome === 'draw' ? 0.5 : 0); this.backpropagate(input, target); } private stateToVector(gameState: any, action: any): number[] { return [Math.random(), Math.random(), Math.random(), Math.random()]; } private forward(input: number[]): number { let sum = 0; for (let i = 0; i < input.length && i < this.weights[0].length; i++) { sum += input[i] * this.weights[0][i]; } sum += this.biases[0]; return 1 / (1 + Math.exp(-sum)); } private backpropagate(input: number[], target: number): void { const output = this.forward(input); const error = target - output; const deltaOutput = error * output * (1 - output); for (let i = 0; i < input.length && i < this.weights[0].length; i++) { this.weights[0][i] += this.learningRate * deltaOutput * input[i]; } this.biases[0] += this.learningRate * deltaOutput; } private initializeWeights(): number[][] { const weights = []; weights[0] = []; for (let i = 0; i < 4; i++) { weights[0][i] = (Math.random() - 0.5) * 0.1; } return weights; } private initializeBiases(): number[] { return [(Math.random() - 0.5) * 0.1]; } } class PatternRecognizer { updatePatterns(profile: PlayerProfile, gameData: any): void { this.updateTimingPatterns(profile, gameData); } private updateTimingPatterns(profile: PlayerProfile, gameData: any): void { const timingPatternId = 'timing_consistency'; const existingPattern = profile.gamePatterns.get(timingPatternId); if (existingPattern) { existingPattern.frequency++; existingPattern.confidence = Math.min(1, existingPattern.confidence + 0.1); existingPattern.lastSeen = new Date(); } else { profile.gamePatterns.set(timingPatternId, { type: 'timing_pattern', pattern: [gameData.timeSpent], confidence: 0.3, frequency: 1, effectiveness: 0.5, lastSeen: new Date() }); } } } class DifficultyAdapter { updateDifficulty(profile: PlayerProfile, gameData: any): void { const { result } = gameData; if (result === 'success') { profile.skillLevel = Math.min(100, profile.skillLevel + 1); } else if (result === 'failure') { profile.skillLevel = Math.max(0, profile.skillLevel - 0.5); } } calculateDifficulty(profile: PlayerProfile, gameType: string): { difficulty: string; reasoning: string; adjustments: Record<string, number>; } { const { skillLevel, emotionalState } = profile; let difficultyScore = skillLevel; if (emotionalState.frustration > 0.7) difficultyScore -= 10; if (emotionalState.confidence < 0.3) difficultyScore -= 5; if (emotionalState.engagement < 0.5) difficultyScore += 5; let targetDifficulty = 'medium'; if (difficultyScore < 25) targetDifficulty = 'easy'; else if (difficultyScore < 50) targetDifficulty = 'medium'; else if (difficultyScore < 75) targetDifficulty = 'hard'; else targetDifficulty = 'expert'; return { difficulty: targetDifficulty, reasoning: `Skill: ${skillLevel}, Frustration: ${emotionalState.frustration.toFixed(2)}, Confidence: ${emotionalState.confidence.toFixed(2)}`, adjustments: { aiSpeed: difficultyScore / 100, aiAccuracy: difficultyScore / 100, hintFrequency: Math.max(0, 1 - difficultyScore / 100) } }; } } interface GameHistoryEntry { timestamp: Date; aiId: string; gameState: any; decision: AIDecision; opponentId?: string; outcome: 'win' | 'loss' | 'draw' | null; } // Export singleton instance export const advancedAIEngine = AdvancedAIEngine.getInstance(); /** * React Hook for AI integration */ export function useAI(gameType: string) { const [availableAI, setAvailableAI] = React.useState<AIPlayerConfig[]>([]); const [adaptiveDifficulty, setAdaptiveDifficulty] = React.useState<string>('medium'); React.useEffect(() => { setAvailableAI(advancedAIEngine.getAvailableAIPlayers()); }, []); const getAIDecision = React.useCallback(async ( aiId: string, gameState: any, availableActions: any[], opponentId?: string ) => { return await advancedAIEngine.getAIDecision(aiId, gameState, availableActions, opponentId); }, []); const updatePlayerProfile = React.useCallback((playerId: string, gameData: any) => { advancedAIEngine.updatePlayerProfile(playerId, gameData); const difficulty = advancedAIEngine.getAdaptiveDifficulty(playerId, gameType); setAdaptiveDifficulty(difficulty.difficulty); }, [gameType]); const createAI = React.useCallback((config: Partial<AIPlayerConfig>) => { const aiId = advancedAIEngine.createAIPlayer(config); setAvailableAI(advancedAIEngine.getAvailableAIPlayers()); return aiId; }, []); return { availableAI, adaptiveDifficulty, getAIDecision, updatePlayerProfile, createAI, updateDecisionOutcome: advancedAIEngine.updateDecisionOutcome.bind(advancedAIEngine), getPlayerProfile: advancedAIEngine.getPlayerProfile.bind(advancedAIEngine) }; }