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; } }
void GBStackBrain::TwoVectorToVectorOp(GBFinePoint (GBFinePoint::* op)(const GBFinePoint &) const) { GBVector v2 = PopVector(); GBVector v1 = PopVector(); PushVector((v1.*op)(v2)); }
void GBStackBrain::VectorToVectorOp(GBFinePoint (GBFinePoint::* op)() const) { GBVector v = PopVector(); PushVector((v.*op)()); }
/* ==================== 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; }
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; } }
int GetPosition(lua_State* L) { assert(luaGameInfo); Vectormath::Aos::Vector3 v = luaGameInfo->player.GetPosition(); PushVector(L, &v); return 1; }
int Right(lua_State* L) { assert(luaGameInfo); Vectormath::Aos::Vector3 v = luaGameInfo->player.Right(); PushVector(L, &v); return 1; }