Package pr.battlebots.gen

Source Code of pr.battlebots.gen.MazeGen

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package pr.battlebots.gen;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import pr.battlebots.World;
import pr.battlebots.blocks.BlockType;
import pr.lib.Debug;
import pr.lib.Dir;
import pr.lib.Turn;
import pr.lib.U;
import pr.lib.Vec;

/**
*
* @author Paul
*/
public class MazeGen implements IGen {

    boolean[][] map;
    Random rng;
    World world;

    Vec[][] getNeigborPaths(Vec p, Dir d) {
        Vec[][] paths = new Vec[4][2];
        for (int i = 0; i < 4; i++) {
            Dir pd = d.turn(Turn.values()[i]);
            paths[i][0] = p.InDirection(pd);
            paths[i][1] = paths[i][0].InDirection(pd);
        }
        return paths;
    }

    Vec[] getNeighbors(Vec p) {
        Vec[] n = new Vec[4];
        for (int i = 0; i < 4; i++) {
            n[i] = p.InDirection(Dir.dirs[i]);
        }
        return n;
    }

    private void randomWalk(Vec p, Dir d, int steps, int baseScore, int noRepeatScore, int noBackTrackScore, int noTurnScore) {
        set(p);
        for (int i = 0; i < steps; i++) {
            int[] pSpotsScores = new int[4];
            for (int j = 0; j < 4; j++) {
                Dir pd = d.turn(Turn.values()[j]);
                Vec pHallSpot = p.InDirection(pd);
                Vec pSpot = pHallSpot.InDirection(pd);

                if (pSpot.distanceTo(world.midpoint) >= world.width / 2) {
                    //Debug.log(pSpot+" " + j+ " is out of bounds! ");
                    pSpotsScores[j] = 0;
                    continue;
                }

                boolean alreadBeenAtPSpot = get(pSpot);
                boolean backTrack = get(pHallSpot);

                int score = baseScore;

                if (d == pd) {
                    score += noTurnScore;
                }
                if (!alreadBeenAtPSpot) {
                    score += noRepeatScore;

                }

                if (!backTrack) {
                    score += noBackTrackScore;
                }

                pSpotsScores[j] = score;
            }

            d = d.turn(Turn.values()[weightedChoise(pSpotsScores)]);

            for (int j = 0; j < 2; j++) {
                set(p = p.InDirection(d));
            }

        }
    }

    private void make(long seed) {
        rng.setSeed(seed);
        map = new boolean[world.height][world.width];
        Vec start = world.midpoint;
        int steps = world.width * world.height / (4 * 6);

        int baseScore = 10;
        int noRepeatScore = 10000;
        int noBackTrackScore = -5;
        int noTurnScore = 20;
        int radius = world.width / 2 - 2;

        randomWalk(start, Dir.East, steps, baseScore, noRepeatScore, noBackTrackScore, noTurnScore);

        for (Dir d : Dir.dirs) {
            Vec startPoint = world.midpoint.InDirection(d, d == Dir.North ? radius + 2 : radius);
            randomWalk(startPoint, Dir.East, steps, baseScore, noRepeatScore, noBackTrackScore, noTurnScore);
        }
    }

    int score() {
        int visitedCells = 0;
        for (int r = 2; r < world.height - 2; r += 2) {
            for (int c = 2; c < world.width - 2; c += 2) {
                if (map[r][c]) {
                    visitedCells++;
                }
            }
        }
        return visitedCells;
    }

    public int length = -1;
    public int seed = -1;

    @Override
    public void gen(World world) {
        rng = new Random();
        this.world = world;
        //long seed = rng.nextLong();
        //rng.setSeed(seed);

        make(seed);
        length = astar(map, world.midpoint, world.getGoal());
        world.setMessage(length + "," + seed + "," + score());

        Iterator<Vec> vi = world.iterator();
        while (vi.hasNext()) {
            Vec p = vi.next();
            if (!get(p)) {
                world.makeBlock(blockType, p);
            }
        }
    }

    int weightedChoise(int[] weights) {

        float[] ps = U.accumulate(U.pnorm(weights));
        //Debug.log(U.join(ps,","));
        float r = 1 - rng.nextFloat();

        for (int i = 0; i < weights.length; i++) {
            if (ps[i] > r && weights[i] != 0) {
                return i;
            }
        }
        return 0;
    }

    void set(Vec p, boolean v) {
        map[p.y][p.x] = v;
    }

    void set(Vec p) {
        set(p, true);
    }

    boolean get(Vec p) {
        return map[p.y][p.x];
    }

    int astar(boolean[][] map, Vec pos, Vec goal) {
        int[][] dists = new int[world.height][world.width];
        int d = 0;
        HashSet<Vec> open = new HashSet<Vec>();
        open.add(pos);
        while (open.size() > 0) {
            Vec[] working = new Vec[open.size()];
            //closed.addAll(open);
            open.toArray(working);
            open.clear();

            ++d;
           
            if(d>200)
                return -1;
           
            for (Vec p : working) {
                dists[p.y][p.x] = d;
                if (goal.equals(p)) {
                    return d;
                }
                for (Vec oo : p.getNeighbors()) {
                    if (map[p.y][p.x]) {
                        open.add(oo);
                    }
                }
            }
        }
        return -1;
    }

    BlockType blockType = BlockType.BEDROCK;

}
TOP

Related Classes of pr.battlebots.gen.MazeGen

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.