/*
 *	s e t u p N e w A u x i l i a r y Q P
 */
returnValue SQProblem::setupNewAuxiliaryQP(	const real_t* const H_new, const real_t* const A_new,
											const real_t *lb_new, const real_t *ub_new, const real_t *lbA_new, const real_t *ubA_new
											)
{
	int_t nV = getNV( );
	int_t nC = getNC( );

	DenseMatrix *dA = 0;
	SymDenseMat *sH = 0;

	if ( A_new != 0 )
	{
		dA = new DenseMatrix(nC, nV, nV, (real_t*) A_new);
	}
	else
	{
		if ( nC > 0 )
			return THROWERROR( RET_INVALID_ARGUMENTS );
	}

	if ( H_new != 0 )
		sH = new SymDenseMat(nV, nV, nV, (real_t*) H_new);

	returnValue returnvalue = setupNewAuxiliaryQP( sH,dA, lb_new,ub_new,lbA_new,ubA_new );

	if ( H_new != 0 )
		freeHessian = BT_TRUE;
	freeConstraintMatrix = BT_TRUE;

	return returnvalue;
}
示例#2
0
int32_t pkCU::movePriority_Bracket()
{
	// SOURCE: http://www.smogon.com/dp/articles/move_priority
	
	 /* action:
	 * AT_MOVE_0-3: pokemon's move
	 * AT_MOVE_STRUGGLE  : struggle
	 * AT_MOVE_NOTHING  : do nothing
	 * AT_SWITCH_0-5: pokemon switches out for pokemon n-6
	 * AT_ITEM_USE: pokemon uses an item (not implemented)
	 */
	
	// team:
	// 0 - a
	// 1 - b

	int32_t actionResult = 0;
	const environment_volatile& base = getBase().getEnv();
	size_t iCAction = getICAction();
	size_t iCTeam = getICTeam();
	
	// if the pokemon is switching out, its move priority is +6
	switch(iActions[0])
	{
		case AT_SWITCH_0:
		case AT_SWITCH_1:
		case AT_SWITCH_2:
		case AT_SWITCH_3:
		case AT_SWITCH_4:
		case AT_SWITCH_5:
			actionResult = 6;
			break;
		case AT_MOVE_0:
		case AT_MOVE_1:
		case AT_MOVE_2:
		case AT_MOVE_3:
		{
			// if the pokemon is performing a move, find the move's priority
			actionResult = (int32_t) getNV().getTeam(iCTeam).getPKNV(base.getTeam(iCTeam)).getMove_base(iCAction).getSpeedPriority();
			
			//script - modify movePriority - action
			int result = 0;
			CALLPLUGIN(result, PLUGIN_ON_SETSPEEDBRACKET, onModifyBracket_rawType, 
				*this, getPKNV().getMove_base(iCAction), getPKNV(), getTMV(), getPKV(), actionResult);
			break;
		}
		case AT_MOVE_NOTHING:
			actionResult = -7;
			break;
		case AT_MOVE_STRUGGLE:
		case AT_ITEM_USE:
		default:
			actionResult = 0;
			break;
	}
	
	return actionResult;
}
示例#3
0
文件: dense_cp.cpp 项目: rtkg/acado
Vector DenseCP::getMergedDualSolution( ) const
{
	Vector dualSolution( getNV()+getNC() );

	uint i;
	for( i=0; i<getNV(); ++i )
	{
		if ( acadoIsGreater( fabs( (*ylb)(i) ),1e-10 ) == BT_TRUE )
			dualSolution(i) = (*ylb)(i);
		else
			dualSolution(i) = (*yub)(i);
	}

	for( i=0; i<getNC(); ++i )
	{
		if ( acadoIsGreater( fabs( (*ylbA)(i) ),1e-10 ) == BT_TRUE )
			dualSolution( getNV()+i ) = (*ylbA)(i);
		else
			dualSolution( getNV()+i ) = (*yubA)(i);
	}

	return dualSolution;
}
示例#4
0
size_t pkCU::insertPluginHandler(plugin_t& cPlugin, size_t pluginType, size_t iNTeammate)
{
	size_t numAdded = 0;

	uint32_t target = cPlugin.target;
	size_t iNTeam = (iNTeammate>=6)?1:0;
	size_t iTeammate = iNTeammate - 6*iNTeam;

	for (size_t iNCTeammate = 0; iNCTeammate != pluginSets.size(); ++iNCTeammate)
	{
		size_t iCTeam = iNCTeammate >= 6;
		size_t iCTeammate = iNCTeammate - 6*iCTeam;
		// don't add to a teammate that doesn't exist:
		if ((iCTeammate) >= getNV().getTeam(iCTeam).getNumTeammates()) { continue; }

		if ((target==TEAM_A) && (iCTeam != iNTeam)) { continue; }
		else if ((target==TEAM_B) && (iCTeam == iNTeam)) { continue; }

		//if on team of adding team, only match to this teammate. Otherwise match to all teammates
		if ((iNTeammate != SIZE_MAX) && (iNTeam == iCTeam) && (iTeammate != iCTeammate)) { continue; }

		for (size_t iOTeammate = 0; iOTeammate != getNV().getOtherTeam(iCTeam).getNumTeammates(); ++iOTeammate)
		{
			// if on opposite team of adding team, and not add
			if ((iNTeammate != SIZE_MAX) && (iCTeam != iNTeam) && (iTeammate != iOTeammate)) { continue; }

			std::vector<plugin_t>& _cPluginSet = pluginSets[iNCTeammate][iOTeammate][pluginType];
			// check for duplicate:
			if (std::find(_cPluginSet.begin(), _cPluginSet.end(), cPlugin) != _cPluginSet.end()) { continue; }
			// add:
			_cPluginSet.push_back(cPlugin);
			numAdded++;
		}
	}

	return numAdded;
}
示例#5
0
文件: dense_cp.cpp 项目: rtkg/acado
returnValue DenseCP::setQPsolution( const Vector &x_, const Vector &y_ ){

    uint run1;
    clean();

    ASSERT( x_.getDim() == getNV()           );
    ASSERT( y_.getDim() == getNV() + getNC() );


    // SET THE PRIMAL SOLUTION:
    // ------------------------
    x = new Vector(x_);


    // SET THE DUAL SOLUTION FOR THE BOUNDS:
    // -------------------------------------
    ylb = new Vector( getNV() );
    yub = new Vector( getNV() );

    for( run1 = 0; run1 < getNV(); run1++ ){
        if( fabs(x_(run1)-lb(run1)) <= BOUNDTOL ){
            ylb->operator()(run1) = y_(run1);
            yub->operator()(run1) = 0.0     ;
        }
        else{
            ylb->operator()(run1) = 0.0     ;
            yub->operator()(run1) = y_(run1);
        }
    }


    // SET THE DUAL SOLUTION FOR THE CONSTRAINTS:
    // ------------------------------------------
    Vector tmp = A*x_;
    ylbA = new Vector( getNC() );
    yubA = new Vector( getNC() );

    for( run1 = 0; run1 < getNC(); run1++ ){
        if( fabs(tmp(run1)-lbA(run1)) <= BOUNDTOL ){
            ylbA->operator()(run1) = y_(getNV()+run1);
            yubA->operator()(run1) = 0.0             ;
        }
        else{
            ylbA->operator()(run1) = 0.0             ;
            yubA->operator()(run1) = y_(getNV()+run1);
        }
    }


    return SUCCESSFUL_RETURN;
}
示例#6
0
/*
 *	s e t u p A u x i l i a r y Q P
 */
