#!/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 . # # ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' # # lasermirror.py # -------------------- # date created : Tue Aug 7 2016 # copyright : (C) 2016 Niels G. W. Serup # maintained by : Niels G. W. Serup """ 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 from robotgame.logic.rollingstone import Blocker 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 16x16 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 (15, 0) starts in (16, 0), heading left + the one in the lower right corner (15, 15) starts in (15, 16), heading up + the one in the lower left corner (0, 15) starts in (-1, 15), 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 = {(6, 6): Target, (9, 6): Target, (6, 9): Target, (9, 9): Target, (7, 7): rstone.Blocker, (7, 8): rstone.Blocker, (8, 7): rstone.Blocker, (8, 8): 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( 7, 7, nm, 0, False, False) for pos, direc in stone_playfield.items(): playfield[_adjust(source_direc, 16 - 1, 16 - 1, *pos)] = Mirror succs = (lambda s: lambda d: succ(s(d)))(succs) source_direc = succ(source_direc) 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 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))