Package koth.user.jlb

Source Code of koth.user.jlb.Maze

package koth.user.jlb;

import koth.game.Board;
import koth.game.Generator;
import koth.game.Move;
import koth.util.Algorithms;
import koth.util.Vector;

import java.util.*;

/**
* Generate a pseudo-random maze-like map.
*/
public class Maze implements Generator {

    private final Random random = new Random();

    /**
     * Modified version of Prim's algorithm to generate pseudo-maze.
     * @see <a href=http://en.wikipedia.org/wiki/Maze_generation_algorithm#Randomized_Prim.27s_algorithm>Wikipedia</a>
     */
    public static Set<Vector> generate(int size, float redundantProbability, Random random) {
        // Add origin as a maze tile
        Set<Vector> tiles = new HashSet<Vector>();
        tiles.add(new Vector());
        Set<Vector> walls = new HashSet<Vector>();
        walls.add(new Vector(1, 0));
        walls.add(new Vector(-1, 0));
        walls.add(new Vector(0, 1));
        walls.add(new Vector(0, -1));
        // Repeat specified number of times
        for (int n = 1; n < size;) {
            // Choose randomly a wall
            Vector wall = Algorithms.random(walls, random);
            walls.remove(wall);
            // Check if both endpoints already exist
            Move dir = wall.getX() % 2 == 0 ? Move.North : Move.East;
            Vector a = wall.add(dir), b = wall.sub(dir);
            boolean ac = tiles.contains(a), bc = tiles.contains(b);
            if (ac && bc && random.nextFloat() >= redundantProbability)
                continue;
            // Add tiles to maze
            tiles.add(wall);
            ++n;
            if (!ac) {
                tiles.add(a);
                ++n;
            }
            if (!bc) {
                tiles.add(b);
                ++n;
            }
            // Add neighbors as walls
            for (Move m : Move.getNonzeros()) {
                Vector am = a.add(m);
                if (!tiles.contains(am))
                    walls.add(am);
                Vector bm = b.add(m);
                if (!tiles.contains(bm))
                    walls.add(bm);
            }
        }
        return tiles;
    }

    /**
     * Create a board with specified parameters.
     */
    public static Board create(int teams, int spawnRadius, int size, float redundantProbability, Random random) {
        if (random == null)
            throw new NullPointerException();
        if (teams < 0 || spawnRadius < 0 || size <= 0)
            throw new IllegalArgumentException();
        // Create tiles
        Set<Vector> tiles = generate(size, redundantProbability, random);
        Map<Vector, Map<Vector, Integer>> dists = Algorithms.distances(tiles);
        int max = 0;
        for (Map<Vector, Integer> m : dists.values())
            for (int i : m.values())
                max = Math.max(i, max);
        // Try to select equidistant spawn origins
        List<Vector> origins = null;
        long score = Long.MAX_VALUE;
        for (int n = 0; n < 50; ++n) {
            List<Vector> test = new ArrayList<Vector>(teams);
            long cost = 0;
            for (int i = 0; i < teams; ++i) {
                Vector p = Algorithms.random(tiles, random);
                test.add(p);
                for (int j = 0; j < i; ++j) {
                    long d = max - dists.get(p).get(test.get(j));
                    cost += d * d;
                }
            }
            if (origins == null || cost < score) {
                origins = test;
                score = cost;
            }
        }
        // Add surroundings to spawns
        List<Set<Vector>> spawns = new ArrayList<Set<Vector>>(teams);
        for (int i = 0; i < teams; ++i) {
            Set<Vector> ss = new HashSet<Vector>();
            Map<Vector, Integer> ds = dists.get(origins.get(i));
            for (Vector t : tiles)
                if (ds.get(t) <= spawnRadius)
                    ss.add(t);
            spawns.add(ss);
        }
        return new Board(tiles, spawns);
    }

    @Override
    public Board create(int teams) {
        return create(teams, 4, 50 * teams, 0.3f, random);
    }

}
TOP

Related Classes of koth.user.jlb.Maze

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.