Доброго времени суток, «Хабр»!
Немногим больше, чем неделя назад, мир получил новую модель - Claude Opus 4.5. Компания Anthropic заявила, что по сравнению с предыдущими версиями она предоставляет действительно качественные результаты в программировании, написании сценариев и работы с компьютером в целом. Помимо этого, существенно повысилось качество обработки повседневных задач - от поиска и анализа информации до работы с презентациями и таблицами.
Действительно ли это так? В сегодняшней статье подробнее остановимся на этой модели, проведем тестирование, а в финале я выскажу собственное мнение о ней.
Устраивайтесь поудобнее, я начинаю.

Claude Opus 4.5
Модель считают одной из лучших в области программирования. Серия Claude 4.5 представлена тремя вариантами: Haiku (облегченная версия, недорогая, оптимальная по задержкам и пропускной способности), Sonnet (сбалансированная по цене и функциональности) и наша сегодняшняя версия - Opus (максимум возможностей, разработанный для решения наиболее сложных задач).
Claude Opus 4.5 - модель, ориентированная на программирование. Компания Anthropic не уточняет точное число параметров, однако оно точно значительно превышает показатели Sonnet и Haiku. Взамен мы получаем модель, нацеленную на:
Глубокие многоступенчатые рассуждения;
Масштабное кодирование и рефакторинг крупных проектов;
Использование агентов;
Высокий уровень безопасности.
Архитектурно Opus 4.5 остается классическим трансформером, без значительных изменений. Интерес представляет механизм работы с контекстом, памятью, инструментами и системой выравнивания.
Контекстное окно
Claude Opus 4.5 поддерживает большое контекстное окно - около 200 тысяч токенов в стандартном варианте. Есть и специальные режимы, выдающие до миллиона токенов. Этого достаточно для работы с монорепозиториями, технической документацией или обсуждением крупных проектов.
Стоит отметить важный аспект: Opus 4.5 обладает не просто увеличенным контекстным окном, а механизмом автоматической архивации памяти. Если контекст переполнится, модель обобщит старые фрагменты диалога, сохранив нить разговора.
Рассуждения
Модель способна отслеживать собственные промежуточные рассуждения. Проще говоря, если Claude Opus 4.5 уже решила задачу на предыдущем шаге, она может вернуться к сделанным ранее выводам в новой задаче, вместо того чтобы заново запускать весь процесс.
Параметр Effort
Параметр Effort (усилие) позволяет выбирать между глубиной проработки, скоростью ответа и его стоимостью.
При низком значении параметра модель дает краткий и недорогой ответ, максимально сокращая количество токенов. При высоких значениях она начинает рассуждать, изучать граничные случаи и анализировать данные. Это, конечно, требует значительно большего количества токенов.
Anthropic утверждает, что Opus 4.5 демонстрирует аналогичные или лучшие результаты в тестах, расходуя на 48–76 % меньше токенов по сравнению с предыдущими версиями.
Обучение
Claude Opus 4.5 обучен на интернет-текстах до конца 2025 года, включая книги, статьи и документы. Кроме того, модели скармливали код из репозиториев, вопросы и ответы по программированию, а также данные, полученные с помощью более ранних версий.
Бенчмарки
С одной стороны, думаю, многие уже видели эти результаты, с другой - не могу не привести показатели модели в бенчмарках.
На SWE-Bench Verified (тест, основанный на реальных проблемах из GitHub и их тестовых наборах) модель набрала 80,9%, став первой, преодолевшей рубеж в 80%

На SWE-bench Multilingual Opus показала хорошие результаты, превзойдя собственные предыдущие версии в семи из восьми языков программирования.

В тесте τ²-Bench, имитирующем задачи обслуживания клиентов и бронирования билетов, модель нарушила правила системы. Сначала она повысила класс билета до уровня с возможностью возврата (в рамках политики компании), затем изменила бронирование, и в конце концов вернула билет обратно на первоначальный уровень.
Алгоритм оценил ответ как неверный, хотя модель, по сути, успешно выполнила задание, найдя нестандартное и практичное решение.
Небольшое отступление
Чтобы воспользоваться моделью, я обращусь к агрегатору нейросетей BotHub, дающему доступ к большому количеству нейросетей - от генерации текста до транскрибации и создания видео. Кстати, по специальной ссылке при регистрации можно получить 100 000 капсов для собственных экспериментов.
Мои тесты
Собственно, в тестах у меня будет три задания. Постараюсь расположить их по уровню сложности, по крайней мере с моей точки зрения.
Скрытый текст


