base.Engine.java Source code

Java tutorial

Introduction

Here is the source code for base.Engine.java

Source

package base;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.collections4.map.ReferenceMap;

import objects.PatternEntry;
import objects.PatternInstance;
import objects.PatternWrapper;
import rules.Ruleset;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Rectangle;

/*
 PatternLife utility methods
 Copyright (C) 2015 Eugene "eaglgenes101" Wang
    
 This program 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 2 of the License, or
 (at your option) any later version.
    
 This program 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 this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

public class Engine {

    public static final byte[][] EMPTY_PATTERN = {};

    public static final PatternEntry nullPattern = new PatternEntry(EMPTY_PATTERN);

    public static LinkedList<PatternInstance> cleanList(LinkedList<PatternInstance> toClean) {
        PatternInstance nowPatternInstance = null;
        for (ListIterator<PatternInstance> li = toClean.listIterator(); li.hasNext();) {
            nowPatternInstance = li.next();
            if (nowPatternInstance.getEntry().equals(nullPattern)) {
                li.remove();
            }
        }
        return toClean;
    }

    public static Pixmap generatePatternPixmap(PatternEntry basedOn, Color color) {
        Pixmap returnPixmap = new Pixmap(basedOn.getWrapper().getW(), basedOn.getWrapper().getH(),
                Pixmap.Format.RGBA8888);
        returnPixmap.setColor(Color.rgba8888(0, 0, 0, 0));
        returnPixmap.fill();

        returnPixmap.setColor(Color.DARK_GRAY);
        returnPixmap.drawPixel(0, 0);

        returnPixmap.setColor(color);

        for (int x = 0; x < basedOn.getWrapper().getW(); x++)
            for (int y = 0; y < basedOn.getWrapper().getH(); y++)
                if (basedOn.getCells()[x][y] != 0)
                    returnPixmap.drawPixel(x, y);

        return returnPixmap;
    }

    public static Texture generatePatternTexture(PatternEntry basedOn, Color color) {
        Pixmap px = generatePatternPixmap(basedOn, color);
        Texture tx = new Texture(px);
        px.dispose();
        return tx;
    }

    // Returns patterns that are likely to be collisions
    public static Set<TreeSet<PatternInstance>> findCollisions(List<PatternInstance> instanceList,
            int caseThreshold) {
        Set<TreeSet<PatternInstance>> returnSet = new TreeSet<>(new TreeComparator());

        if (instanceList.size() < 2)
            return returnSet; // Our base case

        if (instanceList.size() < caseThreshold) {
            PatternInstance currentInstance = null;
            for (ListIterator<PatternInstance> i = instanceList.listIterator(); i.hasNext();) {
                currentInstance = i.next();
                PatternInstance otherInstance = null;
                for (ListIterator<PatternInstance> j = instanceList.listIterator(i.nextIndex()); j.hasNext();) {
                    otherInstance = j.next();
                    if (currentInstance != otherInstance
                            && currentInstance.getRectangle().overlaps(otherInstance.getRectangle())) {
                        returnSet = addPair(returnSet, currentInstance, otherInstance);
                    }
                }
            }
            return returnSet; // Our other base case
        }

        Rectangle getRect = instanceList.get(0).getRectangle();
        // Create a super-rectangle that encompasses all the objects
        PatternInstance currentInstance = null;
        for (ListIterator<PatternInstance> i = instanceList.listIterator(1); i.hasNext();) {
            currentInstance = i.next();
            getRect = getRect.merge(currentInstance.getRectangle());
        }

        List<PatternInstance> listQ1 = new LinkedList<>();
        List<PatternInstance> listQ2 = new LinkedList<>();
        List<PatternInstance> listQ3 = new LinkedList<>();
        List<PatternInstance> listQ4 = new LinkedList<>();

        Rectangle rectQ1 = new Rectangle(getRect.getX(), getRect.getY(), getRect.getWidth() / 2 + 1,
                getRect.getHeight() / 2 + 1);
        Rectangle rectQ2 = new Rectangle(getRect.getX(), getRect.getY() + getRect.getHeight() / 2 + 1,
                getRect.getWidth() / 2 + 1, getRect.getHeight() / 2 + 1);
        Rectangle rectQ3 = new Rectangle(getRect.getX() + getRect.getWidth() / 2 + 1,
                getRect.getY() + getRect.getHeight() / 2 + 1, getRect.getWidth() / 2 + 1,
                getRect.getHeight() / 2 + 1);
        Rectangle rectQ4 = new Rectangle(getRect.getX() + getRect.getWidth() / 2 + 1, getRect.getY(),
                getRect.getWidth() / 2 + 1, getRect.getHeight() / 2 + 1);

        for (ListIterator<PatternInstance> iter = instanceList.listIterator(); iter.hasNext();) {
            currentInstance = iter.next();
            if (currentInstance.getRectangle().overlaps(rectQ1))
                listQ1.add(currentInstance);
            if (currentInstance.getRectangle().overlaps(rectQ2))
                listQ2.add(currentInstance);
            if (currentInstance.getRectangle().overlaps(rectQ3))
                listQ3.add(currentInstance);
            if (currentInstance.getRectangle().overlaps(rectQ4))
                listQ4.add(currentInstance);
        }

        for (TreeSet<PatternInstance> t1 : findCollisions(listQ1, caseThreshold * 2))
            resolveTree(returnSet, t1);
        for (TreeSet<PatternInstance> t2 : findCollisions(listQ2, caseThreshold * 2))
            resolveTree(returnSet, t2);
        for (TreeSet<PatternInstance> t3 : findCollisions(listQ3, caseThreshold * 2))
            resolveTree(returnSet, t3);
        for (TreeSet<PatternInstance> t4 : findCollisions(listQ4, caseThreshold * 2))
            resolveTree(returnSet, t4);

        return returnSet;

    }

    static Set<TreeSet<PatternInstance>> resolveTree(Set<TreeSet<PatternInstance>> returnSet,
            Set<PatternInstance> colls) {
        TreeSet<PatternInstance> workingTree = new TreeSet<>(new InstanceComparator());
        for (PatternInstance p : colls) {
            TreeSet<PatternInstance> onThisTree = null;
            for (TreeSet<PatternInstance> it : returnSet) {
                if (it.contains(p)) {
                    onThisTree = it;
                    break;
                }
            }

            if (onThisTree == null) {
                workingTree.add(p);
            } else {
                workingTree.addAll(onThisTree);
                returnSet.remove(onThisTree);
            }
        }
        returnSet.add(workingTree);
        return returnSet;
    }

    static Set<TreeSet<PatternInstance>> addPair(Set<TreeSet<PatternInstance>> returnSet, PatternInstance p1,
            PatternInstance p2) {
        TreeSet<PatternInstance> t1 = null;
        TreeSet<PatternInstance> t2 = null;
        for (TreeSet<PatternInstance> aTree : returnSet) {
            if (aTree.contains(p1)) {
                t1 = aTree;
                break;
            }
        }
        for (TreeSet<PatternInstance> aTree : returnSet) {
            if (aTree.contains(p2)) {
                t2 = aTree;
                break;
            }
        }

        if (t1 == null && t2 == null) {
            TreeSet<PatternInstance> newTree = new TreeSet<>(new InstanceComparator());
            newTree.add(p1);
            newTree.add(p2);
            returnSet.add(newTree);
        } else if (t1 == null && t2 != null) {
            t2.add(p1);
        } else if (t1 != null && t2 == null) {
            t1.add(p2);
        } else if (t1 != t2) {
            t1.addAll(t2);
            returnSet.remove(t2);
        }
        return returnSet;
    }

    static class TreeComparator implements Comparator<TreeSet<PatternInstance>>, Serializable {
        /**
         * 
         */
        private static final long serialVersionUID = 5813705474478664901L;

        public int compare(TreeSet<PatternInstance> t1, TreeSet<PatternInstance> t2) {
            InstanceComparator i = new InstanceComparator();
            PatternInstance v1 = t1.first();
            PatternInstance v2 = t2.first();
            return i.compare(v1, v2);
        }
    }

    static class InstanceComparator implements Comparator<PatternInstance>, Serializable {
        /**
         * 
         */
        private static final long serialVersionUID = 7403013395596959125L;

        public int compare(PatternInstance p1, PatternInstance p2) {
            EntryComparator e = new EntryComparator();
            if (e.compare(p1.getEntry(), p2.getEntry()) != 0) {
                return e.compare(p1.getEntry(), p2.getEntry());
            }
            if (p1.getX() > p2.getX())
                return 1;
            if (p1.getX() < p2.getX())
                return -1;
            if (p1.getY() > p2.getY())
                return 1;
            if (p1.getY() < p2.getY())
                return -1;
            return 0;
        }
    }

    static public class EntryComparator implements Comparator<PatternEntry>, Serializable {
        /**
         * 
         */
        private static final long serialVersionUID = 4092108741360732815L;

        public int compare(PatternEntry p1, PatternEntry p2) {
            if (p1 == null && p2 == null)
                return 0;
            else if (p1 == null)
                return 1;
            else if (p2 == null)
                return -1;
            else if (p1.getWrapper().getW() != p2.getWrapper().getW())
                return p1.getWrapper().getW() - p2.getWrapper().getW();
            else if (p1.getWrapper().getH() != p2.getWrapper().getH())
                return p1.getWrapper().getH() - p2.getWrapper().getH();
            else if (!Arrays.deepEquals(p1.getCells(), p2.getCells())) {
                for (int x = 0; x < p1.getWrapper().getW(); x++) {
                    for (int y = 0; y < p1.getWrapper().getH(); y++) {
                        if (p1.getCells()[x][y] > p2.getCells()[x][y])
                            return 1;
                        if (p1.getCells()[x][y] < p2.getCells()[x][y])
                            return -1;
                    }
                }
            }
            return 0;
        }
    }

    /*public static class IntArrayComparator implements Comparator<int[]>, Serializable
    {
        
       private static final long serialVersionUID = 2961394193017916069L;
        
       @Override
       public int compare(int[] o1, int[] o2)
       {
     if (o1 == null && o2 == null)
        return 0;
     else if (o1 == null)
        return 1;
     else if (o2 == null)
        return -1;
     for (int index = 0; index < o1.length && index < o2.length; index++)
     {
        if (o1[index] > o2[index])
           return -1;
        if (o1[index] < o2[index])
           return 1;
     }
     if (o1.length > o2.length)
        return -1;
     if (o1.length < o2.length)
        return 1;
     return 0;
       }
           
    }*/

    static LinkedList<PatternInstance> massMerge(Set<TreeSet<PatternInstance>> collisions,
            LinkedList<PatternInstance> instances, ReferenceMap<PatternWrapper, PatternEntry> knownPatterns,
            Ruleset rule) {
        PatternInstance currentInstances = null;
        for (ListIterator<PatternInstance> i = instances.listIterator(); i.hasNext();) {
            currentInstances = i.next();
            boolean shouldRemove = false;
            for (TreeSet<PatternInstance> groups : collisions) {
                if (groups.contains(currentInstances)) {
                    shouldRemove = true;
                    break;
                }
            }
            if (shouldRemove)
                i.remove();
        }

        for (TreeSet<PatternInstance> group : collisions) {
            TreeSet<PatternInstance> runningParts = group;
            boolean stillFindingParts = true;

            while (stillFindingParts) {
                stillFindingParts = false;

                eachMatchLoop: for (PatternInstance part1 : runningParts)
                    for (PatternInstance part2 : runningParts)
                        if (part1 != part2 && part1.collides(rule, part2)) {
                            stillFindingParts = true;
                            runningParts.remove(part1);
                            runningParts.remove(part2);
                            runningParts.add(part1.merge(knownPatterns, part2));
                            break eachMatchLoop;
                        }
            }

            for (PatternInstance part : runningParts) {
                instances.add(part);
            }
        }

        return instances;

    }

    public static byte getByte(byte[][] array, int xCoord, int yCoord) {
        if (xCoord < 0 || xCoord >= array.length)
            return 0;
        if (yCoord < 0 || yCoord >= array[0].length)
            return 0;
        return array[xCoord][yCoord];
    }

    public static boolean isActive(boolean[][] array, int xCoord, int yCoord) {
        if (xCoord < 0 || xCoord >= array.length)
            return false;
        if (yCoord < 0 || yCoord >= array[0].length)
            return false;
        return array[xCoord][yCoord];
    }
}