Package ru.shalnov.pacman.server

Source Code of ru.shalnov.pacman.server.MapGenerator

package ru.shalnov.pacman.server;

import ru.shalnov.pacman.protocol.Courses;
import ru.shalnov.pacman.protocol.Map;

import java.util.ArrayList;
import java.util.Random;

/**
* Created with IntelliJ IDEA.
* User: Kirill Shalnov
* Date: 27.03.13
* Time: 1:20
*/
public class MapGenerator extends Object {
    public static final int MIN_HEIGHT = 10;
    public static final int MIN_WIDTH = 20;
    private int mHeight;
    private int mWidth;
    //filling density map
    private double mDensity;
    //minimal step for turning trek to other side
    private int mStepLength;
    private Map mMap;

    public MapGenerator() {
        //last arguments are dummies used to fault fixer
        initialize(MIN_WIDTH, MIN_HEIGHT, 1.0, MIN_HEIGHT);
    }

    public MapGenerator(int width, int height, double density, int stepLength) {
        initialize(width, height, density, stepLength);
    }

    public int getStepLength() {
        return mStepLength;
    }

    public void setStepLength(int stepLength) {
        if (stepLength < getHeight() / 2 && stepLength < getWidth() / 2) {
            mStepLength = stepLength;
        } else {
            mStepLength = Math.min(getHeight() / 2, getWidth() / 2);
        }
    }

    public double getDensity() {
        return mDensity;
    }

    public void setDensity(double density) {
        //if density value will be 0.4 or more, we can't generate map
        if (density <= 0.45) {
            mDensity = density;
        } else {
            mDensity = 0.4;
        }
    }

    public int getWidth() {
        return mWidth;
    }

    public void setWidth(int width) {
        if (width > MIN_WIDTH) {
            mWidth = width;
        } else {
            mWidth = MIN_WIDTH;
        }
    }

    public int getHeight() {
        return mHeight;
    }

    public void setHeight(int height) {
        if (height > MIN_HEIGHT) {
            mHeight = height;
        } else {
            mHeight = MIN_HEIGHT;
        }
    }

    public void initialize(int width, int height, double density, int stepLength) {
        //regularity is important
        setHeight(height);
        setWidth(width);
        setDensity(density);
        setStepLength(stepLength);
    }

    public Map generateMap() {
        mMap = new Map(mWidth, mHeight);
        int numberPassables = (int) (mHeight * mWidth * mDensity);
        //before route generating
        //drawing border
        for (int i = 0; i < mHeight; i++) {
            mMap.setPassable(0, i, true);
            mMap.setPassable(mWidth - 1, i, true);
        }
        for (int i = 0; i < mWidth; i++) {
            mMap.setPassable(i, 0, true);
            mMap.setPassable(i, mHeight - 1, true);
        }

        //start point
        int x = mWidth / 2;
        int y = mHeight / 2;
        //last start point
        int lastX = x;
        int lastY = y;
        mMap.setPassable(x, y, true);
        //counter of passable points
        int passableCounter = mHeight + mWidth - 4;
        int course = Courses.STAY;
        int step = 0; //step less than mStepLength
        //begin drawing trek on the map
        for (int iteration = 2 * mHeight * mWidth; iteration > 0; iteration--) {
            ArrayList<Integer> courses = getPossibleCourses(x, y);
            if (step == mStepLength || !courses.contains(course) || course == Courses.STAY) {
                course = changeCourse(courses);
                step = 0;
            }

            switch (course) {
                case Courses.RIGHT:
                    mMap.setPassable(++x, y, true);
                    step++;
                    passableCounter++;
                    break;
                case Courses.LEFT:
                    mMap.setPassable(--x, y, true);
                    step++;
                    passableCounter++;
                    break;
                case Courses.UP:
                    mMap.setPassable(x, ++y, true);
                    step++;
                    passableCounter++;
                    break;
                case Courses.DOWN:
                    mMap.setPassable(x, --y, true);
                    step++;
                    passableCounter++;
                    break;
                case Courses.STAY:
                    //if density is to low then proceed to generating from point on the border
                    if (passableCounter < numberPassables) {
                        if (lastX == -1 && lastY == -1) {
                            x = Math.abs(new Random().nextInt()) % mWidth;
                            y = Math.abs(new Random().nextInt()) % mHeight;

                            lastX = x;
                            lastY = y;

                            ArrayList<Integer> tmpCourses = getPossibleCourses(x, y);
                            // size == 1 when it contain only "STAY"
                            if (tmpCourses.size() != 1 && checkStartPoint(x, y)) {
                                mMap.setPassable(x, y, true);
                            }
                        } else {
                            x = lastX;
                            y = lastY;
                            lastX = -1;
                            lastY = -1;
                        }
                    } else {
                        iteration = 0;
                    }
                    break;
            }
        }
        fillFood();
        return mMap;
    }

