From abb272600e84ff90f9130cd0426b9abc2db82ee9 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Mon, 10 Aug 2015 18:16:00 +0200 Subject: [PATCH] Merged CBrain into CProgrammableObject --- src/CMakeLists.txt | 1 - src/object/auto/autoegg.cpp | 10 +- src/object/auto/autofactory.cpp | 14 +- src/object/brain.cpp | 785 --------------------- src/object/brain.h | 170 ----- src/object/interface/programmable_object.h | 51 +- src/object/motion/motion.h | 1 - src/object/motion/motionvehicle.cpp | 2 +- src/object/object.h | 2 + src/object/object_factory.cpp | 11 +- src/object/old_object.cpp | 721 +++++++++++++++++-- src/object/old_object.h | 91 ++- src/object/old_object_interface.cpp | 5 - src/object/old_object_interface.h | 9 - src/object/robotmain.cpp | 91 ++- src/object/task/task.cpp | 5 +- src/object/task/task.h | 12 +- src/object/task/taskshield.cpp | 2 - src/object/task/taskterraform.cpp | 2 - src/physics/physics.cpp | 3 +- src/physics/physics.h | 8 +- src/script/scriptfunc.cpp | 10 +- src/ui/mainshort.cpp | 4 +- src/ui/object_interface.cpp | 123 ++-- src/ui/object_interface.h | 6 +- src/ui/studio.cpp | 3 +- 26 files changed, 955 insertions(+), 1187 deletions(-) delete mode 100644 src/object/brain.cpp delete mode 100644 src/object/brain.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 399dc072..f939533f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -149,7 +149,6 @@ set(BASE_SOURCES object/auto/autovault.cpp object/auto/autopowerstation.cpp object/auto/autotower.cpp - object/brain.cpp object/drive_type.cpp object/level/parser.cpp object/level/parserexceptions.cpp diff --git a/src/object/auto/autoegg.cpp b/src/object/auto/autoegg.cpp index 18af17ed..6befc1f2 100644 --- a/src/object/auto/autoegg.cpp +++ b/src/object/auto/autoegg.cpp @@ -26,7 +26,6 @@ #include "math/geometry.h" -#include "object/brain.h" #include "object/object_manager.h" #include "object/old_object.h" @@ -185,11 +184,11 @@ bool CAutoEgg::EventProcess(const Event &event) if (alien->Implements(ObjectInterfaceType::Programmable)) { - CBrain* brain = dynamic_cast(alien)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(alien); - Program* program = brain->AddProgram(); - brain->ReadProgram(program, m_alienProgramName.c_str()); - brain->RunProgram(program); + Program* program = programmable->AddProgram(); + programmable->ReadProgram(program, m_alienProgramName.c_str()); + programmable->RunProgram(program); } Init(); } @@ -332,4 +331,3 @@ bool CAutoEgg::Read(CLevelParserLine* line) return true; } - diff --git a/src/object/auto/autofactory.cpp b/src/object/auto/autofactory.cpp index d753f2b3..55ed0f94 100644 --- a/src/object/auto/autofactory.cpp +++ b/src/object/auto/autofactory.cpp @@ -25,7 +25,6 @@ #include "math/geometry.h" -#include "object/brain.h" #include "object/object_create_params.h" #include "object/object_manager.h" #include "object/old_object.h" @@ -408,7 +407,6 @@ bool CAutoFactory::EventProcess(const Event &event) } vehicle->SetLock(false); // vehicle useable -//? vehicle->GetPhysics()->GetBrain()->StartTaskAdvance(16.0f); vehicle->SetRotationY(m_object->GetRotationY()+Math::PI); vehicle->SetScale(1.0f); @@ -416,8 +414,8 @@ bool CAutoFactory::EventProcess(const Event &event) { if (vehicle->Implements(ObjectInterfaceType::Programmable)) { - CBrain* brain = dynamic_cast(vehicle)->GetBrain(); - Program* program = brain->AddProgram(); + CProgrammableObject* programmable = dynamic_cast(vehicle); + Program* program = programmable->AddProgram(); if (boost::regex_search(m_program, boost::regex("^[A-Za-z0-9_]+$"))) // Public function name? { @@ -433,7 +431,7 @@ bool CAutoFactory::EventProcess(const Event &event) program->script->SendScript(m_program.c_str()); } - brain->RunProgram(program); + programmable->RunProgram(program); } } } @@ -680,13 +678,13 @@ bool CAutoFactory::CreateVehicle() if (vehicle->Implements(ObjectInterfaceType::Programmable)) { - CBrain* brain = dynamic_cast(vehicle)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(vehicle); for ( int i=0 ; ; i++ ) { char* name = m_main->GetNewScriptName(m_type, i); if ( name == nullptr ) break; - Program* prog = brain->GetOrAddProgram(i); - brain->ReadProgram(prog, name); + Program* prog = programmable->GetOrAddProgram(i); + programmable->ReadProgram(prog, name); prog->readOnly = true; } } diff --git a/src/object/brain.cpp b/src/object/brain.cpp deleted file mode 100644 index ee206f8b..00000000 --- a/src/object/brain.cpp +++ /dev/null @@ -1,785 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsiteс.ch; http://colobot.info; http://github.com/colobot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://gnu.org/licenses - */ - - -#include "object/brain.h" - -#include "common/make_unique.h" - -#include "math/geometry.h" - -#include "object/old_object.h" -#include "object/robotmain.h" - -#include "object/interface/task_executor_object.h" - -#include "object/level/parserline.h" -#include "object/level/parserparam.h" - -#include "object/motion/motion.h" -#include "object/motion/motionvehicle.h" - -#include "object/task/taskmanager.h" - -#include "physics/physics.h" - -#include "script/script.h" - -#include "ui/studio.h" - -#include "ui/controls/edit.h" - -#include -#include - - - -const int MAXTRACERECORD = 1000; - -// Object's constructor. - -CBrain::CBrain(COldObject* object) -{ - m_object = object; - assert(object->Implements(ObjectInterfaceType::TaskExecutor)); - m_taskExecutor = dynamic_cast(m_object); - - m_physics = nullptr; - m_motion = nullptr; - - m_engine = Gfx::CEngine::GetInstancePointer(); - m_main = CRobotMain::GetInstancePointer(); - m_camera = m_main->GetCamera(); - - m_program.clear(); - m_currentProgram = nullptr; - m_bBurn = false; - m_bActiveVirus = false; - m_time = 0.0f; - m_burnTime = 0.0f; - - m_buttonAxe = EVENT_NULL; - - m_scriptRun = nullptr; - m_soluceName[0] = 0; - - m_traceRecord = false; -} - -// Object's destructor. - -CBrain::~CBrain() -{ -} - -void CBrain::SetPhysics(CPhysics* physics) -{ - m_physics = physics; -} - -void CBrain::SetMotion(CMotion* motion) -{ - m_motion = motion; -} - - -// Saves all parameters of the object. - -bool CBrain::Write(CLevelParserLine* line) -{ - line->AddParam("bVirusActive", MakeUnique(m_bActiveVirus)); - - if ( m_object->GetType() == OBJECT_MOBILErs ) - { - line->AddParam("bShieldActive", MakeUnique(m_taskExecutor->IsBackgroundTask())); - } - - return true; -} - -// Restores all parameters of the object. - -bool CBrain::Read(CLevelParserLine* line) -{ - m_bActiveVirus = line->GetParam("bVirusActive")->AsBool(false); - if ( m_object->GetType() == OBJECT_MOBILErs ) - { - if( line->GetParam("bShieldActive")->AsBool(false) ) - { - m_taskExecutor->StartTaskShield(TSM_START); - } - } - return true; -} - - -// Management of an event. - -bool CBrain::EventProcess(const Event &event) -{ - if ( event.type == EVENT_FRAME ) - { - EventFrame(event); - } - - if ( !m_object->GetSelect() && // robot pas sélectionné ? - m_currentProgram == nullptr && - !m_taskExecutor->IsForegroundTask() ) - { - float axeX = 0.0f; - float axeY = 0.0f; - float axeZ = 0.0f; - if ( m_object->GetBurn() ) // Gifted? - { - if ( !m_bBurn ) // beginning? - { - m_bBurn = true; - m_burnTime = 0.0f; - } - - axeZ = -1.0f; // tomb - - if ( !m_object->GetFixed() && - (m_object->GetType() == OBJECT_ANT || - m_object->GetType() == OBJECT_SPIDER || - m_object->GetType() == OBJECT_WORM ) ) - { - axeY = 2.0f; // zigzag disorganized fast - if ( m_object->GetType() == OBJECT_WORM ) axeY = 5.0f; - axeX = 0.5f+sinf(m_time* 1.0f)*0.5f+ - sinf(m_time* 6.0f)*2.0f+ - sinf(m_time*21.0f)*0.2f; - float factor = 1.0f-m_burnTime/15.0f; // slow motion - if ( factor < 0.0f ) factor = 0.0f; - axeY *= factor; - axeX *= factor; - } - } - m_physics->SetMotorSpeedX(axeY); // move forward/move back - m_physics->SetMotorSpeedY(axeZ); // up / down - m_physics->SetMotorSpeedZ(axeX); // rotate - return true; - } - - if ( m_currentProgram != nullptr && - m_object->GetRuin() ) - { - StopProgram(); - return true; - } - - if ( !m_object->GetSelect() ) return true; // robot not selected? - - if ( m_taskExecutor->IsForegroundTask() || // current task? - m_currentProgram != nullptr ) - { - if ( !m_taskExecutor->IsForegroundTask() || !m_taskExecutor->GetForegroundTask()->IsPilot() ) return true; - } - - if ( event.type == EVENT_OBJECT_LEFT || - event.type == EVENT_OBJECT_RIGHT || - event.type == EVENT_OBJECT_UP || - event.type == EVENT_OBJECT_DOWN || - event.type == EVENT_OBJECT_GASUP || - event.type == EVENT_OBJECT_GASDOWN ) - { - m_buttonAxe = event.type; - } - if ( event.type == EVENT_MOUSE_BUTTON_UP ) - { - m_buttonAxe = EVENT_NULL; - } - - float axeX = event.motionInput.x; - float axeY = event.motionInput.y; - float axeZ = event.motionInput.z; - - if ( (!m_main->GetTrainerPilot() && - m_object->GetTrainer()) || - !m_main->CanPlayerInteract() ) // drive vehicle? - { - axeX = 0.0f; - axeY = 0.0f; - axeZ = 0.0f; // Remote control impossible! - } - - if ( m_buttonAxe == EVENT_OBJECT_LEFT ) axeX = -1.0f; - if ( m_buttonAxe == EVENT_OBJECT_RIGHT ) axeX = 1.0f; - if ( m_buttonAxe == EVENT_OBJECT_UP ) axeY = 1.0f; - if ( m_buttonAxe == EVENT_OBJECT_DOWN ) axeY = -1.0f; - if ( m_buttonAxe == EVENT_OBJECT_GASUP ) axeZ = 1.0f; - if ( m_buttonAxe == EVENT_OBJECT_GASDOWN ) axeZ = -1.0f; - - if ( m_object->GetType() == OBJECT_MOBILEdr && m_object->GetManual() ) // scribbler in manual mode? - { - if ( axeX != 0.0f ) axeY = 0.0f; // if running -> not moving! - axeX *= 0.5f; - axeY *= 0.5f; - } - - if ( !m_main->IsResearchDone(RESEARCH_FLY, m_object->GetTeam()) ) - { - axeZ = -1.0f; // tomb - } - - axeX += m_camera->GetMotorTurn(); // additional power according to camera - if ( axeX > 1.0f ) axeX = 1.0f; - if ( axeX < -1.0f ) axeX = -1.0f; - - m_physics->SetMotorSpeedX(axeY); // move forward/move back - m_physics->SetMotorSpeedY(axeZ); // up/down - m_physics->SetMotorSpeedZ(axeX); // rotate - - return true; -} - - -// The brain is changing by time. - -bool CBrain::EventFrame(const Event &event) -{ - m_time += event.rTime; - if ( m_bBurn ) m_burnTime += event.rTime; - - if ( m_engine->GetPause() ) return true; - if ( !m_object->GetActivity() ) return true; - - if ( m_currentProgram != nullptr ) // current program? - { - if ( m_currentProgram->script->Continue() ) - { - StopProgram(); - } - } - - if ( m_traceRecord ) // registration of the design in progress? - { - TraceRecordFrame(); - } - - return true; -} - - -// Stops the running program. - -void CBrain::StopProgram() -{ - m_taskExecutor->StopForegroundTask(); - - if ( m_object->GetType() == OBJECT_HUMAN || - m_object->GetType() == OBJECT_TECH ) return; - - if ( m_currentProgram != nullptr ) - { - m_currentProgram->script->Stop(); - } - - m_currentProgram = nullptr; - - m_physics->SetMotorSpeedX(0.0f); - m_physics->SetMotorSpeedY(0.0f); - m_physics->SetMotorSpeedZ(0.0f); - - m_motion->SetAction(-1); - - m_object->UpdateInterface(); - m_main->UpdateShortcuts(); - m_object->CreateSelectParticle(); -} - - -// Introduces a virus into a program. -// Returns true if it was inserted. - -bool CBrain::IntroduceVirus() -{ - if(m_program.size() == 0) return false; - - for ( int i=0 ; i<50 ; i++ ) - { - int j = rand()%m_program.size(); - if ( m_program[j]->script->IntroduceVirus() ) // tries to introduce - { - m_bActiveVirus = true; // active virus - return true; - } - } - return false; -} - -// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus) -// letters which automatically disappear after a while, -// ActiveVirus does not disappear after you edit the program -// (Even if the virus is not fixed). - - -void CBrain::SetActiveVirus(bool bActive) -{ - m_bActiveVirus = bActive; - - if ( !m_bActiveVirus ) // virus disabled? - { - m_object->SetVirusMode(false); // chtites (??? - Programerus) letters also - } -} - -bool CBrain::GetActiveVirus() -{ - return m_bActiveVirus; -} - -// Indicates whether a program is running. - -bool CBrain::IsProgram() -{ - return m_currentProgram != nullptr; -} - -// Starts a program. - -void CBrain::RunProgram(Program* program) -{ - if ( program->script->Run() ) - { - m_currentProgram = program; // start new program - m_object->UpdateInterface(); - m_object->CreateSelectParticle(); - m_main->UpdateShortcuts(); - if(m_object->GetTrainer()) - m_main->StartMissionTimer(); - } -} - - -// Returns the current program. - -int CBrain::GetProgram() -{ - if(m_currentProgram == nullptr) - return -1; - - for(unsigned int i = 0; i < m_program.size(); i++) - { - if(m_program[i].get() == m_currentProgram) - { - return i; - } - } - return -1; -} - - -// Name management scripts to load. - -void CBrain::SetScriptRun(Program* program) -{ - m_scriptRun = program; -} - -Program* CBrain::GetScriptRun() -{ - return m_scriptRun; -} - -void CBrain::SetSoluceName(char *name) -{ - strcpy(m_soluceName, name); -} - -char* CBrain::GetSoluceName() -{ - return m_soluceName; -} - - -// Load a script solution, in the first free script. -// If there is already an identical script, nothing is loaded. - -bool CBrain::ReadSoluce(char* filename) -{ - Program* prog = AddProgram(); - - if ( !ReadProgram(prog, filename) ) return false; // load solution - prog->readOnly = true; - - for(unsigned int i = 0; i < m_program.size(); i++) - { - if(m_program[i].get() == prog) continue; - - //TODO: This is bad. It's very sensitive to things like \n vs \r\n etc. - if ( m_program[i]->script->Compare(prog->script.get()) ) // the same already? - { - m_program[i]->readOnly = true; // Mark is as read-only - RemoveProgram(prog); - return false; - } - } - - return true; -} - -// Load a script with a text file. - -bool CBrain::ReadProgram(Program* program, const char* filename) -{ - if ( program->script->ReadScript(filename) ) return true; - - return false; -} - -// Indicates whether a program is compiled correctly. - -bool CBrain::GetCompile(Program* program) -{ - return program->script->GetCompile(); -} - -// Saves a script in a text file. - -bool CBrain::WriteProgram(Program* program, const char* filename) -{ - if ( program->script->WriteScript(filename) ) return true; - - return false; -} - - -// Load a stack of script implementation from a file. - -bool CBrain::ReadStack(FILE *file) -{ - short op; - - fRead(&op, sizeof(short), 1, file); - if ( op == 1 ) // run ? - { - fRead(&op, sizeof(short), 1, file); // program rank - if ( op >= 0 ) - { - assert(op < static_cast(m_program.size())); //TODO: is it good? - - //TODO: m_selScript = op; - - if ( !m_program[op]->script->ReadStack(file) ) return false; - } - } - - return true; -} - -// Save the script implementation stack of a file. - -bool CBrain::WriteStack(FILE *file) -{ - short op; - - if ( m_currentProgram != nullptr && // current program? - m_currentProgram->script->IsRunning() ) - { - op = 1; // run - fWrite(&op, sizeof(short), 1, file); - - op = GetProgram(); - fWrite(&op, sizeof(short), 1, file); - - return m_currentProgram->script->WriteStack(file); - } - - op = 0; // stop - fWrite(&op, sizeof(short), 1, file); - return true; -} - - - -// Start of registration of the design. - -void CBrain::TraceRecordStart() -{ - if (m_traceRecord) - { - TraceRecordStop(); - } - - CMotionVehicle* motionVehicle = dynamic_cast(m_motion); - assert(motionVehicle != nullptr); - - m_traceRecord = true; - - m_traceOper = TO_STOP; - - m_tracePos = m_object->GetPosition(); - m_traceAngle = m_object->GetRotationY(); - - if ( motionVehicle->GetTraceDown() ) // pencil down? - { - m_traceColor = motionVehicle->GetTraceColor(); - } - else // pen up? - { - m_traceColor = TraceColor::Default; - } - - m_traceRecordBuffer = MakeUniqueArray(MAXTRACERECORD); - m_traceRecordIndex = 0; -} - -// Saving the current drawing. - -void CBrain::TraceRecordFrame() -{ - TraceOper oper = TO_STOP; - Math::Vector pos; - float angle, len, speed; - - CMotionVehicle* motionVehicle = dynamic_cast(m_motion); - assert(motionVehicle != nullptr); - - speed = m_physics->GetLinMotionX(MO_REASPEED); - if ( speed > 0.0f ) oper = TO_ADVANCE; - if ( speed < 0.0f ) oper = TO_RECEDE; - - speed = m_physics->GetCirMotionY(MO_REASPEED); - if ( speed != 0.0f ) oper = TO_TURN; - - TraceColor color = TraceColor::Default; - if ( motionVehicle->GetTraceDown() ) // pencil down? - { - color = motionVehicle->GetTraceColor(); - } - - if ( oper != m_traceOper || - color != m_traceColor ) - { - if ( m_traceOper == TO_ADVANCE || - m_traceOper == TO_RECEDE ) - { - pos = m_object->GetPosition(); - len = Math::DistanceProjected(pos, m_tracePos); - TraceRecordOper(m_traceOper, len); - } - if ( m_traceOper == TO_TURN ) - { - angle = m_object->GetRotationY()-m_traceAngle; - TraceRecordOper(m_traceOper, angle); - } - - if ( color != m_traceColor ) - { - TraceRecordOper(TO_PEN, static_cast(color)); - } - - m_traceOper = oper; - m_tracePos = m_object->GetPosition(); - m_traceAngle = m_object->GetRotationY(); - m_traceColor = color; - } -} - -// End of the registration of the design. Program generates the CBOT. - -void CBrain::TraceRecordStop() -{ - TraceOper lastOper, curOper; - float lastParam, curParam; - - m_traceRecord = false; - - std::stringstream buffer; - buffer << "extern void object::AutoDraw()\n{\n"; - - lastOper = TO_STOP; - lastParam = 0.0f; - for ( int i=0 ; iscript->SendScript(buffer.str().c_str()); -} - -// Saves an instruction CBOT. - -bool CBrain::TraceRecordOper(TraceOper oper, float param) -{ - int i; - - i = m_traceRecordIndex; - if ( i >= MAXTRACERECORD ) return false; - - m_traceRecordBuffer[i].oper = oper; - m_traceRecordBuffer[i].param = param; - - m_traceRecordIndex = i+1; - return true; -} - -// Generates an instruction CBOT. - -bool CBrain::TraceRecordPut(std::stringstream& buffer, TraceOper oper, float param) -{ - if ( oper == TO_ADVANCE ) - { - param /= g_unit; - buffer << "\tmove(" << std::fixed << std::setprecision(1) << param << ");\n"; - } - - if ( oper == TO_RECEDE ) - { - param /= g_unit; - buffer << "\tmove(-" << std::fixed << std::setprecision(1) << param << ");\n"; - } - - if ( oper == TO_TURN ) - { - param = -param*180.0f/Math::PI; - buffer << "\tturn(" << static_cast(param) << ");\n"; - } - - if ( oper == TO_PEN ) - { - TraceColor color = static_cast(static_cast(param)); - if ( color == TraceColor::Default ) - buffer << "\tpenup();\n"; - else - buffer << "\tpendown(" << TraceColorName(color) << ");\n"; - } - - return true; -} - -bool CBrain::IsTraceRecord() -{ - return m_traceRecord; -} - -Program* CBrain::AddProgram() -{ - auto program = MakeUnique(); - program->script = MakeUnique(m_object); - program->readOnly = false; - program->runnable = true; - - Program* prog = program.get(); - AddProgram(std::move(program)); - return prog; -} - -void CBrain::AddProgram(std::unique_ptr program) -{ - m_program.push_back(std::move(program)); - m_object->UpdateInterface(); -} - -void CBrain::RemoveProgram(Program* program) -{ - if(m_currentProgram == program) - { - StopProgram(); - } - m_program.erase( - std::remove_if(m_program.begin(), m_program.end(), - [program](std::unique_ptr& prog) { return prog.get() == program; }), - m_program.end()); -} - -Program* CBrain::CloneProgram(Program* program) -{ - Program* newprog = AddProgram(); - - // TODO: Is there any reason CScript doesn't have a function to get the program code directly? - Ui::CEdit* edit = new Ui::CEdit(); - edit->SetMaxChar(Ui::EDITSTUDIOMAX); - program->script->PutScript(edit, ""); - newprog->script->GetScript(edit); - delete edit; - - return newprog; -} - -std::vector>& CBrain::GetPrograms() -{ - return m_program; -} - -int CBrain::GetProgramCount() -{ - return static_cast(m_program.size()); -} - -int CBrain::GetProgramIndex(Program* program) -{ - for(unsigned int i = 0; i < m_program.size(); i++) - { - if(m_program[i].get() == program) - { - return i; - } - } - return -1; -} - -Program* CBrain::GetProgram(int index) -{ - if(index < 0 || index >= static_cast(m_program.size())) - return nullptr; - - return m_program[index].get(); -} - -Program* CBrain::GetOrAddProgram(int index) -{ - if(index < 0) - return nullptr; - - if(index < static_cast(m_program.size())) - return m_program[index].get(); - - for(int i = m_program.size(); i < index; i++) - { - AddProgram(); - } - return AddProgram(); -} diff --git a/src/object/brain.h b/src/object/brain.h deleted file mode 100644 index 5e2940d3..00000000 --- a/src/object/brain.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsiteс.ch; http://colobot.info; http://github.com/colobot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://gnu.org/licenses - */ - -/** - * \file object/brain.h - * \brief CBrain - dispatches commands to objects - */ - -#pragma once - -#include "common/event.h" - -#include "object/trace_color.h" - -#include -#include -#include - -class COldObject; -class CTaskExecutorObject; -class CPhysics; -class CMotion; -class CScript; -class CRobotMain; -class CLevelParserLine; - -namespace Gfx -{ -class CEngine; -class CCamera; -} /* Gfx */ - - - -enum TraceOper -{ - TO_STOP = 0, // stop - TO_ADVANCE = 1, // advance - TO_RECEDE = 2, // back - TO_TURN = 3, // rotate - TO_PEN = 4, // color change -}; - -struct TraceRecord -{ - TraceOper oper; - float param; -}; - -struct Program -{ - std::unique_ptr script; - std::string filename; - bool readOnly; - bool runnable; -}; - - - -class CBrain -{ -public: - CBrain(COldObject* object); - ~CBrain(); - - void SetPhysics(CPhysics* physics); - void SetMotion(CMotion* motion); - - bool EventProcess(const Event &event); - - bool Write(CLevelParserLine* line); - bool Read(CLevelParserLine* line); - - bool IsProgram(); - void RunProgram(Program* program); - int GetProgram(); - void StopProgram(); - - bool IntroduceVirus(); - void SetActiveVirus(bool bActive); - bool GetActiveVirus(); - - void SetScriptRun(Program* rank); - Program* GetScriptRun(); - void SetSoluceName(char *name); - char* GetSoluceName(); - - bool ReadSoluce(char* filename); - bool ReadProgram(Program* program, const char* filename); - bool GetCompile(Program* program); - bool WriteProgram(Program* program, const char* filename); - bool ReadStack(FILE *file); - bool WriteStack(FILE *file); - - Program* AddProgram(); - void AddProgram(std::unique_ptr program); - void RemoveProgram(Program* program); - Program* CloneProgram(Program* program); - - std::vector>& GetPrograms(); - int GetProgramCount(); - Program* GetProgram(int index); - Program* GetOrAddProgram(int index); - int GetProgramIndex(Program* program); - - //! Start recording trace - void TraceRecordStart(); - //! Stop recording trace and generate CBot program - void TraceRecordStop(); - //! Returns true if trace recording is in progress - bool IsTraceRecord(); - -protected: - bool EventFrame(const Event &event); - - //! Save current status to recording buffer - void TraceRecordFrame(); - //! Save this operation to recording buffer - bool TraceRecordOper(TraceOper oper, float param); - //! Convert this recording operation to CBot instruction - bool TraceRecordPut(std::stringstream& buffer, TraceOper oper, float param); - -protected: - CRobotMain* m_main; - Gfx::CEngine* m_engine; - Gfx::CCamera* m_camera; - - COldObject* m_object; - CTaskExecutorObject* m_taskExecutor; - CPhysics* m_physics; - CMotion* m_motion; - - std::vector> m_program; - Program* m_currentProgram; - - bool m_bBurn; - bool m_bActiveVirus; - - Program* m_scriptRun; - char m_soluceName[50]; - - EventType m_buttonAxe; - - float m_time; - float m_burnTime; - - bool m_traceRecord; - TraceOper m_traceOper; - Math::Vector m_tracePos; - float m_traceAngle; - TraceColor m_traceColor; - int m_traceRecordIndex; - std::unique_ptr m_traceRecordBuffer; -}; diff --git a/src/object/interface/programmable_object.h b/src/object/interface/programmable_object.h index 85ec155a..588eb513 100644 --- a/src/object/interface/programmable_object.h +++ b/src/object/interface/programmable_object.h @@ -21,7 +21,15 @@ #include "object/object_interface_type.h" -class CBrain; +class CScript; + +struct Program +{ + std::unique_ptr script; + std::string filename; + bool readOnly; + bool runnable; +}; /** * \class CProgrammableObject @@ -39,11 +47,42 @@ public: virtual ~CProgrammableObject() {} - //! Returns CBrain - /** If only the object implements ObjectInterfaceType::Programmable, - * returned object will always be non-null*/ - virtual CBrain* GetBrain() = 0; + virtual bool IsProgram() = 0; + virtual void RunProgram(Program* program) = 0; + virtual int GetProgram() = 0; + virtual void StopProgram() = 0; + virtual bool IntroduceVirus() = 0; + virtual void SetActiveVirus(bool bActive) = 0; + virtual bool GetActiveVirus() = 0; - // TODO: CBrain interface can actually be moved here + virtual void SetScriptRun(Program* rank) = 0; + virtual Program* GetScriptRun() = 0; + virtual void SetSoluceName(char *name) = 0; + virtual char* GetSoluceName() = 0; + + virtual bool ReadSoluce(char* filename) = 0; + virtual bool ReadProgram(Program* program, const char* filename) = 0; + virtual bool GetCompile(Program* program) = 0; + virtual bool WriteProgram(Program* program, const char* filename) = 0; + virtual bool ReadStack(FILE *file) = 0; + virtual bool WriteStack(FILE *file) = 0; + + virtual Program* AddProgram() = 0; + virtual void AddProgram(std::unique_ptr program) = 0; + virtual void RemoveProgram(Program* program) = 0; + virtual Program* CloneProgram(Program* program) = 0; + + virtual std::vector>& GetPrograms() = 0; + virtual int GetProgramCount() = 0; + virtual Program* GetProgram(int index) = 0; + virtual Program* GetOrAddProgram(int index) = 0; + virtual int GetProgramIndex(Program* program) = 0; + + //! Start recording trace + virtual void TraceRecordStart() = 0; + //! Stop recording trace and generate CBot program + virtual void TraceRecordStop() = 0; + //! Returns true if trace recording is in progress + virtual bool IsTraceRecord() = 0; }; diff --git a/src/object/motion/motion.h b/src/object/motion/motion.h index 6c721a9e..074fe91a 100644 --- a/src/object/motion/motion.h +++ b/src/object/motion/motion.h @@ -38,7 +38,6 @@ class COldModelManager; } class CApplication; -class CBrain; class CPhysics; class COldObject; class CRobotMain; diff --git a/src/object/motion/motionvehicle.cpp b/src/object/motion/motionvehicle.cpp index 5b3762da..05bcd2e5 100644 --- a/src/object/motion/motionvehicle.cpp +++ b/src/object/motion/motionvehicle.cpp @@ -30,11 +30,11 @@ #include "math/geometry.h" -#include "object/brain.h" #include "object/object_manager.h" #include "object/old_object.h" #include "object/interface/powered_object.h" +#include "object/interface/programmable_object.h" #include "object/interface/transportable_object.h" #include "physics/physics.h" diff --git a/src/object/object.h b/src/object/object.h index e47cdc4a..0beef7d5 100644 --- a/src/object/object.h +++ b/src/object/object.h @@ -35,6 +35,8 @@ namespace Gfx struct ModelCrashSphere; } // namespace Gfx +class CLevelParserLine; + /** * \class CObject * \brief Base class for all 3D in-game objects diff --git a/src/object/object_factory.cpp b/src/object/object_factory.cpp index 80e4d2df..1030d89f 100644 --- a/src/object/object_factory.cpp +++ b/src/object/object_factory.cpp @@ -30,7 +30,6 @@ #include "math/geometry.h" -#include "object/brain.h" #include "object/object_create_params.h" #include "object/old_object.h" #include "object/robotmain.h" @@ -2632,7 +2631,6 @@ CObjectUPtr CObjectFactory::CreateVehicle(const ObjectCreateParams& params) obj->SetShowLimitRadius(showLimitRadius); auto physics = MakeUnique(obj.get()); - auto brain = MakeUnique(obj.get()); std::unique_ptr motion; if ( type == OBJECT_HUMAN || @@ -2649,14 +2647,12 @@ CObjectUPtr CObjectFactory::CreateVehicle(const ObjectCreateParams& params) motion = MakeUnique(obj.get()); } - brain->SetMotion(motion.get()); - brain->SetPhysics(physics.get()); motion->SetPhysics(physics.get()); physics->SetMotion(motion.get()); motion->Create(pos, angle, type, power, m_oldModelManager); - obj->SetBrain(std::move(brain)); + obj->SetProgrammable(true); obj->SetMotion(std::move(motion)); obj->SetPhysics(std::move(physics)); @@ -2677,7 +2673,6 @@ CObjectUPtr CObjectFactory::CreateInsect(const ObjectCreateParams& params) obj->SetTeam(params.team); auto physics = MakeUnique(obj.get()); - auto brain = MakeUnique(obj.get()); std::unique_ptr motion; if ( type == OBJECT_MOTHER ) @@ -2703,15 +2698,13 @@ CObjectUPtr CObjectFactory::CreateInsect(const ObjectCreateParams& params) assert(motion != nullptr); physics->SetMotion(motion.get()); - brain->SetMotion(motion.get()); - brain->SetPhysics(physics.get()); motion->SetPhysics(physics.get()); motion->Create(pos, angle, type, 0.0f, m_oldModelManager); obj->SetMotion(std::move(motion)); obj->SetPhysics(std::move(physics)); - obj->SetBrain(std::move(brain)); + obj->SetProgrammable(true); return std::move(obj); } diff --git a/src/object/old_object.cpp b/src/object/old_object.cpp index 00669e34..1877a2a5 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -37,7 +37,6 @@ #include "math/geometry.h" -#include "object/brain.h" #include "object/object_manager.h" #include "object/robotmain.h" @@ -56,11 +55,16 @@ #include "physics/physics.h" #include "script/cbottoken.h" +#include "script/script.h" #include "script/scriptfunc.h" #include "ui/object_interface.h" +#include "ui/studio.h" + +#include "ui/controls/edit.h" #include +#include @@ -83,6 +87,8 @@ static float debug_arm2 = 0.0f; static float debug_arm3 = 0.0f; #endif +const int MAXTRACERECORD = 1000; + // Object's constructor. @@ -96,7 +102,7 @@ COldObject::COldObject(int id) , CCarrierObject(m_implementedInterfaces) , CPoweredObject(m_implementedInterfaces) { - // A bit of a hack since CBrain is set externally in SetBrain() + // A bit of a hack since we don't have subclasses yet, set externally in SetProgrammable() m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = false; // Another hack m_implementedInterfaces[static_cast(ObjectInterfaceType::Jostleable)] = false; @@ -191,6 +197,18 @@ COldObject::COldObject(int id) m_activity = true; + m_currentProgram = nullptr; + m_bActiveVirus = false; + m_time = 0.0f; + m_burnTime = 0.0f; + + m_buttonAxe = EVENT_NULL; + + m_scriptRun = nullptr; + m_soluceName[0] = 0; + + m_traceRecord = false; + DeleteAllCrashSpheres(); m_botVar = CScriptFunctions::CreateObjectVar(this); @@ -331,18 +349,18 @@ void COldObject::DeleteObject(bool bAll) if ( !bAll ) m_main->CreateShortcuts(); } -// Simplifies a object (he was the brain, among others). +// Simplifies a object (he was the programmable, among others). void COldObject::Simplify() { - m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = false; - - if ( m_brain != nullptr ) + if ( Implements(ObjectInterfaceType::Programmable) ) { - m_brain->StopProgram(); + StopProgram(); } m_main->SaveOneScript(this); + m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = false; + if ( m_physics != nullptr ) { m_physics->DeleteObject(); @@ -355,11 +373,6 @@ void COldObject::Simplify() m_objectInterface.reset(); } - if ( m_brain != nullptr ) - { - m_brain.reset(); - } - if ( m_motion != nullptr ) { m_motion->DeleteObject(); @@ -568,9 +581,9 @@ bool COldObject::ExplodeObject(ExplosionType type, float force, float decay) if ( shield == 0.0f ) // dead? { - if ( m_brain != nullptr ) + if ( Implements(ObjectInterfaceType::Programmable) ) { - m_brain->StopProgram(); + StopProgram(); } m_main->SaveOneScript(this); } @@ -839,9 +852,14 @@ void COldObject::Write(CLevelParserLine* line) m_motion->Write(line); } - if ( m_brain != nullptr ) + if ( Implements(ObjectInterfaceType::Programmable) ) { - m_brain->Write(line); + line->AddParam("bVirusActive", MakeUnique(m_bActiveVirus)); + + if ( m_type == OBJECT_MOBILErs ) + { + line->AddParam("bShieldActive", MakeUnique(IsBackgroundTask())); + } } if ( m_physics != nullptr ) @@ -905,9 +923,16 @@ void COldObject::Read(CLevelParserLine* line) m_motion->Read(line); } - if ( m_brain != nullptr ) + if ( Implements(ObjectInterfaceType::Programmable) ) { - m_brain->Read(line); + m_bActiveVirus = line->GetParam("bVirusActive")->AsBool(false); + if ( m_type == OBJECT_MOBILErs ) + { + if( line->GetParam("bShieldActive")->AsBool(false) ) + { + StartTaskShield(TSM_START); + } + } } if ( m_physics != nullptr ) { @@ -1857,9 +1882,103 @@ bool COldObject::EventProcess(const Event &event) } } - if ( m_brain != nullptr ) + if ( Implements(ObjectInterfaceType::Programmable) ) { - m_brain->EventProcess(event); + if ( GetRuin() && m_currentProgram != nullptr ) + { + StopProgram(); + } + + if ( !GetSelect() && // robot pas sélectionné ? + m_currentProgram == nullptr && + !IsForegroundTask() ) + { + float axeX = 0.0f; + float axeY = 0.0f; + float axeZ = 0.0f; + if ( m_bBurn ) // Gifted? + { + axeZ = -1.0f; // tomb + + if ( !GetFixed() && + (m_type == OBJECT_ANT || + m_type == OBJECT_SPIDER || + m_type == OBJECT_WORM ) ) + { + axeY = 2.0f; // zigzag disorganized fast + if ( m_type == OBJECT_WORM ) axeY = 5.0f; + axeX = 0.5f+sinf(m_time* 1.0f)*0.5f+ + sinf(m_time* 6.0f)*2.0f+ + sinf(m_time*21.0f)*0.2f; + float factor = 1.0f-m_burnTime/15.0f; // slow motion + if ( factor < 0.0f ) factor = 0.0f; + axeY *= factor; + axeX *= factor; + } + } + m_physics->SetMotorSpeedX(axeY); // move forward/move back + m_physics->SetMotorSpeedY(axeZ); // up / down + m_physics->SetMotorSpeedZ(axeX); // rotate + } + else if (GetSelect()) + { + if ( (IsForegroundTask() && GetForegroundTask()->IsPilot()) || m_currentProgram == nullptr ) + { + if ( event.type == EVENT_OBJECT_LEFT || + event.type == EVENT_OBJECT_RIGHT || + event.type == EVENT_OBJECT_UP || + event.type == EVENT_OBJECT_DOWN || + event.type == EVENT_OBJECT_GASUP || + event.type == EVENT_OBJECT_GASDOWN ) + { + m_buttonAxe = event.type; + } + if ( event.type == EVENT_MOUSE_BUTTON_UP ) + { + m_buttonAxe = EVENT_NULL; + } + + float axeX = event.motionInput.x; + float axeY = event.motionInput.y; + float axeZ = event.motionInput.z; + + if ( (!m_main->GetTrainerPilot() && + GetTrainer()) || + !m_main->CanPlayerInteract() ) // drive vehicle? + { + axeX = 0.0f; + axeY = 0.0f; + axeZ = 0.0f; // Remote control impossible! + } + + if ( m_buttonAxe == EVENT_OBJECT_LEFT ) axeX = -1.0f; + if ( m_buttonAxe == EVENT_OBJECT_RIGHT ) axeX = 1.0f; + if ( m_buttonAxe == EVENT_OBJECT_UP ) axeY = 1.0f; + if ( m_buttonAxe == EVENT_OBJECT_DOWN ) axeY = -1.0f; + if ( m_buttonAxe == EVENT_OBJECT_GASUP ) axeZ = 1.0f; + if ( m_buttonAxe == EVENT_OBJECT_GASDOWN ) axeZ = -1.0f; + + if ( m_type == OBJECT_MOBILEdr && GetManual() ) // scribbler in manual mode? + { + if ( axeX != 0.0f ) axeY = 0.0f; // if running -> not moving! + axeX *= 0.5f; + axeY *= 0.5f; + } + + if ( !m_main->IsResearchDone(RESEARCH_FLY, GetTeam()) ) + { + axeZ = -1.0f; // tomb + } + + axeX += m_camera->GetMotorTurn(); // additional power according to camera + if ( axeX > 1.0f ) axeX = 1.0f; + if ( axeX < -1.0f ) axeX = -1.0f; + + m_physics->SetMotorSpeedX(axeY); // move forward/move back + m_physics->SetMotorSpeedY(axeZ); // up/down + m_physics->SetMotorSpeedZ(axeX); // rotate + } + } } if ( m_objectInterface != nullptr ) @@ -1903,8 +2022,12 @@ bool COldObject::EventFrame(const Event &event) return true; } + m_time += event.rTime; + if ( m_engine->GetPause() && m_type != OBJECT_SHOW ) return true; + if ( m_bBurn ) m_burnTime += event.rTime; + m_aTime += event.rTime; m_shotTime += event.rTime; @@ -1929,6 +2052,25 @@ bool COldObject::EventFrame(const Event &event) } } + if (Implements(ObjectInterfaceType::Programmable)) + { + if ( GetActivity() ) + { + if ( m_currentProgram != nullptr ) // current program? + { + if ( m_currentProgram->script->Continue() ) + { + StopProgram(); + } + } + + if ( m_traceRecord ) // registration of the design in progress? + { + TraceRecordFrame(); + } + } + } + // NOTE: This MUST be called AFTER CScriptFunctions::Process, otherwise weird stuff may happen to scripts EndedTask(); @@ -2404,9 +2546,9 @@ void COldObject::SetVirusMode(bool bEnable) m_bVirusMode = bEnable; m_virusTime = 0.0f; - if ( m_bVirusMode && m_brain != nullptr ) + if ( m_bVirusMode && Implements(ObjectInterfaceType::Programmable) ) { - if ( !m_brain->IntroduceVirus() ) // tries to infect + if ( !IntroduceVirus() ) // tries to infect { m_bVirusMode = false; // program was not contaminated! } @@ -2679,6 +2821,7 @@ bool COldObject::IsExploding() void COldObject::SetBurn(bool bBurn) { m_bBurn = bBurn; + m_burnTime = 0.0f; //? if ( m_botVar != 0 ) //? { @@ -2696,9 +2839,9 @@ void COldObject::SetDead(bool bDead) { m_bDead = bDead; - if ( bDead && m_brain != nullptr ) + if ( bDead && Implements(ObjectInterfaceType::Programmable) ) { - m_brain->StopProgram(); // stops the current task + StopProgram(); // stops the current task } //? if ( m_botVar != 0 ) @@ -2827,14 +2970,6 @@ void COldObject::SetShowLimitRadius(float radius) m_showLimitRadius = radius; } -// Indicates whether a program is under execution. - -bool COldObject::IsProgram() -{ - if ( m_brain == nullptr ) return false; - return m_brain->IsProgram(); -} - // Creates or removes particles associated to the object. @@ -3082,17 +3217,10 @@ void COldObject::SetPhysics(std::unique_ptr physics) m_physics = std::move(physics); } -// Returns the brain associated to the object. - -CBrain* COldObject::GetBrain() +// TODO: Temporary hack until we'll have subclasses for objects +void COldObject::SetProgrammable(bool programmable) { - return m_brain.get(); -} - -void COldObject::SetBrain(std::unique_ptr brain) -{ - m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = true; - m_brain = std::move(brain); + m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = programmable; } // Returns the movement associated to the object. @@ -3497,3 +3625,512 @@ void COldObject::UpdateInterface() m_objectInterface->UpdateInterface(); } } + + + +// Stops the running program. + +void COldObject::StopProgram() +{ + StopForegroundTask(); + + if ( m_type == OBJECT_HUMAN || + m_type == OBJECT_TECH ) return; + + if ( m_currentProgram != nullptr ) + { + m_currentProgram->script->Stop(); + } + + m_currentProgram = nullptr; + + m_physics->SetMotorSpeedX(0.0f); + m_physics->SetMotorSpeedY(0.0f); + m_physics->SetMotorSpeedZ(0.0f); + + m_motion->SetAction(-1); + + UpdateInterface(); + m_main->UpdateShortcuts(); + CreateSelectParticle(); +} + + +// Introduces a virus into a program. +// Returns true if it was inserted. + +bool COldObject::IntroduceVirus() +{ + if(m_program.size() == 0) return false; + + for ( int i=0 ; i<50 ; i++ ) + { + int j = rand()%m_program.size(); + if ( m_program[j]->script->IntroduceVirus() ) // tries to introduce + { + m_bActiveVirus = true; // active virus + return true; + } + } + return false; +} + +// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus) +// letters which automatically disappear after a while, +// ActiveVirus does not disappear after you edit the program +// (Even if the virus is not fixed). + + +void COldObject::SetActiveVirus(bool bActive) +{ + m_bActiveVirus = bActive; + + if ( !m_bActiveVirus ) // virus disabled? + { + SetVirusMode(false); // chtites (??? - Programerus) letters also + } +} + +bool COldObject::GetActiveVirus() +{ + return m_bActiveVirus; +} + +// Indicates whether a program is running. + +bool COldObject::IsProgram() +{ + return m_currentProgram != nullptr; +} + +// Starts a program. + +void COldObject::RunProgram(Program* program) +{ + if ( program->script->Run() ) + { + m_currentProgram = program; // start new program + UpdateInterface(); + CreateSelectParticle(); + m_main->UpdateShortcuts(); + if(GetTrainer()) + m_main->StartMissionTimer(); + } +} + + +// Returns the current program. + +int COldObject::GetProgram() +{ + if(m_currentProgram == nullptr) + return -1; + + for(unsigned int i = 0; i < m_program.size(); i++) + { + if(m_program[i].get() == m_currentProgram) + { + return i; + } + } + return -1; +} + + +// Name management scripts to load. + +void COldObject::SetScriptRun(Program* program) +{ + m_scriptRun = program; +} + +Program* COldObject::GetScriptRun() +{ + return m_scriptRun; +} + +void COldObject::SetSoluceName(char *name) +{ + strcpy(m_soluceName, name); +} + +char* COldObject::GetSoluceName() +{ + return m_soluceName; +} + + +// Load a script solution, in the first free script. +// If there is already an identical script, nothing is loaded. + +bool COldObject::ReadSoluce(char* filename) +{ + Program* prog = AddProgram(); + + if ( !ReadProgram(prog, filename) ) return false; // load solution + prog->readOnly = true; + + for(unsigned int i = 0; i < m_program.size(); i++) + { + if(m_program[i].get() == prog) continue; + + //TODO: This is bad. It's very sensitive to things like \n vs \r\n etc. + if ( m_program[i]->script->Compare(prog->script.get()) ) // the same already? + { + m_program[i]->readOnly = true; // Mark is as read-only + RemoveProgram(prog); + return false; + } + } + + return true; +} + +// Load a script with a text file. + +bool COldObject::ReadProgram(Program* program, const char* filename) +{ + if ( program->script->ReadScript(filename) ) return true; + + return false; +} + +// Indicates whether a program is compiled correctly. + +bool COldObject::GetCompile(Program* program) +{ + return program->script->GetCompile(); +} + +// Saves a script in a text file. + +bool COldObject::WriteProgram(Program* program, const char* filename) +{ + if ( program->script->WriteScript(filename) ) return true; + + return false; +} + + +// Load a stack of script implementation from a file. + +bool COldObject::ReadStack(FILE *file) +{ + short op; + + fRead(&op, sizeof(short), 1, file); + if ( op == 1 ) // run ? + { + fRead(&op, sizeof(short), 1, file); // program rank + if ( op >= 0 ) + { + assert(op < static_cast(m_program.size())); //TODO: is it good? + + //TODO: m_selScript = op; + + if ( !m_program[op]->script->ReadStack(file) ) return false; + } + } + + return true; +} + +// Save the script implementation stack of a file. + +bool COldObject::WriteStack(FILE *file) +{ + short op; + + if ( m_currentProgram != nullptr && // current program? + m_currentProgram->script->IsRunning() ) + { + op = 1; // run + fWrite(&op, sizeof(short), 1, file); + + op = GetProgram(); + fWrite(&op, sizeof(short), 1, file); + + return m_currentProgram->script->WriteStack(file); + } + + op = 0; // stop + fWrite(&op, sizeof(short), 1, file); + return true; +} + + + +// Start of registration of the design. + +void COldObject::TraceRecordStart() +{ + if (m_traceRecord) + { + TraceRecordStop(); + } + + CMotionVehicle* motionVehicle = dynamic_cast(m_motion.get()); + assert(motionVehicle != nullptr); + + m_traceRecord = true; + + m_traceOper = TO_STOP; + + m_tracePos = GetPosition(); + m_traceAngle = GetRotationY(); + + if ( motionVehicle->GetTraceDown() ) // pencil down? + { + m_traceColor = motionVehicle->GetTraceColor(); + } + else // pen up? + { + m_traceColor = TraceColor::Default; + } + + m_traceRecordBuffer = MakeUniqueArray(MAXTRACERECORD); + m_traceRecordIndex = 0; +} + +// Saving the current drawing. + +void COldObject::TraceRecordFrame() +{ + TraceOper oper = TO_STOP; + Math::Vector pos; + float angle, len, speed; + + CMotionVehicle* motionVehicle = dynamic_cast(m_motion.get()); + assert(motionVehicle != nullptr); + + speed = m_physics->GetLinMotionX(MO_REASPEED); + if ( speed > 0.0f ) oper = TO_ADVANCE; + if ( speed < 0.0f ) oper = TO_RECEDE; + + speed = m_physics->GetCirMotionY(MO_REASPEED); + if ( speed != 0.0f ) oper = TO_TURN; + + TraceColor color = TraceColor::Default; + if ( motionVehicle->GetTraceDown() ) // pencil down? + { + color = motionVehicle->GetTraceColor(); + } + + if ( oper != m_traceOper || + color != m_traceColor ) + { + if ( m_traceOper == TO_ADVANCE || + m_traceOper == TO_RECEDE ) + { + pos = GetPosition(); + len = Math::DistanceProjected(pos, m_tracePos); + TraceRecordOper(m_traceOper, len); + } + if ( m_traceOper == TO_TURN ) + { + angle = GetRotationY()-m_traceAngle; + TraceRecordOper(m_traceOper, angle); + } + + if ( color != m_traceColor ) + { + TraceRecordOper(TO_PEN, static_cast(color)); + } + + m_traceOper = oper; + m_tracePos = GetPosition(); + m_traceAngle = GetRotationY(); + m_traceColor = color; + } +} + +// End of the registration of the design. Program generates the CBOT. + +void COldObject::TraceRecordStop() +{ + TraceOper lastOper, curOper; + float lastParam, curParam; + + m_traceRecord = false; + + std::stringstream buffer; + buffer << "extern void object::AutoDraw()\n{\n"; + + lastOper = TO_STOP; + lastParam = 0.0f; + for ( int i=0 ; iscript->SendScript(buffer.str().c_str()); +} + +// Saves an instruction CBOT. + +bool COldObject::TraceRecordOper(TraceOper oper, float param) +{ + int i; + + i = m_traceRecordIndex; + if ( i >= MAXTRACERECORD ) return false; + + m_traceRecordBuffer[i].oper = oper; + m_traceRecordBuffer[i].param = param; + + m_traceRecordIndex = i+1; + return true; +} + +// Generates an instruction CBOT. + +bool COldObject::TraceRecordPut(std::stringstream& buffer, TraceOper oper, float param) +{ + if ( oper == TO_ADVANCE ) + { + param /= g_unit; + buffer << "\tmove(" << std::fixed << std::setprecision(1) << param << ");\n"; + } + + if ( oper == TO_RECEDE ) + { + param /= g_unit; + buffer << "\tmove(-" << std::fixed << std::setprecision(1) << param << ");\n"; + } + + if ( oper == TO_TURN ) + { + param = -param*180.0f/Math::PI; + buffer << "\tturn(" << static_cast(param) << ");\n"; + } + + if ( oper == TO_PEN ) + { + TraceColor color = static_cast(static_cast(param)); + if ( color == TraceColor::Default ) + buffer << "\tpenup();\n"; + else + buffer << "\tpendown(" << TraceColorName(color) << ");\n"; + } + + return true; +} + +bool COldObject::IsTraceRecord() +{ + return m_traceRecord; +} + +Program* COldObject::AddProgram() +{ + auto program = MakeUnique(); + program->script = MakeUnique(this); + program->readOnly = false; + program->runnable = true; + + Program* prog = program.get(); + AddProgram(std::move(program)); + return prog; +} + +void COldObject::AddProgram(std::unique_ptr program) +{ + m_program.push_back(std::move(program)); + UpdateInterface(); +} + +void COldObject::RemoveProgram(Program* program) +{ + if(m_currentProgram == program) + { + StopProgram(); + } + m_program.erase( + std::remove_if(m_program.begin(), m_program.end(), + [program](std::unique_ptr& prog) { return prog.get() == program; }), + m_program.end()); +} + +Program* COldObject::CloneProgram(Program* program) +{ + Program* newprog = AddProgram(); + + // TODO: Is there any reason CScript doesn't have a function to get the program code directly? + Ui::CEdit* edit = new Ui::CEdit(); + edit->SetMaxChar(Ui::EDITSTUDIOMAX); + program->script->PutScript(edit, ""); + newprog->script->GetScript(edit); + delete edit; + + return newprog; +} + +std::vector>& COldObject::GetPrograms() +{ + return m_program; +} + +int COldObject::GetProgramCount() +{ + return static_cast(m_program.size()); +} + +int COldObject::GetProgramIndex(Program* program) +{ + for(unsigned int i = 0; i < m_program.size(); i++) + { + if(m_program[i].get() == program) + { + return i; + } + } + return -1; +} + +Program* COldObject::GetProgram(int index) +{ + if(index < 0 || index >= static_cast(m_program.size())) + return nullptr; + + return m_program[index].get(); +} + +Program* COldObject::GetOrAddProgram(int index) +{ + if(index < 0) + return nullptr; + + if(index < static_cast(m_program.size())) + return m_program[index].get(); + + for(int i = m_program.size(); i < index; i++) + { + AddProgram(); + } + return AddProgram(); +} diff --git a/src/object/old_object.h b/src/object/old_object.h index dc27c15f..7617bd15 100644 --- a/src/object/old_object.h +++ b/src/object/old_object.h @@ -55,6 +55,21 @@ struct ObjectPart Math::Matrix matWorld; }; +enum TraceOper +{ + TO_STOP = 0, // stop + TO_ADVANCE = 1, // advance + TO_RECEDE = 2, // back + TO_TURN = 3, // rotate + TO_PEN = 4, // color change +}; + +struct TraceRecord +{ + TraceOper oper; + float param; +}; + namespace Ui { class CObjectInterface; @@ -76,7 +91,7 @@ class COldObject : public CObject, protected: void DeleteObject(bool bAll=false); void SetPhysics(std::unique_ptr physics); - void SetBrain(std::unique_ptr brain); + void SetProgrammable(bool programmable); void SetMotion(std::unique_ptr motion); void SetAuto(std::unique_ptr automat); void SetShowLimitRadius(float radius); @@ -227,8 +242,8 @@ public: //! Management of object "activity" (temporairly stops program execution, right now used only by Aliens in eggs) //@{ - void SetActivity(bool activity); - bool GetActivity(); + void SetActivity(bool activity) override; + bool GetActivity() override; //@} void SetVisible(bool bVisible); @@ -270,14 +285,12 @@ public: bool StartShowLimit() override; void StopShowLimit() override; - bool IsProgram() override; void CreateSelectParticle(); void SetRunScript(CScript* script); CScript* GetRunScript() override; CBotVar* GetBotVar() override; CPhysics* GetPhysics() override; - CBrain* GetBrain() override; CMotion* GetMotion() override; CAuto* GetAuto() override; @@ -336,6 +349,45 @@ public: void UpdateInterface(); + bool IsProgram() override; + void RunProgram(Program* program) override; + int GetProgram() override; + void StopProgram() override; + + bool IntroduceVirus() override; + void SetActiveVirus(bool bActive) override; + bool GetActiveVirus() override; + + void SetScriptRun(Program* rank) override; + Program* GetScriptRun() override; + void SetSoluceName(char *name) override; + char* GetSoluceName() override; + + bool ReadSoluce(char* filename) override; + bool ReadProgram(Program* program, const char* filename) override; + bool GetCompile(Program* program) override; + bool WriteProgram(Program* program, const char* filename) override; + bool ReadStack(FILE *file) override; + bool WriteStack(FILE *file) override; + + Program* AddProgram() override; + void AddProgram(std::unique_ptr program) override; + void RemoveProgram(Program* program) override; + Program* CloneProgram(Program* program) override; + + std::vector>& GetPrograms() override; + int GetProgramCount() override; + Program* GetProgram(int index) override; + Program* GetOrAddProgram(int index) override; + int GetProgramIndex(Program* program) override; + + //! Start recording trace + void TraceRecordStart() override; + //! Stop recording trace and generate CBot program + void TraceRecordStop() override; + //! Returns true if trace recording is in progress + bool IsTraceRecord() override; + protected: bool EventFrame(const Event &event); void VirusFrame(float rTime); @@ -352,6 +404,13 @@ protected: Error EndedTask(); + //! Save current status to recording buffer + void TraceRecordFrame(); + //! Save this operation to recording buffer + bool TraceRecordOper(TraceOper oper, float param); + //! Convert this recording operation to CBot instruction + bool TraceRecordPut(std::stringstream& buffer, TraceOper oper, float param); + protected: Gfx::CEngine* m_engine; Gfx::CLightManager* m_lightMan; @@ -362,7 +421,6 @@ protected: CSoundInterface* m_sound; std::unique_ptr m_physics; - std::unique_ptr m_brain; std::unique_ptr m_motion; std::unique_ptr m_auto; std::unique_ptr m_objectInterface; @@ -441,4 +499,25 @@ protected: bool m_activity; std::unique_ptr m_foregroundTask; std::unique_ptr m_backgroundTask; + + std::vector> m_program; + Program* m_currentProgram; + + bool m_bActiveVirus; + + Program* m_scriptRun; + char m_soluceName[50]; + + EventType m_buttonAxe; + + float m_time; + float m_burnTime; + + bool m_traceRecord; + TraceOper m_traceOper; + Math::Vector m_tracePos; + float m_traceAngle; + TraceColor m_traceColor; + int m_traceRecordIndex; + std::unique_ptr m_traceRecordBuffer; }; diff --git a/src/object/old_object_interface.cpp b/src/object/old_object_interface.cpp index bff54746..60011b36 100644 --- a/src/object/old_object_interface.cpp +++ b/src/object/old_object_interface.cpp @@ -397,11 +397,6 @@ void COldObjectInterface::StopShowLimit() } -bool COldObjectInterface::IsProgram() -{ - throw std::logic_error("IsProgram: not implemented!"); -} - CScript* COldObjectInterface::GetRunScript() { throw std::logic_error("GetRunScript: not implemented!"); diff --git a/src/object/old_object_interface.h b/src/object/old_object_interface.h index 166a262f..b986fc8e 100644 --- a/src/object/old_object_interface.h +++ b/src/object/old_object_interface.h @@ -33,17 +33,11 @@ #include -class CApplication; class CPhysics; -class CBrain; class CMotion; class CAuto; -class CDisplayText; -class CRobotMain; class CBotVar; class CScript; -class CLevelParserLine; -struct Program; struct Character @@ -175,8 +169,6 @@ public: virtual bool StartShowLimit(); virtual void StopShowLimit(); - virtual bool IsProgram(); - virtual CScript* GetRunScript(); virtual CBotVar* GetBotVar(); virtual CPhysics* GetPhysics(); @@ -192,4 +184,3 @@ public: virtual float GetInfoReturn(); }; - diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp index 6c52dade..cf33f968 100644 --- a/src/object/robotmain.cpp +++ b/src/object/robotmain.cpp @@ -56,7 +56,6 @@ #include "math/const.h" #include "math/geometry.h" -#include "object/brain.h" #include "object/mainmovie.h" #include "object/object.h" #include "object/object_create_exception.h" @@ -3468,13 +3467,13 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) m_controller->SetIgnoreBuildCheck(true); if (m_controller->Implements(ObjectInterfaceType::Programmable)) { - CBrain* brain = dynamic_cast(m_controller)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(m_controller); if (line->GetParam("script")->IsDefined()) { - Program* program = brain->AddProgram(); + Program* program = programmable->AddProgram(); program->filename = "../" + line->GetParam("script")->AsPath("ai"); program->readOnly = true; - brain->SetScriptRun(program); + programmable->SetScriptRun(program); } } continue; @@ -3637,7 +3636,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) std::map loadedPrograms; if (oldObj->Implements(ObjectInterfaceType::Programmable)) { - CBrain* brain = dynamic_cast(oldObj)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(oldObj); bool allFilled = true; for (int i = 0; i < 10 || allFilled; i++) @@ -3647,7 +3646,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) std::string opRunnable = "scriptRunnable" + boost::lexical_cast(i+1); // scriptRunnable1..scriptRunnable10 if (line->GetParam(op)->IsDefined()) { - Program* program = brain->AddProgram(); + Program* program = programmable->AddProgram(); program->filename = "../" + line->GetParam(op)->AsPath("ai"); program->readOnly = line->GetParam(opReadOnly)->AsBool(true); program->runnable = line->GetParam(opRunnable)->AsBool(true); @@ -3663,7 +3662,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (i != 0) { run = i-1; - brain->SetScriptRun(loadedPrograms[run]); + programmable->SetScriptRun(loadedPrograms[run]); } } CAuto* automat = oldObj->GetAuto(); @@ -3688,7 +3687,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) } if (soluce && oldObj->Implements(ObjectInterfaceType::Programmable) && line->GetParam("soluce")->IsDefined()) - dynamic_cast(oldObj)->GetBrain() + dynamic_cast(oldObj) ->SetSoluceName(const_cast(line->GetParam("soluce")->AsPath("ai").c_str())); if (line->GetParam("reset")->AsBool(false)) @@ -4684,27 +4683,27 @@ void CRobotMain::CompileScript(bool soluce) m_ui->GetLoadingScreen()->SetProgress(0.75f+objectProgress*0.25f, RT_LOADING_PROGRAMS, "for object "+StrUtils::ToString(objCounter+1)+" / "+StrUtils::ToString(numObjects)); objCounter++; - CBrain* brain = dynamic_cast(obj)->GetBrain(); - for (auto& prog : brain->GetPrograms()) + CProgrammableObject* programmable = dynamic_cast(obj); + for (auto& prog : programmable->GetPrograms()) { Program* program = prog.get(); if (program->filename.empty()) continue; std::string name = "ai/" + program->filename; - if (! brain->ReadProgram(program, const_cast(name.c_str()))) + if (! programmable->ReadProgram(program, const_cast(name.c_str()))) { GetLogger()->Error("Unable to read script from file \"%s\"\n", name.c_str()); } - //? if (!brain->GetCompile(program)) nbError++; + //? if (!programmable->GetCompile(program)) nbError++; } if (soluce) { - char* name = brain->GetSoluceName(); + char* name = programmable->GetSoluceName(); if (name[0] != 0) { - brain->ReadSoluce(name); // load solution + programmable->ReadSoluce(name); // load solution } } @@ -4716,11 +4715,11 @@ void CRobotMain::CompileScript(bool soluce) { if (! obj->Implements(ObjectInterfaceType::Programmable)) continue; - CBrain* brain = dynamic_cast(obj)->GetBrain(); - Program* program = brain->GetScriptRun(); + CProgrammableObject* programmable = dynamic_cast(obj); + Program* program = programmable->GetScriptRun(); if (program != nullptr) { - brain->RunProgram(program); // starts the program + programmable->RunProgram(program); // starts the program } } } @@ -4730,7 +4729,7 @@ void CRobotMain::LoadOneScript(CObject *obj) { if (! obj->Implements(ObjectInterfaceType::Programmable)) return; - CBrain* brain = dynamic_cast(obj)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(obj); if (!IsSelectable(obj)) return; @@ -4749,10 +4748,10 @@ void CRobotMain::LoadOneScript(CObject *obj) if (CResourceManager::Exists(filename)) { - Program* program = brain->GetOrAddProgram(i); - if(brain->GetCompile(program)) continue; // If already loaded (e.g. from level file), skip - brain->ReadProgram(program, filename.c_str()); - //? if (!brain->GetCompile(program)) nbError++; + Program* program = programmable->GetOrAddProgram(i); + if(programmable->GetCompile(program)) continue; // If already loaded (e.g. from level file), skip + programmable->ReadProgram(program, filename.c_str()); + //? if (!programmable->GetCompile(program)) nbError++; } } } @@ -4764,7 +4763,7 @@ void CRobotMain::LoadFileScript(CObject *obj, const char* filename, int objRank) if (! obj->Implements(ObjectInterfaceType::Programmable)) return; - CBrain* brain = dynamic_cast(obj)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(obj); ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return; @@ -4778,9 +4777,9 @@ void CRobotMain::LoadFileScript(CObject *obj, const char* filename, int objRank) sprintf(fn, "%s/prog%.3d%.3d.txt", dirname.c_str(), objRank, i); if (CResourceManager::Exists(fn)) { - Program* program = brain->GetOrAddProgram(i); - brain->ReadProgram(program, fn); - //? if (!brain->GetCompile(program)) nbError++; + Program* program = programmable->GetOrAddProgram(i); + programmable->ReadProgram(program, fn); + //? if (!programmable->GetCompile(program)) nbError++; } } } @@ -4800,7 +4799,7 @@ void CRobotMain::SaveOneScript(CObject *obj) { if (! obj->Implements(ObjectInterfaceType::Programmable)) return; - CBrain* brain = dynamic_cast(obj)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(obj); if (!IsSelectable(obj)) return; @@ -4811,7 +4810,7 @@ void CRobotMain::SaveOneScript(CObject *obj) if (objRank == -1) return; char categoryChar = GetLevelCategoryDir(m_levelCategory)[0]; - auto& programs = brain->GetPrograms(); + auto& programs = programmable->GetPrograms(); // TODO: Find a better way to do that for (unsigned int i = 0; i <= 999; i++) { @@ -4821,7 +4820,7 @@ void CRobotMain::SaveOneScript(CObject *obj) if (i < programs.size()) { - brain->WriteProgram(programs[i].get(), filename.c_str()); + programmable->WriteProgram(programs[i].get(), filename.c_str()); } else { @@ -4838,7 +4837,7 @@ void CRobotMain::SaveFileScript(CObject *obj, const char* filename, int objRank) if (! obj->Implements(ObjectInterfaceType::Programmable)) return; - CBrain* brain = dynamic_cast(obj)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(obj); ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return; @@ -4847,14 +4846,14 @@ void CRobotMain::SaveFileScript(CObject *obj, const char* filename, int objRank) dirname = dirname.substr(0, dirname.find_last_of("/")); char fn[MAX_FNAME]; //TODO: Refactor to std::string - auto& programs = brain->GetPrograms(); + auto& programs = programmable->GetPrograms(); // TODO: Find a better way to do that for (unsigned int i = 0; i <= 999; i++) { sprintf(fn, "%s/prog%.3d%.3d.txt", dirname.c_str(), objRank, i); if (i < programs.size()) { - brain->WriteProgram(programs[i].get(), fn); + programmable->WriteProgram(programs[i].get(), fn); } else { @@ -4870,12 +4869,12 @@ bool CRobotMain::SaveFileStack(CObject *obj, FILE *file, int objRank) if (! obj->Implements(ObjectInterfaceType::Programmable)) return true; - CBrain* brain = dynamic_cast(obj)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(obj); ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return true; - return brain->WriteStack(file); + return programmable->WriteStack(file); } //! Resumes the execution stack of the program in a robot @@ -4885,12 +4884,12 @@ bool CRobotMain::ReadFileStack(CObject *obj, FILE *file, int objRank) if (! obj->Implements(ObjectInterfaceType::Programmable)) return true; - CBrain* brain = dynamic_cast(obj)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(obj); ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return true; - return brain->ReadStack(file); + return programmable->ReadStack(file); } @@ -5005,15 +5004,15 @@ void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj) if (obj->Implements(ObjectInterfaceType::Programmable)) { - CBrain* brain = dynamic_cast(obj)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(obj); - int run = brain->GetProgram(); + int run = programmable->GetProgram(); if (run != -1) { line->AddParam("run", MakeUnique(run+1)); } - auto& programs = brain->GetPrograms(); + auto& programs = programmable->GetPrograms(); for (unsigned int i = 0; i < programs.size(); i++) { if (programs[i]->readOnly) @@ -5249,19 +5248,19 @@ CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const char* filename, if (obj->Implements(ObjectInterfaceType::Programmable)) { - CBrain* brain = dynamic_cast(obj)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(obj); if (run != -1) { - Program* program = brain->GetOrAddProgram(run-1); - brain->SetScriptRun(program); // marks the program to be started + Program* program = programmable->GetOrAddProgram(run-1); + programmable->SetScriptRun(program); // marks the program to be started } for (unsigned int i = 0; i <= 999; i++) { if (line->GetParam("scriptReadOnly" + boost::lexical_cast(i+1))->AsBool(false)) { - Program* prog = brain->GetOrAddProgram(i); + Program* prog = programmable->GetOrAddProgram(i); prog->readOnly = true; } } @@ -5371,12 +5370,12 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot) if (! obj->Implements(ObjectInterfaceType::Programmable)) continue; if (obj->GetDefRank() == -1) continue; - CBrain* brain = dynamic_cast(obj)->GetBrain(); + CProgrammableObject* programmable = dynamic_cast(obj); - Program* program = brain->GetScriptRun(); + Program* program = programmable->GetScriptRun(); if (program != nullptr) { - brain->RunProgram(program); // starts the program + programmable->RunProgram(program); // starts the program } } diff --git a/src/object/task/task.cpp b/src/object/task/task.cpp index db54fb48..95cfe114 100644 --- a/src/object/task/task.cpp +++ b/src/object/task/task.cpp @@ -43,10 +43,10 @@ CTask::CTask(COldObject* object) m_object = object; m_physics = m_object->GetPhysics(); - m_brain = nullptr; + m_programmable = nullptr; if (object->Implements(ObjectInterfaceType::Programmable)) { - m_brain = dynamic_cast(m_object)->GetBrain(); + m_programmable = dynamic_cast(m_object); } m_motion = m_object->GetMotion(); } @@ -88,4 +88,3 @@ bool CTask::Abort() { return true; } - diff --git a/src/object/task/task.h b/src/object/task/task.h index 4c5a546c..df721bd4 100644 --- a/src/object/task/task.h +++ b/src/object/task/task.h @@ -28,10 +28,10 @@ #include "math/const.h" -class CBrain; class CPhysics; class CMotion; class COldObject; +class CProgrammableObject; class CRobotMain; class CSoundInterface; @@ -80,11 +80,11 @@ protected: Gfx::CTerrain* m_terrain; Gfx::CWater* m_water; Gfx::CCamera* m_camera; - CMotion* m_motion; - CBrain* m_brain; - CPhysics* m_physics; - COldObject* m_object; CRobotMain* m_main; CSoundInterface* m_sound; -}; + COldObject* m_object; + CProgrammableObject* m_programmable; + CMotion* m_motion; + CPhysics* m_physics; +}; diff --git a/src/object/task/taskshield.cpp b/src/object/task/taskshield.cpp index f310817d..cf4199bc 100644 --- a/src/object/task/taskshield.cpp +++ b/src/object/task/taskshield.cpp @@ -27,7 +27,6 @@ #include "math/geometry.h" -#include "object/brain.h" #include "object/object_manager.h" #include "object/old_object.h" #include "object/robotmain.h" @@ -578,4 +577,3 @@ float CTaskShield::GetRadius() { return RADIUS_SHIELD_MIN + (RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)*m_object->GetParam(); } - diff --git a/src/object/task/taskterraform.cpp b/src/object/task/taskterraform.cpp index cbc387fa..0cb5af0d 100644 --- a/src/object/task/taskterraform.cpp +++ b/src/object/task/taskterraform.cpp @@ -25,13 +25,11 @@ #include "math/geometry.h" -#include "object/brain.h" #include "object/object_manager.h" #include "object/old_object.h" #include "object/robotmain.h" #include "object/interface/powered_object.h" -#include "object/interface/programmable_object.h" #include "object/motion/motionant.h" #include "object/motion/motionspider.h" diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index a4fc83c5..78dd0c2d 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -35,7 +35,6 @@ #include "math/geometry.h" -#include "object/brain.h" #include "object/object_manager.h" #include "object/old_object.h" #include "object/robotmain.h" @@ -3829,7 +3828,7 @@ Error CPhysics::GetError() if (m_object->Implements(ObjectInterfaceType::Programmable)) { - if ( dynamic_cast(m_object)->GetBrain()->GetActiveVirus() ) + if ( dynamic_cast(m_object)->GetActiveVirus() ) { return ERR_VEH_VIRUS; } diff --git a/src/physics/physics.h b/src/physics/physics.h index e8e221c9..463fdb2e 100644 --- a/src/physics/physics.h +++ b/src/physics/physics.h @@ -35,7 +35,6 @@ class CObject; class COldObject; -class CBrain; class CMotion; class CSoundInterface; class CLevelParserLine; @@ -111,7 +110,6 @@ public: bool EventProcess(const Event &event); - void SetBrain(CBrain* brain); void SetMotion(CMotion* motion); void SetType(PhysicsType type); @@ -216,11 +214,11 @@ protected: Gfx::CTerrain* m_terrain; Gfx::CWater* m_water; Gfx::CCamera* m_camera; - COldObject* m_object; - CBrain* m_brain; - CMotion* m_motion; CSoundInterface* m_sound; + COldObject* m_object; + CMotion* m_motion; + PhysicsType m_type; // TYPE_* float m_gravity; // force of gravity float m_time; // absolute time diff --git a/src/script/scriptfunc.cpp b/src/script/scriptfunc.cpp index 93bc25af..2034e7ef 100644 --- a/src/script/scriptfunc.cpp +++ b/src/script/scriptfunc.cpp @@ -35,7 +35,6 @@ #include "math/all.h" -#include "object/brain.h" #include "object/object.h" #include "object/object_manager.h" #include "object/robotmain.h" @@ -45,6 +44,7 @@ #include "object/auto/autobase.h" #include "object/auto/autofactory.h" +#include "object/interface/programmable_object.h" #include "object/interface/task_executor_object.h" #include "object/level/parser.h" @@ -1611,10 +1611,10 @@ bool CScriptFunctions::rProduce(CBotVar* var, CBotVar* result, int& exception, v std::string name2 = InjectLevelPathsForCurrentLevel(name, "ai"); if (object->Implements(ObjectInterfaceType::Programmable)) { - CBrain* brain = dynamic_cast(object)->GetBrain(); - Program* program = brain->AddProgram(); - brain->ReadProgram(program, name2.c_str()); - brain->RunProgram(program); + CProgrammableObject* programmable = dynamic_cast(object); + Program* program = programmable->AddProgram(); + programmable->ReadProgram(program, name2.c_str()); + programmable->RunProgram(program); } } diff --git a/src/ui/mainshort.cpp b/src/ui/mainshort.cpp index ca7ad6e7..c91a6889 100644 --- a/src/ui/mainshort.cpp +++ b/src/ui/mainshort.cpp @@ -27,6 +27,8 @@ #include "object/object.h" #include "object/object_manager.h" +#include "object/interface/programmable_object.h" + namespace Ui { @@ -233,7 +235,7 @@ bool CMainShort::UpdateShortcuts() if ( pc != nullptr ) { pc->SetState(STATE_CHECK, m_shortcuts[i]->GetSelect()); - pc->SetState(STATE_RUN, m_shortcuts[i]->IsProgram()); + pc->SetState(STATE_RUN, m_shortcuts[i]->Implements(ObjectInterfaceType::Programmable) && dynamic_cast(m_shortcuts[i])->IsProgram()); } } return true; diff --git a/src/ui/object_interface.cpp b/src/ui/object_interface.cpp index 068ac240..e3821e0d 100644 --- a/src/ui/object_interface.cpp +++ b/src/ui/object_interface.cpp @@ -28,7 +28,6 @@ #include "math/geometry.h" -#include "object/brain.h" #include "object/old_object.h" #include "object/interface/carrier_object.h" @@ -63,7 +62,7 @@ CObjectInterface::CObjectInterface(COldObject* object) assert(object->Implements(ObjectInterfaceType::TaskExecutor)); m_taskExecutor = dynamic_cast(m_object); assert(object->Implements(ObjectInterfaceType::Programmable)); - m_brain = dynamic_cast(m_object)->GetBrain(); + m_programmable = dynamic_cast(m_object); m_physics = m_object->GetPhysics(); m_motion = m_object->GetMotion(); @@ -194,8 +193,8 @@ bool CObjectInterface::EventProcess(const Event &event) index = data->key-KEY(1); else if(data->key == KEY(0)) index = 9; - if(index < 0) index = m_brain->GetProgramCount()-1; - if(index > static_cast(m_brain->GetProgramCount())-1) index = 0; + if(index < 0) index = m_programmable->GetProgramCount()-1; + if(index > static_cast(m_programmable->GetProgramCount())-1) index = 0; if(GetSelScript() != index) { @@ -226,29 +225,29 @@ bool CObjectInterface::EventProcess(const Event &event) if ( action == EVENT_OBJECT_PROGRUN ) { - if ( !m_brain->IsProgram() ) + if ( !m_programmable->IsProgram() ) { - if(m_selScript < m_brain->GetProgramCount()) + if(m_selScript < m_programmable->GetProgramCount()) { - m_brain->RunProgram(m_brain->GetProgram(m_selScript)); + m_programmable->RunProgram(m_programmable->GetProgram(m_selScript)); } } else { - m_brain->StopProgram(); + m_programmable->StopProgram(); } } if ( action == EVENT_OBJECT_PROGSTART ) { m_main->SaveOneScript(m_object); - if(m_selScript < m_brain->GetProgramCount()) + if(m_selScript < m_programmable->GetProgramCount()) { - m_brain->RunProgram(m_brain->GetProgram(m_selScript)); + m_programmable->RunProgram(m_programmable->GetProgram(m_selScript)); } } if ( action == EVENT_OBJECT_PROGSTOP ) { - m_brain->StopProgram(); + m_programmable->StopProgram(); } if ( action == EVENT_STUDIO_OK ) { @@ -263,8 +262,8 @@ bool CObjectInterface::EventProcess(const Event &event) if( action == EVENT_STUDIO_CLONE ) { StopEditScript(false); - Program* newProgram = m_brain->CloneProgram(m_brain->GetProgram(m_selScript)); - m_selScript = m_brain->GetProgramIndex(newProgram); + Program* newProgram = m_programmable->CloneProgram(m_programmable->GetProgram(m_selScript)); + m_selScript = m_programmable->GetProgramIndex(newProgram); m_main->SaveOneScript(m_object); UpdateInterface(); @@ -296,29 +295,29 @@ bool CObjectInterface::EventProcess(const Event &event) } } if ( m_taskExecutor->IsForegroundTask() || // current task? - m_brain->IsProgram() ) + m_programmable->IsProgram() ) { if ( action == EVENT_OBJECT_PROGRUN ) { - m_brain->StopProgram(); + m_programmable->StopProgram(); } if ( action == EVENT_OBJECT_PROGEDIT ) { - if(m_selScript < m_brain->GetProgramCount()) + if(m_selScript < m_programmable->GetProgramCount()) { - StartEditScript(m_brain->GetProgram(m_selScript), m_main->GetScriptName()); + StartEditScript(m_programmable->GetProgram(m_selScript), m_main->GetScriptName()); } } if ( !m_taskExecutor->IsForegroundTask() || !m_taskExecutor->GetForegroundTask()->IsPilot() ) return true; } - if ( !m_brain->IsProgram() ) + if ( !m_programmable->IsProgram() ) { if( action == EVENT_OBJECT_PROGADD ) { - Program* program = m_brain->AddProgram(); - m_selScript = m_brain->GetProgramIndex(program); + Program* program = m_programmable->AddProgram(); + m_selScript = m_programmable->GetProgramIndex(program); m_main->SaveOneScript(m_object); UpdateInterface(); @@ -332,11 +331,11 @@ bool CObjectInterface::EventProcess(const Event &event) if( action == EVENT_OBJECT_PROGREMOVE ) { - if(m_selScript < m_brain->GetProgramCount()) + if(m_selScript < m_programmable->GetProgramCount()) { - m_brain->RemoveProgram(m_brain->GetProgram(m_selScript)); - if(m_selScript >= m_brain->GetProgramCount()) - m_selScript = m_brain->GetProgramCount()-1; + m_programmable->RemoveProgram(m_programmable->GetProgram(m_selScript)); + if(m_selScript >= m_programmable->GetProgramCount()) + m_selScript = m_programmable->GetProgramCount()-1; m_main->SaveOneScript(m_object); UpdateInterface(); @@ -351,10 +350,10 @@ bool CObjectInterface::EventProcess(const Event &event) if( action == EVENT_OBJECT_PROGCLONE ) { - if(m_selScript < m_brain->GetProgramCount()) + if(m_selScript < m_programmable->GetProgramCount()) { - m_brain->CloneProgram(m_brain->GetProgram(m_selScript)); - m_selScript = m_brain->GetProgramCount()-1; + m_programmable->CloneProgram(m_programmable->GetProgram(m_selScript)); + m_selScript = m_programmable->GetProgramCount()-1; m_main->SaveOneScript(m_object); UpdateInterface(); @@ -370,7 +369,7 @@ bool CObjectInterface::EventProcess(const Event &event) if( action == EVENT_OBJECT_PROGMOVEUP ) { - std::iter_swap(m_brain->GetPrograms().begin() + m_selScript, m_brain->GetPrograms().begin() + m_selScript - 1); + std::iter_swap(m_programmable->GetPrograms().begin() + m_selScript, m_programmable->GetPrograms().begin() + m_selScript - 1); m_selScript--; m_main->SaveOneScript(m_object); @@ -385,7 +384,7 @@ bool CObjectInterface::EventProcess(const Event &event) if( action == EVENT_OBJECT_PROGMOVEDOWN ) { - std::iter_swap(m_brain->GetPrograms().begin() + m_selScript, m_brain->GetPrograms().begin() + m_selScript + 1); + std::iter_swap(m_programmable->GetPrograms().begin() + m_selScript, m_programmable->GetPrograms().begin() + m_selScript + 1); m_selScript++; m_main->SaveOneScript(m_object); @@ -407,25 +406,25 @@ bool CObjectInterface::EventProcess(const Event &event) if ( action == EVENT_OBJECT_PROGEDIT ) { - if(m_selScript < m_brain->GetProgramCount()) + if(m_selScript < m_programmable->GetProgramCount()) { - StartEditScript(m_brain->GetProgram(m_selScript), m_main->GetScriptName()); + StartEditScript(m_programmable->GetProgram(m_selScript), m_main->GetScriptName()); } } if ( action == EVENT_OBJECT_PROGRUN ) { - m_brain->StopProgram(); // stops the current program - if(m_selScript < m_brain->GetProgramCount()) + m_programmable->StopProgram(); // stops the current program + if(m_selScript < m_programmable->GetProgramCount()) { - m_brain->RunProgram(m_brain->GetProgram(m_selScript)); + m_programmable->RunProgram(m_programmable->GetProgram(m_selScript)); } UpdateInterface(); } err = ERR_OK; - if ( !m_brain->IsProgram() ) + if ( !m_programmable->IsProgram() ) { if ( action == EVENT_OBJECT_HTAKE ) { @@ -644,13 +643,13 @@ bool CObjectInterface::EventProcess(const Event &event) if ( action == EVENT_OBJECT_REC ) // registered? { - if ( m_brain->IsTraceRecord() ) + if ( m_programmable->IsTraceRecord() ) { - m_brain->TraceRecordStop(); + m_programmable->TraceRecordStop(); } else { - m_brain->TraceRecordStart(); + m_programmable->TraceRecordStart(); } UpdateInterface(); pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW0)); @@ -661,9 +660,9 @@ bool CObjectInterface::EventProcess(const Event &event) } if ( action == EVENT_OBJECT_STOP ) // stops? { - if ( m_brain->IsTraceRecord() ) + if ( m_programmable->IsTraceRecord() ) { - m_brain->TraceRecordStop(); + m_programmable->TraceRecordStop(); } UpdateInterface(); pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW0)); @@ -756,7 +755,7 @@ void CObjectInterface::StopEditScript(bool bCancel) if ( !m_studio->StopEditScript(bCancel) ) return; m_studio.reset(); - if ( !bCancel ) m_brain->SetActiveVirus(false); + if ( !bCancel ) m_programmable->SetActiveVirus(false); CreateInterface(true); // puts the control buttons } @@ -1657,7 +1656,7 @@ void CObjectInterface::UpdateInterface(float rTime) pb = static_cast(pw->SearchControl(EVENT_OBJECT_REC)); if ( pb != 0 ) { - if ( m_brain->IsTraceRecord() && Math::Mod(m_time, 0.4f) >= 0.2f ) + if ( m_programmable->IsTraceRecord() && Math::Mod(m_time, 0.4f) >= 0.2f ) { pb->SetState(STATE_CHECK); } @@ -1756,15 +1755,15 @@ void CObjectInterface::UpdateInterface() type = m_object->GetType(); - bEnable = ( !m_taskExecutor->IsForegroundTask() && !m_brain->IsProgram() ) && m_main->CanPlayerInteract(); + bEnable = ( !m_taskExecutor->IsForegroundTask() && !m_programmable->IsProgram() ) && m_main->CanPlayerInteract(); - EnableInterface(pw, EVENT_OBJECT_PROGEDIT, !m_brain->IsTraceRecord() && m_selScript < m_brain->GetProgramCount() && m_main->CanPlayerInteract()); - EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_brain->IsTraceRecord()); - EnableInterface(pw, EVENT_OBJECT_PROGADD, !m_brain->IsProgram() && m_main->CanPlayerInteract()); - EnableInterface(pw, EVENT_OBJECT_PROGREMOVE, !m_brain->IsProgram() && m_selScript < m_brain->GetProgramCount() && !m_brain->GetProgram(m_selScript)->readOnly && m_main->CanPlayerInteract()); - EnableInterface(pw, EVENT_OBJECT_PROGCLONE, !m_brain->IsProgram() && m_selScript < m_brain->GetProgramCount() && m_brain->GetProgram(m_selScript)->runnable && m_main->CanPlayerInteract()); - EnableInterface(pw, EVENT_OBJECT_PROGMOVEUP, !m_brain->IsProgram() && m_brain->GetProgramCount() >= 2 && m_selScript > 0 && m_main->CanPlayerInteract()); - EnableInterface(pw, EVENT_OBJECT_PROGMOVEDOWN,!m_brain->IsProgram() && m_brain->GetProgramCount() >= 2 && m_selScript < m_brain->GetProgramCount()-1 && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGEDIT, !m_programmable->IsTraceRecord() && m_selScript < m_programmable->GetProgramCount() && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_programmable->IsTraceRecord()); + EnableInterface(pw, EVENT_OBJECT_PROGADD, !m_programmable->IsProgram() && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGREMOVE, !m_programmable->IsProgram() && m_selScript < m_programmable->GetProgramCount() && !m_programmable->GetProgram(m_selScript)->readOnly && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGCLONE, !m_programmable->IsProgram() && m_selScript < m_programmable->GetProgramCount() && m_programmable->GetProgram(m_selScript)->runnable && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGMOVEUP, !m_programmable->IsProgram() && m_programmable->GetProgramCount() >= 2 && m_selScript > 0 && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGMOVEDOWN,!m_programmable->IsProgram() && m_programmable->GetProgramCount() >= 2 && m_selScript < m_programmable->GetProgramCount()-1 && m_main->CanPlayerInteract()); EnableInterface(pw, EVENT_OBJECT_LEFT, bEnable); EnableInterface(pw, EVENT_OBJECT_RIGHT, bEnable); EnableInterface(pw, EVENT_OBJECT_UP, bEnable); @@ -1832,7 +1831,7 @@ void CObjectInterface::UpdateInterface() if ( type == OBJECT_MOBILErs ) // shield? { - if ( (!m_taskExecutor->IsBackgroundTask() || !m_taskExecutor->GetBackgroundTask()->IsBusy()) && !m_brain->IsProgram() ) + if ( (!m_taskExecutor->IsBackgroundTask() || !m_taskExecutor->GetBackgroundTask()->IsBusy()) && !m_programmable->IsProgram() ) { EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, !m_taskExecutor->IsBackgroundTask() && m_main->CanPlayerInteract()); EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, m_taskExecutor->IsBackgroundTask() && m_main->CanPlayerInteract()); @@ -1910,11 +1909,11 @@ void CObjectInterface::UpdateInterface() type == OBJECT_CONTROLLER) // vehicle? { bRun = false; - if ( m_selScript < m_brain->GetProgramCount() ) + if ( m_selScript < m_programmable->GetProgramCount() ) { - if(m_brain->GetProgram(m_selScript)->runnable) + if(m_programmable->GetProgram(m_selScript)->runnable) { - m_brain->GetProgram(m_selScript)->script->GetTitle(title); + m_programmable->GetProgram(m_selScript)->script->GetTitle(title); if ( title[0] != 0 ) { bRun = true; @@ -1925,23 +1924,23 @@ void CObjectInterface::UpdateInterface() bRun = false; } } - if ( !bEnable && !m_brain->IsProgram() ) bRun = false; - if ( m_brain->IsTraceRecord() ) bRun = false; + if ( !bEnable && !m_programmable->IsProgram() ) bRun = false; + if ( m_programmable->IsTraceRecord() ) bRun = false; EnableInterface(pw, EVENT_OBJECT_PROGRUN, bRun && m_main->CanPlayerInteract()); pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_PROGRUN)); if ( pb != 0 ) { - pb->SetIcon(!m_brain->IsProgram() ? 21 : 8); // run/stop + pb->SetIcon(!m_programmable->IsProgram() ? 21 : 8); // run/stop } //? pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGEDIT); //? if ( pb != 0 ) //? { -//? pb->SetIcon(!m_brain->IsProgram() ? 22 : 40); // edit/debug +//? pb->SetIcon(!m_programmable->IsProgram() ? 22 : 40); // edit/debug //? } - BlinkScript(m_brain->IsProgram()); // blinks if script execution + BlinkScript(m_programmable->IsProgram()); // blinks if script execution } if ( type == OBJECT_MOBILEfa || @@ -2068,14 +2067,14 @@ void CObjectInterface::UpdateScript(CWindow *pw) if ( pl == 0 ) return; pl->Flush(); - for ( int i = 0 ; i < m_brain->GetProgramCount() ; i++ ) + for ( int i = 0 ; i < m_programmable->GetProgramCount() ; i++ ) { sprintf(name, "%d", i+1); - m_brain->GetProgram(i)->script->GetTitle(title); + m_programmable->GetProgram(i)->script->GetTitle(title); if ( title[0] != 0 ) { - if(!m_brain->GetProgram(i)->readOnly) + if(!m_programmable->GetProgram(i)->readOnly) { sprintf(name, "%d: %s", i+1, title); } diff --git a/src/ui/object_interface.h b/src/ui/object_interface.h index a36436e9..cb684398 100644 --- a/src/ui/object_interface.h +++ b/src/ui/object_interface.h @@ -23,12 +23,12 @@ class COldObject; class CTaskExecutorObject; +class CProgrammableObject; class CPhysics; class CMotion; class CRobotMain; class CSoundInterface; class CLevelParserLine; -class CBrain; struct Program; namespace Gfx @@ -87,12 +87,12 @@ protected: Gfx::CCamera* m_camera; Gfx::CParticle* m_particle; CRobotMain* m_main; - Ui::CInterface* m_interface; + CInterface* m_interface; CSoundInterface* m_sound; COldObject* m_object; CTaskExecutorObject* m_taskExecutor; - CBrain* m_brain; + CProgrammableObject* m_programmable; CPhysics* m_physics; CMotion* m_motion; diff --git a/src/ui/studio.cpp b/src/ui/studio.cpp index 3bc1490d..e3f3c107 100644 --- a/src/ui/studio.cpp +++ b/src/ui/studio.cpp @@ -34,10 +34,11 @@ #include "graphics/engine/camera.h" #include "graphics/engine/engine.h" -#include "object/brain.h" #include "object/object.h" #include "object/player_profile.h" +#include "object/interface/programmable_object.h" + #include "script/cbottoken.h" #include "script/script.h"