returnValue SQProblem::setupAuxiliaryQP( const real_t* const H_new, const real_t* const A_new,
    const real_t *lb_new, const real_t *ub_new, const real_t *lbA_new, const real_t *ubA_new )
{
	int nV = getNV( );
	int nC = getNC( );

	DenseMatrix *dA = new DenseMatrix(nC, nV, nV, (real_t*) A_new);
	SymDenseMat *sH = new SymDenseMat(nV, nV, nV, (real_t*) H_new);

	returnValue returnvalue = setupAuxiliaryQP ( sH, dA, lb_new, ub_new, lbA_new, ubA_new );

	if ( H_new != 0 )
		freeHessian = BT_TRUE;
	freeConstraintMatrix = BT_TRUE;

	return returnvalue;
}
示例#7
0
/*
 *	s e t u p A u x i l i a r y Q P
 */
returnValue SQProblem::setupAuxiliaryQP ( SymmetricMatrix *H_new, Matrix *A_new,
    const real_t *lb_new, const real_t *ub_new, const real_t *lbA_new, const real_t *ubA_new
)
{

	int i;
	int nV = getNV( );
	int nC = getNC( );
	returnValue returnvalue;

	if ( ( getStatus( ) == QPS_NOTINITIALISED )       ||
		 ( getStatus( ) == QPS_PREPARINGAUXILIARYQP ) ||
		 ( getStatus( ) == QPS_PERFORMINGHOMOTOPY )   )
	{
		return THROWERROR( RET_UPDATEMATRICES_FAILED_AS_QP_NOT_SOLVED );
	}

	status = QPS_PREPARINGAUXILIARYQP;


	/* I) SETUP NEW QP MATRICES AND VECTORS: */
	/* 1) Shift constraints' bounds vectors by (A_new - A)'*x_opt to ensure
	 *    that old optimal solution remains feasible for new QP data. */
	/*    Firstly, shift by -A'*x_opt and ... */
	if ( nC > 0 )
	{
		if ( A_new == 0 )
			return THROWERROR( RET_INVALID_ARGUMENTS );

		for ( i=0; i<nC; ++i )
		{
			lbA[i] = -Ax_l[i];
			ubA[i] =  Ax_u[i];
		}

		/* Set constraint matrix as well as ... */
		setA( A_new );

		/* ... secondly, shift by +A_new'*x_opt. */
		for ( i=0; i<nC; ++i )
		{
			lbA[i] += Ax[i];
			ubA[i] += Ax[i];
		}

		/* update constraint products. */
		for ( i=0; i<nC; ++i )
		{
			Ax_u[i] = ubA[i] - Ax[i];
			Ax_l[i] = Ax[i] - lbA[i];
		}
	}

	/* 2) Set new Hessian matrix, determine Hessian type and
	 *    regularise new Hessian matrix if necessary. */
	/* a) Setup new Hessian matrix and determine its type. */
	if ( H_new != 0 )
	{
		setH( H_new );

		hessianType = HST_UNKNOWN;
		if ( determineHessianType( ) != SUCCESSFUL_RETURN )
			return THROWERROR( RET_SETUP_AUXILIARYQP_FAILED );

		/* b) Regularise new Hessian if necessary. */
		if ( ( hessianType == HST_ZERO ) ||
			 ( hessianType == HST_SEMIDEF ) ||
			 ( usingRegularisation( ) == BT_TRUE ) )
		{
			regVal = 0.0; /* reset previous regularisation */

			if ( regulariseHessian( ) != SUCCESSFUL_RETURN )
				return THROWERROR( RET_SETUP_AUXILIARYQP_FAILED );
		}
	}
	else
	{
		if ( H != 0 )
			return THROWERROR( RET_NO_HESSIAN_SPECIFIED );
	}

	/* 3) Setup QP gradient. */
	if ( setupAuxiliaryQPgradient( ) != SUCCESSFUL_RETURN )
		return THROWERROR( RET_SETUP_AUXILIARYQP_FAILED );


	/* II) SETUP WORKING SETS AND MATRIX FACTORISATIONS: */
	/* 1) Make a copy of current bounds/constraints ... */
	Bounds      oldBounds      = bounds;
	Constraints oldConstraints = constraints;

    /* we're trying to find an active set with positive definite null
     * space Hessian twice:
     * - first for the current active set including all equalities
     * - second after moving all inactive variables to a bound
     *   (depending on Options). This creates an empty null space and
     *   is guaranteed to succeed. Thus this loop will exit after n_try=1.
     */
    int n_try;
    for (n_try = 0; n_try < 2; ++n_try) {

        if (n_try > 0) {
            // the current active set leaves an indefinite null space Hessian
            // move all inactive variables to a bound, creating an empty null space
            for (int ii = 0; ii < nV; ++ii)
                if (oldBounds.getStatus (ii) == ST_INACTIVE)
                    oldBounds.setStatus (ii, options.initialStatusBounds);
        }

        /*    ... reset them ... */
        bounds.init( nV );
        constraints.init( nC );

        /*    ... and set them up afresh. */
        if ( setupSubjectToType(lb_new,ub_new,lbA_new,ubA_new ) != SUCCESSFUL_RETURN )
            return THROWERROR( RET_SETUP_AUXILIARYQP_FAILED );

        if ( bounds.setupAllFree( ) != SUCCESSFUL_RETURN )
            return THROWERROR( RET_SETUP_AUXILIARYQP_FAILED );

        if ( constraints.setupAllInactive( ) != SUCCESSFUL_RETURN )
            return THROWERROR( RET_SETUP_AUXILIARYQP_FAILED );

        /* 2) Setup TQ factorisation. */
        if ( setupTQfactorisation( ) != SUCCESSFUL_RETURN )
            return THROWERROR( RET_SETUP_AUXILIARYQP_FAILED );

		// check for equalities that have become bounds ...
		for (int ii = 0; ii < nC; ++ii) {
			if (oldConstraints.getType (ii) == ST_EQUALITY && constraints.getType (ii) == ST_BOUNDED) {
				if (oldConstraints.getStatus (ii) == ST_LOWER && y[nV+ii] < 0.0)
					oldConstraints.setStatus (ii, ST_UPPER);
				else if (oldConstraints.getStatus (ii) == ST_UPPER && y[nV+ii] > 0.0)
					oldConstraints.setStatus (ii, ST_LOWER);
			}
		}

		// ... and do the same also for the bounds!
		for (int ii = 0; ii < nV; ++ii) {
			if (oldBounds.getType(ii) == ST_EQUALITY
					&& bounds.getType(ii) == ST_BOUNDED) {
				if (oldBounds.getStatus(ii) == ST_LOWER && y[ii] < 0.0)
					oldBounds.setStatus(ii, ST_UPPER);
				else if (oldBounds.getStatus(ii) == ST_UPPER && y[ii] > 0.0)
					oldBounds.setStatus(ii, ST_LOWER);
			}
		}

        /* 3) Setup old working sets afresh (updating TQ factorisation). */
        if ( setupAuxiliaryWorkingSet( &oldBounds,&oldConstraints,BT_TRUE ) != SUCCESSFUL_RETURN )
            return THROWERROR( RET_SETUP_AUXILIARYQP_FAILED );

        /* Factorise projected Hessian
        * this now handles all special cases (no active bounds/constraints, no nullspace) */
        returnvalue = computeProjectedCholesky( );

        /* leave the loop if decomposition was successful, i.e. we have
         * found an active set with positive definite null space Hessian */
        if ( returnvalue == SUCCESSFUL_RETURN )
            break;
    }

    /* adjust lb/ub if we changed the old active set in the second try
     */
    if (n_try > 0) {
		// as per setupAuxiliaryQPbounds assumptions ... oh the troubles
		for (int ii = 0; ii < nC; ++ii)
			Ax_l[ii] = Ax_u[ii] = Ax[ii];
        setupAuxiliaryQPbounds (&bounds, &constraints, BT_FALSE);
	}

	status = QPS_AUXILIARYQPSOLVED;

	return SUCCESSFUL_RETURN;
}
示例#8
0
/*
 *	h o t s t a r t
 */
