Пример #1
0
void GBStackBrain::ExecuteInstruction(GBStackInstruction ins, GBRobot * robot, GBWorld * world) {
	GBStackInstruction index = ins & kOpcodeIndexMask;
	switch ( ins >> kOpcodeTypeShift ) {
		case otPrimitive:
			ExecutePrimitive(index, robot, world);
			break;
		case otConstantRead:
			Push(spec->ReadConstant(index));
			break;
		case otVariableRead:
			Push(ReadVariable(index));
			break;
		case otVariableWrite:
			WriteVariable(index, Pop());
			break;
		case otVectorRead:
			PushVector(ReadVectorVariable(index));
			break;
		case otVectorWrite:
			WriteVectorVariable(index, PopVector());
			break;
		case otLabelRead:
			Push(spec->ReadLabel(index));
			break;
		case otLabelCall:
			ExecuteCall(spec->ReadLabel(index));
			break;
		case otHardwareRead:
			Push(ReadHardware(index, robot, world));
			break;
		case otHardwareWrite:
			WriteHardware(index, Pop(), robot, world);
			break;
		case otHardwareVectorRead:
			PushVector(ReadHardwareVector(index, robot, world));
			break;
		case otHardwareVectorWrite:
			WriteHardwareVector(index, PopVector(), robot, world);
			break;
		default:	
			throw GBUnknownInstructionError();
			break;
	}
}
Пример #2
0
void GBStackBrain::TwoVectorToVectorOp(GBFinePoint (GBFinePoint::* op)(const GBFinePoint &) const) {
	GBVector v2 = PopVector();
	GBVector v1 = PopVector();
	PushVector((v1.*op)(v2));
}
Пример #3
0
void GBStackBrain::VectorToVectorOp(GBFinePoint (GBFinePoint::* op)() const) {
	GBVector v = PopVector();
	PushVector((v.*op)());
}
Пример #4
0
/*
====================
idInterpreter::Execute
====================
*/
bool idInterpreter::Execute( void ) {
	varEval_t	var_a;
	varEval_t	var_b;
	varEval_t	var_c;
	varEval_t	var;
	statement_t	*st;
	int			runaway;
	idThread	*newThread;
	float		floatVal;
	idScriptObject *obj;
	const function_t *func;

	if ( threadDying || !currentFunction ) {
		return true;
	}

	if ( multiFrameEvent ) {
		// move to previous instruction and call it again
		instructionPointer--;
	}

	runaway = 5000000;

	doneProcessing = false;
	while( !doneProcessing && !threadDying ) {
		instructionPointer++;

		if ( !--runaway ) {
			Error( "runaway loop error" );
		}

		// next statement
		st = &gameLocal.program.GetStatement( instructionPointer );

		switch( st->op ) {
		case OP_RETURN:
			LeaveFunction( st->a );
			break;

		case OP_THREAD:
			newThread = new idThread( this, st->a->value.functionPtr, st->b->value.argSize );
			newThread->Start();

			// return the thread number to the script
			gameLocal.program.ReturnFloat( newThread->GetThreadNum() );
			PopParms( st->b->value.argSize );
			break;

		case OP_OBJTHREAD:
			var_a = GetVariable( st->a );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( obj ) {
				func = obj->GetTypeDef()->GetFunction( st->b->value.virtualFunction );
				assert( st->c->value.argSize == func->parmTotal );
				newThread = new idThread( this, GetEntity( *var_a.entityNumberPtr ), func, func->parmTotal );
				newThread->Start();

				// return the thread number to the script
				gameLocal.program.ReturnFloat( newThread->GetThreadNum() );
			} else {
				// return a null thread to the script
				gameLocal.program.ReturnFloat( 0.0f );
			}
			PopParms( st->c->value.argSize );
			break;

		case OP_CALL:
			EnterFunction( st->a->value.functionPtr, false );
			break;

		case OP_EVENTCALL:
			CallEvent( st->a->value.functionPtr, st->b->value.argSize );
			break;

		case OP_OBJECTCALL:
			var_a = GetVariable( st->a );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( obj ) {
				func = obj->GetTypeDef()->GetFunction( st->b->value.virtualFunction );
				EnterFunction( func, false );
			} else {
				// return a 'safe' value
				gameLocal.program.ReturnVector( vec3_zero );
				gameLocal.program.ReturnString( "" );
				PopParms( st->c->value.argSize );
			}
			break;

		case OP_SYSCALL:
			CallSysEvent( st->a->value.functionPtr, st->b->value.argSize );
			break;

		case OP_IFNOT:
			var_a = GetVariable( st->a );
			if ( *var_a.intPtr == 0 ) {
				NextInstruction( instructionPointer + st->b->value.jumpOffset );
			}
			break;

		case OP_IF:
			var_a = GetVariable( st->a );
			if ( *var_a.intPtr != 0 ) {
				NextInstruction( instructionPointer + st->b->value.jumpOffset );
			}
			break;

		case OP_GOTO:
			NextInstruction( instructionPointer + st->a->value.jumpOffset );
			break;

		case OP_ADD_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = *var_a.floatPtr + *var_b.floatPtr;
			break;

		case OP_ADD_V:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.vectorPtr = *var_a.vectorPtr + *var_b.vectorPtr;
			break;

		case OP_ADD_S:
			SetString( st->c, GetString( st->a ) );
			AppendString( st->c, GetString( st->b ) );
			break;

		case OP_ADD_FS:
			var_a = GetVariable( st->a );
			SetString( st->c, FloatToString( *var_a.floatPtr ) );
			AppendString( st->c, GetString( st->b ) );
			break;

		case OP_ADD_SF:
			var_b = GetVariable( st->b );
			SetString( st->c, GetString( st->a ) );
			AppendString( st->c, FloatToString( *var_b.floatPtr ) );
			break;

		case OP_ADD_VS:
			var_a = GetVariable( st->a );
			SetString( st->c, var_a.vectorPtr->ToString() );
			AppendString( st->c, GetString( st->b ) );
			break;

		case OP_ADD_SV:
			var_b = GetVariable( st->b );
			SetString( st->c, GetString( st->a ) );
			AppendString( st->c, var_b.vectorPtr->ToString() );
			break;

		case OP_SUB_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = *var_a.floatPtr - *var_b.floatPtr;
			break;

		case OP_SUB_V:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.vectorPtr = *var_a.vectorPtr - *var_b.vectorPtr;
			break;

		case OP_MUL_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = *var_a.floatPtr * *var_b.floatPtr;
			break;

		case OP_MUL_V:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = *var_a.vectorPtr * *var_b.vectorPtr;
			break;

		case OP_MUL_FV:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.vectorPtr = *var_a.floatPtr * *var_b.vectorPtr;
			break;

		case OP_MUL_VF:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.vectorPtr = *var_a.vectorPtr * *var_b.floatPtr;
			break;

		case OP_DIV_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );

			if ( *var_b.floatPtr == 0.0f ) {
				Warning( "Divide by zero" );
				*var_c.floatPtr = idMath::INFINITY;
			} else {
				*var_c.floatPtr = *var_a.floatPtr / *var_b.floatPtr;
			}
			break;

		case OP_MOD_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable ( st->c );

			if ( *var_b.floatPtr == 0.0f ) {
				Warning( "Divide by zero" );
				*var_c.floatPtr = *var_a.floatPtr;
			} else {
				*var_c.floatPtr = static_cast<int>( *var_a.floatPtr ) % static_cast<int>( *var_b.floatPtr );
			}
			break;

		case OP_BITAND:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = static_cast<int>( *var_a.floatPtr ) & static_cast<int>( *var_b.floatPtr );
			break;

		case OP_BITOR:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = static_cast<int>( *var_a.floatPtr ) | static_cast<int>( *var_b.floatPtr );
			break;

		case OP_GE:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr >= *var_b.floatPtr );
			break;

		case OP_LE:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr <= *var_b.floatPtr );
			break;

		case OP_GT:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr > *var_b.floatPtr );
			break;

		case OP_LT:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr < *var_b.floatPtr );
			break;

		case OP_AND:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr != 0.0f ) && ( *var_b.floatPtr != 0.0f );
			break;

		case OP_AND_BOOLF:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.intPtr != 0 ) && ( *var_b.floatPtr != 0.0f );
			break;

		case OP_AND_FBOOL:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr != 0.0f ) && ( *var_b.intPtr != 0 );
			break;

		case OP_AND_BOOLBOOL:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.intPtr != 0 ) && ( *var_b.intPtr != 0 );
			break;

		case OP_OR:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr != 0.0f ) || ( *var_b.floatPtr != 0.0f );
			break;

		case OP_OR_BOOLF:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.intPtr != 0 ) || ( *var_b.floatPtr != 0.0f );
			break;

		case OP_OR_FBOOL:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr != 0.0f ) || ( *var_b.intPtr != 0 );
			break;

		case OP_OR_BOOLBOOL:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.intPtr != 0 ) || ( *var_b.intPtr != 0 );
			break;

		case OP_NOT_BOOL:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.intPtr == 0 );
			break;

		case OP_NOT_F:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr == 0.0f );
			break;

		case OP_NOT_V:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.vectorPtr == vec3_zero );
			break;

		case OP_NOT_S:
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( strlen( GetString( st->a ) ) == 0 );
			break;

		case OP_NOT_ENT:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( GetEntity( *var_a.entityNumberPtr ) == NULL );
			break;

		case OP_NEG_F:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = -*var_a.floatPtr;
			break;

		case OP_NEG_V:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			*var_c.vectorPtr = -*var_a.vectorPtr;
			break;

		case OP_INT_F:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = static_cast<int>( *var_a.floatPtr );
			break;

		case OP_EQ_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr == *var_b.floatPtr );
			break;

		case OP_EQ_V:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.vectorPtr == *var_b.vectorPtr );
			break;

		case OP_EQ_S:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( idStr::Cmp( GetString( st->a ), GetString( st->b ) ) == 0 );
			break;

		case OP_EQ_E:
		case OP_EQ_EO:
		case OP_EQ_OE:
		case OP_EQ_OO:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.entityNumberPtr == *var_b.entityNumberPtr );
			break;

		case OP_NE_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.floatPtr != *var_b.floatPtr );
			break;

		case OP_NE_V:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.vectorPtr != *var_b.vectorPtr );
			break;

		case OP_NE_S:
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( idStr::Cmp( GetString( st->a ), GetString( st->b ) ) != 0 );
			break;

		case OP_NE_E:
		case OP_NE_EO:
		case OP_NE_OE:
		case OP_NE_OO:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ( *var_a.entityNumberPtr != *var_b.entityNumberPtr );
			break;

		case OP_UADD_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.floatPtr += *var_a.floatPtr;
			break;

		case OP_UADD_V:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.vectorPtr += *var_a.vectorPtr;
			break;

		case OP_USUB_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.floatPtr -= *var_a.floatPtr;
			break;

		case OP_USUB_V:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.vectorPtr -= *var_a.vectorPtr;
			break;

		case OP_UMUL_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.floatPtr *= *var_a.floatPtr;
			break;

		case OP_UMUL_V:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.vectorPtr *= *var_a.floatPtr;
			break;

		case OP_UDIV_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );

			if ( *var_a.floatPtr == 0.0f ) {
				Warning( "Divide by zero" );
				*var_b.floatPtr = idMath::INFINITY;
			} else {
				*var_b.floatPtr = *var_b.floatPtr / *var_a.floatPtr;
			}
			break;

		case OP_UDIV_V:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );

			if ( *var_a.floatPtr == 0.0f ) {
				Warning( "Divide by zero" );
				var_b.vectorPtr->Set( idMath::INFINITY, idMath::INFINITY, idMath::INFINITY );
			} else {
				*var_b.vectorPtr = *var_b.vectorPtr / *var_a.floatPtr;
			}
			break;

		case OP_UMOD_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );

			if ( *var_a.floatPtr == 0.0f ) {
				Warning( "Divide by zero" );
				*var_b.floatPtr = *var_a.floatPtr;
			} else {
				*var_b.floatPtr = static_cast<int>( *var_b.floatPtr ) % static_cast<int>( *var_a.floatPtr );
			}
			break;

		case OP_UOR_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.floatPtr = static_cast<int>( *var_b.floatPtr ) | static_cast<int>( *var_a.floatPtr );
			break;

		case OP_UAND_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.floatPtr = static_cast<int>( *var_b.floatPtr ) & static_cast<int>( *var_a.floatPtr );
			break;

		case OP_UINC_F:
			var_a = GetVariable( st->a );
			( *var_a.floatPtr )++;
			break;

		case OP_UINCP_F:
			var_a = GetVariable( st->a );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( obj ) {
				var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
				( *var.floatPtr )++;
			}
			break;

		case OP_UDEC_F:
			var_a = GetVariable( st->a );
			( *var_a.floatPtr )--;
			break;

		case OP_UDECP_F:
			var_a = GetVariable( st->a );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( obj ) {
				var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
				( *var.floatPtr )--;
			}
			break;

		case OP_COMP_F:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			*var_c.floatPtr = ~static_cast<int>( *var_a.floatPtr );
			break;

		case OP_STORE_F:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.floatPtr = *var_a.floatPtr;
			break;

		case OP_STORE_ENT:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.entityNumberPtr = *var_a.entityNumberPtr;
			break;

		case OP_STORE_BOOL:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.intPtr = *var_a.intPtr;
			break;

		case OP_STORE_OBJENT:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( !obj ) {
				*var_b.entityNumberPtr = 0;
			} else if ( !obj->GetTypeDef()->Inherits( st->b->TypeDef() ) ) {
				//Warning( "object '%s' cannot be converted to '%s'", obj->GetTypeName(), st->b->TypeDef()->Name() );
				*var_b.entityNumberPtr = 0;
			} else {
				*var_b.entityNumberPtr = *var_a.entityNumberPtr;
			}
			break;

		case OP_STORE_OBJ:
		case OP_STORE_ENTOBJ:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.entityNumberPtr = *var_a.entityNumberPtr;
			break;

		case OP_STORE_S:
			SetString( st->b, GetString( st->a ) );
			break;

		case OP_STORE_V:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.vectorPtr = *var_a.vectorPtr;
			break;

		case OP_STORE_FTOS:
			var_a = GetVariable( st->a );
			SetString( st->b, FloatToString( *var_a.floatPtr ) );
			break;

		case OP_STORE_BTOS:
			var_a = GetVariable( st->a );
			SetString( st->b, *var_a.intPtr ? "true" : "false" );
			break;

		case OP_STORE_VTOS:
			var_a = GetVariable( st->a );
			SetString( st->b, var_a.vectorPtr->ToString() );
			break;

		case OP_STORE_FTOBOOL:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			if ( *var_a.floatPtr != 0.0f ) {
				*var_b.intPtr = 1;
			} else {
				*var_b.intPtr = 0;
			}
			break;

		case OP_STORE_BOOLTOF:
			var_a = GetVariable( st->a );
			var_b = GetVariable( st->b );
			*var_b.floatPtr = static_cast<float>( *var_a.intPtr );
			break;

		case OP_STOREP_F:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->floatPtr ) {
				var_a = GetVariable( st->a );
				*var_b.evalPtr->floatPtr = *var_a.floatPtr;
			}
			break;

		case OP_STOREP_ENT:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->entityNumberPtr ) {
				var_a = GetVariable( st->a );
				*var_b.evalPtr->entityNumberPtr = *var_a.entityNumberPtr;
			}
			break;

		case OP_STOREP_FLD:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->intPtr ) {
				var_a = GetVariable( st->a );
				*var_b.evalPtr->intPtr = *var_a.intPtr;
			}
			break;

		case OP_STOREP_BOOL:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->intPtr ) {
				var_a = GetVariable( st->a );
				*var_b.evalPtr->intPtr = *var_a.intPtr;
			}
			break;

		case OP_STOREP_S:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->stringPtr ) {
				idStr::Copynz( var_b.evalPtr->stringPtr, GetString( st->a ), MAX_STRING_LEN );
			}
			break;

		case OP_STOREP_V:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->vectorPtr ) {
				var_a = GetVariable( st->a );
				*var_b.evalPtr->vectorPtr = *var_a.vectorPtr;
			}
			break;

		case OP_STOREP_FTOS:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->stringPtr ) {
				var_a = GetVariable( st->a );
				idStr::Copynz( var_b.evalPtr->stringPtr, FloatToString( *var_a.floatPtr ), MAX_STRING_LEN );
			}
			break;

		case OP_STOREP_BTOS:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->stringPtr ) {
				var_a = GetVariable( st->a );
				if ( *var_a.floatPtr != 0.0f ) {
					idStr::Copynz( var_b.evalPtr->stringPtr, "true", MAX_STRING_LEN );
				} else {
					idStr::Copynz( var_b.evalPtr->stringPtr, "false", MAX_STRING_LEN );
				}
			}
			break;

		case OP_STOREP_VTOS:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->stringPtr ) {
				var_a = GetVariable( st->a );
				idStr::Copynz( var_b.evalPtr->stringPtr, var_a.vectorPtr->ToString(), MAX_STRING_LEN );
			}
			break;

		case OP_STOREP_FTOBOOL:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->intPtr ) {
				var_a = GetVariable( st->a );
				if ( *var_a.floatPtr != 0.0f ) {
					*var_b.evalPtr->intPtr = 1;
				} else {
					*var_b.evalPtr->intPtr = 0;
				}
			}
			break;

		case OP_STOREP_BOOLTOF:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->floatPtr ) {
				var_a = GetVariable( st->a );
				*var_b.evalPtr->floatPtr = static_cast<float>( *var_a.intPtr );
			}
			break;

		case OP_STOREP_OBJ:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->entityNumberPtr ) {
				var_a = GetVariable( st->a );
				*var_b.evalPtr->entityNumberPtr = *var_a.entityNumberPtr;
			}
			break;

		case OP_STOREP_OBJENT:
			var_b = GetVariable( st->b );
			if ( var_b.evalPtr && var_b.evalPtr->entityNumberPtr ) {
				var_a = GetVariable( st->a );
				obj = GetScriptObject( *var_a.entityNumberPtr );
				if ( !obj ) {
					*var_b.evalPtr->entityNumberPtr = 0;

				// st->b points to type_pointer, which is just a temporary that gets its type reassigned, so we store the real type in st->c
				// so that we can do a type check during run time since we don't know what type the script object is at compile time because it
				// comes from an entity
				} else if ( !obj->GetTypeDef()->Inherits( st->c->TypeDef() ) ) {
					//Warning( "object '%s' cannot be converted to '%s'", obj->GetTypeName(), st->c->TypeDef()->Name() );
					*var_b.evalPtr->entityNumberPtr = 0;
				} else {
					*var_b.evalPtr->entityNumberPtr = *var_a.entityNumberPtr;
				}
			}
			break;

		case OP_ADDRESS:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( obj ) {
				var_c.evalPtr->bytePtr = &obj->data[ st->b->value.ptrOffset ];
			} else {
				var_c.evalPtr->bytePtr = NULL;
			}
			break;

		case OP_INDIRECT_F:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( obj ) {
				var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
				*var_c.floatPtr = *var.floatPtr;
			} else {
				*var_c.floatPtr = 0.0f;
			}
			break;

		case OP_INDIRECT_ENT:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( obj ) {
				var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
				*var_c.entityNumberPtr = *var.entityNumberPtr;
			} else {
				*var_c.entityNumberPtr = 0;
			}
			break;

		case OP_INDIRECT_BOOL:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( obj ) {
				var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
				*var_c.intPtr = *var.intPtr;
			} else {
				*var_c.intPtr = 0;
			}
			break;

		case OP_INDIRECT_S:
			var_a = GetVariable( st->a );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( obj ) {
				var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
				SetString( st->c, var.stringPtr );
			} else {
				SetString( st->c, "" );
			}
			break;

		case OP_INDIRECT_V:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( obj ) {
				var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
				*var_c.vectorPtr = *var.vectorPtr;
			} else {
				var_c.vectorPtr->Zero();
			}
			break;

		case OP_INDIRECT_OBJ:
			var_a = GetVariable( st->a );
			var_c = GetVariable( st->c );
			obj = GetScriptObject( *var_a.entityNumberPtr );
			if ( !obj ) {
				*var_c.entityNumberPtr = 0;
			} else {
				var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
				*var_c.entityNumberPtr = *var.entityNumberPtr;
			}
			break;

		case OP_PUSH_F:
			var_a = GetVariable( st->a );
			Push( *var_a.intPtr );
			break;

		case OP_PUSH_FTOS:
			var_a = GetVariable( st->a );
			PushString( FloatToString( *var_a.floatPtr ) );
			break;

		case OP_PUSH_BTOF:
			var_a = GetVariable( st->a );
			floatVal = *var_a.intPtr;
			Push( *reinterpret_cast<int *>( &floatVal ) );
			break;

		case OP_PUSH_FTOB:
			var_a = GetVariable( st->a );
			if ( *var_a.floatPtr != 0.0f ) {
				Push( 1 );
			} else {
				Push( 0 );
			}
			break;

		case OP_PUSH_VTOS:
			var_a = GetVariable( st->a );
			PushString( var_a.vectorPtr->ToString() );
			break;

		case OP_PUSH_BTOS:
			var_a = GetVariable( st->a );
			PushString( *var_a.intPtr ? "true" : "false" );
			break;

		case OP_PUSH_ENT:
			var_a = GetVariable( st->a );
			Push( *var_a.entityNumberPtr );
			break;

		case OP_PUSH_S:
			PushString( GetString( st->a ) );
			break;

		case OP_PUSH_V:
			var_a = GetVariable( st->a );
			PushVector(*var_a.vectorPtr);
			break;

		case OP_PUSH_OBJ:
			var_a = GetVariable( st->a );
			Push( *var_a.entityNumberPtr );
			break;

		case OP_PUSH_OBJENT:
			var_a = GetVariable( st->a );
			Push( *var_a.entityNumberPtr );
			break;

		case OP_BREAK:
		case OP_CONTINUE:
		default:
			Error( "Bad opcode %i", st->op );
			break;
		}
	}

	return threadDying;
}
Пример #5
0
void GBStackBrain::ExecutePrimitive(GBSymbolIndex index, GBRobot * robot, GBWorld * world) {
	GBStackDatum temp, temp2, temp3;
	long tempInt;
	switch ( index ) {
		case opNop: break;
	// stack manipulation
		case opDrop: Pop(); break;
		case op2Drop: Pop(); Pop(); break;
		case opNip: temp = Pop(); Pop(); Push(temp); break;
		case opRDrop: PopReturn(); break;
		case opDropN: {
			int n = PopInteger();
			if ( n > stackHeight ) throw GBBadArgumentError();
			stackHeight -= n;
		} break;
		case opSwap: temp = Pop(); temp2 = Pop(); Push(temp); Push(temp2); break;
		case op2Swap: { GBVector v1 = PopVector(); GBVector v2 = PopVector();
			PushVector(v1); PushVector(v2); } break;
		case opRotate: temp = Pop(); temp2 = Pop(); temp3 = Pop(); Push(temp2); Push(temp); Push(temp3); break;
		case opReverseRotate: temp = Pop(); temp2 = Pop(); temp3 = Pop(); Push(temp); Push(temp3); Push(temp2); break;
		case opDup: temp = Peek(); Push(temp); break;
		case op2Dup: temp = Peek(2); temp2 = Peek(); Push(temp); Push(temp2); break;
		case opTuck: temp = Pop(); temp2 = Pop(); Push(temp); Push(temp2); Push(temp); break;
		case opOver: temp = Peek(2); Push(temp); break;
		case op2Over: temp = Peek(4); temp2 = Peek(3); Push(temp); Push(temp2); break;
		case opStackHeight: Push(stackHeight); break;
		case opStackLimit: Push(kStackLimit); break;
		case opPick: Push(Peek(PopInteger())); break;
		case opToReturn: PushReturn(ToAddress(Pop())); break;
		case opFromReturn: Push(PopReturn()); break;
	// branches
		case opJump: pc = ToAddress(Pop()); break;
		case opCall: ExecuteCall(ToAddress(Pop())); break;
		case opReturn: pc = PopReturn(); break;
		case opIfGo: temp = Pop(); if ( Pop().Nonzero() ) pc = ToAddress(temp); break;
		case opIfElseGo: temp = Pop(); temp2 = Pop();
			if ( Pop().Nonzero() ) pc = ToAddress(temp2); else pc = ToAddress(temp); break;
		case opIfCall: temp = Pop(); if ( Pop().Nonzero() ) ExecuteCall(ToAddress(temp)); break;
		case opIfElseCall: temp = Pop(); temp2 = Pop();
			if ( Pop().Nonzero() ) ExecuteCall(ToAddress(temp2)); else ExecuteCall(ToAddress(temp)); break;
		case opIfReturn: if ( Pop().Nonzero() ) pc = PopReturn(); break;
		case opNotIfGo: temp = Pop(); if ( ! Pop().Nonzero() ) pc = ToAddress(temp); break;
		case opNotIfReturn: if ( ! Pop().Nonzero() ) pc = PopReturn(); break;
		case opNotIfCall: temp = Pop(); if ( ! Pop().Nonzero() ) ExecuteCall(ToAddress(temp)); break;
	// arithmetic
		case opAdd: TwoNumberToNumberOp(&GBNumber::operator +); break;
		case opSubtract: TwoNumberToNumberOp(&GBNumber::operator -); break;
		case opNegate: NumberToNumberOp(&GBNumber::operator -); break;
		// mult and divide are written out because of MrCpp internal error
		case opMultiply: temp = Pop(); Push(Pop() * temp); break;
		case opDivide: temp = Pop(); Push(Pop() / temp); break;
		case opReciprocal: Push(GBNumber(1) / Pop()); break;
		case opMod: TwoNumberToNumberOp(&GBNumber::Mod); break;
		case opRem: TwoNumberToNumberOp(&GBNumber::Rem); break;
		case opSqrt: NumberToNumberOp(&GBNumber::Sqrt); break;
		case opExponent: TwoNumberToNumberOp(&GBNumber::Exponent); break;
		case opIsInteger: PushBoolean(Pop().IsInteger()); break;
		case opFloor: Push(Pop().Floor()); break;
		case opCeiling: Push(Pop().Ceiling()); break;
		case opRound: Push(Pop().Round()); break;
		case opMin: TwoNumberToNumberOp(&GBNumber::Min); break;
		case opMax: TwoNumberToNumberOp(&GBNumber::Max); break;
		case opAbs: NumberToNumberOp(&GBNumber::Abs); break;
		case opSignum: NumberToNumberOp(&GBNumber::Signum); break;
		case opReorient: NumberToNumberOp(&GBNumber::Reorient); break;
		case opSine: NumberToNumberOp(&GBNumber::Sin); break;
		case opCosine: NumberToNumberOp(&GBNumber::Cos); break;
		case opTangent: NumberToNumberOp(&GBNumber::Tan); break;
		case opArcSine: NumberToNumberOp(&GBNumber::ArcSin); break;
		case opArcCosine: NumberToNumberOp(&GBNumber::ArcCos); break;
		case opArcTangent: NumberToNumberOp(&GBNumber::ArcTan); break;
		case opRandom: temp = Pop(); Push(world->Randoms().InRange(Pop(), temp)); break;
		case opRandomAngle: Push(world->Randoms().Angle()); break;
		case opRandomInt: temp = Pop(); Push(world->Randoms().LongInRange(Pop().Ceiling(), temp.Floor())); break;
		case opRandomBoolean: PushBoolean(world->Randoms().Boolean(Pop())); break;
	// constants
		case opPi: Push(GBNumber::pi); break;
		case op2Pi: Push(GBNumber::pi * 2); break;
		case opPiOver2: Push(GBNumber::pi / 2); break;
		case opE: Push(GBNumber::e); break;
		case opEpsilon: Push(GBNumber::epsilon); break;
		case opInfinity: Push(GBNumber::infinity); break;
	// vector operations
		case opRectToPolar: { GBVector v = PopVector(); Push(v.Norm()); Push(v.Angle()); } break;
		case opPolarToRect: temp = Pop(); temp2 = Pop(); PushVector(GBFinePoint::MakePolar(temp2, temp)); break;
		case opVectorAdd: TwoVectorToVectorOp(&GBFinePoint::operator +); break;
		case opVectorSubtract: TwoVectorToVectorOp(&GBFinePoint::operator -); break;
		case opVectorNegate: VectorToVectorOp(&GBFinePoint::operator -); break;
		case opVectorScalarMultiply: temp = Pop(); PushVector(PopVector() * temp); break;
		case opVectorScalarDivide: temp = Pop(); PushVector(PopVector() / temp); break;
		case opVectorNorm: VectorToScalarOp(&GBFinePoint::Norm); break;
		case opVectorAngle: VectorToScalarOp(&GBFinePoint::Angle); break;
		case opDotProduct: TwoVectorToScalarOp(&GBFinePoint::DotProduct);  break;
		case opProject: TwoVectorToVectorOp(&GBFinePoint::Projection); break;
		case opCross: TwoVectorToScalarOp(&GBFinePoint::Cross); break;
		case opUnitize: VectorToVectorOp(&GBFinePoint::Unit); break;
		case opDistance: Push((PopVector() - PopVector()).Norm()); break;
		case opInRange: temp = Pop(); PushBoolean(PopVector().InRange(PopVector(), temp)); break;
		case opRestrictPosition: {
			temp = Pop(); //wall distance
			GBVector pos = PopVector();
			Push(pos.x.Max(temp).Min(world->Size().x - temp));
			Push(pos.y.Max(temp).Min(world->Size().y - temp));
			} break;
		case opVectorEqual: PushBoolean(PopVector() == PopVector()); break;
		case opVectorNotEqual: PushBoolean(PopVector() != PopVector()); break;
	// comparisons
		case opEqual: PushBoolean(Pop() == Pop()); break;
		case opNotEqual: PushBoolean(Pop() != Pop()); break;
		case opLessThan: temp = Pop(); PushBoolean(Pop() < temp); break;
		case opLessThanOrEqual: temp = Pop(); PushBoolean(Pop() <= temp); break;
		case opGreaterThan: temp = Pop(); PushBoolean(Pop() > temp); break;
		case opGreaterThanOrEqual: temp = Pop(); PushBoolean(Pop() >= temp); break;
	// booleans
		case opNot: PushBoolean(! Pop().Nonzero()); break;
		case opAnd: temp = Pop(); temp2 = Pop(); PushBoolean(temp.Nonzero() && temp2.Nonzero()); break;
		case opOr: temp = Pop(); temp2 = Pop(); PushBoolean(temp.Nonzero() || temp2.Nonzero()); break;
		case opXor: temp = Pop(); temp2 = Pop();
			PushBoolean(temp.Nonzero() && ! temp2.Nonzero() || ! temp.Nonzero() && temp2.Nonzero()); break;
		case opNand: temp = Pop(); temp2 = Pop(); PushBoolean(! (temp.Nonzero() && temp2.Nonzero())); break;
		case opNor: temp = Pop(); temp2 = Pop(); PushBoolean(! (temp.Nonzero() || temp2.Nonzero())); break;
		case opValueConditional: temp = Pop(); temp2 = Pop();
			if ( Pop().Nonzero() ) Push(temp2); else Push(temp);
			break;
	// misc external
		case opPrint:
			DoPrint(ToString(Pop()));
			if ( world->reportPrints )
				NonfatalError(robot->Description() + " prints: " + *lastPrint);
			break;
		case opPrintVector:
			DoPrint(ToString(PopVector()));
			if ( world->reportPrints )
				NonfatalError(robot->Description() + " prints: " + *lastPrint);
			break;
		case opBeep: StartSound(siBeep); break;
		case opStop: SetStatus(bsStopped); break;
		case opPause: if ( world->reportErrors ) world->running = false; break;
		case opSync: remaining = 0; break;
	// basic hardware
		case opSeekLocation: robot->EngineSeek(PopVector(), GBVector(0, 0)); break;
		case opSeekMovingLocation: {
			GBVector vel = PopVector();
			robot->EngineSeek(PopVector(), vel);
			} break;
		case opDie: robot->Die(robot->Owner()); SetStatus(bsStopped); break;
		case opWriteLocalMemory:
			tempInt = PopInteger();
			WriteLocalMemory(tempInt, Pop(), robot);
			break;
		case opReadLocalMemory:
			tempInt = PopInteger();
			Push(ReadLocalMemory(tempInt, robot));
			break;
		case opWriteLocalVector:
			tempInt = PopInteger();
			WriteLocalMemory(tempInt + 1, Pop(), robot);
			WriteLocalMemory(tempInt, Pop(), robot);
			break;
		case opReadLocalVector:
			tempInt = PopInteger();
			Push(ReadLocalMemory(tempInt, robot));
			Push(ReadLocalMemory(tempInt + 1, robot));
			break;
		case opWriteSharedMemory:
			tempInt = PopInteger();
			robot->hardware.radio.Write(Pop(), tempInt, robot->Owner());
			break;
		case opReadSharedMemory:
			Push(robot->hardware.radio.Read(PopInteger(), robot->Owner()));
			break;
		case opWriteSharedVector:
			tempInt = PopInteger();
			robot->hardware.radio.Write(Pop(), tempInt + 1, robot->Owner());
			robot->hardware.radio.Write(Pop(), tempInt, robot->Owner());
			break;
		case opReadSharedVector:
			tempInt = PopInteger();
			Push(robot->hardware.radio.Read(tempInt, robot->Owner()));
			Push(robot->hardware.radio.Read(tempInt + 1, robot->Owner()));
			break;
		case opMessagesWaiting:
			Push(robot->hardware.radio.MessagesWaiting(PopInteger(), robot->Owner()));
			break;
		case opSendMessage: {
				GBMessage sendee;
				tempInt = PopInteger(); //channel
				int numArgs = ToInteger(Pop()); //number of numbers
				for ( int i = 0; i < numArgs; i++ ) {
					sendee.AddDatum(Pop()); //higher indices in message correspond with earlier numbers in stack. :(
				}
				if ( numArgs <= 0 )
					throw GBGenericError("Cannot send message of non-positive length");
				robot->hardware.radio.Send(sendee, tempInt, robot->Owner());
			} break;
		case opReceiveMessage: {
				tempInt = PopInteger();
				const GBMessage * received = robot->hardware.radio.Receive(tempInt, robot->Owner());
				if ( received == 0 ) {
					Push(0);
				} else {
					if ( received->Length() <= 0 ) {
						throw GBGenericError("non-positive length message received");
					}
					for ( int i = received->Length() - 1; i >= 0; i-- )
						Push(received->Datum(i));
					Push(received->Length());
				}
			} break;
		case opClearMessages:
			robot->hardware.radio.ClearChannel(PopInteger(), robot->Owner());
			break;
		case opSkipMessages:
			tempInt = PopInteger();
			robot->hardware.radio.SkipMessages(tempInt, PopInteger(), robot->Owner());
			break;
		case opTypePopulation: {
				GBRobotType * theType = robot->Owner()->GetType(PopInteger());
				if (theType)
					Push(theType->Population());
				else
					Push(-1);
			} break;
		case opAutoConstruct: {
			GBConstructorState & ctor = robot->hardware.constructor;
			if ( robot->Energy() > robot->hardware.MaxEnergy() * .9 ) {
				if ( ! ctor.Type() ) ctor.Start(robot->Type());
				ctor.SetRate(ctor.MaxRate());
			} else
				ctor.SetRate(ctor.Type() && robot->Energy() > ctor.Remaining() + 10 ? ctor.MaxRate() : GBNumber(0));
			} break;
		case opBalanceTypes: { // frac type --
				GBRobotType * theType = robot->Owner()->GetType(PopInteger());
				GBNumber fraction = Pop();
				if (theType && GBNumber(theType->Population()) < fraction * robot->Owner()->Scores().Population())
					robot->hardware.constructor.Start(theType); //FIXME don't abort?
			} break;
	// sensors
		case opFireRobotSensor: robot->hardware.sensor1.Fire(); break;
		case opFireFoodSensor: robot->hardware.sensor2.Fire(); break;
		case opFireShotSensor: robot->hardware.sensor3.Fire(); break;
		case opRobotSensorNext: Push(robot->hardware.sensor1.NextResult() ? 1 : 0); break;
		case opFoodSensorNext: Push(robot->hardware.sensor2.NextResult() ? 1 : 0); break;
		case opShotSensorNext: Push(robot->hardware.sensor3.NextResult() ? 1 : 0); break;
		case opPeriodicRobotSensor:
			FirePeriodic(robot->hardware.sensor1, world);
			break;
		case opPeriodicFoodSensor:
			FirePeriodic(robot->hardware.sensor2, world);
			break;
		case opPeriodicShotSensor:
			FirePeriodic(robot->hardware.sensor3, world);
			break;
	// weapons
		case opFireBlaster: robot->hardware.blaster.Fire(Pop()); break;
		case opFireGrenade: temp = Pop(); robot->hardware.grenades.Fire(Pop(), temp); break;
		case opLeadBlaster: { //pos vel --
			GBVelocity vel = PopVector() - robot->Velocity();
			GBPosition pos = PopVector() - robot->Position();
			GBPosition target = LeadShot(pos, vel, robot->hardware.blaster.Speed(), robot->Radius());
			if ( target.Nonzero() && target.Norm() <= robot->hardware.blaster.MaxRange() + robot->Radius() )
				robot->hardware.blaster.Fire(target.Angle());
			} break;
		case opLeadGrenade: { //pos vel --
			GBVelocity vel = PopVector() - robot->Velocity();
			GBPosition pos = PopVector() - robot->Position();
			GBPosition target = LeadShot(pos, vel, robot->hardware.grenades.Speed(), robot->Radius());
			if ( target.Nonzero() && target.Norm() <= robot->hardware.grenades.MaxRange() + robot->Radius() )
				robot->hardware.grenades.Fire(target.Norm(), target.Angle()); //worry about short range?
			} break;
		case opSetForceField: { //pos angle --
			temp = Pop();
			GBPosition pos = PopVector() - robot->Position();
			robot->hardware.forceField.SetDistance(pos.Norm());
			robot->hardware.forceField.SetDirection(pos.Angle());
			robot->hardware.forceField.SetAngle(temp);
			robot->hardware.forceField.SetPower(robot->hardware.forceField.MaxPower());
			} break;
	// otherwise...
		default:	
			throw GBUnknownInstructionError();
			break;
	}
}
Пример #6
0
int GetPosition(lua_State* L) {
    assert(luaGameInfo);
    Vectormath::Aos::Vector3 v = luaGameInfo->player.GetPosition();
    PushVector(L, &v);
    return 1;
}
Пример #7
0
int Right(lua_State* L) {
    assert(luaGameInfo);
    Vectormath::Aos::Vector3 v = luaGameInfo->player.Right();
    PushVector(L, &v);
    return 1;
}