X-Git-Url: https://plomlompom.com/repos/foo.html?a=blobdiff_plain;ds=inline;f=new%2Fplomrogue%2Fmapping.py;h=b670938e64658e2ff34306483bdb6cb7adf12d77;hb=8f4f45798471d5b0069d7ac2caaf7d6a389ce981;hp=0ec953d329befd0dd5e6ec93910e06e78ed69d7a;hpb=3b7db36664e8989b106d8975d7a115e8a872b473;p=plomrogue2-experiments
diff --git a/new/plomrogue/mapping.py b/new/plomrogue/mapping.py
index 0ec953d..b670938 100644
--- a/new/plomrogue/mapping.py
+++ b/new/plomrogue/mapping.py
@@ -1,12 +1,27 @@
from plomrogue.errors import ArgError
+import collections
+
+
+
+class YX(collections.namedtuple('YX', ('y', 'x'))):
+
+ def __add__(self, other):
+ return YX(self.y + other.y, self.x + other.x)
+
+ def __sub__(self, other):
+ return YX(self.y - other.y, self.x - other.x)
+
+ def __str__(self):
+ return 'Y:%s,X:%s' % (self.y, self.x)
class Map:
- def __init__(self, size=(0, 0)):
+ def __init__(self, size=YX(0, 0), init_char = '?', start_indented=True):
self.size = size
- self.terrain = '?'*self.size_i
+ self.terrain = init_char * self.size_i
+ self.start_indented = start_indented
def __getitem__(self, yx):
return self.terrain[self.get_position_index(yx)]
@@ -20,17 +35,17 @@ class Map:
def __iter__(self):
"""Iterate over YX position coordinates."""
- for y in range(self.size[0]):
- for x in range(self.size[1]):
- yield (y, x)
+ for y in range(self.size.y):
+ for x in range(self.size.x):
+ yield YX(y, x)
@property
def size_i(self):
- return self.size[0] * self.size[1]
+ return self.size.y * self.size.x
def set_line(self, y, line):
- height_map = self.size[0]
- width_map = self.size[1]
+ height_map = self.size.y
+ width_map = self.size.x
if y >= height_map:
raise ArgError('too large row number %s' % y)
width_line = len(line)
@@ -40,15 +55,22 @@ class Map:
self.terrain[(y + 1) * width_map:]
def get_position_index(self, yx):
- return yx[0] * self.size[1] + yx[1]
+ return yx.y * self.size.x + yx.x
def lines(self):
- width = self.size[1]
- for y in range(self.size[0]):
+ width = self.size.x
+ for y in range(self.size.y):
yield (y, self.terrain[y * width:(y + 1) * width])
- def get_fov_map(self, yx):
- return self.fov_map_type(self, yx)
+
+
+class MapChunk(Map):
+ awake = 0 # asleep if zero
+ stats = {}
+
+
+
+class MapGeometry():
def get_directions(self):
directions = []
@@ -57,100 +79,133 @@ class Map:
directions += [name[5:]]
return directions
- def get_neighbors(self, pos):
+ def get_neighbors(self, pos, map_size, start_indented=True):
neighbors = {}
- pos = tuple(pos)
if not hasattr(self, 'neighbors_to'):
self.neighbors_to = {}
- if pos in self.neighbors_to:
- return self.neighbors_to[pos]
+ if not map_size in self.neighbors_to:
+ self.neighbors_to[map_size] = {}
+ if not start_indented in self.neighbors_to[map_size]:
+ self.neighbors_to[map_size][start_indented] = {}
+ if pos in self.neighbors_to[map_size][start_indented]:
+ return self.neighbors_to[map_size][start_indented][pos]
for direction in self.get_directions():
- neighbors[direction] = None
- neighbor_pos = self.move(pos, direction)
- if neighbor_pos:
- neighbors[direction] = neighbor_pos
- self.neighbors_to[pos] = neighbors
+ neighbors[direction] = self.move(pos, direction, map_size,
+ start_indented)
+ self.neighbors_to[map_size][start_indented][pos] = neighbors
return neighbors
- def new_from_shape(self, init_char):
- import copy
- new_map = copy.deepcopy(self)
- for pos in new_map:
- new_map[pos] = init_char
- return new_map
-
- def move(self, start_pos, direction):
+ def undouble_coordinate(self, maps_size, coordinate):
+ y = maps_size.y * coordinate[0].y + coordinate[1].y
+ x = maps_size.x * coordinate[0].x + coordinate[1].x
+ return YX(y, x)
+
+ def get_view_offset(self, maps_size, center, radius):
+ yx_to_origin = self.undouble_coordinate(maps_size, center)
+ return yx_to_origin - YX(radius, radius)
+
+ def pos_in_view(self, pos, offset, maps_size):
+ return self.undouble_coordinate(maps_size, pos) - offset
+
+ def get_view_and_seen_maps(self, maps_size, get_map, radius, view_offset):
+ m = Map(size=YX(radius*2+1, radius*2+1),
+ start_indented=(view_offset.y % 2 == 0))
+ seen_maps = []
+ for pos in m:
+ seen_pos = self.correct_double_coordinate(maps_size, (0,0),
+ pos + view_offset)
+ if seen_pos[0] not in seen_maps:
+ seen_maps += [seen_pos[0]]
+ seen_map = get_map(seen_pos[0])
+ if seen_map is None:
+ seen_map = Map(size=maps_size)
+ m[pos] = seen_map[seen_pos[1]]
+ return m, seen_maps
+
+ def correct_double_coordinate(self, map_size, big_yx, little_yx):
+
+ def adapt_axis(axis):
+ maps_crossed = little_yx[axis] // map_size[axis]
+ new_big = big_yx[axis] + maps_crossed
+ new_little = little_yx[axis] % map_size[axis]
+ return new_big, new_little
+
+ new_big_y, new_little_y = adapt_axis(0)
+ new_big_x, new_little_x = adapt_axis(1)
+ return YX(new_big_y, new_big_x), YX(new_little_y, new_little_x)
+
+ def move(self, start_pos, direction, map_size, start_indented=True):
mover = getattr(self, 'move_' + direction)
- new_pos = mover(start_pos)
- if new_pos[0] < 0 or new_pos[1] < 0 or \
- new_pos[0] >= self.size[0] or new_pos[1] >= self.size[1]:
- return None
- return new_pos
+ big_yx, little_yx = start_pos
+ uncorrected_target = mover(little_yx, start_indented)
+ return self.correct_double_coordinate(map_size, big_yx,
+ uncorrected_target)
-class MapWithLeftRightMoves(Map):
+class MapGeometryWithLeftRightMoves(MapGeometry):
- def move_LEFT(self, start_pos):
- return (start_pos[0], start_pos[1] - 1)
+ def move_LEFT(self, start_pos, _):
+ return YX(start_pos.y, start_pos.x - 1)
- def move_RIGHT(self, start_pos):
- return (start_pos[0], start_pos[1] + 1)
+ def move_RIGHT(self, start_pos, _):
+ return YX(start_pos.y, start_pos.x + 1)
-class MapSquare(MapWithLeftRightMoves):
+class MapGeometrySquare(MapGeometryWithLeftRightMoves):
- def move_UP(self, start_pos):
- return (start_pos[0] - 1, start_pos[1])
+ def move_UP(self, start_pos, _):
+ return YX(start_pos.y - 1, start_pos.x)
- def move_DOWN(self, start_pos):
- return (start_pos[0] + 1, start_pos[1])
+ def move_DOWN(self, start_pos, _):
+ return YX(start_pos.y + 1, start_pos.x)
-class MapHex(MapWithLeftRightMoves):
+class MapGeometryHex(MapGeometryWithLeftRightMoves):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fov_map_type = FovMapHex
- def move_UPLEFT(self, start_pos):
- if start_pos[0] % 2 == 1:
- return (start_pos[0] - 1, start_pos[1] - 1)
+ def move_UPLEFT(self, start_pos, start_indented):
+ if start_pos.y % 2 == start_indented:
+ return YX(start_pos.y - 1, start_pos.x - 1)
else:
- return (start_pos[0] - 1, start_pos[1])
+ return YX(start_pos.y - 1, start_pos.x)
- def move_UPRIGHT(self, start_pos):
- if start_pos[0] % 2 == 1:
- return (start_pos[0] - 1, start_pos[1])
+ def move_UPRIGHT(self, start_pos, start_indented):
+ if start_pos.y % 2 == start_indented:
+ return YX(start_pos.y - 1, start_pos.x)
else:
- return (start_pos[0] - 1, start_pos[1] + 1)
+ return YX(start_pos.y - 1, start_pos.x + 1)
- def move_DOWNLEFT(self, start_pos):
- if start_pos[0] % 2 == 1:
- return (start_pos[0] + 1, start_pos[1] - 1)
+ def move_DOWNLEFT(self, start_pos, start_indented):
+ if start_pos.y % 2 == start_indented:
+ return YX(start_pos.y + 1, start_pos.x - 1)
else:
- return (start_pos[0] + 1, start_pos[1])
+ return YX(start_pos.y + 1, start_pos.x)
- def move_DOWNRIGHT(self, start_pos):
- if start_pos[0] % 2 == 1:
- return (start_pos[0] + 1, start_pos[1])
+ def move_DOWNRIGHT(self, start_pos, start_indented):
+ if start_pos.y % 2 == start_indented:
+ return YX(start_pos.y + 1, start_pos.x)
else:
- return (start_pos[0] + 1, start_pos[1] + 1)
+ return YX(start_pos.y + 1, start_pos.x + 1)
-class FovMap:
+class FovMap(Map):
- def __init__(self, source_map, yx):
+ def __init__(self, source_map, center):
self.source_map = source_map
self.size = self.source_map.size
- self.fov_radius = (self.size[0] / 2) - 0.5
+ self.fov_radius = (self.size.y / 2) - 0.5
+ self.start_indented = source_map.start_indented
self.terrain = '?' * self.size_i
- self[yx] = '.'
+ self[center] = '.'
self.shadow_cones = []
- self.circle_out(yx, self.shadow_process_hex)
+ self.circle_out(center, self.shadow_process_hex)
def shadow_process_hex(self, yx, distance_to_center, dir_i, dir_progress):
# Possible optimization: If no shadow_cones yet and self[yx] == '.',
@@ -221,10 +276,10 @@ class FovMap:
def basic_circle_out_move(self, pos, direction):
"""Move position pos into direction. Return whether still in map."""
- mover = getattr(self, 'move_' + direction)
- pos = mover(pos)
- if pos[0] < 0 or pos[1] < 0 or \
- pos[0] >= self.size[0] or pos[1] >= self.size[1]:
+ mover = getattr(self.geometry, 'move_' + direction)
+ pos = mover(pos, self.start_indented)
+ if pos.y < 0 or pos.x < 0 or \
+ pos.y >= self.size.y or pos.x >= self.size.x:
return pos, False
return pos, True
@@ -240,7 +295,7 @@ class FovMap:
# TODO: get rid of circle_in_map logic
circle_in_map = True
distance = 1
- yx = yx[:]
+ yx = YX(yx.y, yx.x)
#print('DEBUG CIRCLE_OUT', yx)
while circle_in_map:
if distance > self.fov_radius:
@@ -258,19 +313,28 @@ class FovMap:
-class FovMapHex(FovMap, MapHex):
+class FovMapHex(FovMap):
circle_out_directions = ('DOWNLEFT', 'LEFT', 'UPLEFT',
'UPRIGHT', 'RIGHT', 'DOWNRIGHT')
+ def __init__(self, *args, **kwargs):
+ self.geometry = MapGeometryHex()
+ super().__init__(*args, **kwargs)
+
def circle_out_move(self, yx, direction):
return self.basic_circle_out_move(yx, direction)
-class FovMapSquare(FovMap, MapSquare):
+class FovMapSquare(FovMap):
circle_out_directions = (('DOWN', 'LEFT'), ('LEFT', 'UP'),
('UP', 'RIGHT'), ('RIGHT', 'DOWN'))
+ def __init__(self, *args, **kwargs):
+ self.geometry = MapGeometrySquare()
+ super().__init__(*args, **kwargs)
+
def circle_out_move(self, yx, direction):
self.basic_circle_out_move(yx, direction[0])
return self.basic_circle_out_move(yx, direction[1])
+