<commit_before>#include "game/state/rules/battle/battlemap.h"
#include "game/state/battle/battle.h"
#include "game/state/battle/battledoor.h"
#include "game/state/battle/battleitem.h"
#include "game/state/battle/battlemappart.h"
#include "game/state/battle/battlescanner.h"
#include "game/state/battle/battleunit.h"
#include "game/state/city/base.h"
#include "game/state/city/building.h"
#include "game/state/city/facility.h"
#include "game/state/city/vehicle.h"
#include "game/state/gamestate.h"
#include "game/state/rules/aequipmenttype.h"
#include "game/state/rules/battle/battlecommonsamplelist.h"
#include "game/state/rules/battle/battlemapparttype.h"
#include "game/state/rules/battle/battlemaptileset.h"
#include "game/state/rules/city/vehicletype.h"
#include "game/state/shared/aequipment.h"
#include "game/state/shared/agent.h"
#include "game/state/shared/organisation.h"
#include <algorithm>
#include <unordered_map>

namespace OpenApoc
{

namespace
{
int getCorridorSectorID(sp<Base> base, Vec2<int> pos)
{
	// key is North South West East (true = occupied, false = vacant)
	const std::unordered_map<std::vector<bool>, int> TILE_CORRIDORS = {
	    {{false, false, false, false}, 3}, {{true, false, false, false}, 4},
	    {{false, false, false, true}, 5},  {{true, false, false, true}, 6},
	    {{false, true, false, false}, 7},  {{true, true, false, false}, 8},
	    {{false, true, false, true}, 9},   {{true, true, false, true}, 10},
	    {{false, false, true, false}, 11}, {{true, false, true, false}, 12},
	    {{false, false, true, true}, 13},  {{true, false, true, true}, 14},
	    {{false, true, true, false}, 15},  {{true, true, true, false}, 16},
	    {{false, true, true, true}, 17},   {{true, true, true, true}, 18}};

	if (pos.x < 0 || pos.y < 0 || pos.x >= Base::SIZE || pos.y >= Base::SIZE)
	{
		LogError("Going out of bounds for base");
		return 0;
	}
	else if (!base->corridors[pos.x][pos.y])
	{
		// We need to cap any facilities
		// For that we need to find where facilities are
		std::vector<std::vector<bool>> facilities;
		facilities.resize(Base::SIZE);
		for (int i = 0; i < Base::SIZE; i++)
		{
			facilities[i].resize(Base::SIZE);
		}
		for (auto &facility : base->facilities)
		{
			if (facility->buildTime > 0)
			{
				continue;
			}
			for (int x = 0; x < facility->type->size; x++)
			{
				for (int y = 0; y < facility->type->size; y++)
				{
					facilities[facility->pos.x + x][facility->pos.y + y] = true;
				}
			}
		}

		bool north = pos.y > 0 && facilities[pos.x][pos.y - 1];
		bool south = pos.y < Base::SIZE - 1 && facilities[pos.x][pos.y + 1];
		bool west = pos.x > 0 && facilities[pos.x - 1][pos.y];
		bool east = pos.x < Base::SIZE - 1 && facilities[pos.x + 1][pos.y];
		return TILE_CORRIDORS.at({north, south, west, east}) - 3;
		return 0;
	}
	else
	{
		bool north = pos.y > 0 && base->corridors[pos.x][pos.y - 1];
		bool south = pos.y < Base::SIZE - 1 && base->corridors[pos.x][pos.y + 1];
		bool west = pos.x > 0 && base->corridors[pos.x - 1][pos.y];
		bool east = pos.x < Base::SIZE - 1 && base->corridors[pos.x + 1][pos.y];
		return TILE_CORRIDORS.at({north, south, west, east}) - 3 + 15;
	}
}
}

BattleMap::BattleMap() {}

sp<BattleMap> BattleMap::get(const GameState &state, const UString &id)
{
	auto it = state.battle_maps.find(id);
	if (it == state.battle_maps.end())
	{
		LogError("No battle_map matching ID \"%s\"", id);
		return nullptr;
	}
	return it->second;
}

const UString &BattleMap::getPrefix()
{
	static UString prefix = "BATTLEMAP_";
	return prefix;
}
const UString &BattleMap::getTypeName()
{
	static UString name = "BattleMap";
	return name;
}
const UString &BattleMap::getId(const GameState &state, const sp<BattleMap> ptr)
{
	static const UString emptyString = "";
	for (auto &a : state.battle_maps)
	{
		if (a.second == ptr)
			return a.first;
	}
	LogError("No battle_map matching pointer %p", ptr.get());
	return emptyString;
}

// Create UFO battle
sp<Battle> BattleMap::createBattle(GameState &state, StateRef<Organisation> opponent,
                                   std::list<StateRef<Agent>> &player_agents,
                                   const std::map<StateRef<AgentType>, int> *aliens,
                                   StateRef<Vehicle> player_craft, StateRef<Vehicle> target_craft)
{
	if (!aliens)
	{
		aliens = &target_craft->type->crew_downed;
	}
	auto alienOrg = state.getAliens();

	int countAliens = 0;
	for (auto &a : *aliens)
	{
		for (int i = 0; i < a.second; i++)
		{
			player_agents.push_back(state.agent_generator.createAgent(state, alienOrg, a.first));
			if (++countAliens >= MAX_UNITS_PER_SIDE)
			{
				break;
			}
		}
		if (countAliens >= MAX_UNITS_PER_SIDE)
		{
			break;
		}
	}

	return target_craft->type->battle_map->createBattle(
	    state, target_craft->owner, opponent, player_agents, player_craft,
	    Battle::MissionType::UfoRecovery, target_craft.id);
}

// Create building battle
sp<Battle> BattleMap::createBattle(GameState &state, StateRef<Organisation> opponent,
                                   std::list<StateRef<Agent>> &player_agents,
                                   const std::map<StateRef<AgentType>, int> *aliens,
                                   const int *guards, const int *civilians,
                                   StateRef<Vehicle> player_craft, StateRef<Building> building)
{
	std::list<std::pair<StateRef<Organisation>, StateRef<AgentType>>> otherParticipants;
	auto missionType = Battle::MissionType::AlienExtermination;

	std::map<StateRef<AgentType>, int> current_crew;
	StateRef<BattleMap> map;

	// Setup mission type and other participants
	if (building->owner == state.getPlayer())
	{
		// Base defense mission
		map = {&state, "BATTLEMAP_37base"};

		if (opponent == state.getAliens() && !aliens)
		{<commit_msg>No base error fixed #400<commit_after>#include "game/state/rules/battle/battlemap.h"
#include "game/state/battle/battle.h"
#include "game/state/battle/battledoor.h"
#include "game/state/battle/battleitem.h"
#include "game/state/battle/battlemappart.h"
#include "game/state/battle/battlescanner.h"
#include "game/state/battle/battleunit.h"
#include "game/state/city/base.h"
#include "game/state/city/building.h"
#include "game/state/city/facility.h"
#include "game/state/city/vehicle.h"
#include "game/state/gamestate.h"
#include "game/state/rules/aequipmenttype.h"
#include "game/state/rules/battle/battlecommonsamplelist.h"
#include "game/state/rules/battle/battlemapparttype.h"
#include "game/state/rules/battle/battlemaptileset.h"
#include "game/state/rules/city/vehicletype.h"
#include "game/state/shared/aequipment.h"
#include "game/state/shared/agent.h"
#include "game/state/shared/organisation.h"
#include <algorithm>
#include <unordered_map>

namespace OpenApoc
{

namespace
{
int getCorridorSectorID(sp<Base> base, Vec2<int> pos)
{
	// key is North South West East (true = occupied, false = vacant)
	const std::unordered_map<std::vector<bool>, int> TILE_CORRIDORS = {
	    {{false, false, false, false}, 3}, {{true, false, false, false}, 4},
	    {{false, false, false, true}, 5},  {{true, false, false, true}, 6},
	    {{false, true, false, false}, 7},  {{true, true, false, false}, 8},
	    {{false, true, false, true}, 9},   {{true, true, false, true}, 10},
	    {{false, false, true, false}, 11}, {{true, false, true, false}, 12},
	    {{false, false, true, true}, 13},  {{true, false, true, true}, 14},
	    {{false, true, true, false}, 15},  {{true, true, true, false}, 16},
	    {{false, true, true, true}, 17},   {{true, true, true, true}, 18}};

	if (pos.x < 0 || pos.y < 0 || pos.x >= Base::SIZE || pos.y >= Base::SIZE)
	{
		LogError("Going out of bounds for base");
		return 0;
	}
	else if (!base->corridors[pos.x][pos.y])
	{
		// We need to cap any facilities
		// For that we need to find where facilities are
		std::vector<std::vector<bool>> facilities;
		facilities.resize(Base::SIZE);
		for (int i = 0; i < Base::SIZE; i++)
		{
			facilities[i].resize(Base::SIZE);
		}
		for (auto &facility : base->facilities)
		{
			if (facility->buildTime > 0)
			{
				continue;
			}
			for (int x = 0; x < facility->type->size; x++)
			{
				for (int y = 0; y < facility->type->size; y++)
				{
					facilities[facility->pos.x + x][facility->pos.y + y] = true;
				}
			}
		}

		bool north = pos.y > 0 && facilities[pos.x][pos.y - 1];
		bool south = pos.y < Base::SIZE - 1 && facilities[pos.x][pos.y + 1];
		bool west = pos.x > 0 && facilities[pos.x - 1][pos.y];
		bool east = pos.x < Base::SIZE - 1 && facilities[pos.x + 1][pos.y];
		return TILE_CORRIDORS.at({north, south, west, east}) - 3;
		return 0;
	}
	else
	{
		bool north = pos.y > 0 && base->corridors[pos.x][pos.y - 1];
		bool south = pos.y < Base::SIZE - 1 && base->corridors[pos.x][pos.y + 1];
		bool west = pos.x > 0 && base->corridors[pos.x - 1][pos.y];
		bool east = pos.x < Base::SIZE - 1 && base->corridors[pos.x + 1][pos.y];
		return TILE_CORRIDORS.at({north, south, west, east}) - 3 + 15;
	}
}
}

BattleMap::BattleMap() {}

sp<BattleMap> BattleMap::get(const GameState &state, const UString &id)
{
	auto it = state.battle_maps.find(id);
	if (it == state.battle_maps.end())
	{
		LogError("No battle_map matching ID \"%s\"", id);
		return nullptr;
	}
	return it->second;
}

const UString &BattleMap::getPrefix()
{
	static UString prefix = "BATTLEMAP_";
	return prefix;
}
const UString &BattleMap::getTypeName()
{
	static UString name = "BattleMap";
	return name;
}
const UString &BattleMap::getId(const GameState &state, const sp<BattleMap> ptr)
{
	static const UString emptyString = "";
	for (auto &a : state.battle_maps)
	{
		if (a.second == ptr)
			return a.first;
	}
	LogError("No battle_map matching pointer %p", ptr.get());
	return emptyString;
}

// Create UFO battle
sp<Battle> BattleMap::createBattle(GameState &state, StateRef<Organisation> opponent,
                                   std::list<StateRef<Agent>> &player_agents,
                                   const std::map<StateRef<AgentType>, int> *aliens,
                                   StateRef<Vehicle> player_craft, StateRef<Vehicle> target_craft)
{
	if (!aliens)
	{
		aliens = &target_craft->type->crew_downed;
	}
	auto alienOrg = state.getAliens();

	int countAliens = 0;
	for (auto &a : *aliens)
	{
		for (int i = 0; i < a.second; i++)
		{
			player_agents.push_back(state.agent_generator.createAgent(state, alienOrg, a.first));
			if (++countAliens >= MAX_UNITS_PER_SIDE)
			{
				break;
			}
		}
		if (countAliens >= MAX_UNITS_PER_SIDE)
		{
			break;
		}
	}

	return target_craft->type->battle_map->createBattle(
	    state, target_craft->owner, opponent, player_agents, player_craft,
	    Battle::MissionType::UfoRecovery, target_craft.id);
}

// Create building battle
sp<Battle> BattleMap::createBattle(GameState &state, StateRef<Organisation> opponent,
                                   std::list<StateRef<Agent>> &player_agents,
                                   const std::map<StateRef<AgentType>, int> *aliens,
                                   const int *guards, const int *civilians,
                                   StateRef<Vehicle> player_craft, StateRef<Building> building)
{
	std::list<std::pair<StateRef<Organisation>, StateRef<AgentType>>> otherParticipants;
	auto missionType = Battle::MissionType::AlienExtermination;

	std::map<StateRef<AgentType>, int> current_crew;
	StateRef<BattleMap> map;

	// Setup mission type and other participants
	if (building->base != nullptr && building->owner == state.getPlayer())
	{
		// Base defense mission
		map = {&state, "BATTLEMAP_37base"};

		if (opponent == state.getAliens() && !aliens)
		{
{'fraction_non_alphanumeric': 0.1653726708074534, 'fraction_numerical': 0.010265700483091788, 'mean_word_length': 3.482985305491106, 'pattern_counts': {'":': 0, '<': 89, '<?xml version=': 0, '>': 130, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6328721', 'n_tokens_mistral': 4490, 'n_tokens_neox': 4151, 'n_words': 946}