Improve and rework this code:

```
import pygame
import random

# Constants
WIDTH, HEIGHT = 600, 600
GRID_SIZE = 20
GRID_WIDTH = WIDTH // GRID_SIZE
GRID_HEIGHT = HEIGHT // GRID_SIZE
FPS = 10

# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)  # New: Portal color

# Directions
UP = (0, -1)
DOWN = (0, 1)
LEFT = (-1, 0)
RIGHT = (1, 0)

# New Mechanics:
PORTALS = True       # Enable/Disable portals
OBSTACLES = True    # Enable/Disable obstacles
SPEED_BOOST = True  # Enable/Disable speed boost
SCORE_MULTIPLIER = True  # Enable/Disable score multipliers

class Snake:
    def __init__(self):
        self.body = [(GRID_WIDTH // 2, GRID_HEIGHT // 2)]
        self.direction = RIGHT
        self.growing = 0

    def move(self):
        head = (self.body[0][0] + self.direction[0], self.body[0][1] + self.direction[1])
        self.body.insert(0, head)
        if self.growing > 0:
            self.growing -= 1
        else:
            self.body.pop()

    def grow(self):
        self.growing += 3  # Grow by 3 segments

    def collides(self, obstacles):
        head = self.body[0]
        return (
            head[0] < 0 or head[0] >= GRID_WIDTH or
            head[1] < 0 or head[1] >= GRID_HEIGHT or
            head in self.body[1:] or head in obstacles
        )

    def draw(self, screen):
        for segment in self.body:
            pygame.draw.rect(screen, GREEN, (segment[0] * GRID_SIZE, segment[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE))

class Food:
    def __init__(self, snake, obstacles, portal1, portal2):
        self.position = self.generate_position(snake, obstacles, portal1, portal2)

    def generate_position(self, snake, obstacles, portal1, portal2):
        while True:
            position = (random.randrange(GRID_WIDTH), random.randrange(GRID_HEIGHT))
            if position not in snake.body and position not in obstacles and position != portal1.position and position != portal2.position:
                return position

    def draw(self, screen):
        pygame.draw.rect(screen, RED, (self.position[0] * GRID_SIZE, self.position[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE))

class Portal:
    def __init__(self, snake, obstacles):
        self.position = self.generate_position(snake, obstacles)

    def generate_position(self, snake, obstacles):
        while True:
            position = (random.randrange(GRID_WIDTH), random.randrange(GRID_HEIGHT))
            if position not in snake.body and position not in obstacles:
                return position

    def draw(self, screen):
        pygame.draw.rect(screen, YELLOW, (self.position[0] * GRID_SIZE, self.position[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE))

class SpeedBoost:
    def __init__(self, snake, obstacles, food, portal1, portal2):
        self.position = self.generate_position(snake, obstacles, food, portal1, portal2)
        self.duration = 10  # Duration in seconds

    def generate_position(self, snake, obstacles, food, portal1, portal2):
        while True:
            position = (random.randrange(GRID_WIDTH), random.randrange(GRID_HEIGHT))
            if position not in snake.body and position not in obstacles and position != food.position and position != portal1.position and position != portal2.position:
                return position

    def draw(self, screen):
        pygame.draw.rect(screen, BLUE, (self.position[0] * GRID_SIZE, self.position[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE))

# Initialize Pygame
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Snake Game")
clock = pygame.time.Clock()

# Game variables
snake = Snake()
obstacles = []  # List to store obstacle positions

# Initialize obstacles before defining food and portals
if OBSTACLES:
    num_obstacles = 10  # Number of obstacles to generate
    for _ in range(num_obstacles):
        while True:
            obstacle = (random.randrange(GRID_WIDTH), random.randrange(GRID_HEIGHT))
            if obstacle not in snake.body:  # Ensure obstacles don't overlap
                obstacles.append(obstacle)
                break

# Initialize portals
if PORTALS:
    portal1 = Portal(snake, obstacles)
    portal2 = Portal(snake, obstacles)

# Initialize food after defining obstacles and portals
food = Food(snake, obstacles, portal1, portal2)

speed_boost_active = False
speed_boost_start_time = 0

speed_boost = None  # Initialize speed boost object

multiplier_active = False
multiplier_start_time = 0
multiplier_duration = 5

score_multiplier = 1
score = 0

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP and snake.direction != DOWN:
                snake.direction = UP
            elif event.key == pygame.K_DOWN and snake.direction != UP:
                snake.direction = DOWN
            elif event.key == pygame.K_LEFT and snake.direction != RIGHT:
                snake.direction = LEFT
            elif event.key == pygame.K_RIGHT and snake.direction != LEFT:
                snake.direction = RIGHT

    snake.move()

    if snake.body[0] == food.position:
        score += 1 * score_multiplier
        snake.grow()
        food.position = food.generate_position(snake, obstacles, portal1, portal2)

        # Generate a speed boost with a 10% chance
        if SPEED_BOOST and random.random() < 0.1 and speed_boost is None:
            speed_boost = SpeedBoost(snake, obstacles, food, portal1, portal2)

        # Activate a score multiplier for a short time (5 seconds) with a 10% chance
        if SCORE_MULTIPLIER and random.random() < 0.1 and not multiplier_active:
            multiplier_active = True
            multiplier_start_time = pygame.time.get_ticks()
            score_multiplier = 2  # Double the score

    # Check for score multiplier duration
    if multiplier_active and pygame.time.get_ticks() - multiplier_start_time > multiplier_duration * 1000:
        multiplier_active = False
        score_multiplier = 1

    # Check for speed boost
    if SPEED_BOOST and speed_boost is not None and snake.body[0] == speed_boost.position:
        speed_boost_active = True
        speed_boost_start_time = pygame.time.get_ticks()
        speed_boost = None  # Remove the speed boost
        FPS = 20

    # Deactivate speed boost after its duration
    if speed_boost_active and pygame.time.get_ticks() - speed_boost_start_time > speed_boost.duration * 1000:
        speed_boost_active = False
        FPS = 10

    if PORTALS and snake.body[0] == portal1.position:
        snake.body[0] = portal2.position
    elif PORTALS and snake.body[0] == portal2.position:
        snake.body[0] = portal1.position

    if snake.collides(obstacles):
        print("Game Over! Score:", score)
        running = False

    # Drawing
    screen.fill(BLACK)

    for obstacle in obstacles:
        pygame.draw.rect(screen, WHITE, (obstacle[0] * GRID_SIZE, obstacle[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE))

    snake.draw(screen)
    food.draw(screen)

    if PORTALS:
        portal1.draw(screen)
        portal2.draw(screen)

    if SPEED_BOOST and speed_boost is not None:
        speed_boost.draw(screen)

    pygame.display.flip()

    clock.tick(FPS)

pygame.quit()
```