@Override
  public Map generateMap() {
    Tile[][] grid = new Tile[length][length];

    for (int i = 0; i < grid.length; i++) {
      for (int j = 0; j < grid[i].length; j++) {
        grid[i][j] = new House(i, j);
      }
    }

    Map m = new Map(grid, new ArrayList<Car>());

    for (int t = 0; t < 3; t++) {
      for (int i = 0; i < length; i += 4) {
        if (Math.random() < .85) {
          int start = (int) (Math.random() * length / 2) * 2;
          int width = (int) (Math.random() * (length - start - 6) / 2) * 2 + 6;

          m.createHorizontalRoad(start, i, width, 2, 1);
        }
      }

      for (int i = 0; i < length; i += 4) {
        if (Math.random() < .85) {
          int start = (int) (Math.random() * length / 2) * 2;
          int width = (int) (Math.random() * (length - start - 6) / 2) * 2 + 6;

          m.createVerticalRoad(i, start, width, 2, 1);
        }
      }
    }

    removeIslands(m);

    ArrayList<Road> roads = new ArrayList<Road>();

    for (Tile[] a : grid) {
      for (Tile b : a) {
        if (b instanceof Road && !(b instanceof TrafficLight)) {
          roads.add((Road) b);
        }
      }
    }
    if (!assignSpeeds(m, roads))
      for (int i = 0; i < 30; i++) System.out.println("MAPGEN DONE GOOFED");

    for (int i = 0; i < cars; i++) {
      Road start, end;

      do {
        start = roads.get((int) (roads.size() * Math.random()));
        end = roads.get((int) (roads.size() * Math.random()));
      } while (start == end);

      m.placeCar(new Car(start.x, start.y, end.x, end.y, m, 0));
    }

    return m;
  }
  private boolean assignSpeeds(Map m, ArrayList<Road> roads) {
    int[][] speeds = new int[m.getLengthX()][m.getLengthY()];
    int count = 0;
    for (Road r : roads) {

      Tile[] adjTiles = getAdjTiles(m.grid, m.grid[r.getX()][r.getY()]);
      Road start = null;
      for (int i = 0; i < 4; i++) {
        if (adjTiles[i] instanceof TrafficLight) {
          start = r;
        }
        if (adjTiles[i] == null || adjTiles[i] instanceof NonRoad) {
          if (i == r.getDirection() || i == Math.abs(r.getDirection() - 4)) {
            start = r;
          }
        }
      }

      if (start != null) {
        int dir = start.getDirection();
        int length = 1;
        Tile t = r;

        //       if(m.getInDir(r,dir) != null){
        t = m.getInDir(r, dir);

        if (t instanceof TrafficLight || t == null || t instanceof NonRoad) {

          int reverseDir = (dir + 2 > 3) ? dir - 2 : dir + 2;
          if (m.getInDir(r, reverseDir) != null) t = m.getInDir(r, reverseDir);

          while (!(t == null || t instanceof TrafficLight || t instanceof NonRoad)) {

            length++;
            if (m.getInDir(t, reverseDir) != null) t = m.getInDir(t, reverseDir);
            else break;
          }
          for (int i = 0; i < length; i++) {
            t = m.getInDir(t, dir); // reverse direction
            speeds[t.getX()][t.getY()] = determineSpeed(length);
          }

        } else {

          while (!(t == null || t instanceof TrafficLight || t instanceof NonRoad)) {

            length++;
            if (m.getInDir(t, dir) != null) t = m.getInDir(t, dir);
            else break;
          }
          int reverseDir = (dir + 2 > 3) ? dir - 2 : dir + 2;

          for (int i = 0; i < length; i++) {
            t = m.getInDir(t, reverseDir); // reverse directions
            speeds[t.getX()][t.getY()] = determineSpeed(length);
          }
        }
      }
      //   }
      count++;
    }
    for (Road r : roads) {
      r.setSpeed(speeds[r.getX()][r.getY()]);
    }
    return true;
  }