Initial Commit
This commit is contained in:
commit
14c182a39c
72
README.md
Normal file
72
README.md
Normal file
@ -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;
|
||||
```
|
21
empyre.py
Normal file
21
empyre.py
Normal file
@ -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
|
28
experiments/animateLacunarity.py
Normal file
28
experiments/animateLacunarity.py
Normal file
@ -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)
|
68
experiments/camera.py
Normal file
68
experiments/camera.py
Normal file
@ -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()
|
16
experiments/make_map_animation.py
Normal file
16
experiments/make_map_animation.py
Normal file
@ -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)
|
18
experiments/make_map_animation_lacunarity.py
Normal file
18
experiments/make_map_animation_lacunarity.py
Normal file
@ -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)
|
19
experiments/make_map_animation_shift.py
Normal file
19
experiments/make_map_animation_shift.py
Normal file
@ -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)
|
31
experiments/test.py
Normal file
31
experiments/test.py
Normal file
@ -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)
|
28
gen_map.py
Normal file
28
gen_map.py
Normal file
@ -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" ) )
|
20
loadstate.py
Normal file
20
loadstate.py
Normal file
@ -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(" ")
|
59
location_test.py
Normal file
59
location_test.py
Normal file
@ -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()
|
152
map.py
Normal file
152
map.py
Normal file
@ -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)<self.distance and abs(city['y']-y)<self.distance:
|
||||
noCityNear = False
|
||||
counter+=1
|
||||
return noCityNear
|
||||
|
||||
|
||||
def calcDistance(self,city,x,y):
|
||||
return math.ceil( math.sqrt( ((city['x']-x)**2)+((city['y']-y)**2) ) )
|
||||
|
||||
|
||||
def addCities(self):
|
||||
print("Adding cities to map")
|
||||
for city in self.cities:
|
||||
self.map[city['x']][city['y']] = "c"
|
||||
|
||||
|
||||
# Print the world in its entirety
|
||||
# Per column we print the entire row
|
||||
def printWorld(self):
|
||||
print("Printing map: num_cities:"+str(self.num_cities)+" base:"+str(self.base)+" Offset:"+str(self.xoffset)+"/"+str(self.yoffset))
|
||||
for y in range(1,self.height+1):
|
||||
for x in range(1,self.width+1):
|
||||
if self.map[x][y] == "c":
|
||||
print('\x1b[1;37;42m' + '*' + '\x1b[0m', end='')
|
||||
elif self.map[x][y] == "l":
|
||||
print('\x1b[1;37;42m' + ' ' + '\x1b[0m', end='')
|
||||
else:
|
||||
print('\x1b[1;37;44m' + ' ' + '\x1b[0m', end='')
|
||||
print("")
|
||||
|
||||
# Dump the map that Python can work with
|
||||
def dumpMap(self):
|
||||
terrain = self.map
|
||||
metadata = {}
|
||||
metadata['width'] = self.width
|
||||
metadata['height'] = self.height
|
||||
metadata['coast_percentage'] = self.coast_percentage
|
||||
metadata['scale'] = self.scale
|
||||
metadata['base'] = self.base
|
||||
metadata['octaves'] = self.octaves
|
||||
metadata['persistence'] = self.persistence
|
||||
metadata['lacunarity'] = self.lacunarity
|
||||
metadata['xoffset'] = self.xoffset
|
||||
metadata['yoffset'] = self.yoffset
|
||||
return terrain, self.cities, self.coast, metadata
|
86
notes.txt
Normal file
86
notes.txt
Normal file
@ -0,0 +1,86 @@
|
||||
The world is a rectangle 60 by 100 squares on a side. The world consists of sea (.), land (+), uncontrolled cities (*), computer-controlled cities (X), and cities that you control (O).
|
||||
|
||||
Starting options:
|
||||
Enemy Start:
|
||||
- Entrenched enemy (default)
|
||||
- 1 vs 1 (second stage)
|
||||
Fog of War: 0) 100% intel 1) knows map 2) Fog of War + sees units 3) Fog of War + blind without units
|
||||
MapSize: x,y
|
||||
Message Delay
|
||||
# WaterPercentage
|
||||
# Smoothness
|
||||
|
||||
|
||||
Storing data
|
||||
pickle-file:
|
||||
Units:
|
||||
Unit:
|
||||
Type
|
||||
Side
|
||||
Location
|
||||
Action
|
||||
Order
|
||||
Cities:
|
||||
City:
|
||||
Location
|
||||
Side
|
||||
Order
|
||||
Stage
|
||||
Terrain:
|
||||
x
|
||||
y
|
||||
type
|
||||
|
||||
numpad keys:
|
||||
49 t/m 57
|
||||
|
||||
Keys:
|
||||
c: cities
|
||||
p: pause
|
||||
b: build
|
||||
a: army
|
||||
f: fighter
|
||||
p: patrol boat
|
||||
d: destoryer
|
||||
s: submarine
|
||||
t: troop transport
|
||||
c: aircraft carrier
|
||||
b: battleship
|
||||
z: Satellite
|
||||
u: units
|
||||
direction: move/attack/load
|
||||
u+l: unload (for transport/carrier)
|
||||
s: entry/sleep
|
||||
w: waypoint (tells unit to move to x position)
|
||||
n: give AI x turns
|
||||
g: give AI 1 turn
|
||||
q: save and quit
|
||||
l: log
|
||||
|
||||
sealevel: -0.37 = 0.38
|
||||
|
||||
-------------------------------
|
||||
Layers:
|
||||
Fog of War - Black
|
||||
Fog of War - Unit-Intel
|
||||
Units - Atmosphere
|
||||
Cities
|
||||
Units - Sky
|
||||
Units - Group
|
||||
Terrain
|
||||
-------------------------------
|
||||
# from PIL import Image, ImageDraw
|
||||
|
||||
# def saveWorldToImage(self):
|
||||
# img = Image.new('RGB', (self.width,self.height))
|
||||
# for y in range(1,self.height+1):
|
||||
# for x in range(1,self.width+1):
|
||||
# if self.map[x][y] == "c":
|
||||
# img.putpixel( (x-1,y-1), (255,0,0) )
|
||||
# elif self.map[x][y] == "l":
|
||||
# img.putpixel( (x-1,y-1), (0,255,0) )
|
||||
# else:
|
||||
# img.putpixel( (x-1,y-1), (0,0,255) )
|
||||
# d = ImageDraw.Draw(img)
|
||||
# d.text( (1,1), "SL: "+str(self.sealevel))
|
||||
# return img
|
114
render.py
Normal file
114
render.py
Normal file
@ -0,0 +1,114 @@
|
||||
# Render the window
|
||||
|
||||
import curses
|
||||
|
||||
class Render():
|
||||
|
||||
def __init__(self):
|
||||
print("Starting Render-Engine")
|
||||
|
||||
|
||||
def renderScreen(stdscr, gamestate, centerx, centery):
|
||||
|
||||
# Calculate what to render
|
||||
# Get screen y and x
|
||||
height, width = stdscr.getmaxyx()
|
||||
|
||||
top_left_x = centerx - round(width/2)
|
||||
top_left_y = centery - round(height/2)
|
||||
|
||||
xoffset = 0
|
||||
yoffset = 0
|
||||
if width > 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
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
noise
|
BIN
savegame.empyre_save
Normal file
BIN
savegame.empyre_save
Normal file
Binary file not shown.
21
state.py
Normal file
21
state.py
Normal file
@ -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"))
|
109
test.py
Normal file
109
test.py
Normal file
@ -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()
|
Loading…
x
Reference in New Issue
Block a user