


class IAction
{
public:
	virtual ~IAction() {}
	virtual void action()=0;
};


// 敵を探し、見つけたら攻撃する行動パターン

class SearchAndDestroy : public IAction
{
public:
	void action()
	{
		if(isEnemyInSight()) {
			if(isEnemyInAttackRange())
				attack();
			else
				approach();
		}
		else {
			patrol();
		}
	}

protected:
	virtual bool isEnemyInSight()=0;
	virtual bool isEnemyInAttackRange()=0;
	virtual void attack()=0;
	virtual void approach()=0;
	virtual void patrol()=0;
};


// 基本的に上のと同じだけど、敵を見つけたとき危機的状況だったら逃げ出す行動パターン

class ChickenSearchAndDestroy : public SearchAndDestroy
{
public:
	void action()
	{
		if(isEnemyInSight()) {
			if(isPinch())
				runAway();
			else if(isEnemyInAttackRange())
				attack();
			else
				approach();
		}
		else {
			patrol();
		}
	}

protected:
	virtual void runAway()=0;
	virtual bool isPinch()=0;
};










// 以下、使用例



#include <boost/smart_ptr.hpp>
using namespace boost;




template <class T, class U>
class TSearchAndDestroy : public T
{
public:
	typedef T base_class;
	typedef U gobj_type;

	TSearchAndDestroy(gobj_type *go_) : go(go_) {}

protected:
	gobj_type *go;

	bool isEnemyInSight()       { return go->isEnemyInSight(); }
	bool isEnemyInAttackRange() { return go->isEnemyInAttackRange(); }
	void attack()   { go->attack(); }
	void approach() { go->approach(); }
	void patrol()   { go->patrol(); }

	bool isPinch()  { return go->isPinch(); }
	void runAway()  { go->runAway(); }
};




class IGameObject
{
public:
	virtual ~IGameObject() {}
	virtual void update()=0;
};


class ChickenEnemy : public IGameObject
{
public:
	typedef scoped_ptr<IAction> action_ptr;

	ChickenEnemy() {
		action.reset(new TSearchAndDestroy<ChickenSearchAndDestroy, ChickenEnemy>(this));
	}
	void update() { action->action(); }

	// 公開されてるゲーム内情報と自分の状態を使って以下をどっかに適当に定義。今回は略。
	bool isEnemyInSight();
	bool isEnemyInAttackRange();
	void attack();
	void approach();
	void patrol();
	void runAway();
	bool isPinch();

private:
	action_ptr action;
};


