Added lasers. Lasers not pretty yet.
This commit is contained in:
@@ -19,8 +19,8 @@
|
||||
#
|
||||
# lasermirror.py
|
||||
# --------------------
|
||||
# date created : Tue Aug 7 2016
|
||||
# copyright : (C) 2016 Niels G. W. Serup
|
||||
# date created : Tue Aug 7 2012
|
||||
# copyright : (C) 2012 Niels G. W. Serup
|
||||
# maintained by : Niels G. W. Serup <ns@metanohi.name>
|
||||
|
||||
"""
|
||||
@@ -36,7 +36,10 @@ import robotgame.logic.rollingstone as rstone
|
||||
from robotgame.logic.rollingstone import Blocker
|
||||
import robotgame.misc as misc
|
||||
|
||||
class Mirror(object):
|
||||
class MirrorLeft(object):
|
||||
pass
|
||||
|
||||
class MirrorRight(object):
|
||||
pass
|
||||
|
||||
class Lever(object):
|
||||
@@ -58,7 +61,8 @@ def generate_simple_playfield(nmirrors):
|
||||
* there are nmirrors levers
|
||||
* all levers are at the wall
|
||||
|
||||
Return playfield : {(x, y): Target | Mirror | rstone.Blocker | Lever}
|
||||
Return playfield : {(x, y):
|
||||
Target | MirrorLeft | MirrorRight | rstone.Blocker | Lever}
|
||||
"""
|
||||
playfield = {(6, 6): Target,
|
||||
(9, 6): Target,
|
||||
@@ -69,6 +73,8 @@ def generate_simple_playfield(nmirrors):
|
||||
(8, 7): rstone.Blocker,
|
||||
(8, 8): rstone.Blocker,
|
||||
}
|
||||
width, height = 16, 16
|
||||
|
||||
succs = lambda d: d
|
||||
source_direc = Up
|
||||
nlevers = nmirrors
|
||||
@@ -78,22 +84,54 @@ 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)] = Mirror
|
||||
playfield[_adjust(source_direc, 16 - 1, 16 - 1, *pos)] \
|
||||
= random.choice((MirrorLeft, MirrorRight))
|
||||
succs = (lambda s: lambda d: succ(s(d)))(succs)
|
||||
source_direc = succ(source_direc)
|
||||
|
||||
occup = set(playfield.keys())
|
||||
|
||||
is_empty = lambda x, y: (x, y) not in occup
|
||||
|
||||
ok_a = lambda y: is_empty(1, y)
|
||||
ok_b = lambda y: is_empty(width - 2, y)
|
||||
ok_c = lambda x: is_empty(x, 1)
|
||||
ok_d = lambda x: is_empty(x, height - 2)
|
||||
no_block = lambda x, y: \
|
||||
all((ok_a(y) if x == 0 else True,
|
||||
ok_b(y) if x == width - 1 else True,
|
||||
ok_c(x) if y == 0 else True,
|
||||
ok_d(x) if y == height - 1 else True))
|
||||
|
||||
emptys = set([(0, y) for y in filter(ok_a, range(height))]
|
||||
+ [(width - 1, y) for y in filter(ok_b, range(height))]
|
||||
+ [(x, 0) for x in filter(ok_c, range(width))]
|
||||
+ [(x, height - 1) for x in filter(ok_d, range(width))]) - occup
|
||||
emptys_full = set(itertools.product(range(width), range(height))) - occup
|
||||
|
||||
emptys = list(emptys)
|
||||
random.shuffle(emptys)
|
||||
emptys = set(emptys)
|
||||
|
||||
is_empty = lambda x, y: (x, y) in emptys_full
|
||||
|
||||
levers = []
|
||||
for _ in range(nlevers):
|
||||
# This needs to be optimized...
|
||||
occup = set(playfield.keys())
|
||||
emptys = list(
|
||||
set([(0, y) for y in filter(lambda y: (1, y) not in occup, range(16))]
|
||||
+ [(15, y) for y in filter(lambda y: (10, y) not in occup, range(16))]
|
||||
+ [(x, 0) for x in filter(lambda x: (x, 1) not in occup, range(16))]
|
||||
+ [(x, 15) for x in filter(lambda x: (x, 10) not in occup, range(16))]) - occup)
|
||||
pos = emptys[random.randrange(len(emptys))]
|
||||
playfield[pos] = Lever
|
||||
while True:
|
||||
pos = next(iter(emptys))
|
||||
emptys.remove(pos)
|
||||
emptys_full.remove(pos)
|
||||
if no_block(*pos):
|
||||
playfield[pos] = Lever
|
||||
if not all(no_block(*pos) for pos in levers):
|
||||
del playfield[pos]
|
||||
else:
|
||||
levers.append(pos)
|
||||
break
|
||||
|
||||
return playfield
|
||||
|
||||
|
||||
def _adjust(source_direc, w, h, x, y):
|
||||
return {
|
||||
Up: lambda x, y: (x, y),
|
||||
@@ -101,7 +139,45 @@ def _adjust(source_direc, w, h, x, y):
|
||||
Down: lambda x, y: (w - x, h - y),
|
||||
Left: lambda x, y: (y, h - x),
|
||||
}[source_direc](x, y)
|
||||
|
||||
|
||||
def generate_lasers(playfield):
|
||||
width, height = 16, 16
|
||||
sources = (((0, -1), Down),
|
||||
((width, 0), Left),
|
||||
((width - 1, height), Up),
|
||||
((-1, height - 1), Right))
|
||||
lasers = []
|
||||
for start, direc in sources:
|
||||
end = start
|
||||
while True:
|
||||
cur = playfield.get(end)
|
||||
if cur is Target:
|
||||
lasers.append((start, end))
|
||||
break
|
||||
if cur is Blocker:
|
||||
lasers.append((start, end))
|
||||
break
|
||||
if cur in (MirrorLeft, MirrorRight):
|
||||
if (start, end) in lasers:
|
||||
break
|
||||
lasers.append((start, end))
|
||||
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))
|
||||
break
|
||||
end = new_end
|
||||
return lasers
|
||||
|
||||
def _mirror_new_direc(mirror_type, old_direc):
|
||||
return {Down: (Left, Right),
|
||||
Left: (Down, Up),
|
||||
Up: (Right, Left),
|
||||
Right: (Up, Down)}[old_direc][
|
||||
0 if mirror_type is MirrorLeft else 1]
|
||||
|
||||
def print_playfield(playfield, width, height, hide_directions=False):
|
||||
text = [['·' for _ in range(width)] for _ in range(height)]
|
||||
for (x, y), val in playfield.items():
|
||||
|
||||
Reference in New Issue
Block a user