3

I have the following code rendering the display for my roguelike game. It includes rendering the map.

  def render_all(self):
    for y in range(self.height):
      for x in range(self.width):
        wall = self.map.lookup(x,y).blocked
        if wall:
          self.main.addch(y, x, "#")
        else:
          self.main.addch(y, x, ".")
    for thing in self.things:
      draw_thing(thing)

It errors out every time. I think it's because it's going off the screen, but the height and width variables are coming from self.main.getmaxyx(), so it shouldn't do that, right? What am I missing? Python 3.4.3 running in Ubuntu 14.04 should that matter.

Jonathanb
  • 1,224
  • 1
  • 11
  • 16

1 Answers1

4

That's expected behavior. Python uses ncurses, which does this because other implementations do this.

In the manual page for addch:

The addch, waddch, mvaddch and mvwaddch routines put the character ch into the given window at its current window position, which is then advanced. They are analogous to putchar in stdio(3). If the advance is at the right margin:

  • The cursor automatically wraps to the beginning of the next line.

  • At the bottom of the current scrolling region, and if scrollok is enabled, the scrolling region is scrolled up one line.

  • If scrollok is not enabled, writing a character at the lower right margin succeeds. However, an error is returned because it is not possible to wrap to a new line

Python's curses binding has scrollok. To add characters without scrolling, you would call it with a "false" parameter, e.g.,

self.main.scrollok(0)

If you do not want to scroll, you can use a try/catch block, like this:

import curses

def main(win):
  for y in range(curses.LINES):
    for x in range(curses.COLS):
      try:
        win.addch(y, x, ord('.'))
      except (curses.error):
        pass
      curses.napms(1)
      win.refresh()
  ch = win.getch()

curses.wrapper(main)
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • So what do I do if I want to put a character at the lower right margin without scrolling? – Jonathanb Jun 07 '16 at 12:45
  • No advice @Thomas Dickey? How do I write to the bottom-right margin without crashing? Wrap it in a try/except clause? But what if there is another, legitimate curses error? – Jonathanb Jun 22 '16 at 09:38
  • `addch` would return an error if the window is a null pointer, but that's unlikely. A try/catch around `addch` seems your only solution (making a special case to do this only at the lower-right corner would add clutter). – Thomas Dickey Jun 23 '16 at 00:31
  • Ok, I'm trying to use try/except but it's not working. Here's the code: try: self.main.addch(thing.y, thing.x, thing.disp, curses.color_pair(self.color_palette[thing.color])) except _curses.error: pass It says that _curses is not defined. But when I run it outside the block, the error message it gives me is _curses.error: add_wch() returned ERR. ERR doesn't work either. – Jonathanb Jun 26 '16 at 07:45