X-Git-Url: https://plomlompom.com/repos/foo.html?a=blobdiff_plain;f=plomrogue%2Fmapping.py;h=29078d87c0b9d71ef9ee2d8616e862888b73f705;hb=9ac7e8befde463275086945c1ed5399bb8ef3af0;hp=e3c071f85251ae9e947183a474fe69d78294e2bf;hpb=a789724e6b1b5eb514f82ac4d7092f7575180c31;p=plomrogue2 diff --git a/plomrogue/mapping.py b/plomrogue/mapping.py index e3c071f..29078d8 100644 --- a/plomrogue/mapping.py +++ b/plomrogue/mapping.py @@ -85,6 +85,10 @@ class MapGeometry(): x = big_yx.x * self.size.x + little_yx.x return YX(y, x) + def basic_circle_out_move(self, position, direction): + mover = getattr(self, 'move__' + direction) + return mover(position) + class MapGeometryWithLeftRightMoves(MapGeometry): @@ -98,10 +102,12 @@ class MapGeometryWithLeftRightMoves(MapGeometry): class MapGeometrySquare(MapGeometryWithLeftRightMoves): + circle_out_directions = (('DOWN', 'LEFT'), ('LEFT', 'UP'), + ('UP', 'RIGHT'), ('RIGHT', 'DOWN')) - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.fov_map_class = FovMapSquare + def circle_out_move(self, yx, direction): + yx = self.basic_circle_out_move(yx, direction[0]) + return self.basic_circle_out_move(yx, direction[1]) def define_segment(self, source_center, radius): source_center = self.undouble_yxyx(*source_center) @@ -118,10 +124,11 @@ class MapGeometrySquare(MapGeometryWithLeftRightMoves): class MapGeometryHex(MapGeometryWithLeftRightMoves): + circle_out_directions = ('DOWNLEFT', 'LEFT', 'UPLEFT', + 'UPRIGHT', 'RIGHT', 'DOWNRIGHT') - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.fov_map_class = FovMapHex + def circle_out_move(self, yx, direction): + return self.basic_circle_out_move(yx, direction) def define_segment(self, source_center, radius): source_center = self.undouble_yxyx(*source_center) @@ -210,8 +217,8 @@ class Map(): class SourcedMap(Map): - def __init__(self, block_chars, things, source_maps, source_center, radius, - get_map): + def __init__(self, block_chars, obstacle_positions, source_maps, + source_center, radius, get_map): self.block_chars = block_chars self.radius = radius example_map = get_map(YX(0, 0)) @@ -219,20 +226,11 @@ class SourcedMap(Map): size, self.offset, self.center = \ self.source_geometry.define_segment(source_center, radius) self.geometry = self.source_geometry.__class__(size) - for yx in self: - big_yx, _ = self.source_yxyx(yx) - get_map(big_yx) self.source_map_segment = '' - obstacles = {} - for yxyx in [t.position for t in things if t.blocking]: - if yxyx == source_center: - continue - if yxyx[0] not in obstacles: - obstacles[yxyx[0]] = [] - obstacles[yxyx[0]] += [yxyx[1]] - for yx in self: # TODO: iter and source_yxyx expensive, cache earlier? + for yx in self: big_yx, little_yx = self.source_yxyx(yx) - if big_yx in obstacles and little_yx in obstacles[big_yx]: + get_map(big_yx) + if (big_yx, little_yx) in obstacle_positions: self.source_map_segment += self.block_chars[0] else: self.source_map_segment += source_maps[big_yx][little_yx] @@ -260,7 +258,6 @@ class DijkstraMap(SourcedMap): def __init__(self, *args, **kwargs): # TODO: check potential optimizations: - # - do a first pass circling out from the center # - somehow ignore tiles that have the lowest possible value (we can # compare with a precalculated map for given starting position) # - check if Python offers more efficient data structures to use here @@ -268,18 +265,34 @@ class DijkstraMap(SourcedMap): super().__init__(*args, **kwargs) self.terrain = [255] * self.size_i self[self.center] = 0 + + def work_tile(position_i): + shrunk_test = False + if self.source_map_segment[position_i] in self.block_chars: + return shrunk_test + neighbors = self.geometry.get_neighbors_i(position_i) + for direction in [d for d in neighbors if neighbors[d]]: + j = neighbors[direction] + if self.terrain[j] < self.terrain[position_i] - 1: + self.terrain[position_i] = self.terrain[j] + 1 + shrunk_test = True + return shrunk_test + + # TODO: refactor with FovMap.circle_out() shrunk = True while shrunk: shrunk = False - for i in range(self.size_i): - if self.source_map_segment[i] in self.block_chars: - continue - neighbors = self.geometry.get_neighbors_i(i) - for direction in [d for d in neighbors if neighbors[d]]: - j = neighbors[direction] - if self.terrain[j] < self.terrain[i] - 1: - self.terrain[i] = self.terrain[j] + 1 - shrunk = True + yx = self.center + distance = 1 + while distance <= self.radius: + yx = self.geometry.basic_circle_out_move(yx, 'RIGHT') + for dir_i in range(len(self.geometry.circle_out_directions)): + for dir_progress in range(distance): + direction = self.geometry.circle_out_directions[dir_i] + yx = self.geometry.circle_out_move(yx, direction) + position_i = self.get_position_index(yx) + shrunk = True if work_tile(position_i) else shrunk + distance += 1 # print('DEBUG Dijkstra') # line_to_print = [] # x = 0 @@ -362,7 +375,8 @@ class FovMap(SourcedMap): if unmerged: self.shadow_cones += [cone] - step_size = (CIRCLE / len(self.circle_out_directions)) / distance_to_center + step_size = (CIRCLE / len(self.geometry.circle_out_directions))\ + / distance_to_center number_steps = dir_i * distance_to_center + dir_progress left_arm = correct_arm(step_size / 2 + step_size * number_steps) right_arm = correct_arm(left_arm + step_size) @@ -375,10 +389,6 @@ class FovMap(SourcedMap): else: eval_cone([left_arm, right_arm]) - def basic_circle_out_move(self, pos, direction): - mover = getattr(self.geometry, 'move__' + direction) - return mover(pos) - def circle_out(self, yx, f): # Optimization potential: Precalculate movement positions. # Optimization potential: Precalculate what tiles are shaded by what tile @@ -388,30 +398,10 @@ class FovMap(SourcedMap): distance = 1 yx = YX(yx.y, yx.x) while distance <= self.radius: - yx = self.basic_circle_out_move(yx, 'RIGHT') - for dir_i in range(len(self.circle_out_directions)): + yx = self.geometry.basic_circle_out_move(yx, 'RIGHT') + for dir_i in range(len(self.geometry.circle_out_directions)): for dir_progress in range(distance): - direction = self.circle_out_directions[dir_i] - yx = self.circle_out_move(yx, direction) + direction = self.geometry.circle_out_directions[dir_i] + yx = self.geometry.circle_out_move(yx, direction) f(yx, distance, dir_i, dir_progress) distance += 1 - - - - -class FovMapHex(FovMap): - circle_out_directions = ('DOWNLEFT', 'LEFT', 'UPLEFT', - 'UPRIGHT', 'RIGHT', 'DOWNRIGHT') - - def circle_out_move(self, yx, direction): - return self.basic_circle_out_move(yx, direction) - - - -class FovMapSquare(FovMap): - circle_out_directions = (('DOWN', 'LEFT'), ('LEFT', 'UP'), - ('UP', 'RIGHT'), ('RIGHT', 'DOWN')) - - def circle_out_move(self, yx, direction): - yx = self.basic_circle_out_move(yx, direction[0]) - return self.basic_circle_out_move(yx, direction[1])