commit 14c182a39c10fa8427e5b5ddfe243d62463f614d Author: Sacha Ligthert Date: Mon Oct 17 19:17:22 2022 +0200 Initial Commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..c5628ee --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# emPYre +(should change as soon as the game is more complete) + +## About +EmPYre is an (experimental) python 3 implementation of the old Empire game. + +### Why? +The current port on Ubuntu is slow AF and also the control-scheme like many tools from that era it didn't era very well. (ignoring features we see in modern open-source RTS-games these days) + +# Requirements +* Python 3.4+ + +# Developer notes +TODO: +* Look into how the original version did the battle system ( units vs units vs cities ) +* Look into ASCII, Colours, blinking and other flashy things + * + land + * . sea + * ^ (mountains?) +* Look into nCurses to deal with the interface issues + * Different parts of the screen + * Pop-up a window if something is required? +* Look into how to do this + * Separate the logic from the interface? + * Multiple opponents? + * Multi-player? + * Multi-session multi-player? +* Modern systems + * Waypoints? + * Build-queues? + * Patrols? + +## Combat + +``` while (att_obj->hits > 0 && def_obj->hits > 0) { + if (irand (2) == 0) /* defender hits? */ + att_obj->hits -= piece_attr[def_obj->type].strength; + else def_obj->hits -= piece_attr[att_obj->type].strength; + } +``` + +|Piece|You|Enemy|Moves|Hits|Str|Cost| +| --- | ---| ---| ---| ---| ---| ---| +|Army|A|a|1|1|1|5(6)| +|Fighter|F|f|8|1|1|10(12)| +|Patrol Boat|P|p|4|1|1|15(18)| +|Destroyer|D|d|2|3|1|20(24)| +|Submarine|S|s|2|2|3|20(24)| +|Troop Transport|T|t|2|1|1|30(36)| +|Aircraft Carrier|C|c|2|8|1|30(36)| +|Battleship|B|b|2|10|2|40(48)| +|Satellite|Z|z|10|--|--|50(60)| + +Other details: http://www.catb.org/~esr/vms-empire/vms-empire.html + + +``` +typedef struct piece_attr { + char sname; /* eg 'C' */ + char name[20]; /* eg "aircraft carrier" */ + char nickname[20]; /* eg "carrier" */ + char article[20]; /* eg "an aircraft carrier" */ + char plural[20]; /* eg "aircraft carriers" */ + char terrain[4]; /* terrain piece can pass over eg "." */ + uchar build_time; /* time needed to build unit */ + uchar strength; /* attack strength */ + uchar max_hits; /* number of hits when completely repaired */ + uchar speed; /* number of squares moved per turn */ + uchar capacity; /* max objects that can be held */ + long range; /* range of piece */ +} piece_attr_t; +``` diff --git a/empyre.py b/empyre.py new file mode 100644 index 0000000..02504fb --- /dev/null +++ b/empyre.py @@ -0,0 +1,21 @@ +# Import mapgen +# Import state-engine + + + +# Main loop + # Check if there is a save-file + # Load Gamestate + # Else + # Generate Gamestate + # Generate map+assesories + # Create a fog of war + # Create extra metadata entries: round# movesPlayer movesAI Stats turn(c or p) + + # Look who's turn it is + # If its Computer + # Magic happens here + # else + # Player's turn + # Iterate through cities + # Iterate through units diff --git a/experiments/animateLacunarity.py b/experiments/animateLacunarity.py new file mode 100644 index 0000000..01bb8da --- /dev/null +++ b/experiments/animateLacunarity.py @@ -0,0 +1,28 @@ +from PIL import Image, ImageDraw +import noise + +slides = [] +width=500 +height=500 +#cycles=5948 +cycles=595 +divider=1000 +divider=100 + +for lacu in range(0,cycles): + + print("Lacunarity: "+str(round(lacu/divider,3)) ) + + img = Image.new('RGB', (width,height)) + + for x in range(1,width): + for y in range(1,height): + area = noise.pnoise2( x/128, y/128, octaves=50, persistence=0.5, lacunarity=round(lacu/divider,3), repeatx=width, repeaty=height, base=25 ) + img.putpixel( (int(x),int(y)), round(area*255) ) + + d = ImageDraw.Draw(img) + d.text( (1,1), "Lacunarity: "+str(round(lacu/divider,3)), fill=(255,0,0)) + + slides.append(img) + +slides[0].save("lacunarity.gif", save_all=True, append_images=slides[1:], optimize=True, duration=50, loop=0) diff --git a/experiments/camera.py b/experiments/camera.py new file mode 100644 index 0000000..886bb37 --- /dev/null +++ b/experiments/camera.py @@ -0,0 +1,68 @@ + +# Import 1st party modules +import curses + +# Import my own libraries +from state import State + +gamestate = State() +gamestate.load() + +#print(gamestate.terrain[1][2]) + +def draw_map(stdscr): + # key press + k = 0 + + # Map center + center = {} + center['x'] = round(gamestate.metadata['width']/2) + center['y'] = round(gamestate.metadata['height']/2) + + # Clear and refresh the screen for a blank canvas + stdscr.clear() + stdscr.refresh() + + # Start colors in curses + curses.start_color() + curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_GREEN) # Neutral Land + curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE) # Neutral Sea + curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_GREEN) # Friendly Land + curses.init_pair(4, curses.COLOR_WHITE, curses.COLOR_BLUE) # Friendly Sea + curses.init_pair(5, curses.COLOR_RED, curses.COLOR_GREEN) # Enemy Land + curses.init_pair(6, curses.COLOR_RED, curses.COLOR_BLUE) # Enemy Sea + curses.init_pair(7, curses.COLOR_BLACK, curses.COLOR_BLACK) # Outside of the map + + while (k != ord('q')): + # Initialization + stdscr.clear() + height, width = stdscr.getmaxyx() + + if k == curses.KEY_DOWN: + center['y'] = center['y'] + 1 + elif k == curses.KEY_UP: + center['y'] = center['y'] - 1 + elif k == curses.KEY_RIGHT: + center['x'] = center['x'] + 1 + elif k == curses.KEY_LEFT: + center['x'] = center['x'] - 1 + + for y in range(1,height): + for x in range(1,width): + if gamestate.terrain[x][y] == "l": + stdscr.addstr( y, x, " ", curses.color_pair(1) ) + elif gamestate.terrain[x][y] == "w": + stdscr.addstr( y, x, " ", curses.color_pair(2) ) + + + # Refresh the screen + stdscr.refresh() + + # Wait for next input + k = stdscr.getch() + +def main(): + curses.wrapper(draw_map) + +if __name__ == "__main__": + main() diff --git a/experiments/make_map_animation.py b/experiments/make_map_animation.py new file mode 100644 index 0000000..b85624b --- /dev/null +++ b/experiments/make_map_animation.py @@ -0,0 +1,16 @@ +from map import Map +from PIL import Image, ImageDraw + +slides = [] + +if __name__ == "__main__": + for x in range(1,100): + map = Map(sealevel=x, xoffset=0, yoffset=0) + map.generateMap() +# map.findCoast() +# map.generateCities() +# map.addCities() + #map.printWorld() + slides.append(map.saveWorld()) + + slides[0].save("zlevel_7.gif", save_all=True, append_images=slides[1:], optimize=True, duration=500, loop=0) diff --git a/experiments/make_map_animation_lacunarity.py b/experiments/make_map_animation_lacunarity.py new file mode 100644 index 0000000..c12c348 --- /dev/null +++ b/experiments/make_map_animation_lacunarity.py @@ -0,0 +1,18 @@ +from map import Map +# from PIL import Image, ImageDraw + +slides = [] + +if __name__ == "__main__": + max_scale = 32 + max_lacunarity = 100 + width=150 + height=50 + for lacunarity in range(1,max_lacunarity): + lacunarity = lacunarity/100 + print("Lacunarity: "+str(lacunarity)) + map = Map(scale=32, base=1, width=width, height=height, lacunarity=lacunarity) + map.generateMap() + slides.append(map.saveWorld()) + + slides[0].save("zoom_base1_zoom"+str(max_scale)+"_lacunarity"+str(max_lacunarity)+"_width"+str(width)+"_height"+str(height)+".gif", save_all=True, append_images=slides[1:], optimize=True, duration=40, loop=0) diff --git a/experiments/make_map_animation_shift.py b/experiments/make_map_animation_shift.py new file mode 100644 index 0000000..59c64f1 --- /dev/null +++ b/experiments/make_map_animation_shift.py @@ -0,0 +1,19 @@ +from map import Map +from PIL import Image, ImageDraw + +slides = [] + +if __name__ == "__main__": + max_scale = 64 + lacunarity = 1.5 + for scale in range(32,max_scale): + print("Scale: "+str(scale)) + map = Map(scale=scale, base=1, width=640, height=480, lacunarity=lacunarity) + map.generateMap() +# map.findCoast() +# map.generateCities() +# map.addCities() + #map.printWorld() + slides.append(map.saveWorld()) + + slides[0].save("zoom_base1_zoom"+str(max_scale)+"_lacunarity"+str(lacunarity)+".gif", save_all=True, append_images=slides[1:], optimize=True, duration=150, loop=0) diff --git a/experiments/test.py b/experiments/test.py new file mode 100644 index 0000000..4fc7095 --- /dev/null +++ b/experiments/test.py @@ -0,0 +1,31 @@ +import curses + +from state import State + +k = 0 + +gamestate = State() +gamestate.load() +terrain = gamestate.terrain + +def main(stdscr): + mypad = curses.newpad(62,62) + for y in range(0,62): + mypad.addstr( y, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqerstuvwxyz1234567890") + + mypad_pos = 0 + mypad.refresh(mypad_pos, 0, 5, 5, 10, 30) + + while (k != ord('q')): + mypad.refresh(mypad_pos, 0, 5, 5, 10, 30) + + if k == curses.KEY_DOWN: + mypad_pos += 1 + mypad.refresh(mypad_pos, 0, 5, 5, 10, 60) + elif k == curses.KEY_UP: + mypad_pos -= 1 + mypad.refresh(mypad_pos, 0, 5, 5, 10, 60) + + k = stdscr.getch() + +curses.wrapper(main) diff --git a/gen_map.py b/gen_map.py new file mode 100644 index 0000000..5eb35d3 --- /dev/null +++ b/gen_map.py @@ -0,0 +1,28 @@ +from map import Map +import pickle + +slides = [] + +if __name__ == "__main__": + # Generate the basic map. + map = Map() + map.generateMap() + + # Add the cities + map.findCoast() + map.generateCities() + map.addCities() + + # Print stuff or dump to image + #map.printWorld() + terrain, cities, coast, metadata = map.dumpMap() + gamestate = {} + gamestate['metadata'] = metadata + gamestate['terrain'] = terrain + gamestate['cities'] = cities + gamestate['coast'] = coast + gamestate['units'] = [] + gamestate['fog'] = [] + + pickle.dump(gamestate, open("savegame.empyre_save","wb")) + #gamestate = pickle.load( open( "savegame.empyre", "rb" ) ) diff --git a/loadstate.py b/loadstate.py new file mode 100644 index 0000000..a821be0 --- /dev/null +++ b/loadstate.py @@ -0,0 +1,20 @@ +#from map import Map +from state import State + +if __name__ == "__main__": + gamestate = State() + gamestate.load() + + print(gamestate.metadata) + #print(gamestate.terrain) + #Map.printWorldExt(gamestate.terrain, gamestate.metadata) + + for y in range(1,gamestate.metadata['height']+1): + for x in range(1,gamestate.metadata['width']+1): + if gamestate.terrain[x][y] == "c": + print('\x1b[1;37;42m' + '*' + '\x1b[0m', end='') + elif gamestate.terrain[x][y] == "l": + print('\x1b[1;37;42m' + ' ' + '\x1b[0m', end='') + else: + print('\x1b[1;37;44m' + ' ' + '\x1b[0m', end='') + print(" ") diff --git a/location_test.py b/location_test.py new file mode 100644 index 0000000..6545243 --- /dev/null +++ b/location_test.py @@ -0,0 +1,59 @@ +import curses + +# Import my own libraries +from state import State +gamestate = State() +gamestate.load() + +from render import Render + +# -- Initialize -- +stdscr = curses.initscr() +curses.noecho() +curses.cbreak() +stdscr.keypad(1) +stdscr.notimeout(1) + +# Clear and refresh the screen for a blank canvas +stdscr.clear() +stdscr.refresh() + +height, width = stdscr.getmaxyx() + +curses.start_color() +curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) # Neutral Land +curses.init_pair(2, curses.COLOR_BLUE, curses.COLOR_BLACK) # Neutral Sea +curses.init_pair(3 , curses.COLOR_RED, curses.COLOR_BLACK) # Hostile +curses.init_pair(7, curses.COLOR_BLACK, curses.COLOR_BLACK) # Outside of the map + +#stdscr = Render.renderScreen(stdscr, gamestate, 40, 12) +stdscr = Render.renderScreen(stdscr, gamestate, 75, 25) + +k = 0 +map_focus_x = round(gamestate.metadata['width']/2) +map_focus_y = round(gamestate.metadata['height']/2) +while (k != ord('q')): + + if k == curses.KEY_DOWN: + map_focus_y = map_focus_y + 1 + elif k == curses.KEY_UP: + map_focus_y = map_focus_y - 1 + elif k == curses.KEY_RIGHT: + map_focus_x = map_focus_x + 1 + elif k == curses.KEY_LEFT: + map_focus_x = map_focus_x - 1 + + map_focus_x = max(0, map_focus_x) + map_focus_x = min(gamestate.metadata['width'], map_focus_x) + + map_focus_y = max(0, map_focus_y) + map_focus_y = min(gamestate.metadata['height'], map_focus_y) + + stdscr = Render.renderScreen(stdscr, gamestate, map_focus_x, map_focus_y) + + k = stdscr.getch() + +stdscr.keypad(0) +curses.echo() +curses.nocbreak() +curses.endwin() diff --git a/map.py b/map.py new file mode 100644 index 0000000..772ca77 --- /dev/null +++ b/map.py @@ -0,0 +1,152 @@ +import noise +import random +from collections import defaultdict +import math + +class Map(): + + def __init__( self, width=150, height=50, sealevel=50, scale=32, base=random.randint(1,250), lacunarity=0.5+random.random(), octaves=50, persistence=0.5, xoffset=random.randint(1,10000), yoffset=random.randint(1,10000) ): + + print("Initializing map") + + # Dealing with basic params + self.width = width + self.height = height + self.sealevel = -0.37+((0.75/100)*sealevel) + self.scale = scale + self.base = base + self.octaves = octaves + self.persistence = persistence + self.lacunarity = lacunarity + self.xoffset = xoffset + self.yoffset = yoffset + + # The master map we are going to need + self.map = defaultdict(dict) + self.coast = [] + + # All the required stuff to determine cities + self.cities = [] + # self.num_cities = 50+(100-int(self.sealevel)) + self.num_cities = 75 + self.coast_percentage = 25 + self.distance = 3 + + + def generateMap(self): + print("Generating Map") + # Fill in the blanks with random stuff + for x in range(1,self.width+1): + for y in range(1,self.height+1): + area = noise.pnoise2( self.xoffset+x/self.scale, self.yoffset+y/(self.scale/3), octaves=self.octaves, persistence=self.persistence, lacunarity=self.lacunarity, repeatx=self.height, repeaty=self.width, base=self.base ) + if area > self.sealevel: + self.map[x][y] = "l" + else: + self.map[x][y] = "w" + + + # Find coastal positions + def findCoast(self): + print("Finding coastal tiles") + # Should replace with a range()-loop + y = 1 + + while y <= self.height: + x = 1 + while x <= self.width: + water = 0 + if x !=1 and x!=self.width and y!=1 and y!=self.height and self.map[x][y]=="l": + if self.map[x-1][y-1]=="w": + water += 1 + if self.map[x][y-1]=="w": + water += 1 + if self.map[x+1][y-1]=="w": + water += 1 + if self.map[x+1][y]=="w": + water += 1 + if self.map[x+1][y+1]=="w": + water += 1 + if self.map[x][y+1]=="w": + water += 1 + if self.map[x-1][y+1]=="w": + water += 1 + if self.map[x-1][y]=="w": + water += 1 + if water >= 1: + coords = {} + coords['x'] = x + coords['y'] = y + self.coast.append(coords) + x+=1 + y+=1 + + + def generateCities(self): + print("Generate cities") + for round in range(0,self.num_cities): + if random.randint(1,100) < self.coast_percentage: + self.cities.append(random.choice(self.coast)) + else: + found = 0 + while found == 0: + randX = random.randint(1,self.width) + randY = random.randint(1,self.height) + if self.map[randX][randY]=="l" and self.noCityNear(self.distance,randX,randY): + found = 1 + coords = {} + coords['x'] = randX + coords['y'] = randY + self.cities.append(coords) + + + def noCityNear(self,distance,x,y): + noCityNear = True + counter = 0 + for city in self.cities: + #Lay-Z D-Bug: print( str(counter) +" x:"+ str( abs(city['x']-x) ) +"; y:"+ str( abs(city['y']-y) ) +";") + # This should be an OR, but this takes forever! So this is good enough. + if abs(city['x']-x) gamestate.metadata['width']: + xoffset = round( (width - gamestate.metadata['width'])/2 ) + if height > gamestate.metadata['height']: + yoffset = round( (height-gamestate.metadata['height'])/2 ) + + + # Draw the visible segment of the map + for y in range(1,height): + top_left_x = centerx - round(width/2) + for x in range(1,width-3): + if top_left_y <= 0 or top_left_y > gamestate.metadata['height'] or top_left_x <= 0 or top_left_x > gamestate.metadata['width']: + stdscr.addstr( y-1, x-1, " ", curses.color_pair(7)) + elif gamestate.terrain[top_left_x][top_left_y] == "l": + stdscr.addstr( y-1, x-1, "+", curses.color_pair(1) ) + elif gamestate.terrain[top_left_x][top_left_y] == "w": + stdscr.addstr( y-1, x-1, ".", curses.color_pair(2) ) + elif gamestate.terrain[top_left_x][top_left_y] == "c": + stdscr.addstr( y-1, x-1, "*" ) + top_left_x += 1 + top_left_y += 1 + + +##### Print the horizontal ruler at the bottom of the screen + xruler = "" + xrulery = 0 + xrulerx = 0 + xrulerx_offset = 0 + + + if width > gamestate.metadata['width']: + xrulerx_offset = xoffset + 1 + xrulerx = gamestate.metadata['width'] + elif width < gamestate.metadata['width']: + xrulerx = width + else: + xrulerx = gamestate.metadata['width'] + + + if gamestate.metadata['height']-1 < height-1: + xrulery = yoffset+gamestate.metadata['height'] + else: + xrulery = height-1 + + + skip = 0 + if width > gamestate.metadata['width']: + xruler_start = 0 + xruler_end = gamestate.metadata['width'] + else: + xruler_start = centerx - round(width/2) + xruler_end = (xruler_start + width) - 4 + + for scale in range(xruler_start,xruler_end): + if skip != 0: + skip-=1 + continue + if scale%10 == 0: + skip=len(str(scale))-1 + xruler+=str(scale) + elif str(scale)[-1:]=="5": + xruler+="|" + else: + xruler+="." + stdscr.addstr( xrulery, xrulerx_offset, xruler ) + + +##### Print the verticle ruler + yruler = centery - round(height/2) + yruler_offset = 0 + yrulery = 1 + #yruler = 0 + yrulerx = 0 + + if width > gamestate.metadata['width']: + yrulerx = int((width - gamestate.metadata['width'])/2)+1+gamestate.metadata['width'] + yruler_offset = (width - gamestate.metadata['width'])/2 + elif gamestate.metadata['width'] < width-4: + yrulerx = gamestate.metadata['width'] + else: + yrulerx = width-4 + + while yrulery < height-1 and yrulery-yruler_offset < gamestate.metadata['height'] and yruler <= gamestate.metadata['height']-1: + if yruler >= 0: + if yruler%5==0: + yruler_text = "{: >3}".format( yruler ) + stdscr.addstr( yrulery, yrulerx, yruler_text ) + else: + stdscr.addstr( yrulery, yrulerx, "{: >3}".format(".") ) + yruler+=1 + yrulery+=1 + + # Return stdscr asif nothing happened + return stdscr diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..81d45d7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +noise diff --git a/savegame.empyre_save b/savegame.empyre_save new file mode 100644 index 0000000..8f5e254 Binary files /dev/null and b/savegame.empyre_save differ diff --git a/state.py b/state.py new file mode 100644 index 0000000..4bf1346 --- /dev/null +++ b/state.py @@ -0,0 +1,21 @@ +# This loads/saves and manages the gamestate and can be used to query what is on the tiles + +import pickle + +class State(): + + def __init__(self): + #print("Loading state-engine") + self.gamestate = {} + + def load(self): + self.gamestate = pickle.load( open( "savegame.empyre_save", "rb" ) ) + self.metadata = self.gamestate['metadata'] + self.terrain = self.gamestate['terrain'] + self.cities = self.gamestate['cities'] + self.coast = self.gamestate['coast'] + self.units = self.gamestate['units'] + self.fog = self.gamestate['fog'] + + def save(self): + pickle.dump(self.gamestate, open("savegame.empyre_save","wb")) diff --git a/test.py b/test.py new file mode 100644 index 0000000..91e1b24 --- /dev/null +++ b/test.py @@ -0,0 +1,109 @@ +import curses + +# Import my own libraries +from state import State +gamestate = State() +gamestate.load() + + +# Print (portion of the) map +#def fillMap(stdscr,gamestate): +# for y in range(1,height): +# for x in range(1,width-3): +# if y < 0 or y > gamestate.metadata['height'] or x < 0 or x > gamestate.metadata['width']: +# stdscr.addstr( y-1, x-1, " ", curses.color_pair(7)) +# elif gamestate.terrain[x][y] == "l": +# stdscr.addstr( y-1, x-1, "+", curses.color_pair(1) ) +# elif gamestate.terrain[x][y] == "w": +# stdscr.addstr( y-1, x-1, ".", curses.color_pair(2) ) +# elif gamestate.terrain[x][y] == "c": +# stdscr.addstr( y-1, x-1, "O" ) +# return stdscr + +# -- Initialize -- +stdscr = curses.initscr() +curses.noecho() +curses.cbreak() +stdscr.keypad(1) +stdscr.notimeout(1) + +height, width = stdscr.getmaxyx() + +curses.start_color() +curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) # Neutral Land +curses.init_pair(2, curses.COLOR_BLUE, curses.COLOR_BLACK) # Neutral Sea +curses.init_pair(3 , curses.COLOR_RED, curses.COLOR_BLACK) # Hostile +curses.init_pair(7, curses.COLOR_BLACK, curses.COLOR_BLACK) # Outside of the map + + +# Print (portion of the) map +for y in range(1,height): + for x in range(1,width-3): + if y < 0 or y > gamestate.metadata['height'] or x < 0 or x > gamestate.metadata['width']: + stdscr.addstr( y-1, x-1, " ", curses.color_pair(7)) + elif gamestate.terrain[x][y] == "l": + stdscr.addstr( y-1, x-1, "+", curses.color_pair(1) ) + elif gamestate.terrain[x][y] == "w": + stdscr.addstr( y-1, x-1, ".", curses.color_pair(2) ) + elif gamestate.terrain[x][y] == "c": + stdscr.addstr( y-1, x-1, "O" ) + +#stdscr = fillMap(stdscr, gamestate) + +# Print horizontal ruler +xruler = "" +xrulery = 0 +xrulerx = 0 + +if width < gamestate.metadata['width']: + xrulerx = width +else: + xrulerx = gamestate.metadata['width'] + +if gamestate.metadata['height']-1 < height-1: + xrulery = gamestate.metadata['height']-1 +else: + xrulery = height-1 + +for scale in range(0,100): + xruler += "{:.<10}".format(scale*10) + if (xrulerx - 10) - len(xruler) < 6 : + xruler += str((scale+1)*10) + break +while len(xruler) < width-4 and len(xruler) < gamestate.metadata['width']: + xruler += "." +stdscr.addstr( xrulery, 0, xruler ) + + +# Print the verticle ruler +yruler = 0 +yrulerx = 0 + +if gamestate.metadata['width'] < width-4: + yrulerx = gamestate.metadata['width'] +else: + yrulerx = width-4 + +while yruler < height-1 and yruler < gamestate.metadata['height']: + if yruler%5==0: + yruler_text = "{: >3}".format( yruler ) + stdscr.addstr( yruler, yrulerx, yruler_text ) + else: + stdscr.addstr( yruler, yrulerx, "{: >3}".format(".") ) + yruler+=1 + + +#stdscr.addstr( 1, 22, "a", curses.color_pair(3)) +#stdscr.addstr( 5, 5, "p", curses.color_pair(3)) + + +while True: + # stay in this loop till the user presses 'q' + ch = stdscr.getch() + if ch == ord('q'): + break + +stdscr.keypad(0) +curses.echo() +curses.nocbreak() +curses.endwin()