Claude Sonnet 4にマリオっぽいやつ作らせてみた

# はじめに
最近発表されたClaude Sonnet 4があんまり盛り上がってない気がするのですが、気のせいでしょうか。
それはさておき、今回のモデルの性能をマリオを作らせて検証してみました。

# コード
```python:python
import pygame
import sys

# 初期化
pygame.init()

# 画面サイズ
WIDTH = 800
HEIGHT = 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("マリオゲーム")

# 色の定義
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
BROWN = (139, 69, 19)
SKY_BLUE = (135, 206, 235)
YELLOW = (255, 255, 0)

# ゲームクロック
clock = pygame.time.Clock()

class Mario:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 30
        self.height = 40
        self.vel_x = 0
        self.vel_y = 0
        self.on_ground = False
        self.speed = 5
        self.jump_power = -15
        self.gravity = 0.8
        self.max_fall_speed = 10
        
    def update(self):
        # 重力を適用
        if not self.on_ground:
            self.vel_y += self.gravity
            if self.vel_y > self.max_fall_speed:
                self.vel_y = self.max_fall_speed
        
        # 位置を更新
        self.x += self.vel_x
        self.y += self.vel_y
        
        # 画面端での処理
        if self.x < 0:
            self.x = 0
        elif self.x > WIDTH - self.width:
            self.x = WIDTH - self.width
            
        # 地面との衝突判定
        self.check_ground_collision()
        
        # プラットフォームとの衝突判定
        self.check_platform_collision()
        
    def check_ground_collision(self):
        # 地面（画面下部）との衝突
        if self.y + self.height >= HEIGHT - 50:
            self.y = HEIGHT - 50 - self.height
            self.vel_y = 0
            self.on_ground = True
        else:
            self.on_ground = False
            
    def check_platform_collision(self):
        mario_rect = pygame.Rect(self.x, self.y, self.width, self.height)
        
        for platform in platforms:
            platform_rect = pygame.Rect(platform['x'], platform['y'], platform['width'], platform['height'])
            
            if mario_rect.colliderect(platform_rect):
                # 上から落ちてきた場合
                if self.vel_y > 0 and self.y < platform['y']:
                    self.y = platform['y'] - self.height
                    self.vel_y = 0
                    self.on_ground = True
                # 下から来た場合
                elif self.vel_y < 0 and self.y > platform['y']:
                    self.y = platform['y'] + platform['height']
                    self.vel_y = 0
                # 横から来た場合
                elif self.vel_x > 0:  # 右に移動中
                    self.x = platform['x'] - self.width
                elif self.vel_x < 0:  # 左に移動中
                    self.x = platform['x'] + platform['width']
    
    def jump(self):
        if self.on_ground:
            self.vel_y = self.jump_power
            self.on_ground = False
    
    def move_left(self):
        self.vel_x = -self.speed
    
    def move_right(self):
        self.vel_x = self.speed
    
    def stop_horizontal(self):
        self.vel_x = 0
    
    def draw(self, screen):
        # マリオの体（赤い帽子と青いオーバーオール）
        # 帽子
        pygame.draw.rect(screen, RED, (self.x, self.y, self.width, 15))
        # 顔
        pygame.draw.rect(screen, (255, 220, 177), (self.x + 5, self.y + 10, self.width - 10, 15))
        # オーバーオール
        pygame.draw.rect(screen, BLUE, (self.x + 3, self.y + 20, self.width - 6, 20))
        # 足
        pygame.draw.rect(screen, BROWN, (self.x + 5, self.y + 35, 8, 5))
        pygame.draw.rect(screen, BROWN, (self.x + 17, self.y + 35, 8, 5))

class Enemy:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 25
        self.height = 25
        self.speed = 2
        self.direction = -1  # -1は左、1は右
        
    def update(self):
        self.x += self.speed * self.direction
        
        # 画面端で方向転換
        if self.x <= 0 or self.x >= WIDTH - self.width:
            self.direction *= -1
            
        # プラットフォームの端で方向転換
        on_platform = False
        for platform in platforms:
            if (self.y + self.height >= platform['y'] and 
                self.y + self.height <= platform['y'] + platform['height'] + 10 and
                self.x + self.width > platform['x'] and 
                self.x < platform['x'] + platform['width']):
                on_platform = True
                break
                
        if not on_platform and self.y + self.height < HEIGHT - 50:
            self.direction *= -1
    
    def draw(self, screen):
        # 敵（茶色のクリボー風）
        pygame.draw.ellipse(screen, BROWN, (self.x, self.y, self.width, self.height))
        # 目
        pygame.draw.circle(screen, WHITE, (self.x + 8, self.y + 8), 3)
        pygame.draw.circle(screen, WHITE, (self.x + 17, self.y + 8), 3)
        pygame.draw.circle(screen, (0, 0, 0), (self.x + 8, self.y + 8), 1)
        pygame.draw.circle(screen, (0, 0, 0), (self.x + 17, self.y + 8), 1)

class Coin:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 20
        self.height = 20
        self.collected = False
        
    def draw(self, screen):
        if not self.collected:
            pygame.draw.circle(screen, YELLOW, (self.x + 10, self.y + 10), 10)
            pygame.draw.circle(screen, (255, 215, 0), (self.x + 10, self.y + 10), 8)

# ゲームオブジェクトの初期化
mario = Mario(50, HEIGHT - 100)

# プラットフォーム
platforms = [
    {'x': 200, 'y': 450, 'width': 150, 'height': 20},
    {'x': 400, 'y': 350, 'width': 150, 'height': 20},
    {'x': 600, 'y': 250, 'width': 150, 'height': 20},
    {'x': 100, 'y': 300, 'width': 80, 'height': 20},
]

# 敵
enemies = [
    Enemy(250, 425),
    Enemy(450, 325),
    Enemy(650, 225),
]

# コイン
coins = [
    Coin(220, 420),
    Coin(270, 420),
    Coin(420, 320),
    Coin(470, 320),
    Coin(620, 220),
    Coin(670, 220),
]

# スコア
score = 0
font = pygame.font.Font(None, 36)

# ゲームループ
running = True
while running:
    # イベント処理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    # キー入力処理
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT] or keys[pygame.K_a]:
        mario.move_left()
    elif keys[pygame.K_RIGHT] or keys[pygame.K_d]:
        mario.move_right()
    else:
        mario.stop_horizontal()
    
    if keys[pygame.K_SPACE] or keys[pygame.K_UP] or keys[pygame.K_w]:
        mario.jump()
    
    # ゲームオブジェクトの更新
    mario.update()
    
    for enemy in enemies:
        enemy.update()
    
    # 衝突判定
    mario_rect = pygame.Rect(mario.x, mario.y, mario.width, mario.height)
    
    # 敵との衝突
    for enemy in enemies:
        enemy_rect = pygame.Rect(enemy.x, enemy.y, enemy.width, enemy.height)
        if mario_rect.colliderect(enemy_rect):
            # ゲームオーバー（リスタート）
            mario.x = 50
            mario.y = HEIGHT - 100
            mario.vel_x = 0
            mario.vel_y = 0
            score = max(0, score - 10)
    
    # コインとの衝突
    for coin in coins:
        if not coin.collected:
            coin_rect = pygame.Rect(coin.x, coin.y, coin.width, coin.height)
            if mario_rect.colliderect(coin_rect):
                coin.collected = True
                score += 10
    
    # 描画
    screen.fill(SKY_BLUE)
    
    # 地面
    pygame.draw.rect(screen, GREEN, (0, HEIGHT - 50, WIDTH, 50))
    
    # プラットフォーム
    for platform in platforms:
        pygame.draw.rect(screen, BROWN, (platform['x'], platform['y'], platform['width'], platform['height']))
    
    # ゲームオブジェクトの描画
    mario.draw(screen)
    
    for enemy in enemies:
        enemy.draw(screen)
    
    for coin in coins:
        coin.draw(screen)
    
    # スコア表示
    score_text = font.render(f"Score: {score}", True, WHITE)
    screen.blit(score_text, (10, 10))
    
    # 操作説明
    controls_text = font.render("←→/AD: Move, Space/↑/W: Jump", True, WHITE)
    screen.blit(controls_text, (10, HEIGHT - 30))
    
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()
```

# 結果
![スクリーンショット 2025-05-28 022948.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4001229/9de6feac-8261-45cf-8276-51ad13b5fc6a.png)

いい感じに動作しました。見た目もぽい。
左上の茶色の台ｈ何目的で作ったんだろう。。

# 感想
- 1回の実行でエラー起こさずに生成できるのがすごい
- 生成のスピードが速いと感じた
- SWE-benchで、GPT-4.1やGemini 2.5 Proを大幅に超える性能を示していただけあって、正確性が高い
- 新しくコードを書きたいときの一発目に使うのが効果を実感できそう