advanced-games-library
Version:
Advanced Gaming Library for React Native - Four Complete Games with iOS Compatibility Fixes
794 lines (674 loc) • 24.7 kB
text/typescript
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)
};
}