diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..664c5544
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+*.lua text eol=lf
+*.md text eol=lf
\ No newline at end of file
diff --git a/docs/Index.md b/docs/Index.md
index 02053b6e..913c042c 100644
--- a/docs/Index.md
+++ b/docs/Index.md
@@ -1,6 +1,6 @@
-## RedMew Documentation Index
- - [Installing and Using the RedMew Scenario](Installation.md)
- - [Creating a New Scenario Using the RedMew Framework](NewScenario.md)
-
-### Scenario Specific Documentation
- - [Diggy Installation and Configuration](scenarios/Diggy.md)
+## RedMew Documentation Index
+ - [Installing and Using the RedMew Scenario](Installation.md)
+ - [Creating a New Scenario Using the RedMew Framework](NewScenario.md)
+
+### Scenario Specific Documentation
+ - [Diggy Installation and Configuration](scenarios/Diggy.md)
diff --git a/docs/Installation.md b/docs/Installation.md
index 663158c9..b462e761 100644
--- a/docs/Installation.md
+++ b/docs/Installation.md
@@ -1,49 +1,49 @@
-## Installing and Using the RedMew Scenario
-Some scenarios have more detailed information, please check [the index](Index.md) before continuing with the generic
-RedMew installation. To install the RedMew scenario directly into something playable, [download the
-archive](https://github.com/Valansch/RedMew/archive/develop.zip) and take the next step based on your Operating System.
-
-- **Windows**: extract the the zip file into `%appdata%\Factorio\Scenarios\RedMew`
-- **MacOS**: extract the the zip file into `~/Library/Application Support/factorio/Scenarios/RedMew`
-- **Linux**: extract the the zip file into `~/.factorio/scenarios/RedMew`
-
-Make sure it's called RedMew and there's a `control.lua` in the root of that directory. If you are using the RedMew
-scenario for a public-facing multi-player server, be sure to provide attribution back to github and keep links to the
-Discord, Patreon and website intact.
-
-> _Note_: these locations are based on the default configuration [defined by
-factorio](https://wiki.factorio.com/Application_directory). If your installation is not default, you have to find your
-scenarios directory in another way.
-
-## Generating maps
-There are 3 ways to generate maps using our scenario: Vanilla, FactorioMapConverter and Custom Maps.
-
-### Vanilla
-Start the scenario from the scenario menu and you are ready to go. Additionally you can turn features on or off via
-[`control.lua`](../control.lua) if desired.
-
-### Custom Maps
-There are many pre-made map modules that can be combined to create a unique map.
-
-Map module previews can be found in [map_gen/data/.map_previews](../map_gen/data/.map_previews). You can select and
-activate a module by removing the `--` in front of the require in [`map_layout.lua`](../map_layout.lua).
-
-You can mix as many modules as you want, as long as they logically fit together.
-
-### FactorioMapConverter (Windows only)
-
-You can generate your own maps from images. First convert the image file into a lua file (For example `image_data.lua`).
-Then use our scenario to load the `image_data.lua` file and generate the map from it.
-
-To create your own map preview:
-1. Download the Map Converter [here](https://github.com/grilledham/FactorioMapConverter/releases) to generate the
-   `image_data.lua`.
-2. Place your `image_data.lua` file in the `map_gen/data/presets/` directory.
-3. Create new lua file (for example `my_image.lua`) inside the folder `map_gen/presets/`. This file is used to configure
-   your map (scale, translate etc.). To do this, you can copy `map_gen/presets/template.lua` and replace line 8 to point
-   to your `image_data.lua`
-4. Load your new preset by adding a new line to `map_layout.lua`. This should look similar to this:
-    ```lua
-    MAP_GEN = require "map_gen.presets.my_image.lua"
-    ```
-5. Load the scenario from the scenario menu.
+## Installing and Using the RedMew Scenario
+Some scenarios have more detailed information, please check [the index](Index.md) before continuing with the generic
+RedMew installation. To install the RedMew scenario directly into something playable, [download the
+archive](https://github.com/Valansch/RedMew/archive/develop.zip) and take the next step based on your Operating System.
+
+- **Windows**: extract the the zip file into `%appdata%\Factorio\Scenarios\RedMew`
+- **MacOS**: extract the the zip file into `~/Library/Application Support/factorio/Scenarios/RedMew`
+- **Linux**: extract the the zip file into `~/.factorio/scenarios/RedMew`
+
+Make sure it's called RedMew and there's a `control.lua` in the root of that directory. If you are using the RedMew
+scenario for a public-facing multi-player server, be sure to provide attribution back to github and keep links to the
+Discord, Patreon and website intact.
+
+> _Note_: these locations are based on the default configuration [defined by
+factorio](https://wiki.factorio.com/Application_directory). If your installation is not default, you have to find your
+scenarios directory in another way.
+
+## Generating maps
+There are 3 ways to generate maps using our scenario: Vanilla, FactorioMapConverter and Custom Maps.
+
+### Vanilla
+Start the scenario from the scenario menu and you are ready to go. Additionally you can turn features on or off via
+[`control.lua`](../control.lua) if desired.
+
+### Custom Maps
+There are many pre-made map modules that can be combined to create a unique map.
+
+Map module previews can be found in [map_gen/data/.map_previews](../map_gen/data/.map_previews). You can select and
+activate a module by removing the `--` in front of the require in [`map_layout.lua`](../map_layout.lua).
+
+You can mix as many modules as you want, as long as they logically fit together.
+
+### FactorioMapConverter (Windows only)
+
+You can generate your own maps from images. First convert the image file into a lua file (For example `image_data.lua`).
+Then use our scenario to load the `image_data.lua` file and generate the map from it.
+
+To create your own map preview:
+1. Download the Map Converter [here](https://github.com/grilledham/FactorioMapConverter/releases) to generate the
+   `image_data.lua`.
+2. Place your `image_data.lua` file in the `map_gen/data/presets/` directory.
+3. Create new lua file (for example `my_image.lua`) inside the folder `map_gen/presets/`. This file is used to configure
+   your map (scale, translate etc.). To do this, you can copy `map_gen/presets/template.lua` and replace line 8 to point
+   to your `image_data.lua`
+4. Load your new preset by adding a new line to `map_layout.lua`. This should look similar to this:
+    ```lua
+    MAP_GEN = require "map_gen.presets.my_image.lua"
+    ```
+5. Load the scenario from the scenario menu.
diff --git a/docs/NewScenario.md b/docs/NewScenario.md
index 87774181..f6b635a2 100644
--- a/docs/NewScenario.md
+++ b/docs/NewScenario.md
@@ -1,28 +1,28 @@
-## Creating a New Scenario Using the RedMew Framework
-To add a new scenario and make it available to everyone that wants to use RedMew, make a Pull Request on github to
-request adding your scenario to the repository.
-
-### Starting From Scratch
-Depending on the size of the scenario, it could be desired to have its own dedicated directory. By default a scenario
-is added in `map_gen/combined/your_scenario.lua`.
-
-#### Step 1
-If you're not experienced with git, it's advised to read up on how git works first or ask someone else to help out. To
-get your change into the repository, you need to [fork the repository](https://help.github.com/articles/fork-a-repo/)
-and eventually make your Pull Request from there. [Clone](https://help.github.com/articles/cloning-a-repository/) the
-fork to your local environment and get your favorite IDE or Editor ready.
-
-#### Step 2
-Small scenarios can go into a single lua file, bigger scenarios might need their own dedicated directory. To follow the
-RedMew structure for scenarios, create your scenario file: `map_gen/combined/your_scenario_file.lua`.
-
-#### Step 3 (Optional)
-If you plan on making a bigger scenario, create a directory: `map_gen/combined/your_scenario_file/` where you can place
-your scenario specific lua files.
-
-#### Step 4
-Regardless, the `map_gen/combined/your_scenario_file.lua` file will be the entry point for your scenario and will be
-loaded via `map_layout.lua`. Underneath `--combined--`, add your require: `require map_gen.combined.your_scenario_file`.
-
-When making the Pull Request, make sure to comment the require in `map_layout.lua` as by default it should be off. To
-enable debugging and get some extra feedback during development, enable `_DEBUG` in `config.lua`.
+## Creating a New Scenario Using the RedMew Framework
+To add a new scenario and make it available to everyone that wants to use RedMew, make a Pull Request on github to
+request adding your scenario to the repository.
+
+### Starting From Scratch
+Depending on the size of the scenario, it could be desired to have its own dedicated directory. By default a scenario
+is added in `map_gen/combined/your_scenario.lua`.
+
+#### Step 1
+If you're not experienced with git, it's advised to read up on how git works first or ask someone else to help out. To
+get your change into the repository, you need to [fork the repository](https://help.github.com/articles/fork-a-repo/)
+and eventually make your Pull Request from there. [Clone](https://help.github.com/articles/cloning-a-repository/) the
+fork to your local environment and get your favorite IDE or Editor ready.
+
+#### Step 2
+Small scenarios can go into a single lua file, bigger scenarios might need their own dedicated directory. To follow the
+RedMew structure for scenarios, create your scenario file: `map_gen/combined/your_scenario_file.lua`.
+
+#### Step 3 (Optional)
+If you plan on making a bigger scenario, create a directory: `map_gen/combined/your_scenario_file/` where you can place
+your scenario specific lua files.
+
+#### Step 4
+Regardless, the `map_gen/combined/your_scenario_file.lua` file will be the entry point for your scenario and will be
+loaded via `map_layout.lua`. Underneath `--combined--`, add your require: `require map_gen.combined.your_scenario_file`.
+
+When making the Pull Request, make sure to comment the require in `map_layout.lua` as by default it should be off. To
+enable debugging and get some extra feedback during development, enable `_DEBUG` in `config.lua`.
diff --git a/docs/scenarios/Diggy.md b/docs/scenarios/Diggy.md
index b2065d7c..281725ff 100644
--- a/docs/scenarios/Diggy.md
+++ b/docs/scenarios/Diggy.md
@@ -1,79 +1,79 @@
-## Diggy Installation and Configuration
-Diggy is a custom [RedMew](../../README.md) scenario. You start out with nothing but a market, your pick-axe and some
-walls [deep, deep in the mine](https://www.youtube.com/watch?v=ov5pxaIbJlM). The goal is to launch a rocket, but be
-careful, there's not a lot of space and the mine is unstable!
-
-- Gameplay: https://www.youtube.com/watch?v=J3lheDK-6Cw
-- Time lapse video: https://www.youtube.com/watch?v=4cRsx-wl_fk (By Namelesshunter Gaming)
-
-> _Note_: Scenarios- also known as soft-mods- are scripted maps. They can be played online without having to download
-any mods as the script is included in the map.
-
-### Scenario Information
-The idea of Diggy is similar to vanilla, except that it greatly changes how to build your factory. As you're in a cave,
-each rock you dig, each support entity you remove and every tile you mine, can cause a collapse. You can use walls,
-stone paths and (refined) concrete floor to increase the strength of your mine and reduce the chance of a collapse.
-
-Whenever you place or remove a wall for example, the stress level of the area around it (9x9 tiles) will rise or lower.
-When a certain threshold is reached, the cave will collapse. You can stop this by quickly placing walls or run away as
-fast as you can. Letting the cave collapse _will_ destroy structures below it! The recommended pattern on dirt is to
-place a wall every 4th tile. Using stone paths and concrete will increase this to 5 tiles while refined concrete will
-make it 6.
-
-## How to start Diggy for Single-player mode
-
-#### Step 1
-Download the zip file from
-[https://github.com/Valansch/RedMew/archive/develop.zip](https://github.com/Valansch/RedMew/archive/develop.zip)
-
-#### Step 2
-- **Windows**: extract the the zip file into `%appdata%\Factorio\Scenarios\Diggy`
-- **MacOS**: extract the the zip file into `~/Library/Application Support/factorio/Scenarios/Diggy`
-- **Linux**: extract the the zip file into `~/.factorio/scenarios/Diggy`
-
-Make sure it's called Diggy and there's a `control.lua` in the root of that directory.
-
-> _Note_: these locations are based on the default configuration [defined by
-factorio](https://wiki.factorio.com/Application_directory). If your installation is not default, you have to find your
-scenarios directory in another way.
-
-#### Step 3
-Open `map_layout.lua` in that directory and look for `--require "map_gen.combined.diggy"`.
-Change this to `require "map_gen.combined.diggy"`, by removing the double dashes.
-
-#### Step 4
-In factorio start either a local or online game via Scenarios. Select `Diggy` under
-`User scenarios` and start it up.
-
-> _Note:_ Downloading the latest version might not always be a functional version, please consult on discord for a
-working version if this is the case.
-
-#### Step 5 (optional)
-Diggy is designed to work for at least 15 players online, working together. It's advised to change the configuration
-to adjust the difficulty for your needs. You can find the config in `map_gen/Diggy/Config.lua`. Most options should be
-well-explained. For Single-player it's recommend to enable cheats with modified values. You can change the starting
-items and some pre-defined cheat values (if cheats are enabled) under the `SetupPlayer` config item.
-
-## Configuring Diggy
-
-### Changing or Disabling Biter Spawning
-You can find the biter spawning feature in the config file under `AlienSpawner`. If you don't want biters to spawn
-according to the Diggy scenario, turn this feature off completely.
-
-### Disabling Collapses
-While one of the core features, it can also be fun to play without. To turn off collapses completely, you can turn off
-this feature under `DiggyCaveCollapse`. If you experience performance issues while digging, you can turn off this
-feature as well as it can be quite heavy.
-
-### Configuring Resource Spawning
-At the moment, Diggy is not yet using any of the build-in mechanics to spawn resources and you will have to manually add
-them. The resource spawning mechanism is quite complex, so don't hesitate to us how to configure it on Discord. Most
-basic configuration can be found under `ScatteredResources`. To customize the resource weights, you have to configure
-those specifics in the `map_gen/Diggy/Orepattern` directory. Resources are defined with a weight, meaning you can add
-your own resources (for example bobs or angels) with a value and the scenario will automatically calculate the proper
-spawn chances.
-
-### Adding Market Items
-Items can be configured by adding the desired item under the `MarketExchange` configuration. You only have to define a
-level at which it unlocks, a price or prices in case it can cost more, and what the item prototype is. For a list of
-items, you can look up each possible item on the [Factorio raw data page](https://wiki.factorio.com/Data.raw#item).
+## Diggy Installation and Configuration
+Diggy is a custom [RedMew](../../README.md) scenario. You start out with nothing but a market, your pick-axe and some
+walls [deep, deep in the mine](https://www.youtube.com/watch?v=ov5pxaIbJlM). The goal is to launch a rocket, but be
+careful, there's not a lot of space and the mine is unstable!
+
+- Gameplay: https://www.youtube.com/watch?v=J3lheDK-6Cw
+- Time lapse video: https://www.youtube.com/watch?v=4cRsx-wl_fk (By Namelesshunter Gaming)
+
+> _Note_: Scenarios- also known as soft-mods- are scripted maps. They can be played online without having to download
+any mods as the script is included in the map.
+
+### Scenario Information
+The idea of Diggy is similar to vanilla, except that it greatly changes how to build your factory. As you're in a cave,
+each rock you dig, each support entity you remove and every tile you mine, can cause a collapse. You can use walls,
+stone paths and (refined) concrete floor to increase the strength of your mine and reduce the chance of a collapse.
+
+Whenever you place or remove a wall for example, the stress level of the area around it (9x9 tiles) will rise or lower.
+When a certain threshold is reached, the cave will collapse. You can stop this by quickly placing walls or run away as
+fast as you can. Letting the cave collapse _will_ destroy structures below it! The recommended pattern on dirt is to
+place a wall every 4th tile. Using stone paths and concrete will increase this to 5 tiles while refined concrete will
+make it 6.
+
+## How to start Diggy for Single-player mode
+
+#### Step 1
+Download the zip file from
+[https://github.com/Valansch/RedMew/archive/develop.zip](https://github.com/Valansch/RedMew/archive/develop.zip)
+
+#### Step 2
+- **Windows**: extract the the zip file into `%appdata%\Factorio\Scenarios\Diggy`
+- **MacOS**: extract the the zip file into `~/Library/Application Support/factorio/Scenarios/Diggy`
+- **Linux**: extract the the zip file into `~/.factorio/scenarios/Diggy`
+
+Make sure it's called Diggy and there's a `control.lua` in the root of that directory.
+
+> _Note_: these locations are based on the default configuration [defined by
+factorio](https://wiki.factorio.com/Application_directory). If your installation is not default, you have to find your
+scenarios directory in another way.
+
+#### Step 3
+Open `map_layout.lua` in that directory and look for `--require "map_gen.combined.diggy"`.
+Change this to `require "map_gen.combined.diggy"`, by removing the double dashes.
+
+#### Step 4
+In factorio start either a local or online game via Scenarios. Select `Diggy` under
+`User scenarios` and start it up.
+
+> _Note:_ Downloading the latest version might not always be a functional version, please consult on discord for a
+working version if this is the case.
+
+#### Step 5 (optional)
+Diggy is designed to work for at least 15 players online, working together. It's advised to change the configuration
+to adjust the difficulty for your needs. You can find the config in `map_gen/Diggy/Config.lua`. Most options should be
+well-explained. For Single-player it's recommend to enable cheats with modified values. You can change the starting
+items and some pre-defined cheat values (if cheats are enabled) under the `SetupPlayer` config item.
+
+## Configuring Diggy
+
+### Changing or Disabling Biter Spawning
+You can find the biter spawning feature in the config file under `AlienSpawner`. If you don't want biters to spawn
+according to the Diggy scenario, turn this feature off completely.
+
+### Disabling Collapses
+While one of the core features, it can also be fun to play without. To turn off collapses completely, you can turn off
+this feature under `DiggyCaveCollapse`. If you experience performance issues while digging, you can turn off this
+feature as well as it can be quite heavy.
+
+### Configuring Resource Spawning
+At the moment, Diggy is not yet using any of the build-in mechanics to spawn resources and you will have to manually add
+them. The resource spawning mechanism is quite complex, so don't hesitate to us how to configure it on Discord. Most
+basic configuration can be found under `ScatteredResources`. To customize the resource weights, you have to configure
+those specifics in the `map_gen/Diggy/Orepattern` directory. Resources are defined with a weight, meaning you can add
+your own resources (for example bobs or angels) with a value and the scenario will automatically calculate the proper
+spawn chances.
+
+### Adding Market Items
+Items can be configured by adding the desired item under the `MarketExchange` configuration. You only have to define a
+level at which it unlocks, a price or prices in case it can cost more, and what the item prototype is. For a list of
+items, you can look up each possible item on the [Factorio raw data page](https://wiki.factorio.com/Data.raw#item).
diff --git a/features/report.lua b/features/report.lua
index 293c3bf2..2467dae3 100644
--- a/features/report.lua
+++ b/features/report.lua
@@ -1,360 +1,360 @@
-local Module = {}
-
-local Gui = require("utils.gui")
-local Utils = require("utils.utils");
-local Game = require 'utils.game'
-
-local report_frame_name = Gui.uid_name()
-local report_close_button_name = Gui.uid_name()
-local report_tab_button_name = Gui.uid_name()
-local jail_offender_button_name = Gui.uid_name()
-local report_body_name = Gui.uid_name()
-local prefix = '------------------NOTICE-------------------'
-local prefix_e = '--------------------------------------------'
-
-global.reports = {}
-global.player_report_data = {}
-
-
-local function draw_report(parent, report_id)
-    local report = global.reports[report_id]
-    if report_id == 0 or not report then
-        parent.add {type = "label", caption="No reports yet."}
-        return
-    end
-
-    local reported_player_name = Game.get_player_by_index(report.reported_player_index).name
-    local reporting_player_name = "<script>"
-    if report.reporting_player_index then
-      reporting_player_name = Game.get_player_by_index(report.reporting_player_index).name
-    end
-    local time = Utils.format_time(report.tick)
-    local time_ago = Utils.format_time(game.tick - report.tick)
-
-    local message = report.message
-    Gui.clear(parent)
-
-    parent.add {type="label", caption="Offender: " .. reported_player_name}
-    local msg_label_pane = parent.add {type="scroll-pane", vertical_scroll_policy = "auto-and-reserve-space", horizontal_scroll_policy="never"}
-    msg_label_pane.style.maximal_height = 400
-    local msg_label = msg_label_pane.add {type="label", caption="Message: " .. message}
-    local jail_offender_button = parent.add {type = 'button', name = jail_offender_button_name, caption = 'Jail ' .. reported_player_name}
-    jail_offender_button.style.height = 24
-    jail_offender_button.style.font = 'default-small'
-    jail_offender_button.style.top_padding = 0
-    jail_offender_button.style.bottom_padding = 0
-    jail_offender_button.style.left_padding = 0
-    jail_offender_button.style.right_padding = 0
-    msg_label.style.single_line = false
-    msg_label.style.maximal_width = 680
-    parent.add {type="label", caption=string.format("Time: %s (%s ago)", time, time_ago)}
-    parent.add {type="label", caption="Reported by: " .. reporting_player_name}
-end
-
-Module.show_reports = function(player)
-    local reports = global.reports or {}
-
-    local center = player.gui.center
-
-    local report_frame = center[report_frame_name]
-    if report_frame and report_frame.valid then
-        Gui.destroy(report_frame)
-    end
-
-    report_frame = center.add {
-        type = 'frame',
-        name = report_frame_name,
-        direction = 'vertical',
-        caption = 'User reports'
-    }
-    report_frame.style.maximal_width = 700
-    player.opened = report_frame
-
-    if #reports > 1 then
-        local scroll_pane = report_frame.add{type = "scroll-pane", horizontal_scroll_policy = "auto-and-reserve-space", vertical_scroll_policy="never"}
-        local tab_flow = scroll_pane.add{type="flow"}
-        for k,report in pairs(reports) do
-            local button_cell = tab_flow.add{type="flow", caption="reportuid" .. k}
-            button_cell.add {
-                type="button",
-                name=report_tab_button_name,
-                caption = Game.get_player_by_index(report.reported_player_index).name
-            }
-        end
-    end
-    local report_body = report_frame.add {type = "scroll-pane", name = report_body_name, horizontal_scroll_policy = "never", vertical_scroll_policy="never"}
-    report_frame.add {type = 'button', name = report_close_button_name, caption = 'Close'}
-
-    draw_report(report_body, #reports)
-end
-
-function Module.report(reporting_player, reported_player, message)
-    local player_index
-    if reporting_player then
-        player_index = reporting_player.index
-    end
-    table.insert(global.reports, {reporting_player_index = player_index, reported_player_index = reported_player.index, message = message, tick = game.tick})
-
-    local notified = false
-    for _,p in pairs(game.players) do
-        if p.admin and p.connected then
-            p.play_sound{path='utility/tutorial_notice', volume_modifier = 1}
-            Module.show_reports(p)
-            if p.afk_time < 3600 then notified = true end
-        end
-    end
-    if not notified then
-        for _,p in pairs(game.players) do
-            if p.admin then
-                Module.show_reports(p)
-            end
-        end
-    end
-end
-
-function Module.cmd_report(cmd)
-    local reporting_player = game.player
-    if reporting_player then
-        local params = {}
-        for param in string.gmatch(cmd.parameter, '%S+') do
-            table.insert(params, param)
-        end
-        if #params < 2 then
-            reporting_player.print('Please enter then name of the offender and the reason for the report.')
-            return nil
-        end
-        local reported_player_name = params[1] or ''
-        local reported_player = game.players[reported_player_name]
-
-        if not reported_player then
-            reporting_player.print(reported_player_name .. ' does not exist.')
-            return nil
-        end
-        Module.report(reporting_player, reported_player, string.sub(cmd.parameter, string.len(params[1]) + 2))
-    end
-end
-
--- Places a target in jail as long as player is admin or server
-function Module.jail(target_player, player)
-    -- Set the name of the jail permission group
-    local jail_name = 'Jail'
-
-    local print
-    local jailed_by
-    if player then
-        jailed_by = "a server admin"
-        print = player.print
-    else
-        jailed_by = "script for causing too many collapses"
-        print = log
-    end
-
-    if not target_player then
-        print('Unknown player.')
-        return
-    end
-
-    local permissions = game.permissions
-
-    -- Check if the permission group exists, if it doesn't, create it.
-    local permission_group = permissions.get_group(jail_name)
-    if not permission_group then
-        permission_group = permissions.create_group(jail_name)
-    end
-
-    if target_player.permission_group == permission_group then
-        print('Player ' .. target_player.name .. ' is already in jail.')
-        return
-    end
-
-    -- Set all permissions to disabled
-    for action_name, _ in pairs(defines.input_action) do
-        permission_group.set_allows_action(defines.input_action[action_name], false)
-    end
-    -- Enable writing to console to allow a person to speak
-    permission_group.set_allows_action(defines.input_action.write_to_console, true)
-    permission_group.set_allows_action(defines.input_action.edit_permission_group, true)
-
-    -- Kick player out of vehicle
-    target_player.driving=false
-    -- Add player to jail group
-    permission_group.add_player(target_player)
-    -- If a player is shooting when they're jailed they can't stop shooting, so we change their shooting state
-    if target_player.shooting_state.state ~= 0 then
-        target_player.shooting_state.state = {state = defines.shooting.not_shooting, position = {0,0}}
-    end
-
-    -- Check that it worked
-    if target_player.permission_group == permission_group then
-        -- Let admin know it worked, let target know what's going on.
-        print(target_player.name .. ' has been jailed. They have been advised of this.')
-        target_player.print(prefix)
-        target_player.print('You have been placed in jail by ' .. jailed_by .. '. The only action avaliable to you is chatting.')
-        target_player.print('Please respond to inquiries from the admins.', {r = 1, g = 1, b = 0, a = 1})
-        Utils.print_admins(target_player.name .. 'has been jailed by' .. player.name)
-        Utils.log_command(player, 'jail', target_player.name)
-    else
-        -- Let admin know it didn't work.
-        print('Something went wrong in the jailing of ' .. target_player.name .. '. You can still change their group via /permissions.')
-    end
-end
-
-function Module.unjail_player(cmd)
-    local default_group = 'Default'
-    local player = game.player
-    -- Check if the player can run the command
-    if player and not player.admin then
-        Utils.cant_run(cmd.name)
-        return
-    end
-    -- Check if the target is valid (copied from the invoke command)
-    local target = cmd['parameter']
-    if target == nil then
-        Game.player_print('Usage: /unjail <player>')
-        return
-    end
-
-    local target_player = game.players[target]
-    if not target_player then
-        Game.player_print('Unknown player.')
-        return
-    end
-
-    local permissions = game.permissions
-
-    -- Check if the permission group exists, if it doesn't, create it.
-    local permission_group = permissions.get_group(default_group)
-    if not permission_group then
-        permission_group = permissions.create_group(default_group)
-    end
-
-    local jail_permission_group = permissions.get_group('Jail')
-    if (not jail_permission_group) or target_player.permission_group ~= jail_permission_group then
-        Game.player_print('The player ' .. target .. ' is already not in Jail.')
-        return
-    end
-
-    -- Move player
-    permission_group.add_player(target)
-    -- Set player to a non-shooting state (solves a niche case where players jailed while shooting will be locked into a shooting state)
-    target_player.shooting_state.state = 0
-
-    -- Check that it worked
-    if target_player.permission_group == permission_group then
-        -- Let admin know it worked, let target know what's going on.
-        Game.player_print(target .. ' has been returned to the default group. They have been advised of this.')
-        target_player.print(prefix)
-        target_player.print('Your ability to perform actions has been restored', {r = 0, g = 1, b = 0, a = 1})
-        target_player.print(prefix_e)
-    else
-        -- Let admin know it didn't work.
-        Game.player_print(
-            'Something went wrong in the unjailing of ' ..
-                    target .. '. You can still change their group via /permissions and inform them.'
-        )
-    end
-end
-
-Gui.on_custom_close(
-    report_frame_name,
-    function(event)
-        Gui.destroy(event.element)
-    end
-)
-
-Gui.on_click(
-    report_close_button_name,
-    function(event)
-        Gui.destroy(event.element.parent)
-    end
-)
-
-Gui.on_click(
-    jail_offender_button_name,
-    function(event)
-        local target_name = string.sub(event.element.caption, 6)
-        local target = game.players[target_name]
-        Module.jail(target, event.player)
-    end
-)
-
-Gui.on_click(
-    report_tab_button_name,
-    function(event)
-        local center = event.player.gui.center
-        local report_frame = center[report_frame_name]
-        local report_uid_str = string.sub(event.element.parent.caption, 10)
-        local report_uid = tonumber(report_uid_str)
-        draw_report(report_frame[report_body_name], report_uid)
-    end
-)
-
-
-local reporting_popup_name = Gui.uid_name()
-local reporting_cancel_button_name = Gui.uid_name()
-local reporting_submit_button_name = Gui.uid_name()
-local reporting_input_name = Gui.uid_name()
-
-Module.spawn_reporting_popup = function(player, reported_player)
-
-    local center = player.gui.center
-
-    local reporting_popup = center[reporting_popup_name]
-    if reporting_popup and reporting_popup.valid then
-        Gui.destroy(reporting_popup)
-    end
-    reporting_popup = center.add {
-        type = 'frame',
-        name = reporting_popup_name,
-        direction = 'vertical',
-        caption = 'Report player ' .. reported_player.name
-    }
-    Gui.set_data(reporting_popup, {reported_player_index = reported_player.index})
-
-    reporting_popup.style.maximal_width = 500
-    player.opened = reporting_popup
-    reporting_popup.add {
-        type = 'label',
-        caption = 'Report message:'
-    }
-    local input = reporting_popup.add {type = 'text-box', name=reporting_input_name}
-    input.style.width = 400
-    input.style.height = 85
-    local button_flow = reporting_popup.add {type = "flow"}
-    button_flow.add {type = "button", name = reporting_submit_button_name, caption="Submit"}
-    button_flow.add {type = "button", name = reporting_cancel_button_name, caption="Cancel"}
-end
-
-Gui.on_custom_close(
-    reporting_popup_name,
-    function(event)
-        Gui.destroy(event.element)
-    end
-)
-
-Gui.on_click(
-    reporting_cancel_button_name,
-    function(event)
-        local frame = event.element.parent.parent
-        Gui.destroy(frame)
-    end
-)
-
-Gui.on_click(
-    reporting_submit_button_name,
-    function(event)
-        local frame = event.element.parent.parent
-        local msg = frame[reporting_input_name].text
-        local data = Gui.get_data(frame)
-        local reported_player_index = data["reported_player_index"]
-        local print = event.player.print
-
-        Gui.destroy(frame)
-        Module.report(event.player, Game.get_player_by_index(reported_player_index), msg)
-        print(prefix)
-        print("You have successfully reported the player: " .. Game.get_player_by_index(reported_player_index).name)
-        print(prefix_e)
-    end
-)
-
-return Module
+local Module = {}
+
+local Gui = require("utils.gui")
+local Utils = require("utils.utils");
+local Game = require 'utils.game'
+
+local report_frame_name = Gui.uid_name()
+local report_close_button_name = Gui.uid_name()
+local report_tab_button_name = Gui.uid_name()
+local jail_offender_button_name = Gui.uid_name()
+local report_body_name = Gui.uid_name()
+local prefix = '------------------NOTICE-------------------'
+local prefix_e = '--------------------------------------------'
+
+global.reports = {}
+global.player_report_data = {}
+
+
+local function draw_report(parent, report_id)
+    local report = global.reports[report_id]
+    if report_id == 0 or not report then
+        parent.add {type = "label", caption="No reports yet."}
+        return
+    end
+
+    local reported_player_name = Game.get_player_by_index(report.reported_player_index).name
+    local reporting_player_name = "<script>"
+    if report.reporting_player_index then
+      reporting_player_name = Game.get_player_by_index(report.reporting_player_index).name
+    end
+    local time = Utils.format_time(report.tick)
+    local time_ago = Utils.format_time(game.tick - report.tick)
+
+    local message = report.message
+    Gui.clear(parent)
+
+    parent.add {type="label", caption="Offender: " .. reported_player_name}
+    local msg_label_pane = parent.add {type="scroll-pane", vertical_scroll_policy = "auto-and-reserve-space", horizontal_scroll_policy="never"}
+    msg_label_pane.style.maximal_height = 400
+    local msg_label = msg_label_pane.add {type="label", caption="Message: " .. message}
+    local jail_offender_button = parent.add {type = 'button', name = jail_offender_button_name, caption = 'Jail ' .. reported_player_name}
+    jail_offender_button.style.height = 24
+    jail_offender_button.style.font = 'default-small'
+    jail_offender_button.style.top_padding = 0
+    jail_offender_button.style.bottom_padding = 0
+    jail_offender_button.style.left_padding = 0
+    jail_offender_button.style.right_padding = 0
+    msg_label.style.single_line = false
+    msg_label.style.maximal_width = 680
+    parent.add {type="label", caption=string.format("Time: %s (%s ago)", time, time_ago)}
+    parent.add {type="label", caption="Reported by: " .. reporting_player_name}
+end
+
+Module.show_reports = function(player)
+    local reports = global.reports or {}
+
+    local center = player.gui.center
+
+    local report_frame = center[report_frame_name]
+    if report_frame and report_frame.valid then
+        Gui.destroy(report_frame)
+    end
+
+    report_frame = center.add {
+        type = 'frame',
+        name = report_frame_name,
+        direction = 'vertical',
+        caption = 'User reports'
+    }
+    report_frame.style.maximal_width = 700
+    player.opened = report_frame
+
+    if #reports > 1 then
+        local scroll_pane = report_frame.add{type = "scroll-pane", horizontal_scroll_policy = "auto-and-reserve-space", vertical_scroll_policy="never"}
+        local tab_flow = scroll_pane.add{type="flow"}
+        for k,report in pairs(reports) do
+            local button_cell = tab_flow.add{type="flow", caption="reportuid" .. k}
+            button_cell.add {
+                type="button",
+                name=report_tab_button_name,
+                caption = Game.get_player_by_index(report.reported_player_index).name
+            }
+        end
+    end
+    local report_body = report_frame.add {type = "scroll-pane", name = report_body_name, horizontal_scroll_policy = "never", vertical_scroll_policy="never"}
+    report_frame.add {type = 'button', name = report_close_button_name, caption = 'Close'}
+
+    draw_report(report_body, #reports)
+end
+
+function Module.report(reporting_player, reported_player, message)
+    local player_index
+    if reporting_player then
+        player_index = reporting_player.index
+    end
+    table.insert(global.reports, {reporting_player_index = player_index, reported_player_index = reported_player.index, message = message, tick = game.tick})
+
+    local notified = false
+    for _,p in pairs(game.players) do
+        if p.admin and p.connected then
+            p.play_sound{path='utility/tutorial_notice', volume_modifier = 1}
+            Module.show_reports(p)
+            if p.afk_time < 3600 then notified = true end
+        end
+    end
+    if not notified then
+        for _,p in pairs(game.players) do
+            if p.admin then
+                Module.show_reports(p)
+            end
+        end
+    end
+end
+
+function Module.cmd_report(cmd)
+    local reporting_player = game.player
+    if reporting_player then
+        local params = {}
+        for param in string.gmatch(cmd.parameter, '%S+') do
+            table.insert(params, param)
+        end
+        if #params < 2 then
+            reporting_player.print('Please enter then name of the offender and the reason for the report.')
+            return nil
+        end
+        local reported_player_name = params[1] or ''
+        local reported_player = game.players[reported_player_name]
+
+        if not reported_player then
+            reporting_player.print(reported_player_name .. ' does not exist.')
+            return nil
+        end
+        Module.report(reporting_player, reported_player, string.sub(cmd.parameter, string.len(params[1]) + 2))
+    end
+end
+
+-- Places a target in jail as long as player is admin or server
+function Module.jail(target_player, player)
+    -- Set the name of the jail permission group
+    local jail_name = 'Jail'
+
+    local print
+    local jailed_by
+    if player then
+        jailed_by = "a server admin"
+        print = player.print
+    else
+        jailed_by = "script for causing too many collapses"
+        print = log
+    end
+
+    if not target_player then
+        print('Unknown player.')
+        return
+    end
+
+    local permissions = game.permissions
+
+    -- Check if the permission group exists, if it doesn't, create it.
+    local permission_group = permissions.get_group(jail_name)
+    if not permission_group then
+        permission_group = permissions.create_group(jail_name)
+    end
+
+    if target_player.permission_group == permission_group then
+        print('Player ' .. target_player.name .. ' is already in jail.')
+        return
+    end
+
+    -- Set all permissions to disabled
+    for action_name, _ in pairs(defines.input_action) do
+        permission_group.set_allows_action(defines.input_action[action_name], false)
+    end
+    -- Enable writing to console to allow a person to speak
+    permission_group.set_allows_action(defines.input_action.write_to_console, true)
+    permission_group.set_allows_action(defines.input_action.edit_permission_group, true)
+
+    -- Kick player out of vehicle
+    target_player.driving=false
+    -- Add player to jail group
+    permission_group.add_player(target_player)
+    -- If a player is shooting when they're jailed they can't stop shooting, so we change their shooting state
+    if target_player.shooting_state.state ~= 0 then
+        target_player.shooting_state.state = {state = defines.shooting.not_shooting, position = {0,0}}
+    end
+
+    -- Check that it worked
+    if target_player.permission_group == permission_group then
+        -- Let admin know it worked, let target know what's going on.
+        print(target_player.name .. ' has been jailed. They have been advised of this.')
+        target_player.print(prefix)
+        target_player.print('You have been placed in jail by ' .. jailed_by .. '. The only action avaliable to you is chatting.')
+        target_player.print('Please respond to inquiries from the admins.', {r = 1, g = 1, b = 0, a = 1})
+        Utils.print_admins(target_player.name .. 'has been jailed by' .. player.name)
+        Utils.log_command(player, 'jail', target_player.name)
+    else
+        -- Let admin know it didn't work.
+        print('Something went wrong in the jailing of ' .. target_player.name .. '. You can still change their group via /permissions.')
+    end
+end
+
+function Module.unjail_player(cmd)
+    local default_group = 'Default'
+    local player = game.player
+    -- Check if the player can run the command
+    if player and not player.admin then
+        Utils.cant_run(cmd.name)
+        return
+    end
+    -- Check if the target is valid (copied from the invoke command)
+    local target = cmd['parameter']
+    if target == nil then
+        Game.player_print('Usage: /unjail <player>')
+        return
+    end
+
+    local target_player = game.players[target]
+    if not target_player then
+        Game.player_print('Unknown player.')
+        return
+    end
+
+    local permissions = game.permissions
+
+    -- Check if the permission group exists, if it doesn't, create it.
+    local permission_group = permissions.get_group(default_group)
+    if not permission_group then
+        permission_group = permissions.create_group(default_group)
+    end
+
+    local jail_permission_group = permissions.get_group('Jail')
+    if (not jail_permission_group) or target_player.permission_group ~= jail_permission_group then
+        Game.player_print('The player ' .. target .. ' is already not in Jail.')
+        return
+    end
+
+    -- Move player
+    permission_group.add_player(target)
+    -- Set player to a non-shooting state (solves a niche case where players jailed while shooting will be locked into a shooting state)
+    target_player.shooting_state.state = 0
+
+    -- Check that it worked
+    if target_player.permission_group == permission_group then
+        -- Let admin know it worked, let target know what's going on.
+        Game.player_print(target .. ' has been returned to the default group. They have been advised of this.')
+        target_player.print(prefix)
+        target_player.print('Your ability to perform actions has been restored', {r = 0, g = 1, b = 0, a = 1})
+        target_player.print(prefix_e)
+    else
+        -- Let admin know it didn't work.
+        Game.player_print(
+            'Something went wrong in the unjailing of ' ..
+                    target .. '. You can still change their group via /permissions and inform them.'
+        )
+    end
+end
+
+Gui.on_custom_close(
+    report_frame_name,
+    function(event)
+        Gui.destroy(event.element)
+    end
+)
+
+Gui.on_click(
+    report_close_button_name,
+    function(event)
+        Gui.destroy(event.element.parent)
+    end
+)
+
+Gui.on_click(
+    jail_offender_button_name,
+    function(event)
+        local target_name = string.sub(event.element.caption, 6)
+        local target = game.players[target_name]
+        Module.jail(target, event.player)
+    end
+)
+
+Gui.on_click(
+    report_tab_button_name,
+    function(event)
+        local center = event.player.gui.center
+        local report_frame = center[report_frame_name]
+        local report_uid_str = string.sub(event.element.parent.caption, 10)
+        local report_uid = tonumber(report_uid_str)
+        draw_report(report_frame[report_body_name], report_uid)
+    end
+)
+
+
+local reporting_popup_name = Gui.uid_name()
+local reporting_cancel_button_name = Gui.uid_name()
+local reporting_submit_button_name = Gui.uid_name()
+local reporting_input_name = Gui.uid_name()
+
+Module.spawn_reporting_popup = function(player, reported_player)
+
+    local center = player.gui.center
+
+    local reporting_popup = center[reporting_popup_name]
+    if reporting_popup and reporting_popup.valid then
+        Gui.destroy(reporting_popup)
+    end
+    reporting_popup = center.add {
+        type = 'frame',
+        name = reporting_popup_name,
+        direction = 'vertical',
+        caption = 'Report player ' .. reported_player.name
+    }
+    Gui.set_data(reporting_popup, {reported_player_index = reported_player.index})
+
+    reporting_popup.style.maximal_width = 500
+    player.opened = reporting_popup
+    reporting_popup.add {
+        type = 'label',
+        caption = 'Report message:'
+    }
+    local input = reporting_popup.add {type = 'text-box', name=reporting_input_name}
+    input.style.width = 400
+    input.style.height = 85
+    local button_flow = reporting_popup.add {type = "flow"}
+    button_flow.add {type = "button", name = reporting_submit_button_name, caption="Submit"}
+    button_flow.add {type = "button", name = reporting_cancel_button_name, caption="Cancel"}
+end
+
+Gui.on_custom_close(
+    reporting_popup_name,
+    function(event)
+        Gui.destroy(event.element)
+    end
+)
+
+Gui.on_click(
+    reporting_cancel_button_name,
+    function(event)
+        local frame = event.element.parent.parent
+        Gui.destroy(frame)
+    end
+)
+
+Gui.on_click(
+    reporting_submit_button_name,
+    function(event)
+        local frame = event.element.parent.parent
+        local msg = frame[reporting_input_name].text
+        local data = Gui.get_data(frame)
+        local reported_player_index = data["reported_player_index"]
+        local print = event.player.print
+
+        Gui.destroy(frame)
+        Module.report(event.player, Game.get_player_by_index(reported_player_index), msg)
+        print(prefix)
+        print("You have successfully reported the player: " .. Game.get_player_by_index(reported_player_index).name)
+        print(prefix_e)
+    end
+)
+
+return Module
diff --git a/map_gen/Diggy/AlienEvolutionProgress.lua b/map_gen/Diggy/AlienEvolutionProgress.lua
index 7570fe29..5f3950c4 100644
--- a/map_gen/Diggy/AlienEvolutionProgress.lua
+++ b/map_gen/Diggy/AlienEvolutionProgress.lua
@@ -1,159 +1,159 @@
---[[-- info
-    Original (javascript) version: https://hastebin.com/udakacavap.js
-    Can be tested against: https://wiki.factorio.com/Enemies#Spawn_chances_by_evolution_factor
-]]
-
--- dependencies
-local Global = require 'utils.global'
-local random = math.random
-local round = math.round
-
--- this
-local AlienEvolutionProgress = {}
-
-local alien_cache = {
-    biters = {
-        evolution = -1,
-        cache = {},
-    },
-    spitters = {
-        evolution = -1,
-        cache = {},
-    },
-}
-
-Global.register({
-    alien_cache = alien_cache,
-}, function(tbl)
-    alien_cache = tbl.alien_cache
-end)
-
--- values are in the form {evolution, weight}
-local biters = {
-    {'small-biter',     {{0.0, 0.3}, {0.6, 0.0}}},
-    {'medium-biter',    {{0.2, 0.0}, {0.6, 0.3}, {0.7, 0.1}}},
-    {'big-biter',       {{0.5, 0.0}, {1.0, 0.4}}},
-    {'behemoth-biter',  {{0.9, 0.0}, {1.0, 0.3}}},
-}
-
-local spitters = {
-    {'small-biter',       {{0.0, 0.3}, {0.35, 0.0}}},
-    {'small-spitter',     {{0.25, 0.0}, {0.5, 0.3}, {0.7, 0.0}}},
-    {'medium-spitter',    {{0.4, 0.0}, {0.7, 0.3}, {0.9, 0.1}}},
-    {'big-spitter',       {{0.5, 0.0}, {1.0, 0.4}}},
-    {'behemoth-spitter',  {{0.9, 0.0}, {1.0, 0.3}}},
-}
-
-local function lerp(low, high, pos)
-    local s = high[1] - low[1];
-    local l = (pos - low[1]) / s;
-    return (low[2] * (1 - l)) + (high[2] * l)
-end
-
-local function get_values(map, evo)
-    local result = {}
-    local sum = 0
-
-    for _, data in pairs(map) do
-        local list = data[2];
-        local low = list[1];
-        local high = list[#list];
-
-        for _, val in pairs(list) do
-            if(val[1] <= evo and val[1] >  low[1]) then
-                low = val;
-            end
-            if(val[1] >= evo and val[1] < high[1]) then
-                high = val
-            end
-        end
-
-        local val
-        if (evo <= low[1]) then
-            val = low[2]
-        elseif (evo >= high[1]) then
-            val = high[2];
-        else
-            val = lerp(low, high, evo)
-        end
-        sum = sum + val;
-
-        result[data[1]] = val;
-    end
-
-    for index, _ in pairs(result) do
-        result[index] = result[index] / sum
-    end
-
-    return result;
-end
-
-local function get_name_by_random(collection)
-    local pre_calculated = random()
-    local current = 0
-
-    for name, probability in pairs(collection) do
-        current = current + probability
-        if (current >= pre_calculated) then
-            return name
-        end
-    end
-
-    Debug.print('AlienEvolutionProgress.get_name_by_random: Current \'' .. current .. '\' should be higher or equal to random \'' .. pre_calculated .. '\'')
-end
-
-function AlienEvolutionProgress.getBiterValues(evolution)
-    local evolution_value = round(evolution * 100)
-
-    if (alien_cache.biters.evolution < evolution_value) then
-        alien_cache.biters.evolution = evolution_value
-        alien_cache.biters.cache = get_values(biters, evolution)
-    end
-
-    return alien_cache.biters.cache
-end
-
-function AlienEvolutionProgress.getSpitterValues(evolution)
-    local evolution_value = round(evolution * 100)
-
-    if (alien_cache.spitters.evolution < evolution_value) then
-        alien_cache.spitters.evolution = evolution_value
-        alien_cache.spitters.cache = get_values(spitters, evolution)
-    end
-
-    return alien_cache.spitters.cache
-end
-
-function AlienEvolutionProgress.getBitersByEvolution(total_biters, evolution)
-    local biters_calculated = {}
-    local map = AlienEvolutionProgress.getBiterValues(evolution)
-
-    for i = 1, total_biters do
-        local name = get_name_by_random(map)
-        if (nil == biters_calculated[name]) then
-            biters_calculated[name] = 1
-        else
-            biters_calculated[name] = biters_calculated[name] + 1
-        end
-    end
-
-    return biters_calculated
-end
-
-function AlienEvolutionProgress.getSpittersByEvolution(total_spitters, evolution)
-    local spitters_calculated = {}
-    local map = AlienEvolutionProgress.getSpitterValues(evolution)
-
-    for i = 1, total_spitters do
-        local name = get_name_by_random(map)
-        if (nil == spitters_calculated[name]) then
-            spitters_calculated[name] = 1
-        else
-            spitters_calculated[name] = spitters_calculated[name] + 1
-        end
-    end
-
-    return spitters_calculated
-end
-
-return AlienEvolutionProgress
+--[[-- info
+    Original (javascript) version: https://hastebin.com/udakacavap.js
+    Can be tested against: https://wiki.factorio.com/Enemies#Spawn_chances_by_evolution_factor
+]]
+
+-- dependencies
+local Global = require 'utils.global'
+local random = math.random
+local round = math.round
+
+-- this
+local AlienEvolutionProgress = {}
+
+local alien_cache = {
+    biters = {
+        evolution = -1,
+        cache = {},
+    },
+    spitters = {
+        evolution = -1,
+        cache = {},
+    },
+}
+
+Global.register({
+    alien_cache = alien_cache,
+}, function(tbl)
+    alien_cache = tbl.alien_cache
+end)
+
+-- values are in the form {evolution, weight}
+local biters = {
+    {'small-biter',     {{0.0, 0.3}, {0.6, 0.0}}},
+    {'medium-biter',    {{0.2, 0.0}, {0.6, 0.3}, {0.7, 0.1}}},
+    {'big-biter',       {{0.5, 0.0}, {1.0, 0.4}}},
+    {'behemoth-biter',  {{0.9, 0.0}, {1.0, 0.3}}},
+}
+
+local spitters = {
+    {'small-biter',       {{0.0, 0.3}, {0.35, 0.0}}},
+    {'small-spitter',     {{0.25, 0.0}, {0.5, 0.3}, {0.7, 0.0}}},
+    {'medium-spitter',    {{0.4, 0.0}, {0.7, 0.3}, {0.9, 0.1}}},
+    {'big-spitter',       {{0.5, 0.0}, {1.0, 0.4}}},
+    {'behemoth-spitter',  {{0.9, 0.0}, {1.0, 0.3}}},
+}
+
+local function lerp(low, high, pos)
+    local s = high[1] - low[1];
+    local l = (pos - low[1]) / s;
+    return (low[2] * (1 - l)) + (high[2] * l)
+end
+
+local function get_values(map, evo)
+    local result = {}
+    local sum = 0
+
+    for _, data in pairs(map) do
+        local list = data[2];
+        local low = list[1];
+        local high = list[#list];
+
+        for _, val in pairs(list) do
+            if(val[1] <= evo and val[1] >  low[1]) then
+                low = val;
+            end
+            if(val[1] >= evo and val[1] < high[1]) then
+                high = val
+            end
+        end
+
+        local val
+        if (evo <= low[1]) then
+            val = low[2]
+        elseif (evo >= high[1]) then
+            val = high[2];
+        else
+            val = lerp(low, high, evo)
+        end
+        sum = sum + val;
+
+        result[data[1]] = val;
+    end
+
+    for index, _ in pairs(result) do
+        result[index] = result[index] / sum
+    end
+
+    return result;
+end
+
+local function get_name_by_random(collection)
+    local pre_calculated = random()
+    local current = 0
+
+    for name, probability in pairs(collection) do
+        current = current + probability
+        if (current >= pre_calculated) then
+            return name
+        end
+    end
+
+    Debug.print('AlienEvolutionProgress.get_name_by_random: Current \'' .. current .. '\' should be higher or equal to random \'' .. pre_calculated .. '\'')
+end
+
+function AlienEvolutionProgress.getBiterValues(evolution)
+    local evolution_value = round(evolution * 100)
+
+    if (alien_cache.biters.evolution < evolution_value) then
+        alien_cache.biters.evolution = evolution_value
+        alien_cache.biters.cache = get_values(biters, evolution)
+    end
+
+    return alien_cache.biters.cache
+end
+
+function AlienEvolutionProgress.getSpitterValues(evolution)
+    local evolution_value = round(evolution * 100)
+
+    if (alien_cache.spitters.evolution < evolution_value) then
+        alien_cache.spitters.evolution = evolution_value
+        alien_cache.spitters.cache = get_values(spitters, evolution)
+    end
+
+    return alien_cache.spitters.cache
+end
+
+function AlienEvolutionProgress.getBitersByEvolution(total_biters, evolution)
+    local biters_calculated = {}
+    local map = AlienEvolutionProgress.getBiterValues(evolution)
+
+    for i = 1, total_biters do
+        local name = get_name_by_random(map)
+        if (nil == biters_calculated[name]) then
+            biters_calculated[name] = 1
+        else
+            biters_calculated[name] = biters_calculated[name] + 1
+        end
+    end
+
+    return biters_calculated
+end
+
+function AlienEvolutionProgress.getSpittersByEvolution(total_spitters, evolution)
+    local spitters_calculated = {}
+    local map = AlienEvolutionProgress.getSpitterValues(evolution)
+
+    for i = 1, total_spitters do
+        local name = get_name_by_random(map)
+        if (nil == spitters_calculated[name]) then
+            spitters_calculated[name] = 1
+        else
+            spitters_calculated[name] = spitters_calculated[name] + 1
+        end
+    end
+
+    return spitters_calculated
+end
+
+return AlienEvolutionProgress
diff --git a/map_gen/Diggy/Debug.lua b/map_gen/Diggy/Debug.lua
index aa977634..eb4dfff4 100644
--- a/map_gen/Diggy/Debug.lua
+++ b/map_gen/Diggy/Debug.lua
@@ -1,224 +1,224 @@
--- dependencies
-local min = math.min
-local max = math.max
-local floor = math.floor
-local abs = math.abs
-
--- this
-local Debug = {}
-
--- private state
-local debug = false
-local cheats = false
-
-function Debug.enable_debug()
-    debug = true
-end
-
-function Debug.disable_debug()
-    debug = false
-end
-
-function Debug.enable_cheats()
-    cheats = true
-end
-
-function Debug.disable_cheats()
-    cheats = true
-end
-
-global.message_count = 0
-
---[[--
-    Shows the given message if debug is enabled.
-
-    @param message string
-]]
-function Debug.print(message)
-    if type(message) ~= 'string' and type(message) ~= 'number'  and type(message) ~= 'boolean' then message = type(message) end
-    global.message_count = global.message_count + 1
-    if (debug) then
-        game.print('[' .. global.message_count .. '] ' .. tostring(message))
-        log('[' .. global.message_count .. '] ' .. tostring(message))
-    end
-end
-
---[[--
-    Shows the given message with serpent enabled, if debug is enabled.
-
-    @param message string
-]]
-function Debug.print_serpent(message)
-    Debug.print(serpent.line(message))
-end
-
---[[--
-    Shows the given message if _DEBUG == true for a given position.
-
-    @param x number
-    @param y number
-    @param message string
-]]
-function Debug.print_position(position, message)
-    message = message or ''
-    if type(message) ~= 'string' and type(message) ~= 'number'  and type(message) ~= 'boolean' then message = type(message) end
-    global.message_count = global.message_count + 1
-    if (debug) then
-        game.print('[' .. global.message_count .. '] {x=' .. position.x .. ', y=' .. position.y .. '} ' .. tostring(message))
-    end
-end
-
---[[--
-    Executes the given callback if cheating is enabled.
-
-    @param callback function
-]]
-function Debug.cheat(callback)
-    if (cheats) then
-        callback()
-    end
-end
-
---[[--
-    Prints a colored value on a location.
-
-    @param value between -1 and 1
-    @param surface LuaSurface
-    @param position Position {x, y}
-    @param scale float
-    @param offset float
-    @param immutable bool if immutable, only set, never do a surface lookup, values never change
-]]
-function Debug.print_grid_value(value, surface, position, scale, offset, immutable)
-    local is_string = type(value) == 'string'
-    local color = {r = 1, g = 1, b = 1}
-    text = value
-
-    if type(immutable) ~= 'boolean' then
-        immutable = false
-    end
-    
-    if not is_string then
-        scale = scale or 1
-        offset = offset or 0
-        position = {x = position.x + offset, y = position.y + offset}
-        local r = max(1, value) / scale
-        local g = 1 - abs(value) / scale
-        local b = min(1, value) / scale
-
-        if (r > 0) then
-            r = 0
-        end
-
-        if (b < 0) then
-            b = 0
-        end
-
-        if (g < 0) then
-            g = 0
-        end
-
-        r = abs(r)
-
-        color = { r = r, g = g, b = b}
-
-        -- round at precision of 2
-        text = floor(100 * value) * 0.01
-
-        if (0 == text) then
-            text = '0.00'
-        end
-    end
-
-    if not immutable then
-        local text_entity = surface.find_entity('flying-text', position)
-
-        if text_entity then
-            text_entity.text = text
-            text_entity.color = color
-            return
-        end
-    end
-
-    surface.create_entity{
-        name = 'flying-text',
-        color = color,
-        text = text,
-        position = position
-    }.active = false
-end
-
---[[--
-    Prints a colored value on a location. When given a color_value and a delta_color,
-    will change the color of the text from the base to base + value * delta. This will
-    make the color of the text range from 'base_color' to 'base_color + delta_color'
-    as the color_value ranges from 0 to 1
-
-    @param value of number to be displayed
-    @param surface LuaSurface
-    @param position Position {x, y}
-    @param scale float
-    @param offset float position offset
-    @param immutable bool if immutable, only set, never do a surface lookup, values never change
-    @param color_value float How far along the range of values of colors the value is to be displayed
-    @param base_color {r,g,b} The color for the text to be if color_value is 0
-    @param delta_color {r,g,b} The amount to correct the base_color if color_value is 1
-    @param under_bound {r,g,b} The color to be used if color_value < 0
-    @param over_bound {r,g,b} The color to be used if color_value > 1
-]]
-function Debug.print_colored_grid_value(value, surface, position, scale, offset, immutable,
-        color_value, base_color, delta_color, under_bound, over_bound)
-    local is_string = type(value) == 'string'
-    -- default values:
-    local color = base_color or {r = 1, g = 1, b = 1}
-    local d_color = delta_color or {r = 0, g = 0, b = 0}
-    local u_color = under_bound or color
-    local o_color = over_bound or color
-    
-    if (color_value < 0) then
-        color = u_color
-    elseif (color_value > 1) then
-        color = o_color
-    else
-        color = { r = color.r + color_value * d_color.r,
-                  g = color.g + color_value * d_color.g,
-                  b = color.b + color_value * d_color.b }
-    end
-    
-    text = value
-
-    if type(immutable) ~= 'boolean' then
-        immutable = false
-    end
-
-    if not is_string then
-        offset = offset or 0
-        position = {x = position.x + offset, y = position.y + offset}
-
-        -- round at precision of 2
-        text = floor(100 * value) * 0.01
-
-        if (0 == text) then
-            text = '0.00'
-        end
-    end
-
-    if not immutable then
-        local text_entity = surface.find_entity('flying-text', position)
-
-        if text_entity then
-            text_entity.text = text
-            text_entity.color = color
-            return
-        end
-    end
-
-    surface.create_entity{
-        name = 'flying-text',
-        color = color,
-        text = text,
-        position = position
-    }.active = false
-end
-
-return Debug
+-- dependencies
+local min = math.min
+local max = math.max
+local floor = math.floor
+local abs = math.abs
+
+-- this
+local Debug = {}
+
+-- private state
+local debug = false
+local cheats = false
+
+function Debug.enable_debug()
+    debug = true
+end
+
+function Debug.disable_debug()
+    debug = false
+end
+
+function Debug.enable_cheats()
+    cheats = true
+end
+
+function Debug.disable_cheats()
+    cheats = true
+end
+
+global.message_count = 0
+
+--[[--
+    Shows the given message if debug is enabled.
+
+    @param message string
+]]
+function Debug.print(message)
+    if type(message) ~= 'string' and type(message) ~= 'number'  and type(message) ~= 'boolean' then message = type(message) end
+    global.message_count = global.message_count + 1
+    if (debug) then
+        game.print('[' .. global.message_count .. '] ' .. tostring(message))
+        log('[' .. global.message_count .. '] ' .. tostring(message))
+    end
+end
+
+--[[--
+    Shows the given message with serpent enabled, if debug is enabled.
+
+    @param message string
+]]
+function Debug.print_serpent(message)
+    Debug.print(serpent.line(message))
+end
+
+--[[--
+    Shows the given message if _DEBUG == true for a given position.
+
+    @param x number
+    @param y number
+    @param message string
+]]
+function Debug.print_position(position, message)
+    message = message or ''
+    if type(message) ~= 'string' and type(message) ~= 'number'  and type(message) ~= 'boolean' then message = type(message) end
+    global.message_count = global.message_count + 1
+    if (debug) then
+        game.print('[' .. global.message_count .. '] {x=' .. position.x .. ', y=' .. position.y .. '} ' .. tostring(message))
+    end
+end
+
+--[[--
+    Executes the given callback if cheating is enabled.
+
+    @param callback function
+]]
+function Debug.cheat(callback)
+    if (cheats) then
+        callback()
+    end
+end
+
+--[[--
+    Prints a colored value on a location.
+
+    @param value between -1 and 1
+    @param surface LuaSurface
+    @param position Position {x, y}
+    @param scale float
+    @param offset float
+    @param immutable bool if immutable, only set, never do a surface lookup, values never change
+]]
+function Debug.print_grid_value(value, surface, position, scale, offset, immutable)
+    local is_string = type(value) == 'string'
+    local color = {r = 1, g = 1, b = 1}
+    text = value
+
+    if type(immutable) ~= 'boolean' then
+        immutable = false
+    end
+    
+    if not is_string then
+        scale = scale or 1
+        offset = offset or 0
+        position = {x = position.x + offset, y = position.y + offset}
+        local r = max(1, value) / scale
+        local g = 1 - abs(value) / scale
+        local b = min(1, value) / scale
+
+        if (r > 0) then
+            r = 0
+        end
+
+        if (b < 0) then
+            b = 0
+        end
+
+        if (g < 0) then
+            g = 0
+        end
+
+        r = abs(r)
+
+        color = { r = r, g = g, b = b}
+
+        -- round at precision of 2
+        text = floor(100 * value) * 0.01
+
+        if (0 == text) then
+            text = '0.00'
+        end
+    end
+
+    if not immutable then
+        local text_entity = surface.find_entity('flying-text', position)
+
+        if text_entity then
+            text_entity.text = text
+            text_entity.color = color
+            return
+        end
+    end
+
+    surface.create_entity{
+        name = 'flying-text',
+        color = color,
+        text = text,
+        position = position
+    }.active = false
+end
+
+--[[--
+    Prints a colored value on a location. When given a color_value and a delta_color,
+    will change the color of the text from the base to base + value * delta. This will
+    make the color of the text range from 'base_color' to 'base_color + delta_color'
+    as the color_value ranges from 0 to 1
+
+    @param value of number to be displayed
+    @param surface LuaSurface
+    @param position Position {x, y}
+    @param scale float
+    @param offset float position offset
+    @param immutable bool if immutable, only set, never do a surface lookup, values never change
+    @param color_value float How far along the range of values of colors the value is to be displayed
+    @param base_color {r,g,b} The color for the text to be if color_value is 0
+    @param delta_color {r,g,b} The amount to correct the base_color if color_value is 1
+    @param under_bound {r,g,b} The color to be used if color_value < 0
+    @param over_bound {r,g,b} The color to be used if color_value > 1
+]]
+function Debug.print_colored_grid_value(value, surface, position, scale, offset, immutable,
+        color_value, base_color, delta_color, under_bound, over_bound)
+    local is_string = type(value) == 'string'
+    -- default values:
+    local color = base_color or {r = 1, g = 1, b = 1}
+    local d_color = delta_color or {r = 0, g = 0, b = 0}
+    local u_color = under_bound or color
+    local o_color = over_bound or color
+    
+    if (color_value < 0) then
+        color = u_color
+    elseif (color_value > 1) then
+        color = o_color
+    else
+        color = { r = color.r + color_value * d_color.r,
+                  g = color.g + color_value * d_color.g,
+                  b = color.b + color_value * d_color.b }
+    end
+    
+    text = value
+
+    if type(immutable) ~= 'boolean' then
+        immutable = false
+    end
+
+    if not is_string then
+        offset = offset or 0
+        position = {x = position.x + offset, y = position.y + offset}
+
+        -- round at precision of 2
+        text = floor(100 * value) * 0.01
+
+        if (0 == text) then
+            text = '0.00'
+        end
+    end
+
+    if not immutable then
+        local text_entity = surface.find_entity('flying-text', position)
+
+        if text_entity then
+            text_entity.text = text
+            text_entity.color = color
+            return
+        end
+    end
+
+    surface.create_entity{
+        name = 'flying-text',
+        color = color,
+        text = text,
+        position = position
+    }.active = false
+end
+
+return Debug
diff --git a/map_gen/Diggy/Feature/AlienSpawner.lua b/map_gen/Diggy/Feature/AlienSpawner.lua
index 9142446f..15051901 100644
--- a/map_gen/Diggy/Feature/AlienSpawner.lua
+++ b/map_gen/Diggy/Feature/AlienSpawner.lua
@@ -1,66 +1,66 @@
---[[-- info
-    Provides the ability to spawn aliens.
-]]
-
--- dependencies
-local Event = require 'utils.event'
-local AlienEvolutionProgress = require 'map_gen.Diggy.AlienEvolutionProgress'
-local Debug = require 'map_gen.Diggy.Debug'
-local Template = require 'map_gen.Diggy.Template'
-local insert = table.insert
-local random = math.random
-
--- this
-local AlienSpawner = {}
-
-local function spawn_alien(surface, x, y)
-    local enemy_force = game.forces.enemy
-    local enemy_force_evolution = enemy_force.evolution_factor
-    local position = {x = x, y = y}
-    local biters = AlienEvolutionProgress.getBitersByEvolution(random(1, 2), enemy_force_evolution)
-    local spitters = AlienEvolutionProgress.getSpittersByEvolution(random(1, 2), enemy_force_evolution)
-
-    local units = {}
-    for name, amount in pairs(biters) do
-        insert(units, {name = name, position = position, force = enemy_force, amount = amount})
-    end
-    for name, amount in pairs(spitters) do
-        insert(units, {name = name, position = position, force = enemy_force, amount = amount})
-    end
-
-    Template.units(surface, units, 1.5, 'small-biter')
-end
-
---[[--
-    Registers all event handlers.
-]]
-function AlienSpawner.register(config)
-    local alien_minimum_distance_square = config.alien_minimum_distance ^ 2
-
-    Event.add(Template.events.on_void_removed, function (event)
-        game.forces.enemy.evolution_factor = game.forces.enemy.evolution_factor + 0.0000012
-
-        local position = event.position
-        local x = position.x
-        local y = position.y
-
-        if (x * x + y * y < alien_minimum_distance_square or config.alien_probability < random()) then
-            return
-        end
-
-        spawn_alien(event.surface, x, y)
-    end)
-end
-
-function AlienSpawner.get_extra_map_info(config)
-    return [[Alien Spawner, aliens might spawn when mining!
-Spawn chance: ]] .. (config.alien_probability * 100) .. [[%
-Minimum spawn distance: ]] .. config.alien_minimum_distance .. ' tiles'
-end
-
-function AlienSpawner.on_init()
-	-- base factorio =                pollution_factor = 0.000015
-    game.map_settings.enemy_evolution.pollution_factor = 0.000004
-end
-
-return AlienSpawner
+--[[-- info
+    Provides the ability to spawn aliens.
+]]
+
+-- dependencies
+local Event = require 'utils.event'
+local AlienEvolutionProgress = require 'map_gen.Diggy.AlienEvolutionProgress'
+local Debug = require 'map_gen.Diggy.Debug'
+local Template = require 'map_gen.Diggy.Template'
+local insert = table.insert
+local random = math.random
+
+-- this
+local AlienSpawner = {}
+
+local function spawn_alien(surface, x, y)
+    local enemy_force = game.forces.enemy
+    local enemy_force_evolution = enemy_force.evolution_factor
+    local position = {x = x, y = y}
+    local biters = AlienEvolutionProgress.getBitersByEvolution(random(1, 2), enemy_force_evolution)
+    local spitters = AlienEvolutionProgress.getSpittersByEvolution(random(1, 2), enemy_force_evolution)
+
+    local units = {}
+    for name, amount in pairs(biters) do
+        insert(units, {name = name, position = position, force = enemy_force, amount = amount})
+    end
+    for name, amount in pairs(spitters) do
+        insert(units, {name = name, position = position, force = enemy_force, amount = amount})
+    end
+
+    Template.units(surface, units, 1.5, 'small-biter')
+end
+
+--[[--
+    Registers all event handlers.
+]]
+function AlienSpawner.register(config)
+    local alien_minimum_distance_square = config.alien_minimum_distance ^ 2
+
+    Event.add(Template.events.on_void_removed, function (event)
+        game.forces.enemy.evolution_factor = game.forces.enemy.evolution_factor + 0.0000012
+
+        local position = event.position
+        local x = position.x
+        local y = position.y
+
+        if (x * x + y * y < alien_minimum_distance_square or config.alien_probability < random()) then
+            return
+        end
+
+        spawn_alien(event.surface, x, y)
+    end)
+end
+
+function AlienSpawner.get_extra_map_info(config)
+    return [[Alien Spawner, aliens might spawn when mining!
+Spawn chance: ]] .. (config.alien_probability * 100) .. [[%
+Minimum spawn distance: ]] .. config.alien_minimum_distance .. ' tiles'
+end
+
+function AlienSpawner.on_init()
+	-- base factorio =                pollution_factor = 0.000015
+    game.map_settings.enemy_evolution.pollution_factor = 0.000004
+end
+
+return AlienSpawner
diff --git a/map_gen/Diggy/Feature/Antigrief.lua b/map_gen/Diggy/Feature/Antigrief.lua
index 3f2f89a1..c72a9afd 100644
--- a/map_gen/Diggy/Feature/Antigrief.lua
+++ b/map_gen/Diggy/Feature/Antigrief.lua
@@ -1,57 +1,57 @@
---[[-- info
-    Provides the ability to setup a player when first joined.
-]]
-
--- dependencies
-local Event = require 'utils.event'
-local Global = require 'utils.global'
-local CaveCollapse = require 'map_gen.Diggy.Feature.DiggyCaveCollapse'
-local Game = require 'utils.game'
-local Report = require 'features.report'
-
--- this
-local Antigrief = {}
-
-global.Antigrief = {
-    autojail = false,
-    jailed_players = {},
-    last_collapse = 0
-}
-
-local allowed_collapses_first_hour = 0
-
-local player_collapses = {}
-
-Global.register({
-    cave_collapse_disabled = cave_collapse_disabled
-}, function(tbl)
-    cave_collapse_disabled = tbl.cave_collapse_disabled
-end)
-
-
---[[--
-    Registers all event handlers.
-]]
-function Antigrief.register(config)
-    global.Antigrief.autojail = config.autojail
-    allowed_collapses_first_hour = config.allowed_collapses_first_hour
-end
-
-
-Event.add(CaveCollapse.events.on_collapse, function(event)
-    local player_index = event.player_index
-    if player_index and global.Antigrief.last_collapse ~= game.tick then
-        global.Antigrief.last_collapse = game.tick
-        local count = player_collapses[player_index] or 0
-        count = count + 1
-        player_collapses[player_index] = count
-        local player = Game.get_player_by_index(player_index)
-        if global.Antigrief.autojail and count > allowed_collapses_first_hour and player.online_time < 216000 and not global.Antigrief.jailed_players[player_index] then
-            Report.jail(player)
-            Report.report(nil, player, string.format("Caused %d collapses in the first hour", count))
-            global.Antigrief.jailed_players[player_index] = true
-        end
-    end
-end)
-
-return Antigrief
+--[[-- info
+    Provides the ability to setup a player when first joined.
+]]
+
+-- dependencies
+local Event = require 'utils.event'
+local Global = require 'utils.global'
+local CaveCollapse = require 'map_gen.Diggy.Feature.DiggyCaveCollapse'
+local Game = require 'utils.game'
+local Report = require 'features.report'
+
+-- this
+local Antigrief = {}
+
+global.Antigrief = {
+    autojail = false,
+    jailed_players = {},
+    last_collapse = 0
+}
+
+local allowed_collapses_first_hour = 0
+
+local player_collapses = {}
+
+Global.register({
+    cave_collapse_disabled = cave_collapse_disabled
+}, function(tbl)
+    cave_collapse_disabled = tbl.cave_collapse_disabled
+end)
+
+
+--[[--
+    Registers all event handlers.
+]]
+function Antigrief.register(config)
+    global.Antigrief.autojail = config.autojail
+    allowed_collapses_first_hour = config.allowed_collapses_first_hour
+end
+
+
+Event.add(CaveCollapse.events.on_collapse, function(event)
+    local player_index = event.player_index
+    if player_index and global.Antigrief.last_collapse ~= game.tick then
+        global.Antigrief.last_collapse = game.tick
+        local count = player_collapses[player_index] or 0
+        count = count + 1
+        player_collapses[player_index] = count
+        local player = Game.get_player_by_index(player_index)
+        if global.Antigrief.autojail and count > allowed_collapses_first_hour and player.online_time < 216000 and not global.Antigrief.jailed_players[player_index] then
+            Report.jail(player)
+            Report.report(nil, player, string.format("Caused %d collapses in the first hour", count))
+            global.Antigrief.jailed_players[player_index] = true
+        end
+    end
+end)
+
+return Antigrief
diff --git a/map_gen/Diggy/Feature/ArtefactHunting.lua b/map_gen/Diggy/Feature/ArtefactHunting.lua
index ef7a637e..e133fd9f 100644
--- a/map_gen/Diggy/Feature/ArtefactHunting.lua
+++ b/map_gen/Diggy/Feature/ArtefactHunting.lua
@@ -1,242 +1,242 @@
---[[-- info
-    Provides the ability to collect coins and send them to space.
-]]
-
--- dependencies
-local Event = require 'utils.event'
-local Game = require 'utils.game'
-local ScoreTable = require 'map_gen.Diggy.ScoreTable'
-local Debug = require 'map_gen.Diggy.Debug'
-local Template = require 'map_gen.Diggy.Template'
-local Perlin = require 'map_gen.shared.perlin_noise'
-local random = math.random
-local ceil = math.ceil
-local Gui = require 'utils.gui'
-local utils = require 'utils.utils'
-
--- this
-local ArtefactHunting = {}
-
--- some GUI stuff
-local function redraw_table(data)
-    local list = data.list
-    Gui.clear(list)
-
-    data.frame.caption = 'Scoretable'
-
-    local score_keys = ScoreTable.all_keys()
-
-    for _, data in pairs(score_keys) do
-        local val = ScoreTable.get(data)
-
-        local table = list.add({type = 'table', column_count = 2})
-
-        local key = table.add({type = 'label', name = 'Diggy.ArtefactHunting.Frame.List.Key', caption = data})
-        key.style.minimal_width = 175
-
-        local val = table.add({type = 'label', name = 'Diggy.ArtefactHunting.Frame.List.Val', caption = utils.comma_value(val)})
-        val.style.minimal_width = 225
-    end
-end
-
-
-local function toggle(event)
-    local player = event.player
-    local center = player.gui.left
-    local frame = center['Diggy.ArtefactHunting.Frame']
-
-    if (frame and event.trigger == nil) then
-        Gui.destroy(frame)
-        return
-    elseif (frame) then
-        local data = Gui.get_data(frame)
-        redraw_table(data)
-        return
-    end
-
-    frame = center.add({name = 'Diggy.ArtefactHunting.Frame', type = 'frame', direction = 'vertical'})
-
-    local scroll_pane = frame.add({type = 'scroll-pane'})
-    scroll_pane.style.maximal_height = 400
-
-    frame.add({ type = 'button', name = 'Diggy.ArtefactHunting.Button', caption = 'Close'})
-
-    local data = {
-        frame = frame,
-        list = scroll_pane
-    }
-
-    redraw_table(data)
-
-    Gui.set_data(frame, data)
-end
-
-local function on_player_created(event)
-    Game.get_player_by_index(event.player_index).gui.top.add({
-        name = 'Diggy.ArtefactHunting.Button',
-        type = 'sprite-button',
-        sprite = 'item/steel-axe',
-    })
-end
-
-Gui.on_click('Diggy.ArtefactHunting.Button', toggle)
-Gui.on_custom_close('Diggy.ArtefactHunting.Frame', function (event)
-    event.element.destroy()
-end)
-
-function ArtefactHunting.update_gui()
-    for _, p in ipairs(game.connected_players) do
-        local frame = p.gui.left['Diggy.ArtefactHunting.Frame']
-
-        if frame and frame.valid then
-            local data = {player = p, trigger = 'update_gui'}
-            toggle(data)
-        end
-    end
-end
-
---[[--
-    Registers all event handlers.
-]]
-function ArtefactHunting.register(config)
-    Event.add(defines.events.on_player_created, on_player_created)
-    Event.on_nth_tick(61, ArtefactHunting.update_gui)
-
-    ScoreTable.reset('Coins sent to space')
-
-    local seed
-    local function get_noise(surface, x, y)
-        seed = seed or surface.map_gen_settings.seed + surface.index + 300
-        return Perlin.noise(x * config.noise_variance * 0.9, y * config.noise_variance * 1.1, seed)
-    end
-
-    local distance_required = config.minimal_treasure_chest_distance * config.minimal_treasure_chest_distance
-
-    Event.add(defines.events.on_rocket_launched, function (event)
-        local coins = event.rocket.get_inventory(defines.inventory.rocket).get_item_count('coin')
-        if coins > 0 then
-            local sum = ScoreTable.add('Coins sent to space', coins)
-            game.print('sent ' .. coins .. ' coins into space! The space station is now holding ' .. sum .. ' coins.')
-        end
-    end)
-
-    Event.add(Template.events.on_void_removed, function (event)
-        local position = event.position
-        local x = position.x
-        local y = position.y
-
-        if (x * x + y * y <= distance_required) then
-            return
-        end
-
-        local surface = event.surface
-
-        if get_noise(surface, x, y) < config.treasure_chest_noise_threshold then
-            return
-        end
-
-        local chest = surface.create_entity({name = 'steel-chest', position = position, force = game.forces.player})
-
-        if not chest then
-            return
-        end
-
-        for name, prototype in pairs(config.treasure_chest_raffle) do
-            if random() <= prototype.chance then
-                chest.insert({name = name, count = random(prototype.min, prototype.max)})
-            end
-        end
-    end)
-
-    local modifiers = config.alien_coin_modifiers
-
-    local function picked_up_coins(player_index, count)
-        local text
-        if count == 1 then
-            text = '+1 coin'
-            ScoreTable.increment('Collected coins')
-        else
-            text = '+' .. count ..' coins'
-            ScoreTable.add('Collected coins', count)
-        end
-
-        Game.print_player_floating_text(player_index, text, {r = 255, g = 215, b = 0})
-    end
-
-    ScoreTable.reset('Collected coins')
-
-    Event.add(defines.events.on_entity_died, function (event)
-        local entity = event.entity
-        local force = entity.force
-
-        if force.name ~= 'enemy' then
-            return
-        end
-
-        local cause = event.cause
-
-        if not cause or cause.type ~= 'player' or not cause.valid then
-            return
-        end
-
-        local modifier = modifiers[entity.name] or 1
-        local evolution_multiplier = force.evolution_factor * 11
-        local count = random(
-            ceil(2 * evolution_multiplier * 0.1),
-            ceil(5 * (evolution_multiplier * evolution_multiplier + modifier) * 0.1)
-        )
-
-        entity.surface.create_entity({
-            name = 'item-on-ground',
-            position = entity.position,
-            stack = {name = 'coin', count = count}
-        })
-    end)
-
-    Event.add(defines.events.on_picked_up_item, function (event)
-        local stack = event.item_stack
-        if stack.name ~= 'coin' then
-            return
-        end
-
-        picked_up_coins(event.player_index, stack.count)
-    end)
-
-    Event.add(defines.events.on_pre_player_mined_item, function (event)
-        if event.entity.type ~= 'simple-entity' then
-            return
-        end
-
-        if random() > config.mining_artefact_chance then
-            return
-        end
-
-        local count = random(config.mining_artefact_amount.min, config.mining_artefact_amount.max)
-        local player_index = event.player_index
-
-        Game.get_player_by_index(player_index).insert({name = 'coin', count = count})
-        picked_up_coins(player_index, count)
-    end)
-
-    if (config.display_chest_locations) then
-        Event.add(defines.events.on_chunk_generated, function (event)
-            local surface = event.surface
-            local area = event.area
-
-            for x = area.left_top.x, area.left_top.x + 31 do
-                local sq_x = x * x
-                for y = area.left_top.y, area.left_top.y + 31 do
-                    if sq_x + y * y >= distance_required and get_noise(surface, x, y) >= config.treasure_chest_noise_threshold then
-                        Debug.print_grid_value('chest', surface, {x = x, y = y}, nil, nil, true)
-                    end
-                end
-            end
-        end)
-    end
-end
-
-function ArtefactHunting.get_extra_map_info(config)
-    return 'Artefact Hunting, find precious coins while mining and launch them to the surface!'
-end
-
-return ArtefactHunting
+--[[-- info
+    Provides the ability to collect coins and send them to space.
+]]
+
+-- dependencies
+local Event = require 'utils.event'
+local Game = require 'utils.game'
+local ScoreTable = require 'map_gen.Diggy.ScoreTable'
+local Debug = require 'map_gen.Diggy.Debug'
+local Template = require 'map_gen.Diggy.Template'
+local Perlin = require 'map_gen.shared.perlin_noise'
+local random = math.random
+local ceil = math.ceil
+local Gui = require 'utils.gui'
+local utils = require 'utils.utils'
+
+-- this
+local ArtefactHunting = {}
+
+-- some GUI stuff
+local function redraw_table(data)
+    local list = data.list
+    Gui.clear(list)
+
+    data.frame.caption = 'Scoretable'
+
+    local score_keys = ScoreTable.all_keys()
+
+    for _, data in pairs(score_keys) do
+        local val = ScoreTable.get(data)
+
+        local table = list.add({type = 'table', column_count = 2})
+
+        local key = table.add({type = 'label', name = 'Diggy.ArtefactHunting.Frame.List.Key', caption = data})
+        key.style.minimal_width = 175
+
+        local val = table.add({type = 'label', name = 'Diggy.ArtefactHunting.Frame.List.Val', caption = utils.comma_value(val)})
+        val.style.minimal_width = 225
+    end
+end
+
+
+local function toggle(event)
+    local player = event.player
+    local center = player.gui.left
+    local frame = center['Diggy.ArtefactHunting.Frame']
+
+    if (frame and event.trigger == nil) then
+        Gui.destroy(frame)
+        return
+    elseif (frame) then
+        local data = Gui.get_data(frame)
+        redraw_table(data)
+        return
+    end
+
+    frame = center.add({name = 'Diggy.ArtefactHunting.Frame', type = 'frame', direction = 'vertical'})
+
+    local scroll_pane = frame.add({type = 'scroll-pane'})
+    scroll_pane.style.maximal_height = 400
+
+    frame.add({ type = 'button', name = 'Diggy.ArtefactHunting.Button', caption = 'Close'})
+
+    local data = {
+        frame = frame,
+        list = scroll_pane
+    }
+
+    redraw_table(data)
+
+    Gui.set_data(frame, data)
+end
+
+local function on_player_created(event)
+    Game.get_player_by_index(event.player_index).gui.top.add({
+        name = 'Diggy.ArtefactHunting.Button',
+        type = 'sprite-button',
+        sprite = 'item/steel-axe',
+    })
+end
+
+Gui.on_click('Diggy.ArtefactHunting.Button', toggle)
+Gui.on_custom_close('Diggy.ArtefactHunting.Frame', function (event)
+    event.element.destroy()
+end)
+
+function ArtefactHunting.update_gui()
+    for _, p in ipairs(game.connected_players) do
+        local frame = p.gui.left['Diggy.ArtefactHunting.Frame']
+
+        if frame and frame.valid then
+            local data = {player = p, trigger = 'update_gui'}
+            toggle(data)
+        end
+    end
+end
+
+--[[--
+    Registers all event handlers.
+]]
+function ArtefactHunting.register(config)
+    Event.add(defines.events.on_player_created, on_player_created)
+    Event.on_nth_tick(61, ArtefactHunting.update_gui)
+
+    ScoreTable.reset('Coins sent to space')
+
+    local seed
+    local function get_noise(surface, x, y)
+        seed = seed or surface.map_gen_settings.seed + surface.index + 300
+        return Perlin.noise(x * config.noise_variance * 0.9, y * config.noise_variance * 1.1, seed)
+    end
+
+    local distance_required = config.minimal_treasure_chest_distance * config.minimal_treasure_chest_distance
+
+    Event.add(defines.events.on_rocket_launched, function (event)
+        local coins = event.rocket.get_inventory(defines.inventory.rocket).get_item_count('coin')
+        if coins > 0 then
+            local sum = ScoreTable.add('Coins sent to space', coins)
+            game.print('sent ' .. coins .. ' coins into space! The space station is now holding ' .. sum .. ' coins.')
+        end
+    end)
+
+    Event.add(Template.events.on_void_removed, function (event)
+        local position = event.position
+        local x = position.x
+        local y = position.y
+
+        if (x * x + y * y <= distance_required) then
+            return
+        end
+
+        local surface = event.surface
+
+        if get_noise(surface, x, y) < config.treasure_chest_noise_threshold then
+            return
+        end
+
+        local chest = surface.create_entity({name = 'steel-chest', position = position, force = game.forces.player})
+
+        if not chest then
+            return
+        end
+
+        for name, prototype in pairs(config.treasure_chest_raffle) do
+            if random() <= prototype.chance then
+                chest.insert({name = name, count = random(prototype.min, prototype.max)})
+            end
+        end
+    end)
+
+    local modifiers = config.alien_coin_modifiers
+
+    local function picked_up_coins(player_index, count)
+        local text
+        if count == 1 then
+            text = '+1 coin'
+            ScoreTable.increment('Collected coins')
+        else
+            text = '+' .. count ..' coins'
+            ScoreTable.add('Collected coins', count)
+        end
+
+        Game.print_player_floating_text(player_index, text, {r = 255, g = 215, b = 0})
+    end
+
+    ScoreTable.reset('Collected coins')
+
+    Event.add(defines.events.on_entity_died, function (event)
+        local entity = event.entity
+        local force = entity.force
+
+        if force.name ~= 'enemy' then
+            return
+        end
+
+        local cause = event.cause
+
+        if not cause or cause.type ~= 'player' or not cause.valid then
+            return
+        end
+
+        local modifier = modifiers[entity.name] or 1
+        local evolution_multiplier = force.evolution_factor * 11
+        local count = random(
+            ceil(2 * evolution_multiplier * 0.1),
+            ceil(5 * (evolution_multiplier * evolution_multiplier + modifier) * 0.1)
+        )
+
+        entity.surface.create_entity({
+            name = 'item-on-ground',
+            position = entity.position,
+            stack = {name = 'coin', count = count}
+        })
+    end)
+
+    Event.add(defines.events.on_picked_up_item, function (event)
+        local stack = event.item_stack
+        if stack.name ~= 'coin' then
+            return
+        end
+
+        picked_up_coins(event.player_index, stack.count)
+    end)
+
+    Event.add(defines.events.on_pre_player_mined_item, function (event)
+        if event.entity.type ~= 'simple-entity' then
+            return
+        end
+
+        if random() > config.mining_artefact_chance then
+            return
+        end
+
+        local count = random(config.mining_artefact_amount.min, config.mining_artefact_amount.max)
+        local player_index = event.player_index
+
+        Game.get_player_by_index(player_index).insert({name = 'coin', count = count})
+        picked_up_coins(player_index, count)
+    end)
+
+    if (config.display_chest_locations) then
+        Event.add(defines.events.on_chunk_generated, function (event)
+            local surface = event.surface
+            local area = event.area
+
+            for x = area.left_top.x, area.left_top.x + 31 do
+                local sq_x = x * x
+                for y = area.left_top.y, area.left_top.y + 31 do
+                    if sq_x + y * y >= distance_required and get_noise(surface, x, y) >= config.treasure_chest_noise_threshold then
+                        Debug.print_grid_value('chest', surface, {x = x, y = y}, nil, nil, true)
+                    end
+                end
+            end
+        end)
+    end
+end
+
+function ArtefactHunting.get_extra_map_info(config)
+    return 'Artefact Hunting, find precious coins while mining and launch them to the surface!'
+end
+
+return ArtefactHunting
diff --git a/map_gen/Diggy/Feature/DiggyCaveCollapse.lua b/map_gen/Diggy/Feature/DiggyCaveCollapse.lua
index eb335f85..639795ba 100644
--- a/map_gen/Diggy/Feature/DiggyCaveCollapse.lua
+++ b/map_gen/Diggy/Feature/DiggyCaveCollapse.lua
@@ -1,646 +1,646 @@
---[[-- info
-    Provides the ability to collapse caves when digging.
-]]
--- dependencies
-require 'utils.list_utils'
-
-local Event = require 'utils.event'
-local Template = require 'map_gen.Diggy.Template'
-local ScoreTable = require 'map_gen.Diggy.ScoreTable'
-local Debug = require 'map_gen.Diggy.Debug'
-local Task = require 'utils.Task'
-local Token = require 'utils.global_token'
-local Global = require 'utils.global'
-local Game = require 'utils.game'
-local insert = table.insert
-local random = math.random
-local floor = math.floor
-local abs = math.abs
-
--- this
-local DiggyCaveCollapse = {}
-
-local config = {}
-
-local n = 9
-local radius = 0
-local radius_sq = 0
-local center_radius_sq = 0
-local disc_radius_sq = 0
-
-local center_weight
-local disc_weight
-local ring_weight
-
-local disc_blur_sum = 0
-
-local center_value = 0
-local disc_value = 0
-local ring_value = 0
-
-local enable_stress_grid = 0
-local stress_map_add
-local mask_disc_blur
-local stress_map_check_stress_in_threshold
-local support_beam_entities
-local on_surface_created
-
-local stress_threshold_causing_collapse = 3.57
-
-local show_deconstruction_alert_message = {}
-local stress_map_storage = {}
-local new_tile_map = {}
-local collapse_positions_storage = {}
-
-Global.register({
-    new_tile_map = new_tile_map,
-    stress_map_storage = stress_map_storage,
-    deconstruction_alert_message_shown = show_deconstruction_alert_message,
-    collapse_positions_storage = collapse_positions_storage,
-}, function(tbl)
-    new_tile_map = tbl.new_tile_map
-    stress_map_storage = tbl.stress_map_storage
-    show_deconstruction_alert_message = tbl.deconstruction_alert_message_shown
-    collapse_positions_storage = tbl.collapse_positions_storage
-end)
-
-local defaultValue = 0
-
-DiggyCaveCollapse.events = {
-    --[[--
-        When stress at certain position is above the collapse threshold
-         - position LuaPosition
-         - surface LuaSurface
-         - player_index Number (index of player that caused the collapse)
-    ]]
-    on_collapse_triggered = script.generate_event_name(),
-
-    --[[--
-        After a collapse
-         - position LuaPosition
-         - surface LuaSurface
-         - player_index Number (index of player that caused the collapse)
-    ]]
-    on_collapse = script.generate_event_name()
-}
-
-local function create_collapse_template(positions, surface)
-    local entities = {}
-
-    local find_entities_filtered = surface.find_entities_filtered
-
-    for _, position in pairs(positions) do
-        local x = position.x
-        local y = position.y
-        local do_insert = true
-
-        for _, entity in pairs(find_entities_filtered{area = {{x, y}, {x + 1, y + 1}}}) do
-            pcall(function()
-                local strength = support_beam_entities[entity.name]
-                if strength then
-                    do_insert = false
-                else
-                    entity.die()
-                end
-            end)
-        end
-        if do_insert then
-            insert(entities, {position = {x = x, y = y}, name = 'sand-rock-big'})
-        end
-    end
-    return entities
-end
-
-local function create_collapse_alert(surface, position)
-    local target = surface.create_entity{position = position, name = "sand-rock-big"}
-    for _,player in pairs(game.connected_players) do
-        player.add_custom_alert(target, {type="item", name="stone"}, "Cave collapsed!", true)
-    end
-    target.destroy()
-end
-
-local function collapse(args)
-    local position = args.position
-    local surface = args.surface
-    local positions = {}
-    local strength = config.collapse_threshold_total_strength
-    local player_index = args.player_index
-    create_collapse_alert(surface, position)
-    mask_disc_blur(
-        position.x,  position.y,
-        strength,
-        function(x, y, value)
-            stress_map_check_stress_in_threshold(
-                surface,
-                {x = x, y = y},
-                value,
-                function(_, position)
-                    insert(positions, position)
-                end
-            )
-        end
-    )
-    local entities = create_collapse_template(positions, surface)
-    Template.insert(surface, {}, entities)
-
-    script.raise_event(DiggyCaveCollapse.events.on_collapse, args)
-    ScoreTable.increment('Cave collapse')
-end
-
-local on_collapse_timeout_finished = Token.register(collapse)
-
-local function spawn_cracking_sound_text(surface, position)
-    local text = config.cracking_sounds[random(1, #config.cracking_sounds)]
-
-    local color = {
-        r = 1,
-        g = random(1, 100) * 0.01,
-        b = 0
-    }
-
-    local create_entity = surface.create_entity
-
-    for i = 1, #text do
-        local x_offset = (i - #text / 2 - 1) / 3
-        local char = text:sub(i, i)
-        create_entity {
-            name = 'flying-text',
-            color = color,
-            text = char,
-            position = {x = position.x + x_offset, y = position.y - ((i + 1) % 2) * 0.25}
-        }.active = true
-    end
-end
-
-local function on_collapse_triggered(event)
-    if global.cave_collapse_disabled then return end --kill switch
-
-    local surface = event.surface
-    local position = event.position
-    local x = position.x
-    local y = position.y
-
-    local x_t = new_tile_map[x]
-    if x_t and x_t[y] then
-        Template.insert(surface, {}, {{position = position, name = 'sand-rock-big'}})
-        return
-    end
-    spawn_cracking_sound_text(surface, position)
-    Task.set_timeout(
-        config.collapse_delay,
-        on_collapse_timeout_finished,
-        event
-    )
-end
-
-local function on_built_tile(surface, new_tile, tiles)
-    local new_tile_strength = support_beam_entities[new_tile.name]
-
-    for _, tile in pairs(tiles) do
-        if new_tile_strength then
-            stress_map_add(surface, tile.position, -1 * new_tile_strength, true)
-        end
-
-        local old_tile_strength = support_beam_entities[tile.old_tile.name]
-        if (old_tile_strength) then
-            stress_map_add(surface, tile.position, old_tile_strength, true)
-        end
-    end
-end
-
---It is impossible to track which player marked the tile for deconstruction
-local function on_robot_mined_tile(event)
-    local surface
-    for _, tile in pairs(event.tiles) do
-        local strength = support_beam_entities[tile.old_tile.name]
-        if strength then
-            surface = surface or event.robot.surface
-            stress_map_add(surface, tile.position, strength, true)
-        end
-    end
-end
-
-local function on_player_mined_tile(event)
-    local surface = game.surfaces[event.surface_index]
-    for _, tile in pairs(event.tiles) do
-        local strength = support_beam_entities[tile.old_tile.name]
-
-        if strength then
-            stress_map_add(surface, tile.position, strength, true, event.player_index)
-        end
-    end
-end
-
-local function on_robot_mined_entity(event)
-    local entity = event.entity
-    local strength = support_beam_entities[entity.name]
-
-    if strength then
-        stress_map_add(entity.surface, entity.position, strength, false, entity.last_user.index)
-    end
-end
-
-local function on_mined_entity(event)
-    local entity = event.entity
-    local name = entity.name
-    local strength = support_beam_entities[name]
-    if strength then
-        stress_map_add(entity.surface, entity.position, strength, false, (not (name == "sand-rock-big" or name == "rock-huge")) and event.player_index)
-    end
-end
-
-local function on_entity_died(event)
-    local entity = event.entity
-    local name = entity.name
-    local strength = support_beam_entities[name]
-    if strength then
-        local cause = event.cause or {}
-        stress_map_add(entity.surface, entity.position, strength, false, (not (name == "sand-rock-big" or name == "rock-huge")) and cause.index)
-    end
-end
-
-local function on_built_entity(event)
-    local entity = event.created_entity
-    local strength = support_beam_entities[entity.name]
-
-    if strength then
-        stress_map_add(entity.surface, entity.position, -1 * strength)
-    end
-end
-
-local function on_placed_entity(event)
-    local strength = support_beam_entities[event.entity.name]
-
-    if strength then
-        stress_map_add(event.entity.surface, event.entity.position, -1 * strength)
-    end
-end
-
-
-local on_new_tile_timeout_finished = Token.register(function(args)
-    local x_t = new_tile_map[args.x]
-    if x_t then
-       x_t[args.y] = nil --reset new tile status. This tile can cause a chain collapse now
-    end
-end)
-
-local function on_void_removed(event)
-    local strength = support_beam_entities['out-of-map']
-
-    local position = event.position
-    if strength then
-        stress_map_add(event.surface, position, strength)
-    end
-
-    local x = position.x
-    local y = position.y
-
-    --To avoid room collapse:
-    local x_t = new_tile_map[x]
-    if x_t then
-        x_t[y] = true
-    else
-        x_t = {
-            [y] = true
-        }
-        new_tile_map[x] = x_t
-    end
-    Task.set_timeout(3, on_new_tile_timeout_finished, {x = x, y = y})
-end
-
---[[--
-    Registers all event handlers.]
-
-    @param global_config Table {@see Diggy.Config}.
-]]
-function DiggyCaveCollapse.register(cfg)
-    config = cfg
-    support_beam_entities = config.support_beam_entities
-
-    if support_beam_entities['stone-path'] then
-        support_beam_entities['stone-brick'] = support_beam_entities['stone-path']
-    else
-        support_beam_entities['stone-brick'] = nil
-    end
-
-    if support_beam_entities['hazard-concrete'] then
-        support_beam_entities['hazard-concrete-left'] = support_beam_entities['hazard-concrete']
-        support_beam_entities['hazard-concrete-right'] = support_beam_entities['hazard-concrete']
-    else
-        support_beam_entities['hazard-concrete-left'] = nil
-        support_beam_entities['hazard-concrete-right'] = nil
-    end
-
-    if support_beam_entities['refined-hazard-concrete'] then
-        support_beam_entities['refined-hazard-concrete-left'] = support_beam_entities['refined-hazard-concrete']
-        support_beam_entities['refined-hazard-concrete-right'] = support_beam_entities['refined-hazard-concrete']
-    else
-        support_beam_entities['refined-hazard-concrete-left'] = nil
-        support_beam_entities['refined-hazard-concrete-right'] = nil
-    end
-
-    ScoreTable.reset('Cave collapse')
-
-    Event.add(DiggyCaveCollapse.events.on_collapse_triggered, on_collapse_triggered)
-    Event.add(defines.events.on_robot_built_entity, on_built_entity)
-    Event.add(defines.events.on_robot_built_tile, function (event)
-        on_built_tile(event.robot.surface, event.item, event.tiles)
-    end)
-    Event.add(defines.events.on_player_built_tile, function (event)
-        on_built_tile(game.surfaces[event.surface_index], event.item, event.tiles)
-    end)
-    Event.add(defines.events.on_robot_mined_tile, on_robot_mined_tile)
-    Event.add(defines.events.on_player_mined_tile, on_player_mined_tile)
-    Event.add(defines.events.on_robot_mined_entity, on_robot_mined_entity)
-    Event.add(defines.events.on_built_entity, on_built_entity)
-    Event.add(Template.events.on_placed_entity, on_placed_entity)
-    Event.add(defines.events.on_entity_died, on_entity_died)
-    Event.add(defines.events.on_player_mined_entity, on_mined_entity)
-    Event.add(Template.events.on_void_removed, on_void_removed)
-    Event.add(defines.events.on_surface_created, on_surface_created)
-
-    Event.add(defines.events.on_marked_for_deconstruction, function (event)
-        if (nil ~= support_beam_entities[event.entity.name]) then
-            event.entity.cancel_deconstruction(Game.get_player_by_index(event.player_index).force)
-        end
-    end)
-
-    Event.add(defines.events.on_player_created, function (event)
-        show_deconstruction_alert_message[event.player_index] = true
-    end)
-
-    Event.add(defines.events.on_pre_player_mined_item, function (event)
-        local player_index = event.player_index
-        if not show_deconstruction_alert_message[player_index] then
-            return
-        end
-
-        if (nil ~= support_beam_entities[event.entity.name]) then
-            require 'features.gui.popup'.player(
-                Game.get_player_by_index(player_index),[[
-Mining entities such as walls, stone paths, concrete
-and rocks, can cause a cave-in, be careful miner!
-
-Foreman's advice: Place a wall every 4th tile to
-prevent a cave-in. Use stone paths and concrete
-to reinforce it further.
-]]
-            )
-            show_deconstruction_alert_message[player_index] = nil
-        end
-    end)
-
-    enable_stress_grid = config.enable_stress_grid
-
-    on_surface_created({surface_index = 1})
-
-    mask_init(config)
-    if (config.enable_mask_debug) then
-        local surface = game.surfaces.nauvis
-        mask_disc_blur(0, 0, 10,  function(x, y, fraction)
-            Debug.print_grid_value(fraction, surface, {x = x, y = y})
-        end)
-    end
-
-
-    if config.enable_debug_commands then
-        commands.add_command('test-tile-support-range', '<tilename> <range> creates a square of tiles with length <range>. It is spawned one <range> north of the player.', function(cmd)
-                local params = {}
-                for param in string.gmatch(cmd.parameter, '%S+') do
-                    table.insert(params, param)
-                end
-
-                local tilename = params[1]
-                local range = tonumber(params[2])
-
-                local position = {x = math.floor(game.player.position.x), y = math.floor(game.player.position.y) - 5 * range - 1}
-                local surface = game.player.surface
-                local tiles = {}
-                local entities = {}
-                for x = position.x, position.x + range * 5 do
-                    for y = position.y, position.y + range  * 5 do
-                        if y % range + x % range == 0 then
-                            insert(entities,{name = "stone-wall", position = {x=x,y=y}})
-                        end
-                        insert(tiles, {position = {x = x, y = y}, name = tilename})
-
-                        local strength = support_beam_entities[tilename]
-                        if strength then
-                            stress_map_add(surface, {x =x, y=y}, - strength)
-                        end
-                        for _, entity in pairs(surface.find_entities_filtered({position = {x=x,y=y}})) do
-                            pcall(function()
-                                    local strength = support_beam_entities[entity.name]
-                                    local position = entity.position
-                                    entity.die()
-                                    if strength then
-                                        stress_map_add(surface, position, strength)
-                                    end
-                                end
-                            )
-                        end
-                    end
-                end
-                Template.insert(surface, tiles, entities)
-            end
-        )
-     end
-
-    commands.add_command('toggle-cave-collapse', 'Toggles cave collapse (admins only).', function()
-      pcall(function() --better safe than sorry
-          if not game.player or game.player.admin then
-              cave_collapse_disabled = not cave_collapse_disabled
-              if cave_collapse_disabled then
-                  game.print("Cave collapse: Disabled.")
-              else
-                  game.print("Cave collapse: Enabled.")
-              end
-          end
-      end)
-    end)
-end
-
---
---STRESS MAP
---
---[[--
-    Adds a fraction to a given location on the stress_map. Returns the new
-    fraction value of that position.
-
-    @param stress_map Table of {x,y}
-    @param position Table with x and y
-    @param number fraction
-
-    @return number sum of old fraction + new fraction
-]]
-local function add_fraction(stress_map, x, y, fraction, player_index)
-    x = 2 * floor(x * 0.5)
-    y = 2 * floor(y * 0.5)
-
-    local x_t = stress_map[x]
-    if not x_t then
-        x_t = {}
-        stress_map[x] = x_t
-    end
-
-    local value = x_t[y]
-    if not value then
-        value = defaultValue
-    end
-
-    value = value + fraction
-
-    x_t[y] = value
-
-    if (fraction > 0 and value > stress_threshold_causing_collapse) then
-        script.raise_event(
-            DiggyCaveCollapse.events.on_collapse_triggered,
-            {surface = game.surfaces[stress_map.surface_index], position = {x = x, y = y}, player_index = player_index}
-        )
-    end
-    if (enable_stress_grid) then
-        local surface = game.surfaces[stress_map.surface_index]
-        Debug.print_colored_grid_value(value, surface, {x = x, y = y}, 4, 0.5, false,
-            value / stress_threshold_causing_collapse,  {r = 0, g = 1, b = 0}, {r = 1, g = -1, b = 0},
-            {r = 0, g = 1, b = 0}, {r = 1, g = 1, b = 1})
-    end
-    return value
-end
-
-on_surface_created = function (event)
-    stress_map_storage[event.surface_index] = {}
-
-    local map = stress_map_storage[event.surface_index]
-
-    map['surface_index'] = event.surface_index
-    map[1] = {index = 1}
-    map[2] = {index = 2}
-    map[3] = {index = 3}
-    map[4] = {index = 4}
-end
-
---[[--
-    Checks whether a tile's pressure is within a given threshold and calls the handler if not.
-    @param surface LuaSurface
-    @param position Position with x and y
-    @param number threshold
-    @param callback
-]]
-stress_map_check_stress_in_threshold = function(surface, position, threshold, callback)
-    local stress_map = stress_map_storage[surface.index]
-    local value = add_fraction(stress_map, position.x, position.y, 0)
-
-    if (value >= stress_threshold_causing_collapse - threshold) then
-        callback(surface, position)
-    end
-end
-
-stress_map_add = function(surface, position, factor, no_blur, player_index)
-    local x_start = floor(position.x)
-    local y_start = floor(position.y)
-
-    local stress_map = stress_map_storage[surface.index]
-    if not stress_map then
-        return
-    end
-
-    if no_blur then
-        add_fraction(stress_map, x_start, y_start, factor, player_index)
-        return
-    end
-
-    for x = -radius, radius do
-        for y = -radius, radius do
-            local value = 0
-            local distance_sq = x * x + y * y
-            if distance_sq <= center_radius_sq then
-                value = center_value
-            elseif distance_sq <= disc_radius_sq then
-                value = disc_value
-            elseif distance_sq <= radius_sq then
-                value = ring_value
-            end
-            if abs(value) > 0.001 then
-                add_fraction(stress_map, x + x_start, y + y_start, value * factor, player_index)
-            end
-        end
-    end
-end
-
-DiggyCaveCollapse.stress_map_add = stress_map_add
-
---
--- MASK
---
-
-function mask_init(config)
-    n = config.mask_size
-
-    ring_weight = config.mask_relative_ring_weights[1]
-    disc_weight = config.mask_relative_ring_weights[2]
-    center_weight = config.mask_relative_ring_weights[3]
-
-    radius = floor(n * 0.5)
-
-    radius_sq = (radius + 0.2) * (radius + 0.2)
-    center_radius_sq = radius_sq / 9
-    disc_radius_sq = radius_sq * 4 / 9
-
-    for x = -radius, radius do
-        for y = -radius, radius do
-            local distance_sq = x * x + y * y
-            if distance_sq <= center_radius_sq then
-                disc_blur_sum = disc_blur_sum + center_weight
-            elseif distance_sq <= disc_radius_sq then
-                disc_blur_sum = disc_blur_sum + disc_weight
-            elseif distance_sq <= radius_sq then
-                disc_blur_sum = disc_blur_sum + ring_weight
-            end
-        end
-    end
-    center_value = center_weight / disc_blur_sum
-    disc_value = disc_weight / disc_blur_sum
-    ring_value = ring_weight / disc_blur_sum
-end
-
---[[--
-    Applies a blur
-    Applies the disc in 3 discs: center, (middle) disc and (outer) ring.
-    The relative weights for tiles in a disc are:
-    center: 3/3
-    disc: 2/3
-    ring: 1/3
-    The sum of all values is 1
-
-    @param x_start number center point
-    @param y_start number center point
-    @param factor the factor to multiply the cell value with (value = cell_value * factor)
-    @param callback function to execute on each tile within the mask callback(x, y, value)
-]]
-mask_disc_blur = function(x_start, y_start, factor, callback)
-    x_start = floor(x_start)
-    y_start = floor(y_start)
-    for x = -radius, radius do
-        for y = -radius, radius do
-            local value = 0
-            local distance_sq = x * x + y * y
-            if distance_sq <= center_radius_sq then
-                value = center_value
-            elseif distance_sq <= disc_radius_sq then
-                value = disc_value
-            elseif distance_sq <= radius_sq then
-                value = ring_value
-            end
-            if abs(value) > 0.001 then
-                callback(x_start + x, y_start + y, value * factor)
-            end
-        end
-    end
-end
-
-function DiggyCaveCollapse.get_extra_map_info(config)
-    return [[Alien Spawner, aliens might spawn when mining!
-Place stone walls, stone paths and (refined) concrete to reinforce the mine. If you see cracks appear, run!]]
-end
-
-return DiggyCaveCollapse
+--[[-- info
+    Provides the ability to collapse caves when digging.
+]]
+-- dependencies
+require 'utils.list_utils'
+
+local Event = require 'utils.event'
+local Template = require 'map_gen.Diggy.Template'
+local ScoreTable = require 'map_gen.Diggy.ScoreTable'
+local Debug = require 'map_gen.Diggy.Debug'
+local Task = require 'utils.Task'
+local Token = require 'utils.global_token'
+local Global = require 'utils.global'
+local Game = require 'utils.game'
+local insert = table.insert
+local random = math.random
+local floor = math.floor
+local abs = math.abs
+
+-- this
+local DiggyCaveCollapse = {}
+
+local config = {}
+
+local n = 9
+local radius = 0
+local radius_sq = 0
+local center_radius_sq = 0
+local disc_radius_sq = 0
+
+local center_weight
+local disc_weight
+local ring_weight
+
+local disc_blur_sum = 0
+
+local center_value = 0
+local disc_value = 0
+local ring_value = 0
+
+local enable_stress_grid = 0
+local stress_map_add
+local mask_disc_blur
+local stress_map_check_stress_in_threshold
+local support_beam_entities
+local on_surface_created
+
+local stress_threshold_causing_collapse = 3.57
+
+local show_deconstruction_alert_message = {}
+local stress_map_storage = {}
+local new_tile_map = {}
+local collapse_positions_storage = {}
+
+Global.register({
+    new_tile_map = new_tile_map,
+    stress_map_storage = stress_map_storage,
+    deconstruction_alert_message_shown = show_deconstruction_alert_message,
+    collapse_positions_storage = collapse_positions_storage,
+}, function(tbl)
+    new_tile_map = tbl.new_tile_map
+    stress_map_storage = tbl.stress_map_storage
+    show_deconstruction_alert_message = tbl.deconstruction_alert_message_shown
+    collapse_positions_storage = tbl.collapse_positions_storage
+end)
+
+local defaultValue = 0
+
+DiggyCaveCollapse.events = {
+    --[[--
+        When stress at certain position is above the collapse threshold
+         - position LuaPosition
+         - surface LuaSurface
+         - player_index Number (index of player that caused the collapse)
+    ]]
+    on_collapse_triggered = script.generate_event_name(),
+
+    --[[--
+        After a collapse
+         - position LuaPosition
+         - surface LuaSurface
+         - player_index Number (index of player that caused the collapse)
+    ]]
+    on_collapse = script.generate_event_name()
+}
+
+local function create_collapse_template(positions, surface)
+    local entities = {}
+
+    local find_entities_filtered = surface.find_entities_filtered
+
+    for _, position in pairs(positions) do
+        local x = position.x
+        local y = position.y
+        local do_insert = true
+
+        for _, entity in pairs(find_entities_filtered{area = {{x, y}, {x + 1, y + 1}}}) do
+            pcall(function()
+                local strength = support_beam_entities[entity.name]
+                if strength then
+                    do_insert = false
+                else
+                    entity.die()
+                end
+            end)
+        end
+        if do_insert then
+            insert(entities, {position = {x = x, y = y}, name = 'sand-rock-big'})
+        end
+    end
+    return entities
+end
+
+local function create_collapse_alert(surface, position)
+    local target = surface.create_entity{position = position, name = "sand-rock-big"}
+    for _,player in pairs(game.connected_players) do
+        player.add_custom_alert(target, {type="item", name="stone"}, "Cave collapsed!", true)
+    end
+    target.destroy()
+end
+
+local function collapse(args)
+    local position = args.position
+    local surface = args.surface
+    local positions = {}
+    local strength = config.collapse_threshold_total_strength
+    local player_index = args.player_index
+    create_collapse_alert(surface, position)
+    mask_disc_blur(
+        position.x,  position.y,
+        strength,
+        function(x, y, value)
+            stress_map_check_stress_in_threshold(
+                surface,
+                {x = x, y = y},
+                value,
+                function(_, position)
+                    insert(positions, position)
+                end
+            )
+        end
+    )
+    local entities = create_collapse_template(positions, surface)
+    Template.insert(surface, {}, entities)
+
+    script.raise_event(DiggyCaveCollapse.events.on_collapse, args)
+    ScoreTable.increment('Cave collapse')
+end
+
+local on_collapse_timeout_finished = Token.register(collapse)
+
+local function spawn_cracking_sound_text(surface, position)
+    local text = config.cracking_sounds[random(1, #config.cracking_sounds)]
+
+    local color = {
+        r = 1,
+        g = random(1, 100) * 0.01,
+        b = 0
+    }
+
+    local create_entity = surface.create_entity
+
+    for i = 1, #text do
+        local x_offset = (i - #text / 2 - 1) / 3
+        local char = text:sub(i, i)
+        create_entity {
+            name = 'flying-text',
+            color = color,
+            text = char,
+            position = {x = position.x + x_offset, y = position.y - ((i + 1) % 2) * 0.25}
+        }.active = true
+    end
+end
+
+local function on_collapse_triggered(event)
+    if global.cave_collapse_disabled then return end --kill switch
+
+    local surface = event.surface
+    local position = event.position
+    local x = position.x
+    local y = position.y
+
+    local x_t = new_tile_map[x]
+    if x_t and x_t[y] then
+        Template.insert(surface, {}, {{position = position, name = 'sand-rock-big'}})
+        return
+    end
+    spawn_cracking_sound_text(surface, position)
+    Task.set_timeout(
+        config.collapse_delay,
+        on_collapse_timeout_finished,
+        event
+    )
+end
+
+local function on_built_tile(surface, new_tile, tiles)
+    local new_tile_strength = support_beam_entities[new_tile.name]
+
+    for _, tile in pairs(tiles) do
+        if new_tile_strength then
+            stress_map_add(surface, tile.position, -1 * new_tile_strength, true)
+        end
+
+        local old_tile_strength = support_beam_entities[tile.old_tile.name]
+        if (old_tile_strength) then
+            stress_map_add(surface, tile.position, old_tile_strength, true)
+        end
+    end
+end
+
+--It is impossible to track which player marked the tile for deconstruction
+local function on_robot_mined_tile(event)
+    local surface
+    for _, tile in pairs(event.tiles) do
+        local strength = support_beam_entities[tile.old_tile.name]
+        if strength then
+            surface = surface or event.robot.surface
+            stress_map_add(surface, tile.position, strength, true)
+        end
+    end
+end
+
+local function on_player_mined_tile(event)
+    local surface = game.surfaces[event.surface_index]
+    for _, tile in pairs(event.tiles) do
+        local strength = support_beam_entities[tile.old_tile.name]
+
+        if strength then
+            stress_map_add(surface, tile.position, strength, true, event.player_index)
+        end
+    end
+end
+
+local function on_robot_mined_entity(event)
+    local entity = event.entity
+    local strength = support_beam_entities[entity.name]
+
+    if strength then
+        stress_map_add(entity.surface, entity.position, strength, false, entity.last_user.index)
+    end
+end
+
+local function on_mined_entity(event)
+    local entity = event.entity
+    local name = entity.name
+    local strength = support_beam_entities[name]
+    if strength then
+        stress_map_add(entity.surface, entity.position, strength, false, (not (name == "sand-rock-big" or name == "rock-huge")) and event.player_index)
+    end
+end
+
+local function on_entity_died(event)
+    local entity = event.entity
+    local name = entity.name
+    local strength = support_beam_entities[name]
+    if strength then
+        local cause = event.cause or {}
+        stress_map_add(entity.surface, entity.position, strength, false, (not (name == "sand-rock-big" or name == "rock-huge")) and cause.index)
+    end
+end
+
+local function on_built_entity(event)
+    local entity = event.created_entity
+    local strength = support_beam_entities[entity.name]
+
+    if strength then
+        stress_map_add(entity.surface, entity.position, -1 * strength)
+    end
+end
+
+local function on_placed_entity(event)
+    local strength = support_beam_entities[event.entity.name]
+
+    if strength then
+        stress_map_add(event.entity.surface, event.entity.position, -1 * strength)
+    end
+end
+
+
+local on_new_tile_timeout_finished = Token.register(function(args)
+    local x_t = new_tile_map[args.x]
+    if x_t then
+       x_t[args.y] = nil --reset new tile status. This tile can cause a chain collapse now
+    end
+end)
+
+local function on_void_removed(event)
+    local strength = support_beam_entities['out-of-map']
+
+    local position = event.position
+    if strength then
+        stress_map_add(event.surface, position, strength)
+    end
+
+    local x = position.x
+    local y = position.y
+
+    --To avoid room collapse:
+    local x_t = new_tile_map[x]
+    if x_t then
+        x_t[y] = true
+    else
+        x_t = {
+            [y] = true
+        }
+        new_tile_map[x] = x_t
+    end
+    Task.set_timeout(3, on_new_tile_timeout_finished, {x = x, y = y})
+end
+
+--[[--
+    Registers all event handlers.]
+
+    @param global_config Table {@see Diggy.Config}.
+]]
+function DiggyCaveCollapse.register(cfg)
+    config = cfg
+    support_beam_entities = config.support_beam_entities
+
+    if support_beam_entities['stone-path'] then
+        support_beam_entities['stone-brick'] = support_beam_entities['stone-path']
+    else
+        support_beam_entities['stone-brick'] = nil
+    end
+
+    if support_beam_entities['hazard-concrete'] then
+        support_beam_entities['hazard-concrete-left'] = support_beam_entities['hazard-concrete']
+        support_beam_entities['hazard-concrete-right'] = support_beam_entities['hazard-concrete']
+    else
+        support_beam_entities['hazard-concrete-left'] = nil
+        support_beam_entities['hazard-concrete-right'] = nil
+    end
+
+    if support_beam_entities['refined-hazard-concrete'] then
+        support_beam_entities['refined-hazard-concrete-left'] = support_beam_entities['refined-hazard-concrete']
+        support_beam_entities['refined-hazard-concrete-right'] = support_beam_entities['refined-hazard-concrete']
+    else
+        support_beam_entities['refined-hazard-concrete-left'] = nil
+        support_beam_entities['refined-hazard-concrete-right'] = nil
+    end
+
+    ScoreTable.reset('Cave collapse')
+
+    Event.add(DiggyCaveCollapse.events.on_collapse_triggered, on_collapse_triggered)
+    Event.add(defines.events.on_robot_built_entity, on_built_entity)
+    Event.add(defines.events.on_robot_built_tile, function (event)
+        on_built_tile(event.robot.surface, event.item, event.tiles)
+    end)
+    Event.add(defines.events.on_player_built_tile, function (event)
+        on_built_tile(game.surfaces[event.surface_index], event.item, event.tiles)
+    end)
+    Event.add(defines.events.on_robot_mined_tile, on_robot_mined_tile)
+    Event.add(defines.events.on_player_mined_tile, on_player_mined_tile)
+    Event.add(defines.events.on_robot_mined_entity, on_robot_mined_entity)
+    Event.add(defines.events.on_built_entity, on_built_entity)
+    Event.add(Template.events.on_placed_entity, on_placed_entity)
+    Event.add(defines.events.on_entity_died, on_entity_died)
+    Event.add(defines.events.on_player_mined_entity, on_mined_entity)
+    Event.add(Template.events.on_void_removed, on_void_removed)
+    Event.add(defines.events.on_surface_created, on_surface_created)
+
+    Event.add(defines.events.on_marked_for_deconstruction, function (event)
+        if (nil ~= support_beam_entities[event.entity.name]) then
+            event.entity.cancel_deconstruction(Game.get_player_by_index(event.player_index).force)
+        end
+    end)
+
+    Event.add(defines.events.on_player_created, function (event)
+        show_deconstruction_alert_message[event.player_index] = true
+    end)
+
+    Event.add(defines.events.on_pre_player_mined_item, function (event)
+        local player_index = event.player_index
+        if not show_deconstruction_alert_message[player_index] then
+            return
+        end
+
+        if (nil ~= support_beam_entities[event.entity.name]) then
+            require 'features.gui.popup'.player(
+                Game.get_player_by_index(player_index),[[
+Mining entities such as walls, stone paths, concrete
+and rocks, can cause a cave-in, be careful miner!
+
+Foreman's advice: Place a wall every 4th tile to
+prevent a cave-in. Use stone paths and concrete
+to reinforce it further.
+]]
+            )
+            show_deconstruction_alert_message[player_index] = nil
+        end
+    end)
+
+    enable_stress_grid = config.enable_stress_grid
+
+    on_surface_created({surface_index = 1})
+
+    mask_init(config)
+    if (config.enable_mask_debug) then
+        local surface = game.surfaces.nauvis
+        mask_disc_blur(0, 0, 10,  function(x, y, fraction)
+            Debug.print_grid_value(fraction, surface, {x = x, y = y})
+        end)
+    end
+
+
+    if config.enable_debug_commands then
+        commands.add_command('test-tile-support-range', '<tilename> <range> creates a square of tiles with length <range>. It is spawned one <range> north of the player.', function(cmd)
+                local params = {}
+                for param in string.gmatch(cmd.parameter, '%S+') do
+                    table.insert(params, param)
+                end
+
+                local tilename = params[1]
+                local range = tonumber(params[2])
+
+                local position = {x = math.floor(game.player.position.x), y = math.floor(game.player.position.y) - 5 * range - 1}
+                local surface = game.player.surface
+                local tiles = {}
+                local entities = {}
+                for x = position.x, position.x + range * 5 do
+                    for y = position.y, position.y + range  * 5 do
+                        if y % range + x % range == 0 then
+                            insert(entities,{name = "stone-wall", position = {x=x,y=y}})
+                        end
+                        insert(tiles, {position = {x = x, y = y}, name = tilename})
+
+                        local strength = support_beam_entities[tilename]
+                        if strength then
+                            stress_map_add(surface, {x =x, y=y}, - strength)
+                        end
+                        for _, entity in pairs(surface.find_entities_filtered({position = {x=x,y=y}})) do
+                            pcall(function()
+                                    local strength = support_beam_entities[entity.name]
+                                    local position = entity.position
+                                    entity.die()
+                                    if strength then
+                                        stress_map_add(surface, position, strength)
+                                    end
+                                end
+                            )
+                        end
+                    end
+                end
+                Template.insert(surface, tiles, entities)
+            end
+        )
+     end
+
+    commands.add_command('toggle-cave-collapse', 'Toggles cave collapse (admins only).', function()
+      pcall(function() --better safe than sorry
+          if not game.player or game.player.admin then
+              cave_collapse_disabled = not cave_collapse_disabled
+              if cave_collapse_disabled then
+                  game.print("Cave collapse: Disabled.")
+              else
+                  game.print("Cave collapse: Enabled.")
+              end
+          end
+      end)
+    end)
+end
+
+--
+--STRESS MAP
+--
+--[[--
+    Adds a fraction to a given location on the stress_map. Returns the new
+    fraction value of that position.
+
+    @param stress_map Table of {x,y}
+    @param position Table with x and y
+    @param number fraction
+
+    @return number sum of old fraction + new fraction
+]]
+local function add_fraction(stress_map, x, y, fraction, player_index)
+    x = 2 * floor(x * 0.5)
+    y = 2 * floor(y * 0.5)
+
+    local x_t = stress_map[x]
+    if not x_t then
+        x_t = {}
+        stress_map[x] = x_t
+    end
+
+    local value = x_t[y]
+    if not value then
+        value = defaultValue
+    end
+
+    value = value + fraction
+
+    x_t[y] = value
+
+    if (fraction > 0 and value > stress_threshold_causing_collapse) then
+        script.raise_event(
+            DiggyCaveCollapse.events.on_collapse_triggered,
+            {surface = game.surfaces[stress_map.surface_index], position = {x = x, y = y}, player_index = player_index}
+        )
+    end
+    if (enable_stress_grid) then
+        local surface = game.surfaces[stress_map.surface_index]
+        Debug.print_colored_grid_value(value, surface, {x = x, y = y}, 4, 0.5, false,
+            value / stress_threshold_causing_collapse,  {r = 0, g = 1, b = 0}, {r = 1, g = -1, b = 0},
+            {r = 0, g = 1, b = 0}, {r = 1, g = 1, b = 1})
+    end
+    return value
+end
+
+on_surface_created = function (event)
+    stress_map_storage[event.surface_index] = {}
+
+    local map = stress_map_storage[event.surface_index]
+
+    map['surface_index'] = event.surface_index
+    map[1] = {index = 1}
+    map[2] = {index = 2}
+    map[3] = {index = 3}
+    map[4] = {index = 4}
+end
+
+--[[--
+    Checks whether a tile's pressure is within a given threshold and calls the handler if not.
+    @param surface LuaSurface
+    @param position Position with x and y
+    @param number threshold
+    @param callback
+]]
+stress_map_check_stress_in_threshold = function(surface, position, threshold, callback)
+    local stress_map = stress_map_storage[surface.index]
+    local value = add_fraction(stress_map, position.x, position.y, 0)
+
+    if (value >= stress_threshold_causing_collapse - threshold) then
+        callback(surface, position)
+    end
+end
+
+stress_map_add = function(surface, position, factor, no_blur, player_index)
+    local x_start = floor(position.x)
+    local y_start = floor(position.y)
+
+    local stress_map = stress_map_storage[surface.index]
+    if not stress_map then
+        return
+    end
+
+    if no_blur then
+        add_fraction(stress_map, x_start, y_start, factor, player_index)
+        return
+    end
+
+    for x = -radius, radius do
+        for y = -radius, radius do
+            local value = 0
+            local distance_sq = x * x + y * y
+            if distance_sq <= center_radius_sq then
+                value = center_value
+            elseif distance_sq <= disc_radius_sq then
+                value = disc_value
+            elseif distance_sq <= radius_sq then
+                value = ring_value
+            end
+            if abs(value) > 0.001 then
+                add_fraction(stress_map, x + x_start, y + y_start, value * factor, player_index)
+            end
+        end
+    end
+end
+
+DiggyCaveCollapse.stress_map_add = stress_map_add
+
+--
+-- MASK
+--
+
+function mask_init(config)
+    n = config.mask_size
+
+    ring_weight = config.mask_relative_ring_weights[1]
+    disc_weight = config.mask_relative_ring_weights[2]
+    center_weight = config.mask_relative_ring_weights[3]
+
+    radius = floor(n * 0.5)
+
+    radius_sq = (radius + 0.2) * (radius + 0.2)
+    center_radius_sq = radius_sq / 9
+    disc_radius_sq = radius_sq * 4 / 9
+
+    for x = -radius, radius do
+        for y = -radius, radius do
+            local distance_sq = x * x + y * y
+            if distance_sq <= center_radius_sq then
+                disc_blur_sum = disc_blur_sum + center_weight
+            elseif distance_sq <= disc_radius_sq then
+                disc_blur_sum = disc_blur_sum + disc_weight
+            elseif distance_sq <= radius_sq then
+                disc_blur_sum = disc_blur_sum + ring_weight
+            end
+        end
+    end
+    center_value = center_weight / disc_blur_sum
+    disc_value = disc_weight / disc_blur_sum
+    ring_value = ring_weight / disc_blur_sum
+end
+
+--[[--
+    Applies a blur
+    Applies the disc in 3 discs: center, (middle) disc and (outer) ring.
+    The relative weights for tiles in a disc are:
+    center: 3/3
+    disc: 2/3
+    ring: 1/3
+    The sum of all values is 1
+
+    @param x_start number center point
+    @param y_start number center point
+    @param factor the factor to multiply the cell value with (value = cell_value * factor)
+    @param callback function to execute on each tile within the mask callback(x, y, value)
+]]
+mask_disc_blur = function(x_start, y_start, factor, callback)
+    x_start = floor(x_start)
+    y_start = floor(y_start)
+    for x = -radius, radius do
+        for y = -radius, radius do
+            local value = 0
+            local distance_sq = x * x + y * y
+            if distance_sq <= center_radius_sq then
+                value = center_value
+            elseif distance_sq <= disc_radius_sq then
+                value = disc_value
+            elseif distance_sq <= radius_sq then
+                value = ring_value
+            end
+            if abs(value) > 0.001 then
+                callback(x_start + x, y_start + y, value * factor)
+            end
+        end
+    end
+end
+
+function DiggyCaveCollapse.get_extra_map_info(config)
+    return [[Alien Spawner, aliens might spawn when mining!
+Place stone walls, stone paths and (refined) concrete to reinforce the mine. If you see cracks appear, run!]]
+end
+
+return DiggyCaveCollapse
diff --git a/map_gen/Diggy/Feature/DiggyHole.lua b/map_gen/Diggy/Feature/DiggyHole.lua
index 264eb4c1..fdb852d1 100644
--- a/map_gen/Diggy/Feature/DiggyHole.lua
+++ b/map_gen/Diggy/Feature/DiggyHole.lua
@@ -1,307 +1,307 @@
---[[-- info
-    Provides the ability to "mine" through out-of-map tiles by destroying or
-    mining rocks next to it.
-]]
-
--- dependencies
-local Event = require 'utils.event'
-local Global = require 'utils.global'
-local Game = require 'utils.game'
-local Scanner = require 'map_gen.Diggy.Scanner'
-local Template = require 'map_gen.Diggy.Template'
-local ScoreTable = require 'map_gen.Diggy.ScoreTable'
-local Debug = require 'map_gen.Diggy.Debug'
-local insert = table.insert
-local random = math.random
-
--- todo remove this dependency
-local ResourceConfig = require 'map_gen.Diggy.Config'.features.ScatteredResources
-
-local Perlin = require 'map_gen.shared.perlin_noise'
-local Simplex = require 'map_gen.shared.simplex_noise'
-
--- this
-local DiggyHole = {}
-
--- keeps track of the amount of times per player when they mined with a full inventory in a row
-local full_inventory_mining_cache = {}
-
-Global.register({
-    full_inventory_mining_cache = full_inventory_mining_cache,
-}, function (tbl)
-    full_inventory_mining_cache = tbl.full_inventory_mining_cache
-end)
-
-local function reset_player_full_inventory_cache(player)
-    if not full_inventory_mining_cache[player.index] then
-        return
-    end
-
-    full_inventory_mining_cache[player.index] = nil
-end
-
-local full_inventory_message = 'Miner, you have a full inventory!\n\nMake sure to empty it before you continue digging.'
-
-local function trigger_inventory_warning(player)
-    local player_index = player.index
-    local count = full_inventory_mining_cache[player_index]
-    if not count then
-        full_inventory_mining_cache[player_index] = 1
-        player.print('## - ' .. full_inventory_message, {r = 1, g = 1, b = 0, a = 1})
-        player.play_sound{path='utility/new_objective', volume_modifier = 1 }
-        return
-    end
-
-    full_inventory_mining_cache[player_index] = count + 1
-
-    if count % 5 == 0 then
-        require 'features.gui.popup'.player(player, full_inventory_message)
-    end
-end
-
---[[--
-    Triggers a diggy diggy hole for a given sand-rock-big or rock-huge.
-
-    Will return true even if the tile behind it is immune.
-
-    @param entity LuaEntity
-]]
-local function diggy_hole(entity)
-    if ((entity.name ~= 'sand-rock-big') and (entity.name ~= 'rock-huge')) then
-        return
-    end
-
-    local tiles = {}
-    local rocks = {}
-    local surface = entity.surface
-    local position = entity.position
-    local x = position.x
-    local y = position.y
-
-    local out_of_map_found = Scanner.scan_around_position(surface, position, 'out-of-map');
-    local distance = ResourceConfig.distance(x, y)
-
-    -- source of noise for resource generation
-    -- index determines offset
-    -- '-1' is reserved for cluster mode
-    -- compound clusters use as many indexes as needed > 1
-    local base_seed
-    local function seeded_noise(surface, x, y, index, sources)
-        base_seed = base_seed or surface.map_gen_settings.seed + surface.index + 4000
-        local noise = 0
-        for _, settings in ipairs(sources) do
-            settings.type = settings.type or 'perlin'
-            settings.offset = settings.offset or 0
-            if settings.type == 'zero' then
-                noise = noise + 0
-            elseif settings.type == 'one' then
-                noise = noise + settings.weight * 1
-            elseif settings.type == 'perlin' then
-                noise = noise + settings.weight * Perlin.noise(x/settings.variance, y/settings.variance,
-                            base_seed + 2000*index + settings.offset)
-            elseif settings.type == 'simplex' then
-                noise = noise + settings.weight * Simplex.d2(x/settings.variance, y/settings.variance,
-                            base_seed + 2000*index + settings.offset)
-            else
-                Debug.print('noise type \'' .. settings.type .. '\' not recognized')
-            end
-            
-        end
-        return noise
-    end
-
-    -- global config values
-    local resource_richness_weights = ResourceConfig.resource_richness_weights
-    local resource_richness_weights_sum = 0
-    for _, weight in pairs(resource_richness_weights) do
-        resource_richness_weights_sum = resource_richness_weights_sum + weight
-    end
-
-    local s_resource_weights = ResourceConfig.scattered_resource_weights
-    local s_resource_weights_sum = 0
-    for _, weight in pairs(s_resource_weights) do
-        s_resource_weights_sum = s_resource_weights_sum + weight
-    end
-
-    -- compound cluster spawning
-    local c_mode = ResourceConfig.cluster_mode
---    local c_clusters = Config.features.ScatteredResources.clusters
-    local c_clusters = require(ResourceConfig.cluster_file_location)
-    if ('table' ~= type(c_clusters)) then
-        error('cluster_file_location invalid')
-    end
-    
-    local c_count = 0
-    for _, cluster in ipairs(c_clusters) do
-        c_count = c_count + 1
-        cluster.weights_sum = 0
-        for _, weight in pairs(cluster.weights) do
-            cluster.weights_sum = cluster.weights_sum + weight
-        end
-    end
-
-    local function spawn_cluster_resource(surface, x, y, cluster_index, cluster)
-        for name, weight in pairs(cluster.weights) do
-            if name == 'skip' then return false end
-        end
-        return true
-    end
-
-        local huge_rock_inserted = false
-    for _, position in pairs(out_of_map_found) do
-        insert(tiles, {name = 'dirt-' .. random(1, 7), position = position})
---        if (random() > 0.50) then
---        insert(rocks, {name = 'rock-huge', position = position})
-
-
-        if c_mode then
-            for index,cluster in ipairs(c_clusters) do
-                if distance >= cluster.min_distance and cluster.noise_settings.type ~= 'skip' then
-                    if cluster.noise_settings.type == "connected_tendril" then
-                        local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
-                        if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
-                            if spawn_cluster_resource(surface, x, y, index, cluster) then
-                                insert(rocks, {name = 'rock-huge', position = position})
-                                huge_rock_inserted = true
-                            end
-                        end
-                    elseif cluster.noise_settings.type == "fragmented_tendril" then
-                        local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
-                        local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
-                        if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold 
-                                and -1 * cluster.noise_settings.discriminator_threshold < noise2
-                                and noise2 < cluster.noise_settings.discriminator_threshold then
-                            if spawn_cluster_resource(surface, x, y, index, cluster) then
-                                insert(rocks, {name = 'rock-huge', position = position})
-                                huge_rock_inserted = true
-                            end
-                        end
-                    else
-                        local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
-                        if noise >= cluster.noise_settings.threshold then
-                            if spawn_cluster_resource(surface, x, y, index, cluster) then
-                                insert(rocks, {name = 'rock-huge', position = position})
-                                huge_rock_inserted = true
-                            end
-                        end
-                    end
-                end
-            end
-        end
-    
-    if (huge_rock_inserted == false) then
-        insert(rocks, {name = 'sand-rock-big', position = position})
-        end
-    end
-
-    Template.insert(surface, tiles, rocks)
-end
-
-local artificial_tiles = {
-    ['stone-brick'] = true,
-    ['stone-path'] = true,
-    ['concrete'] = true,
-    ['hazard-concrete-left'] = true,
-    ['hazard-concrete-right'] = true,
-    ['refined-concrete'] = true,
-    ['refined-hazard-concrete-left'] = true,
-    ['refined-hazard-concrete-right'] = true,
-}
-
-local function on_mined_tile(surface, tiles)
-    local new_tiles = {}
-
-    for _, tile in pairs(tiles) do
-        if (artificial_tiles[tile.old_tile.name]) then
-            insert(new_tiles, { name = 'dirt-' .. random(1, 7), position = tile.position})
-        end
-    end
-
-    Template.insert(surface, new_tiles, {})
-end
-
---[[--
-    Registers all event handlers.
-]]
-function DiggyHole.register(config)
-    ScoreTable.reset('Void removed')
-
-    Event.add(defines.events.on_entity_died, function (event)
-        diggy_hole(event.entity)
-    end)
-
-    local enable_digging_warning = config.enable_digging_warning
-
-    Event.add(defines.events.on_player_mined_entity, function (event)
-        local entity = event.entity
-        local name = entity.name
-
-        if name == 'sand-rock-big' or name == 'rock-huge' then
-            event.buffer.remove({name = 'coal', count = 100})
-
-            -- this logic can be replaced once we've fully replaced the stone to surface functionality
-            if enable_digging_warning then
-                local player = Game.get_player_by_index(event.player_index)
-                if player and player.valid then
-                    if player.get_main_inventory().can_insert({name = 'stone'}) then
-                        reset_player_full_inventory_cache(player)
-                    else
-                        trigger_inventory_warning(player)
-                    end
-                end
-            end
-        end
-
-        diggy_hole(entity)
-    end)
-
-    Event.add(defines.events.on_robot_mined_tile, function (event)
-        on_mined_tile(event.robot.surface, event.tiles)
-    end)
-
-    Event.add(defines.events.on_player_mined_tile, function (event)
-        on_mined_tile(game.surfaces[event.surface_index], event.tiles)
-    end)
-
-    Event.add(Template.events.on_void_removed, function ()
-        ScoreTable.increment('Void removed')
-    end)
-
-    if config.enable_debug_commands then
-        commands.add_command('clear-void', '<left top x> <left top y> <width> <height> <surface index> triggers Template.insert for the given area.', function(cmd)
-            local params = {}
-            local args = cmd.parameter or ''
-            for param in string.gmatch(args, '%S+') do
-                table.insert(params, param)
-            end
-
-            if (#params ~= 5) then
-                game.player.print('/clear-void requires exactly 5 arguments: <left top x> <left top y> <width> <height> <surface index>')
-                return
-            end
-
-            local left_top_x = tonumber(params[1])
-            local left_top_y = tonumber(params[2])
-            local width = tonumber(params[3])
-            local height = tonumber(params[4])
-            local surface_index = params[5]
-            local tiles = {}
-            local entities = {}
-
-            for x = 0, width do
-                for y = 0, height do
-                    insert(tiles, {name = 'dirt-' .. random(1, 7), position = {x = x + left_top_x, y = y + left_top_y}})
-                end
-            end
-
-            Template.insert(game.surfaces[surface_index], tiles, entities)
-        end
-        )
-    end
-end
-
-function DiggyHole.on_init()
-    game.forces.player.technologies['landfill'].enabled = false
-end
-
-return DiggyHole
+--[[-- info
+    Provides the ability to "mine" through out-of-map tiles by destroying or
+    mining rocks next to it.
+]]
+
+-- dependencies
+local Event = require 'utils.event'
+local Global = require 'utils.global'
+local Game = require 'utils.game'
+local Scanner = require 'map_gen.Diggy.Scanner'
+local Template = require 'map_gen.Diggy.Template'
+local ScoreTable = require 'map_gen.Diggy.ScoreTable'
+local Debug = require 'map_gen.Diggy.Debug'
+local insert = table.insert
+local random = math.random
+
+-- todo remove this dependency
+local ResourceConfig = require 'map_gen.Diggy.Config'.features.ScatteredResources
+
+local Perlin = require 'map_gen.shared.perlin_noise'
+local Simplex = require 'map_gen.shared.simplex_noise'
+
+-- this
+local DiggyHole = {}
+
+-- keeps track of the amount of times per player when they mined with a full inventory in a row
+local full_inventory_mining_cache = {}
+
+Global.register({
+    full_inventory_mining_cache = full_inventory_mining_cache,
+}, function (tbl)
+    full_inventory_mining_cache = tbl.full_inventory_mining_cache
+end)
+
+local function reset_player_full_inventory_cache(player)
+    if not full_inventory_mining_cache[player.index] then
+        return
+    end
+
+    full_inventory_mining_cache[player.index] = nil
+end
+
+local full_inventory_message = 'Miner, you have a full inventory!\n\nMake sure to empty it before you continue digging.'
+
+local function trigger_inventory_warning(player)
+    local player_index = player.index
+    local count = full_inventory_mining_cache[player_index]
+    if not count then
+        full_inventory_mining_cache[player_index] = 1
+        player.print('## - ' .. full_inventory_message, {r = 1, g = 1, b = 0, a = 1})
+        player.play_sound{path='utility/new_objective', volume_modifier = 1 }
+        return
+    end
+
+    full_inventory_mining_cache[player_index] = count + 1
+
+    if count % 5 == 0 then
+        require 'features.gui.popup'.player(player, full_inventory_message)
+    end
+end
+
+--[[--
+    Triggers a diggy diggy hole for a given sand-rock-big or rock-huge.
+
+    Will return true even if the tile behind it is immune.
+
+    @param entity LuaEntity
+]]
+local function diggy_hole(entity)
+    if ((entity.name ~= 'sand-rock-big') and (entity.name ~= 'rock-huge')) then
+        return
+    end
+
+    local tiles = {}
+    local rocks = {}
+    local surface = entity.surface
+    local position = entity.position
+    local x = position.x
+    local y = position.y
+
+    local out_of_map_found = Scanner.scan_around_position(surface, position, 'out-of-map');
+    local distance = ResourceConfig.distance(x, y)
+
+    -- source of noise for resource generation
+    -- index determines offset
+    -- '-1' is reserved for cluster mode
+    -- compound clusters use as many indexes as needed > 1
+    local base_seed
+    local function seeded_noise(surface, x, y, index, sources)
+        base_seed = base_seed or surface.map_gen_settings.seed + surface.index + 4000
+        local noise = 0
+        for _, settings in ipairs(sources) do
+            settings.type = settings.type or 'perlin'
+            settings.offset = settings.offset or 0
+            if settings.type == 'zero' then
+                noise = noise + 0
+            elseif settings.type == 'one' then
+                noise = noise + settings.weight * 1
+            elseif settings.type == 'perlin' then
+                noise = noise + settings.weight * Perlin.noise(x/settings.variance, y/settings.variance,
+                            base_seed + 2000*index + settings.offset)
+            elseif settings.type == 'simplex' then
+                noise = noise + settings.weight * Simplex.d2(x/settings.variance, y/settings.variance,
+                            base_seed + 2000*index + settings.offset)
+            else
+                Debug.print('noise type \'' .. settings.type .. '\' not recognized')
+            end
+            
+        end
+        return noise
+    end
+
+    -- global config values
+    local resource_richness_weights = ResourceConfig.resource_richness_weights
+    local resource_richness_weights_sum = 0
+    for _, weight in pairs(resource_richness_weights) do
+        resource_richness_weights_sum = resource_richness_weights_sum + weight
+    end
+
+    local s_resource_weights = ResourceConfig.scattered_resource_weights
+    local s_resource_weights_sum = 0
+    for _, weight in pairs(s_resource_weights) do
+        s_resource_weights_sum = s_resource_weights_sum + weight
+    end
+
+    -- compound cluster spawning
+    local c_mode = ResourceConfig.cluster_mode
+--    local c_clusters = Config.features.ScatteredResources.clusters
+    local c_clusters = require(ResourceConfig.cluster_file_location)
+    if ('table' ~= type(c_clusters)) then
+        error('cluster_file_location invalid')
+    end
+    
+    local c_count = 0
+    for _, cluster in ipairs(c_clusters) do
+        c_count = c_count + 1
+        cluster.weights_sum = 0
+        for _, weight in pairs(cluster.weights) do
+            cluster.weights_sum = cluster.weights_sum + weight
+        end
+    end
+
+    local function spawn_cluster_resource(surface, x, y, cluster_index, cluster)
+        for name, weight in pairs(cluster.weights) do
+            if name == 'skip' then return false end
+        end
+        return true
+    end
+
+        local huge_rock_inserted = false
+    for _, position in pairs(out_of_map_found) do
+        insert(tiles, {name = 'dirt-' .. random(1, 7), position = position})
+--        if (random() > 0.50) then
+--        insert(rocks, {name = 'rock-huge', position = position})
+
+
+        if c_mode then
+            for index,cluster in ipairs(c_clusters) do
+                if distance >= cluster.min_distance and cluster.noise_settings.type ~= 'skip' then
+                    if cluster.noise_settings.type == "connected_tendril" then
+                        local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
+                        if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
+                            if spawn_cluster_resource(surface, x, y, index, cluster) then
+                                insert(rocks, {name = 'rock-huge', position = position})
+                                huge_rock_inserted = true
+                            end
+                        end
+                    elseif cluster.noise_settings.type == "fragmented_tendril" then
+                        local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
+                        local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
+                        if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold 
+                                and -1 * cluster.noise_settings.discriminator_threshold < noise2
+                                and noise2 < cluster.noise_settings.discriminator_threshold then
+                            if spawn_cluster_resource(surface, x, y, index, cluster) then
+                                insert(rocks, {name = 'rock-huge', position = position})
+                                huge_rock_inserted = true
+                            end
+                        end
+                    else
+                        local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
+                        if noise >= cluster.noise_settings.threshold then
+                            if spawn_cluster_resource(surface, x, y, index, cluster) then
+                                insert(rocks, {name = 'rock-huge', position = position})
+                                huge_rock_inserted = true
+                            end
+                        end
+                    end
+                end
+            end
+        end
+    
+    if (huge_rock_inserted == false) then
+        insert(rocks, {name = 'sand-rock-big', position = position})
+        end
+    end
+
+    Template.insert(surface, tiles, rocks)
+end
+
+local artificial_tiles = {
+    ['stone-brick'] = true,
+    ['stone-path'] = true,
+    ['concrete'] = true,
+    ['hazard-concrete-left'] = true,
+    ['hazard-concrete-right'] = true,
+    ['refined-concrete'] = true,
+    ['refined-hazard-concrete-left'] = true,
+    ['refined-hazard-concrete-right'] = true,
+}
+
+local function on_mined_tile(surface, tiles)
+    local new_tiles = {}
+
+    for _, tile in pairs(tiles) do
+        if (artificial_tiles[tile.old_tile.name]) then
+            insert(new_tiles, { name = 'dirt-' .. random(1, 7), position = tile.position})
+        end
+    end
+
+    Template.insert(surface, new_tiles, {})
+end
+
+--[[--
+    Registers all event handlers.
+]]
+function DiggyHole.register(config)
+    ScoreTable.reset('Void removed')
+
+    Event.add(defines.events.on_entity_died, function (event)
+        diggy_hole(event.entity)
+    end)
+
+    local enable_digging_warning = config.enable_digging_warning
+
+    Event.add(defines.events.on_player_mined_entity, function (event)
+        local entity = event.entity
+        local name = entity.name
+
+        if name == 'sand-rock-big' or name == 'rock-huge' then
+            event.buffer.remove({name = 'coal', count = 100})
+
+            -- this logic can be replaced once we've fully replaced the stone to surface functionality
+            if enable_digging_warning then
+                local player = Game.get_player_by_index(event.player_index)
+                if player and player.valid then
+                    if player.get_main_inventory().can_insert({name = 'stone'}) then
+                        reset_player_full_inventory_cache(player)
+                    else
+                        trigger_inventory_warning(player)
+                    end
+                end
+            end
+        end
+
+        diggy_hole(entity)
+    end)
+
+    Event.add(defines.events.on_robot_mined_tile, function (event)
+        on_mined_tile(event.robot.surface, event.tiles)
+    end)
+
+    Event.add(defines.events.on_player_mined_tile, function (event)
+        on_mined_tile(game.surfaces[event.surface_index], event.tiles)
+    end)
+
+    Event.add(Template.events.on_void_removed, function ()
+        ScoreTable.increment('Void removed')
+    end)
+
+    if config.enable_debug_commands then
+        commands.add_command('clear-void', '<left top x> <left top y> <width> <height> <surface index> triggers Template.insert for the given area.', function(cmd)
+            local params = {}
+            local args = cmd.parameter or ''
+            for param in string.gmatch(args, '%S+') do
+                table.insert(params, param)
+            end
+
+            if (#params ~= 5) then
+                game.player.print('/clear-void requires exactly 5 arguments: <left top x> <left top y> <width> <height> <surface index>')
+                return
+            end
+
+            local left_top_x = tonumber(params[1])
+            local left_top_y = tonumber(params[2])
+            local width = tonumber(params[3])
+            local height = tonumber(params[4])
+            local surface_index = params[5]
+            local tiles = {}
+            local entities = {}
+
+            for x = 0, width do
+                for y = 0, height do
+                    insert(tiles, {name = 'dirt-' .. random(1, 7), position = {x = x + left_top_x, y = y + left_top_y}})
+                end
+            end
+
+            Template.insert(game.surfaces[surface_index], tiles, entities)
+        end
+        )
+    end
+end
+
+function DiggyHole.on_init()
+    game.forces.player.technologies['landfill'].enabled = false
+end
+
+return DiggyHole
diff --git a/map_gen/Diggy/Feature/MarketExchange.lua b/map_gen/Diggy/Feature/MarketExchange.lua
index 9d6b0a92..3d23506a 100644
--- a/map_gen/Diggy/Feature/MarketExchange.lua
+++ b/map_gen/Diggy/Feature/MarketExchange.lua
@@ -1,649 +1,649 @@
---[[-- info
-    Provides the ability to purchase items from the market.
-]]
-
--- dependencies
-local Event = require 'utils.event'
-local Token = require 'utils.global_token'
-local Task = require 'utils.Task'
-local Gui = require 'utils.gui'
-local Debug = require 'map_gen.Diggy.Debug'
-local Template = require 'map_gen.Diggy.Template'
-local Global = require 'utils.global'
-local Game = require 'utils.game'
-local MarketUnlockables = require 'map_gen.Diggy.MarketUnlockables'
-local calculate_level = MarketUnlockables.calculate_level
-local insert = table.insert
-local max = math.max
-local utils = require 'utils.utils'
-local prefix = '## - '
-
--- this
-local MarketExchange = {}
-
-local config = {}
-
-local stone_tracker = {
-    stone_sent_to_surface = 0,
-    previous_stone_sent_to_surface = 0,
-    current_level = 0,
-}
-
-local stone_collecting = {
-    initial_value = 0,
-    active_modifier = 0,
-    research_modifier = 0,
-    market_modifier = 0,
-}
-
-local mining_efficiency = {
-    active_modifier = 0,
-    research_modifier = 0,
-    market_modifier = 0,
-}
-
-local inventory_slots = {
-    active_modifier = 0,
-    research_modifier = 0,
-    market_modifier = 0,
-}
-
-Global.register({
-    stone_collecting = stone_collecting,
-    stone_tracker = stone_tracker,
-    mining_efficiency = mining_efficiency,
-    inventory_slots = inventory_slots,
-}, function(tbl)
-    stone_collecting = tbl.stone_collecting
-    stone_tracker = tbl.stone_tracker
-    mining_efficiency = tbl.mining_efficiency
-    inventory_slots = tbl.inventory_slots
-end)
-
-local function send_stone_to_surface(total)
-    stone_tracker.previous_stone_sent_to_surface = stone_tracker.stone_sent_to_surface
-    stone_tracker.stone_sent_to_surface = stone_tracker.stone_sent_to_surface + total
-end
-
-local on_market_timeout_finished = Token.register(function(params)
-    Template.market(params.surface, params.position, params.player_force, {})
-
-    local tiles = {}
-    for _, position in pairs(params.void_chest_tiles) do
-        insert(tiles, {name = 'tutorial-grid', position = position})
-    end
-
-    params.surface.set_tiles(tiles)
-end)
-
-local function update_mining_speed(force)
-    -- remove the current buff
-    local old_modifier = force.manual_mining_speed_modifier - mining_efficiency.active_modifier
-
-    -- update the active modifier
-    mining_efficiency.active_modifier = mining_efficiency.research_modifier + mining_efficiency.market_modifier
-
-    -- add the new active modifier to the non-buffed modifier
-    force.manual_mining_speed_modifier = old_modifier + mining_efficiency.active_modifier
-end
-
-local function update_inventory_slots(force)
-    -- remove the current buff
-    local old_modifier = force.character_inventory_slots_bonus - inventory_slots.active_modifier
-
-    -- update the active modifier
-    inventory_slots.active_modifier = inventory_slots.research_modifier + inventory_slots.market_modifier
-
-    -- add the new active modifier to the non-buffed modifier
-    force.character_inventory_slots_bonus = old_modifier + inventory_slots.active_modifier
-end
-
-local function update_stone_collecting()
-    -- remove the current buff
-    local old_modifier = stone_collecting.initial_value - stone_collecting.active_modifier
-
-    -- update the active modifier
-    stone_collecting.active_modifier = stone_collecting.research_modifier + stone_collecting.market_modifier
-
-    -- add the new active modifier to the non-buffed modifier
-    stone_collecting.initial_value = old_modifier + stone_collecting.active_modifier
-end
-
-
---Handles the updating of market items when unlocked, also handles the buffs
-local function update_market_contents(market)
-    if (stone_tracker.previous_stone_sent_to_surface == stone_tracker.stone_sent_to_surface) then
-        return
-    end
-
-    local should_update_mining_speed = false
-    local should_update_inventory_slots = false
-    local should_update_stone_collecting = false
-    local add_market_item
-    local old_level = stone_tracker.current_level
-    local print = game.print
-    local item_unlocked = false
-            
-    if (calculate_level(stone_tracker.current_level+1) <= stone_tracker.stone_sent_to_surface) then
-        stone_tracker.current_level = stone_tracker.current_level + 1
-    end
-            
-    for _, unlockable in pairs(config.unlockables) do
-        local stone_unlock = calculate_level(unlockable.level)
-        local is_in_range = stone_unlock > stone_tracker.previous_stone_sent_to_surface and stone_unlock <= stone_tracker.stone_sent_to_surface
-
-        -- only add the item to the market if it's between the old and new stone range
-        if (is_in_range and unlockable.type == 'market') then
-            add_market_item = add_market_item or market.add_market_item
-
-            local name = unlockable.prototype.name
-            local price = unlockable.prototype.price
-            if type(price) == 'number' then
-                add_market_item({
-                    price = {{config.currency_item, price}},
-                    offer = {type = 'give-item', item = name, count = 1}
-                })
-            elseif type(price) == 'table' then
-                add_market_item({
-                    price = price,
-                    offer = {type = 'give-item', item = name, count = 1}
-                })
-            end
-            item_unlocked = true
-
-        end
-    end
-
-    MarketExchange.update_gui()
-
-    if (old_level < stone_tracker.current_level) then
-        if item_unlocked then
-            print(prefix..'We have reached level ' .. stone_tracker.current_level .. '! New items are available from the market!')
-        else
-            print(prefix..'We have reached level ' .. stone_tracker.current_level .. '!')
-        end
-        for _, buffs in pairs(config.buffs) do
-            if (buffs.prototype.name == 'mining_speed') then
-                local value = buffs.prototype.value
-                Debug.print('Mining Foreman: Increased mining speed by ' .. value .. '%!')
-                should_update_mining_speed = true
-                mining_efficiency.market_modifier = mining_efficiency.market_modifier + (value / 100)
-            elseif (buffs.prototype.name == 'inventory_slot') then
-                local value = buffs.prototype.value
-                Debug.print('Mining Foreman: Increased inventory slots by ' .. value .. '!')
-                should_update_inventory_slots = true
-                inventory_slots.market_modifier = inventory_slots.market_modifier + value
-            elseif (buffs.prototype.name == 'stone_automation') then
-                local value = buffs.prototype.value
-                if (stone_tracker.current_level == 1) then
-                    print('Mining Foreman: We can now automatically send stone to the surface from a chest below the market!')
-                else
-                    Debug.print('Mining Foreman: We can now automatically send ' .. value .. ' more stones!')
-                end
-                should_update_stone_collecting = true
-                stone_collecting.market_modifier = stone_collecting.market_modifier + value
-            end
-        end
-    end
-    
-    local force
-
-    if (should_update_mining_speed) then
-        force = force or game.forces.player
-        update_mining_speed(force)
-    end
-
-    if (should_update_inventory_slots) then
-        force = force or game.forces.player
-        update_inventory_slots(force)
-    end
-
-    if (should_update_stone_collecting) then
-        update_stone_collecting()
-    end
-end
-
-local function on_research_finished(event)
-    local force = game.forces.player
-    local current_modifier = mining_efficiency.research_modifier
-    local new_modifier = force.mining_drill_productivity_bonus * config.mining_speed_productivity_multiplier * 0.5
-
-    if (current_modifier == new_modifier) then
-        -- something else was researched
-        return
-    end
-
-    mining_efficiency.research_modifier = new_modifier
-    inventory_slots.research_modifier = force.mining_drill_productivity_bonus * 50 -- 1 per level
-    stone_collecting.research_modifier = force.mining_drill_productivity_bonus * 1250 -- 25 per level
-
-    update_inventory_slots(force)
-    update_mining_speed(force)
-    update_stone_collecting()
-end
-
-local function redraw_title(data)
-    data.frame.caption = utils.comma_value(stone_tracker.stone_sent_to_surface) .. ' ' .. config.currency_item .. ' sent to the surface'
-end
-
-local function get_data(unlocks, stone, type)
-    local result = {}
-
-    for _, data in pairs(unlocks) do
-        if calculate_level(data.level) == stone and data.type == type then
-            insert(result, data)
-        end
-    end
-
-    return result
-end
-
-local tag_label_stone = Gui.uid_name()
-local tag_label_buff = Gui.uid_name()
-local tag_label_item = Gui.uid_name()
-
-local function apply_heading_style(style, width)
-    style.font = 'default-bold'
-    style.width = width
-end
-
-local function redraw_heading(data, header)
-    local head_condition = (header == 1)
-    local frame = (head_condition) and data.market_list_heading or data.buff_list_heading
-    local header_caption = (head_condition) and 'Reward Item' or 'Reward Buff'
-    Gui.clear(frame)
-
-    local heading_table = frame.add({type = 'table', column_count = 2})
-    apply_heading_style(heading_table.add({type = 'label', name = tag_label_stone, caption = 'Requirement'}).style, 100)
-    apply_heading_style(heading_table.add({type = 'label', name = tag_label_buff, caption = header_caption}).style, 220)
-end
-
-local function redraw_progressbar(data)
-
-    local flow = data.market_progressbars
-    Gui.clear(flow)
-
-    -- progress bar for next level
-    local act_stone = (stone_tracker.current_level ~= 0) and calculate_level(stone_tracker.current_level) or 0
-    local next_stone = calculate_level(stone_tracker.current_level+1)
-
-    local range = next_stone - act_stone
-    local sent = stone_tracker.stone_sent_to_surface - act_stone
-    local percentage = (math.floor((sent / range)*1000))*0.001
-    percentage = (percentage < 0) and (percentage*-1) or percentage
-
-    apply_heading_style(flow.add({type = 'label', tooltip = 'Currently at level: ' .. stone_tracker.current_level .. '\nNext level at: ' .. utils.comma_value(next_stone) ..'\nRemaining stone: ' .. utils.comma_value(range - sent), name = 'Diggy.MarketExchange.Frame.Progress.Level', caption = 'Progress to next level:'}).style)
-    local level_progressbar = flow.add({type = 'progressbar', tooltip = percentage * 100 .. '% stone to next level'})
-    level_progressbar.style.width = 350
-    level_progressbar.value = percentage
-end
-
-local function redraw_table(data)
-    local market_scroll_pane = data.market_scroll_pane
-    Gui.clear(market_scroll_pane)
-
-    local buffs = {}
-    local items = {}
-    local last_stone = 0
-    local number_of_rows = 0
-    local row = {}
-
-    -- create the progress bars in the window
-    redraw_progressbar(data)
-
-    -- create table headings
-    redraw_heading(data, 1)
-
-    -- create table
-    for i = 1, #config.unlockables do
-        if calculate_level(config.unlockables[i].level) ~= last_stone then
-
-            -- get items and buffs for each stone value
-            items = get_data(config.unlockables, calculate_level(config.unlockables[i].level), 'market')
-
-            -- get number of rows
-            number_of_rows = max(#buffs, #items)
-
-            -- loop through buffs and items for number of rows
-            for j = 1, number_of_rows do
-                local result = {}
-                local item = items[j]
-                local level = item.level
-
-                -- 1st column
-                result[6] = calculate_level(level)
-                result[1] = 'Level ' ..level
-                -- 3rd column
-                if items[j] ~= nil then
-                    result[3] = '+ ' .. item.prototype.name
-                else
-                    result[3] = ''
-                end
-                -- indicator to stop print stone number
-                if j > 1 then
-                    result[4] = true
-                else
-                    result[4] = false
-                end
-                -- indicator to draw horizontal line
-                if j == number_of_rows then
-                    result[5] = true
-                else
-                    result[5] = false
-                end
-
-                insert(row, result)
-            end
-        end
-
-        -- save lastStone
-        last_stone = calculate_level(config.unlockables[i].level)
-    end
-
-    -- print table
-    for _, unlockable in pairs(row) do
-        local is_unlocked = unlockable[6] <= stone_tracker.stone_sent_to_surface
-        local list = market_scroll_pane.add {type = 'table', column_count = 2 }
-
-        list.style.horizontal_spacing = 16
-
-        local caption = ''
-        if unlockable[4] ~= true then
-            caption = unlockable[1]
-        else
-            caption = ''
-        end
-        local tag_stone = list.add {type = 'label', name = tag_label_stone, caption = caption}
-        tag_stone.style.minimal_width = 100
-
-        local tag_items = list.add {type = 'label', name = tag_label_item, caption = unlockable[3]}
-        tag_items.style.minimal_width = 220
-
-        -- draw horizontal line
-        if unlockable[5] == true then
-            list.draw_horizontal_line_after_headers = true
-        end
-
-        if (is_unlocked) then
-            tag_stone.style.font_color = {r = 1, g = 1, b = 1 }
-            tag_items.style.font_color = {r = 1, g = 1, b = 1 }
-        else
-            tag_stone.style.font_color = {r = 0.5, g = 0.5, b = 0.5 }
-            tag_items.style.font_color = {r = 0.5, g = 0.5, b = 0.5 }
-        end
-    end
-end
-
-local function redraw_buff(data) --! Almost equals to the redraw_table() function !
-    local buff_scroll_pane = data.buff_scroll_pane
-    Gui.clear(buff_scroll_pane)
-
-    local buffs = {}
-    local number_of_rows = 0
-    local row = {}
-    
-    for i = 1, #config.buffs do
-        -- get items and buffs for each stone value
-        buffs = config.buffs
-        
-        local result = {}
-
-        -- 1st column
-        result[1] = 'All levels'
-
-        -- 2nd column
-        if buffs[i].prototype.name == 'mining_speed' then
-            result[2] = '+ '.. buffs[i].prototype.value .. '% mining speed'
-        elseif buffs[i].prototype.name == 'inventory_slot' then
-            if buffs[i].prototype.value > 1 then
-                result[2] = '+ '.. buffs[i].prototype.value .. ' inventory slots'
-            else
-                result[2] = '+ '.. buffs[i].prototype.value .. ' inventory slot'
-            end
-        elseif buffs[i].prototype.name == 'stone_automation' then
-            result[2] = '+ '.. buffs[i].prototype.value .. ' stones automatically sent'
-        else
-            result[2] = 'Description missing: unknown buff. Please contact admin'
-        end
-        
-        -- 3rd column
-        result[3] = ''
-        -- indicator to stop print level number
-        if i > 1 then
-            result[4] = true
-        else
-            result[4] = false
-        end
-        insert(row, result)
-    end    
-    for _, unlockable in pairs(row) do
-        local list = buff_scroll_pane.add {type = 'table', column_count = 2 }
-        list.style.horizontal_spacing = 16
-
-        local caption = ''
-        if unlockable[4] ~= true then
-            caption = unlockable[1]
-        else
-            caption = ''
-        end
-        local tag_stone = list.add {type = 'label', name = buff_tag_label_stone, caption = caption}
-        tag_stone.style.minimal_width = 100
-
-        local tag_buffs = list.add {type = 'label', name = buff_tag_label_buff, caption = unlockable[2]}
-        tag_buffs.style.minimal_width = 220
-
-        tag_stone.style.font_color = {r = 1, g = 1, b = 1 }
-        tag_buffs.style.font_color = {r = 1, g = 1, b = 1 }
-    end
-end
-
-local function on_market_item_purchased(event)
-    if (1 ~= event.offer_index) then
-        return
-    end
-
-    local sum = config.stone_to_surface_amount * event.count
-    Game.print_player_floating_text(event.player_index, '-' .. sum .. ' stone', {r = 0.6, g = 0.55, b = 0.42})
-
-    send_stone_to_surface(sum)
-    update_market_contents(event.market)
-end
-
-local function on_placed_entity(event)
-    local market = event.entity
-    if ('market' ~= market.name) then
-        return
-    end
-
-    market.add_market_item({
-        price = {{config.currency_item, 50}},
-        offer = {type = 'nothing', effect_description = 'Send ' .. config.stone_to_surface_amount .. ' ' .. config.currency_item .. ' to the surface. To see the overall progress and rewards, click the market button in the menu.'}
-    })
-
-    update_market_contents(market)
-end
-
-function MarketExchange.get_extra_map_info(config)
-    return 'Market Exchange, trade your stone or send it to the surface'
-end
-
-local function toggle(event)
-    local player = event.player
-    local left = player.gui.left
-    local frame = left['Diggy.MarketExchange.Frame']
-
-    if (frame and event.trigger == nil) then
-        Gui.destroy(frame)
-        return
-    elseif (frame) then
-        local data = Gui.get_data(frame)
-        redraw_title(data)
-        redraw_progressbar(data)
-        redraw_table(data)
-        return
-    end
-
-    frame = left.add({name = 'Diggy.MarketExchange.Frame', type = 'frame', direction = 'vertical'})
-
-    local market_progressbars = frame.add({type = 'flow', direction = 'vertical'})
-    local market_list_heading = frame.add({type = 'flow', direction = 'horizontal'})
-
-    local market_scroll_pane = frame.add({type = 'scroll-pane'})
-    market_scroll_pane.style.maximal_height = 300
-    
-    local buff_list_heading = frame.add({type = 'flow', direction = 'horizontal'})
-    
-    local buff_scroll_pane = frame.add({type = 'scroll-pane'})
-    buff_scroll_pane.style.maximal_height = 100
-
-    frame.add({ type = 'button', name = 'Diggy.MarketExchange.Button', caption = 'Close'})
-
-    local data = {
-        frame = frame,
-        market_progressbars = market_progressbars,
-        market_list_heading = market_list_heading,
-        market_scroll_pane = market_scroll_pane,
-        buff_list_heading = buff_list_heading,
-        buff_scroll_pane = buff_scroll_pane,
-    }
-
-    redraw_title(data)
-    redraw_table(data)
-    
-    redraw_heading(data, 2)
-    redraw_buff(data)
-
-    Gui.set_data(frame, data)
-
-end
-
-local function on_player_created(event)
-    Game.get_player_by_index(event.player_index).gui.top.add({
-        name = 'Diggy.MarketExchange.Button',
-        type = 'sprite-button',
-        sprite = 'entity/market',
-    })
-end
-
-Gui.on_click('Diggy.MarketExchange.Button', toggle)
-Gui.on_custom_close('Diggy.MarketExchange.Frame', function (event)
-    event.element.destroy()
-end)
-
-function MarketExchange.update_gui()
-    for _, p in ipairs(game.connected_players) do
-        local frame = p.gui.left['Diggy.MarketExchange.Frame']
-
-        if frame and frame.valid then
-            local data = {player = p, trigger = 'update_gui'}
-            toggle(data)
-            --toggle(data)
-        end
-    end
-end
-
-function MarketExchange.on_init()
-    Task.set_timeout_in_ticks(50, on_market_timeout_finished, {
-        surface = game.surfaces.nauvis,
-        position = config.market_spawn_position,
-        player_force = game.forces.player,
-        void_chest_tiles = config.void_chest_tiles,
-    })
-
-    update_mining_speed(game.forces.player)
-end
-
---[[--
-    Registers all event handlers.
-]]
-function MarketExchange.register(cfg)
-    config = cfg
-
-    Event.add(defines.events.on_research_finished, on_research_finished)
-    Event.add(defines.events.on_market_item_purchased, on_market_item_purchased)
-    Event.add(Template.events.on_placed_entity, on_placed_entity)
-    Event.add(defines.events.on_player_created, on_player_created)
-
-    local x_min
-    local y_min
-    local x_max
-    local y_max
-
-    for _, position in pairs(config.void_chest_tiles) do
-        local x = position.x
-        local y = position.y
-
-        if (nil == x_min or x < x_min) then
-            x_min = x
-        end
-
-        if (nil == x_max or x > x_max) then
-            x_max = x
-        end
-
-        if (nil == y_min or y < y_min) then
-            y_min = y
-        end
-
-        if (nil == y_max or y > y_max) then
-            y_max = y
-        end
-    end
-
-    local area = {{x_min, y_min}, {x_max + 1, y_max + 1}}
-    local message_x = (x_max + x_min) * 0.5
-    local message_y = (y_max + y_min) * 0.5
-
-    Event.on_nth_tick(config.void_chest_frequency, function ()
-        local send_to_surface = 0
-        local surface = game.surfaces.nauvis
-        local find_entities_filtered = surface.find_entities_filtered
-        local chests = find_entities_filtered({area = area, type = {'container', 'logistic-container'}})
-        local to_fetch = stone_collecting.active_modifier
-
-        for _, chest in pairs(chests) do
-            local chest_contents = chest.get_inventory(defines.inventory.chest)
-            local stone_in_chest = chest_contents.get_item_count(config.currency_item)
-            local delta = to_fetch
-
-            if (stone_in_chest < delta) then
-                delta = stone_in_chest
-            end
-
-            if (delta > 0) then
-                chest_contents.remove({name = config.currency_item, count = delta})
-                send_to_surface = send_to_surface + delta
-            end
-        end
-
-        if (send_to_surface == 0) then
-            if (0 == to_fetch) then
-                return
-            end
-
-            local message = 'Missing chests below market'
-            if (#chests > 0) then
-                message = 'No stone in chests found'
-            end
-
-            Game.print_floating_text(surface, {x = message_x, y = message_y}, message, { r = 220, g = 100, b = 50})
-            return
-        end
-
-        local markets = find_entities_filtered({name = 'market', position = config.market_spawn_position, limit = 1})
-
-        if (#markets == 0) then
-            Debug.print_position(config.market_spawn_position, 'Unable to find a market')
-            return
-        end
-
-        local message = send_to_surface .. ' stone sent to the surface'
-
-        Game.print_floating_text(surface, {x = message_x, y = message_y}, message, { r = 0.6, g = 0.55, b = 0.42})
-
-        send_stone_to_surface(send_to_surface)
-        update_market_contents(markets[1])
-    end)
-end
-
-return MarketExchange
+--[[-- info
+    Provides the ability to purchase items from the market.
+]]
+
+-- dependencies
+local Event = require 'utils.event'
+local Token = require 'utils.global_token'
+local Task = require 'utils.Task'
+local Gui = require 'utils.gui'
+local Debug = require 'map_gen.Diggy.Debug'
+local Template = require 'map_gen.Diggy.Template'
+local Global = require 'utils.global'
+local Game = require 'utils.game'
+local MarketUnlockables = require 'map_gen.Diggy.MarketUnlockables'
+local calculate_level = MarketUnlockables.calculate_level
+local insert = table.insert
+local max = math.max
+local utils = require 'utils.utils'
+local prefix = '## - '
+
+-- this
+local MarketExchange = {}
+
+local config = {}
+
+local stone_tracker = {
+    stone_sent_to_surface = 0,
+    previous_stone_sent_to_surface = 0,
+    current_level = 0,
+}
+
+local stone_collecting = {
+    initial_value = 0,
+    active_modifier = 0,
+    research_modifier = 0,
+    market_modifier = 0,
+}
+
+local mining_efficiency = {
+    active_modifier = 0,
+    research_modifier = 0,
+    market_modifier = 0,
+}
+
+local inventory_slots = {
+    active_modifier = 0,
+    research_modifier = 0,
+    market_modifier = 0,
+}
+
+Global.register({
+    stone_collecting = stone_collecting,
+    stone_tracker = stone_tracker,
+    mining_efficiency = mining_efficiency,
+    inventory_slots = inventory_slots,
+}, function(tbl)
+    stone_collecting = tbl.stone_collecting
+    stone_tracker = tbl.stone_tracker
+    mining_efficiency = tbl.mining_efficiency
+    inventory_slots = tbl.inventory_slots
+end)
+
+local function send_stone_to_surface(total)
+    stone_tracker.previous_stone_sent_to_surface = stone_tracker.stone_sent_to_surface
+    stone_tracker.stone_sent_to_surface = stone_tracker.stone_sent_to_surface + total
+end
+
+local on_market_timeout_finished = Token.register(function(params)
+    Template.market(params.surface, params.position, params.player_force, {})
+
+    local tiles = {}
+    for _, position in pairs(params.void_chest_tiles) do
+        insert(tiles, {name = 'tutorial-grid', position = position})
+    end
+
+    params.surface.set_tiles(tiles)
+end)
+
+local function update_mining_speed(force)
+    -- remove the current buff
+    local old_modifier = force.manual_mining_speed_modifier - mining_efficiency.active_modifier
+
+    -- update the active modifier
+    mining_efficiency.active_modifier = mining_efficiency.research_modifier + mining_efficiency.market_modifier
+
+    -- add the new active modifier to the non-buffed modifier
+    force.manual_mining_speed_modifier = old_modifier + mining_efficiency.active_modifier
+end
+
+local function update_inventory_slots(force)
+    -- remove the current buff
+    local old_modifier = force.character_inventory_slots_bonus - inventory_slots.active_modifier
+
+    -- update the active modifier
+    inventory_slots.active_modifier = inventory_slots.research_modifier + inventory_slots.market_modifier
+
+    -- add the new active modifier to the non-buffed modifier
+    force.character_inventory_slots_bonus = old_modifier + inventory_slots.active_modifier
+end
+
+local function update_stone_collecting()
+    -- remove the current buff
+    local old_modifier = stone_collecting.initial_value - stone_collecting.active_modifier
+
+    -- update the active modifier
+    stone_collecting.active_modifier = stone_collecting.research_modifier + stone_collecting.market_modifier
+
+    -- add the new active modifier to the non-buffed modifier
+    stone_collecting.initial_value = old_modifier + stone_collecting.active_modifier
+end
+
+
+--Handles the updating of market items when unlocked, also handles the buffs
+local function update_market_contents(market)
+    if (stone_tracker.previous_stone_sent_to_surface == stone_tracker.stone_sent_to_surface) then
+        return
+    end
+
+    local should_update_mining_speed = false
+    local should_update_inventory_slots = false
+    local should_update_stone_collecting = false
+    local add_market_item
+    local old_level = stone_tracker.current_level
+    local print = game.print
+    local item_unlocked = false
+            
+    if (calculate_level(stone_tracker.current_level+1) <= stone_tracker.stone_sent_to_surface) then
+        stone_tracker.current_level = stone_tracker.current_level + 1
+    end
+            
+    for _, unlockable in pairs(config.unlockables) do
+        local stone_unlock = calculate_level(unlockable.level)
+        local is_in_range = stone_unlock > stone_tracker.previous_stone_sent_to_surface and stone_unlock <= stone_tracker.stone_sent_to_surface
+
+        -- only add the item to the market if it's between the old and new stone range
+        if (is_in_range and unlockable.type == 'market') then
+            add_market_item = add_market_item or market.add_market_item
+
+            local name = unlockable.prototype.name
+            local price = unlockable.prototype.price
+            if type(price) == 'number' then
+                add_market_item({
+                    price = {{config.currency_item, price}},
+                    offer = {type = 'give-item', item = name, count = 1}
+                })
+            elseif type(price) == 'table' then
+                add_market_item({
+                    price = price,
+                    offer = {type = 'give-item', item = name, count = 1}
+                })
+            end
+            item_unlocked = true
+
+        end
+    end
+
+    MarketExchange.update_gui()
+
+    if (old_level < stone_tracker.current_level) then
+        if item_unlocked then
+            print(prefix..'We have reached level ' .. stone_tracker.current_level .. '! New items are available from the market!')
+        else
+            print(prefix..'We have reached level ' .. stone_tracker.current_level .. '!')
+        end
+        for _, buffs in pairs(config.buffs) do
+            if (buffs.prototype.name == 'mining_speed') then
+                local value = buffs.prototype.value
+                Debug.print('Mining Foreman: Increased mining speed by ' .. value .. '%!')
+                should_update_mining_speed = true
+                mining_efficiency.market_modifier = mining_efficiency.market_modifier + (value / 100)
+            elseif (buffs.prototype.name == 'inventory_slot') then
+                local value = buffs.prototype.value
+                Debug.print('Mining Foreman: Increased inventory slots by ' .. value .. '!')
+                should_update_inventory_slots = true
+                inventory_slots.market_modifier = inventory_slots.market_modifier + value
+            elseif (buffs.prototype.name == 'stone_automation') then
+                local value = buffs.prototype.value
+                if (stone_tracker.current_level == 1) then
+                    print('Mining Foreman: We can now automatically send stone to the surface from a chest below the market!')
+                else
+                    Debug.print('Mining Foreman: We can now automatically send ' .. value .. ' more stones!')
+                end
+                should_update_stone_collecting = true
+                stone_collecting.market_modifier = stone_collecting.market_modifier + value
+            end
+        end
+    end
+    
+    local force
+
+    if (should_update_mining_speed) then
+        force = force or game.forces.player
+        update_mining_speed(force)
+    end
+
+    if (should_update_inventory_slots) then
+        force = force or game.forces.player
+        update_inventory_slots(force)
+    end
+
+    if (should_update_stone_collecting) then
+        update_stone_collecting()
+    end
+end
+
+local function on_research_finished(event)
+    local force = game.forces.player
+    local current_modifier = mining_efficiency.research_modifier
+    local new_modifier = force.mining_drill_productivity_bonus * config.mining_speed_productivity_multiplier * 0.5
+
+    if (current_modifier == new_modifier) then
+        -- something else was researched
+        return
+    end
+
+    mining_efficiency.research_modifier = new_modifier
+    inventory_slots.research_modifier = force.mining_drill_productivity_bonus * 50 -- 1 per level
+    stone_collecting.research_modifier = force.mining_drill_productivity_bonus * 1250 -- 25 per level
+
+    update_inventory_slots(force)
+    update_mining_speed(force)
+    update_stone_collecting()
+end
+
+local function redraw_title(data)
+    data.frame.caption = utils.comma_value(stone_tracker.stone_sent_to_surface) .. ' ' .. config.currency_item .. ' sent to the surface'
+end
+
+local function get_data(unlocks, stone, type)
+    local result = {}
+
+    for _, data in pairs(unlocks) do
+        if calculate_level(data.level) == stone and data.type == type then
+            insert(result, data)
+        end
+    end
+
+    return result
+end
+
+local tag_label_stone = Gui.uid_name()
+local tag_label_buff = Gui.uid_name()
+local tag_label_item = Gui.uid_name()
+
+local function apply_heading_style(style, width)
+    style.font = 'default-bold'
+    style.width = width
+end
+
+local function redraw_heading(data, header)
+    local head_condition = (header == 1)
+    local frame = (head_condition) and data.market_list_heading or data.buff_list_heading
+    local header_caption = (head_condition) and 'Reward Item' or 'Reward Buff'
+    Gui.clear(frame)
+
+    local heading_table = frame.add({type = 'table', column_count = 2})
+    apply_heading_style(heading_table.add({type = 'label', name = tag_label_stone, caption = 'Requirement'}).style, 100)
+    apply_heading_style(heading_table.add({type = 'label', name = tag_label_buff, caption = header_caption}).style, 220)
+end
+
+local function redraw_progressbar(data)
+
+    local flow = data.market_progressbars
+    Gui.clear(flow)
+
+    -- progress bar for next level
+    local act_stone = (stone_tracker.current_level ~= 0) and calculate_level(stone_tracker.current_level) or 0
+    local next_stone = calculate_level(stone_tracker.current_level+1)
+
+    local range = next_stone - act_stone
+    local sent = stone_tracker.stone_sent_to_surface - act_stone
+    local percentage = (math.floor((sent / range)*1000))*0.001
+    percentage = (percentage < 0) and (percentage*-1) or percentage
+
+    apply_heading_style(flow.add({type = 'label', tooltip = 'Currently at level: ' .. stone_tracker.current_level .. '\nNext level at: ' .. utils.comma_value(next_stone) ..'\nRemaining stone: ' .. utils.comma_value(range - sent), name = 'Diggy.MarketExchange.Frame.Progress.Level', caption = 'Progress to next level:'}).style)
+    local level_progressbar = flow.add({type = 'progressbar', tooltip = percentage * 100 .. '% stone to next level'})
+    level_progressbar.style.width = 350
+    level_progressbar.value = percentage
+end
+
+local function redraw_table(data)
+    local market_scroll_pane = data.market_scroll_pane
+    Gui.clear(market_scroll_pane)
+
+    local buffs = {}
+    local items = {}
+    local last_stone = 0
+    local number_of_rows = 0
+    local row = {}
+
+    -- create the progress bars in the window
+    redraw_progressbar(data)
+
+    -- create table headings
+    redraw_heading(data, 1)
+
+    -- create table
+    for i = 1, #config.unlockables do
+        if calculate_level(config.unlockables[i].level) ~= last_stone then
+
+            -- get items and buffs for each stone value
+            items = get_data(config.unlockables, calculate_level(config.unlockables[i].level), 'market')
+
+            -- get number of rows
+            number_of_rows = max(#buffs, #items)
+
+            -- loop through buffs and items for number of rows
+            for j = 1, number_of_rows do
+                local result = {}
+                local item = items[j]
+                local level = item.level
+
+                -- 1st column
+                result[6] = calculate_level(level)
+                result[1] = 'Level ' ..level
+                -- 3rd column
+                if items[j] ~= nil then
+                    result[3] = '+ ' .. item.prototype.name
+                else
+                    result[3] = ''
+                end
+                -- indicator to stop print stone number
+                if j > 1 then
+                    result[4] = true
+                else
+                    result[4] = false
+                end
+                -- indicator to draw horizontal line
+                if j == number_of_rows then
+                    result[5] = true
+                else
+                    result[5] = false
+                end
+
+                insert(row, result)
+            end
+        end
+
+        -- save lastStone
+        last_stone = calculate_level(config.unlockables[i].level)
+    end
+
+    -- print table
+    for _, unlockable in pairs(row) do
+        local is_unlocked = unlockable[6] <= stone_tracker.stone_sent_to_surface
+        local list = market_scroll_pane.add {type = 'table', column_count = 2 }
+
+        list.style.horizontal_spacing = 16
+
+        local caption = ''
+        if unlockable[4] ~= true then
+            caption = unlockable[1]
+        else
+            caption = ''
+        end
+        local tag_stone = list.add {type = 'label', name = tag_label_stone, caption = caption}
+        tag_stone.style.minimal_width = 100
+
+        local tag_items = list.add {type = 'label', name = tag_label_item, caption = unlockable[3]}
+        tag_items.style.minimal_width = 220
+
+        -- draw horizontal line
+        if unlockable[5] == true then
+            list.draw_horizontal_line_after_headers = true
+        end
+
+        if (is_unlocked) then
+            tag_stone.style.font_color = {r = 1, g = 1, b = 1 }
+            tag_items.style.font_color = {r = 1, g = 1, b = 1 }
+        else
+            tag_stone.style.font_color = {r = 0.5, g = 0.5, b = 0.5 }
+            tag_items.style.font_color = {r = 0.5, g = 0.5, b = 0.5 }
+        end
+    end
+end
+
+local function redraw_buff(data) --! Almost equals to the redraw_table() function !
+    local buff_scroll_pane = data.buff_scroll_pane
+    Gui.clear(buff_scroll_pane)
+
+    local buffs = {}
+    local number_of_rows = 0
+    local row = {}
+    
+    for i = 1, #config.buffs do
+        -- get items and buffs for each stone value
+        buffs = config.buffs
+        
+        local result = {}
+
+        -- 1st column
+        result[1] = 'All levels'
+
+        -- 2nd column
+        if buffs[i].prototype.name == 'mining_speed' then
+            result[2] = '+ '.. buffs[i].prototype.value .. '% mining speed'
+        elseif buffs[i].prototype.name == 'inventory_slot' then
+            if buffs[i].prototype.value > 1 then
+                result[2] = '+ '.. buffs[i].prototype.value .. ' inventory slots'
+            else
+                result[2] = '+ '.. buffs[i].prototype.value .. ' inventory slot'
+            end
+        elseif buffs[i].prototype.name == 'stone_automation' then
+            result[2] = '+ '.. buffs[i].prototype.value .. ' stones automatically sent'
+        else
+            result[2] = 'Description missing: unknown buff. Please contact admin'
+        end
+        
+        -- 3rd column
+        result[3] = ''
+        -- indicator to stop print level number
+        if i > 1 then
+            result[4] = true
+        else
+            result[4] = false
+        end
+        insert(row, result)
+    end    
+    for _, unlockable in pairs(row) do
+        local list = buff_scroll_pane.add {type = 'table', column_count = 2 }
+        list.style.horizontal_spacing = 16
+
+        local caption = ''
+        if unlockable[4] ~= true then
+            caption = unlockable[1]
+        else
+            caption = ''
+        end
+        local tag_stone = list.add {type = 'label', name = buff_tag_label_stone, caption = caption}
+        tag_stone.style.minimal_width = 100
+
+        local tag_buffs = list.add {type = 'label', name = buff_tag_label_buff, caption = unlockable[2]}
+        tag_buffs.style.minimal_width = 220
+
+        tag_stone.style.font_color = {r = 1, g = 1, b = 1 }
+        tag_buffs.style.font_color = {r = 1, g = 1, b = 1 }
+    end
+end
+
+local function on_market_item_purchased(event)
+    if (1 ~= event.offer_index) then
+        return
+    end
+
+    local sum = config.stone_to_surface_amount * event.count
+    Game.print_player_floating_text(event.player_index, '-' .. sum .. ' stone', {r = 0.6, g = 0.55, b = 0.42})
+
+    send_stone_to_surface(sum)
+    update_market_contents(event.market)
+end
+
+local function on_placed_entity(event)
+    local market = event.entity
+    if ('market' ~= market.name) then
+        return
+    end
+
+    market.add_market_item({
+        price = {{config.currency_item, 50}},
+        offer = {type = 'nothing', effect_description = 'Send ' .. config.stone_to_surface_amount .. ' ' .. config.currency_item .. ' to the surface. To see the overall progress and rewards, click the market button in the menu.'}
+    })
+
+    update_market_contents(market)
+end
+
+function MarketExchange.get_extra_map_info(config)
+    return 'Market Exchange, trade your stone or send it to the surface'
+end
+
+local function toggle(event)
+    local player = event.player
+    local left = player.gui.left
+    local frame = left['Diggy.MarketExchange.Frame']
+
+    if (frame and event.trigger == nil) then
+        Gui.destroy(frame)
+        return
+    elseif (frame) then
+        local data = Gui.get_data(frame)
+        redraw_title(data)
+        redraw_progressbar(data)
+        redraw_table(data)
+        return
+    end
+
+    frame = left.add({name = 'Diggy.MarketExchange.Frame', type = 'frame', direction = 'vertical'})
+
+    local market_progressbars = frame.add({type = 'flow', direction = 'vertical'})
+    local market_list_heading = frame.add({type = 'flow', direction = 'horizontal'})
+
+    local market_scroll_pane = frame.add({type = 'scroll-pane'})
+    market_scroll_pane.style.maximal_height = 300
+    
+    local buff_list_heading = frame.add({type = 'flow', direction = 'horizontal'})
+    
+    local buff_scroll_pane = frame.add({type = 'scroll-pane'})
+    buff_scroll_pane.style.maximal_height = 100
+
+    frame.add({ type = 'button', name = 'Diggy.MarketExchange.Button', caption = 'Close'})
+
+    local data = {
+        frame = frame,
+        market_progressbars = market_progressbars,
+        market_list_heading = market_list_heading,
+        market_scroll_pane = market_scroll_pane,
+        buff_list_heading = buff_list_heading,
+        buff_scroll_pane = buff_scroll_pane,
+    }
+
+    redraw_title(data)
+    redraw_table(data)
+    
+    redraw_heading(data, 2)
+    redraw_buff(data)
+
+    Gui.set_data(frame, data)
+
+end
+
+local function on_player_created(event)
+    Game.get_player_by_index(event.player_index).gui.top.add({
+        name = 'Diggy.MarketExchange.Button',
+        type = 'sprite-button',
+        sprite = 'entity/market',
+    })
+end
+
+Gui.on_click('Diggy.MarketExchange.Button', toggle)
+Gui.on_custom_close('Diggy.MarketExchange.Frame', function (event)
+    event.element.destroy()
+end)
+
+function MarketExchange.update_gui()
+    for _, p in ipairs(game.connected_players) do
+        local frame = p.gui.left['Diggy.MarketExchange.Frame']
+
+        if frame and frame.valid then
+            local data = {player = p, trigger = 'update_gui'}
+            toggle(data)
+            --toggle(data)
+        end
+    end
+end
+
+function MarketExchange.on_init()
+    Task.set_timeout_in_ticks(50, on_market_timeout_finished, {
+        surface = game.surfaces.nauvis,
+        position = config.market_spawn_position,
+        player_force = game.forces.player,
+        void_chest_tiles = config.void_chest_tiles,
+    })
+
+    update_mining_speed(game.forces.player)
+end
+
+--[[--
+    Registers all event handlers.
+]]
+function MarketExchange.register(cfg)
+    config = cfg
+
+    Event.add(defines.events.on_research_finished, on_research_finished)
+    Event.add(defines.events.on_market_item_purchased, on_market_item_purchased)
+    Event.add(Template.events.on_placed_entity, on_placed_entity)
+    Event.add(defines.events.on_player_created, on_player_created)
+
+    local x_min
+    local y_min
+    local x_max
+    local y_max
+
+    for _, position in pairs(config.void_chest_tiles) do
+        local x = position.x
+        local y = position.y
+
+        if (nil == x_min or x < x_min) then
+            x_min = x
+        end
+
+        if (nil == x_max or x > x_max) then
+            x_max = x
+        end
+
+        if (nil == y_min or y < y_min) then
+            y_min = y
+        end
+
+        if (nil == y_max or y > y_max) then
+            y_max = y
+        end
+    end
+
+    local area = {{x_min, y_min}, {x_max + 1, y_max + 1}}
+    local message_x = (x_max + x_min) * 0.5
+    local message_y = (y_max + y_min) * 0.5
+
+    Event.on_nth_tick(config.void_chest_frequency, function ()
+        local send_to_surface = 0
+        local surface = game.surfaces.nauvis
+        local find_entities_filtered = surface.find_entities_filtered
+        local chests = find_entities_filtered({area = area, type = {'container', 'logistic-container'}})
+        local to_fetch = stone_collecting.active_modifier
+
+        for _, chest in pairs(chests) do
+            local chest_contents = chest.get_inventory(defines.inventory.chest)
+            local stone_in_chest = chest_contents.get_item_count(config.currency_item)
+            local delta = to_fetch
+
+            if (stone_in_chest < delta) then
+                delta = stone_in_chest
+            end
+
+            if (delta > 0) then
+                chest_contents.remove({name = config.currency_item, count = delta})
+                send_to_surface = send_to_surface + delta
+            end
+        end
+
+        if (send_to_surface == 0) then
+            if (0 == to_fetch) then
+                return
+            end
+
+            local message = 'Missing chests below market'
+            if (#chests > 0) then
+                message = 'No stone in chests found'
+            end
+
+            Game.print_floating_text(surface, {x = message_x, y = message_y}, message, { r = 220, g = 100, b = 50})
+            return
+        end
+
+        local markets = find_entities_filtered({name = 'market', position = config.market_spawn_position, limit = 1})
+
+        if (#markets == 0) then
+            Debug.print_position(config.market_spawn_position, 'Unable to find a market')
+            return
+        end
+
+        local message = send_to_surface .. ' stone sent to the surface'
+
+        Game.print_floating_text(surface, {x = message_x, y = message_y}, message, { r = 0.6, g = 0.55, b = 0.42})
+
+        send_stone_to_surface(send_to_surface)
+        update_market_contents(markets[1])
+    end)
+end
+
+return MarketExchange
diff --git a/map_gen/Diggy/Feature/RefreshMap.lua b/map_gen/Diggy/Feature/RefreshMap.lua
index 9918b08e..51822d14 100644
--- a/map_gen/Diggy/Feature/RefreshMap.lua
+++ b/map_gen/Diggy/Feature/RefreshMap.lua
@@ -1,40 +1,40 @@
---[[-- info
-    Provides the ability to refresh the map and generate darkness.
-]]
-
--- dependencies
-local Event = require 'utils.event'
-local insert = table.insert
-
--- this
-local RefreshMap = {}
-
---[[--
-    Registers all event handlers.
-]]
-function RefreshMap.register(config)
-    Event.add(defines.events.on_chunk_generated, function (event)
-        local tiles = {}
-
-        for x = 0, 31, 1 do
-            for y = 0, 31, 1 do
-                local target_x = event.area.left_top.x + x
-                local target_y = event.area.left_top.y + y
-                local tile = 'out-of-map'
-
-                if (target_x < 1 and target_y < 1 and target_x > -2 and target_y > -2) then
-                    tile = 'lab-dark-1'
-                end
-
-                insert(tiles, {
-                    name = tile,
-                    position = {x = target_x, y = target_y}
-                })
-            end
-        end
-
-        event.surface.set_tiles(tiles)
-    end)
-end
-
-return RefreshMap
+--[[-- info
+    Provides the ability to refresh the map and generate darkness.
+]]
+
+-- dependencies
+local Event = require 'utils.event'
+local insert = table.insert
+
+-- this
+local RefreshMap = {}
+
+--[[--
+    Registers all event handlers.
+]]
+function RefreshMap.register(config)
+    Event.add(defines.events.on_chunk_generated, function (event)
+        local tiles = {}
+
+        for x = 0, 31, 1 do
+            for y = 0, 31, 1 do
+                local target_x = event.area.left_top.x + x
+                local target_y = event.area.left_top.y + y
+                local tile = 'out-of-map'
+
+                if (target_x < 1 and target_y < 1 and target_x > -2 and target_y > -2) then
+                    tile = 'lab-dark-1'
+                end
+
+                insert(tiles, {
+                    name = tile,
+                    position = {x = target_x, y = target_y}
+                })
+            end
+        end
+
+        event.surface.set_tiles(tiles)
+    end)
+end
+
+return RefreshMap
diff --git a/map_gen/Diggy/Feature/ScatteredResources.lua b/map_gen/Diggy/Feature/ScatteredResources.lua
index 4abd730e..45a1efe0 100644
--- a/map_gen/Diggy/Feature/ScatteredResources.lua
+++ b/map_gen/Diggy/Feature/ScatteredResources.lua
@@ -1,262 +1,262 @@
---[[-- info
-    Provides the ability to spawn random ores all over the place.
-]]
-
--- dependencies
-local Event = require 'utils.event'
-local Debug = require 'map_gen.Diggy.Debug'
-local Template = require 'map_gen.Diggy.Template'
-local Perlin = require 'map_gen.shared.perlin_noise'
-local Simplex = require 'map_gen.shared.simplex_noise'
-local random = math.random
-local sqrt = math.sqrt
-local ceil = math.ceil
-local floor = math.floor
-
--- this
-local ScatteredResources = {}
-
-local function get_name_by_weight(collection, sum)
-    local pre_calculated = random()
-    local current = 0
-    local target = pre_calculated * sum
-    
-    for name, weight in pairs(collection) do
-        current = current + weight
-        if (current >= target) then
-            return name
-        end
-    end
-
-    Debug.print('Current \'' .. current .. '\' should be higher or equal to random \'' .. target .. '\'')
-end
-
---[[--
-    Registers all event handlers.
-]]
-function ScatteredResources.register(config)
-
-    -- source of noise for resource generation
-    -- index determines offset
-    -- '-1' is reserved for cluster mode
-    -- compound clusters use as many indexes as needed > 1
-    local base_seed
-    local function seeded_noise(surface, x, y, index, sources)
-        base_seed = base_seed or surface.map_gen_settings.seed + surface.index + 4000
-        local noise = 0
-        for _, settings in ipairs(sources) do
-            settings.type = settings.type or 'perlin'
-            settings.offset = settings.offset or 0
-            if settings.type == 'zero' then
-                noise = noise + 0
-            elseif settings.type == 'one' then
-                noise = noise + settings.weight * 1
-            elseif settings.type == 'perlin' then
-                noise = noise + settings.weight * Perlin.noise(x/settings.variance, y/settings.variance,
-                            base_seed + 2000*index + settings.offset)
-            elseif settings.type == 'simplex' then
-                noise = noise + settings.weight * Simplex.d2(x/settings.variance, y/settings.variance,
-                            base_seed + 2000*index + settings.offset)
-            else
-                Debug.print('noise type \'' .. settings.type .. '\' not recognized')
-            end
-            
-        end
-        return noise
-    end
-    
-    -- global config values
-    
-    local resource_richness_weights = config.resource_richness_weights
-    local resource_richness_weights_sum = 0
-    for _, weight in pairs(resource_richness_weights) do
-        resource_richness_weights_sum = resource_richness_weights_sum + weight
-    end
-    local resource_richness_values = config.resource_richness_values
-    local resource_type_scalar = config.resource_type_scalar
-    
-    -- scattered config values
-    local s_mode = config.scattered_mode
-    local s_dist_mod = config.scattered_distance_probability_modifier
-    local s_min_prob = config.scattered_min_probability
-    local s_max_prob = config.scattered_max_probability
-    local s_dist_richness = config.scattered_distance_richness_modifier
-    local s_cluster_prob = config.scattered_cluster_probability_multiplier
-    local s_cluster_mult = config.scattered_cluster_yield_multiplier
-    
-    local s_resource_weights = config.scattered_resource_weights
-    local s_resource_weights_sum = 0
-    for _, weight in pairs(s_resource_weights) do
-        s_resource_weights_sum = s_resource_weights_sum + weight
-    end
-    local s_min_dist = config.scattered_minimum_resource_distance
-
-    -- cluster config values
-    local cluster_mode = config.cluster_mode
-    
-    -- compound cluster spawning
-    local c_mode = config.cluster_mode
-    local c_clusters = require(config.cluster_file_location)
-    if ('table' ~= type(c_clusters)) then
-        error('cluster_file_location invalid')
-    end
-    local c_count = 0
-    for _, cluster in ipairs(c_clusters) do
-        c_count = c_count + 1
-        cluster.weights_sum = 0
-        -- ensure the cluster colors are valid otherwise it fails silently
-        -- and breaks things elsewhere
-        if cluster.color then
-            local c = cluster.color
-            if (not c.r) or (not c.g) or (not c.b) then
-                cluster.color = nil
-            elseif c.r < 0 or c.r > 1 or c.g < 0 or c.g > 1 or c.b < 0 or c.b > 1 then
-                cluster.color = nil
-            end
-        end
-        for _, weight in pairs(cluster.weights) do
-            cluster.weights_sum = cluster.weights_sum + weight
-        end
-    end
-    
-    local function spawn_cluster_resource(surface, x, y, cluster_index, cluster)
-        local distance = sqrt(x * x + y * y)
-        local resource_name = get_name_by_weight(cluster.weights, cluster.weights_sum)
-        if resource_name == 'skip' then
-            return false
-        end
-        if cluster.distances[resource_name] then
-            if distance < cluster.distances[resource_name] then
-                return false
-            end
-        end
-    
-        local range = resource_richness_values[get_name_by_weight(resource_richness_weights, resource_richness_weights_sum)]
-        local amount = random(range[1], range[2])
-        amount = amount * (1 + ((distance / cluster.distance_richness) * 0.01))
-        amount = amount * cluster.yield
-        
-        if resource_type_scalar[resource_name] then 
-            amount = amount * resource_type_scalar[resource_name]
-        end
-
-        Template.resources(surface, {{name = resource_name, position = {x = x, y = y}, amount = ceil(amount)}})
-        return true
-    end
-    
-    -- event registration
-    Event.add(Template.events.on_void_removed, function (event)
-        local position = event.position
-        local x = position.x
-        local y = position.y
-        local surface = event.surface
-
-        local distance = config.distance(x, y)
-        
-        if c_mode then
-            for index,cluster in ipairs(c_clusters) do
-                if distance >= cluster.min_distance and cluster.noise_settings.type ~= 'skip' then
-                    if cluster.noise_settings.type == "connected_tendril" then
-                        local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
-                        if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
-                            if spawn_cluster_resource(surface, x, y, index, cluster) then
-                                return -- resource spawned
-                            end
-                        end
-                    elseif cluster.noise_settings.type == "fragmented_tendril" then
-                        local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
-                        local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
-                        if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold 
-                                and -1 * cluster.noise_settings.discriminator_threshold < noise2
-                                and noise2 < cluster.noise_settings.discriminator_threshold then
-                            if spawn_cluster_resource(surface, x, y, index, cluster) then
-                                return -- resource spawned
-                            end
-                        end
-                    else
-                        local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
-                        if noise >= cluster.noise_settings.threshold then
-                            if spawn_cluster_resource(surface, x, y, index, cluster) then
-                                return -- resource spawned
-                            end
-                        end
-                    end
-                end
-            end
-        end
-        
-        if s_mode then
-            local probability = math.min(s_max_prob, s_min_prob + 0.01 * (distance / s_dist_mod))
-
-            if (cluster_mode) then
-                probability = probability * s_cluster_prob
-            end
-
-            if (probability > random()) then
-                -- spawn single resource point for scatter mode
-                local resource_name = get_name_by_weight(s_resource_weights, s_resource_weights_sum)            
-                if resource_name == 'skip' or s_min_dist[resource_name] > distance then
-                    return
-                end
-
-                local range = resource_richness_values[get_name_by_weight(resource_richness_weights, resource_richness_weights_sum)]
-                local amount = random(range[1], range[2])
-                amount = amount * (1 + ((distance / s_dist_richness) * 0.01))
-
-                if resource_type_scalar[resource_name] then
-                    amount = amount * resource_type_scalar[resource_name]
-                end
-
-                if (cluster_mode) then
-                    amount = amount * s_cluster_mult
-                end
-                
-                Template.resources(surface, {{name = resource_name, position={x=x,y=y}, amount = ceil(amount)}})
-            end
-        end
-    end)
-    
-    if (config.display_ore_clusters) then
-        local color = {}
-        Event.add(defines.events.on_chunk_generated, function (event)
-            local surface = event.surface
-            local area = event.area
-
-            for x = area.left_top.x, area.left_top.x + 31 do
-                for y = area.left_top.y, area.left_top.y + 31 do
-                    for index,cluster in ipairs(c_clusters) do
-                        if cluster.noise_settings.type == "connected_tendril" then
-                            local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
-                            if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
-                                color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
-                                Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
-                            end
-                        elseif cluster.noise_settings.type == "fragmented_tendril" then
-                            local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
-                            local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
-                            if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold 
-                                    and -1 * cluster.noise_settings.discriminator_threshold < noise2
-                                    and noise2 < cluster.noise_settings.discriminator_threshold then
-                                color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
-                                Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
-                            end
-                        elseif cluster.noise_settings.type ~= 'skip' then
-                            local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
-                            if noise >= cluster.noise_settings.threshold then
-                                color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
-                                Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
-                            end
-                        end
-                    end
-                end
-            end
-        end)
-    end
-end
-
-function ScatteredResources.get_extra_map_info(config)
-    return [[Scattered Resources, resources are everywhere!
-Scans of the mine have shown greater amounts of resources to be deeper in the mine]]
-end
-
-return ScatteredResources
+--[[-- info
+    Provides the ability to spawn random ores all over the place.
+]]
+
+-- dependencies
+local Event = require 'utils.event'
+local Debug = require 'map_gen.Diggy.Debug'
+local Template = require 'map_gen.Diggy.Template'
+local Perlin = require 'map_gen.shared.perlin_noise'
+local Simplex = require 'map_gen.shared.simplex_noise'
+local random = math.random
+local sqrt = math.sqrt
+local ceil = math.ceil
+local floor = math.floor
+
+-- this
+local ScatteredResources = {}
+
+local function get_name_by_weight(collection, sum)
+    local pre_calculated = random()
+    local current = 0
+    local target = pre_calculated * sum
+    
+    for name, weight in pairs(collection) do
+        current = current + weight
+        if (current >= target) then
+            return name
+        end
+    end
+
+    Debug.print('Current \'' .. current .. '\' should be higher or equal to random \'' .. target .. '\'')
+end
+
+--[[--
+    Registers all event handlers.
+]]
+function ScatteredResources.register(config)
+
+    -- source of noise for resource generation
+    -- index determines offset
+    -- '-1' is reserved for cluster mode
+    -- compound clusters use as many indexes as needed > 1
+    local base_seed
+    local function seeded_noise(surface, x, y, index, sources)
+        base_seed = base_seed or surface.map_gen_settings.seed + surface.index + 4000
+        local noise = 0
+        for _, settings in ipairs(sources) do
+            settings.type = settings.type or 'perlin'
+            settings.offset = settings.offset or 0
+            if settings.type == 'zero' then
+                noise = noise + 0
+            elseif settings.type == 'one' then
+                noise = noise + settings.weight * 1
+            elseif settings.type == 'perlin' then
+                noise = noise + settings.weight * Perlin.noise(x/settings.variance, y/settings.variance,
+                            base_seed + 2000*index + settings.offset)
+            elseif settings.type == 'simplex' then
+                noise = noise + settings.weight * Simplex.d2(x/settings.variance, y/settings.variance,
+                            base_seed + 2000*index + settings.offset)
+            else
+                Debug.print('noise type \'' .. settings.type .. '\' not recognized')
+            end
+            
+        end
+        return noise
+    end
+    
+    -- global config values
+    
+    local resource_richness_weights = config.resource_richness_weights
+    local resource_richness_weights_sum = 0
+    for _, weight in pairs(resource_richness_weights) do
+        resource_richness_weights_sum = resource_richness_weights_sum + weight
+    end
+    local resource_richness_values = config.resource_richness_values
+    local resource_type_scalar = config.resource_type_scalar
+    
+    -- scattered config values
+    local s_mode = config.scattered_mode
+    local s_dist_mod = config.scattered_distance_probability_modifier
+    local s_min_prob = config.scattered_min_probability
+    local s_max_prob = config.scattered_max_probability
+    local s_dist_richness = config.scattered_distance_richness_modifier
+    local s_cluster_prob = config.scattered_cluster_probability_multiplier
+    local s_cluster_mult = config.scattered_cluster_yield_multiplier
+    
+    local s_resource_weights = config.scattered_resource_weights
+    local s_resource_weights_sum = 0
+    for _, weight in pairs(s_resource_weights) do
+        s_resource_weights_sum = s_resource_weights_sum + weight
+    end
+    local s_min_dist = config.scattered_minimum_resource_distance
+
+    -- cluster config values
+    local cluster_mode = config.cluster_mode
+    
+    -- compound cluster spawning
+    local c_mode = config.cluster_mode
+    local c_clusters = require(config.cluster_file_location)
+    if ('table' ~= type(c_clusters)) then
+        error('cluster_file_location invalid')
+    end
+    local c_count = 0
+    for _, cluster in ipairs(c_clusters) do
+        c_count = c_count + 1
+        cluster.weights_sum = 0
+        -- ensure the cluster colors are valid otherwise it fails silently
+        -- and breaks things elsewhere
+        if cluster.color then
+            local c = cluster.color
+            if (not c.r) or (not c.g) or (not c.b) then
+                cluster.color = nil
+            elseif c.r < 0 or c.r > 1 or c.g < 0 or c.g > 1 or c.b < 0 or c.b > 1 then
+                cluster.color = nil
+            end
+        end
+        for _, weight in pairs(cluster.weights) do
+            cluster.weights_sum = cluster.weights_sum + weight
+        end
+    end
+    
+    local function spawn_cluster_resource(surface, x, y, cluster_index, cluster)
+        local distance = sqrt(x * x + y * y)
+        local resource_name = get_name_by_weight(cluster.weights, cluster.weights_sum)
+        if resource_name == 'skip' then
+            return false
+        end
+        if cluster.distances[resource_name] then
+            if distance < cluster.distances[resource_name] then
+                return false
+            end
+        end
+    
+        local range = resource_richness_values[get_name_by_weight(resource_richness_weights, resource_richness_weights_sum)]
+        local amount = random(range[1], range[2])
+        amount = amount * (1 + ((distance / cluster.distance_richness) * 0.01))
+        amount = amount * cluster.yield
+        
+        if resource_type_scalar[resource_name] then 
+            amount = amount * resource_type_scalar[resource_name]
+        end
+
+        Template.resources(surface, {{name = resource_name, position = {x = x, y = y}, amount = ceil(amount)}})
+        return true
+    end
+    
+    -- event registration
+    Event.add(Template.events.on_void_removed, function (event)
+        local position = event.position
+        local x = position.x
+        local y = position.y
+        local surface = event.surface
+
+        local distance = config.distance(x, y)
+        
+        if c_mode then
+            for index,cluster in ipairs(c_clusters) do
+                if distance >= cluster.min_distance and cluster.noise_settings.type ~= 'skip' then
+                    if cluster.noise_settings.type == "connected_tendril" then
+                        local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
+                        if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
+                            if spawn_cluster_resource(surface, x, y, index, cluster) then
+                                return -- resource spawned
+                            end
+                        end
+                    elseif cluster.noise_settings.type == "fragmented_tendril" then
+                        local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
+                        local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
+                        if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold 
+                                and -1 * cluster.noise_settings.discriminator_threshold < noise2
+                                and noise2 < cluster.noise_settings.discriminator_threshold then
+                            if spawn_cluster_resource(surface, x, y, index, cluster) then
+                                return -- resource spawned
+                            end
+                        end
+                    else
+                        local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
+                        if noise >= cluster.noise_settings.threshold then
+                            if spawn_cluster_resource(surface, x, y, index, cluster) then
+                                return -- resource spawned
+                            end
+                        end
+                    end
+                end
+            end
+        end
+        
+        if s_mode then
+            local probability = math.min(s_max_prob, s_min_prob + 0.01 * (distance / s_dist_mod))
+
+            if (cluster_mode) then
+                probability = probability * s_cluster_prob
+            end
+
+            if (probability > random()) then
+                -- spawn single resource point for scatter mode
+                local resource_name = get_name_by_weight(s_resource_weights, s_resource_weights_sum)            
+                if resource_name == 'skip' or s_min_dist[resource_name] > distance then
+                    return
+                end
+
+                local range = resource_richness_values[get_name_by_weight(resource_richness_weights, resource_richness_weights_sum)]
+                local amount = random(range[1], range[2])
+                amount = amount * (1 + ((distance / s_dist_richness) * 0.01))
+
+                if resource_type_scalar[resource_name] then
+                    amount = amount * resource_type_scalar[resource_name]
+                end
+
+                if (cluster_mode) then
+                    amount = amount * s_cluster_mult
+                end
+                
+                Template.resources(surface, {{name = resource_name, position={x=x,y=y}, amount = ceil(amount)}})
+            end
+        end
+    end)
+    
+    if (config.display_ore_clusters) then
+        local color = {}
+        Event.add(defines.events.on_chunk_generated, function (event)
+            local surface = event.surface
+            local area = event.area
+
+            for x = area.left_top.x, area.left_top.x + 31 do
+                for y = area.left_top.y, area.left_top.y + 31 do
+                    for index,cluster in ipairs(c_clusters) do
+                        if cluster.noise_settings.type == "connected_tendril" then
+                            local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
+                            if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
+                                color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
+                                Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
+                            end
+                        elseif cluster.noise_settings.type == "fragmented_tendril" then
+                            local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
+                            local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
+                            if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold 
+                                    and -1 * cluster.noise_settings.discriminator_threshold < noise2
+                                    and noise2 < cluster.noise_settings.discriminator_threshold then
+                                color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
+                                Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
+                            end
+                        elseif cluster.noise_settings.type ~= 'skip' then
+                            local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
+                            if noise >= cluster.noise_settings.threshold then
+                                color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
+                                Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
+                            end
+                        end
+                    end
+                end
+            end
+        end)
+    end
+end
+
+function ScatteredResources.get_extra_map_info(config)
+    return [[Scattered Resources, resources are everywhere!
+Scans of the mine have shown greater amounts of resources to be deeper in the mine]]
+end
+
+return ScatteredResources
diff --git a/map_gen/Diggy/Feature/SetupPlayer.lua b/map_gen/Diggy/Feature/SetupPlayer.lua
index 71415810..4ec36b98 100644
--- a/map_gen/Diggy/Feature/SetupPlayer.lua
+++ b/map_gen/Diggy/Feature/SetupPlayer.lua
@@ -1,53 +1,53 @@
---[[-- info
-    Provides the ability to setup a player when first joined.
-]]
-
--- dependencies
-local Event = require 'utils.event'
-local Debug = require 'map_gen.Diggy.Debug'
-local Game = require 'utils.game'
-
--- this
-local SetupPlayer = {}
-
-global.SetupPlayer = {
-    first_player_spawned = false,
-}
-
---[[--
-    Registers all event handlers.
-]]
-function SetupPlayer.register(config)
-    Event.add(defines.events.on_player_created, function (event)
-        local player = Game.get_player_by_index(event.player_index)
-        local player_insert = player.insert
-        local position = {0, 0}
-        local surface = player.surface
-
-        for _, item in pairs(config.starting_items) do
-            player_insert(item)
-        end
-
-        if (global.SetupPlayer.first_player_spawned) then
-            position = surface.find_non_colliding_position('player', position, 3, 0.1)
-        else
-            global.SetupPlayer.first_player_spawned = true
-        end
-
-        player.force.set_spawn_position(position, surface)
-        player.teleport(position)
-
-        Debug.cheat(function()
-            local cheats = config.cheats
-            player.force.manual_mining_speed_modifier = cheats.manual_mining_speed_modifier
-            player.force.character_inventory_slots_bonus = cheats.character_inventory_slots_bonus
-            player.force.character_running_speed_modifier = cheats.character_running_speed_modifier
-
-            for _, item in pairs(cheats.starting_items) do
-                player_insert(item)
-            end
-        end)
-    end)
-end
-
-return SetupPlayer
+--[[-- info
+    Provides the ability to setup a player when first joined.
+]]
+
+-- dependencies
+local Event = require 'utils.event'
+local Debug = require 'map_gen.Diggy.Debug'
+local Game = require 'utils.game'
+
+-- this
+local SetupPlayer = {}
+
+global.SetupPlayer = {
+    first_player_spawned = false,
+}
+
+--[[--
+    Registers all event handlers.
+]]
+function SetupPlayer.register(config)
+    Event.add(defines.events.on_player_created, function (event)
+        local player = Game.get_player_by_index(event.player_index)
+        local player_insert = player.insert
+        local position = {0, 0}
+        local surface = player.surface
+
+        for _, item in pairs(config.starting_items) do
+            player_insert(item)
+        end
+
+        if (global.SetupPlayer.first_player_spawned) then
+            position = surface.find_non_colliding_position('player', position, 3, 0.1)
+        else
+            global.SetupPlayer.first_player_spawned = true
+        end
+
+        player.force.set_spawn_position(position, surface)
+        player.teleport(position)
+
+        Debug.cheat(function()
+            local cheats = config.cheats
+            player.force.manual_mining_speed_modifier = cheats.manual_mining_speed_modifier
+            player.force.character_inventory_slots_bonus = cheats.character_inventory_slots_bonus
+            player.force.character_running_speed_modifier = cheats.character_running_speed_modifier
+
+            for _, item in pairs(cheats.starting_items) do
+                player_insert(item)
+            end
+        end)
+    end)
+end
+
+return SetupPlayer
diff --git a/map_gen/Diggy/Feature/SimpleRoomGenerator.lua b/map_gen/Diggy/Feature/SimpleRoomGenerator.lua
index 3d555856..a6431ac8 100644
--- a/map_gen/Diggy/Feature/SimpleRoomGenerator.lua
+++ b/map_gen/Diggy/Feature/SimpleRoomGenerator.lua
@@ -1,108 +1,108 @@
---[[-- info
-    Provides the ability to make a simple room with contents
-]]
-
--- dependencies
-local Template = require 'map_gen.Diggy.Template'
-local Perlin = require 'map_gen.shared.perlin_noise'
-local Event = require 'utils.event'
-local Debug = require'map_gen.Diggy.Debug'
-local Task = require 'utils.Task'
-local Token = require 'utils.global_token'
-local raise_event = script.raise_event
-
--- this
-local SimpleRoomGenerator = {}
-
-local do_spawn_tile = Token.register(function(params)
-    Template.insert(params.surface, {params.tile}, {})
-end)
-
-local do_mine = Token.register(function(params)
-    local surface = params.surface
-    local position = params.position
-    local rocks = surface.find_entities_filtered({ position = position, name = { 'sand-rock-big', 'rock-huge'}})
-
-    if (0 == #rocks) then
-        return
-    end
-
-    for _, rock in pairs(rocks) do
-        raise_event(defines.events.on_entity_died, {entity = rock})
-        rock.destroy()
-    end
-end)
-
-local function handle_noise(name, surface, position)
-    Task.set_timeout_in_ticks(1, do_mine, {surface = surface, position = position})
-
-    if ('water' == name) then
-        -- water is slower because for some odd reason it doesn't always want to mine it properly
-        Task.set_timeout_in_ticks(4, do_spawn_tile, { surface = surface, tile = { name = 'deepwater-green', position = position}})
-        return
-    end
-
-    if ('dirt' == name) then
-        return
-    end
-
-    error('No noise handled for type \'' .. name .. '\'')
-end
-
---[[--
-    Registers all event handlers.
-]]
-function SimpleRoomGenerator.register(config)
-    local room_noise_minimum_distance_sq = config.room_noise_minimum_distance * config.room_noise_minimum_distance
-
-    local seed
-    local function get_noise(surface, x, y)
-        seed = seed or surface.map_gen_settings.seed + surface.index + 100
-        return Perlin.noise(x * config.noise_variance, y * config.noise_variance, seed)
-    end
-
-    Event.add(Template.events.on_void_removed, function (event)
-        local position = event.position
-        local x = position.x
-        local y = position.y
-
-        local distance_sq = x * x + y * y
-
-        if (distance_sq <= room_noise_minimum_distance_sq) then
-            return
-        end
-
-        local surface = event.surface
-        local noise = get_noise(surface, x, y)
-
-        for _, noise_range in pairs(config.room_noise_ranges) do
-            if (noise >= noise_range.min and noise <= noise_range.max) then
-                handle_noise(noise_range.name, surface, position)
-            end
-        end
-    end)
-
-    if (config.display_room_locations) then
-        Event.add(defines.events.on_chunk_generated, function (event)
-            local surface = event.surface
-            local area = event.area
-
-            for x = area.left_top.x, area.left_top.x + 31 do
-                for y = area.left_top.y, area.left_top.y + 31 do
-                    for _, noise_range in pairs(config.room_noise_ranges) do
-                        local noise = get_noise(surface, x, y)
-                        if (noise >= noise_range.min and noise <= noise_range.max) then
-                            Debug.print_grid_value(noise_range.name, surface, {x = x, y = y}, nil, nil, true)
-                        end
-                    end
-                end
-            end
-        end)
-    end
-end
-
-function SimpleRoomGenerator.get_extra_map_info(config)
-    return 'Simple Room Generator, digging around might open rooms!'
-end
-
-return SimpleRoomGenerator
+--[[-- info
+    Provides the ability to make a simple room with contents
+]]
+
+-- dependencies
+local Template = require 'map_gen.Diggy.Template'
+local Perlin = require 'map_gen.shared.perlin_noise'
+local Event = require 'utils.event'
+local Debug = require'map_gen.Diggy.Debug'
+local Task = require 'utils.Task'
+local Token = require 'utils.global_token'
+local raise_event = script.raise_event
+
+-- this
+local SimpleRoomGenerator = {}
+
+local do_spawn_tile = Token.register(function(params)
+    Template.insert(params.surface, {params.tile}, {})
+end)
+
+local do_mine = Token.register(function(params)
+    local surface = params.surface
+    local position = params.position
+    local rocks = surface.find_entities_filtered({ position = position, name = { 'sand-rock-big', 'rock-huge'}})
+
+    if (0 == #rocks) then
+        return
+    end
+
+    for _, rock in pairs(rocks) do
+        raise_event(defines.events.on_entity_died, {entity = rock})
+        rock.destroy()
+    end
+end)
+
+local function handle_noise(name, surface, position)
+    Task.set_timeout_in_ticks(1, do_mine, {surface = surface, position = position})
+
+    if ('water' == name) then
+        -- water is slower because for some odd reason it doesn't always want to mine it properly
+        Task.set_timeout_in_ticks(4, do_spawn_tile, { surface = surface, tile = { name = 'deepwater-green', position = position}})
+        return
+    end
+
+    if ('dirt' == name) then
+        return
+    end
+
+    error('No noise handled for type \'' .. name .. '\'')
+end
+
+--[[--
+    Registers all event handlers.
+]]
+function SimpleRoomGenerator.register(config)
+    local room_noise_minimum_distance_sq = config.room_noise_minimum_distance * config.room_noise_minimum_distance
+
+    local seed
+    local function get_noise(surface, x, y)
+        seed = seed or surface.map_gen_settings.seed + surface.index + 100
+        return Perlin.noise(x * config.noise_variance, y * config.noise_variance, seed)
+    end
+
+    Event.add(Template.events.on_void_removed, function (event)
+        local position = event.position
+        local x = position.x
+        local y = position.y
+
+        local distance_sq = x * x + y * y
+
+        if (distance_sq <= room_noise_minimum_distance_sq) then
+            return
+        end
+
+        local surface = event.surface
+        local noise = get_noise(surface, x, y)
+
+        for _, noise_range in pairs(config.room_noise_ranges) do
+            if (noise >= noise_range.min and noise <= noise_range.max) then
+                handle_noise(noise_range.name, surface, position)
+            end
+        end
+    end)
+
+    if (config.display_room_locations) then
+        Event.add(defines.events.on_chunk_generated, function (event)
+            local surface = event.surface
+            local area = event.area
+
+            for x = area.left_top.x, area.left_top.x + 31 do
+                for y = area.left_top.y, area.left_top.y + 31 do
+                    for _, noise_range in pairs(config.room_noise_ranges) do
+                        local noise = get_noise(surface, x, y)
+                        if (noise >= noise_range.min and noise <= noise_range.max) then
+                            Debug.print_grid_value(noise_range.name, surface, {x = x, y = y}, nil, nil, true)
+                        end
+                    end
+                end
+            end
+        end)
+    end
+end
+
+function SimpleRoomGenerator.get_extra_map_info(config)
+    return 'Simple Room Generator, digging around might open rooms!'
+end
+
+return SimpleRoomGenerator
diff --git a/map_gen/Diggy/Feature/StartingZone.lua b/map_gen/Diggy/Feature/StartingZone.lua
index e70dc7e1..fb982260 100644
--- a/map_gen/Diggy/Feature/StartingZone.lua
+++ b/map_gen/Diggy/Feature/StartingZone.lua
@@ -1,81 +1,81 @@
---[[-- info
-    Provides the ability to create a pre-configured starting zone.
-]]
--- dependencies
-local Event = require 'utils.event'
-local Token = require 'utils.global_token'
-local Template = require 'map_gen.Diggy.Template'
-local Debug = require 'map_gen.Diggy.Debug'
-local DiggyCaveCollapse = require 'map_gen.Diggy.Feature.DiggyCaveCollapse'
-local insert = table.insert
-local random = math.random
-local sqrt = math.sqrt
-local floor = math.floor
-
--- this
-local StartingZone = {}
-
---[[--
-    Registers all event handlers.
-]]
-function StartingZone.register(config)
-    local callback_token
-    local starting_zone_size = config.starting_size
-
-    local function on_chunk_generated(event)
-        local start_point_area = {{-0.9, -0.9}, {0.9, 0.9}}
-        local start_point_cleanup = {{-0.9, -0.9}, {1.9, 1.9}}
-        local surface = event.surface
-
-        -- hack to figure out whether the important chunks are generated via Diggy.Feature.RefreshMap.
-        if (4 ~= surface.count_tiles_filtered({start_point_area, name = 'lab-dark-1'})) then
-            return
-        end
-
-        -- ensure a clean starting point
-        for _, entity in pairs(surface.find_entities_filtered({area = start_point_cleanup, type = 'resource'})) do
-            entity.destroy()
-        end
-
-        local tiles = {}
-        local rocks = {}
-
-        local dirt_range = floor(starting_zone_size * 0.5)
-        local rock_range = starting_zone_size - 2
-        local stress_hack = floor(starting_zone_size * 0.1)
-
-        for x = -starting_zone_size, starting_zone_size do
-            for y = -starting_zone_size, starting_zone_size do
-                local distance = floor(sqrt(x * x + y * y))
-
-                if (distance < starting_zone_size) then
-                    if (distance > dirt_range) then
-                        insert(tiles, {name = 'dirt-' .. random(1, 7), position = {x = x, y = y}})
-                    else
-                        insert(tiles, {name = 'stone-path', position = {x = x, y = y}})
-                    end
-
-                    if (distance > rock_range) then
-                        insert(rocks, {name = 'sand-rock-big', position = {x = x, y = y}})
-                    end
-
-                    -- hack to avoid starting area from collapsing
-                    if (distance > stress_hack) then
-                        DiggyCaveCollapse.stress_map_add(surface, {x = x, y = y}, -0.5)
-                    end
-                end
-            end
-        end
-
-        Template.insert(event.surface, tiles, rocks)
-
-        Event.remove_removable(defines.events.on_chunk_generated, callback_token)
-    end
-
-    callback_token = Token.register(on_chunk_generated)
-
-    Event.add_removable(defines.events.on_chunk_generated, callback_token)
-end
-
-
-return StartingZone
+--[[-- info
+    Provides the ability to create a pre-configured starting zone.
+]]
+-- dependencies
+local Event = require 'utils.event'
+local Token = require 'utils.global_token'
+local Template = require 'map_gen.Diggy.Template'
+local Debug = require 'map_gen.Diggy.Debug'
+local DiggyCaveCollapse = require 'map_gen.Diggy.Feature.DiggyCaveCollapse'
+local insert = table.insert
+local random = math.random
+local sqrt = math.sqrt
+local floor = math.floor
+
+-- this
+local StartingZone = {}
+
+--[[--
+    Registers all event handlers.
+]]
+function StartingZone.register(config)
+    local callback_token
+    local starting_zone_size = config.starting_size
+
+    local function on_chunk_generated(event)
+        local start_point_area = {{-0.9, -0.9}, {0.9, 0.9}}
+        local start_point_cleanup = {{-0.9, -0.9}, {1.9, 1.9}}
+        local surface = event.surface
+
+        -- hack to figure out whether the important chunks are generated via Diggy.Feature.RefreshMap.
+        if (4 ~= surface.count_tiles_filtered({start_point_area, name = 'lab-dark-1'})) then
+            return
+        end
+
+        -- ensure a clean starting point
+        for _, entity in pairs(surface.find_entities_filtered({area = start_point_cleanup, type = 'resource'})) do
+            entity.destroy()
+        end
+
+        local tiles = {}
+        local rocks = {}
+
+        local dirt_range = floor(starting_zone_size * 0.5)
+        local rock_range = starting_zone_size - 2
+        local stress_hack = floor(starting_zone_size * 0.1)
+
+        for x = -starting_zone_size, starting_zone_size do
+            for y = -starting_zone_size, starting_zone_size do
+                local distance = floor(sqrt(x * x + y * y))
+
+                if (distance < starting_zone_size) then
+                    if (distance > dirt_range) then
+                        insert(tiles, {name = 'dirt-' .. random(1, 7), position = {x = x, y = y}})
+                    else
+                        insert(tiles, {name = 'stone-path', position = {x = x, y = y}})
+                    end
+
+                    if (distance > rock_range) then
+                        insert(rocks, {name = 'sand-rock-big', position = {x = x, y = y}})
+                    end
+
+                    -- hack to avoid starting area from collapsing
+                    if (distance > stress_hack) then
+                        DiggyCaveCollapse.stress_map_add(surface, {x = x, y = y}, -0.5)
+                    end
+                end
+            end
+        end
+
+        Template.insert(event.surface, tiles, rocks)
+
+        Event.remove_removable(defines.events.on_chunk_generated, callback_token)
+    end
+
+    callback_token = Token.register(on_chunk_generated)
+
+    Event.add_removable(defines.events.on_chunk_generated, callback_token)
+end
+
+
+return StartingZone
diff --git a/map_gen/Diggy/Readme.md b/map_gen/Diggy/Readme.md
index 05300b0a..f147d062 100644
--- a/map_gen/Diggy/Readme.md
+++ b/map_gen/Diggy/Readme.md
@@ -1,3 +1,3 @@
-## RedMew - Diggy, Custom Scenario
-
-The documentation for Diggy has moved to [docs/scenarios/Diggy.md](../../docs/scenarios/Diggy.md).
+## RedMew - Diggy, Custom Scenario
+
+The documentation for Diggy has moved to [docs/scenarios/Diggy.md](../../docs/scenarios/Diggy.md).
diff --git a/map_gen/Diggy/Scanner.lua b/map_gen/Diggy/Scanner.lua
index 03f8a646..40fa2a93 100644
--- a/map_gen/Diggy/Scanner.lua
+++ b/map_gen/Diggy/Scanner.lua
@@ -1,42 +1,42 @@
--- dependencies
-local insert = table.insert
-
--- this
-local Scanner = {}
-
---[[--
-    returns a list with all direct positions that contain tile_search.
-
-    @param surface LuaSurface
-    @param position Position
-    @param tile_search string name of the tile to search for
-    @return table with 0~4 directions of which have the tile searched for adjacent
-]]
-function Scanner.scan_around_position(surface, position, tile_search)
-    local tile_found = {}
-    local get_tile = surface.get_tile
-
-    -- north
-    if (tile_search == get_tile(position.x, position.y - 1).name) then
-        insert(tile_found, {x = position.x, y = position.y - 1})
-    end
-
-    -- east
-    if (tile_search == get_tile(position.x + 1, position.y).name) then
-        insert(tile_found, {x = position.x + 1, y = position.y})
-    end
-
-    -- south
-    if (tile_search == get_tile(position.x, position.y + 1).name) then
-        insert(tile_found, {x = position.x, y = position.y + 1})
-    end
-
-    -- west
-    if (tile_search == get_tile(position.x - 1, position.y).name) then
-        insert(tile_found, {x = position.x - 1, y = position.y})
-    end
-
-    return tile_found;
-end
-
-return Scanner
+-- dependencies
+local insert = table.insert
+
+-- this
+local Scanner = {}
+
+--[[--
+    returns a list with all direct positions that contain tile_search.
+
+    @param surface LuaSurface
+    @param position Position
+    @param tile_search string name of the tile to search for
+    @return table with 0~4 directions of which have the tile searched for adjacent
+]]
+function Scanner.scan_around_position(surface, position, tile_search)
+    local tile_found = {}
+    local get_tile = surface.get_tile
+
+    -- north
+    if (tile_search == get_tile(position.x, position.y - 1).name) then
+        insert(tile_found, {x = position.x, y = position.y - 1})
+    end
+
+    -- east
+    if (tile_search == get_tile(position.x + 1, position.y).name) then
+        insert(tile_found, {x = position.x + 1, y = position.y})
+    end
+
+    -- south
+    if (tile_search == get_tile(position.x, position.y + 1).name) then
+        insert(tile_found, {x = position.x, y = position.y + 1})
+    end
+
+    -- west
+    if (tile_search == get_tile(position.x - 1, position.y).name) then
+        insert(tile_found, {x = position.x - 1, y = position.y})
+    end
+
+    return tile_found;
+end
+
+return Scanner
diff --git a/map_gen/Diggy/Scenario.lua b/map_gen/Diggy/Scenario.lua
index 13411257..ea1870d0 100644
--- a/map_gen/Diggy/Scenario.lua
+++ b/map_gen/Diggy/Scenario.lua
@@ -1,96 +1,96 @@
--- dependencies
-local Config = require 'map_gen.Diggy.Config'
-local Debug = require 'map_gen.Diggy.Debug'
-local ScenarioInfo = require 'features.gui.info'
-local Event = require 'utils.event'
-
-require 'utils.list_utils'
-require 'utils.utils'
-
--- this
-local Scenario = {}
-
-global.diggy_scenario_registered = false
-
---[[--
-    Allows calling a callback for each enabled feature.
-
-    Signature: callback(feature_name, Table feature_data) from {@see Config.features}.
-
-    @param if_enabled function to be called if enabled
-]]
-local function each_enabled_feature(if_enabled)
-    local type = type(if_enabled)
-    if ('function' ~= type) then
-        error('each_enabled_feature expects callback to be a function, given type: ' .. type)
-    end
-
-    for current_name, feature_data in pairs(Config.features) do
-        if (nil == feature_data.enabled) then
-            error('Feature ' .. current_name .. ' did not define the enabled property.')
-        end
-
-        if (feature_data.enabled) then
-            if_enabled(current_name, feature_data)
-        end
-    end
-end
-
---[[--
-    Register the events required to initialize the scenario.
-]]
-function Scenario.register(debug)
-    if global.diggy_scenario_registered then
-        error('Cannot register the Diggy scenario multiple times.')
-        return
-    end
-
-    global.scenario.config.player_list.enable_coin_col = false
-    if global.scenario.config then
-        global.scenario.config.fish_market.enable = nil
-    end
-
-    if ('boolean' == type(debug)) then
-        Config.Debug = debug
-    end
-
-    if (Config.debug) then
-        Debug.enable_debug()
-    end
-
-    if (Config.cheats) then
-        Debug.enable_cheats()
-    end
-
-    local extra_map_info = ''
-
-    each_enabled_feature(
-        function(feature_name, feature_config)
-            local feature = require ('map_gen.Diggy.Feature.' .. feature_name)
-            if ('function' ~= type(feature.register)) then
-                error('Feature ' .. feature_name .. ' did not define a register function.')
-            end
-
-            feature.register(feature_config)
-
-            if ('function' == type(feature.get_extra_map_info)) then
-                extra_map_info = extra_map_info .. feature.get_extra_map_info(feature_config) .. '\n\n'
-            end
-
-            if ('function' == type(feature.on_init)) then
-                Event.on_init(feature.on_init)
-            end
-        end
-    )
-
-    local landfill_tiles = {'dirt-1','dirt-2','dirt-3','dirt-4','dirt-5','dirt-6','dirt-7'}
-    require ('map_gen.misc.change_landfill_tile')(landfill_tiles)
-
-    ScenarioInfo.set_map_name('Diggy')
-    ScenarioInfo.set_map_description('Dig your way through!')
-    ScenarioInfo.set_map_extra_info(extra_map_info)
-
-    global.diggy_scenario_registered = true
-end
-
-return Scenario
+-- dependencies
+local Config = require 'map_gen.Diggy.Config'
+local Debug = require 'map_gen.Diggy.Debug'
+local ScenarioInfo = require 'features.gui.info'
+local Event = require 'utils.event'
+
+require 'utils.list_utils'
+require 'utils.utils'
+
+-- this
+local Scenario = {}
+
+global.diggy_scenario_registered = false
+
+--[[--
+    Allows calling a callback for each enabled feature.
+
+    Signature: callback(feature_name, Table feature_data) from {@see Config.features}.
+
+    @param if_enabled function to be called if enabled
+]]
+local function each_enabled_feature(if_enabled)
+    local type = type(if_enabled)
+    if ('function' ~= type) then
+        error('each_enabled_feature expects callback to be a function, given type: ' .. type)
+    end
+
+    for current_name, feature_data in pairs(Config.features) do
+        if (nil == feature_data.enabled) then
+            error('Feature ' .. current_name .. ' did not define the enabled property.')
+        end
+
+        if (feature_data.enabled) then
+            if_enabled(current_name, feature_data)
+        end
+    end
+end
+
+--[[--
+    Register the events required to initialize the scenario.
+]]
+function Scenario.register(debug)
+    if global.diggy_scenario_registered then
+        error('Cannot register the Diggy scenario multiple times.')
+        return
+    end
+
+    global.scenario.config.player_list.enable_coin_col = false
+    if global.scenario.config then
+        global.scenario.config.fish_market.enable = nil
+    end
+
+    if ('boolean' == type(debug)) then
+        Config.Debug = debug
+    end
+
+    if (Config.debug) then
+        Debug.enable_debug()
+    end
+
+    if (Config.cheats) then
+        Debug.enable_cheats()
+    end
+
+    local extra_map_info = ''
+
+    each_enabled_feature(
+        function(feature_name, feature_config)
+            local feature = require ('map_gen.Diggy.Feature.' .. feature_name)
+            if ('function' ~= type(feature.register)) then
+                error('Feature ' .. feature_name .. ' did not define a register function.')
+            end
+
+            feature.register(feature_config)
+
+            if ('function' == type(feature.get_extra_map_info)) then
+                extra_map_info = extra_map_info .. feature.get_extra_map_info(feature_config) .. '\n\n'
+            end
+
+            if ('function' == type(feature.on_init)) then
+                Event.on_init(feature.on_init)
+            end
+        end
+    )
+
+    local landfill_tiles = {'dirt-1','dirt-2','dirt-3','dirt-4','dirt-5','dirt-6','dirt-7'}
+    require ('map_gen.misc.change_landfill_tile')(landfill_tiles)
+
+    ScenarioInfo.set_map_name('Diggy')
+    ScenarioInfo.set_map_description('Dig your way through!')
+    ScenarioInfo.set_map_extra_info(extra_map_info)
+
+    global.diggy_scenario_registered = true
+end
+
+return Scenario
diff --git a/map_gen/Diggy/ScoreTable.lua b/map_gen/Diggy/ScoreTable.lua
index 041a709d..4a24a310 100644
--- a/map_gen/Diggy/ScoreTable.lua
+++ b/map_gen/Diggy/ScoreTable.lua
@@ -1,84 +1,84 @@
--- dependencies
-local Global = require 'utils.global'
-
--- this
-local ScoreTable = {}
-
-local scores = {}
-
-Global.register({
-    scores = scores,
-}, function (tbl)
-    scores = tbl.scores
-end)
-
---[[--
-    Resets the score 0 for the given name
-
-    @param name String
-]]
-function ScoreTable.reset(name)
-    scores[name] = 0
-end
-
---[[--
-    Adds score.
-
-    @param name String
-    @param value int amount to add
-
-    @return int the sum for the score added by name
-]]
-function ScoreTable.add(name, value)
-    local new = (scores[name] or 0) + value
-    scores[name] = new
-    return new
-end
-
---[[--
-    Increments the score by 1 for name.
-
-    @param name String
-
-    @return int the sum for the score incremented by name
-]]
-function ScoreTable.increment(name)
-    return ScoreTable.add(name, 1)
-end
-
---[[--
-    Returns the score for a single key.
-
-    @param
-]]
-function ScoreTable.get(name)
-    return scores[name] or 0
-end
-
---[[--
-    Returns all scores.
-
-    @return table {[string] = int}
-]]
-function ScoreTable.all()
-    return scores
-end
-
---[[--
-    Returns all keys of table scores.
-
-    @return table {[string] = name of key}
-]]
-function ScoreTable.all_keys()
-    local keyset = {}
-    local n = 0
-
-    for k, v in pairs(scores) do
-        n = n + 1
-        keyset[n] = k
-    end
-
-    return keyset
-end
-
-return ScoreTable
+-- dependencies
+local Global = require 'utils.global'
+
+-- this
+local ScoreTable = {}
+
+local scores = {}
+
+Global.register({
+    scores = scores,
+}, function (tbl)
+    scores = tbl.scores
+end)
+
+--[[--
+    Resets the score 0 for the given name
+
+    @param name String
+]]
+function ScoreTable.reset(name)
+    scores[name] = 0
+end
+
+--[[--
+    Adds score.
+
+    @param name String
+    @param value int amount to add
+
+    @return int the sum for the score added by name
+]]
+function ScoreTable.add(name, value)
+    local new = (scores[name] or 0) + value
+    scores[name] = new
+    return new
+end
+
+--[[--
+    Increments the score by 1 for name.
+
+    @param name String
+
+    @return int the sum for the score incremented by name
+]]
+function ScoreTable.increment(name)
+    return ScoreTable.add(name, 1)
+end
+
+--[[--
+    Returns the score for a single key.
+
+    @param
+]]
+function ScoreTable.get(name)
+    return scores[name] or 0
+end
+
+--[[--
+    Returns all scores.
+
+    @return table {[string] = int}
+]]
+function ScoreTable.all()
+    return scores
+end
+
+--[[--
+    Returns all keys of table scores.
+
+    @return table {[string] = name of key}
+]]
+function ScoreTable.all_keys()
+    local keyset = {}
+    local n = 0
+
+    for k, v in pairs(scores) do
+        n = n + 1
+        keyset[n] = k
+    end
+
+    return keyset
+end
+
+return ScoreTable
diff --git a/map_gen/Diggy/Template.lua b/map_gen/Diggy/Template.lua
index 605a91e5..0f2bb488 100644
--- a/map_gen/Diggy/Template.lua
+++ b/map_gen/Diggy/Template.lua
@@ -1,216 +1,216 @@
--- dependencies
-local Task = require 'utils.Task'
-local Token = require 'utils.global_token'
-local Debug = require 'map_gen.Diggy.Debug'
-local insert = table.insert
-local min = math.min
-local ceil = math.ceil
-local raise_event = script.raise_event
-
--- this
-local Template = {}
-
-local tiles_per_call = 5 --how many tiles are inserted with each call of insert_action
-local entities_per_call = 5 --how many entities are inserted with each call of insert_action
-
-Template.events = {
-    --[[--
-        When an entity is placed via the template function.
-         - event.entity LuaEntity
-    ]]
-    on_placed_entity = script.generate_event_name(),
-
-    --[[--
-        Triggers when an 'out-of-map' tile is replaced by something else.
-
-        {surface, old_tile={name, position={x, y}}}
-    ]]
-    on_void_removed = script.generate_event_name(),
-}
-
-local function insert_next_tiles(data)
-    local void_removed = {}
-    local surface = data.surface
-    local get_tile = surface.get_tile
-    local tiles = {}
-
-    pcall(
-        function()
-            --use pcall to assure tile_iterator is always incremented, to avoid endless loops
-            for i = data.tile_iterator, min(data.tile_iterator + tiles_per_call - 1, data.tiles_n) do
-                local new_tile = data.tiles[i]
-                insert(tiles, new_tile)
-                local current_tile = get_tile(new_tile.position.x, new_tile.position.y)
-                local current_is_void = current_tile.name == 'out-of-map'
-                local new_is_void = new_tile.name == 'out-of-map'
-
-                if (current_is_void and not new_is_void) then
-                    insert(void_removed, {surface = surface, position = current_tile.position})
-                end
-            end
-        end
-    )
-
-    data.tile_iterator = data.tile_iterator + tiles_per_call
-
-    surface.set_tiles(tiles)
-
-    for _, event in pairs(void_removed) do
-        raise_event(Template.events.on_void_removed, event)
-    end
-end
-
-local function insert_next_entities(data)
-    local created_entities = {}
-    local surface = data.surface
-    local create_entity = surface.create_entity
-
-    pcall(
-        function()
-            --use pcall to assure tile_iterator is always incremented, to avoid endless loops
-            for i = data.entity_iterator, min(data.entity_iterator + entities_per_call - 1, data.entities_n) do
-                local entity = data.entities[i]
-                local created_entity = create_entity(entity)
-                if (nil == created_entity) then
-                    error('Failed creating entity ' .. entity.name .. ' on surface.')
-                end
-
-                insert(created_entities, created_entity)
-            end
-        end
-    )
-
-    data.entity_iterator = data.entity_iterator + entities_per_call
-
-    for _, entity in pairs(created_entities) do
-        raise_event(Template.events.on_placed_entity, {entity = entity})
-    end
-
-    return data.entity_iterator <= data.entities_n
-end
-
-local function insert_action(data)
-    if data.tile_iterator <= data.tiles_n then
-        insert_next_tiles(data)
-        return true
-    end
-
-    return insert_next_entities(data)
-end
-
-local insert_token = Token.register(insert_action)
-
---[[--
-    Inserts a batch of tiles and then entities.
-
-    @see LuaSurface.set_tiles
-    @see LuaSurface.entity
-
-    @param surface LuaSurface to put the tiles and entities on
-    @param tiles table of tiles as required by set_tiles
-    @param entities table of entities as required by create_entity
-]]
-function Template.insert(surface, tiles, entities)
-    tiles = tiles or {}
-    entities = entities or {}
-
-    local tiles_n = #tiles
-    local entities_n = #entities
-    local total_calls = ceil(tiles_n / tiles_per_call) + (entities_n / entities_per_call)
-    local data = {
-        tiles_n = tiles_n,
-        tile_iterator = 1,
-        entities_n = entities_n,
-        entity_iterator = 1,
-        surface = surface,
-        tiles = tiles,
-        entities = entities
-    }
-
-    local continue = true
-    for i = 1, 4 do
-        continue = insert_action(data)
-        if not continue then
-            return
-        end
-    end
-
-    if continue then
-        Task.queue_task(insert_token, data, total_calls - 4)
-    end
-end
-
---[[--
-    Designed to spawn aliens, uses find_non_colliding_position.
-
-    @see LuaSurface.entity
-
-    @param surface LuaSurface to put the tiles and entities on
-    @param units table of entities as required by create_entity
-    @param non_colliding_distance int amount of tiles to scan around original position in case it's already taken
-    @param generic_unit_name_for_spawn_size String allows setting a custom unit name for spawn size, will overwrite the actual
-]]
-function Template.units(surface, units, non_colliding_distance, generic_unit_name_for_spawn_size)
-    non_colliding_distance = non_colliding_distance or 1
-    generic_unit_name_for_spawn_size = generic_unit_name_for_spawn_size or 'player'
-
-    local create_entity = surface.create_entity
-    local position
-
-    for _, entity in pairs(units) do
-        position = position or surface.find_non_colliding_position(
-            generic_unit_name_for_spawn_size,
-            entity.position, non_colliding_distance,
-            0.5
-        )
-
-        if (nil ~= position) then
-            entity.position = position
-            create_entity(entity)
-        elseif (nil == create_entity(entity)) then
-            Debug.print_position(entity.position, "Failed to spawn '" .. entity.name .. "'")
-        end
-    end
-end
-
---[[--
-    Designed to spawn resources.
-
-    @see LuaSurface.entity
-
-    @param surface LuaSurface to put the tiles and entities on
-    @param resources table of entities as required by create_entity
-]]
-function Template.resources(surface, resources)
-    local create_entity = surface.create_entity
-    for _, entity in pairs(resources) do
-        create_entity(entity)
-    end
-end
-
---[[--
-    Designed to spawn a market.
-
-    @param surface LuaSurface
-    @param position Position
-    @param force LuaForce
-    @param market_items Table
-]]
-function Template.market(surface, position, force, market_inventory)
-    local market = surface.create_entity({name = 'market', position = position})
-    local add_market_item = market.add_market_item
-    market.destructible = false
-
-    for _, item in ipairs(market_inventory) do
-        add_market_item(item)
-    end
-
-    force.add_chart_tag(surface, {
-        text = 'Market',
-        position = position,
-    })
-
-    raise_event(Template.events.on_placed_entity, {entity = market})
-end
-
-return Template
+-- dependencies
+local Task = require 'utils.Task'
+local Token = require 'utils.global_token'
+local Debug = require 'map_gen.Diggy.Debug'
+local insert = table.insert
+local min = math.min
+local ceil = math.ceil
+local raise_event = script.raise_event
+
+-- this
+local Template = {}
+
+local tiles_per_call = 5 --how many tiles are inserted with each call of insert_action
+local entities_per_call = 5 --how many entities are inserted with each call of insert_action
+
+Template.events = {
+    --[[--
+        When an entity is placed via the template function.
+         - event.entity LuaEntity
+    ]]
+    on_placed_entity = script.generate_event_name(),
+
+    --[[--
+        Triggers when an 'out-of-map' tile is replaced by something else.
+
+        {surface, old_tile={name, position={x, y}}}
+    ]]
+    on_void_removed = script.generate_event_name(),
+}
+
+local function insert_next_tiles(data)
+    local void_removed = {}
+    local surface = data.surface
+    local get_tile = surface.get_tile
+    local tiles = {}
+
+    pcall(
+        function()
+            --use pcall to assure tile_iterator is always incremented, to avoid endless loops
+            for i = data.tile_iterator, min(data.tile_iterator + tiles_per_call - 1, data.tiles_n) do
+                local new_tile = data.tiles[i]
+                insert(tiles, new_tile)
+                local current_tile = get_tile(new_tile.position.x, new_tile.position.y)
+                local current_is_void = current_tile.name == 'out-of-map'
+                local new_is_void = new_tile.name == 'out-of-map'
+
+                if (current_is_void and not new_is_void) then
+                    insert(void_removed, {surface = surface, position = current_tile.position})
+                end
+            end
+        end
+    )
+
+    data.tile_iterator = data.tile_iterator + tiles_per_call
+
+    surface.set_tiles(tiles)
+
+    for _, event in pairs(void_removed) do
+        raise_event(Template.events.on_void_removed, event)
+    end
+end
+
+local function insert_next_entities(data)
+    local created_entities = {}
+    local surface = data.surface
+    local create_entity = surface.create_entity
+
+    pcall(
+        function()
+            --use pcall to assure tile_iterator is always incremented, to avoid endless loops
+            for i = data.entity_iterator, min(data.entity_iterator + entities_per_call - 1, data.entities_n) do
+                local entity = data.entities[i]
+                local created_entity = create_entity(entity)
+                if (nil == created_entity) then
+                    error('Failed creating entity ' .. entity.name .. ' on surface.')
+                end
+
+                insert(created_entities, created_entity)
+            end
+        end
+    )
+
+    data.entity_iterator = data.entity_iterator + entities_per_call
+
+    for _, entity in pairs(created_entities) do
+        raise_event(Template.events.on_placed_entity, {entity = entity})
+    end
+
+    return data.entity_iterator <= data.entities_n
+end
+
+local function insert_action(data)
+    if data.tile_iterator <= data.tiles_n then
+        insert_next_tiles(data)
+        return true
+    end
+
+    return insert_next_entities(data)
+end
+
+local insert_token = Token.register(insert_action)
+
+--[[--
+    Inserts a batch of tiles and then entities.
+
+    @see LuaSurface.set_tiles
+    @see LuaSurface.entity
+
+    @param surface LuaSurface to put the tiles and entities on
+    @param tiles table of tiles as required by set_tiles
+    @param entities table of entities as required by create_entity
+]]
+function Template.insert(surface, tiles, entities)
+    tiles = tiles or {}
+    entities = entities or {}
+
+    local tiles_n = #tiles
+    local entities_n = #entities
+    local total_calls = ceil(tiles_n / tiles_per_call) + (entities_n / entities_per_call)
+    local data = {
+        tiles_n = tiles_n,
+        tile_iterator = 1,
+        entities_n = entities_n,
+        entity_iterator = 1,
+        surface = surface,
+        tiles = tiles,
+        entities = entities
+    }
+
+    local continue = true
+    for i = 1, 4 do
+        continue = insert_action(data)
+        if not continue then
+            return
+        end
+    end
+
+    if continue then
+        Task.queue_task(insert_token, data, total_calls - 4)
+    end
+end
+
+--[[--
+    Designed to spawn aliens, uses find_non_colliding_position.
+
+    @see LuaSurface.entity
+
+    @param surface LuaSurface to put the tiles and entities on
+    @param units table of entities as required by create_entity
+    @param non_colliding_distance int amount of tiles to scan around original position in case it's already taken
+    @param generic_unit_name_for_spawn_size String allows setting a custom unit name for spawn size, will overwrite the actual
+]]
+function Template.units(surface, units, non_colliding_distance, generic_unit_name_for_spawn_size)
+    non_colliding_distance = non_colliding_distance or 1
+    generic_unit_name_for_spawn_size = generic_unit_name_for_spawn_size or 'player'
+
+    local create_entity = surface.create_entity
+    local position
+
+    for _, entity in pairs(units) do
+        position = position or surface.find_non_colliding_position(
+            generic_unit_name_for_spawn_size,
+            entity.position, non_colliding_distance,
+            0.5
+        )
+
+        if (nil ~= position) then
+            entity.position = position
+            create_entity(entity)
+        elseif (nil == create_entity(entity)) then
+            Debug.print_position(entity.position, "Failed to spawn '" .. entity.name .. "'")
+        end
+    end
+end
+
+--[[--
+    Designed to spawn resources.
+
+    @see LuaSurface.entity
+
+    @param surface LuaSurface to put the tiles and entities on
+    @param resources table of entities as required by create_entity
+]]
+function Template.resources(surface, resources)
+    local create_entity = surface.create_entity
+    for _, entity in pairs(resources) do
+        create_entity(entity)
+    end
+end
+
+--[[--
+    Designed to spawn a market.
+
+    @param surface LuaSurface
+    @param position Position
+    @param force LuaForce
+    @param market_items Table
+]]
+function Template.market(surface, position, force, market_inventory)
+    local market = surface.create_entity({name = 'market', position = position})
+    local add_market_item = market.add_market_item
+    market.destructible = false
+
+    for _, item in ipairs(market_inventory) do
+        add_market_item(item)
+    end
+
+    force.add_chart_tag(surface, {
+        text = 'Market',
+        position = position,
+    })
+
+    raise_event(Template.events.on_placed_entity, {entity = market})
+end
+
+return Template
diff --git a/map_gen/combined/diggy.lua b/map_gen/combined/diggy.lua
index b71f5236..7304a920 100644
--- a/map_gen/combined/diggy.lua
+++ b/map_gen/combined/diggy.lua
@@ -1,2 +1,2 @@
--- authors Linaori, valansch
-require 'map_gen.Diggy.Scenario'.register(_DEBUG)
+-- authors Linaori, valansch
+require 'map_gen.Diggy.Scenario'.register(_DEBUG)
diff --git a/map_gen/data/presets/plus.lua b/map_gen/data/presets/plus.lua
index 165a8836..e755538f 100644
--- a/map_gen/data/presets/plus.lua
+++ b/map_gen/data/presets/plus.lua
@@ -1,191 +1,191 @@
-return {
-height = 185,
-width = 337,
-data = {
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,10,1,30,2,84,1,30,2,80,1,29,2,74,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
-	{2,10,1,30,2,84,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,195,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,79,1,31,2,73,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
-	{2,11,1,28,2,85,1,30,2,79,1,31,2,73,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,124,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-	{2,11,1,28,2,85,1,30,2,183,},
-}
+return {
+height = 185,
+width = 337,
+data = {
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,10,1,30,2,84,1,30,2,80,1,29,2,74,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
+	{2,10,1,30,2,84,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,195,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,79,1,31,2,73,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
+	{2,11,1,28,2,85,1,30,2,79,1,31,2,73,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,124,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+	{2,11,1,28,2,85,1,30,2,183,},
+}
 }
\ No newline at end of file
diff --git a/map_gen/ores/neko_crazy_ores.lua b/map_gen/ores/neko_crazy_ores.lua
index c6bbbec9..a626325e 100644
--- a/map_gen/ores/neko_crazy_ores.lua
+++ b/map_gen/ores/neko_crazy_ores.lua
@@ -1,48 +1,48 @@
-local perlin = require 'map_gen.shared.perlin_noise'
-local Event = require 'utils.event'
-
-local random_ores = {'iron-ore', 'coal', 'copper-ore', 'stone', 'uranium-ore'}
-local random_dense = {1.6, 0.8, 1, 0.6, 0.5} --ore density reference
-
-local function run_ores_module_setup()
-    local seed = game.surfaces[1].map_gen_settings.seed
-    if not global.ores_seed_A then
-        global.ores_seed_A = seed
-    end
-    if not global.ores_seed_B then
-        global.ores_seed_B = seed * 2
-    end
-end
-
-Event.on_init(run_ores_module_setup)
-
-return function(x, y, world)
-    local d_sq = world.x * world.x + world.y * world.y
-    if d_sq < 9216 then
-        return
-    end
-
-    local distance_bonus = 100 + 0.4 * d ^ 1.2
-
-    local wiggle = 100 + perlin.noise((x * 0.005), (y * 0.005), global.ores_seed_A + 41) * 60
-    local Ores_A = perlin.noise((x * 0.01), (y * 0.01), global.ores_seed_B + 57) * wiggle
-
-    if Ores_A > 35 then --we place ores
-        local Ores_B = perlin.noise((x * 0.02), (y * 0.02), global.ores_seed_B + 13) * wiggle
-        local a = 5
-        --
-        if Ores_A < 76 then
-            a = math.floor(Ores_A * 0.75 + Ores_B * 0.5) % 4 + 1
-        end --if its not super high we place normal ores
-        --
-        local res_amount = distance_bonus
-        res_amount = math.floor(res_amount * random_dense[a])
-        --
-
-        return {name = random_ores[a], amount = res_amount}
-    elseif Ores_A < -60 then
-        if math.random(1, 200) == 1 then
-            return {name = 'crude-oil', amount = 5000 + math.floor(distance_bonus) * 500}
-        end
-    end
-end
+local perlin = require 'map_gen.shared.perlin_noise'
+local Event = require 'utils.event'
+
+local random_ores = {'iron-ore', 'coal', 'copper-ore', 'stone', 'uranium-ore'}
+local random_dense = {1.6, 0.8, 1, 0.6, 0.5} --ore density reference
+
+local function run_ores_module_setup()
+    local seed = game.surfaces[1].map_gen_settings.seed
+    if not global.ores_seed_A then
+        global.ores_seed_A = seed
+    end
+    if not global.ores_seed_B then
+        global.ores_seed_B = seed * 2
+    end
+end
+
+Event.on_init(run_ores_module_setup)
+
+return function(x, y, world)
+    local d_sq = world.x * world.x + world.y * world.y
+    if d_sq < 9216 then
+        return
+    end
+
+    local distance_bonus = 100 + 0.4 * d ^ 1.2
+
+    local wiggle = 100 + perlin.noise((x * 0.005), (y * 0.005), global.ores_seed_A + 41) * 60
+    local Ores_A = perlin.noise((x * 0.01), (y * 0.01), global.ores_seed_B + 57) * wiggle
+
+    if Ores_A > 35 then --we place ores
+        local Ores_B = perlin.noise((x * 0.02), (y * 0.02), global.ores_seed_B + 13) * wiggle
+        local a = 5
+        --
+        if Ores_A < 76 then
+            a = math.floor(Ores_A * 0.75 + Ores_B * 0.5) % 4 + 1
+        end --if its not super high we place normal ores
+        --
+        local res_amount = distance_bonus
+        res_amount = math.floor(res_amount * random_dense[a])
+        --
+
+        return {name = random_ores[a], amount = res_amount}
+    elseif Ores_A < -60 then
+        if math.random(1, 200) == 1 then
+            return {name = 'crude-oil', amount = 5000 + math.floor(distance_bonus) * 500}
+        end
+    end
+end
diff --git a/map_gen/presets/maltease_crossings.lua b/map_gen/presets/maltease_crossings.lua
index 1adfe924..eee60602 100644
--- a/map_gen/presets/maltease_crossings.lua
+++ b/map_gen/presets/maltease_crossings.lua
@@ -1,178 +1,178 @@
--- Map by Jayefuu, plague006 and grilledham
--- Map in the shape of a maltese cross, with narrow water bridges around the spawn to force "interesting" transfer of materials
-
-local b = require 'map_gen.shared.builders'
-local math = require "utils.math"
-local degrees = math.rad
-
-local function value(base, mult, pow)
-    return function(x, y)
-        local d_sq = x * x + y * y
-        return base + mult * d_sq ^ (pow / 2) -- d ^ pow
-    end
-end
-
-local function no_trees(world, tile)
-    if not tile then
-        return
-    end
-    for _, e in ipairs(
-        world.surface.find_entities_filtered(
-            {type = 'tree', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}}
-        )
-    ) do
-        e.destroy()
-    end
-    return tile
-end
-
-local function no_resources(world, tile)
-    for _, e in ipairs(
-        world.surface.find_entities_filtered(
-            {type = 'resource', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}}
-        )
-    ) do
-        e.destroy()
-    end
-    return tile
-end
-
-local starting_area = 59
-
-local gradient = 0.05
-local tiles_half = (starting_area) * 0.5
-
-local function maltese_cross(x,y)
-	--Create maltese shape
-
-	local abs_x = math.abs(x)
-	local abs_y = math.abs(y)
-
-	return not (abs_x > (tiles_half+(abs_y*gradient)) and abs_y > (tiles_half+(abs_x*gradient)))
-end
-
--- create water crossings and pattern
-local water_line =
-        b.any {
-        b.rectangle(10,8)
-    }
-water_line = b.change_tile(water_line, true, 'water')
-
-local waters = b.single_y_pattern(water_line, 9)
-local bounds = b.rectangle(10, starting_area+1)
-waters = b.choose(bounds, waters, b.empty_shape)
-waters = b.translate(waters,34,0)
-
-local water_pattern = b.any{
-	    waters,
-	    b.rotate(waters,degrees(90)),
-	    b.rotate(waters,degrees(180)),
-	    b.rotate(waters,degrees(270))
-    }
-
--- create the starting area as a grass square
-local starting_square =  b.rectangle(60, 60)
-starting_square = b.change_tile(starting_square, true, 'grass-1')
-
-local starting_patch = b.circle(20)
-local starting_coal = b.resource(starting_patch, 'coal', value(1800, 0.8, 1.5))
-local starting_iron = b.resource(starting_patch, 'iron-ore', value(3000, 0.8, 1.5))
-local starting_copper = b.resource(starting_patch, 'copper-ore',  value(2200, 0.75, 1.5))
-local starting_stone = b.resource(starting_patch, 'stone',  value(1100, 0.75, 1.5))
-local null = b.no_entity
-local starting_resources = b.segment_pattern({null,starting_coal,null,starting_copper,null,starting_stone,null,starting_iron})
-starting_resources = b.rotate(starting_resources, degrees(45/2))
--- starting_circle = b.circle(14)
-
--- ore generation
-local patch = b.circle(20)
-local small_patch = b.circle(8)
-local patches = b.single_pattern(patch, 220, 220)
-
-local stone = b.resource(patch, 'stone', value(100, 0.75, 1.1))
-local oil = b.resource(b.throttle_world_xy(small_patch,1,4,1,4), 'crude-oil', value(33000, 50, 1.05))
-local coal = b.resource(patch, 'coal',  value(100, 0.75, 1.1))
-local uranium = b.resource(small_patch, 'uranium-ore', value(200, 0.75, 1.1))
-
-local pattern1 =
-{
-    {stone, oil,stone},
-    {stone, oil, oil},
-    {stone, stone, stone}
-}
-local stone_arm = b.grid_pattern(pattern1, 3, 3,  220,220)
-
-local pattern2 =
-{
-    {coal, coal, coal},
-    {coal, coal, coal},
-    {coal, coal, uranium}
-}
-local coal_arm = b.grid_pattern(pattern2, 3, 3,  220, 220)
-local iron = b.resource(patches, 'iron-ore', value(500, 0.8, 1.075))
-local copper = b.resource(patches, 'copper-ore',  value(400, 0.75, 1.1))
-
-local resources = b.segment_pattern({null,coal_arm,null,copper,null,stone_arm,null,iron})
-resources = b.rotate(resources, degrees(45/2))
-
--- worm islands
-local worm_island = b.rectangle(20,300)
-local worm_island_end = b.circle(10)
-worm_island = b.any{
-	worm_island_end,
-	b.translate(worm_island,0,-150),
-	b.translate(worm_island_end,0,-300)
-}
-worm_island = b.change_tile(worm_island, true, 'grass-1')
-
---[[
-local worm_names = {
-    'small-worm-turret',
-    'medium-worm-turret',
-    'big-worm-turret'
-}
-]]--
-
-local max_worm_chance = 64 / 128
-local worm_chance_factor = 1 --/ (192 * 512)
-local function worms(_, _, world)
-    local wx, wy = world.x, world.y
-    local d = math.sqrt(wx * wx + wy * wy)
-    local worm_chance = d - 20
-    if worm_chance > 0 then
-        worm_chance = worm_chance * worm_chance_factor
-        worm_chance = math.min(worm_chance, max_worm_chance)
-        if math.random() < worm_chance then
-            return {name = 'big-worm-turret'}
-
-        end
-    end
-end
-
-worm_island = b.apply_entity(worm_island, worms)
-worm_island = b.apply_effect(worm_island, no_trees)
-
-local worm_islands = b.any{
-	b.rotate(b.translate(worm_island,0,-110),degrees(45)),
-	b.rotate(b.translate(worm_island,0,-110),degrees(45+90)),
-	b.rotate(b.translate(worm_island,0,-110),degrees(45+180)),
-	b.rotate(b.translate(worm_island,0,-110),degrees(45+270))
-}
-
--- create the start area using the water and grass square
-local start_area =
-    b.any {
-    water_pattern,
-    starting_square
-}
-
--- finalising some bits
-start_area = b.apply_entity(start_area, starting_resources)     -- adds a different density ore patch to start
-maltese_cross = b.change_tile(maltese_cross, true, 'grass-1')
-maltese_cross = b.apply_entity(maltese_cross, resources)        -- adds our custom ore gen
-local sea = b.change_tile(b.full_shape, true, 'water')          -- turn the void to water
-sea = b.fish(sea, 0.00125)                                      -- feesh!
-local map = b.any{worm_islands, start_area, maltese_cross, sea} -- combine everything
-map = b.apply_effect(map, no_resources)                         -- removes vanilla ores
-
+-- Map by Jayefuu, plague006 and grilledham
+-- Map in the shape of a maltese cross, with narrow water bridges around the spawn to force "interesting" transfer of materials
+
+local b = require 'map_gen.shared.builders'
+local math = require "utils.math"
+local degrees = math.rad
+
+local function value(base, mult, pow)
+    return function(x, y)
+        local d_sq = x * x + y * y
+        return base + mult * d_sq ^ (pow / 2) -- d ^ pow
+    end
+end
+
+local function no_trees(world, tile)
+    if not tile then
+        return
+    end
+    for _, e in ipairs(
+        world.surface.find_entities_filtered(
+            {type = 'tree', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}}
+        )
+    ) do
+        e.destroy()
+    end
+    return tile
+end
+
+local function no_resources(world, tile)
+    for _, e in ipairs(
+        world.surface.find_entities_filtered(
+            {type = 'resource', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}}
+        )
+    ) do
+        e.destroy()
+    end
+    return tile
+end
+
+local starting_area = 59
+
+local gradient = 0.05
+local tiles_half = (starting_area) * 0.5
+
+local function maltese_cross(x,y)
+	--Create maltese shape
+
+	local abs_x = math.abs(x)
+	local abs_y = math.abs(y)
+
+	return not (abs_x > (tiles_half+(abs_y*gradient)) and abs_y > (tiles_half+(abs_x*gradient)))
+end
+
+-- create water crossings and pattern
+local water_line =
+        b.any {
+        b.rectangle(10,8)
+    }
+water_line = b.change_tile(water_line, true, 'water')
+
+local waters = b.single_y_pattern(water_line, 9)
+local bounds = b.rectangle(10, starting_area+1)
+waters = b.choose(bounds, waters, b.empty_shape)
+waters = b.translate(waters,34,0)
+
+local water_pattern = b.any{
+	    waters,
+	    b.rotate(waters,degrees(90)),
+	    b.rotate(waters,degrees(180)),
+	    b.rotate(waters,degrees(270))
+    }
+
+-- create the starting area as a grass square
+local starting_square =  b.rectangle(60, 60)
+starting_square = b.change_tile(starting_square, true, 'grass-1')
+
+local starting_patch = b.circle(20)
+local starting_coal = b.resource(starting_patch, 'coal', value(1800, 0.8, 1.5))
+local starting_iron = b.resource(starting_patch, 'iron-ore', value(3000, 0.8, 1.5))
+local starting_copper = b.resource(starting_patch, 'copper-ore',  value(2200, 0.75, 1.5))
+local starting_stone = b.resource(starting_patch, 'stone',  value(1100, 0.75, 1.5))
+local null = b.no_entity
+local starting_resources = b.segment_pattern({null,starting_coal,null,starting_copper,null,starting_stone,null,starting_iron})
+starting_resources = b.rotate(starting_resources, degrees(45/2))
+-- starting_circle = b.circle(14)
+
+-- ore generation
+local patch = b.circle(20)
+local small_patch = b.circle(8)
+local patches = b.single_pattern(patch, 220, 220)
+
+local stone = b.resource(patch, 'stone', value(100, 0.75, 1.1))
+local oil = b.resource(b.throttle_world_xy(small_patch,1,4,1,4), 'crude-oil', value(33000, 50, 1.05))
+local coal = b.resource(patch, 'coal',  value(100, 0.75, 1.1))
+local uranium = b.resource(small_patch, 'uranium-ore', value(200, 0.75, 1.1))
+
+local pattern1 =
+{
+    {stone, oil,stone},
+    {stone, oil, oil},
+    {stone, stone, stone}
+}
+local stone_arm = b.grid_pattern(pattern1, 3, 3,  220,220)
+
+local pattern2 =
+{
+    {coal, coal, coal},
+    {coal, coal, coal},
+    {coal, coal, uranium}
+}
+local coal_arm = b.grid_pattern(pattern2, 3, 3,  220, 220)
+local iron = b.resource(patches, 'iron-ore', value(500, 0.8, 1.075))
+local copper = b.resource(patches, 'copper-ore',  value(400, 0.75, 1.1))
+
+local resources = b.segment_pattern({null,coal_arm,null,copper,null,stone_arm,null,iron})
+resources = b.rotate(resources, degrees(45/2))
+
+-- worm islands
+local worm_island = b.rectangle(20,300)
+local worm_island_end = b.circle(10)
+worm_island = b.any{
+	worm_island_end,
+	b.translate(worm_island,0,-150),
+	b.translate(worm_island_end,0,-300)
+}
+worm_island = b.change_tile(worm_island, true, 'grass-1')
+
+--[[
+local worm_names = {
+    'small-worm-turret',
+    'medium-worm-turret',
+    'big-worm-turret'
+}
+]]--
+
+local max_worm_chance = 64 / 128
+local worm_chance_factor = 1 --/ (192 * 512)
+local function worms(_, _, world)
+    local wx, wy = world.x, world.y
+    local d = math.sqrt(wx * wx + wy * wy)
+    local worm_chance = d - 20
+    if worm_chance > 0 then
+        worm_chance = worm_chance * worm_chance_factor
+        worm_chance = math.min(worm_chance, max_worm_chance)
+        if math.random() < worm_chance then
+            return {name = 'big-worm-turret'}
+
+        end
+    end
+end
+
+worm_island = b.apply_entity(worm_island, worms)
+worm_island = b.apply_effect(worm_island, no_trees)
+
+local worm_islands = b.any{
+	b.rotate(b.translate(worm_island,0,-110),degrees(45)),
+	b.rotate(b.translate(worm_island,0,-110),degrees(45+90)),
+	b.rotate(b.translate(worm_island,0,-110),degrees(45+180)),
+	b.rotate(b.translate(worm_island,0,-110),degrees(45+270))
+}
+
+-- create the start area using the water and grass square
+local start_area =
+    b.any {
+    water_pattern,
+    starting_square
+}
+
+-- finalising some bits
+start_area = b.apply_entity(start_area, starting_resources)     -- adds a different density ore patch to start
+maltese_cross = b.change_tile(maltese_cross, true, 'grass-1')
+maltese_cross = b.apply_entity(maltese_cross, resources)        -- adds our custom ore gen
+local sea = b.change_tile(b.full_shape, true, 'water')          -- turn the void to water
+sea = b.fish(sea, 0.00125)                                      -- feesh!
+local map = b.any{worm_islands, start_area, maltese_cross, sea} -- combine everything
+map = b.apply_effect(map, no_resources)                         -- removes vanilla ores
+
 return map
\ No newline at end of file
diff --git a/map_gen/shape/right.lua b/map_gen/shape/right.lua
index b09b30e6..00a75582 100644
--- a/map_gen/shape/right.lua
+++ b/map_gen/shape/right.lua
@@ -1,3 +1,3 @@
-return function(x, y, world)
-	return not (x < -150 or y > 32 or y < -568)
-end
+return function(x, y, world)
+	return not (x < -150 or y > 32 or y < -568)
+end
diff --git a/map_gen/shape/spiral.lua b/map_gen/shape/spiral.lua
index 79ffe8e2..5d99f216 100644
--- a/map_gen/shape/spiral.lua
+++ b/map_gen/shape/spiral.lua
@@ -1,16 +1,16 @@
-local thickness = 72 -- change this to change the spiral thickness.
-
-local inv_pi = 1 / math.pi
-local thickness2 = thickness * 2
-
-return function(x, y)
-    local d_sq = x * x + y * y
-    if d_sq < 16384 then --d < 128
-        return true
-    end
-
-    local angle = 1 + inv_pi * math.atan2(x, y)
-    local offset = d + (angle * thickness)
-
-    return offset % thickness2 >= thickness
-end
+local thickness = 72 -- change this to change the spiral thickness.
+
+local inv_pi = 1 / math.pi
+local thickness2 = thickness * 2
+
+return function(x, y)
+    local d_sq = x * x + y * y
+    if d_sq < 16384 then --d < 128
+        return true
+    end
+
+    local angle = 1 + inv_pi * math.atan2(x, y)
+    local offset = d + (angle * thickness)
+
+    return offset % thickness2 >= thickness
+end
diff --git a/map_gen/shape/spiral2.lua b/map_gen/shape/spiral2.lua
index e202595d..accb0a19 100644
--- a/map_gen/shape/spiral2.lua
+++ b/map_gen/shape/spiral2.lua
@@ -1,20 +1,20 @@
-return function(x, y, world)
-	local distance = math.sqrt(x * x + y * y)
-	if distance > 128 then
-		local angle = 180 + math.deg(math.atan2(x, y))
-
-		local offset = distance
-		local offset2 = distance
-		if angle ~= 0 then
-			offset2 = offset - angle / 3.75
-			offset = offset + angle / 3.75
-		end
-		--if angle ~= 0 then offset = offset + angle /1.33333333 end
-
-		if offset % 96 < 64 then
-			return offset2 % 96 >= 64
-		end
-	end
-
-	return true
-end
+return function(x, y, world)
+	local distance = math.sqrt(x * x + y * y)
+	if distance > 128 then
+		local angle = 180 + math.deg(math.atan2(x, y))
+
+		local offset = distance
+		local offset2 = distance
+		if angle ~= 0 then
+			offset2 = offset - angle / 3.75
+			offset = offset + angle / 3.75
+		end
+		--if angle ~= 0 then offset = offset + angle /1.33333333 end
+
+		if offset % 96 < 64 then
+			return offset2 % 96 >= 64
+		end
+	end
+
+	return true
+end
diff --git a/map_gen/shape/spiral_tri.lua b/map_gen/shape/spiral_tri.lua
index 4c0f289c..8ae452cd 100644
--- a/map_gen/shape/spiral_tri.lua
+++ b/map_gen/shape/spiral_tri.lua
@@ -1,23 +1,23 @@
-return function(x, y, world)
-	local distance = math.sqrt(x * x + y * y)
-	if distance > 128 then
-		local angle = (180 + math.deg(math.atan2(x, y))) * 3
-
-		local offset = distance * 0.75
-		if angle ~= 0 then
-			offset = offset + angle / 3.75
-		end
-		--if angle ~= 0 then offset = offset + angle /1.33333333 end
-
-		if offset % 96 < 48 then
-			local offset2 = distance * 0.125
-			if angle ~= 0 then
-				offset2 = offset2 - angle / 3.75
-			end
-
-			return offset2 % 96 >= 80
-		end
-	end
-
-	return true
-end
+return function(x, y, world)
+	local distance = math.sqrt(x * x + y * y)
+	if distance > 128 then
+		local angle = (180 + math.deg(math.atan2(x, y))) * 3
+
+		local offset = distance * 0.75
+		if angle ~= 0 then
+			offset = offset + angle / 3.75
+		end
+		--if angle ~= 0 then offset = offset + angle /1.33333333 end
+
+		if offset % 96 < 48 then
+			local offset2 = distance * 0.125
+			if angle ~= 0 then
+				offset2 = offset2 - angle / 3.75
+			end
+
+			return offset2 % 96 >= 80
+		end
+	end
+
+	return true
+end
diff --git a/map_gen/shape/threaded_spirals.lua b/map_gen/shape/threaded_spirals.lua
index b85aafe0..aed98eaf 100644
--- a/map_gen/shape/threaded_spirals.lua
+++ b/map_gen/shape/threaded_spirals.lua
@@ -1,21 +1,21 @@
--- Author: flowild
-
-local arm_width = 96
-
-local function is_on_spiral(x, y, distance, angle_offset)
-	local angle = angle_offset + math.deg(math.atan2(x, y))
-
-	local offset = distance
-	if angle ~= 0 then
-		offset = offset + angle / 3.75 * 2
-	end
-	return offset % 96 * 2 >= 48 * 2
-end
-
-return function(x, y, world)
-	local pseudo_x = x / (arm_width / 48)
-	local pseudo_y = y / (arm_width / 48)
-	local distance = math.sqrt(pseudo_x * pseudo_x + pseudo_y * pseudo_y)
-
-	return not (distance > 100 and not is_on_spiral(x, y, distance, 0))
-end
+-- Author: flowild
+
+local arm_width = 96
+
+local function is_on_spiral(x, y, distance, angle_offset)
+	local angle = angle_offset + math.deg(math.atan2(x, y))
+
+	local offset = distance
+	if angle ~= 0 then
+		offset = offset + angle / 3.75 * 2
+	end
+	return offset % 96 * 2 >= 48 * 2
+end
+
+return function(x, y, world)
+	local pseudo_x = x / (arm_width / 48)
+	local pseudo_y = y / (arm_width / 48)
+	local distance = math.sqrt(pseudo_x * pseudo_x + pseudo_y * pseudo_y)
+
+	return not (distance > 100 and not is_on_spiral(x, y, distance, 0))
+end
diff --git a/map_gen/shape/up.lua b/map_gen/shape/up.lua
index d9ca0d7e..70d9d539 100644
--- a/map_gen/shape/up.lua
+++ b/map_gen/shape/up.lua
@@ -1,3 +1,3 @@
-return function(x, y, world)
-	return not (x > 180 or x < -180 or y > 80)
-end
+return function(x, y, world)
+	return not (x > 180 or x < -180 or y > 80)
+end
diff --git a/map_gen/shared/ent_functions.lua b/map_gen/shared/ent_functions.lua
index a84d2b9e..8c8a8610 100644
--- a/map_gen/shared/ent_functions.lua
+++ b/map_gen/shared/ent_functions.lua
@@ -1,535 +1,535 @@
---allows any gen to access these functions
-
-function place_entities(surface, entity_list)
-	local directions = {defines.direction.north, defines.direction.east, defines.direction.south, defines.direction.west}	
-	for _, entity in pairs(entity_list) do		
-		local r = math.random(1,entity.chance)		
-		if r == 1 then
-			if not entity.force then entity.force = "player" end
-			local r = math.random(1,4)			
-			if surface.can_place_entity {name=entity.name, position=entity.pos, direction=directions[r], force=entity.force} then														
-				local e = surface.create_entity {name=entity.name, position=entity.pos, direction=directions[r], force=entity.force}
-				if entity.health then
-					if entity.health == "low" then e.health = ((e.health / 1000) * math.random(33,330)) end
-					if entity.health == "medium" then e.health = ((e.health / 1000) * math.random(333,666)) end
-					if entity.health == "high" then e.health = ((e.health / 1000) * math.random(666,999)) end
-					if entity.health == "random" then e.health = ((e.health / 1000) * math.random(1,1000)) end
-				end
-				return true, e
-			end			
-		end		
-	end
-	return false
-end
-
-function auto_place_entity_around_target(entity, scan_radius, mode, density, surface)
-	local x = entity.pos.x
-	local y = entity.pos.y
-	if not surface then surface = game.surfaces[1] end
-	if not scan_radius then scan_radius = 6 end
-	if not entity then return end
-	if not mode then mode = "ball" end
-	if not density then density = 1 end
-	
-	if surface.can_place_entity {name=entity.name, position={x,y}} then														
-		local e = surface.create_entity {name=entity.name, position={x,y}}
-		return true, e
-	end
-	
-	local i = 2
-	local r = 1		
-	
-	if mode == "ball" then
-		if math.random(1,2) == 1 then 
-			density = density * -1
-		end
-		r = math.random(1,4)
-	end
-	if mode == "line" then
-		density = 1
-		r = math.random(1,4)
-	end
-	if mode == "line_down" then
-		density = density * -1
-		r = math.random(1,4)
-	end
-	if mode == "line_up" then
-		density = 1
-		r = math.random(1,4)
-	end
-	if mode == "block" then
-		r = 1
-		density = 1
-	end	
-	
-	if r == 1 then
-		--start placing at -1,-1
-		while i <= scan_radius do
-			y = y - density						
-			x = x - density				
-			for a = 1, i, 1 do				
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-				x = x + density
-			end		
-			for a = 1, i, 1 do				
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-				y = y + density
-			end		
-			for a = 1, i, 1 do				
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-				x = x - density
-			end		
-			for a = 1, i, 1 do				
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-				y = y - density
-			end			
-			i = i + 2
-		end
-	end
-		
-	if r == 2 then
-		--start placing at 0,-1
-		while i <= scan_radius do
-			y = y - density						
-			x = x - density
-			for a = 1, i, 1 do
-				x = x + density
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-			end		
-			for a = 1, i, 1 do
-				y = y + density
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-			end		
-			for a = 1, i, 1 do
-				x = x - density
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-			end		
-			for a = 1, i, 1 do
-				y = y - density
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-			end		
-			i = i + 2
-		end
-	end
-	
-	if r == 3 then
-		--start placing at 1,-1
-		while i <= scan_radius do
-			y = y - density						
-			x = x + density								
-			for a = 1, i, 1 do				
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-				y = y + density
-			end		
-			for a = 1, i, 1 do				
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-				x = x - density
-			end		
-			for a = 1, i, 1 do				
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-				y = y - density
-			end
-			for a = 1, i, 1 do				
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-				x = x + density
-			end				
-			i = i + 2
-		end
-	end
-	
-	if r == 4 then
-		--start placing at 1,0
-		while i <= scan_radius do
-			y = y - density
-			x = x + density				
-			for a = 1, i, 1 do
-				y = y + density
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-			end		
-			for a = 1, i, 1 do
-				x = x - density
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-			end		
-			for a = 1, i, 1 do
-				y = y - density
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-			end
-			for a = 1, i, 1 do
-				x = x + density
-				if surface.can_place_entity {name=entity.name, position={x,y}} then														
-					local e = surface.create_entity {name=entity.name, position={x,y}}
-					return true, e
-				end
-			end			
-			i = i + 2
-		end
-	end
-		
-	return false
-end
-
-function create_entitie_cluster(name, pos, amount)
-	
-	local surface = game.surfaces[1]		
-	local entity = {}	
-	entity.pos = pos
-	entity.name = name
-	local mode = "ball"
-	
-	for i = 1, amount, 1 do
-		local b, e = auto_place_entity_around_target(entity, 30, mode)
-		if b == true then
-			if 1 == math.random(1,40) then
-				entity.pos = e.position
-			end	
-			if e.type == "resource" then
-				e.amount = math.random(500,1500)
-			end						
-		end
-	end	
-	return b, e
-end
-
-function create_rock_cluster(pos, amount)
-	if not pos then return false end
-	if amount == nil then amount = 7 end
-	local scan_radius = amount * 2
-	local mode = "line_down"
-	if math.random(1,2) == 1 then mode = "line_up" end
-	local entity = {}
-	entity.pos = pos		
-	for i = 1, amount, 1 do
-		if 1 == math.random(1,3) then
-			entity.name = "sand-rock-big"
-		else
-			entity.name = "sand-rock-big"
-		end	
-		local b, e = auto_place_entity_around_target(entity, scan_radius, mode)
-		if b == true then
-			if 1 ~= math.random(1,20) then
-				entity.pos = e.position
-			end			
-		end
-	end	
-	return b, e
-end
-
-function create_tree_cluster(pos, amount)
-	if not pos then return false end
-	if amount == nil then amount = 7 end
-	local scan_radius = amount * 2
-	--local mode = "line_down"	
-	--if math.random(1,2) == 1 then mode = "line_up" end
-	local mode = "ball"
-	local entity = {}
-	entity.pos = pos		
-	for i = 1, amount, 1 do
-		entity.name = "tree-06"
-		local density = 2
-		if 1 == math.random(1,20) then entity.name = "tree-07" end	
-		if 1 == math.random(1,70) then entity.name = "tree-09" end
-		if 1 == math.random(1,10) then entity.name = "tree-04" end
-		if 1 == math.random(1,9) then density = 1 end
-		if 1 == math.random(1,3) then density = 3 end
-		if 1 == math.random(1,3) then density = 4 end
-		
-		local b, e = auto_place_entity_around_target(entity, scan_radius, mode, density)
-		if b == true then
-			if 1 == math.random(1,3) then
-				entity.pos = e.position
-			end			
-		end
-	end	
-	return b, e
-end
-
-function find_tile_placement_spot_around_target_position(tilename, position, mode, density)
-	local x = position.x
-	local y = position.y
-	if not surface then surface = game.surfaces[1] end
-	local scan_radius = 50
-	if not tilename then return end
-	if not mode then mode = "ball" end
-	if not density then density = 1 end
-	local cluster_tiles = {}
-	local auto_correct = false
-	
-	local scanned_tile = surface.get_tile(x,y)
-	if scanned_tile.name ~= tilename then
-		table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-		surface.set_tiles(cluster_tiles,false)
-		return true, x, y
-	end
-	
-	local i = 2
-	local r = 1		
-	
-	if mode == "ball" then
-		if math.random(1,2) == 1 then 
-			density = density * -1
-		end
-		r = math.random(1,4)
-	end
-	if mode == "line" then
-		density = 1
-		r = math.random(1,4)
-	end
-	if mode == "line_down" then
-		density = density * -1
-		r = math.random(1,4)
-	end
-	if mode == "line_up" then
-		density = 1
-		r = math.random(1,4)
-	end
-	if mode == "block" then
-		r = 1
-		density = 1
-	end	
-	
-	if r == 1 then
-		--start placing at -1,-1
-		while i <= scan_radius do
-			y = y - density						
-			x = x - density				
-			for a = 1, i, 1 do				
-				local scanned_tile = surface.get_tile(x,y)				
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-				x = x + density
-			end		
-			for a = 1, i, 1 do				
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-				y = y + density
-			end		
-			for a = 1, i, 1 do				
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-				x = x - density
-			end		
-			for a = 1, i, 1 do				
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-				y = y - density
-			end			
-			i = i + 2
-		end
-	end
-		
-	if r == 2 then
-		--start placing at 0,-1
-		while i <= scan_radius do
-			y = y - density						
-			x = x - density
-			for a = 1, i, 1 do
-				x = x + density
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-			end		
-			for a = 1, i, 1 do
-				y = y + density
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-			end		
-			for a = 1, i, 1 do
-				x = x - density
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-			end		
-			for a = 1, i, 1 do
-				y = y - density
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-			end		
-			i = i + 2
-		end
-	end
-	
-	if r == 3 then
-		--start placing at 1,-1
-		while i <= scan_radius do
-			y = y - density						
-			x = x + density								
-			for a = 1, i, 1 do				
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-				y = y + density
-			end		
-			for a = 1, i, 1 do				
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-				x = x - density
-			end		
-			for a = 1, i, 1 do				
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-				y = y - density
-			end
-			for a = 1, i, 1 do				
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-				x = x + density
-			end				
-			i = i + 2
-		end
-	end
-	
-	if r == 4 then
-		--start placing at 1,0
-		while i <= scan_radius do
-			y = y - density
-			x = x + density				
-			for a = 1, i, 1 do
-				y = y + density
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-			end		
-			for a = 1, i, 1 do
-				x = x - density
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-			end		
-			for a = 1, i, 1 do
-				y = y - density
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-			end
-			for a = 1, i, 1 do
-				x = x + density
-				local scanned_tile = surface.get_tile(x,y)
-				if scanned_tile.name ~= tilename then	
-					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
-					surface.set_tiles(cluster_tiles,auto_correct)
-					return true, x, y
-				end
-			end			
-			i = i + 2
-		end
-	end	
-	return false
-end
-
-function create_tile_cluster(tilename,position,amount)
-	local mode = "ball"
-	local cluster_tiles = {}
-	local surface = game.surfaces[1]
-	local pos = position
-	local x = pos.x
-	local y = pos.y
-	for i = 1, amount, 1 do
-		local b,x,y = find_tile_placement_spot_around_target_position(tilename, pos, mode)
-		if b == true then						
-			if 1 == math.random(1,2) then
-				pos.x = x
-				pos.y = y
-			end			
-		end
-		if b == false then return false,x,y end
-		if i >= amount then return true,x,y end
-	end
-end
+--allows any gen to access these functions
+
+function place_entities(surface, entity_list)
+	local directions = {defines.direction.north, defines.direction.east, defines.direction.south, defines.direction.west}	
+	for _, entity in pairs(entity_list) do		
+		local r = math.random(1,entity.chance)		
+		if r == 1 then
+			if not entity.force then entity.force = "player" end
+			local r = math.random(1,4)			
+			if surface.can_place_entity {name=entity.name, position=entity.pos, direction=directions[r], force=entity.force} then														
+				local e = surface.create_entity {name=entity.name, position=entity.pos, direction=directions[r], force=entity.force}
+				if entity.health then
+					if entity.health == "low" then e.health = ((e.health / 1000) * math.random(33,330)) end
+					if entity.health == "medium" then e.health = ((e.health / 1000) * math.random(333,666)) end
+					if entity.health == "high" then e.health = ((e.health / 1000) * math.random(666,999)) end
+					if entity.health == "random" then e.health = ((e.health / 1000) * math.random(1,1000)) end
+				end
+				return true, e
+			end			
+		end		
+	end
+	return false
+end
+
+function auto_place_entity_around_target(entity, scan_radius, mode, density, surface)
+	local x = entity.pos.x
+	local y = entity.pos.y
+	if not surface then surface = game.surfaces[1] end
+	if not scan_radius then scan_radius = 6 end
+	if not entity then return end
+	if not mode then mode = "ball" end
+	if not density then density = 1 end
+	
+	if surface.can_place_entity {name=entity.name, position={x,y}} then														
+		local e = surface.create_entity {name=entity.name, position={x,y}}
+		return true, e
+	end
+	
+	local i = 2
+	local r = 1		
+	
+	if mode == "ball" then
+		if math.random(1,2) == 1 then 
+			density = density * -1
+		end
+		r = math.random(1,4)
+	end
+	if mode == "line" then
+		density = 1
+		r = math.random(1,4)
+	end
+	if mode == "line_down" then
+		density = density * -1
+		r = math.random(1,4)
+	end
+	if mode == "line_up" then
+		density = 1
+		r = math.random(1,4)
+	end
+	if mode == "block" then
+		r = 1
+		density = 1
+	end	
+	
+	if r == 1 then
+		--start placing at -1,-1
+		while i <= scan_radius do
+			y = y - density						
+			x = x - density				
+			for a = 1, i, 1 do				
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+				x = x + density
+			end		
+			for a = 1, i, 1 do				
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+				y = y + density
+			end		
+			for a = 1, i, 1 do				
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+				x = x - density
+			end		
+			for a = 1, i, 1 do				
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+				y = y - density
+			end			
+			i = i + 2
+		end
+	end
+		
+	if r == 2 then
+		--start placing at 0,-1
+		while i <= scan_radius do
+			y = y - density						
+			x = x - density
+			for a = 1, i, 1 do
+				x = x + density
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+			end		
+			for a = 1, i, 1 do
+				y = y + density
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+			end		
+			for a = 1, i, 1 do
+				x = x - density
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+			end		
+			for a = 1, i, 1 do
+				y = y - density
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+			end		
+			i = i + 2
+		end
+	end
+	
+	if r == 3 then
+		--start placing at 1,-1
+		while i <= scan_radius do
+			y = y - density						
+			x = x + density								
+			for a = 1, i, 1 do				
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+				y = y + density
+			end		
+			for a = 1, i, 1 do				
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+				x = x - density
+			end		
+			for a = 1, i, 1 do				
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+				y = y - density
+			end
+			for a = 1, i, 1 do				
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+				x = x + density
+			end				
+			i = i + 2
+		end
+	end
+	
+	if r == 4 then
+		--start placing at 1,0
+		while i <= scan_radius do
+			y = y - density
+			x = x + density				
+			for a = 1, i, 1 do
+				y = y + density
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+			end		
+			for a = 1, i, 1 do
+				x = x - density
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+			end		
+			for a = 1, i, 1 do
+				y = y - density
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+			end
+			for a = 1, i, 1 do
+				x = x + density
+				if surface.can_place_entity {name=entity.name, position={x,y}} then														
+					local e = surface.create_entity {name=entity.name, position={x,y}}
+					return true, e
+				end
+			end			
+			i = i + 2
+		end
+	end
+		
+	return false
+end
+
+function create_entitie_cluster(name, pos, amount)
+	
+	local surface = game.surfaces[1]		
+	local entity = {}	
+	entity.pos = pos
+	entity.name = name
+	local mode = "ball"
+	
+	for i = 1, amount, 1 do
+		local b, e = auto_place_entity_around_target(entity, 30, mode)
+		if b == true then
+			if 1 == math.random(1,40) then
+				entity.pos = e.position
+			end	
+			if e.type == "resource" then
+				e.amount = math.random(500,1500)
+			end						
+		end
+	end	
+	return b, e
+end
+
+function create_rock_cluster(pos, amount)
+	if not pos then return false end
+	if amount == nil then amount = 7 end
+	local scan_radius = amount * 2
+	local mode = "line_down"
+	if math.random(1,2) == 1 then mode = "line_up" end
+	local entity = {}
+	entity.pos = pos		
+	for i = 1, amount, 1 do
+		if 1 == math.random(1,3) then
+			entity.name = "sand-rock-big"
+		else
+			entity.name = "sand-rock-big"
+		end	
+		local b, e = auto_place_entity_around_target(entity, scan_radius, mode)
+		if b == true then
+			if 1 ~= math.random(1,20) then
+				entity.pos = e.position
+			end			
+		end
+	end	
+	return b, e
+end
+
+function create_tree_cluster(pos, amount)
+	if not pos then return false end
+	if amount == nil then amount = 7 end
+	local scan_radius = amount * 2
+	--local mode = "line_down"	
+	--if math.random(1,2) == 1 then mode = "line_up" end
+	local mode = "ball"
+	local entity = {}
+	entity.pos = pos		
+	for i = 1, amount, 1 do
+		entity.name = "tree-06"
+		local density = 2
+		if 1 == math.random(1,20) then entity.name = "tree-07" end	
+		if 1 == math.random(1,70) then entity.name = "tree-09" end
+		if 1 == math.random(1,10) then entity.name = "tree-04" end
+		if 1 == math.random(1,9) then density = 1 end
+		if 1 == math.random(1,3) then density = 3 end
+		if 1 == math.random(1,3) then density = 4 end
+		
+		local b, e = auto_place_entity_around_target(entity, scan_radius, mode, density)
+		if b == true then
+			if 1 == math.random(1,3) then
+				entity.pos = e.position
+			end			
+		end
+	end	
+	return b, e
+end
+
+function find_tile_placement_spot_around_target_position(tilename, position, mode, density)
+	local x = position.x
+	local y = position.y
+	if not surface then surface = game.surfaces[1] end
+	local scan_radius = 50
+	if not tilename then return end
+	if not mode then mode = "ball" end
+	if not density then density = 1 end
+	local cluster_tiles = {}
+	local auto_correct = false
+	
+	local scanned_tile = surface.get_tile(x,y)
+	if scanned_tile.name ~= tilename then
+		table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+		surface.set_tiles(cluster_tiles,false)
+		return true, x, y
+	end
+	
+	local i = 2
+	local r = 1		
+	
+	if mode == "ball" then
+		if math.random(1,2) == 1 then 
+			density = density * -1
+		end
+		r = math.random(1,4)
+	end
+	if mode == "line" then
+		density = 1
+		r = math.random(1,4)
+	end
+	if mode == "line_down" then
+		density = density * -1
+		r = math.random(1,4)
+	end
+	if mode == "line_up" then
+		density = 1
+		r = math.random(1,4)
+	end
+	if mode == "block" then
+		r = 1
+		density = 1
+	end	
+	
+	if r == 1 then
+		--start placing at -1,-1
+		while i <= scan_radius do
+			y = y - density						
+			x = x - density				
+			for a = 1, i, 1 do				
+				local scanned_tile = surface.get_tile(x,y)				
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+				x = x + density
+			end		
+			for a = 1, i, 1 do				
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+				y = y + density
+			end		
+			for a = 1, i, 1 do				
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+				x = x - density
+			end		
+			for a = 1, i, 1 do				
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+				y = y - density
+			end			
+			i = i + 2
+		end
+	end
+		
+	if r == 2 then
+		--start placing at 0,-1
+		while i <= scan_radius do
+			y = y - density						
+			x = x - density
+			for a = 1, i, 1 do
+				x = x + density
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+			end		
+			for a = 1, i, 1 do
+				y = y + density
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+			end		
+			for a = 1, i, 1 do
+				x = x - density
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+			end		
+			for a = 1, i, 1 do
+				y = y - density
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+			end		
+			i = i + 2
+		end
+	end
+	
+	if r == 3 then
+		--start placing at 1,-1
+		while i <= scan_radius do
+			y = y - density						
+			x = x + density								
+			for a = 1, i, 1 do				
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+				y = y + density
+			end		
+			for a = 1, i, 1 do				
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+				x = x - density
+			end		
+			for a = 1, i, 1 do				
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+				y = y - density
+			end
+			for a = 1, i, 1 do				
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+				x = x + density
+			end				
+			i = i + 2
+		end
+	end
+	
+	if r == 4 then
+		--start placing at 1,0
+		while i <= scan_radius do
+			y = y - density
+			x = x + density				
+			for a = 1, i, 1 do
+				y = y + density
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+			end		
+			for a = 1, i, 1 do
+				x = x - density
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+			end		
+			for a = 1, i, 1 do
+				y = y - density
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+			end
+			for a = 1, i, 1 do
+				x = x + density
+				local scanned_tile = surface.get_tile(x,y)
+				if scanned_tile.name ~= tilename then	
+					table.insert(cluster_tiles, {name = tilename, position = {x,y}})
+					surface.set_tiles(cluster_tiles,auto_correct)
+					return true, x, y
+				end
+			end			
+			i = i + 2
+		end
+	end	
+	return false
+end
+
+function create_tile_cluster(tilename,position,amount)
+	local mode = "ball"
+	local cluster_tiles = {}
+	local surface = game.surfaces[1]
+	local pos = position
+	local x = pos.x
+	local y = pos.y
+	for i = 1, amount, 1 do
+		local b,x,y = find_tile_placement_spot_around_target_position(tilename, pos, mode)
+		if b == true then						
+			if 1 == math.random(1,2) then
+				pos.x = x
+				pos.y = y
+			end			
+		end
+		if b == false then return false,x,y end
+		if i >= amount then return true,x,y end
+	end
+end
diff --git a/map_gen/shared/simplex_noise.lua b/map_gen/shared/simplex_noise.lua
index 61bad5dc..6dfb0a7a 100644
--- a/map_gen/shared/simplex_noise.lua
+++ b/map_gen/shared/simplex_noise.lua
@@ -1,106 +1,106 @@
---from https://github.com/thenumbernine/lua-simplexnoise/blob/master/2d.lua
---Mostly as a test, does not give same results as perlin but is designed to give patterns all the same
-
-local Simplex = {}
-
--- 2D simplex noise
-
-local grad3 = {
-	{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
-	{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
-	{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}
-}
-
-local  p = {151,160,137,91,90,15,
-	131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
-	190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
-	88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
-	77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
-	102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
-	135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
-	5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
-	223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
-	129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
-	251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
-	49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
-	138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180}
-local perm = {}
-for i=0,511 do
-	perm[i+1] = p[bit32.band(i, 255) + 1]
-end
-
-local function dot(g, ...)
-	local v = {...}
-	local sum = 0
-	for i=1,#v do
-		sum = sum + v[i] * g[i]
-	end
-	return sum
-end
-
-local F2 = 0.5*(math.sqrt(3.0)-1.0)
-local G2 = (3.0-math.sqrt(3.0))/6.0
-function Simplex.d2(xin, yin,seed)
-	xin = xin + seed
-	yin = yin + seed
-	local n0, n1, n2	-- Noise contributions from the three corners
-	-- Skew the input space to determine which simplex cell we're in
-	local s = (xin+yin)*F2; -- Hairy factor for 2D
-	local i = math.floor(xin+s)
-	local j = math.floor(yin+s)
-	local t = (i+j)*G2
-	local X0 = i-t -- Unskew the cell origin back to (x,y) space
-	local Y0 = j-t
-	local x0 = xin-X0 -- The x,y distances from the cell origin
-	local y0 = yin-Y0
-	-- For the 2D case, the simplex shape is an equilateral triangle.
-	-- Determine which simplex we are in.
-	local i1, j1 -- Offsets for second (middle) corner of simplex in (i,j) coords
-	if x0 > y0 then
-		i1 = 1
-		j1 = 0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1)
-	else
-		i1 = 0
-		j1 = 1
-	end-- upper triangle, YX order: (0,0)->(0,1)->(1,1)
-	-- A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
-	-- a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
-	-- c = (3-sqrt(3))/6
-	local x1 = x0 - i1 + G2 -- Offsets for middle corner in (x,y) unskewed coords
-	local y1 = y0 - j1 + G2
-	local x2 = x0 - 1 + 2 * G2 -- Offsets for last corner in (x,y) unskewed coords
-	local y2 = y0 - 1 + 2 * G2
-	-- Work out the hashed gradient indices of the three simplex corners
-	local ii = bit32.band(i, 255)
-	local jj = bit32.band(j, 255)
-	local gi0 = perm[ii + perm[jj+1]+1] % 12
-	local gi1 = perm[ii + i1 + perm[jj + j1+1]+1] % 12
-	local gi2 = perm[ii + 1 + perm[jj + 1+1]+1] % 12
-	-- Calculate the contribution from the three corners
-	local t0 = 0.5 - x0 * x0 - y0 * y0
-	if t0 < 0 then
-		n0 = 0.0
-	else
-		t0 = t0 * t0
-		n0 = t0 * t0 * dot(grad3[gi0+1], x0, y0) -- (x,y) of grad3 used for 2D gradient
-	end
-	local t1 = 0.5 - x1 * x1 - y1 * y1
-	if t1 < 0 then
-		n1 = 0.0
-	else
-		t1 = t1 * t1
-		n1 = t1 * t1 * dot(grad3[gi1+1], x1, y1)
-	end
-	local t2 = 0.5 - x2 * x2 - y2 * y2
-	if t2 < 0 then
-		n2 = 0.0
-	else
-		t2 = t2 * t2
-		n2 = t2 * t2 * dot(grad3[gi2+1], x2, y2)
-	end
-	-- Add contributions from each corner to get the final noise value.
-	-- The result is scaled to return values in the interval [-1,1].
-	return 70.0 * (n0 + n1 + n2)
-end
-
-return Simplex
+--from https://github.com/thenumbernine/lua-simplexnoise/blob/master/2d.lua
+--Mostly as a test, does not give same results as perlin but is designed to give patterns all the same
+
+local Simplex = {}
+
+-- 2D simplex noise
+
+local grad3 = {
+	{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
+	{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
+	{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}
+}
+
+local  p = {151,160,137,91,90,15,
+	131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+	190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+	88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+	77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+	102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+	135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+	5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+	223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+	129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+	251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+	49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+	138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180}
+local perm = {}
+for i=0,511 do
+	perm[i+1] = p[bit32.band(i, 255) + 1]
+end
+
+local function dot(g, ...)
+	local v = {...}
+	local sum = 0
+	for i=1,#v do
+		sum = sum + v[i] * g[i]
+	end
+	return sum
+end
+
+local F2 = 0.5*(math.sqrt(3.0)-1.0)
+local G2 = (3.0-math.sqrt(3.0))/6.0
+function Simplex.d2(xin, yin,seed)
+	xin = xin + seed
+	yin = yin + seed
+	local n0, n1, n2	-- Noise contributions from the three corners
+	-- Skew the input space to determine which simplex cell we're in
+	local s = (xin+yin)*F2; -- Hairy factor for 2D
+	local i = math.floor(xin+s)
+	local j = math.floor(yin+s)
+	local t = (i+j)*G2
+	local X0 = i-t -- Unskew the cell origin back to (x,y) space
+	local Y0 = j-t
+	local x0 = xin-X0 -- The x,y distances from the cell origin
+	local y0 = yin-Y0
+	-- For the 2D case, the simplex shape is an equilateral triangle.
+	-- Determine which simplex we are in.
+	local i1, j1 -- Offsets for second (middle) corner of simplex in (i,j) coords
+	if x0 > y0 then
+		i1 = 1
+		j1 = 0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1)
+	else
+		i1 = 0
+		j1 = 1
+	end-- upper triangle, YX order: (0,0)->(0,1)->(1,1)
+	-- A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
+	-- a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
+	-- c = (3-sqrt(3))/6
+	local x1 = x0 - i1 + G2 -- Offsets for middle corner in (x,y) unskewed coords
+	local y1 = y0 - j1 + G2
+	local x2 = x0 - 1 + 2 * G2 -- Offsets for last corner in (x,y) unskewed coords
+	local y2 = y0 - 1 + 2 * G2
+	-- Work out the hashed gradient indices of the three simplex corners
+	local ii = bit32.band(i, 255)
+	local jj = bit32.band(j, 255)
+	local gi0 = perm[ii + perm[jj+1]+1] % 12
+	local gi1 = perm[ii + i1 + perm[jj + j1+1]+1] % 12
+	local gi2 = perm[ii + 1 + perm[jj + 1+1]+1] % 12
+	-- Calculate the contribution from the three corners
+	local t0 = 0.5 - x0 * x0 - y0 * y0
+	if t0 < 0 then
+		n0 = 0.0
+	else
+		t0 = t0 * t0
+		n0 = t0 * t0 * dot(grad3[gi0+1], x0, y0) -- (x,y) of grad3 used for 2D gradient
+	end
+	local t1 = 0.5 - x1 * x1 - y1 * y1
+	if t1 < 0 then
+		n1 = 0.0
+	else
+		t1 = t1 * t1
+		n1 = t1 * t1 * dot(grad3[gi1+1], x1, y1)
+	end
+	local t2 = 0.5 - x2 * x2 - y2 * y2
+	if t2 < 0 then
+		n2 = 0.0
+	else
+		t2 = t2 * t2
+		n2 = t2 * t2 * dot(grad3[gi2+1], x2, y2)
+	end
+	-- Add contributions from each corner to get the final noise value.
+	-- The result is scaled to return values in the interval [-1,1].
+	return 70.0 * (n0 + n1 + n2)
+end
+
+return Simplex
diff --git a/map_gen/terrain/neko_bridged_rivers.lua b/map_gen/terrain/neko_bridged_rivers.lua
index 9b8e772c..6f0176fa 100644
--- a/map_gen/terrain/neko_bridged_rivers.lua
+++ b/map_gen/terrain/neko_bridged_rivers.lua
@@ -1,178 +1,178 @@
-local perlin = require 'map_gen.shared.perlin_noise'
-local simplex = require 'map_gen.shared.simplex_noise'
-
-local tree_to_place = {'dry-tree', 'dry-hairy-tree', 'tree-06', 'tree-06', 'tree-01', 'tree-02', 'tree-03'}
-
-function run_terrain_module(event)
-    if not global.terrain_seed_A then
-        global.terrain_seed_A = math.random(10, 10000)
-    end
-    if not global.terrain_seed_B then
-        global.terrain_seed_B = math.random(10, 10000)
-    end
-
-    local area = event.area
-    local surface = event.surface
-    local tiles = {}
-    local tileswater = {}
-
-    local entities = surface.find_entities(area)
-    for _, entity in pairs(entities) do
-        --if entity.type == "simple-entity" or entity.type == "resource" or entity.type == "tree" then
-        if entity.type == 'simple-entity' or entity.type == 'tree' then
-            --end
-            entity.destroy()
-        elseif (run_ores_module ~= nil and entity.type == 'resource') then
-            entity.destroy()
-        end
-    end
-
-    local top_left = area.left_top --make a more direct reference
-
-    --do it only per chunk, cause cheaper than every square, and who care anyway.
-    --local distance_bonus = 200 + math.sqrt(top_left.x*top_left.x + top_left.y*top_left.y) * 0.2
-
-    --for x = 0, 31, 1 do
-    --	for y = 0, 31, 1 do
-
-    --game.print(top_left.x .."-" ..top_left.y .. " to " .. area.right_bottom.x .. "-" .. area.right_bottom.y)
-
-    for x = top_left.x - 1, top_left.x + 32 do
-        for y = top_left.y - 1, top_left.y + 32 do
-            --local pos_x = top_left.x + x
-            --local pos_y = top_left.y + y
-            local tile = surface.get_tile(x, y)
-
-            if tile.name ~= 'out-of-map' then
-                local tile_to_insert = 'grass-3'
-
-                local wiggle = 50 + perlin.noise((x * 0.005), (y * 0.005), global.terrain_seed_A + 71) * 60
-                local terrain_A = perlin.noise((x * 0.005), (y * 0.005), global.terrain_seed_A + 19) * wiggle --For determining where water is
-                local terrain_sqr = terrain_A * terrain_A --we can use this again to mess with other layers as well
-                local terrain_D = 10 + perlin.noise((x * 0.001), (y * 0.001), global.terrain_seed_A + 5) * wiggle --terrain layer
-
-                --local wiggle = 50 + Simplex.d2((x*0.005),(y*0.005),global.terrain_seed_A + 71) * 60
-                --local terrain_A = Simplex.d2((x*0.005),(y*0.005),global.terrain_seed_A + 19) * wiggle	--For determining where water is
-                --local terrain_sqr = terrain_A * terrain_A	--we can use this again to mess with other layers as well
-                --local terrain_D = 10 + Simplex.d2((x*0.001),(y*0.001),global.terrain_seed_A + 5) * wiggle	--terrain layer
-
-                if terrain_sqr < 50 then --Main water areas
-                    --local deep = (terrain_sqr < 20) and true or false
-                    terrain_A = perlin.noise((x * 0.01), (y * 0.01), global.terrain_seed_A + 31) * 90 + (wiggle * -0.2) --we only gen this when we consider placing water
-                    --terrain_A = Simplex.d2((x*0.01),(y*0.01),global.terrain_seed_A + 31) * 90 + (wiggle * -0.2)	--we only gen this when we consider placing water
-
-                    if terrain_A * terrain_A > 40 then --creates random bridges over the water by overlapping with another noise layer
-                        --table.insert(tileswater, {name = "water", position = {x,y}})
-                        --table.insert(tileswater, {name = "water", position = {x+1,y}})
-                        --table.insert(tileswater, {name = "water", position = {x,y+1}})
-                        --table.insert(tileswater, {name = "water", position = {x+1,y+1}})
-                        tile_to_insert = 'water'
-                    else
-                        if terrain_D >= 20 then
-                            tile_to_insert = 'sand-1'
-                        end
-                    end
-                elseif terrain_sqr > 70 then
-                    wiggle = 100 + perlin.noise((x * 0.01), (y * 0.01), global.terrain_seed_B + 41) * 60
-                    local terrain_C = perlin.noise((x * 0.02), (y * 0.02), global.terrain_seed_A + 13) * wiggle --tree layer
-
-                    --wiggle = 100 + Simplex.d2((x*0.01),(y*0.01),global.terrain_seed_B + 41) * 60
-                    --local terrain_C = Simplex.d2((x*0.02),(y*0.02),global.terrain_seed_A + 13) * wiggle	--tree layer
-
-                    --if surface.can_place_entity {name="stone", position={x,y}} then
-                    --	surface.create_entity {name="stone", position={x,y}, amount=math.floor(terrain_sqr)}
-                    --end
-
-                    if run_ores_module ~= nil then
-                        run_ores_module_setup()
-                        if x > top_left.x - 1 and x < top_left.x + 32 and y > top_left.y - 1 and y < top_left.y + 32 then
-                            run_ores_module_tile(surface, x, y)
-                        end
-                    end
-
-                    --if terrain_B > 35 then	--we place ores
-                    --	local a = 5
-                    --
-                    --	if terrain_B < 76 then a = math.floor(terrain_B*0.75 + terrain_C*0.5) % 4 + 1 end	--if its not super high we place normal ores
-                    --
-                    --	local res_amount = distance_bonus + terrain_sqr * 0.1
-                    --	res_amount = math.floor(res_amount * random_dense[a])
-                    --
-                    --	if surface.can_place_entity {name=random_ores[a], position={pos_x,pos_y}} then
-                    --		surface.create_entity {name=random_ores[a], position={pos_x,pos_y}, amount=res_amount}
-                    --	end
-                    --end
-
-                    --wiggle = 100 + perlin.noise((pos_x*0.02),(pos_y*0.02),global.terrain_seed_B + 71) * 60
-
-                    if terrain_D < 20 then
-                        if terrain_C < 4 then --we set grass-1 around near forest areas
-                            tile_to_insert = 'grass-1'
-
-                            if terrain_C < -20 and math.random(1, 3) == 1 then --dense trees
-                                local treenum = math.random(3, 7)
-                                if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
-                                    surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
-                                end
-                            else
-                                if terrain_C < 0 and math.random(1, 7) == 1 then --less dense trees
-                                    local treenum = math.random(3, 5)
-                                    if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
-                                        surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
-                                    end
-                                end
-                            end
-                        end
-                    else
-                        if terrain_D < 30 then
-                            tile_to_insert = 'sand-1'
-
-                            if terrain_C < -20 and math.random(1, 7) == 1 then --dense trees
-                                local treenum = math.random(1, 3)
-                                if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
-                                    surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
-                                end
-                            elseif terrain_C < 0 and math.random(1, 13) == 1 then --less dense trees
-                                local treenum = math.random(1, 2)
-                                if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
-                                    surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
-                                end
-                            end
-                        else
-                            --if terrain_C > 40 and math.random(1,200) == 1 and surface.can_place_entity {name="crude-oil", position={pos_x,pos_y}} then
-                            --	surface.create_entity {name="crude-oil", position={pos_x,pos_y}, amount = math.random(20000,60000) +distance_bonus* 2000 }
-                            --end
-                            tile_to_insert = 'sand-3'
-                        end
-                    end
-
-                    if
-                        math.floor(terrain_D) % 5 == 1 and math.random(1, 70) == 1 and
-                            surface.can_place_entity {name = 'rock-big', position = {x, y}}
-                     then
-                        surface.create_entity {name = 'rock-big', position = {x, y}}
-                    end
-                else
-                    if terrain_D >= 20 then
-                        if terrain_D < 30 then
-                            tile_to_insert = 'sand-1'
-                        else
-                            tile_to_insert = 'sand-3'
-                        end
-                    end
-                end
-
-                --if tile_to_insert == "water" then
-                --table.insert(tileswater, {name = tile_to_insert, position = {x,y}})
-                --else
-                table.insert(tiles, {name = tile_to_insert, position = {x, y}})
-            --end
-            end
-        end
-    end
-    --game.print("break end")
-    --game.print(lowest .. " to " .. highest)
-
-    surface.set_tiles(tiles, true)
-    --surface.set_tiles(tileswater,true)
-end
+local perlin = require 'map_gen.shared.perlin_noise'
+local simplex = require 'map_gen.shared.simplex_noise'
+
+local tree_to_place = {'dry-tree', 'dry-hairy-tree', 'tree-06', 'tree-06', 'tree-01', 'tree-02', 'tree-03'}
+
+function run_terrain_module(event)
+    if not global.terrain_seed_A then
+        global.terrain_seed_A = math.random(10, 10000)
+    end
+    if not global.terrain_seed_B then
+        global.terrain_seed_B = math.random(10, 10000)
+    end
+
+    local area = event.area
+    local surface = event.surface
+    local tiles = {}
+    local tileswater = {}
+
+    local entities = surface.find_entities(area)
+    for _, entity in pairs(entities) do
+        --if entity.type == "simple-entity" or entity.type == "resource" or entity.type == "tree" then
+        if entity.type == 'simple-entity' or entity.type == 'tree' then
+            --end
+            entity.destroy()
+        elseif (run_ores_module ~= nil and entity.type == 'resource') then
+            entity.destroy()
+        end
+    end
+
+    local top_left = area.left_top --make a more direct reference
+
+    --do it only per chunk, cause cheaper than every square, and who care anyway.
+    --local distance_bonus = 200 + math.sqrt(top_left.x*top_left.x + top_left.y*top_left.y) * 0.2
+
+    --for x = 0, 31, 1 do
+    --	for y = 0, 31, 1 do
+
+    --game.print(top_left.x .."-" ..top_left.y .. " to " .. area.right_bottom.x .. "-" .. area.right_bottom.y)
+
+    for x = top_left.x - 1, top_left.x + 32 do
+        for y = top_left.y - 1, top_left.y + 32 do
+            --local pos_x = top_left.x + x
+            --local pos_y = top_left.y + y
+            local tile = surface.get_tile(x, y)
+
+            if tile.name ~= 'out-of-map' then
+                local tile_to_insert = 'grass-3'
+
+                local wiggle = 50 + perlin.noise((x * 0.005), (y * 0.005), global.terrain_seed_A + 71) * 60
+                local terrain_A = perlin.noise((x * 0.005), (y * 0.005), global.terrain_seed_A + 19) * wiggle --For determining where water is
+                local terrain_sqr = terrain_A * terrain_A --we can use this again to mess with other layers as well
+                local terrain_D = 10 + perlin.noise((x * 0.001), (y * 0.001), global.terrain_seed_A + 5) * wiggle --terrain layer
+
+                --local wiggle = 50 + Simplex.d2((x*0.005),(y*0.005),global.terrain_seed_A + 71) * 60
+                --local terrain_A = Simplex.d2((x*0.005),(y*0.005),global.terrain_seed_A + 19) * wiggle	--For determining where water is
+                --local terrain_sqr = terrain_A * terrain_A	--we can use this again to mess with other layers as well
+                --local terrain_D = 10 + Simplex.d2((x*0.001),(y*0.001),global.terrain_seed_A + 5) * wiggle	--terrain layer
+
+                if terrain_sqr < 50 then --Main water areas
+                    --local deep = (terrain_sqr < 20) and true or false
+                    terrain_A = perlin.noise((x * 0.01), (y * 0.01), global.terrain_seed_A + 31) * 90 + (wiggle * -0.2) --we only gen this when we consider placing water
+                    --terrain_A = Simplex.d2((x*0.01),(y*0.01),global.terrain_seed_A + 31) * 90 + (wiggle * -0.2)	--we only gen this when we consider placing water
+
+                    if terrain_A * terrain_A > 40 then --creates random bridges over the water by overlapping with another noise layer
+                        --table.insert(tileswater, {name = "water", position = {x,y}})
+                        --table.insert(tileswater, {name = "water", position = {x+1,y}})
+                        --table.insert(tileswater, {name = "water", position = {x,y+1}})
+                        --table.insert(tileswater, {name = "water", position = {x+1,y+1}})
+                        tile_to_insert = 'water'
+                    else
+                        if terrain_D >= 20 then
+                            tile_to_insert = 'sand-1'
+                        end
+                    end
+                elseif terrain_sqr > 70 then
+                    wiggle = 100 + perlin.noise((x * 0.01), (y * 0.01), global.terrain_seed_B + 41) * 60
+                    local terrain_C = perlin.noise((x * 0.02), (y * 0.02), global.terrain_seed_A + 13) * wiggle --tree layer
+
+                    --wiggle = 100 + Simplex.d2((x*0.01),(y*0.01),global.terrain_seed_B + 41) * 60
+                    --local terrain_C = Simplex.d2((x*0.02),(y*0.02),global.terrain_seed_A + 13) * wiggle	--tree layer
+
+                    --if surface.can_place_entity {name="stone", position={x,y}} then
+                    --	surface.create_entity {name="stone", position={x,y}, amount=math.floor(terrain_sqr)}
+                    --end
+
+                    if run_ores_module ~= nil then
+                        run_ores_module_setup()
+                        if x > top_left.x - 1 and x < top_left.x + 32 and y > top_left.y - 1 and y < top_left.y + 32 then
+                            run_ores_module_tile(surface, x, y)
+                        end
+                    end
+
+                    --if terrain_B > 35 then	--we place ores
+                    --	local a = 5
+                    --
+                    --	if terrain_B < 76 then a = math.floor(terrain_B*0.75 + terrain_C*0.5) % 4 + 1 end	--if its not super high we place normal ores
+                    --
+                    --	local res_amount = distance_bonus + terrain_sqr * 0.1
+                    --	res_amount = math.floor(res_amount * random_dense[a])
+                    --
+                    --	if surface.can_place_entity {name=random_ores[a], position={pos_x,pos_y}} then
+                    --		surface.create_entity {name=random_ores[a], position={pos_x,pos_y}, amount=res_amount}
+                    --	end
+                    --end
+
+                    --wiggle = 100 + perlin.noise((pos_x*0.02),(pos_y*0.02),global.terrain_seed_B + 71) * 60
+
+                    if terrain_D < 20 then
+                        if terrain_C < 4 then --we set grass-1 around near forest areas
+                            tile_to_insert = 'grass-1'
+
+                            if terrain_C < -20 and math.random(1, 3) == 1 then --dense trees
+                                local treenum = math.random(3, 7)
+                                if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
+                                    surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
+                                end
+                            else
+                                if terrain_C < 0 and math.random(1, 7) == 1 then --less dense trees
+                                    local treenum = math.random(3, 5)
+                                    if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
+                                        surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
+                                    end
+                                end
+                            end
+                        end
+                    else
+                        if terrain_D < 30 then
+                            tile_to_insert = 'sand-1'
+
+                            if terrain_C < -20 and math.random(1, 7) == 1 then --dense trees
+                                local treenum = math.random(1, 3)
+                                if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
+                                    surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
+                                end
+                            elseif terrain_C < 0 and math.random(1, 13) == 1 then --less dense trees
+                                local treenum = math.random(1, 2)
+                                if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
+                                    surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
+                                end
+                            end
+                        else
+                            --if terrain_C > 40 and math.random(1,200) == 1 and surface.can_place_entity {name="crude-oil", position={pos_x,pos_y}} then
+                            --	surface.create_entity {name="crude-oil", position={pos_x,pos_y}, amount = math.random(20000,60000) +distance_bonus* 2000 }
+                            --end
+                            tile_to_insert = 'sand-3'
+                        end
+                    end
+
+                    if
+                        math.floor(terrain_D) % 5 == 1 and math.random(1, 70) == 1 and
+                            surface.can_place_entity {name = 'rock-big', position = {x, y}}
+                     then
+                        surface.create_entity {name = 'rock-big', position = {x, y}}
+                    end
+                else
+                    if terrain_D >= 20 then
+                        if terrain_D < 30 then
+                            tile_to_insert = 'sand-1'
+                        else
+                            tile_to_insert = 'sand-3'
+                        end
+                    end
+                end
+
+                --if tile_to_insert == "water" then
+                --table.insert(tileswater, {name = tile_to_insert, position = {x,y}})
+                --else
+                table.insert(tiles, {name = tile_to_insert, position = {x, y}})
+            --end
+            end
+        end
+    end
+    --game.print("break end")
+    --game.print(lowest .. " to " .. highest)
+
+    surface.set_tiles(tiles, true)
+    --surface.set_tiles(tileswater,true)
+end
diff --git a/utils/utils.lua b/utils/utils.lua
index cbc81df8..6995a863 100644
--- a/utils/utils.lua
+++ b/utils/utils.lua
@@ -1,157 +1,157 @@
-local Module = {}
-local Game = require 'utils.game'
-local prefix = '## - '
-
-Module.distance = function(pos1, pos2)
-    local dx = pos2.x - pos1.x
-    local dy = pos2.y - pos1.y
-    return math.sqrt(dx * dx + dy * dy)
-end
-
-Module.print_except = function(msg, player)
-    for _, p in pairs(game.players) do
-        if p.connected and p ~= player then
-            p.print(msg)
-        end
-    end
-end
-
--- Takes a LuaPlayer or string as source
-Module.print_admins = function(msg, source)
-    local source_name
-    local chat_color
-    if source then
-        if type(source) == 'string' then
-            source_name = source
-            chat_colot = game.players[source].chat_color
-        else
-            source_name = source.name
-            chat_color = source.chat_color
-        end
-    else
-        source_name = "Server"
-        chat_color = {r=255, g=255, b=255}
-    end
-    for _, p in pairs(game.connected_players) do
-        if p.admin then
-            p.print(string.format('%s(ADMIN) %s: %s', prefix, source_name, msg), chat_color)
-        end
-    end
-end
-
-Module.get_actor = function()
-    if game.player then
-        return game.player.name
-    end
-    return '<server>'
-end
-
-Module.cast_bool = function(var)
-    if var then
-        return true
-    else
-        return false
-    end
-end
-
-Module.find_entities_by_last_user =
-    function(player, surface, filters)
-    if type(player) == 'string' or not player then
-        error(
-            "bad argument #1 to '" ..
-                debug.getinfo(1, 'n').name .. "' (number or LuaPlayer expected, got " .. type(player) .. ')',
-            1
-        )
-        return
-    end
-    if type(surface) ~= 'table' and type(surface) ~= 'number' then
-        error(
-            "bad argument #2 to '" ..
-                debug.getinfo(1, 'n').name .. "' (number or LuaSurface expected, got " .. type(surface) .. ')',
-            1
-        )
-        return
-    end
-    local entities = {}
-    local surface = surface
-    local player = player
-    local filters = filters or {}
-    if type(surface) == 'number' then
-        surface = game.surfaces[surface]
-    end
-    if type(player) == 'number' then
-        player = Game.get_player_by_index(player)
-    end
-    filters.force = player.force.name
-    for _, e in pairs(surface.find_entities_filtered(filters)) do
-        if e.last_user == player then
-            table.insert(entities, e)
-        end
-    end
-    return entities
-end
-
-Module.ternary = function(c, t, f)
-    if c then
-        return t
-    else
-        return f
-    end
-end
-
-
-local minutes_to_ticks = 60 * 60
-local hours_to_ticks = 60 * 60 * 60
-local ticks_to_minutes = 1 / minutes_to_ticks
-local ticks_to_hours = 1 / hours_to_ticks
-Module.format_time = function(ticks)
-    local result = {}
-
-    local hours = math.floor(ticks * ticks_to_hours)
-    if hours > 0 then
-        ticks = ticks - hours * hours_to_ticks
-        table.insert(result, hours)
-        if hours == 1 then
-            table.insert(result, 'hour')
-        else
-            table.insert(result, 'hours')
-        end
-    end
-
-    local minutes = math.floor(ticks * ticks_to_minutes)
-    table.insert(result, minutes)
-    if minutes == 1 then
-        table.insert(result, 'minute')
-    else
-        table.insert(result, 'minutes')
-    end
-
-    return table.concat(result, ' ')
-end
-
-Module.cant_run = function(name)
-    Game.player_print("Can't run command (" .. name .. ') - insufficient permission.')
-end
-
-Module.log_command = function(user, command, parameters)
-    local name
-
-    -- We can use a LuaPlayer or a string (ex. "Server").
-    if type(user) == 'string' then
-        name = user
-    else
-        name = user.name
-    end
-    local action = table.concat {'[Admin-Command] ', name, ' used: ', command}
-    if parameters then
-        action = table.concat {'[Admin-Command] ', name, ' used: ', command, ' ', parameters}
-    end
-    log(action)
-end
-
-Module.comma_value = function(n) -- credit http://richard.warburton.it
-    local left,num,right = string.match(n, '^([^%d]*%d)(%d*)(.-)$')
-    return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right
-end
-
-return Module
+local Module = {}
+local Game = require 'utils.game'
+local prefix = '## - '
+
+Module.distance = function(pos1, pos2)
+    local dx = pos2.x - pos1.x
+    local dy = pos2.y - pos1.y
+    return math.sqrt(dx * dx + dy * dy)
+end
+
+Module.print_except = function(msg, player)
+    for _, p in pairs(game.players) do
+        if p.connected and p ~= player then
+            p.print(msg)
+        end
+    end
+end
+
+-- Takes a LuaPlayer or string as source
+Module.print_admins = function(msg, source)
+    local source_name
+    local chat_color
+    if source then
+        if type(source) == 'string' then
+            source_name = source
+            chat_colot = game.players[source].chat_color
+        else
+            source_name = source.name
+            chat_color = source.chat_color
+        end
+    else
+        source_name = "Server"
+        chat_color = {r=255, g=255, b=255}
+    end
+    for _, p in pairs(game.connected_players) do
+        if p.admin then
+            p.print(string.format('%s(ADMIN) %s: %s', prefix, source_name, msg), chat_color)
+        end
+    end
+end
+
+Module.get_actor = function()
+    if game.player then
+        return game.player.name
+    end
+    return '<server>'
+end
+
+Module.cast_bool = function(var)
+    if var then
+        return true
+    else
+        return false
+    end
+end
+
+Module.find_entities_by_last_user =
+    function(player, surface, filters)
+    if type(player) == 'string' or not player then
+        error(
+            "bad argument #1 to '" ..
+                debug.getinfo(1, 'n').name .. "' (number or LuaPlayer expected, got " .. type(player) .. ')',
+            1
+        )
+        return
+    end
+    if type(surface) ~= 'table' and type(surface) ~= 'number' then
+        error(
+            "bad argument #2 to '" ..
+                debug.getinfo(1, 'n').name .. "' (number or LuaSurface expected, got " .. type(surface) .. ')',
+            1
+        )
+        return
+    end
+    local entities = {}
+    local surface = surface
+    local player = player
+    local filters = filters or {}
+    if type(surface) == 'number' then
+        surface = game.surfaces[surface]
+    end
+    if type(player) == 'number' then
+        player = Game.get_player_by_index(player)
+    end
+    filters.force = player.force.name
+    for _, e in pairs(surface.find_entities_filtered(filters)) do
+        if e.last_user == player then
+            table.insert(entities, e)
+        end
+    end
+    return entities
+end
+
+Module.ternary = function(c, t, f)
+    if c then
+        return t
+    else
+        return f
+    end
+end
+
+
+local minutes_to_ticks = 60 * 60
+local hours_to_ticks = 60 * 60 * 60
+local ticks_to_minutes = 1 / minutes_to_ticks
+local ticks_to_hours = 1 / hours_to_ticks
+Module.format_time = function(ticks)
+    local result = {}
+
+    local hours = math.floor(ticks * ticks_to_hours)
+    if hours > 0 then
+        ticks = ticks - hours * hours_to_ticks
+        table.insert(result, hours)
+        if hours == 1 then
+            table.insert(result, 'hour')
+        else
+            table.insert(result, 'hours')
+        end
+    end
+
+    local minutes = math.floor(ticks * ticks_to_minutes)
+    table.insert(result, minutes)
+    if minutes == 1 then
+        table.insert(result, 'minute')
+    else
+        table.insert(result, 'minutes')
+    end
+
+    return table.concat(result, ' ')
+end
+
+Module.cant_run = function(name)
+    Game.player_print("Can't run command (" .. name .. ') - insufficient permission.')
+end
+
+Module.log_command = function(user, command, parameters)
+    local name
+
+    -- We can use a LuaPlayer or a string (ex. "Server").
+    if type(user) == 'string' then
+        name = user
+    else
+        name = user.name
+    end
+    local action = table.concat {'[Admin-Command] ', name, ' used: ', command}
+    if parameters then
+        action = table.concat {'[Admin-Command] ', name, ' used: ', command, ' ', parameters}
+    end
+    log(action)
+end
+
+Module.comma_value = function(n) -- credit http://richard.warburton.it
+    local left,num,right = string.match(n, '^([^%d]*%d)(%d*)(.-)$')
+    return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right
+end
+
+return Module