117 lines
4.2 KiB
Python
117 lines
4.2 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# This file is part of ROBOTGAME
|
|
#
|
|
# ROBOTGAME is free software: you can redistribute it and/or modify it under the
|
|
# terms of the GNU General Public License as published by the Free Software
|
|
# Foundation, either version 3 of the License, or (at your option) any later
|
|
# version.
|
|
#
|
|
# ROBOTGAME is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along with
|
|
# ROBOTGAME. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
|
|
#
|
|
# lasermirror.py
|
|
# --------------------
|
|
# date created : Tue Aug 7 2012
|
|
# copyright : (C) 2012 Niels G. W. Serup
|
|
# maintained by : Niels G. W. Serup <ns@metanohi.name>
|
|
|
|
"""
|
|
Management of lasers in rooms of mirrors and targets.
|
|
"""
|
|
|
|
from __future__ import print_function
|
|
import math
|
|
import random
|
|
import itertools
|
|
from robotgame.logic.direction import *
|
|
import robotgame.logic.rollingstone as rstone
|
|
import robotgame.misc as misc
|
|
|
|
class Mirror(object):
|
|
pass
|
|
|
|
class Lever(object):
|
|
pass
|
|
|
|
class Target(object):
|
|
pass
|
|
|
|
def generate_simple_playfield(nmirrors):
|
|
"""
|
|
Generate a completable 12x12 playfield where:
|
|
* there are four laser sources, one in each corner
|
|
+ the one in the upper left corner (0, 0) starts in (0, -1) heading down
|
|
+ the one in the upper right corner (11, 0) starts in (12, 0), heading left
|
|
+ the one in the lower right corner (11, 11) starts in (11, 12), heading up
|
|
+ the one in the lower left corner (0, 11) starts in (-1, 11), heading right
|
|
* there are four laser targets
|
|
* there are nmirrors mirrors
|
|
* there are nmirrors levers
|
|
* all levers are at the wall
|
|
|
|
Return playfield : {(x, y): Target | Mirror | rstone.Blocker | Lever}
|
|
"""
|
|
playfield = {(4, 4): Target,
|
|
(7, 4): Target,
|
|
(4, 7): Target,
|
|
(7, 7): Target,
|
|
(5, 5): rstone.Blocker,
|
|
(5, 6): rstone.Blocker,
|
|
(6, 5): rstone.Blocker,
|
|
(6, 6): rstone.Blocker,
|
|
}
|
|
succs = lambda d: d
|
|
source_direc = Up
|
|
nlevers = nmirrors
|
|
for missing in range(4, 0, -1):
|
|
nm = nmirrors / missing
|
|
nmirrors -= nm
|
|
stone_playfield, _ = rstone.generate_simple_playfield(
|
|
5, 5, nm, 0, False, False)
|
|
for pos, direc in stone_playfield.items():
|
|
if direc is not None and pos >= (0, 0):
|
|
playfield[_adjust(source_direc, 12 - 1, 12 - 1, *pos)] = Mirror
|
|
succs = (lambda s: lambda d: succ(s(d)))(succs)
|
|
source_direc = succ(source_direc)
|
|
|
|
occup = set(playfield.keys())
|
|
emptys = list(
|
|
set([(0, y) for y in filter(lambda y: (1, y) not in occup, range(12))]
|
|
+ [(11, y) for y in filter(lambda y: (10, y) not in occup, range(12))]
|
|
+ [(x, 0) for x in filter(lambda x: (x, 1) not in occup, range(12))]
|
|
+ [(x, 11) for x in filter(lambda x: (x, 10) not in occup, range(12))])
|
|
- occup)
|
|
if len(emptys) < nlevers:
|
|
raise Exception("Not enough space for all levers!")
|
|
for pos in misc.pick_random_elements(emptys, nlevers):
|
|
playfield[pos] = Lever
|
|
return playfield
|
|
|
|
def _adjust(source_direc, w, h, x, y):
|
|
return {
|
|
Up: lambda x, y: (x, y),
|
|
Right: lambda x, y: (w - y, x),
|
|
Down: lambda x, y: (w - x, h - y),
|
|
Left: lambda x, y: (y, h - x),
|
|
}[source_direc](x, y)
|
|
|
|
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():
|
|
if isDirection(val) and hide_directions:
|
|
continue
|
|
text[y][x] = '%' if val is rstone.Blocker \
|
|
else 'x' if val is Mirror \
|
|
else 'L' if val is Lever \
|
|
else 'T' if val is Target else 'N'
|
|
print('\n'.join(''.join(line) for line in text))
|
|
|