Вопрос: Где и как можно оптимизировать код?

Лучший ответ: Дружище, это кошмар. И в нём виноват не ты, а составители задания, которые обрекли тебя это слепить.
Эта игра состоит в том чтобы пройти по дереву сюжетов, делая выбор той или иной ветви.
Умеешь ли ты строить дерево? Умеешь ли обходить? Умеешь ли хранить/редактировать? Нет, нет, нет. И ты выкрутился, как мог. Молодец, а теперь смотри

Хранить дерево будем в файле 'kolobok.yaml':
intro: "Испеки мне колобок"
choise:
  - "по сусекам поскреби":
      intro: "испекла. Что сделал колобок"
      choise:
        - "покатился с окна на заваленку":
            intro: "встретил зайца"
            choise:
              - "я тебе песенку спою":
                  intro: "спел песенку, а навстречу волк"
                  choise:
                    - "я уже чёрствым стал":
                        final: "Волк поломал зубы"
                    - "отнеси к дедушке с бабушкой":
                        final: "Волк бросил колобка в речку"
                    - "я тебе песенку спою":
                        final: "колобок встретил медведя"
              - "попробуй меня догнать":
                intro: "прошмыгнул между ног зайца"
              - "Не успел ответить":
                final: "заяц его съел"
        - "скатился на лавку"
        - "остался остывать на окне"
  - "свари мне каши":
    final: "Старуха сварила кашу"
  - "пойду на базар":
    final: "медведь его съел"
Движок мог бы быть примерно таким:
import yaml

with open('kolobok.yaml') as f:
    root = yaml.load(f, Loader=yaml.FullLoader)


def dfs(d):
    if 'intro' in d:
        print(d['intro'])
    if 'final' in d:
        print(d['final'])
        exit(0)
    if 'choise' in d:
        print('выберите цифру ответа')
        choise = d['choise']
        for i, p in enumerate(choise, 1):
            print(i, next(iter(p)) if type(p) is dict else p)
        while True:
            try:
                answer = input()
                i = int(answer) - 1
                if not 0 <= i < len(choise):
                    raise ValueError
            except ValueError:
                print(f'ответ "{answer}" не поддерживается, пробуй ещё:')
            p = choise[i]
            if type(p) is dict:
                dfs(p.popitem()[1])
            else:
                print(p)
                exit(0)


dfs(root)
Сколь-нибудь долгий путь, 4 сцены - лишь по ветке 1 -> 1 -> 1 -> 1, вбивать всё недосуг.
Про YAML, DFS  и прочие штуки можно найти в интернете.

Худший ответ: Возможные изменения (скорее не в плане читаемости,  а как можно было бы сделать по самой структуре программы).

Лучше избавиться от использования глобалов, а просто возвращать результат ответа. А варианты ответа задавать не как сплошной текст рассказа, а отдельным списком. Это позволит сделать проверку ответа более универсальной (т.к. мы знаем количество возможных вариантов ответа, то нам не нужна цепочка elif).
# принимаем как текст нового абзаца, так и список ответов
def select(fable, answers):
    print(fable)
    print('\n'.join(answers))

    while True:
        # можно добавить проверку ввода букв вместо цифр
        answer = int(input())
        # т.к. мы знаем кол-во вариантов ответов, то сразу можем проверить валидность
        # аналогично можно добавить и другие проверки
        if answer > len(answers):
            print('Неверный ответ, будь внимательнее')
        else:
            break
    # возвращаем результат ответа, не нужны глобалы
    return answer

# и в основной программе соответственно разделяем текст и ответы
fable = "Жили-были старик со старухой. Вот и просит старик\n   - Испеки мне, старая, колобок.\n   - Да из чего испечь-то? муки нет.\nЧто ответит дед?(выберите цифру ответа):"

# при желании из текста ответа можно и удалить жестко прописанные номера.
# т.к. это у нас список, то мы ведь их можем сгенерировать налету перед печатью
answers = ["Ты по амбару подмети, по сусекам поскреби - вот и наберёшь муки (1) ", "Ну ладно, свари мне тогда каши (2) ", "Ладно, пойду на базар, куплю муки, тогда и испечёшь (3) "]

# и собственно запускаем опрос по первому абзацу
answer = select(fable, answers)
# полученный номер ответа уже используем в дальнейшей проверке

if answer == 1:
# аналогично формируем запрос по следующему абзацу, и т.д.