3
\$\begingroup\$

I started making a game in curses, but I feel like I am displaying the map inefficiently and ineffectively.

Here's the code (only the relevant parts):

import curses world_map = [ '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000011111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000011111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000011111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000111111111111111111110000000000000000000000000000000001111111111111111111111111000000000000000000000000000', '00000000000000000111111111111111111111000000000000000000000000000001111111111111111111111111000000000000000000000000000', '00000000000000000011111111111111111000000000000000000000000000000001111133333111111111111111000000000000000000000000000', '00000000000000000000011111111111100000000000000000000000000000000001111133333111111111111111000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000001111133333111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000001111133333111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000001111133333111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000011111111111111111133333111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000011111111111111111133333111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000011111111111111111111111111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111000000000000000000000000000', '00000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111000000000000000000000000000', '00000000000000001111111111111111111111111000000000000011111111111110000000000000000000000000000000000000000000000000000', '00000000000000001111111111111111111111111000000000000011111111111110000000000000000000000000000000000000000000000000000', '00000000000000001114444411111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000001114444411111115555555111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000001114444411111115555555111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000001114444411111115555555111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000001111111111111115555555111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000001111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'] def win(stdscr): curses.init_color(255, 0, 0x64 * 1000 // 0xff, 0) curses.init_color(254, 0xff * 1000 // 0xff, 0xff * 1000 // 0xff, 0xff * 1000 // 0xff) curses.init_color(253, 0x82 * 1000 // 0xff, 0x8c * 1000 // 0xff, 0x51 * 1000 // 0xff) curses.init_color(252, 0xff * 1000 // 0xff, 0xe4 * 1000 // 0xff, 0xb5 * 1000 // 0xff) curses.init_color(251, 0xc0 * 1000 // 0xff, 0xc0 * 1000 // 0xff, 0xc0 * 1000 // 0xff) curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLUE) # water curses.init_pair(2, curses.COLOR_RED, curses.COLOR_GREEN) # grass curses.init_pair(3, curses.COLOR_RED, 255) # trees curses.init_pair(4, curses.COLOR_RED, 254) # mountains curses.init_pair(5, curses.COLOR_RED, 253) # swamp curses.init_pair(6, curses.COLOR_RED, 252) # desert curses.init_pair(7, curses.COLOR_RED, 251) # village colors = [curses.color_pair(1), curses.color_pair(2), curses.color_pair(3), curses.color_pair(4), curses.color_pair(5), curses.color_pair(6), curses.color_pair(7)] while True: for i in range(30): for j in range(119): stdscr.addch(i, j, ' ', colors[int(world_map[i][j])]) stdscr.refresh() def main(): curses.wrapper(win) if __name__ == '__main__': main() 

Running this produces this window: enter image description here (if you couldn't tell it's just a test)

Is there a better way I could be doing this?

\$\endgroup\$
1
  • \$\begingroup\$If the water is the char that appears the most you can first fill the screen with it and than color only the things that are not water. You can also compare the prev frame to the curr frame and color only the differences, it might seem slow but actually most of the time here is wasted on IO and coloring operations.\$\endgroup\$
    – Yonlif
    CommentedJul 23, 2021 at 9:16

1 Answer 1

3
\$\begingroup\$

Here's a slight refactoring of your code to improve readability and reduce repetitiveness. (I don't think anything I'm doing here will do much for you in terms of performance, sadly.)

import curses as c from itertools import product world_map = [ '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000011111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000011111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000011111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000111111111111111111110000000000000000000000000000000001111111111111111111111111000000000000000000000000000', '00000000000000000111111111111111111111000000000000000000000000000001111111111111111111111111000000000000000000000000000', '00000000000000000011111111111111111000000000000000000000000000000001111133333111111111111111000000000000000000000000000', '00000000000000000000011111111111100000000000000000000000000000000001111133333111111111111111000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000001111133333111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000001111133333111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000001111133333111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000011111111111111111133333111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000011111111111111111133333111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000011111111111111111111111111111111222211000000000000000000000000000', '00000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111000000000000000000000000000', '00000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111000000000000000000000000000', '00000000000000001111111111111111111111111000000000000011111111111110000000000000000000000000000000000000000000000000000', '00000000000000001111111111111111111111111000000000000011111111111110000000000000000000000000000000000000000000000000000', '00000000000000001114444411111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000001114444411111115555555111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000001114444411111115555555111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000001114444411111115555555111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000001111111111111115555555111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000001111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' ] colors_for_initialising = [ (n, *((i * 1000 // 0xff) for i in rgb)) for n, *rgb in ( (255, 0, 0x64, 0), (254, 0xff, 0xff, 0xff), (253, 0x82, 0x8c, 0x51), (252, 0xff, 0xe4, 0xb5), (251, 0xc0, 0xc0, 0xc0) ) ] RED, BLUE, GREEN = c.COLOR_RED, c.COLOR_BLUE, c.COLOR_GREEN color_pairs = ( (1, RED, BLUE), # water (2, RED, GREEN), # grass (3, RED, 255), # trees (4, RED, 254), # mountains (5, RED, 253), # swamp (6, RED, 252), # desert (7, RED, 251) # village ) def win(stdscr): for color in colors_for_initialising: c.init_color(*color) for color_pair in color_pairs: c.init_pair(*color_pair) colors = [c.color_pair(i) for i in range(1, 8)] while True: for i, j in product(range(30), range(119)): stdscr.addch(i, j, ' ', colors[int(world_map[i][j])]) stdscr.refresh() def main(): c.wrapper(win) if __name__ == '__main__': main() 

Summary of the changes I've made here:

  • Introduced an alias for curses (c) to make the code more concise. You can debate whether this change makes the code more or less readable — when you're using a module heavily, such as in this example, I generally prefer to use a shorter alias rather than having to type out the whole module name each time.
  • Also introduced aliases for curses.COLOR_RED, curses.COLOR_BLUE and curses.COLOR_GREEN later on in the code, for the same reason. Out of these three, only curses.COLOR_RED was used more than once, but I introduced aliases for the other two as well so as to keep the naming of colors consistent.
  • In your win function, you were calling curses.init_color and curses.init_pair repeatedly, which led to some repetitive code. I took the arguments for these calls out of win and put them into the global namespace, then abstracted your series of calls to init_color and init_pair into two for-loops in win.
  • I changed your colors list in win from a list-literal to a list-comprehension, making the code less repetitive, more concise and more readable.
  • I took out your nested for-loop in win and replaced it with a call to itertools.product, which does the same thing but is more concise and (arguably) more readable.
\$\endgroup\$
0

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.