If there is a certain length of code coming before the DT (define table) directive, then characters/entries in the DT past a certain point will fail to return a value. Instead, upon reaching that character, the program will restart from the beginning.
Remember, or realize, that DT is actually a short form for a long list of retlw instructions. That means that having a DT holding a long string counts as many instructions.
This does NOT appear to be an issue of crossing the 2000 line limit, because I counted my lines and each character in the DTs, and I am still a good ways away from the next program memory page.
I spent hours working this out. Our book was not helpful at all. I had many theories and many false leads. Unless we hear official word from someone more experienced, my reccomendation would be to keep your DTs at or near the top of your code.
I forgot, or rather vaguely remembered but was not until recently able to find mention in the book, that tables have limited space per page of program memory. My knowledge worked against me, because knowing that DT is just a series of RETLW instructions made me believe that they were simply instructions. It turns out RETLW is also placed in this table memory.
This partially explains things. The strange thing is, the location of DT should not matter if it is only a case of using up memory. There seems to be something else at play here. I remember reading another blog post or question mentioning something similar to this, but I am a little unclear on the details.