Merge branch 'master' of hongabar.org:robotgame
This commit is contained in:
		@@ -1 +1,8 @@
 | 
			
		||||
This is a good game.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
The rolling boulder task in level 1 is not guaranteed to be solvable, because
 | 
			
		||||
you might not be able to move an arrow block to the position you need to move
 | 
			
		||||
it to. However, this scenario is so unlikely that we have chosen to ignore it.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										94
									
								
								robotgame/level4.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								robotgame/level4.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
			
		||||
# 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 boulder
 | 
			
		||||
import lever
 | 
			
		||||
import mirror
 | 
			
		||||
import trigger
 | 
			
		||||
import misc
 | 
			
		||||
import worldobject
 | 
			
		||||
 | 
			
		||||
import logic.lasermirror as lm
 | 
			
		||||
 | 
			
		||||
class Level4(level.Level):
 | 
			
		||||
    def __init__(self, game, graphics_dir, paused=False):
 | 
			
		||||
        level.Level.__init__(self, game, graphics_dir,
 | 
			
		||||
                             size=(64 * 16, 48 * 16), 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+1)*48,
 | 
			
		||||
                              self.imgs['indoor%d' % random.randint(1, 6)]))
 | 
			
		||||
 | 
			
		||||
        self.draw_background()
 | 
			
		||||
        
 | 
			
		||||
        playfield = lm.generate_simple_playfield(16)
 | 
			
		||||
 | 
			
		||||
        for (x, y), t in playfield.items():
 | 
			
		||||
            x, y = 64 * x, 48 * (y + 1)
 | 
			
		||||
            self.objects.append({
 | 
			
		||||
                lm.Mirror: mirror.Mirror(self, x, y, random.choice((True, False))),
 | 
			
		||||
                lm.Lever: lever.Lever(
 | 
			
		||||
                        self, x, y, [], toggling=True,
 | 
			
		||||
                        anim='lever_leftright' if x == 0 or x == 15 * 64
 | 
			
		||||
                        else 'lever_updown'),
 | 
			
		||||
                lm.Target: block.Block(self, x, y, self.imgs['block3'],
 | 
			
		||||
                                       movable=False),
 | 
			
		||||
                lm.Blocker: block.Block(self, x, y, 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)
 | 
			
		||||
            l.links.append((lambda m: lambda setting: m.rotate())(m))
 | 
			
		||||
 | 
			
		||||
        self.player.set_pos(64 * 7, 48 * 2)
 | 
			
		||||
        self.player.set_init_pos()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def restart(self):
 | 
			
		||||
        for obj in self.objects:
 | 
			
		||||
            obj.reset_pos()
 | 
			
		||||
 | 
			
		||||
@@ -85,7 +85,9 @@ class Loader(object):
 | 
			
		||||
             ('arrow_down', os.path.join('matt', 'down')),
 | 
			
		||||
             ('arrow_left', os.path.join('matt', 'right')),
 | 
			
		||||
 | 
			
		||||
             ('stairs', 'stairs')]
 | 
			
		||||
             ('stairs', 'stairs'),
 | 
			
		||||
 | 
			
		||||
             ('mirror', 'mirror')]
 | 
			
		||||
            ):
 | 
			
		||||
 | 
			
		||||
            self.imgs[anim] = []
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,8 @@
 | 
			
		||||
#
 | 
			
		||||
#                         lasermirror.py
 | 
			
		||||
#                     --------------------
 | 
			
		||||
#       date created : Tue Aug 7 2012
 | 
			
		||||
#          copyright : (C) 2012 Niels G. W. Serup
 | 
			
		||||
#       date created : Tue Aug 7 2016
 | 
			
		||||
#          copyright : (C) 2016 Niels G. W. Serup
 | 
			
		||||
#      maintained by : Niels G. W. Serup <ns@metanohi.name>
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
@@ -33,6 +33,7 @@ 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):
 | 
			
		||||
@@ -46,12 +47,12 @@ class Target(object):
 | 
			
		||||
 | 
			
		||||
