1

first of all, sorry if this is already answered I've looked through past Q's but no luck.

My problem is: I've gone through the Python+libtcod tutorial on Roguebasin once and doing it again while making my own modifications.

I'm trying to make a hardcoded map instead of a randomly generated one.

The code so far will not show a window or anything I'm just running and hope it closes with no errors. BUT, I keep getting this:

Traceback (most recent call last):
  File "superrogue.py", line 85, in <module>
    make_map()
  File "superrogue.py", line 68, in make_map
    if MAP_FILE[x][y] in TILE_NAMES:    #Find the tile's name---
IndexError: string index out of range

The whole "string index out of range" is what I've been beating my head against the wall all afternoon and evening.

Here's the code so far:

#---Imports-------------------------------------------------------------
import libtcodpy as libtcod

#---Program Labelings---------------------------------------------------
TITLE = 'Roguetest'
VERSION = '0.01a'

#---Setup Variables-----------------------------------------------------
SCREEN_WIDTH = 80
SCREEN_HEIGHT = 50
LIMIT_FPS = 20
#MAP_FILE = open('Maps/Test.txt', 'r')
#MAP_FILE = MAP_FILE.readlines()
MAP_FILE = ['XXXX',
            'X==X',
            'X..X',
            'X..X',
            'X==X',
            'XXXX',
            ]
MAP_WIDTH = len(MAP_FILE[0])
print MAP_WIDTH
MAP_HEIGHT = len(MAP_FILE)
print MAP_HEIGHT


#---Dictionaries--------------------------------------------------------------
COLORS = {
            'dark_new' : libtcod.Color(255, 0, 255),
            'light_new' : libtcod.Color(255, 0, 255),
            'dark_pavement' : libtcod.Color(20, 20, 20),
            'light_pavement' : libtcod.Color(50, 50, 50),
            'dark_sidewalk' : libtcod.Color(80, 80, 80),
            'light_sidewalk' : libtcod.Color(120, 120, 120),
            'dark_wall' : libtcod.Color(100, 100, 100),
            'light_wall' : libtcod.Color(180, 180, 180)
            }

TILE_NAMES = {
                'X' : 'wall',
                '.' : 'pavement',
                '=' : 'sidewalk'
                }

#---Classes-------------------------------------------------------------
class Tile:
    def __init__(self, name):
        self.name = name
        self.darkcolor = COLORS['dark_' + self.name]
        self.lightcolor = COLORS['light_' + self.name]
        self.blocks = False
        self.blocks_sight = False
        self.inside = False


#---Functions-----------------------------------------------------------
def make_map():

    map = [[ Tile(name='new')
        for x in range(MAP_WIDTH) ]
            for y in range(MAP_HEIGHT) ]

    for x in range(MAP_WIDTH):
        for y in range(MAP_HEIGHT):
            print (x, y)
            if MAP_FILE[x][y] in TILE_NAMES:    #Find the tile's name---
                map[x][y].name = TILE_NAMES[MAP_FILE[x][y]]

            map[x][y].darkcolor = COLORS['dark_' + map[x][y].name]
            map[x][y].lightcolor = COLORS['light_' + map[x][y].name]

            if MAP_FILE[x][y] == 'X':   #The WALL tile------------------
                map[x][y].blocked = True
                map[x][y].block_sight = True
            elif MAP_FILE[x][y] == '.': #The PAVEMENT tile--------------
                map[x][y].blocked = False
                map[x][y].block_sight = False
            elif MAP_FILE[x][y] == '=': #The SIDEWALK tile--------------
                map[x][y].block_sight = False
                map[x][y].ped_walkable = True


make_map()

Thanks.

YAS
  • 363
  • 2
  • 6
  • 9
  • This can't be your actual code. MAP_FILE has a , on the last line which would result in a syntax error. Also, what does your print of MAP_HEIGHT and MAP_WIDTH show along with the x,y printed right before the exception? – gfortune Feb 04 '12 at 06:28
  • 2
    Actually, trailing commas are legal in lists. – tzaman Feb 04 '12 at 06:32
  • Gah, sure enough. Must be SQL clouding my brain. Regardless, I'm pretty certain that's not the actual code he's running and it would be immensely useful to see the index and length numbers that he's printing. – gfortune Feb 04 '12 at 06:40
  • @gfortune: you could try running it... you'll need to blank out the libtcod.Color stuff if you don't have the libtcodpy module, but that's not hard. Or run it in your brain and you'll see why it's going wrong. – Chris Morgan Feb 04 '12 at 06:44

1 Answers1

7

y is getting up to len(MAP_HEIGHT) - 1 (because of the range call); MAP_HEIGHT = len(MAP_FILE); MAP_FILE is a list with six elements.

Thus y will take the values 0, 1, 2, 3, 4, 5. However, the string only has four values, so trying to access the fifth or sixth character will fail.

I think you've tangled map height and map width (it's indexed by [y][x] and you access it by [x][y]).

Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
  • Oh, sure enough. The way his map is setup, I think his list is indexing as map[y][x] instead of map[x][y] – gfortune Feb 04 '12 at 06:46
  • Good catch, x and y are swapped indeed. – Niall Byrne Feb 04 '12 at 06:49
  • So, if I understand it right, the list looks like it is 4 wide and 6 high but is indexed as 6 wide and 4 high? – YAS Feb 04 '12 at 06:59
  • @YAS: you're trying to access it as though it's 6 wide and 4 high. The structure is indexed first by height, then by width, whereas you are trying to access it the other way. If you switch the `[x][y]` to `[y][x]` (and swap the positions of the x and y loops for logic's sake and also, I think, to increase performance), it'll fix it. – Chris Morgan Feb 04 '12 at 07:03
  • The outer portion of the list (`map[i]`) gives you rows. Picking a particular row (`map[i]`) is the same as picking the "y" coordinate. Once you've picked a row, the item inside the row is the column (`map[i][j]`) and picking a column corresponds to picking the "x" coordinate. Does that help? – gfortune Feb 04 '12 at 07:05