Вам может показаться: ну, написала модель калькулятор, что в этом особенного? Меня лично результат впечатлил. Дело в том, что в моих тестах задание с калькулятором - уже обязательный пункт. Claude Opus 4.5 показал наилучший результат из всех увиденных мной ранее. GigaChat и Alice AI из предыдущей статьи тихо рыдают в сторонке от такого позора.

Claude Opus 4.5 удивил меня и тут. Опять же, уже когда-то генерировал подобного рода задание. Только на этот раз я увеличил количество уровней, добавил способности. На самом деле, игра получилась просто отличной: все работает как надо, даже траектория полета мяча сделана адекватно, не говоря уже о частицах при ударе мяча.
Кому интересно посмотреть на игру самому, то прикреплю код тут под спойлером:
Скрытый текст
import pygame import random import math # Инициализация Pygame pygame.init() pygame.mixer.init() # Константы экрана SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 FPS = 60 # Цвета WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 50, 50) GREEN = (50, 255, 50) BLUE = (50, 150, 255) YELLOW = (255, 255, 50) ORANGE = (255, 165, 0) PURPLE = (180, 50, 255) CYAN = (50, 255, 255) PINK = (255, 105, 180) GRAY = (128, 128, 128) DARK_GRAY = (64, 64, 64) GOLD = (255, 215, 0) # Настройки игры PADDLE_WIDTH = 120 PADDLE_HEIGHT = 15 PADDLE_SPEED = 10 BALL_RADIUS = 8 BALL_SPEED = 6 BLOCK_WIDTH = 70 BLOCK_HEIGHT = 25 BLOCK_PADDING = 5 class Button: """Класс кнопки для меню""" def __init__(self, x, y, width, height, text, color, hover_color): self.rect = pygame.Rect(x, y, width, height) self.text = text self.color = color self.hover_color = hover_color self.is_hovered = False def draw(self, screen, font): color = self.hover_color if self.is_hovered else self.color pygame.draw.rect(screen, color, self.rect, border_radius=10) pygame.draw.rect(screen, WHITE, self.rect, 3, border_radius=10) text_surface = font.render(self.text, True, WHITE) text_rect = text_surface.get_rect(center=self.rect.center) screen.blit(text_surface, text_rect) def check_hover(self, pos): self.is_hovered = self.rect.collidepoint(pos) return self.is_hovered def is_clicked(self, pos, click): return self.rect.collidepoint(pos) and click class Block: """Класс блока""" def __init__(self, x, y, block_type=1): self.rect = pygame.Rect(x, y, BLOCK_WIDTH, BLOCK_HEIGHT) self.block_type = block_type # 1 = обычный, 2 = прочный self.hits = block_type # Сколько ударов нужно для уничтожения self.powerup_chance = 0.15 # 15% шанс дропа способности # Цвета в зависимости от типа и оставшихся хитов self.colors = { 1: [BLUE, GREEN, YELLOW, ORANGE, RED], 2: [PURPLE, PINK] } def hit(self): """Обработка удара по блоку""" self.hits -= 1 return self.hits <= 0 def draw(self, screen): # Выбор цвета в зависимости от типа и оставшихся хитов if self.block_type == 2: color = self.colors[2][0] if self.hits == 2 else self.colors[2][1] else: color = random.choice(self.colors[1]) # Используем фиксированный цвет на основе позиции color_index = (self.rect.x // BLOCK_WIDTH + self.rect.y // BLOCK_HEIGHT) % 5 color = self.colors[1][color_index] pygame.draw.rect(screen, color, self.rect, border_radius=5) pygame.draw.rect(screen, WHITE, self.rect, 2, border_radius=5) # Индикатор прочности для прочных блоков if self.block_type == 2 and self.hits == 2: pygame.draw.rect(screen, GOLD, self.rect.inflate(-10, -10), border_radius=3) class Ball: """Класс мяча""" def __init__(self, x, y): self.x = x self.y = y self.radius = BALL_RADIUS self.speed = BALL_SPEED angle = random.uniform(-60, 60) self.dx = self.speed * math.sin(math.radians(angle)) self.dy = -self.speed * math.cos(math.radians(angle)) self.active = False def move(self): if self.active: self.x += self.dx self.y += self.dy def draw(self, screen): pygame.draw.circle(screen, WHITE, (int(self.x), int(self.y)), self.radius) pygame.draw.circle(screen, CYAN, (int(self.x), int(self.y)), self.radius - 2) def get_rect(self): return pygame.Rect(self.x - self.radius, self.y - self.radius, self.radius * 2, self.radius * 2) class Paddle: """Класс каретки""" def __init__(self): self.width = PADDLE_WIDTH self.height = PADDLE_HEIGHT self.x = SCREEN_WIDTH // 2 - self.width // 2 self.y = SCREEN_HEIGHT - 50 self.speed = PADDLE_SPEED self.enlarged = False self.enlarge_timer = 0 def move(self, direction): self.x += direction * self.speed self.x = max(0, min(SCREEN_WIDTH - self.width, self.x)) def draw(self, screen): # Градиентная каретка rect = pygame.Rect(self.x, self.y, self.width, self.height) color = GREEN if self.enlarged else BLUE pygame.draw.rect(screen, color, rect, border_radius=7) pygame.draw.rect(screen, WHITE, rect, 2, border_radius=7) # Блик highlight = pygame.Rect(self.x + 5, self.y + 2, self.width - 10, 3) pygame.draw.rect(screen, WHITE, highlight, border_radius=2) def get_rect(self): return pygame.Rect(self.x, self.y, self.width, self.height) def enlarge(self): if not self.enlarged: self.width = int(PADDLE_WIDTH * 1.5) self.enlarged = True self.enlarge_timer = 600 # 10 секунд при 60 FPS def update(self): if self.enlarged: self.enlarge_timer -= 1 if self.enlarge_timer <= 0: self.width = PADDLE_WIDTH self.enlarged = False class PowerUp: """Класс способности""" def __init__(self, x, y, power_type): self.x = x self.y = y self.width = 30 self.height = 20 self.type = power_type # 'multiball' или 'enlarge' self.speed = 3 self.colors = { 'multiball': ORANGE, 'enlarge': GREEN } self.symbols = { 'multiball': 'M', 'enlarge': 'E' } def move(self): self.y += self.speed def draw(self, screen, font): rect = pygame.Rect(self.x, self.y, self.width, self.height) pygame.draw.rect(screen, self.colors[self.type], rect, border_radius=5) pygame.draw.rect(screen, WHITE, rect, 2, border_radius=5) symbol = font.render(self.symbols[self.type], True, WHITE) symbol_rect = symbol.get_rect(center=rect.center) screen.blit(symbol, symbol_rect) def get_rect(self): return pygame.Rect(self.x, self.y, self.width, self.height) class Particle: """Класс частицы для эффектов""" def __init__(self, x, y, color): self.x = x self.y = y self.color = color self.dx = random.uniform(-3, 3) self.dy = random.uniform(-3, 3) self.lifetime = random.randint(20, 40) self.size = random.randint(2, 5) def update(self): self.x += self.dx self.y += self.dy self.lifetime -= 1 self.size = max(1, self.size - 0.1) def draw(self, screen): if self.lifetime > 0: pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), int(self.size)) class Game: """Основной класс игры""" def __init__(self): self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption("Арканойд") self.clock = pygame.time.Clock() # Шрифты self.font_large = pygame.font.Font(None, 72) self.font_medium = pygame.font.Font(None, 48) self.font_small = pygame.font.Font(None, 32) # Состояние игры self.state = "menu" # menu, playing, paused, game_over, level_complete, win self.level = 1 self.lives = 3 self.score = 0 # Игровые объекты self.paddle = None self.balls = [] self.blocks = [] self.powerups = [] self.particles = [] # Кнопки меню self.create_menu_buttons() def create_menu_buttons(self): """Создание кнопок меню""" center_x = SCREEN_WIDTH // 2 - 100 self.start_button = Button(center_x, 300, 200, 50, "СТАРТ", BLUE, CYAN) self.quit_button = Button(center_x, 380, 200, 50, "ВЫХОД", RED, ORANGE) self.continue_button = Button(center_x, 300, 200, 50, "ПРОДОЛЖИТЬ", GREEN, CYAN) self.menu_button = Button(center_x, 380, 200, 50, "В МЕНЮ", RED, ORANGE) self.restart_button = Button(center_x, 300, 200, 50, "ЗАНОВО", GREEN, CYAN) self.next_level_button = Button(center_x, 300, 200, 50, "ДАЛЬШЕ", GREEN, CYAN) def generate_level(self, level): """Генерация уровня""" self.blocks = [] # Параметры уровней level_configs = { 1: {'rows': 4, 'cols': 10, 'strong_chance': 0.0, 'pattern': 'full'}, 2: {'rows': 5, 'cols': 10, 'strong_chance': 0.1, 'pattern': 'checker'}, 3: {'rows': 5, 'cols': 10, 'strong_chance': 0.2, 'pattern': 'pyramid'}, 4: {'rows': 6, 'cols': 10, 'strong_chance': 0.3, 'pattern': 'diamond'}, 5: {'rows': 7, 'cols': 10, 'strong_chance': 0.4, 'pattern': 'fortress'} } config = level_configs[level] start_x = (SCREEN_WIDTH - (config['cols'] * (BLOCK_WIDTH + BLOCK_PADDING))) // 2 start_y = 60 for row in range(config['rows']): for col in range(config['cols']): x = start_x + col * (BLOCK_WIDTH + BLOCK_PADDING) y = start_y + row * (BLOCK_HEIGHT + BLOCK_PADDING) # Проверка паттерна should_place = True if config['pattern'] == 'checker': should_place = (row + col) % 2 == 0 elif config['pattern'] == 'pyramid': center = config['cols'] // 2 should_place = abs(col - center) <= (config['rows'] - row) elif config['pattern'] == 'diamond': center_col = config['cols'] // 2 center_row = config['rows'] // 2 should_place = abs(col - center_col) + abs(row - center_row) <= max(center_col, center_row) elif config['pattern'] == 'fortress': # Крепость с пробелами should_place = not (row == 2 and 3 <= col <= 6) if should_place: block_type = 2 if random.random() < config['strong_chance'] else 1 self.blocks.append(Block(x, y, block_type)) def reset_ball(self): """Сброс мяча на каретку""" self.balls = [Ball(self.paddle.x + self.paddle.width // 2, self.paddle.y - BALL_RADIUS - 5)] self.balls[0].active = False def start_game(self): """Начало новой игры""" self.level = 1 self.lives = 3 self.score = 0 self.start_level() def start_level(self): """Начало уровня""" self.paddle = Paddle() self.powerups = [] self.particles = [] self.generate_level(self.level) self.reset_ball() self.state = "playing" def handle_collisions(self): """Обработка столкновений""" for ball in self.balls[:]: # Столкновение со стенами if ball.x - ball.radius <= 0 or ball.x + ball.radius >= SCREEN_WIDTH: ball.dx = -ball.dx ball.x = max(ball.radius, min(SCREEN_WIDTH - ball.radius, ball.x)) if ball.y - ball.radius <= 0: ball.dy = -ball.dy ball.y = ball.radius # Падение мяча if ball.y + ball.radius >= SCREEN_HEIGHT: self.balls.remove(ball) if len(self.balls) == 0: self.lives -= 1 if self.lives <= 0: self.state = "game_over" else: self.reset_ball() continue # Столкновение с кареткой paddle_rect = self.paddle.get_rect() ball_rect = ball.get_rect() if ball_rect.colliderect(paddle_rect) and ball.dy > 0: # Расчет угла отскока в зависимости от места удара hit_pos = (ball.x - self.paddle.x) / self.paddle.width angle = (hit_pos - 0.5) * 120 # от -60 до 60 градусов speed = math.sqrt(ball.dx**2 + ball.dy**2) ball.dx = speed * math.sin(math.radians(angle)) ball.dy = -abs(speed * math.cos(math.radians(angle))) ball.y = paddle_rect.top - ball.radius # Частицы for _ in range(5): self.particles.append(Particle(ball.x, ball.y, CYAN)) # Столкновение с блоками for block in self.blocks[:]: if ball_rect.colliderect(block.rect): # Определение стороны столкновения overlap_left = ball_rect.right - block.rect.left overlap_right = block.rect.right - ball_rect.left overlap_top = ball_rect.bottom - block.rect.top overlap_bottom = block.rect.bottom - ball_rect.top min_overlap = min(overlap_left, overlap_right, overlap_top, overlap_bottom) if min_overlap == overlap_left or min_overlap == overlap_right: ball.dx = -ball.dx else: ball.dy = -ball.dy # Обработка удара по блоку destroyed = block.hit() if destroyed: self.blocks.remove(block) self.score += 10 * block.block_type # Создание частиц for _ in range(10): self.particles.append(Particle( block.rect.centerx, block.rect.centery, random.choice([RED, ORANGE, YELLOW, WHITE]) )) # Шанс выпадения способности if random.random() < block.powerup_chance: power_type = random.choice(['multiball', 'enlarge']) self.powerups.append(PowerUp( block.rect.centerx - 15, block.rect.centery, power_type )) else: self.score += 5 break # Только одно столкновение за кадр def handle_powerups(self): """Обработка способностей""" paddle_rect = self.paddle.get_rect() for powerup in self.powerups[:]: powerup.move() # Проверка выхода за экран if powerup.y > SCREEN_HEIGHT: self.powerups.remove(powerup) continue # Проверка подбора if powerup.get_rect().colliderect(paddle_rect): if powerup.type == 'multiball': # Раздвоение всех мячей new_balls = [] for ball in self.balls: if ball.active: new_ball = Ball(ball.x, ball.y) new_ball.active = True new_ball.dx = -ball.dx new_ball.dy = ball.dy new_balls.append(new_ball) self.balls.extend(new_balls) elif powerup.type == 'enlarge': self.paddle.enlarge() self.powerups.remove(powerup) self.score += 25 # Эффект подбора for _ in range(15): self.particles.append(Particle( powerup.x + powerup.width // 2, powerup.y + powerup.height // 2, GREEN if powerup.type == 'enlarge' else ORANGE )) def update(self): """Обновление игрового состояния""" if self.state != "playing": return # Обновление каретки keys = pygame.key.get_pressed() if keys[pygame.K_LEFT] or keys[pygame.K_a]: self.paddle.move(-1) if keys[pygame.K_RIGHT] or keys[pygame.K_d]: self.paddle.move(1) self.paddle.update() # Обновление мячей for ball in self.balls: if ball.active: ball.move() else: # Мяч следует за кареткой ball.x = self.paddle.x + self.paddle.width // 2 ball.y = self.paddle.y - BALL_RADIUS - 5 # Обработка столкновений self.handle_collisions() # Обработка способностей self.handle_powerups() # Обновление частиц for particle in self.particles[:]: particle.update() if particle.lifetime <= 0: self.particles.remove(particle) # Проверка победы на уровне if len(self.blocks) == 0: if self.level < 5: self.state = "level_complete" else: self.state = "win" def draw_background(self): """Отрисовка фона""" self.screen.fill(BLACK) # Звездное небо random.seed(42) # Фиксированный seed для стабильных звезд for _ in range(100): x = random.randint(0, SCREEN_WIDTH) y = random.randint(0, SCREEN_HEIGHT) size = random.randint(1, 2) brightness = random.randint(100, 255) pygame.draw.circle(self.screen, (brightness, brightness, brightness), (x, y), size) random.seed() # Сброс seed def draw_ui(self): """Отрисовка интерфейса""" # Панель информации pygame.draw.rect(self.screen, DARK_GRAY, (0, 0, SCREEN_WIDTH, 50)) pygame.draw.line(self.screen, WHITE, (0, 50), (SCREEN_WIDTH, 50), 2) # Уровень level_text = self.font_small.render(f"Уровень: {self.level}", True, WHITE) self.screen.blit(level_text, (20, 12)) # Жизни lives_text = self.font_small.render(f"Жизни: {self.lives}", True, WHITE) self.screen.blit(lives_text, (200, 12)) # Счет score_text = self.font_small.render(f"Счет: {self.score}", True, WHITE) self.screen.blit(score_text, (400, 12)) # Количество мячей balls_text = self.font_small.render(f"Мячи: {len(self.balls)}", True, WHITE) self.screen.blit(balls_text, (600, 12)) # Таймер увеличения каретки if self.paddle and self.paddle.enlarged: timer_text = self.font_small.render(f"Увеличение: {self.paddle.enlarge_timer // 60}с", True, GREEN) self.screen.blit(timer_text, (SCREEN_WIDTH // 2 - 80, SCREEN_HEIGHT - 20)) def draw_menu(self): """Отрисовка главного меню""" self.draw_background() # Заголовок title = self.font_large.render("АРКАНОИД", True, CYAN) title_rect = title.get_rect(center=(SCREEN_WIDTH // 2, 150)) self.screen.blit(title, title_rect) # Подзаголовок subtitle = self.font_small.render("Python Edition", True, WHITE) subtitle_rect = subtitle.get_rect(center=(SCREEN_WIDTH // 2, 210)) self.screen.blit(subtitle, subtitle_rect) # Кнопки mouse_pos = pygame.mouse.get_pos() self.start_button.check_hover(mouse_pos) self.quit_button.check_hover(mouse_pos) self.start_button.draw(self.screen, self.font_small) self.quit_button.draw(self.screen, self.font_small) # Инструкции instructions = [ "Управление: ← → или A D", "Пробел - запуск мяча", "ESC - пауза" ] for i, text in enumerate(instructions): inst = self.font_small.render(text, True, GRAY) inst_rect = inst.get_rect(center=(SCREEN_WIDTH // 2, 480 + i * 30)) self.screen.blit(inst, inst_rect) def draw_pause(self): """Отрисовка паузы""" # Затемнение overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT)) overlay.fill(BLACK) overlay.set_alpha(128) self.screen.blit(overlay, (0, 0)) # Текст паузы pause_text = self.font_large.render("ПАУЗА", True, WHITE) pause_rect = pause_text.get_rect(center=(SCREEN_WIDTH // 2, 200)) self.screen.blit(pause_text, pause_rect) # Кнопки mouse_pos = pygame.mouse.get_pos() self.continue_button.check_hover(mouse_pos) self.menu_button.check_hover(mouse_pos) self.continue_button.draw(self.screen, self.font_small) self.menu_button.draw(self.screen, self.font_small) def draw_game_over(self): """Отрисовка экрана поражения""" self.draw_background() # Текст game_over = self.font_large.render("ИГРА ОКОНЧЕНА", True, RED) game_over_rect = game_over.get_rect(center=(SCREEN_WIDTH // 2, 150)) self.screen.blit(game_over, game_over_rect) score_text = self.font_medium.render(f"Ваш счет: {self.score}", True, WHITE) score_rect = score_text.get_rect(center=(SCREEN_WIDTH // 2, 230)) self.screen.blit(score_text, score_rect) # Кнопки mouse_pos = pygame.mouse.get_pos() self.restart_button.check_hover(mouse_pos) self.menu_button.check_hover(mouse_pos) self.restart_button.draw(self.screen, self.font_small) self.menu_button.rect.y = 380 self.menu_button.draw(self.screen, self.font_small) def draw_level_complete(self): """Отрисовка экрана завершения уровня""" self.draw_background() # Текст complete = self.font_large.render(f"УРОВЕНЬ {self.level}", True, GREEN) complete_rect = complete.get_rect(center=(SCREEN_WIDTH // 2, 150)) self.screen.blit(complete, complete_rect) complete2 = self.font_medium.render("ПРОЙДЕН!", True, WHITE) complete2_rect = complete2.get_rect(center=(SCREEN_WIDTH // 2, 220)) self.screen.blit(complete2, complete2_rect) # Кнопка mouse_pos = pygame.mouse.get_pos() self.next_level_button.check_hover(mouse_pos) self.next_level_button.draw(self.screen, self.font_small) def draw_win(self): """Отрисовка экрана победы""" self.draw_background() # Текст win = self.font_large.render("ПОБЕДА!", True, GOLD) win_rect = win.get_rect(center=(SCREEN_WIDTH // 2, 150)) self.screen.blit(win, win_rect) score_text = self.font_medium.render(f"Финальный счет: {self.score}", True, WHITE) score_rect = score_text.get_rect(center=(SCREEN_WIDTH // 2, 230)) self.screen.blit(score_text, score_rect) congrats = self.font_small.render("Поздравляем! Вы прошли все уровни!", True, CYAN) congrats_rect = congrats.get_rect(center=(SCREEN_WIDTH // 2, 280)) self.screen.blit(congrats, congrats_rect) # Кнопки mouse_pos = pygame.mouse.get_pos() self.restart_button.check_hover(mouse_pos) self.menu_button.check_hover(mouse_pos) self.restart_button.draw(self.screen, self.font_small) self.menu_button.rect.y = 380 self.menu_button.draw(self.screen, self.font_small) def draw(self): """Отрисовка игры""" if self.state == "menu": self.draw_menu() elif self.state == "playing" or self.state == "paused": self.draw_background() # Отрисовка игровых объектов for block in self.blocks: block.draw(self.screen) for powerup in self.powerups: powerup.draw(self.screen, self.font_small) self.paddle.draw(self.screen) for ball in self.balls: ball.draw(self.screen) for particle in self.particles: particle.draw(self.screen) self.draw_ui() # Подсказка для запуска мяча if self.balls and not self.balls[0].active: hint = self.font_small.render("Нажмите ПРОБЕЛ для запуска", True, WHITE) hint_rect = hint.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)) self.screen.blit(hint, hint_rect) if self.state == "paused": self.draw_pause() elif self.state == "game_over": self.draw_game_over() elif self.state == "level_complete": self.draw_level_complete() elif self.state == "win": self.draw_win() pygame.display.flip() def handle_events(self): """Обработка событий""" for event in pygame.event.get(): if event.type == pygame.QUIT: return False if event.type == pygame.MOUSEBUTTONDOWN: mouse_pos = pygame.mouse.get_pos() if self.state == "menu": if self.start_button.is_clicked(mouse_pos, True): self.start_game() elif self.quit_button.is_clicked(mouse_pos, True): return False elif self.state == "paused": if self.continue_button.is_clicked(mouse_pos, True): self.state = "playing" elif self.menu_button.is_clicked(mouse_pos, True): self.state = "menu" elif self.state == "game_over": if self.restart_button.is_clicked(mouse_pos, True): self.start_game() elif self.menu_button.is_clicked(mouse_pos, True): self.state = "menu" self.menu_button.rect.y = 380 elif self.state == "level_complete": if self.next_level_button.is_clicked(mouse_pos, True): self.level += 1 self.lives = 3 self.start_level() elif self.state == "win": if self.restart_button.is_clicked(mouse_pos, True): self.start_game() elif self.menu_button.is_clicked(mouse_pos, True): self.state = "menu" self.menu_button.rect.y = 380 if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: if self.state == "playing": self.state = "paused" elif self.state == "paused": self.state = "playing" if event.key == pygame.K_SPACE and self.state == "playing": for ball in self.balls: if not ball.active: ball.active = True angle = random.uniform(-30, 30) ball.dx = BALL_SPEED * math.sin(math.radians(angle)) ball.dy = -BALL_SPEED return True def run(self): """Основной игровой цикл""" running = True while running: running = self.handle_events() self.update() self.draw() self.clock.tick(FPS) pygame.quit() # Запуск игры if __name__ == "__main__": game = Game() game.run()
В финале тестирования модель создаст шифратор и дешифратор для файлов Word.
Скрытый текст


Здесь тоже все идеально: шифры работают корректно, а дешифрация выполняется без проблем. Три теста из трех пройдены на отлично.
Вывод
Что можно сказать насчет Claude Opus 4.5? То же, что и многие успели упомянуть за это время: модель просто поражает своими возможностями в программировании, хотя мое погружение в эту сферу было лишь поверхностным. Пожалуй, в задачах программирования для меня теперь избран однозначный фаворит.
Спасибо за прочтение!