def generate_simple_playfield(nmirrors):
 | 
			
		||||
    """
 | 
			
		||||
    Generate a completable 12x12 playfield where:
 | 
			
		||||
    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 (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
 | 
			
		||||
        + 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
 | 
			
		||||
@@ -59,14 +60,14 @@ def generate_simple_playfield(nmirrors):
 | 
			
		||||
 | 
			
		||||
    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,
 | 
			
		||||
    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
 | 
			
		||||
@@ -75,23 +76,21 @@ def generate_simple_playfield(nmirrors):
 | 
			
		||||
        nm = nmirrors / missing
 | 
			
		||||
        nmirrors -= nm
 | 
			
		||||
        stone_playfield, _ = rstone.generate_simple_playfield(
 | 
			
		||||
            5, 5, nm, 0, False, False)
 | 
			
		||||
            7, 7, 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
 | 
			
		||||
            playfield[_adjust(source_direc, 16 - 1, 16 - 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):
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@ def generate_simple_playfield(width, height, nturns, nstones,
 | 
			
		||||
            break
 | 
			
		||||
        else:
 | 
			
		||||
            allowed = set(range(0, height)) - set(not_allowed_y)
 | 
			
		||||
            if missing == 3:
 | 
			
		||||
            if missing <= 3:
 | 
			
		||||
                allowed -= set((height - 1,))
 | 
			
		||||
            if missing == nturns:
 | 
			
		||||
                allowed -= set((0,))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										63
									
								
								robotgame/mirror.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								robotgame/mirror.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
#
 | 
			
		||||
# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
 | 
			
		||||
#
 | 
			
		||||
#                          mirror.py
 | 
			
		||||
#                     --------------------
 | 
			
		||||
#       date created : Fri Aug 10 2012
 | 
			
		||||
#          copyright : (C) 2012 Niels G. W. Serup
 | 
			
		||||
#      maintained by : Niels G. W. Serup <ns@metanohi.name>
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
A generic mirror for drawing.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import pygame
 | 
			
		||||
 | 
			
		||||
import worldobject
 | 
			
		||||
 | 
			
		||||
class Mirror(worldobject.WorldObject):
 | 
			
		||||
    def __init__(self, level, x, y, left_up=True):
 | 
			
		||||
        self.__dict__.update(locals())
 | 
			
		||||
        worldobject.WorldObject.__init__(self, level, x, y)
 | 
			
		||||
 | 
			
		||||
        self.in_rotation = False
 | 
			
		||||
 | 
			
		||||
        self.frame = 7
 | 
			
		||||
        self.anim_speed = 12
 | 
			
		||||
        self._half_anim_len = len(self.level.imgs['mirror']) / 2
 | 
			
		||||
 | 
			
		||||
    def rotate(self):
 | 
			
		||||
        if self.in_rotation:
 | 
			
		||||
            return
 | 
			
		||||
        self.in_rotation = True
 | 
			
		||||
        self.left_up = not self.left_up
 | 
			
		||||
        self.frame = 0
 | 
			
		||||
 | 
			
		||||
    def update(self, e, t, dt):
 | 
			
		||||
        if self.in_rotation:
 | 
			
		||||
            top = self._half_anim_len - 1
 | 
			
		||||
            self.frame = min(self.frame + self.anim_speed * dt, top)
 | 
			
		||||
            if self.frame == top:
 | 
			
		||||
                self.in_rotation = False
 | 
			
		||||
 | 
			
		||||
        worldobject.WorldObject.update(self, e, t, dt)
 | 
			
		||||
 | 
			
		||||
    def draw(self, window):
 | 
			
		||||
        fn = self.frame + 1 if not self.left_up else self.frame + self._half_anim_len
 | 
			
		||||
        self.img = self.level.imgs['mirror'][int(fn)]
 | 
			
		||||
        window.blit(self.img, (self.x - 32 - self.level.camera_x,
 | 
			
		||||
                               self.y - self.img.get_size()[1] + 24
 | 
			
		||||
                               - self.level.camera_y))
 | 
			
		||||
@@ -7,3 +7,7 @@ def pick_random_elements(xs, n):
 | 
			
		||||
        yield xs[i1]
 | 
			
		||||
        xs[i1] = xs[i]
 | 
			
		||||
 | 
			
		||||
def manhattan_dist(p0, p1):
 | 
			
		||||
    x0, y0 = p0
 | 
			
		||||
    x1, y1 = p1
 | 
			
		||||
    return abs(x1 - x0) + abs(y1 - y0)
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ from robotgame.logic.direction import *
 | 
			
		||||
class LaserMirrorTest(unittest.TestCase):
 | 
			
		||||
    def test_playfield_generation(self):
 | 
			
		||||
        print()
 | 
			
		||||
        playfield = generate_simple_playfield(13)
 | 
			
		||||
        playfield = generate_simple_playfield(16)
 | 
			
		||||
        print_playfield(playfield, 12, 12)
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user