diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 334dac1cf7d5a79819550fbce2f0561c27f82fe5..2bf1b6ad8c63fa00570e3adfeff8cf18fcb32a36 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -6,3 +6,4 @@ add_subdirectory(cats_strings)
 add_subdirectory(cats_ini)
 add_subdirectory(cats_csv)
 add_subdirectory(modules/cats_test_module)
+add_subdirectory(modules/butterflies)
\ No newline at end of file
diff --git a/src/modules/butterflies/CMakeLists.txt b/src/modules/butterflies/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a9f3c1f0770d1bda90df1e7573698c7375479643
--- /dev/null
+++ b/src/modules/butterflies/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_library(cats-butterflies SHARED "" butterfly_actions.c butterfly_actions.h butterfly_vital_rates.c butterfly_vital_rates.h module.h butterflies_dispersal.c butterflies_dispersal.h butterflies_populations.c butterflies_populations.h)
+
+target_include_directories(cats-butterflies PUBLIC ".")
+
+target_sources(cats-butterflies
+        PRIVATE
+        butterflies_main.c butterflies_main.h random_walk.c random_walk.h
+
+        PUBLIC
+
+
+        )
+
+
+
+set_property(TARGET cats-butterflies PROPERTY POSITION_INDEPENDENT_CODE ON)
+target_link_libraries(cats-butterflies cats_logging libcats)
diff --git a/src/modules/butterflies/butterflies_dispersal.c b/src/modules/butterflies/butterflies_dispersal.c
new file mode 100644
index 0000000000000000000000000000000000000000..a30bbf1f40d012e77d6eb13c38436b0f7e3d9112
--- /dev/null
+++ b/src/modules/butterflies/butterflies_dispersal.c
@@ -0,0 +1,16 @@
+//
+// Created by gattringera on 21/11/22.
+//
+#include <math.h>
+#include "butterflies_main.h"
+#include "butterflies_dispersal.h"
+#include "configuration/configuration.h"
+#include "modules/module_header.h"
+
+void add_dispersed_eggs(struct cats_configuration *conf, struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, float eggs)
+{
+        //struct conf_data_butterflies *module_conf = CATS_MODULE_DATA;
+        const int module_id = CATS_MODULE_ID;
+        struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data;
+        data->eggs[row][col] += eggs;
+}
\ No newline at end of file
diff --git a/src/modules/butterflies/butterflies_dispersal.h b/src/modules/butterflies/butterflies_dispersal.h
new file mode 100644
index 0000000000000000000000000000000000000000..4017a409fb645905a05f0a7ab6a89f4dd153cad0
--- /dev/null
+++ b/src/modules/butterflies/butterflies_dispersal.h
@@ -0,0 +1,8 @@
+//
+// Created by gattringera on 21/11/22.
+//
+
+#ifndef CATS_BUTTERFLIES_DISPERSAL_H
+#define CATS_BUTTERFLIES_DISPERSAL_H
+
+#endif //CATS_BUTTERFLIES_DISPERSAL_H
diff --git a/src/modules/butterflies/butterflies_main.c b/src/modules/butterflies/butterflies_main.c
new file mode 100644
index 0000000000000000000000000000000000000000..5c9bfcff076a584355da10c51ee8e0354f368ad7
--- /dev/null
+++ b/src/modules/butterflies/butterflies_main.c
@@ -0,0 +1,80 @@
+#include <math.h>
+#include "modules/module_header.h"
+#include "butterflies_main.h"
+#include "configuration/load_configuration_species_params.h"
+#include "module.h"
+#include "actions/cats_actions.h"
+#include "butterfly_actions.h"
+#include "butterfly_vital_rates.h"
+#include "cats_ini/cats_ini.h"
+
+struct cats_global global;
+struct cats_debug_options cats_debug;
+
+
+void *butterfly_grid_init(struct cats_configuration *conf, struct cats_grid *grid, void *ignored)
+{
+        log_message(LOG_INFO, "%s: %s: grid init", module_name, __func__);
+        printf("%d %d\n", grid->dimension.cols, grid->dimension.rows);
+
+        struct grid_data_butterflies *data = malloc_or_die(sizeof(struct grid_data_butterflies));
+        log_message(LOG_INFO, "allocating data for generations");
+        data->generations = new_raw_2d_array_from_dimension(grid->dimension, sizeof(float));
+        log_message(LOG_INFO, "done allocating data for generations");
+        data->generation_current = 0;
+        //struct conf_data_butterflies *conf_data = CATS_MODULE_DATA;
+        data->eggs = new_raw_2d_array_from_dimension(grid->dimension, sizeof(float));
+
+
+        return data;
+}
+
+
+void *grid_cleanup(struct cats_configuration *conf, struct cats_grid *grid, void *data)
+{
+        log_message(LOG_INFO, "%s: grid cleanup", module_name);
+        assert(grid != NULL);
+        struct grid_data_butterflies *grid_data = data;
+        free_grid(&grid_data->generations, grid->dimension.rows);
+        free(grid_data->generations);
+        grid_data->generation_current = -1;
+        return NULL;
+}
+
+
+void load_butterflies_species_params(struct cats_configuration *conf, struct cats_ini *ini, const char *section_name,
+                                     struct cats_species_param *param)
+{
+        struct conf_data_butterflies *data = CATS_MODULE_DATA;
+        load_conf_vital_rate(&data->eggs_per_female, conf, ini, section_name, param);
+        load_conf_vital_rate(&data->butterfly_generations, conf, ini, section_name, param);
+        load_conf_vital_rate(&data->butterfly_egg_to_adult_survival, conf, ini, section_name, param);
+
+        //bool _get_int32_config_value(const struct cats_ini *ini, const char *section, const char *key, bool required, int32_t *value);
+        int32_t rw_max;
+        cats_dt_rates female_percentage;
+        load_conf_value(true, ini, section_name, "butterflies random walk steps maximum", &rw_max);
+        load_conf_value(true, ini, section_name, "butterflies female fraction", &female_percentage);
+        data->generations_max = (int32_t) ceill(data->butterfly_generations.max_rate);
+        if (! data->actions_added) {
+                add_actions(conf);
+                data->actions_added = true;
+        }
+
+}
+
+
+void cats_module_init(struct cats_configuration *conf)
+{
+        struct conf_data_butterflies *data = calloc_or_die(1,sizeof(struct conf_data_butterflies));
+        enum cats_module_flags flags = MODULE_ALTERNATE_DEMOGRAPHIC | MODULE_OVERRIDE_ACTIONS;
+        int32_t id = register_module(conf, module_name, data, flags);
+        register_cats_grid_init_function(conf, butterfly_grid_init, grid_cleanup);
+        register_load_species_param_config_func(conf, load_butterflies_species_params);
+        add_vital_rates(conf, data);
+
+
+        log_message(LOG_INFO, "Hello from %s (id: %d)\n", module_name, id);
+
+}
+
diff --git a/src/modules/butterflies/butterflies_main.h b/src/modules/butterflies/butterflies_main.h
new file mode 100644
index 0000000000000000000000000000000000000000..2a93c9cb762b625d042e5b5affadca7c3745a176
--- /dev/null
+++ b/src/modules/butterflies/butterflies_main.h
@@ -0,0 +1,29 @@
+#ifndef CATS_BUTTERFLIES_MAIN_H
+#define CATS_BUTTERFLIES_MAIN_H
+#include "cats_global.h"
+#include <stdint.h>
+#include "data/cats_datatypes.h"
+#include "vital_rates/vital_rates.h"
+
+struct grid_data_butterflies {
+        float **generations;
+        int32_t generation_current;
+        float **eggs;
+
+
+};
+
+struct conf_data_butterflies {
+
+        int32_t generations_max;
+        int32_t current_generation;
+        int32_t animal_dispersal_max_radius; ///< maximal flight/dispersal distance
+        cats_dt_rates egg_to_adult_survival_rate_maximum;
+        cats_dt_rates egg_per_female_maximum;
+        bool actions_added;
+        struct cats_vital_rate eggs_per_female;
+        struct cats_vital_rate butterfly_egg_to_adult_survival;
+        struct cats_vital_rate butterfly_generations;
+};
+
+#endif //CATS_BUTTERFLIES_MAIN_H
diff --git a/src/modules/butterflies/butterflies_populations.c b/src/modules/butterflies/butterflies_populations.c
new file mode 100644
index 0000000000000000000000000000000000000000..3ac7549b8f65dbf1e87f59a74851ae0cd7934a05
--- /dev/null
+++ b/src/modules/butterflies/butterflies_populations.c
@@ -0,0 +1,46 @@
+//
+// Created by gattringera on 21/11/22.
+//
+
+#include <assert.h>
+#include <math.h>
+#include "butterflies_populations.h"
+#include "data/cats_grid.h"
+#include "overlays/overlay_exclusion.h"
+#include "inline_overlays.h"
+#include "threading/threading-helpers.h"
+#include "modules/module_header.h"
+#include "butterflies_main.h"
+#include "inline_carrying_capacity.h"
+#include "inline_population.h"
+#include "inline.h"
+#include "misc/cats_random.h"
+#include "populations/population.h"
+void butterflies_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cats_dt_coord row, cats_dt_coord col, bool check_exclusion)
+{
+        const struct cats_configuration *conf = ts->conf;
+        if (check_exclusion && cell_excluded_by_overlay(conf, row, col)) return;
+
+        struct conf_data_butterflies *module_conf = CATS_MODULE_DATA;
+        const int module_id = CATS_MODULE_ID;
+        struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data;
+        int32_t local_max_generation = (int32_t) ceilf(data->generations[row][col]);
+        if (data->generation_current  > local_max_generation ) return;
+        if (data->eggs[row][col] == 0) return;
+
+        float proportion = 1.0f;
+        if (data->generation_current == local_max_generation && (float) local_max_generation > proportion) {
+                proportion = data->generations[row][col] - (float) local_max_generation;
+        }
+
+
+        assert (conf->grid_count == 1);
+        float eggs = proportion * data->eggs[row][col];
+        data->eggs[row][col] -= eggs;
+        cats_dt_rates maturation_rate = calculate_rate(&module_conf->butterfly_egg_to_adult_survival, NAN, &grid->param, grid, row, col, NULL);
+        cats_dt_population K = get_carrying_capacity(grid, row, col);
+        cats_dt_population adults = poisson_population_capped(ts->rng, eggs * proportion * maturation_rate, K);
+        set_population_ignore_cc(grid, row, col, adults);
+}
+
+
diff --git a/src/modules/butterflies/butterflies_populations.h b/src/modules/butterflies/butterflies_populations.h
new file mode 100644
index 0000000000000000000000000000000000000000..5babb7ec7ca98f7ef8d82479158e816c9d62cc61
--- /dev/null
+++ b/src/modules/butterflies/butterflies_populations.h
@@ -0,0 +1,9 @@
+//
+// Created by gattringera on 21/11/22.
+//
+
+#ifndef CATS_BUTTERFLIES_POPULATIONS_H
+#define CATS_BUTTERFLIES_POPULATIONS_H
+#include "data/cats_grid.h"
+void butterflies_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cats_dt_coord row, cats_dt_coord col, bool check_exclusion);
+#endif //CATS_BUTTERFLIES_POPULATIONS_H
diff --git a/src/modules/butterflies/butterfly_actions.c b/src/modules/butterflies/butterfly_actions.c
new file mode 100644
index 0000000000000000000000000000000000000000..e74afb51aff94e39a8c01c500ee5046f4f68eab0
--- /dev/null
+++ b/src/modules/butterflies/butterfly_actions.c
@@ -0,0 +1,172 @@
+
+#include "actions/cats_actions.h"
+#include "actions/setup_actions.h"
+#include "modules/module_header.h"
+#include "butterfly_actions.h"
+#include "module.h"
+#include "butterflies_main.h"
+#include "inline_overlays.h"
+#include "butterflies_populations.h"
+#include "inline_population.h"
+
+enum action_status action_butterfly_stats_reset(struct cats_grid *grid, struct cats_configuration *conf)
+{
+        return ACTION_RUN;
+}
+
+void grid_butterflies_maturation(struct cats_grid *grid, struct cats_thread_info *ts)
+{
+        struct cats_configuration *conf = ts->conf;
+        const cats_dt_coord start_row = ts->area.start_row;
+        const cats_dt_coord end_row = ts->area.end_row;
+
+        const cats_dt_coord start_col = ts->area.start_col;
+        const cats_dt_coord end_col = ts->area.end_col;
+
+        for (cats_dt_coord row = start_row; row < end_row; row++) {
+                for (cats_dt_coord col = start_col; col < end_col; col++) {
+                        if (cell_excluded_by_overlay(conf, row, col)) {
+                                continue;
+                        }
+                        butterflies_cell_maturation(grid, ts, row, col, false);
+                }
+        }
+}
+
+
+
+
+void grid_butterflies_kill_adults(struct cats_grid *grid, struct cats_thread_info *ts)
+{
+        const cats_dt_coord start_row = ts->area.start_row;
+        const cats_dt_coord end_row = ts->area.end_row;
+
+        const cats_dt_coord start_col = ts->area.start_col;
+        const cats_dt_coord end_col = ts->area.end_col;
+
+        for (cats_dt_coord row = start_row; row < end_row; row++) {
+                for (cats_dt_coord col = start_col; col < end_col; col++) {
+                        set_population_ignore_cc(grid, row, col, 0);
+                }
+        }
+}
+
+
+enum action_status action_butterflies_maturation(struct cats_grid *grid, struct cats_configuration *conf)
+{
+        threaded_action(&grid_butterflies_maturation, grid, conf, TS_DEFAULT);
+
+        return ACTION_RUN;
+}
+
+
+enum action_status action_butterflies_kill_adults(struct cats_grid *grid, struct cats_configuration *conf)
+{
+        threaded_action(&grid_butterflies_kill_adults, grid, conf, TS_DEFAULT);
+
+        return ACTION_RUN;
+}
+
+
+enum action_status action_butterflies_dispersal(struct cats_grid *grid, struct cats_configuration *conf)
+{
+        return ACTION_RUN;
+}
+
+enum action_status action_butterflies_output(struct cats_grid *grid, struct cats_configuration *conf)
+{
+        return ACTION_RUN;
+}
+
+enum action_status action_butterfly_stats_gather(struct cats_grid *grid, struct cats_configuration *conf)
+{
+        return ACTION_RUN;
+}
+
+enum action_status action_butterfly_stats_write(struct cats_grid *grid, struct cats_configuration *conf)
+{
+        return ACTION_RUN;
+}
+
+
+void grid_update_generations(struct cats_grid *grid, struct cats_thread_info *ts)
+{
+        struct cats_configuration *conf = ts->conf;
+
+
+        struct conf_data_butterflies *module_conf = CATS_MODULE_DATA;
+        int module_id = CATS_MODULE_ID;
+        struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data;
+        struct cats_vital_rate *rate = &module_conf->butterfly_generations;
+
+        const cats_dt_coord start_row = ts->area.start_row;
+        const cats_dt_coord end_row = ts->area.end_row;
+
+        const cats_dt_coord start_col = ts->area.start_col;
+        const cats_dt_coord end_col = ts->area.end_col;
+        for (cats_dt_coord row = start_row; row < end_row; row++) {
+                for (cats_dt_coord col = start_col; col < end_col; col++) {
+
+                        if (cell_excluded_by_overlay(conf, row, col)) {
+                                data->generations[row][col] = 0.0f;
+                                continue;
+                        }
+                        cats_dt_rates gen = calculate_rate(rate, 0, conf->param, grid, row, col, NULL);
+                        data->generations[row][col] = (float) gen;
+                        //printf("GENERATIONS::thread %03d:: %d %d %f\n", ts->id ,row, col, (float) gen);
+                }
+        }
+}
+
+enum action_status action_butterfly_update_generations(struct cats_grid *grid, struct cats_configuration *conf)
+{
+        struct conf_data_butterflies *data = CATS_MODULE_DATA;
+        data->
+        threaded_action(&grid_update_generations, grid, conf, TS_DEFAULT);
+        return ACTION_RUN;
+}
+
+enum action_status action_update_generation(struct cats_grid *grid, struct cats_configuration *conf)
+{
+        struct conf_data_butterflies *data = CATS_MODULE_DATA;
+        return ACTION_RUN;
+}
+
+void add_butterfly_generation_action(struct cats_configuration *conf, action_function function, const char *name, int generation)
+{
+        char *result = NULL;
+        int rc = asprintf(&result, "%s (generation %d)", name, generation);
+        asprintf_check(rc);
+        append_action(conf, function, ALL_STAGES, result, module_name);
+        free(result);
+}
+
+
+
+void add_actions(struct cats_configuration *conf)
+{
+        struct conf_data_butterflies *data = CATS_MODULE_DATA;
+        printf("MAXIMUM GENERATIONS %d\n", data->generations_max);
+
+        register_action_function(conf, action_butterfly_stats_reset, "butterfly_action_reset_stats", "resetting butterfly statistics");
+        register_action_function(conf, action_butterfly_update_generations, "butterfly_action_update_generations", "update generations");
+        register_action_function(conf, action_butterflies_maturation, "butterfly_action_egg_to_adult",
+                                 "transition eggs to adults");
+
+        register_action_function(conf, action_butterflies_dispersal, "butterfly_action_dispersal", "egg dispersal");
+        register_action_function(conf, action_butterflies_kill_adults, "butterfly_kill_adults", "kill adults");
+        list_actions_full(conf);
+
+
+        append_action(conf, action_butterfly_stats_reset, ALL_STAGES, "resetting butterfly statistics", module_name);
+        append_action_by_name(conf, "action_load_environments", ALL_STAGES,  "environment update", module_name);
+        append_action_by_name(conf, "action_overlay_update", ALL_STAGES, "overlay update", module_name);
+        append_action(conf, action_butterfly_update_generations, ALL_STAGES, "update generations", module_name);
+        for (int32_t generation = data->generations_max ; generation > 0 ; generation-- ) {
+                add_butterfly_generation_action(conf, action_update_generation, "update generation",  generation);
+                add_butterfly_generation_action(conf, action_butterflies_maturation, "transition eggs to adults",  generation);
+                add_butterfly_generation_action(conf, action_butterflies_dispersal, "dispersal",  generation);
+                add_butterfly_generation_action(conf, action_butterflies_kill_adults, "kill adults",  generation);
+        }
+
+}
\ No newline at end of file
diff --git a/src/modules/butterflies/butterfly_actions.h b/src/modules/butterflies/butterfly_actions.h
new file mode 100644
index 0000000000000000000000000000000000000000..95595768f3ea4c4434e5591dde82d7a881b85916
--- /dev/null
+++ b/src/modules/butterflies/butterfly_actions.h
@@ -0,0 +1,6 @@
+
+#ifndef CATS_BUTTERFLY_ACTIONS_H
+#define CATS_BUTTERFLY_ACTIONS_H
+#include "configuration/configuration.h"
+void add_actions(struct cats_configuration *conf);
+#endif //CATS_BUTTERFLY_ACTIONS_H
diff --git a/src/modules/butterflies/butterfly_vital_rates.c b/src/modules/butterflies/butterfly_vital_rates.c
new file mode 100644
index 0000000000000000000000000000000000000000..f40c73de5b166cdf7d1355ab36dea6102186c1b7
--- /dev/null
+++ b/src/modules/butterflies/butterfly_vital_rates.c
@@ -0,0 +1,25 @@
+
+
+#include "butterfly_vital_rates.h"
+
+void add_vital_rates(struct cats_configuration *conf,  struct conf_data_butterflies *data)
+{
+        // generations
+        register_module_vital_rate(conf, &data->butterfly_generations,"butterflies generations");
+        set_vital_rate_name(&data->butterfly_generations, "butterflies generations");
+        set_vital_rate_suitability_cutoff_hint(&data->butterfly_generations, HYBRID_SUIT_TS_ZT);
+        set_vital_rate_link_hybrid_function(&data->butterfly_generations, conf, LINK_SUITABILITY_SIGMOID);
+
+        // eggs
+        register_module_vital_rate(conf, &data->eggs_per_female, "butterflies eggs per female");
+        set_vital_rate_name(&data->eggs_per_female, "butterflies eggs per female");
+        set_vital_rate_suitability_cutoff_hint(&data->eggs_per_female, HYBRID_SUIT_TS_ZT);
+        set_vital_rate_link_hybrid_function(&data->eggs_per_female, conf, LINK_SUITABILITY_SIGMOID);
+
+        // egg to adult survival
+        register_module_vital_rate(conf, &data->butterfly_egg_to_adult_survival,"butterflies egg to adult survival rate");
+        set_vital_rate_name(&data->butterfly_egg_to_adult_survival, "butterflies eggs to adult survival rate");
+        set_vital_rate_suitability_cutoff_hint(&data->butterfly_egg_to_adult_survival, HYBRID_SUIT_TS_ZT);
+        set_vital_rate_link_hybrid_function(&data->butterfly_egg_to_adult_survival, conf, LINK_SUITABILITY_SIGMOID);
+        set_vital_density(&data->butterfly_egg_to_adult_survival, DENSITY_DEP_NEGATIVE);
+}
diff --git a/src/modules/butterflies/butterfly_vital_rates.h b/src/modules/butterflies/butterfly_vital_rates.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab32c356889e4fb62fe9e1764b1fee6b7f12e81a
--- /dev/null
+++ b/src/modules/butterflies/butterfly_vital_rates.h
@@ -0,0 +1,10 @@
+
+#ifndef CATS_BUTTERFLY_VITAL_RATES_H
+#define CATS_BUTTERFLY_VITAL_RATES_H
+#include "configuration/configuration.h"
+#include "butterflies_main.h"
+#include "vital_rates/setup_rates.h"
+#include "modules/module_header.h"
+
+void add_vital_rates(struct cats_configuration *conf,  struct conf_data_butterflies *data) ;
+#endif //CATS_BUTTERFLY_VITAL_RATES_H
diff --git a/src/modules/butterflies/module.h b/src/modules/butterflies/module.h
new file mode 100644
index 0000000000000000000000000000000000000000..02ce2be565ffc98fe6d576ff673ef7857bd8217b
--- /dev/null
+++ b/src/modules/butterflies/module.h
@@ -0,0 +1,6 @@
+
+
+#ifndef CATS_MODULE_H
+#define CATS_MODULE_H
+static const char *module_name = "cats-butterflies";
+#endif //CATS_MODULE_H
diff --git a/src/modules/butterflies/random_walk.c b/src/modules/butterflies/random_walk.c
new file mode 100644
index 0000000000000000000000000000000000000000..22b263f0303bac2a60d1f8dd9e7c5502a892c0f1
--- /dev/null
+++ b/src/modules/butterflies/random_walk.c
@@ -0,0 +1,17 @@
+//
+// Created by gattringera on 22/06/22.
+//
+
+#include "random_walk.h"
+
+void random_step(struct cats_grid *grid, cats_dt_coord start_row, cats_dt_coord col)
+{
+
+
+}
+
+
+void random_walk(struct cats_configuration *conf, struct cats_grid *grid)
+{
+
+}
diff --git a/src/modules/butterflies/random_walk.h b/src/modules/butterflies/random_walk.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab3a7d59db481d3325ff8dc4625af50a9faa04fc
--- /dev/null
+++ b/src/modules/butterflies/random_walk.h
@@ -0,0 +1,4 @@
+#ifndef CATS_RANDOM_WALK_H
+#define CATS_RANDOM_WALK_H
+#include "cats/configuration/configuration.h"
+#endif //CATS_RANDOM_WALK_H