<commit_before>
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "butterfly.h"
#include "internal.h"

static int ensure_farm_is_init(struct bf_farm *farm)
{
	struct butterfly *bf;
	struct point point;
	int x, y;

	if (farm->is_init) {
		return 0;
	}

	farm->rng_state = malloc(sizeof(struct random_state));
	if (!farm->rng_state) {
		goto rng_state_failure;
	}
	if (!farm->seed) {
		farm->seed = time(NULL);
	}
	random_seed(farm->rng_state, farm->seed);

	farm->safe_spots = malloc(sizeof(struct pointset));
	if (!farm->safe_spots) {
		goto safe_spots_alloc_failure;
	}
	if (ps_init(farm->safe_spots, farm->width, farm->height)) {
		goto safe_spots_init_failure;
	}

	farm->dangerous_spots = malloc(sizeof(struct pointset));
	if (!farm->dangerous_spots) {
		goto dangerous_spots_alloc_failure;
	}
	if (ps_init(farm->dangerous_spots, farm->width, farm->height)) {
		goto dangerous_spots_init_failure;
	}

	for (x = 0; x < farm->width; ++x) {
		for (y = 0; y < farm->height; ++y) {
			point = (struct point){x, y};
			if (IS_SAFE_AT(farm, x, y)) {
				ps_add(farm->safe_spots, point);
			} else {
				ps_add(farm->dangerous_spots, point);
			}
		}
	}

	farm->butterfly = malloc(sizeof(struct butterfly));
	if (!farm->butterfly) {
		goto butterfly_alloc_failure;
	}
	bf = farm->butterfly;

	memset(bf, 0, sizeof(*bf));
	bf->new_spots = malloc(
		sizeof(*bf->new_spots) * farm->width * farm->height);
	if (!bf->new_spots) {
		goto butterfly_new_spots_alloc_failure;
	}
	memcpy(
		bf->new_spots,
		farm->spots,
		sizeof(*bf->new_spots) * farm->width * farm->height);

	farm->is_init = 1;
	return 0;

butterfly_new_spots_alloc_failure:
	free(farm->butterfly);
butterfly_alloc_failure:
	ps_uninit(farm->dangerous_spots);
dangerous_spots_init_failure:
	free(farm->dangerous_spots);
dangerous_spots_alloc_failure:
	ps_uninit(farm->safe_spots);
safe_spots_init_failure:
	free(farm->safe_spots);
safe_spots_alloc_failure:
	free(farm->rng_state);
rng_state_failure:
	return -1;
}

static void reset_butterfly(
	struct butterfly *bf,
	struct bf_farm *farm,
	bool full)
{
	if (full) {
		memcpy(
			bf->new_spots,
			farm->spots,
			sizeof(*bf->new_spots) * farm->width * farm->height);
	}
	free(bf->path_data);
	bf->path_data = NULL;
	bf->has_goal = false;
	bf->death_timer = 0;
}

static void copy_instincts_with_event(
	struct bf_instinct *dst,
	size_t *dstcount,
	struct bf_instinct *src,
	size_t srccount,
	int action_start, int action_end)
{
	size_t i, j;
	*dstcount = 0;

	for (i = 0; i < srccount; ++i) {
		if (	src[i].action >= action_start &&
			src[i].action <= action_end) {
			dst[*dstcount].action = src[i].action;
			for (j = 0; j < BF_NARGS; ++j) {
				dst[*dstcount].args[j] =
					src[i].args[j];
			}
			++(*dstcount);
		}
	}
}

static void do_morph_actions(
	struct butterfly *bf,
	struct bf_farm *farm,
	struct bf_instinct *instincts,
	size_t count)
{
	struct bf_instinct morphs[count];
	size_t nmorphs;
	size_t r;

	copy_instincts_with_event(
		morphs, &nmorphs,
		instincts, count,
		BF_MORPH_START, BF_MORPH_END);

	if (nmorphs == 0) {
		return;
	}

	r = random_next_index(farm->rng_state, nmorphs);
	morph(bf, farm, &morphs[r]);
}

static void do_goal_actions(
	struct butterfly *bf,
	struct bf_farm *farm,
	struct bf_instinct *instincts,
	size_t count)
{
	struct bf_instinct goals[count];
	size_t ngoals;
	size_t r;

	copy_instincts_with_event(
		goals, &ngoals,
		instincts, count,
		BF_GOAL_START, BF_GOAL_END);

	if (ngoals == 0) {
		return;
	}

	r = random_next_index(farm->rng_state, ngoals);
	goal(bf, farm, &goals[r]);
}

static bool check_if_should_die(
	struct butterfly *bf,
	struct bf_farm *farm,
	struct bf_instinct *instincts,
	size_t count)
{
	struct bf_instinct deaths[count];
	size_t ndeaths;
	size_t i;
	bool should_die = false;

	copy_instincts_with_event(
		deaths, &ndeaths,
		instincts, count,
		BF_DIE_START, BF_DIE_END);

	if (ndeaths == 0) {
		bf->error = BF_ERROR_NO_DEATH;
		return;
	}

	for (i = 0; i < ndeaths; ++i) {
		/* ensure each check is run */
		should_die = should_die || die(bf, farm, &deaths[i]);
	}

	return should_die;
}

