0

The error looks like this:

Traceback (most recent call last):
  File "main.py", line 136, in <module>
    curses.wrapper(main)
  File "/nix/store/p21fdyxqb3yqflpim7g8s1mymgpnqiv7-python3-3.8.12/lib/python3.8/curses/__init__.py", line 105, in wrapper
    return func(stdscr, *args, **kwds)
  File "main.py", line 130, in main
    mainWindow.addstr(0, 0, buildView(windowBorder))
  File "main.py", line 69, in buildView
    newRow += worldRows[charPos[1]][charPos[0]]
IndexError: string index out of range

This program is supposed to take the player position, and print (using curses) the map and the player movement.

If the world DSL looks like this:

world = """
............X.....................................
.......X.......X.......X.........X...........X....
....X......X...X...X...........X.......C.X...X....
.X......X....b...X...X..X...X..X.....X........X...
...X.....................e.............X....X.....
........h..X......X...............................
..............X......X.........X........X...X.....
..X...X.....X....X......X.........................
............X...X......X.......X....d......X......
....X...X.......X...X.....X...........X......X....
.....X....X.X.....X.....X.....X...X...............
..X.X......X.X..a.......................X........
...X...X.........X..X.....g.................X.....
..X.X...X..X....X.........X........f..........X..
..................X....................X..........
"""

and the player's x, y position at start is a tuple (17, 6). The chunk of code constructing the viewport is as follows:

def buildView(border):
    playerView = """"""
    worldRows = [row for row in world.splitlines() if row]
    counterY = -1
    rows = border.splitlines()
    for i, row in enumerate(rows):
        newRow = ""
        if i == 0 or i == len(rows):
            pass
        elif i == 1 or i == len(rows) - 1:
            newRow = row
            newRow += "\n"
        else:
            counterX = -6
            for j, col in enumerate([char for char in row]):
                if col != '#':
                    newRow += col
                else:
                    charPos = (playerPos[0] + counterX,
                               playerPos[1] + counterY)
                    if charPos[0] < 0 or charPos[1] < 0 or charPos[
                            0] > 49 or charPos[1] > 14:
                        newRow += " "
                    else:
                        newRow += worldRows[charPos[1]][charPos[0]]
                    counterX += 1
            newRow += "\n"
        playerView += newRow
        counterY += 1

    temp1 = playerView.splitlines()
    temp2 = [s for s in temp1[2]]
    temp2[7] = "@"
    newtemp = ""
    for i in temp2:
        newtemp += i
    temp2 = newtemp
    temp1[2] = temp2
    thingy = """"""
    for i in temp1:
        thingy += i
        thingy += "\n"
    playerView = thingy
    return playerView

When the program starts, it looks like this:

|=============|
|.X....X......|
|.X...X@.....X|
|.....X...X...|
|=============|

when the player types either w, a, s, or d, the player's xy is updated according to the direction they are moving, but after moving twenty six spaces to the right (player's x coord is += 26), I get the above error. Does anyone see something Im missing?

what I expect to see is this:

|=============|
|......X......|
|.X....@.X....|
|.............|
|=============|

and the player's xy coords should be (9, 43). The max xy coord of the world is (49, 14).

  • `i == len(rows)` will never be true. `i` ranges from `0` to `len(rows)-1`. – Barmar May 19 '22 at 18:59
  • "but after moving twenty six spaces to the right (player's x coord is += 26), I get the above error." When the player does this, which points on the map do you expect to be displayed? What do you believe should be their indices into the `worldRows` data? What do you believe are the dimensions of this data, and what do you believe are the valid numeric indices for data of those dimensions? – Karl Knechtel May 19 '22 at 19:01
  • Thats what I thought @Bramar, but when I used ```i== len(rows) - 1``` the code acted weird and unexpected. – Alaric Malikov May 19 '22 at 19:02
  • Where the code says `if charPos[0] < 0 or charPos[1] < 0 or charPos[0] > 49 or charPos[1] > 14`, how did you choose the values `49` and `14`? What do you think should happen if `charPos[0]` is *equal to* `49`, or if `charPos[1]` is *equal to* `14`? What do you expect will happen if those values are used to index into `worldRows`? Why? – Karl Knechtel May 19 '22 at 19:02
  • 1
    You handle that case in `elif i == 1 or i == len(rows) - 1:` – Barmar May 19 '22 at 19:02
  • 1
    I'll bet anything you have an off-by-one error in some of those magic numbers. Use variables that specify the size of the grid, and remember that indexes go from 0 to len-1. – Barmar May 19 '22 at 19:04
  • Also, try using functions to organize the code, so that you can think about less code at a time, and have testable, *self-contained*, smaller problems. For example, try writing a function that can create a single `newRow` value. Also, try thinking about how `counterX` and `counterY` relate to `i` and `j`. I think you will find that this part of the logic can be simplified. – Karl Knechtel May 19 '22 at 19:05
  • Another idea for a useful function: given the world data and a coordinate, return the *symbol at that coordinate*, or `' '` if out of bounds. *Use the world data itself* in order to determine what coordinates are out of bounds; don't write numbers like `49` or `14` in this function. – Karl Knechtel May 19 '22 at 19:07
  • Finally: please read https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ and learn how to *test your assumptions*. For example: given that an error occurs because of invalid indices, the *very next debugging step* is: when the exception occurs, what are the indices? As a bare-bones approach, use `try`/`except` to add debugging code for this situation (and re-raise the exception so that the program still stops), and use `print` to check the values of those variables. Make sure you know what values make sense, and why. – Karl Knechtel May 19 '22 at 19:09
  • @JacobIRR the error is with the numbers used to index into `worldRows`, which are successfully retrieved from `charPos`. There is no problem with `charPos`. We can tell because a) the code to create `charPos` occurs immediately before, and is straightforward; b) the exception would be different (it wouldn't say `string index` for a length-0 list or tuple, and it would be a `TypeError` rather than `IndexError` for `None`). – Karl Knechtel May 19 '22 at 19:15
  • Thank you, @KarlKnechtel, I will try the idea of breaking up the code into methods now. I also use the method of writing in a ```raise notImplementedError(...) ``` to see if a chunk of code is even doing anything. Is that also a bad practice? – Alaric Malikov May 19 '22 at 19:55
  • All kinds of things can work for temporary debugging efforts. Just don't put it in your version control unless it's directly part of performing the code's task. – Karl Knechtel May 19 '22 at 20:00
  • I've broken the code up into separate functions as you advised, and even revised some of what it was doing, but it seems to break after every time that I as a user go past x coord of 43 when the Y coord is not reduced. I even checked if the issue was with using those magic numbers. I replaced the check where I use the magic numbers of 14 and 49 with ```len(worldRows[0])``` and ```len(worldRows) - 1```, but it is still giving me the same error. – Alaric Malikov May 19 '22 at 20:15

0 Answers0