#!/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 2012 # copyright : (C) 2012 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 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))