diff --git a/robotgame/level_bonus.py b/robotgame/level_bonus.py index 128eec9..69b1f0a 100644 --- a/robotgame/level_bonus.py +++ b/robotgame/level_bonus.py @@ -30,6 +30,7 @@ import random import re import itertools +import misc import level import player import tile @@ -52,10 +53,8 @@ class Level(level.Level): self.draw_background() - emptys = list(itertools.product(range(2, 20), range(2, 20))) - for _ in range(150): - x, y = random.choice(emptys) - emptys.remove((x, y)) + for x, y in misc.pick_random_elements( + list(itertools.product(range(2, 20), range(2, 20))), 150): self.objects.append(block.Block(self, 64 * x, 48 * y, self.imgs['block1'], movable=True)) diff --git a/robotgame/logic/lasermirror.py b/robotgame/logic/lasermirror.py index 4cde2f7..169c264 100644 --- a/robotgame/logic/lasermirror.py +++ b/robotgame/logic/lasermirror.py @@ -33,6 +33,7 @@ import random import itertools from robotgame.logic.direction import * import robotgame.logic.rollingstone as rstone +import robotgame.misc as misc class Mirror(object): pass @@ -81,18 +82,16 @@ def generate_simple_playfield(nmirrors): succs = (lambda s: lambda d: succ(s(d)))(succs) source_direc = succ(source_direc) - emptys = set(itertools.product(range(12), range(12))) \ - - set(playfield.keys()) - emptys = set([(0, y) for y in range(12)] - + [(11, y) for y in range(12)] - + [(x, 0) for x in range(12)] - + [(x, 11) for x in range(12)]) - for _ in range(nlevers): - if not emptys: - raise Exception("Not enough space for all levers!") - pos = random.choice(list(emptys)) + emptys = list( + set([(0, y) for y in range(12)] + + [(11, y) for y in range(12)] + + [(x, 0) for x in range(12)] + + [(x, 11) for x in range(12)]) + - set(playfield.keys())) + if len(emptys) < nlevers: + raise Exception("Not enough space for all levers!") + for pos in misc.pick_random_elements(emptys, nlevers): playfield[pos] = Lever - emptys.remove(pos) return playfield def _adjust(source_direc, w, h, x, y): diff --git a/robotgame/logic/rollingstone.py b/robotgame/logic/rollingstone.py index 8377402..75b5ca9 100644 --- a/robotgame/logic/rollingstone.py +++ b/robotgame/logic/rollingstone.py @@ -32,7 +32,9 @@ from __future__ import print_function import math import random import itertools + from robotgame.logic.direction import * +import robotgame.misc as misc class Blocker(object): pass @@ -89,6 +91,9 @@ def generate_simple_playfield(width, height, nturns, nstones, 'steps' is the number of steps used by the generated solution. It is not necessarily the lowest number of steps the playfield can be completed in. + + This generator favours increasing the turn density the closer to the goal + it gets. """ min_width, min_height = _min_play_size(nturns) @@ -151,13 +156,10 @@ def generate_simple_playfield(width, height, nturns, nstones, del turns[-1] for p, d in turns: playfield[p] = d - emptys = set(itertools.product(range(width), - range(height))) - set(used_fields) - for _ in range(nstones): - if not emptys: - break - pos = random.choice(list(emptys)) - emptys.remove(pos) + + for pos in misc.pick_random_elements( + list(set(itertools.product(range(width), range(height))) + - set(used_fields)), nstones): playfield[pos] = Blocker return playfield, len(used_fields) - 1 diff --git a/robotgame/misc.py b/robotgame/misc.py new file mode 100644 index 0000000..04547a3 --- /dev/null +++ b/robotgame/misc.py @@ -0,0 +1,9 @@ +from __future__ import print_function +import random + +def pick_random_elements(xs, n): + for i in range(min(n, len(xs))): + i1 = random.randrange(i, len(xs)) + yield xs[i1] + xs[i1] = xs[i] +