Laser now shows behind mirrors where needed. Next up is improving laser
graphics and adding laser sources and laser targets.
This commit is contained in:
@@ -29,6 +29,13 @@ class Direction(object):
|
||||
def next_pos(pos):
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def from_sakse(p):
|
||||
return {(0, -1): Up,
|
||||
(0, 1): Down,
|
||||
(-1, 0): Left,
|
||||
(1, 0): Right}[p]
|
||||
|
||||
class Up(Direction):
|
||||
@staticmethod
|
||||
def next_pos(pos):
|
||||
|
||||
@@ -48,6 +48,10 @@ class Lever(object):
|
||||
class Target(object):
|
||||
pass
|
||||
|
||||
class Source(object):
|
||||
def __init__(self, direction):
|
||||
self.__dict__.update(locals())
|
||||
|
||||
def generate_simple_playfield(nmirrors):
|
||||
"""
|
||||
Generate a completable 16x16 playfield where:
|
||||
@@ -64,7 +68,14 @@ def generate_simple_playfield(nmirrors):
|
||||
Return playfield : {(x, y):
|
||||
Target | MirrorLeft | MirrorRight | rstone.Blocker | Lever}
|
||||
"""
|
||||
playfield = {(6, 6): Target,
|
||||
|
||||
width, height = 16, 16
|
||||
|
||||
playfield = {(0, 0): Source(Down),
|
||||
(width - 1, 0): Source(Left),
|
||||
(width - 1, height - 1): Source(Up),
|
||||
(0, height - 1): Source(Right),
|
||||
(6, 6): Target,
|
||||
(9, 6): Target,
|
||||
(6, 9): Target,
|
||||
(9, 9): Target,
|
||||
@@ -73,7 +84,6 @@ def generate_simple_playfield(nmirrors):
|
||||
(8, 7): rstone.Blocker,
|
||||
(8, 8): rstone.Blocker,
|
||||
}
|
||||
width, height = 16, 16
|
||||
|
||||
succs = lambda d: d
|
||||
source_direc = Up
|
||||
@@ -84,7 +94,7 @@ def generate_simple_playfield(nmirrors):
|
||||
stone_playfield, _ = rstone.generate_simple_playfield(
|
||||
7, 7, nm, 0, False, False)
|
||||
for pos, direc in stone_playfield.items():
|
||||
playfield[_adjust(source_direc, 16 - 1, 16 - 1, *pos)] \
|
||||
playfield[_adjust(source_direc, width - 1, height - 1, *pos)] \
|
||||
= random.choice((MirrorLeft, MirrorRight))
|
||||
succs = (lambda s: lambda d: succ(s(d)))(succs)
|
||||
source_direc = succ(source_direc)
|
||||
@@ -141,32 +151,34 @@ def _adjust(source_direc, w, h, x, y):
|
||||
}[source_direc](x, y)
|
||||
|
||||
def generate_lasers(playfield):
|
||||
"""
|
||||
Generate laser paths.
|
||||
|
||||
Return [((x, y), direction), ...]
|
||||
"""
|
||||
width, height = 16, 16
|
||||
sources = (((0, -1), Down),
|
||||
((width, 0), Left),
|
||||
((width - 1, height), Up),
|
||||
((-1, height - 1), Right))
|
||||
sources = ((pos, obj.direction) for pos, obj in filter(lambda posobj: isinstance(posobj[1], Source), playfield.items()))
|
||||
lasers = []
|
||||
for start, direc in sources:
|
||||
end = start
|
||||
while True:
|
||||
cur = playfield.get(end)
|
||||
if cur is Target:
|
||||
lasers.append((start, end))
|
||||
lasers.append(((start, end), direc))
|
||||
break
|
||||
if cur is Blocker:
|
||||
lasers.append((start, end))
|
||||
lasers.append(((start, end), direc))
|
||||
break
|
||||
if cur in (MirrorLeft, MirrorRight):
|
||||
if (start, end) in lasers:
|
||||
if (start, end) in ((start, end) for (start, end), direc in lasers):
|
||||
break
|
||||
lasers.append((start, end))
|
||||
lasers.append(((start, end), direc))
|
||||
direc = _mirror_new_direc(cur, direc)
|
||||
start = end
|
||||
new_end = direc.next_pos(end)
|
||||
if new_end[0] < 0 or new_end[1] < 0 or new_end[0] >= width or new_end[1] >= height:
|
||||
if (start, end) not in lasers:
|
||||
lasers.append((start, new_end))
|
||||
lasers.append(((start, new_end), direc))
|
||||
break
|
||||
end = new_end
|
||||
return lasers
|
||||
|
||||
Reference in New Issue
Block a user