Forgot to commit the source changes in the last commit. Sorry. So, here they are.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5999 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
feynman
2013-04-14 15:54:56 +00:00
parent 25de719d79
commit 8f3bff764b
26 changed files with 11543 additions and 9871 deletions
@@ -0,0 +1,77 @@
/**
* @file
* @author feynman (bears-pit.com)
*/
#ifndef ABSTRACT_PLAN_FACTORY_H_
#define ABSTRACT_PLAN_FACTORY_H_
class SOLDIERTYPE;
namespace AI
{
namespace tactical
{
/**@class AIInputData
* @brief Wrapper class around the environmental data required to build an AI plan
*
* At the moment, simply a wrapper around SOLDIERTYPE. Future versions might require more data; without the
* wrapper, *every* Concrete Factory ever created would need to be changed in this event. With the wrapper, no
* change is required at all.
*/
struct AIInputData
{
SOLDIERTYPE* npc_to_plan_for_;
};
class Plan;
/**@class AbstractPlanFactory
* @brief Abstract Factory. Base class for all plan factories.
*
* The Abstract Factory design pattern is used to create instances of Plan object hierarchies. The concrete
* factories differ not necessarily in the concrete product they produce (as is otherwise the case when using
* this design pattern), but in the structure of the compositions (plans are Composites) instead. Public
* inheritance is required for two reasons: (a) several sub-class instances are packed in a container, and this
* abstract class serves as the container's data type. And (b) implementation of create_plan() and update_plan()
* is forced for concrete subclasses.
*/
class AbstractPlanFactory
{
private:
bool initialize_called_;
public:
AbstractPlanFactory() : initialize_called_(false) { }
bool initialize_called() const { return initialize_called_; }
/**@brief Used for delayed initialization of ressource-intensive initialization tasks
*
* Due to the design of the modularized AI, each factory's constructor must be called, even if the
* factory is not used. Therefore, memory- and cpu intensive tasks should not be performed in the
* constructor, but in this function instead. It will only be called if the factory is actually
* referenced in the AI.ini file.
*/
virtual void initialize() { };
/**@brief Abstract Plan object hierarchy creation function
*
* The subclasses (i.e., Concrete Factories) implpmenting this routine contain
* the decision-making AI core.
*
* @param input A pointer to a structure containing all required input data in order for the AI
* algorithms to perform their task. At the moment, simply a wrapper around SOLDIERTYPE. Future versions
* might require other datatypes; without the wrapper, *every* Concrete Factory ever created would need
* to be changed in this event.
* @return A Plan object tree representing the produced strategy
*/
virtual Plan* create_plan(const AIInputData& input) = 0;
/**@brief Abstract Plan object hierarchy update function, called in order to update an already created
* plan
*
* @param input A pointer to a structure containing all required input data in order for the AI
* algorithms to perform their task
* @param plan_to_change The Plan object hierarchy that is to be updated
*/
virtual void update_plan(const AIInputData& input, Plan* plan_to_change) = 0;
};
}
}
#endif
@@ -0,0 +1,32 @@
/**
* @file
* @author feynman (bears-pit.com)
*/
#ifndef LEGACY_AI_PLAN_H_
#define LEGACY_AI_PLAN_H_
#include "Plan.h"
namespace AI
{
namespace tactical
{
/**@class LegacyAIPlan
* @brief Component/Concrete Product. Generates a Plan that executes the AI as it was before modularization.
*
* A simple encapsulation of the functions TurnBasedHandleNPCAI() and RTHandleAI(), defined in
* TacticalAI/AIMain.cpp and TacticalAI/Realtime.cpp, respectively. The AI handles decisions for all kinds of
* NPCs (enemies, zombies, civilians, ...)
*/
class LegacyAIPlan: public Plan
{
private:
public:
virtual void execute(bool turn_based, PlanInputData& manipulated_object);
};
}
}
#endif
@@ -0,0 +1,32 @@
/**
* @file
* @author feynman (bears-pit.com)
*/
#ifndef LEGACY_AI_PLAN_FACTORY_H_
#define LEGACY_AI_PLAN_FACTORY_H_
#include "AbstractPlanFactory.h"
#include <string>
namespace AI
{
namespace tactical
{
/**@class LegacyAIPlanFactory
* @brief Concrete Factory. Generates the LegacyAIPlan, making NPCs do exactly what it did before this AI
* modularization/re-write.
*/
class LegacyAIPlanFactory : public AbstractPlanFactory
{
private:
public:
static std::string get_name() {return "LegacyAIPlanFactory";}
virtual Plan* create_plan(const AIInputData& input);
virtual void update_plan(const AIInputData& input, Plan* plan_to_change);
};
}
}
#endif
+41
View File
@@ -0,0 +1,41 @@
/**
* @file
* @author feynman (bears-pit.com)
*/
#ifndef NULL_PLAN_H_
#define NULL_PLAN_H_
#include "Plan.h"
namespace AI
{
namespace tactical
{
/**@class NullPlan
* @brief Component/Concrete Product. The NullPlan lets makes the NPC executing it do absolutely nothing.
*
* The purpose of this plan is two-fold. Firstly, it is a good starting point for new plans; to use it
* as such, perform a
* - \c svn copy include/NullPlan.h include/YourPlan.h
* - \c svn copy src/NullPlan.cpp src/YourPlan.cpp
*
* Remember to
*
* - Adjust the include guards
* - A concrete factory using this plan is required in order for it to be used
*
* And secondly, it is a debugging tool (cf. NullPlanFactory)
*/
class NullPlan: public Plan
{
private:
public:
virtual void execute(bool turn_based, PlanInputData& manipulated_object);
};
}
}
#endif
@@ -0,0 +1,46 @@
/**
* @file
* @author feynman (bears-pit.com)
*/
#ifndef NULL_PLAN_FACTORY_H_
#define NULL_PLAN_FACTORY_H_
#include "AbstractPlanFactory.h"
#include <string>
namespace AI
{
namespace tactical
{
/**@class NullPlanFactory
* @brief Concrete Factory. Generates the NullPlan, making a NPC do absolutely nothing.
*
* The purpose of this factory is two-fold. Firstly, it is a good starting point for new plan factories; to use
* it as such, perform a
* \c svn copy include/NullPlanFactory.h include/YourPlanFactory.h\n
* \c svn copy src/NullPlanFactory.cpp src/YourPlanFactory.cpp
*
* Remember to
* - Adjust the include guards
* - Adjust the string returned by get_name()
* - Add a line in PlanFactoryLibrary.cpp to create an instance of the new factory in the library's
* constructor; otherwise, it won't be accessible via the configuration file.
*
* And secondly, it is a debugging tool. Change the configuration file to use this AI factory for a certain
* AI_INDEX to have said group do... nothing (e.g. to measure performance differences).
*/
class NullPlanFactory : public AbstractPlanFactory
{
private:
public:
static std::string get_name() {return "NullPlanFactory";}
virtual Plan* create_plan(const AIInputData& input);
virtual void update_plan(const AIInputData& input, Plan* plan_to_change);
};
}
}
#endif
+52
View File
@@ -0,0 +1,52 @@
/**
* @file
* @author feynman (bears-pit.com)
*/
#ifndef PLAN_H_
#define PLAN_H_
class SOLDIERTYPE;
namespace AI
{
namespace tactical
{
/**@class PlanInputData
* @brief Wrapper class around the entity manipulated through plan execution
*
* At the moment, simply a wrapper around SOLDIERTYPE. Future versions might require other datatypes; without
* the wrapper, *every* Plan subclass ever created would need to be changed in this event. With the wrapper, no
* change is required at all.
*/
struct PlanInputData
{
SOLDIERTYPE* controlled_npc_;
};
/**@class Plan
* @brief Composite/Abstract Product. Base class for all plan compositions and components.
*
* The Plan class provides a common interface for both plan compositions and plan components.
*/
class Plan
{
private:
public:
/** @brief Plan execution is the encapsulation of an action sequence, making up higher-level building blocks
*
* Each plan objects represents a high-level action, implemented by means of lower-level actions. These
* lower level actions can be other Plans subtypes; at some point, a Plan object has no further
* sub-plans, i.e., the objet is no composition, but a component, forming a leaf in the Plan hierarchy.
* The components' lower level actions are formed by the fundamental npc actions made available outside
* the AI framework.
*
* @param turn_based true if turn-based mode is active, false for real-time mode
* @param manipulated_object Encapsulation of around object(s) a plan may manipulate.
*/
virtual void execute(bool turn_based, PlanInputData& manipulated_object) = 0;
};
}
}
#endif
@@ -0,0 +1,42 @@
/**
* @file
* @author feynman (bears-pit.com)
*/
#ifndef PLAN_FACTORY_LIBRARY_H_
#define PLAN_FACTORY_LIBRARY_H_
#include <string>
#include <map>
#include <deque>
namespace AI
{
namespace tactical
{
// forward declarations
class AbstractPlanFactory;
class Plan;
struct AIInputData;
/**@class PlanFactoryLibrary
* @brief Singleton. A "library" containing all available PlanFactories, accessible via the strings returned by
* their get_name() function.
*
*/
class PlanFactoryLibrary
{
private:
static PlanFactoryLibrary* instance_;
std::map<std::string, AbstractPlanFactory*> registred_factories_;
std::deque<AbstractPlanFactory*> ai_index_to_factory_mapping_;
PlanFactoryLibrary();
public:
static PlanFactoryLibrary* instance();
Plan* create_plan(size_t index, AIInputData& input) const;
};
}
}
#endif