Q:

Quero mudar uma string em 3 posições

Gostaria de andar 3 posições com uma letra de uma string, por exemplo, fazer a letra A virar D, eu tentei o segundo comando:
texto[c] = texto[c] + 3

Porém ainda não funciona, qual seria o jeito correto de fazer?

A:

Se eu entendi, você quer fazer algo parecido com a cifra de Cesar. Dada uma string, você precisa andar com cada caractere mais 3 posições.
Você pode usar uma alfabeto de base, em python ele já está implementado por default em string
from string import ascii_lowercase as alfabeto

assim você pode ter uma base para rotacionar. Beleza, temos uma base de strings. Então vamos pegar uma string para colocar no jogo:
string = 'stack'

As string tem um método chamado .index que vai te dar a posição de cada caractere. Por exemplo:
alfabeto.index('a')
# 0

assim você pode somar mais 3 e obter uma nova posição. No mesmo caso:
alfabeto[alfabeto.index('a') + 3]
# 'd'

Nesse caso, você pode iterar na string que quer rotacionar
for letra in 'stack':
    print(alfabeto[alfabeto.index(letra) + 3)
# 'v'
# 'w'
# 'd'
# 'f'
# 'n'

Dessa maneira você teria uma string toda rotacionada. Porém, existem alguns problemas, como se você tentar rotacionar 'z'
for letra in 'zzz':
    print(alfabeto[alfabeto.index(letra) + 3])
# IndexError: string index out of range

Porque sua string não tem uma posição maior do que 'z'. Então você poderia fazer um módulo usando o tamanho do seu alfabeto.
for letra in 'zzz':
    print(alfabeto[(alfabeto.index(letra) + 3)% len(alfabeto)])
#'c'
#'c'
#'c'

O que faria você sempre rodar o alfabeto todo somando mais três e iniciando com o mesmo caso ele estoure o tamanho da sua lista.
''.join([alfabeto[(alfabeto.index(letra) + 3)% len(alfabeto)] for letra in 'stackzz'])
# 'vwdfncc'

A:

Você tem que converter para número para fazer a conta (com ord()) e depois converter para caractere de novo (com chr()), assim:
def DeslocaASCII(texto):
    novoTexto = ''
    for letra in texto:
        numero = ord(letra)
        novoTexto += chr(numero + (-23 if numero > 87 else 3))
    return novoTexto
    
print(DeslocaASCII('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))

Veja funcionando no ideone. E no repl.it. Também coloquei no GitHub para referência futura.
Estou considerando que só será enviado um texto com caracteres maiúsculos. A validação do texto entrado deveria ser feita em outro local para manter a responsabilidade única.
Não tentei resolver nada além do que está na pergunta para não especular onde será usado.