static void do_look_actions(
	struct butterfly *bf,
	struct bf_farm *farm,
	struct bf_instinct *instincts,
	size_t count)
{
	struct bf_instinct looks[count];
	size_t nlooks;
	size_t r;
	static size_t c = 0;

	copy_instincts_with_event(
		looks, &nlooks,<commit_msg>add error on no death instinct.<commit_after>
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "butterfly.h"
#include "internal.h"

static int ensure_farm_is_init(struct bf_farm *farm)
{
	struct butterfly *bf;
	struct point point;
	int x, y;

	if (farm->is_init) {
		return 0;
	}

	farm->rng_state = malloc(sizeof(struct random_state));
	if (!farm->rng_state) {
		goto rng_state_failure;
	}
	if (!farm->seed) {
		farm->seed = time(NULL);
	}
	random_seed(farm->rng_state, farm->seed);

	farm->safe_spots = malloc(sizeof(struct pointset));
	if (!farm->safe_spots) {
		goto safe_spots_alloc_failure;
	}
	if (ps_init(farm->safe_spots, farm->width, farm->height)) {
		goto safe_spots_init_failure;
	}

	farm->dangerous_spots = malloc(sizeof(struct pointset));
	if (!farm->dangerous_spots) {
		goto dangerous_spots_alloc_failure;
	}
	if (ps_init(farm->dangerous_spots, farm->width, farm->height)) {
		goto dangerous_spots_init_failure;
	}

	for (x = 0; x < farm->width; ++x) {
		for (y = 0; y < farm->height; ++y) {
			point = (struct point){x, y};
			if (IS_SAFE_AT(farm, x, y)) {
				ps_add(farm->safe_spots, point);
			} else {
				ps_add(farm->dangerous_spots, point);
			}
		}
	}

	farm->butterfly = malloc(sizeof(struct butterfly));
	if (!farm->butterfly) {
		goto butterfly_alloc_failure;
	}
	bf = farm->butterfly;

	memset(bf, 0, sizeof(*bf));
	bf->new_spots = malloc(
		sizeof(*bf->new_spots) * farm->width * farm->height);
	if (!bf->new_spots) {
		goto butterfly_new_spots_alloc_failure;
	}
	memcpy(
		bf->new_spots,
		farm->spots,
		sizeof(*bf->new_spots) * farm->width * farm->height);

	farm->is_init = 1;
	return 0;

butterfly_new_spots_alloc_failure:
	free(farm->butterfly);
butterfly_alloc_failure:
	ps_uninit(farm->dangerous_spots);
dangerous_spots_init_failure:
	free(farm->dangerous_spots);
dangerous_spots_alloc_failure:
	ps_uninit(farm->safe_spots);
safe_spots_init_failure:
	free(farm->safe_spots);
safe_spots_alloc_failure:
	free(farm->rng_state);
rng_state_failure:
	return -1;
}

static void reset_butterfly(
	struct butterfly *bf,
	struct bf_farm *farm,
	bool full)
{
	if (full) {
		memcpy(
			bf->new_spots,
			farm->spots,
			sizeof(*bf->new_spots) * farm->width * farm->height);
	}
	free(bf->path_data);
	bf->path_data = NULL;
	bf->has_goal = false;
	bf->death_timer = 0;
}

static void copy_instincts_with_event(
	struct bf_instinct *dst,
	size_t *dstcount,
	struct bf_instinct *src,
	size_t srccount,
	int action_start, int action_end)
{
	size_t i, j;
	*dstcount = 0;

	for (i = 0; i < srccount; ++i) {
		if (	src[i].action >= action_start &&
			src[i].action <= action_end) {
			dst[*dstcount].action = src[i].action;
			for (j = 0; j < BF_NARGS; ++j) {
				dst[*dstcount].args[j] =
					src[i].args[j];
			}
			++(*dstcount);
		}
	}
}

static void do_morph_actions(
	struct butterfly *bf,
	struct bf_farm *farm,
	struct bf_instinct *instincts,
	size_t count)
{
	struct bf_instinct morphs[count];
	size_t nmorphs;
	size_t r;

	copy_instincts_with_event(
		morphs, &nmorphs,
		instincts, count,
		BF_MORPH_START, BF_MORPH_END);

	if (nmorphs == 0) {
		return;
	}

	r = random_next_index(farm->rng_state, nmorphs);
	morph(bf, farm, &morphs[r]);
}

static void do_goal_actions(
	struct butterfly *bf,
	struct bf_farm *farm,
	struct bf_instinct *instincts,
	size_t count)
{
	struct bf_instinct goals[count];
	size_t ngoals;
	size_t r;

	copy_instincts_with_event(
		goals, &ngoals,
		instincts, count,
		BF_GOAL_START, BF_GOAL_END);

	if (ngoals == 0) {
		return;
	}

	r = random_next_index(farm->rng_state, ngoals);
	goal(bf, farm, &goals[r]);
}

static bool check_if_should_die(
	struct butterfly *bf,
	struct bf_farm *farm,
	struct bf_instinct *instincts,
	size_t count)
{
	struct bf_instinct deaths[count];
	size_t ndeaths;
	size_t i;
	bool should_die = false;

	copy_instincts_with_event(
		deaths, &ndeaths,
		instincts, count,
		BF_DIE_START, BF_DIE_END);

	if (ndeaths == 0) {
		bf->error = BF_ERROR_NO_DEATH;
		return true;
	}

	for (i = 0; i < ndeaths; ++i) {
		/* ensure each check is run */
		should_die = should_die || die(bf, farm, &deaths[i]);
	}

	return should_die;
}

static void do_look_actions(
	struct butterfly *bf,
	struct bf_farm *farm,
	struct bf_instinct *instincts,
	size_t count)
{
	struct bf_instinct looks[count];
	size_t nlooks;
	size_t r;
	static size_t c = 0;

	copy_instincts_with_event(
		looks, &nlooks,
{'fraction_non_alphanumeric': 0.14147002371005984, 'fraction_numerical': 0.003612961499379022, 'mean_word_length': 4.501863354037267, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 123, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6109760', 'n_tokens_mistral': 4109, 'n_tokens_neox': 3750, 'n_words': 753}