    public Map fillFood() {
        for (int i = 0; i < mMap.getHeight(); i++) {
            for (int j = 0; j < mMap.getWidth(); j++) {
                mMap.setFood(j, i, mMap.isPassable(j, i));
            }
        }
        return mMap;
    }

    //check point to set passable
    private boolean checkStartPoint(int x, int y) {

        try {
            //ooo
            //xoo
            //xxo
            if (mMap.isPassable(x - 1, y)
                    && mMap.isPassable(x - 1, y - 1)
                    && mMap.isPassable(x, y - 1)) {
                return false;
            }
            //xxo
            //xoo
            //ooo
            if (mMap.isPassable(x - 1, y)
                    && mMap.isPassable(x - 1, y + 1)
                    && mMap.isPassable(x, y + 1)) {
                return false;
            }
            //oxx
            //oox
            //ooo
            if (mMap.isPassable(x, y + 1)
                    && mMap.isPassable(x + 1, y + 1)
                    && mMap.isPassable(x + 1, y)) {
                return false;
            }
            //ooo
            //oox
            //oxx
            if (mMap.isPassable(x, y - 1)
                    && mMap.isPassable(x + 1, y - 1)
                    && mMap.isPassable(x + 1, y)) {
                return false;
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            return false;
        }
        return true;
    }

    private int changeCourse(ArrayList<Integer> courses) {
        int numberAvailableCourses = courses.size() - 1;
        //if all courses without STAY were removing. It apart case to exclude from random
        if (numberAvailableCourses == 0) {
            return Courses.STAY;
        }
        Random rand = new Random();
        int courseIndex = Math.abs(rand.nextInt()) % numberAvailableCourses;
        int course = courses.get(courseIndex).intValue();
        return course;
    }

    private ArrayList<Integer> getPossibleCourses(int x, int y) {
        //create an array with courses to remove part of them from the choice
        ArrayList<Integer> courses = new ArrayList<Integer>();
        Integer right = new Integer(Courses.RIGHT);
        Integer up = new Integer(Courses.UP);
        Integer left = new Integer(Courses.LEFT);
        Integer down = new Integer(Courses.DOWN);
        Integer stay = new Integer(Courses.STAY);

        courses.add(right);
        courses.add(up);
        courses.add(left);
        courses.add(down);
        courses.add(stay);

        //Global condition: passable points can`t be side by side
        if (x - 1 < 0 || y + 1 >= mHeight || mMap.isPassable(x - 1, y + 1)) {
            //xoo
            //ooo
            //ooo
            courses.remove(left);
            courses.remove(up);
        }
        if (x + 1 >= mWidth || y + 1 >= mHeight || mMap.isPassable(x + 1, y + 1)) {
            //oox
            //ooo
            //ooo
            courses.remove(right);
            courses.remove(up);
        }
        if (x + 1 >= mWidth || y - 1 < 0 || mMap.isPassable(x + 1, y - 1)) {
            //ooo
            //ooo
            //oox
            courses.remove(right);
            courses.remove(down);
        }
        if (x - 1 < 0 || y - 1 < 0 || mMap.isPassable(x - 1, y - 1)) {
            //ooo
            //ooo
            //xoo
            courses.remove(left);
            courses.remove(down);
        }
        if (y + 1 >= mHeight || mMap.isPassable(x, y + 1)) {
            //oxo
            //ooo
            //ooo
            courses.remove(up);
        }
        if (y - 1 < 0 || mMap.isPassable(x, y - 1)) {
            //ooo
            //ooo
            //oxo
            courses.remove(down);
        }
        if (x - 1 < 0 || mMap.isPassable(x - 1, y)) {
            //ooo
            //xoo
            //ooo
            courses.remove(left);
        }
        if (x + 1 >= mWidth || mMap.isPassable(x + 1, y)) {
            //ooo
            //oox
            //ooo
            courses.remove(right);
        }
        return courses;
    }
}
TOP

Related Classes of ru.shalnov.pacman.server.MapGenerator

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.