Download alien_system.py from testrro/REAVT2: direct link, hf CLI and curl.
- Browser
- Download file 17.2 kB
-
https://huggingface.co/spaces/testrro/REAVT2/resolve/main/alien_system.py
- Command line
-
hf download hf://spaces/testrro/REAVT2/alien_system.py
-
curl -L -o alien_system.py https://huggingface.co/spaces/testrro/REAVT2/resolve/main/alien_system.py
17.2 kB
| import json | |
| import os | |
| import random | |
| import time # ← এই লাইনটি যোগ করতে হবে | |
| from dataclasses import dataclass, asdict | |
| from typing import List, Dict, Optional, Tuple | |
| from enum import Enum | |
| import math | |
| from datetime import datetime | |
| from rng_system import get_rng | |
| class AlienType(Enum): | |
| """এলিয়েনের ধরণ""" | |
| SCOUT = "scout" # ছোট, দ্রুত | |
| FIGHTER = "fighter" # মাঝারি, স্ট্যান্ডার্ড | |
| BOMBER = "bomber" # বড়, ধীর | |
| BOSS = "boss" # খুব বড়, শক্তিশালী | |
| class AlienBehavior(Enum): | |
| """এলিয়েনের আচরণের ধরণ (ডিটারমিনিস্টিক)""" | |
| DIVE = "dive" # ডাইভ অ্যাটাক | |
| CIRCLE = "circle" # বৃত্তাকার পথ | |
| STRAIGHT = "straight" # সরলরেখা | |
| ZIGZAG = "zigzag" # জিগজ্যাগ | |
| FOLLOW = "follow" # প্লেয়ার ফলো | |
| RANDOM = "random" # এলোমেলো (র্যান্ডম) | |
| class AlienPattern: | |
| """এলিয়েন আক্রমণের প্যাটার্ন (ডিটারমিনিস্টিক)""" | |
| behavior: AlienBehavior | |
| speed: float | |
| amplitude: float # জিগজ্যাগ/সার্কেলের জন্য | |
| frequency: float # জিগজ্যাগের ফ্রিকোয়েন্সি | |
| duration: float # প্যাটার্ন চলার সময় | |
| next_pattern: Optional['AlienPattern'] = None | |
| class Alien: | |
| """এলিয়েন অবজেক্ট""" | |
| id: int | |
| type: AlienType | |
| x: float | |
| y: float | |
| health: int | |
| pattern: AlienPattern | |
| pattern_start_time: float | |
| speed_multiplier: float | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'type': self.type.value, | |
| 'x': round(self.x, 2), | |
| 'y': round(self.y, 2), | |
| 'health': self.health, | |
| 'pattern': self.pattern.behavior.value | |
| } | |
| class SpawnEvent: | |
| """স্পন ইভেন্ট""" | |
| time: float | |
| alien_type: AlienType | |
| x: float | |
| y: float | |
| pattern: AlienPattern | |
| class AlienPatternLibrary: | |
| """ | |
| এলিয়েন প্যাটার্ন লাইব্রেরি - ডিটারমিনিস্টিক প্যাটার্নের সেট | |
| PDF অনুযায়ী: এলিয়েনরা ডিটারমিনিস্টিক, র্যান্ডম নয় | |
| """ | |
| def __init__(self, patterns_file: str = "data/alien_patterns.json"): | |
| self.patterns_file = patterns_file | |
| self.patterns: Dict[AlienType, List[AlienPattern]] = {} | |
| self._load_patterns() | |
| def _load_patterns(self): | |
| """প্যাটার্ন লোড করা""" | |
| if os.path.exists(self.patterns_file): | |
| with open(self.patterns_file, 'r') as f: | |
| data = json.load(f) | |
| for alien_type, patterns in data.items(): | |
| self.patterns[AlienType(alien_type)] = [ | |
| AlienPattern(**p) for p in patterns | |
| ] | |
| else: | |
| # ডিফল্ট প্যাটার্ন তৈরি | |
| self._create_default_patterns() | |
| def _create_default_patterns(self): | |
| """ডিফল্ট প্যাটার্ন তৈরি (PDF-এর মতো)""" | |
| # Scout এলিয়েনের প্যাটার্ন | |
| self.patterns[AlienType.SCOUT] = [ | |
| AlienPattern(AlienBehavior.DIVE, 5.0, 0, 0, 2.0), | |
| AlienPattern(AlienBehavior.STRAIGHT, 4.0, 0, 0, 1.5), | |
| AlienPattern(AlienBehavior.CIRCLE, 3.0, 50, 1, 3.0), | |
| AlienPattern(AlienBehavior.ZIGZAG, 4.5, 30, 2, 2.5) | |
| ] | |
| # Fighter এলিয়েনের প্যাটার্ন | |
| self.patterns[AlienType.FIGHTER] = [ | |
| AlienPattern(AlienBehavior.FOLLOW, 3.5, 0, 0, 3.0), | |
| AlienPattern(AlienBehavior.DIVE, 4.0, 0, 0, 2.5), | |
| AlienPattern(AlienBehavior.STRAIGHT, 3.0, 0, 0, 2.0), | |
| AlienPattern(AlienBehavior.ZIGZAG, 3.5, 40, 1.5, 3.0) | |
| ] | |
| # Bomber এলিয়েনের প্যাটার্ন | |
| self.patterns[AlienType.BOMBER] = [ | |
| AlienPattern(AlienBehavior.STRAIGHT, 2.0, 0, 0, 4.0), | |
| AlienPattern(AlienBehavior.CIRCLE, 1.8, 80, 0.5, 5.0), | |
| AlienPattern(AlienBehavior.FOLLOW, 2.2, 0, 0, 3.5) | |
| ] | |
| # Boss এলিয়েনের প্যাটার্ন | |
| self.patterns[AlienType.BOSS] = [ | |
| AlienPattern(AlienBehavior.CIRCLE, 1.5, 100, 0.3, 8.0), | |
| AlienPattern(AlienBehavior.FOLLOW, 2.0, 0, 0, 5.0), | |
| AlienPattern(AlienBehavior.DIVE, 2.5, 0, 0, 4.0), | |
| AlienPattern(AlienBehavior.STRAIGHT, 1.8, 0, 0, 6.0) | |
| ] | |
| def get_pattern_cycle(self, alien_type: AlienType) -> List[AlienPattern]: | |
| """একটি এলিয়েনের জন্য প্যাটার্ন সাইকেল রিটার্ন করে""" | |
| return self.patterns.get(alien_type, self.patterns[AlienType.FIGHTER]) | |
| class AlienSpawner: | |
| """ | |
| এলিয়েন স্পনার - PDF-এর SpawnAlien রুটিনের ইমপ্লিমেন্টেশন | |
| র্যান্ডম অবস্থান তৈরি করতে RNG ব্যবহার করে, কিন্তু এলিয়েনের আচরণ ডিটারমিনিস্টিক | |
| """ | |
| def __init__(self, pattern_library: AlienPatternLibrary, | |
| screen_width: int = 800, screen_height: int = 600): | |
| self.rng = get_rng() | |
| self.pattern_library = pattern_library | |
| self.screen_width = screen_width | |
| self.screen_height = screen_height | |
| self.aliens: List[Alien] = [] | |
| self.spawn_history: List[SpawnEvent] = [] | |
| self.next_alien_id = 0 | |
| # স্পন প্যারামিটার | |
| self.spawn_rate = 0.5 # প্রতি সেকেন্ডে এলিয়েন | |
| self.last_spawn_time = time.time() # ← এখানে time.time() ব্যবহার করা হয়েছে | |
| self.max_aliens = 20 | |
| # স্ট্যাটিস্টিক্স | |
| self.total_spawned = 0 | |
| self.total_killed = 0 | |
| def _get_random_spawn_position(self) -> Tuple[float, float]: | |
| """ | |
| এলোমেলো স্পন অবস্থান (র্যান্ডম - PDF অনুযায়ী) | |
| """ | |
| side = self.rng.next_random_range(0, 3) # 0=উপরে, 1=নিচে, 2=বামে, 3=ডানে | |
| if side == 0: # উপরে | |
| x = self.rng.next_random_float(0, self.screen_width) | |
| y = -50 | |
| elif side == 1: # নিচে | |
| x = self.rng.next_random_float(0, self.screen_width) | |
| y = self.screen_height + 50 | |
| elif side == 2: # বামে | |
| x = -50 | |
| y = self.rng.next_random_float(0, self.screen_height) | |
| else: # ডানে | |
| x = self.screen_width + 50 | |
| y = self.rng.next_random_float(0, self.screen_height) | |
| return x, y | |
| def _select_alien_type(self) -> AlienType: | |
| """ | |
| এলোমেলো এলিয়েন টাইপ সিলেক্ট (র্যান্ডম) | |
| """ | |
| r = self.rng.next_random_float() | |
| if r < 0.5: # ৫০% scout | |
| return AlienType.SCOUT | |
| elif r < 0.8: # ৩০% fighter | |
| return AlienType.FIGHTER | |
| elif r < 0.95: # ১৫% bomber | |
| return AlienType.BOMBER | |
| else: # ৫% boss | |
| return AlienType.BOSS | |
| def _create_alien(self, alien_type: AlienType, x: float, y: float) -> Alien: | |
| """ | |
| নতুন এলিয়েন তৈরি | |
| """ | |
| # এলিয়েন টাইপ অনুযায়ী স্বাস্থ্য | |
| health_map = { | |
| AlienType.SCOUT: 1, | |
| AlienType.FIGHTER: 3, | |
| AlienType.BOMBER: 5, | |
| AlienType.BOSS: 20 | |
| } | |
| # প্যাটার্ন সাইকেল থেকে প্রথম প্যাটার্ন নেওয়া | |
| patterns = self.pattern_library.get_pattern_cycle(alien_type) | |
| pattern = patterns[0] | |
| # স্পিড মাল্টিপ্লায়ার (ছোট ভ্যারিয়েশন) | |
| speed_multiplier = 0.9 + self.rng.next_random_float() * 0.2 | |
| alien = Alien( | |
| id=self.next_alien_id, | |
| type=alien_type, | |
| x=x, | |
| y=y, | |
| health=health_map[alien_type], | |
| pattern=pattern, | |
| pattern_start_time=time.time(), | |
| speed_multiplier=speed_multiplier | |
| ) | |
| self.next_alien_id += 1 | |
| return alien | |
| def update(self, dt: float, player_x: float = 400, player_y: float = 300): | |
| """ | |
| প্রতি ফ্রেমে আপডেট | |
| """ | |
| current_time = time.time() | |
| # নতুন এলিয়েন স্পন | |
| if (len(self.aliens) < self.max_aliens and | |
| current_time - self.last_spawn_time > 1.0 / self.spawn_rate): | |
| alien_type = self._select_alien_type() | |
| x, y = self._get_random_spawn_position() | |
| alien = self._create_alien(alien_type, x, y) | |
| self.aliens.append(alien) | |
| self.spawn_history.append(SpawnEvent( | |
| time=current_time, | |
| alien_type=alien_type, | |
| x=x, | |
| y=y, | |
| pattern=alien.pattern | |
| )) | |
| self.total_spawned += 1 | |
| self.last_spawn_time = current_time | |
| # এলিয়েনদের অবস্থান আপডেট (ডিটারমিনিস্টিক প্যাটার্ন অনুযায়ী) | |
| aliens_to_remove = [] | |
| for alien in self.aliens: | |
| self._update_alien_position(alien, dt, player_x, player_y) | |
| # স্ক্রিনের বাইরে চলে গেলে রিমুভ | |
| if (alien.x < -200 or alien.x > self.screen_width + 200 or | |
| alien.y < -200 or alien.y > self.screen_height + 200): | |
| aliens_to_remove.append(alien) | |
| # মৃত এলিয়েন রিমুভ | |
| for alien in aliens_to_remove: | |
| if alien in self.aliens: | |
| self.aliens.remove(alien) | |
| self.total_killed += 1 | |
| def _update_alien_position(self, alien: Alien, dt: float, | |
| player_x: float, player_y: float): | |
| """ | |
| এলিয়েনের অবস্থান আপডেট (প্যাটার্ন অনুযায়ী - ডিটারমিনিস্টিক) | |
| """ | |
| time_in_pattern = time.time() - alien.pattern_start_time | |
| # প্যাটার্নের সময় শেষ হলে পরবর্তী প্যাটার্নে যাওয়া | |
| if time_in_pattern > alien.pattern.duration: | |
| patterns = self.pattern_library.get_pattern_cycle(alien.type) | |
| current_index = patterns.index(alien.pattern) if alien.pattern in patterns else 0 | |
| next_index = (current_index + 1) % len(patterns) | |
| alien.pattern = patterns[next_index] | |
| alien.pattern_start_time = time.time() | |
| time_in_pattern = 0 | |
| speed = alien.pattern.speed * alien.speed_multiplier * dt * 60 # 60 FPS ধরে | |
| # প্যাটার্ন অনুযায়ী মুভমেন্ট | |
| if alien.pattern.behavior == AlienBehavior.DIVE: | |
| # প্লেয়ারের দিকে ডাইভ | |
| dx = player_x - alien.x | |
| dy = player_y - alien.y | |
| dist = math.sqrt(dx*dx + dy*dy) | |
| if dist > 0: | |
| alien.x += (dx / dist) * speed | |
| alien.y += (dy / dist) * speed | |
| elif alien.pattern.behavior == AlienBehavior.CIRCLE: | |
| # বৃত্তাকার পথ | |
| angle = time_in_pattern * alien.pattern.frequency | |
| alien.x += math.cos(angle) * speed | |
| alien.y += math.sin(angle) * speed | |
| elif alien.pattern.behavior == AlienBehavior.STRAIGHT: | |
| # সরলরেখায় (পূর্ব নির্ধারিত দিকে) | |
| alien.x -= speed # বামে | |
| elif alien.pattern.behavior == AlienBehavior.ZIGZAG: | |
| # জিগজ্যাগ প্যাটার্ন | |
| alien.x -= speed | |
| alien.y += math.sin(time_in_pattern * alien.pattern.frequency) * alien.pattern.amplitude * dt | |
| elif alien.pattern.behavior == AlienBehavior.FOLLOW: | |
| # প্লেয়ারকে ফলো | |
| dx = player_x - alien.x | |
| dy = player_y - alien.y | |
| dist = math.sqrt(dx*dx + dy*dy) | |
| if dist > 100: # ১০০ পিক্সেল দূরত্বে রাখে | |
| if dist > 0: | |
| alien.x += (dx / dist) * speed * 0.5 | |
| alien.y += (dy / dist) * speed * 0.5 | |
| # র্যান্ডম বিহেভিয়ার (শুধু যদি সেট করা থাকে) | |
| elif alien.pattern.behavior == AlienBehavior.RANDOM: | |
| alien.x += (self.rng.next_random_float() - 0.5) * speed * 2 | |
| alien.y += (self.rng.next_random_float() - 0.5) * speed * 2 | |
| def damage_alien(self, alien_id: int, damage: int = 1) -> bool: | |
| """এলিয়েনকে আঘাত করা""" | |
| for alien in self.aliens: | |
| if alien.id == alien_id: | |
| alien.health -= damage | |
| if alien.health <= 0: | |
| self.aliens.remove(alien) | |
| self.total_killed += 1 | |
| return True | |
| break | |
| return False | |
| def get_aliens_data(self) -> List[dict]: | |
| """UI-এর জন্য এলিয়েন ডাটা""" | |
| return [alien.to_dict() for alien in self.aliens] | |
| def get_stats(self) -> dict: | |
| """পরিসংখ্যান""" | |
| return { | |
| 'total_spawned': self.total_spawned, | |
| 'total_killed': self.total_killed, | |
| 'active_aliens': len(self.aliens), | |
| 'spawn_rate': self.spawn_rate | |
| } | |
| def get_spawn_history(self, limit: int = 50) -> List[dict]: | |
| """স্পন হিস্ট্রি""" | |
| return [ | |
| { | |
| 'time': datetime.fromtimestamp(e.time).strftime('%H:%M:%S'), | |
| 'type': e.alien_type.value, | |
| 'position': f"({int(e.x)},{int(e.y)})" | |
| } | |
| for e in self.spawn_history[-limit:] | |
| ] | |
| class AlienAIManager: | |
| """ | |
| এলিয়েন এআই ম্যানেজার - ডিটারমিনিস্টিক প্যাটার্ন ম্যানেজ করে | |
| PDF অনুযায়ী: এলিয়েনরা ডিটারমিনিস্টিক | |
| """ | |
| def __init__(self): | |
| self.pattern_library = AlienPatternLibrary() | |
| self.current_cycle_index = 0 | |
| self.cycle_length = 4 # প্রতি ৪ রাউন্ডে প্যাটার্ন রিসেট | |
| def get_attack_wave_pattern(self, wave_number: int) -> List[AlienPattern]: | |
| """ | |
| ওয়েব নম্বর অনুযায়ী অ্যাটাক প্যাটার্ন | |
| ডিটারমিনিস্টিক - প্রতি ওয়েভে একই প্যাটার্ন রিপিট | |
| """ | |
| base_pattern = self.pattern_library.get_pattern_cycle(AlienType.FIGHTER) | |
| # ওয়েব নম্বর অনুযায়ী প্যাটার্ন মডিফাই | |
| wave_index = (wave_number // self.cycle_length) % len(base_pattern) | |
| return [base_pattern[wave_index]] | |
| def predict_next_attack(self, current_wave: int) -> str: | |
| """ | |
| পরবর্তী অ্যাটাকের ধরণ প্রেডিক্ট (ডিটারমিনিস্টিক) | |
| """ | |
| next_pattern = self.get_attack_wave_pattern(current_wave + 1) | |
| return f"পরবর্তী অ্যাটাক: {next_pattern[0].behavior.value}" |