a-robots-conundrum/robotgame/level4.py

172 lines
6.3 KiB
Python
Raw Normal View History

# 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/>.
#
# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
#
# level1.py
# --------------------
# date created : Fri Aug 10 2012
# copyright : (C) 2012 Niels G. W. Serup
# maintained by : Niels G. W. Serup <ns@metanohi.name>
"""
The fourth level.
"""
import os
import pygame
import random
import re
import itertools
import level
import player
import tile
import block
import lever
import mirror
import laser
import misc
import worldobject
import logic.lasermirror as lm
from logic.direction import *
class Level4(level.Level):
def __init__(self, game, graphics_dir, paused=False):
level.Level.__init__(self, game, graphics_dir,
size=(64 * 16, 48 * 20), paused=paused)
self.dimensions = 16, 16
for i in range(self.dimensions[0]):
for j in range(self.dimensions[1]):
self.tiles.append(
tile.Tile(self, i*64, (j+4)*48,
self.imgs['indoor%d' % random.randint(1, 6)]))
self.draw_background()
2012-08-12 18:28:09 +02:00
2012-08-11 21:47:38 +02:00
self.playfield = lm.generate_simple_playfield(16)
for (x, y), t in self.playfield.items():
x1, y1 = 64 * x, 48 * (y + 4)
if isinstance(t, lm.Source):
self.objects.append(block.Block(
self, x1, y1,
self.imgs['lasersource_' + t.direction.to_str().lower()],
movable=False))
continue
2012-08-11 21:47:38 +02:00
def mir(b, x1, y1):
def f(x, y):
def g(setting):
self.playfield[(x, y)] = lm.MirrorLeft \
if self.playfield[(x, y)] is lm.MirrorRight \
else lm.MirrorRight
self.generate_lasers()
return g
return mirror.Mirror(self, x1, y1, b, links=[f(x, y)])
self.objects.append({
2012-08-11 21:47:38 +02:00
lm.MirrorLeft: mir(True, x1, y1),
lm.MirrorRight: mir(False, x1, y1),
lm.Lever: lever.Lever(
2012-08-11 21:47:38 +02:00
self, x1, y1, [lambda setting: self.generate_lasers],
toggling=True,
anim='lever_leftright' if x in (0, 15)
else 'lever_updown'),
lm.Target: block.Block(self, x1, y1, self.imgs['lasertarget'],
movable=False),
2012-08-11 21:47:38 +02:00
lm.Blocker: block.Block(self, x1, y1, self.imgs['block1'],
movable=False)
}[t])
mirrors = list(filter(lambda obj: isinstance(obj, mirror.Mirror),
self.objects))
levers = list(filter(lambda obj: isinstance(obj, lever.Lever),
self.objects))
random.shuffle(levers)
for l in levers:
m = min(mirrors, key=lambda m: misc.manhattan_dist(
(m.x, m.y), (l.x, l.y)))
mirrors.remove(m)
2012-08-11 14:30:46 +02:00
l.links.insert(0, (lambda m: lambda setting: m.rotate())(m))
for i in range(self.size[0] / 64):
if not i % 3:
self.objects.append(block.Block(self, i * 64,
48 * 3,
self.imgs['wall'],
width=3))
self.objects.append(block.InvisBlock(self, i * 64,
self.size[1]))
for i in range(self.size[1] / 48):
self.objects.append(block.InvisBlock(self, - 64,
i * 48))
self.objects.append(block.InvisBlock(self, self.size[0],
i * 48))
2012-08-11 14:30:46 +02:00
self.generate_lasers()
self.player.set_pos(64 * 7, 48 * 5)
self.player.set_init_pos()
def restart(self):
for obj in self.objects:
obj.reset_pos()
2012-08-11 14:30:46 +02:00
def generate_lasers(self):
self.lasers_orig = lm.generate_lasers(self.playfield)
2012-08-11 14:30:46 +02:00
self.lasers = []
for ((x0, y0), (x1, y1)), direc in self.lasers_orig:
self.lasers.append(laser.Laser(
self, (x0 * 64, y0 * 48),
2012-08-12 20:43:14 +02:00
(x1 * 64, y1 * 48), direc))
2012-08-12 18:28:09 +02:00
2012-08-11 14:30:46 +02:00
def draw(self, window):
self._blit_background(window)
2012-08-12 20:43:14 +02:00
objs = self._sorted_objs(self.objects + self.lasers)
objs = self._after_sort(itertools.groupby(objs, lambda obj: obj.y + obj.z))
2012-08-11 21:47:38 +02:00
for obj in objs:
2012-08-11 14:30:46 +02:00
obj.draw(window)
self.darkness.draw(window)
2012-08-12 20:43:14 +02:00
def _after_sort(self, objss):
n_objs = []
for c, objs in objss:
n_objs.extend(self._after_sort_line(list(objs)))
return n_objs
2012-08-12 20:43:14 +02:00
def _after_sort_line(self, objs):
is_special = lambda obj: isinstance(obj, mirror.Mirror) or isinstance(obj, laser.Laser)
specials, nonspecials = filter(is_special, objs), filter(lambda obj: not is_special(obj), objs)
return nonspecials + self._sort_line_specials(specials)
def _sort_line_specials(self, objs):
mirrors = filter(lambda obj: isinstance(obj, mirror.Mirror), objs)
lasers = filter(lambda obj: isinstance(obj, laser.Laser), objs)
return mirrors + lasers
2012-08-12 20:43:14 +02:00
def _is_laser_behind_mirror(mirror_direc, laser_direc):
return {
(Left, Up): True,
(Left, Left): True,
(Left, Down): False,
(Left, Right): False,
(Right, Up): True,
(Right, Right): True,
(Right, Down): False,
(Right, Left): False
}[(mirror_direc, laser_direc)]