returnValue SQProblem::hotstart(	const char* const H_file, const char* const g_file, const char* const A_file,
									const char* const lb_file, const char* const ub_file,
									const char* const lbA_file, const char* const ubA_file,
									int& nWSR, real_t* const cputime
									)
{
	int nV = getNV( );
	int nC = getNC( );

	returnValue returnvalue;

	/* consistency checks */
	if ( ( H_file == 0 ) || ( g_file == 0 ) )
		return THROWERROR( RET_INVALID_ARGUMENTS );

	if ( ( nC > 0 ) && ( A_file == 0 ) )
		return THROWERROR( RET_INVALID_ARGUMENTS );


	/* 1) Load new QP matrices from files. */
	real_t* H_new  = new real_t[nV*nV];
	real_t* A_new  = new real_t[nC*nV];

	if ( readFromFile( H_new, nV,nV, H_file ) != SUCCESSFUL_RETURN )
		return THROWERROR( RET_UNABLE_TO_READ_FILE );

	if ( readFromFile( A_new, nC,nV, A_file ) != SUCCESSFUL_RETURN )
		return THROWERROR( RET_UNABLE_TO_READ_FILE );

	/* 2) Load new QP vectors from files. */
	real_t* g_new  = new real_t[nV];
	real_t* lb_new = 0;
	real_t* ub_new = 0;
	real_t* lbA_new = 0;
	real_t* ubA_new = 0;

	if ( lb_file != 0 )
		lb_new = new real_t[nV];
	if ( ub_file != 0 )
		ub_new = new real_t[nV];
	if ( lbA_file != 0 )
		lbA_new = new real_t[nC];
	if ( ubA_file != 0 )
		ubA_new = new real_t[nC];

	returnvalue = loadQPvectorsFromFile(	g_file,lb_file,ub_file,lbA_file,ubA_file,
											g_new,lb_new,ub_new,lbA_new,ubA_new
											);
	if ( returnvalue != SUCCESSFUL_RETURN )
	{
		if ( ubA_file != 0 )
			delete[] ubA_new;
		if ( lbA_file != 0 )
			delete[] lbA_new;
		if ( ub_file != 0 )
			delete[] ub_new;
		if ( lb_file != 0 )
			delete[] lb_new;
		delete[] g_new;
		delete[] A_new;
		delete[] H_new;

		return THROWERROR( RET_UNABLE_TO_READ_FILE );
	}

	/* 3) Actually perform hotstart. */
	returnvalue = hotstart(	H_new,g_new,A_new,lb_new,ub_new,lbA_new,ubA_new, nWSR,cputime );

	if ( ubA_file != 0 )
		delete[] ubA_new;
	if ( lbA_file != 0 )
		delete[] lbA_new;
	if ( ub_file != 0 )
		delete[] ub_new;
	if ( lb_file != 0 )
		delete[] lb_new;
	delete[] g_new;
	delete[] A_new;
	delete[] H_new;

	return returnvalue;
}
示例#9
0
文件: dense_cp.cpp 项目: rtkg/acado
void DenseCP::copy( const DenseCP& rhs ){

    uint run1, run2;

    nS = rhs.nS;

    H   = rhs.H;
    g   = rhs.g;

    lb  = rhs.lb;
    ub  = rhs.ub;

    A   = rhs.A;
    lbA = rhs.lbA;
    ubA = rhs.ubA;


    if( rhs.B != 0 ){
        B = (Matrix**)calloc(nS,sizeof(Matrix*));
        for( run1 = 0; run1 < nS; run1++ ){
            B[run1] = new Matrix[ getNV() ];
            for( run2 = 0; run2 < getNV(); run2++ )
                B[run1][run2] = rhs.B[run1][run2];
        }
    }
    else B = 0;


    if( rhs.lbB != 0 ){
        lbB = (Vector*)calloc(nS,sizeof(Vector));
        for( run1 = 0; run1 < nS; run1++ )
            lbB[run1] = rhs.lbB[run1];
    }
    else lbB = 0;

    if( rhs.ubB != 0 ){
        ubB = (Vector*)calloc(nS,sizeof(Vector));
        for( run1 = 0; run1 < nS; run1++ )
            ubB[run1] = rhs.ubB[run1];
    }
    else ubB = 0;


    if( rhs.x != 0 ) x = new Vector(*rhs.x);
    else             x = 0                 ;

    if( rhs.ylb != 0 ) ylb = new Vector(*rhs.ylb);
    else               ylb = 0                   ;

    if( rhs.yub != 0 ) yub = new Vector(*rhs.yub);
    else               yub = 0                   ;

    if( rhs.ylbA != 0 ) ylbA = new Vector(*rhs.ylbA);
    else                ylbA = 0                    ;

    if( rhs.yubA != 0 ) yubA = new Vector(*rhs.yubA);
    else                yubA = 0                    ;

    if( nS > 0 ){

        ylbB = (Vector**)calloc(nS,sizeof(Vector*));
        yubB = (Vector**)calloc(nS,sizeof(Vector*));

        for( run1 = 0; run1 < nS; run1++ ){
            if( rhs.ylbB[run1] != 0 ) ylbB[run1] = new Vector(*rhs.ylbB[run1]);
            else                      ylbB[run1] = 0                          ;

            if( rhs.yubB[run1] != 0 ) yubB[run1] = new Vector(*rhs.yubB[run1]);
            else                      yubB[run1] = 0                          ;
        }
    }
    else{
        ylbB = 0;
        yubB = 0;
    }
}
示例#10
0
const pokemon_nonvolatile& pkCU::getTPKNV()
{
	return getNV().getTeam(getIOTeam()).getPKNV(getBase().getEnv().getTeam(getIOTeam()));
}
示例#11
0
bool pkCU::isValidAction(const environment_volatile& envV, size_t action, size_t iTeam)
{
	const team_volatile& cTV = envV.getTeam(iTeam);
	const team_volatile& oTV = envV.getOtherTeam(iTeam);
	const team_nonvolatile& cTNV = getNV().getTeam(iTeam);
	const pokemon_nonvolatile& cPokemon = cTNV.getPKNV(cTV);
	
	switch(action)
	{
		case AT_MOVE_0:
		case AT_MOVE_1:
		case AT_MOVE_2:
		case AT_MOVE_3:
		{
			/* is this a valid move? */
			if ((action - AT_MOVE_0) >= cPokemon.getNumMoves()) { return false; }

			// is the other pokemon alive?
			if (!(oTV.getPKV().isAlive())) { return false; }

			// is the pokemon we're currently using alive?
			if (!cTV.getPKV().isAlive()) { return false; }

			// does the move we're using have any PP left?
			if ( cTV.getPKV().getMV(action - AT_MOVE_0).hasPP() != true ) { return false; }
		
			//TODO: are we locked out of the current move?

			return true; // by default, allow moves
		}
		case AT_SWITCH_0:
		case AT_SWITCH_1:
		case AT_SWITCH_2:
		case AT_SWITCH_3:
		case AT_SWITCH_4:
		case AT_SWITCH_5:
		{
			// is the pokemon we're switching to a valid teammate?
			if ( ((action - AT_SWITCH_0) < cTNV.getNumTeammates()) != true) { return false; }
		
			// are we trying to switch to ourself?
			if ((action - AT_SWITCH_0) == cTV.getICPKV()) { return false; }

			// is the pokemon we're switching to even alive?
			if ( cTV.teammate(action - AT_SWITCH_0).isAlive() != true) { return false; }

			// are we trying to move during the other team's free move?
			if (
				!(oTV.getPKV().isAlive())
				&& cTV.getPKV().isAlive()
				) { return false; }
		
			// TODO: are we locked out of switching?

			return true; // by default, allow switches
		}
		case AT_MOVE_NOTHING:
			// are we waiting for the other team to take its free move?
			if (
				!(oTV.getPKV().isAlive())
				&& cTV.getPKV().isAlive()
				) { return true; }

			// in most cases, do not allow not moving
			return false;
		case AT_MOVE_STRUGGLE:
			// is the other pokemon alive?
			if (!(oTV.getPKV().isAlive())) { return false; }

			// is the pokemon we're currently using alive?
			if (!cTV.getPKV().isAlive()) { return false; }

			// can the pokemon struggle?
			if (!cTV.cHasPP()) { return true; }

			// cannot struggle by default
			return false;
		// disabled action types:
		case AT_ITEM_USE:
		case AT_MOVE_CONFUSED:
			return false;
		default: // what the hell happened here? No, this isn't a valid move. Shut up.
			return false;
	}
} // endOf is valid action
示例#12
0
bool pkCU::initialize()
{
	size_t numPlugins = 0;
	// clear plugin arrays:
	for (size_t iNCTeammate = 0; iNCTeammate != pluginSets.size(); ++iNCTeammate)
	{
		for (size_t iOTeammate = 0; iOTeammate != pluginSets[iNCTeammate].size(); ++iOTeammate)
		{
			boost::array<std::vector<plugin_t>, PLUGIN_MAXSIZE>& _cPluginSet = pluginSets[iNCTeammate][iOTeammate];
			for (size_t iPlugin = 0; iPlugin != _cPluginSet.size(); ++iPlugin)
			{
				_cPluginSet[iPlugin].clear();
			}
		}
	}

	// add individual plugins: (for each possible current pokemon, 12 total)
	for (size_t iNCTeammate = 0; iNCTeammate != pluginSets.size(); ++iNCTeammate)
	{
		size_t iCTeam = iNCTeammate >= 6;
		size_t iCTeammate = iNCTeammate - 6*iCTeam;
		// don't add to a teammate that doesn't exist:
		if ((iCTeammate) >= getNV().getTeam(iCTeam).getNumTeammates()) { continue; }
		// current nonvolatile teammate:
		const pokemon_nonvolatile& cPKNV = getNV().getTeam(iCTeam).teammate(iCTeammate);

		// plugins for moves:
		for (size_t iCMove = 0; iCMove != cPKNV.getNumMoves(); ++iCMove)
		{
			const pluggable& cPluggable = cPKNV.getMove_base(iCMove);
			for (size_t iPlugin = 0; iPlugin != PLUGIN_MAXSIZE; ++iPlugin)
			{
				plugin_t cPlugin = cPluggable.getPlugin(iPlugin);
				if (cPlugin.pFunction == NULL) { continue; }
				insertPluginHandler(cPlugin, iPlugin, iNCTeammate);
				numPlugins++;
			}
		}

		// plugins for abilities:
		if (cPKNV.abilityExists()) 
		{ 
			const pluggable& cPluggable = cPKNV.getAbility();
			for (size_t iPlugin = 0; iPlugin != PLUGIN_MAXSIZE; ++iPlugin)
			{
				plugin_t cPlugin = cPluggable.getPlugin(iPlugin);
				if (cPlugin.pFunction == NULL) { continue; }
				insertPluginHandler(cPlugin, iPlugin, iNCTeammate);
				numPlugins++;
			}
		}

		// plugins for items: TODO: what if the items switch teammates?
		if (cPKNV.hasInitialItem())
		{ 
			const pluggable& cPluggable = cPKNV.getInitialItem();
			for (size_t iPlugin = 0; iPlugin != PLUGIN_MAXSIZE; ++iPlugin)
			{
				plugin_t cPlugin = cPluggable.getPlugin(iPlugin);
				if (cPlugin.pFunction == NULL) { continue; }
				insertPluginHandler(cPlugin, iPlugin, iNCTeammate);
				numPlugins++;
			}
		}
	} // endOf cTeammate

	// TODO: add plugins that affect the other pokemon:

	// add global (and engine) plugins second:
	for (size_t iPluginType = 0; iPluginType != PLUGIN_MAXSIZE; ++iPluginType)
	{
		for (size_t iPlugin = 0; iPlugin != pkdex->getExtensions().getNumPlugins(iPluginType); ++iPlugin)
		{
			plugin_t cPlugin = pkdex->getExtensions().getPlugin(iPluginType, iPlugin);
			numPlugins++;

			insertPluginHandler(cPlugin, iPluginType);
		}
	}

	// SORT plugins by priority:
	for (size_t iNCTeammate = 0; iNCTeammate != pluginSets.size(); ++iNCTeammate)
	{
		for (size_t iOTeammate = 0; iOTeammate != pluginSets[iNCTeammate].size(); ++iOTeammate)
		{
			boost::array<std::vector<plugin_t>, PLUGIN_MAXSIZE>& _cPluginSet = pluginSets[iNCTeammate][iOTeammate];
			for (size_t iPlugin = 0; iPlugin != _cPluginSet.size(); ++iPlugin)
			{
				std::sort(_cPluginSet[iPlugin].begin(), _cPluginSet[iPlugin].end());
			}
		}
	}

	assert(numPlugins <= MAXPLUGINS);
	return true;
}