I'm giving myself a headache trying to implement a player-focussed scrolling map, rather than a static map that the player moves around on. I'm not even trying anything fancy like saving/loading new areas - I'm trying the simplest possible form (I hope)!

I've got my gameworld map, BigMap, which is a multidimensional list of Tiles - BigMap[500][500], for example, contains 250,000 Tiles.
One of these Tiles contains the player character, 'player'. Player has, as a property, the Tile that it is in. The Tile has the player as a property (because it contains it).
Given that BigMap is 500 by 500 characters, I obviously need a smaller section of that map to display on a typical 81-by-43 character screen (for example). I call this VisMap. It too is a multidimensional list (i.e. VisMap[81][43]) which contains those Tiles that are meant to be displayed on screen at any given time.
Traditionally Awful Paint Representation:
Now, I want VisMap to be centred on the player. I therefore need to do a transformation to take the coordinates of the player's Tile (on BigMap), and from that calculate which Tiles in BigMap belong in VisMap, and in what position.
I thought I'd cracked this, but turns out my 3am brain is evidently a little dull, because it's not working as expected. The code I have for the transformation (and subsequent rendering of the visual map) is this:
#-------------------------------------------------------------------------------
# Rendering
#-------------------------------------------------------------------------------
def render_all(visual_map, player_action):
"""Draws all tiles within visual_map."""
#refresh the visual_map - set the tiles equal to new tiles if needed
if not player_action == 'didnt-take-turn': #don't update if no movement
for x in range(len(visual_map)):
for y in range(len(visual_map[x])):
visual_map[x][y] = player.map[player.Tile.x + x + ((VISI_WIDTH-1)/2) - VISI_WIDTH][player.Tile.y + y + ((VISI_HEIGHT-1)/2) - VISI_HEIGHT]
##print "Refreshed X"+str(x)+" Y"+str(y)+"!"
if player.Tile == visual_map[x][y]:
print "Player BigMap X"+str(player.Tile.x)+" Y"+str(player.Tile.y)+"."
print "Player VisMap X"+str(x)+" Y"+str(y)+"."
#now draw the visual map
for x in range(len(visual_map)):
for y in range(len(visual_map[x])):
visual_map[x][y].draw(x,y,con)
# blit the console
libtcod.console_blit(con,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,0)
In this, VISI_HEIGHT and VISI_WIDTH are the dimensions of the displayed map (i.e. 41 and 83), if that wasn't obvious.
What I get when I render this is, indeed, a screen of the map:
...but moving the player, while apparently working fine on BigMap, is not represented correctly on VisMap. For example, moving one step to the right...
...successfully increases the X value on BigMap by one (see messages at the bottom), and the X value on VisMap remains at 41 (as it should, as the player should still be centred on the screen), but visually what happens is that the entire view shifts one character to the left, so the player (and the map) appear to be drifting off towards the left of the window.
I'm sure I've made some stupidly simple error here, and I just
know that I'll spot it as soon as I click Post and feel like an idiot.

I've been staring at this for too long to be able to see exactly where I've screwed up. I need more caffeine. Sigh.
Edit: okay, weirder and weirder, moving the player UP or DOWN behaves differently to moving them left or right. BigMap coordinates change as expected, VisMap coordinates stay the same as expected, but visually the player character moves up and down the screen while the tiles appear to stay in the same place...like a normal, non-scrolling map. *headdesk*
Edit 2: right, I've now managed to fix the above problems my somewhat simplifying the code (hooray!) I now have my little @ wandering merrily around the Tiles that I've designated as floor tiles. When I get my @ to step off the floor tiles into the vacuum of space, however, suddenly every tile that is designated as vacuum (rather than floor) starts to display as @s.
...well, it's an improvement, at least!