package org.rubyspa.droidgol;

import android.util.Pair;

import java.util.HashMap;
import java.util.Map;

public class Game {

    private final Pair<Integer, Integer> dimensions;
    private Map<Pair<Integer, Integer>, Boolean> state;

    public Game(final Integer width, final Integer height) {
        this.dimensions = Pair.create(width, height);
    }

    public Game(final Integer width, final Integer height, final Map state) {
        this(width, height);
        this.state = initializeState(state);
    }

    private Map<Pair<Integer, Integer>, Boolean> initializeState(final Map<Pair<Integer, Integer>, Boolean> state) {
        Map<Pair<Integer, Integer>, Boolean> newState = new HashMap<Pair<Integer, Integer>, Boolean>();
        final Integer width = dimensions.first;
        final Integer height = dimensions.second;
        for (int row = 1; row <= height; row++) {
            for (int column = 1; column <= width; column++) {
                Pair<Integer, Integer> coordinates = Pair.create(column, row);
                if (state.get(coordinates) == Boolean.TRUE) {
                    newState.put(coordinates, Boolean.TRUE);
                } else {
                    newState.put(coordinates, Boolean.FALSE);
                }
            }
        }
        return newState;
    }

    public Pair<Integer, Integer> dimensions() {
        return dimensions;
    }

    public boolean stateAt(Pair<Integer, Integer> coordinates) {
        return state.get(wrapAroundBorders(coordinates));
    }

    private Pair<Integer, Integer> wrapAroundBorders(Pair<Integer, Integer> unwrapped) {
        int x_wrapped = unwrapped.first < 1 ? dimensions.first : unwrapped.first;
        x_wrapped = x_wrapped > dimensions.first ? 1 : x_wrapped;
        int y_wrapped = unwrapped.second < 1 ? dimensions.second : unwrapped.second;
        y_wrapped = y_wrapped > dimensions.second ? 1 : y_wrapped;
        return Pair.create(x_wrapped, y_wrapped);
    }

    public Integer neighbors(Pair<Integer, Integer> coordinates) {
        int neighbors = 0;
        for (int x = coordinates.first - 1; x <= coordinates.first + 1; x++) {
            for (int y = coordinates.second - 1; y <= coordinates.second + 1; y++) {
                if (stateAt(Pair.create(x, y)) == Boolean.TRUE) {
                    neighbors++;
                }
            }
        }
        if (stateAt(coordinates) == Boolean.TRUE) neighbors--;
        return neighbors;
    }

    public Map<Pair<Integer, Integer>, Boolean> evolve() {
        Map<Pair<Integer, Integer>, Boolean> nextState = new HashMap<Pair<Integer, Integer>, Boolean>();
        for (Pair<Integer, Integer> coordinates : state.keySet()) {
            nextState.put(coordinates, Rules.apply(neighbors(coordinates), stateAt(coordinates)));
        }
        return nextState;
    }
}

@@ -98,16 +98,41 @@
 til.Map;
+%0Aimport java.util.Random;
 %0A%0Apublic
@@ -367,24 +367,60 @@
 h, height);%0A
+        this.state = randomState();%0A
     %7D%0A%0A    p
@@ -513,32 +513,32 @@
 width, height);%0A
-
         this.sta
@@ -565,32 +565,558 @@
 (state);%0A    %7D%0A%0A
+    private Map%3CPair%3CInteger, Integer%3E, Boolean%3E randomState() %7B%0A        Map%3CPair%3CInteger, Integer%3E, Boolean%3E randomState = new HashMap%3CPair%3CInteger, Integer%3E, Boolean%3E();%0A        final Integer width = dimensions.first;%0A        final Integer height = dimensions.second;%0A        for (int row = 1; row %3C height; row++) %7B%0A            for (int column = 1; column %3C width; column++) %7B%0A                randomState.put(Pair.create(column, row), new Random().nextBoolean());%0A            %7D%0A        %7D%0A        return randomState;%0A    %7D%0A%0A
     private Map%3C

add random (initial) state