summaryrefslogtreecommitdiffstats
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-rw-r--r--src/script/ClassFILE.cpp425
-rw-r--r--src/script/cbottoken.cpp521
-rw-r--r--src/script/cbottoken.h39
-rw-r--r--src/script/cmdtoken.cpp978
-rw-r--r--src/script/cmdtoken.h67
-rw-r--r--src/script/dd.cpp175
-rw-r--r--src/script/script.cpp3777
-rw-r--r--src/script/script.h118
8 files changed, 6100 insertions, 0 deletions
diff --git a/src/script/ClassFILE.cpp b/src/script/ClassFILE.cpp
new file mode 100644
index 0000000..ef98e14
--- /dev/null
+++ b/src/script/ClassFILE.cpp
@@ -0,0 +1,425 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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://www.gnu.org/licenses/.
+
+
+
+// Static variables
+
+static CBotClass* m_pClassFILE;
+static CBotProgram* m_pFuncFile;
+static int m_CompteurFileOpen = 0;
+static char* m_filesDir;
+
+
+
+// Prepares a file name.
+
+void PrepareFilename(CBotString &filename)
+{
+ int pos;
+
+ pos = filename.ReverseFind('\\');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // Remove files with
+ }
+
+ pos = filename.ReverseFind('/');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // also with /
+ }
+
+ pos = filename.ReverseFind(':');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // also removes the drive letter C:
+ }
+
+ filename = CBotString(m_filesDir) + CBotString("\\") + filename;
+}
+
+
+// constructor of the class
+// get the filename as a parameter
+
+// execution
+BOOL rfconstruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ CBotString mode;
+
+ // accepts no parameters
+ if ( pVar == NULL ) return TRUE;
+
+ // must be a character string
+ if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return FALSE; }
+
+ CBotString filename = pVar->GivValString();
+ PrepareFilename(filename);
+
+ // there may be a second parameter
+ pVar = pVar->GivNext();
+ if ( pVar != NULL )
+ {
+ // recover mode
+ mode = pVar->GivValString();
+ if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return FALSE; }
+
+ // no third parameter
+ if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return FALSE; }
+ }
+
+ // saves the file name
+ pVar = pThis->GivItem("filename");
+ pVar->SetValString(filename);
+
+ if ( ! mode.IsEmpty() )
+ {
+ // opens the requested file
+ FILE* pFile = fopen( filename, mode );
+ if ( pFile == NULL ) { Exception = CBotErrFileOpen; return FALSE; }
+
+ m_CompteurFileOpen ++;
+
+ // save the channel file
+ pVar = pThis->GivItem("handle");
+ pVar->SetValInt((long)pFile);
+ }
+
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfconstruct (CBotVar* pThis, CBotVar* &pVar)
+{
+ // accepts no parameters
+ if ( pVar == NULL ) return CBotTypResult( 0 );
+
+ // must be a character string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+
+ // there may be a second parameter
+ pVar = pVar->GivNext();
+ if ( pVar != NULL )
+ {
+ // which must be a string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+ // no third parameter
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
+ }
+
+ // the result is void (constructor)
+ return CBotTypResult( 0 );
+}
+
+
+// destructor of the class
+
+// execution
+BOOL rfdestruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ // don't open? no problem :)
+ if ( pVar->GivInit() != IS_DEF) return TRUE;
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+ fclose(pFile);
+ m_CompteurFileOpen --;
+
+ pVar->SetInit(IS_NAN);
+
+ return TRUE;
+}
+
+
+// process FILE :: open
+// get the r/w mode as a parameter
+
+// execution
+BOOL rfopen (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // there must be a parameter
+ if ( pVar == NULL ) { Exception = CBotErrLowParam; return FALSE; }
+
+ // which must be a character string
+ if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return FALSE; }
+
+ // There may be a second parameter
+ if ( pVar->GivNext() != NULL )
+ {
+ // if the first parameter is the file name
+ CBotString filename = pVar->GivValString();
+ PrepareFilename(filename);
+
+ // saves the file name
+ CBotVar* pVar2 = pThis->GivItem("filename");
+ pVar2->SetValString(filename);
+
+ // next parameter is the mode
+ pVar = pVar -> GivNext();
+ }
+
+ CBotString mode = pVar->GivValString();
+ if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return FALSE; }
+
+ // no third parameter
+ if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return FALSE; }
+
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ // which must not be initialized
+ if ( pVar->GivInit() == IS_DEF) { Exception = CBotErrFileOpen; return FALSE; }
+
+ // file contains the name
+ pVar = pThis->GivItem("filename");
+ CBotString filename = pVar->GivValString();
+
+ PrepareFilename(filename); // if the name was h.filename attribute = "...";
+
+ // opens the requested file
+ FILE* pFile = fopen( filename, mode );
+ if ( pFile == NULL )
+ {
+ pResult->SetValInt(FALSE);
+ return TRUE;
+ }
+
+ m_CompteurFileOpen ++;
+
+ // Registered the channel file
+ pVar = pThis->GivItem("handle");
+ pVar->SetValInt((long)pFile);
+
+ pResult->SetValInt(TRUE);
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfopen (CBotVar* pThis, CBotVar* &pVar)
+{
+ // there must be a parameter
+ if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
+
+ // which must be a string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+
+ // there may be a second parameter
+ pVar = pVar->GivNext();
+ if ( pVar != NULL )
+ {
+ // which must be a string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+
+ // no third parameter
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
+ }
+
+ // the result is bool
+ return CBotTypResult(CBotTypBoolean);
+}
+
+
+// process FILE :: close
+
+// execeution
+BOOL rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // it shouldn't be any parameters
+ if ( pVar != NULL ) return CBotErrOverParam;
+
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+ fclose(pFile);
+ m_CompteurFileOpen --;
+
+ pVar->SetInit(IS_NAN);
+
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfclose (CBotVar* pThis, CBotVar* &pVar)
+{
+ // it shouldn't be any parameters
+ if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // function returns a result "void"
+ return CBotTypResult( 0 );
+}
+
+// process FILE :: writeln
+
+// execution
+BOOL rfwrite (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // there must be a parameter
+ if ( pVar == NULL ) { Exception = CBotErrLowParam; return FALSE; }
+
+ // which must be a character string
+ if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return FALSE; }
+
+ CBotString param = pVar->GivValString();
+
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+
+ int res = fputs(param+CBotString("\n"), pFile);
+
+ // if an error occurs generate an exception
+ if ( res < 0 ) { Exception = CBotErrWrite; return FALSE; }
+
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfwrite (CBotVar* pThis, CBotVar* &pVar)
+{
+ // there must be a parameter
+ if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
+
+ // which must be a character string
+ if ( pVar->GivType() != CBotTypString ) return CBotTypResult( CBotErrBadString );
+
+ // no other parameter
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // the function returns a void result
+ return CBotTypResult( 0 );
+}
+
+// process FILE :: readln
+
+// execution
+BOOL rfread (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // it shouldn't be any parameters
+ if ( pVar != NULL ) { Exception = CBotErrOverParam; return FALSE; }
+
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+
+ char chaine[2000];
+ int i;
+ for ( i = 0 ; i < 2000 ; i++ ) chaine[i] = 0;
+
+ fgets(chaine, 1999, pFile);
+
+ for ( i = 0 ; i < 2000 ; i++ ) if (chaine[i] == '\n') chaine[i] = 0;
+
+ // if an error occurs generate an exception
+ if ( ferror(pFile) ) { Exception = CBotErrRead; return FALSE; }
+
+ pResult->SetValString( chaine );
+
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfread (CBotVar* pThis, CBotVar* &pVar)
+{
+ // it should not be any parameter
+ if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // function returns a result "string"
+ return CBotTypResult( CBotTypString );
+}
+// process FILE :: readln
+
+
+// execution
+BOOL rfeof (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // it should not be any parameter
+ if ( pVar != NULL ) { Exception = CBotErrOverParam; return FALSE; }
+
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+
+ pResult->SetValInt( feof( pFile ) );
+
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfeof (CBotVar* pThis, CBotVar* &pVar)
+{
+ // it shouldn't be any parameter
+ if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // the function returns a boolean result
+ return CBotTypResult( CBotTypBoolean );
+}
+
+
+
+
+
+void InitClassFILE()
+{
+// create a class for file management
+// the use is as follows:
+// file canal( "NomFichier.txt" )
+// canal.open( "r" ); // open for read
+// s = canal.readln( ); // reads a line
+// canal.close(); // close the file
+
+ // create the class FILE
+ m_pClassFILE = new CBotClass("file", NULL);
+ // adds the component ".filename"
+ m_pClassFILE->AddItem("filename", CBotTypString);
+ // adds the component ".handle"
+ m_pClassFILE->AddItem("handle", CBotTypInt, PR_PRIVATE);
+
+ // define a constructor and a destructor
+ m_pClassFILE->AddFunction("file", rfconstruct, cfconstruct );
+ m_pClassFILE->AddFunction("~file", rfdestruct, NULL );
+
+ // end of the methods associated
+ m_pClassFILE->AddFunction("open", rfopen, cfopen );
+ m_pClassFILE->AddFunction("close", rfclose, cfclose );
+ m_pClassFILE->AddFunction("writeln", rfwrite, cfwrite );
+ m_pClassFILE->AddFunction("readln", rfread, cfread );
+ m_pClassFILE->AddFunction("eof", rfeof, cfeof );
+
+ m_pFuncFile = new CBotProgram( );
+ CBotStringArray ListFonctions;
+ m_pFuncFile->Compile( "public file openfile(string name, string mode) {return new file(name, mode);}", ListFonctions);
+ m_pFuncFile->SetIdent(-2); // restoreState in special identifier for this function
+}
+
diff --git a/src/script/cbottoken.cpp b/src/script/cbottoken.cpp
new file mode 100644
index 0000000..d97239d
--- /dev/null
+++ b/src/script/cbottoken.cpp
@@ -0,0 +1,521 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "language.h"
+#include "global.h"
+#include "event.h"
+#include "object.h"
+#include "cbottoken.h"
+
+
+
+
+// Seeking the name of an object.
+
+char* RetObjectName(ObjectType type)
+{
+ if ( type == OBJECT_PORTICO ) return "Portico";
+ if ( type == OBJECT_BASE ) return "SpaceShip";
+ if ( type == OBJECT_DERRICK ) return "Derrick";
+ if ( type == OBJECT_FACTORY ) return "BotFactory";
+ if ( type == OBJECT_STATION ) return "PowerStation";
+ if ( type == OBJECT_CONVERT ) return "Converter";
+ if ( type == OBJECT_REPAIR ) return "RepairCenter";
+ if ( type == OBJECT_DESTROYER ) return "Destroyer";
+ if ( type == OBJECT_TOWER ) return "DefenseTower";
+ if ( type == OBJECT_NEST ) return "AlienNest";
+ if ( type == OBJECT_RESEARCH ) return "ResearchCenter";
+ if ( type == OBJECT_RADAR ) return "RadarStation";
+ if ( type == OBJECT_INFO ) return "ExchangePost";
+ if ( type == OBJECT_ENERGY ) return "PowerPlant";
+ if ( type == OBJECT_LABO ) return "AutoLab";
+ if ( type == OBJECT_NUCLEAR ) return "NuclearPlant";
+ if ( type == OBJECT_PARA ) return "PowerCaptor";
+ if ( type == OBJECT_SAFE ) return "Vault";
+ if ( type == OBJECT_HUSTON ) return "Houston";
+ if ( type == OBJECT_TARGET1 ) return "Target1";
+ if ( type == OBJECT_TARGET2 ) return "Target2";
+ if ( type == OBJECT_START ) return "StartArea";
+ if ( type == OBJECT_END ) return "GoalArea";
+ if ( type == OBJECT_TEEN34 ) return "Stone";
+ if ( type == OBJECT_STONE ) return "TitaniumOre";
+ if ( type == OBJECT_URANIUM ) return "UraniumOre";
+ if ( type == OBJECT_METAL ) return "Titanium";
+ if ( type == OBJECT_POWER ) return "PowerCell";
+ if ( type == OBJECT_ATOMIC ) return "NuclearCell";
+ if ( type == OBJECT_BULLET ) return "OrgaMatter";
+ if ( type == OBJECT_BBOX ) return "BlackBox";
+ if ( type == OBJECT_KEYa ) return "KeyA";
+ if ( type == OBJECT_KEYb ) return "KeyB";
+ if ( type == OBJECT_KEYc ) return "KeyC";
+ if ( type == OBJECT_KEYd ) return "KeyD";
+ if ( type == OBJECT_TNT ) return "TNT";
+ if ( type == OBJECT_SCRAP1 ) return "Scrap";
+ if ( type == OBJECT_BOMB ) return "Mine";
+ if ( type == OBJECT_BARRIER1 ) return "Barrier";
+ if ( type == OBJECT_WAYPOINT ) return "WayPoint";
+ if ( type == OBJECT_FLAGb ) return "BlueFlag";
+ if ( type == OBJECT_FLAGr ) return "RedFlag";
+ if ( type == OBJECT_FLAGg ) return "GreenFlag";
+ if ( type == OBJECT_FLAGy ) return "YellowFlag";
+ if ( type == OBJECT_FLAGv ) return "VioletFlag";
+ if ( type == OBJECT_MARKPOWER ) return "PowerSpot";
+ if ( type == OBJECT_MARKSTONE ) return "TitaniumSpot";
+ if ( type == OBJECT_MARKURANIUM ) return "UraniumSpot";
+ if ( type == OBJECT_MARKKEYa ) return "KeyASpot";
+ if ( type == OBJECT_MARKKEYb ) return "KeyBSpot";
+ if ( type == OBJECT_MARKKEYc ) return "KeyCSpot";
+ if ( type == OBJECT_MARKKEYd ) return "KeyDSpot";
+ if ( type == OBJECT_MOBILEwt ) return "PracticeBot";
+ if ( type == OBJECT_MOBILEwa ) return "WheeledGrabber";
+ if ( type == OBJECT_MOBILEta ) return "TrackedGrabber";
+ if ( type == OBJECT_MOBILEfa ) return "WingedGrabber";
+ if ( type == OBJECT_MOBILEia ) return "LeggedGrabber";
+ if ( type == OBJECT_MOBILEwc ) return "WheeledShooter";
+ if ( type == OBJECT_MOBILEtc ) return "TrackedShooter";
+ if ( type == OBJECT_MOBILEfc ) return "WingedShooter";
+ if ( type == OBJECT_MOBILEic ) return "LeggedShooter";
+ if ( type == OBJECT_MOBILEwi ) return "WheeledOrgaShooter";
+ if ( type == OBJECT_MOBILEti ) return "TrackedOrgaShooter";
+ if ( type == OBJECT_MOBILEfi ) return "WingedOrgaShooter";
+ if ( type == OBJECT_MOBILEii ) return "LeggedOrgaShooter";
+ if ( type == OBJECT_MOBILEws ) return "WheeledSniffer";
+ if ( type == OBJECT_MOBILEts ) return "TrackedSniffer";
+ if ( type == OBJECT_MOBILEfs ) return "WingedSniffer";
+ if ( type == OBJECT_MOBILEis ) return "LeggedSniffer";
+ if ( type == OBJECT_MOBILErt ) return "Thumper";
+ if ( type == OBJECT_MOBILErc ) return "PhazerShooter";
+ if ( type == OBJECT_MOBILErr ) return "Recycler";
+ if ( type == OBJECT_MOBILErs ) return "Shielder";
+ if ( type == OBJECT_MOBILEsa ) return "Subber";
+ if ( type == OBJECT_MOBILEtg ) return "TargetBot";
+ if ( type == OBJECT_MOBILEdr ) return "Scribbler";
+ if ( type == OBJECT_HUMAN ) return "Me";
+ if ( type == OBJECT_TECH ) return "Tech";
+ if ( type == OBJECT_MOTHER ) return "AlienQueen";
+ if ( type == OBJECT_EGG ) return "AlienEgg";
+ if ( type == OBJECT_ANT ) return "AlienAnt";
+ if ( type == OBJECT_SPIDER ) return "AlienSpider";
+ if ( type == OBJECT_BEE ) return "AlienWasp";
+ if ( type == OBJECT_WORM ) return "AlienWorm";
+ if ( type == OBJECT_RUINmobilew1) return "Wreck";
+ return "";
+}
+
+// Seeking the name of a secondary object.
+// (because Otto thinks that Germans do not like nuclear power)
+
+char* RetObjectAlias(ObjectType type)
+{
+ if ( type == OBJECT_NUCLEAR ) return "FuelCellPlant";
+ if ( type == OBJECT_URANIUM ) return "PlatinumOre";
+ if ( type == OBJECT_ATOMIC ) return "FuelCell";
+ if ( type == OBJECT_MARKURANIUM ) return "PlatinumSpot";
+ if ( type == OBJECT_ENERGY ) return "Disintegrator"; // for K-CeeBot
+ return "";
+}
+
+
+// Returns the help file to use for the object.
+
+char* RetHelpFilename(ObjectType type)
+{
+ if ( type == OBJECT_BASE ) return "help\\object\\base.txt";
+ if ( type == OBJECT_DERRICK ) return "help\\object\\derrick.txt";
+ if ( type == OBJECT_FACTORY ) return "help\\object\\factory.txt";
+ if ( type == OBJECT_STATION ) return "help\\object\\station.txt";
+ if ( type == OBJECT_CONVERT ) return "help\\object\\convert.txt";
+ if ( type == OBJECT_REPAIR ) return "help\\object\\repair.txt";
+ if ( type == OBJECT_DESTROYER ) return "help\\object\\destroy.txt";
+ if ( type == OBJECT_TOWER ) return "help\\object\\tower.txt";
+ if ( type == OBJECT_NEST ) return "help\\object\\nest.txt";
+ if ( type == OBJECT_RESEARCH ) return "help\\object\\research.txt";
+ if ( type == OBJECT_RADAR ) return "help\\object\\radar.txt";
+ if ( type == OBJECT_INFO ) return "help\\object\\exchange.txt";
+ if ( type == OBJECT_ENERGY ) return "help\\object\\energy.txt";
+ if ( type == OBJECT_LABO ) return "help\\object\\labo.txt";
+ if ( type == OBJECT_NUCLEAR ) return "help\\object\\nuclear.txt";
+ if ( type == OBJECT_PARA ) return "help\\object\\captor.txt";
+ if ( type == OBJECT_SAFE ) return "help\\object\\safe.txt";
+ if ( type == OBJECT_HUSTON ) return "help\\object\\huston.txt";
+ if ( type == OBJECT_START ) return "help\\object\\start.txt";
+ if ( type == OBJECT_END ) return "help\\object\\goal.txt";
+ if ( type == OBJECT_STONE ) return "help\\object\\titanore.txt";
+ if ( type == OBJECT_URANIUM ) return "help\\object\\uranore.txt";
+ if ( type == OBJECT_METAL ) return "help\\object\\titan.txt";
+ if ( type == OBJECT_POWER ) return "help\\object\\power.txt";
+ if ( type == OBJECT_ATOMIC ) return "help\\object\\atomic.txt";
+ if ( type == OBJECT_BULLET ) return "help\\object\\bullet.txt";
+ if ( type == OBJECT_BBOX ) return "help\\object\\bbox.txt";
+ if ( type == OBJECT_KEYa ) return "help\\object\\key.txt";
+ if ( type == OBJECT_KEYb ) return "help\\object\\key.txt";
+ if ( type == OBJECT_KEYc ) return "help\\object\\key.txt";
+ if ( type == OBJECT_KEYd ) return "help\\object\\key.txt";
+ if ( type == OBJECT_TNT ) return "help\\object\\tnt.txt";
+ if ( type == OBJECT_SCRAP1 ) return "help\\object\\scrap.txt";
+ if ( type == OBJECT_BOMB ) return "help\\object\\mine.txt";
+ if ( type == OBJECT_BARRIER1 ) return "help\\object\\barrier.txt";
+ if ( type == OBJECT_WAYPOINT ) return "help\\object\\waypoint.txt";
+ if ( type == OBJECT_FLAGb ) return "help\\object\\flag.txt";
+ if ( type == OBJECT_FLAGr ) return "help\\object\\flag.txt";
+ if ( type == OBJECT_FLAGg ) return "help\\object\\flag.txt";
+ if ( type == OBJECT_FLAGy ) return "help\\object\\flag.txt";
+ if ( type == OBJECT_FLAGv ) return "help\\object\\flag.txt";
+ if ( type == OBJECT_MARKPOWER ) return "help\\object\\enerspot.txt";
+ if ( type == OBJECT_MARKSTONE ) return "help\\object\\stonspot.txt";
+ if ( type == OBJECT_MARKURANIUM ) return "help\\object\\uranspot.txt";
+ if ( type == OBJECT_MOBILEwa ) return "help\\object\\botgr.txt";
+ if ( type == OBJECT_MOBILEta ) return "help\\object\\botgc.txt";
+ if ( type == OBJECT_MOBILEfa ) return "help\\object\\botgj.txt";
+ if ( type == OBJECT_MOBILEia ) return "help\\object\\botgs.txt";
+ if ( type == OBJECT_MOBILEws ) return "help\\object\\botsr.txt";
+ if ( type == OBJECT_MOBILEts ) return "help\\object\\botsc.txt";
+ if ( type == OBJECT_MOBILEfs ) return "help\\object\\botsj.txt";
+ if ( type == OBJECT_MOBILEis ) return "help\\object\\botss.txt";
+ if ( type == OBJECT_MOBILEwi ) return "help\\object\\botor.txt";
+ if ( type == OBJECT_MOBILEti ) return "help\\object\\botoc.txt";
+ if ( type == OBJECT_MOBILEfi ) return "help\\object\\botoj.txt";
+ if ( type == OBJECT_MOBILEii ) return "help\\object\\botos.txt";
+ if ( type == OBJECT_MOBILEwc ) return "help\\object\\botfr.txt";
+ if ( type == OBJECT_MOBILEtc ) return "help\\object\\botfc.txt";
+ if ( type == OBJECT_MOBILEfc ) return "help\\object\\botfj.txt";
+ if ( type == OBJECT_MOBILEic ) return "help\\object\\botfs.txt";
+ if ( type == OBJECT_MOBILErt ) return "help\\object\\bottump.txt";
+ if ( type == OBJECT_MOBILErc ) return "help\\object\\botphaz.txt";
+ if ( type == OBJECT_MOBILErr ) return "help\\object\\botrecy.txt";
+ if ( type == OBJECT_MOBILErs ) return "help\\object\\botshld.txt";
+ if ( type == OBJECT_MOBILEsa ) return "help\\object\\botsub.txt";
+ if ( type == OBJECT_MOBILEwt ) return "help\\object\\bottr.txt";
+ if ( type == OBJECT_MOBILEtg ) return "help\\object\\bottarg.txt";
+ if ( type == OBJECT_MOBILEdr ) return "help\\object\\botdraw.txt";
+ if ( type == OBJECT_APOLLO2 ) return "help\\object\\lrv.txt";
+ if ( type == OBJECT_HUMAN ) return "help\\object\\human.txt";
+ if ( type == OBJECT_MOTHER ) return "help\\object\\mother.txt";
+ if ( type == OBJECT_EGG ) return "help\\object\\egg.txt";
+ if ( type == OBJECT_ANT ) return "help\\object\\ant.txt";
+ if ( type == OBJECT_SPIDER ) return "help\\object\\spider.txt";
+ if ( type == OBJECT_BEE ) return "help\\object\\wasp.txt";
+ if ( type == OBJECT_WORM ) return "help\\object\\worm.txt";
+ if ( type == OBJECT_RUINmobilew1) return "help\\object\\wreck.txt";
+ return "";
+}
+
+
+// Returns the help file to use for instruction.
+
+char* RetHelpFilename(const char *token)
+{
+ if ( strcmp(token, "if" ) == 0 ) return "help\\cbot\\if.txt";
+ if ( strcmp(token, "else" ) == 0 ) return "help\\cbot\\if.txt";
+ if ( strcmp(token, "repeat" ) == 0 ) return "help\\cbot\\repeat.txt";
+ if ( strcmp(token, "for" ) == 0 ) return "help\\cbot\\for.txt";
+ if ( strcmp(token, "while" ) == 0 ) return "help\\cbot\\while.txt";
+ if ( strcmp(token, "do" ) == 0 ) return "help\\cbot\\do.txt";
+ if ( strcmp(token, "break" ) == 0 ) return "help\\cbot\\break.txt";
+ if ( strcmp(token, "continue" ) == 0 ) return "help\\cbot\\continue.txt";
+ if ( strcmp(token, "return" ) == 0 ) return "help\\cbot\\return.txt";
+ if ( strcmp(token, "sizeof" ) == 0 ) return "help\\cbot\\sizeof.txt";
+ if ( strcmp(token, "int" ) == 0 ) return "help\\cbot\\int.txt";
+ if ( strcmp(token, "float" ) == 0 ) return "help\\cbot\\float.txt";
+ if ( strcmp(token, "bool" ) == 0 ) return "help\\cbot\\bool.txt";
+ if ( strcmp(token, "string" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "point" ) == 0 ) return "help\\cbot\\point.txt";
+ if ( strcmp(token, "object" ) == 0 ) return "help\\cbot\\object.txt";
+ if ( strcmp(token, "file" ) == 0 ) return "help\\cbot\\file.txt";
+ if ( strcmp(token, "void" ) == 0 ) return "help\\cbot\\void.txt";
+ if ( strcmp(token, "null" ) == 0 ) return "help\\cbot\\null.txt";
+ if ( strcmp(token, "nan" ) == 0 ) return "help\\cbot\\nan.txt";
+ if ( strcmp(token, "true" ) == 0 ) return "help\\cbot\\true.txt";
+ if ( strcmp(token, "false" ) == 0 ) return "help\\cbot\\false.txt";
+ if ( strcmp(token, "sin" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "cos" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "tan" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "asin" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "acos" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "atan" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "sqrt" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "pow" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "rand" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "abs" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "retobject" ) == 0 ) return "help\\cbot\\retobj.txt";
+ if ( strcmp(token, "search" ) == 0 ) return "help\\cbot\\search.txt";
+ if ( strcmp(token, "radar" ) == 0 ) return "help\\cbot\\radar.txt";
+ if ( strcmp(token, "direction" ) == 0 ) return "help\\cbot\\direct.txt";
+ if ( strcmp(token, "distance" ) == 0 ) return "help\\cbot\\dist.txt";
+ if ( strcmp(token, "distance2d" ) == 0 ) return "help\\cbot\\dist2d.txt";
+ if ( strcmp(token, "space" ) == 0 ) return "help\\cbot\\space.txt";
+ if ( strcmp(token, "flatground" ) == 0 ) return "help\\cbot\\flatgrnd.txt";
+ if ( strcmp(token, "wait" ) == 0 ) return "help\\cbot\\wait.txt";
+ if ( strcmp(token, "move" ) == 0 ) return "help\\cbot\\move.txt";
+ if ( strcmp(token, "turn" ) == 0 ) return "help\\cbot\\turn.txt";
+ if ( strcmp(token, "goto" ) == 0 ) return "help\\cbot\\goto.txt";
+ if ( strcmp(token, "find" ) == 0 ) return "help\\cbot\\find.txt";
+ if ( strcmp(token, "grab" ) == 0 ) return "help\\cbot\\grab.txt";
+ if ( strcmp(token, "drop" ) == 0 ) return "help\\cbot\\drop.txt";
+ if ( strcmp(token, "sniff" ) == 0 ) return "help\\cbot\\sniff.txt";
+ if ( strcmp(token, "receive" ) == 0 ) return "help\\cbot\\receive.txt";
+ if ( strcmp(token, "send" ) == 0 ) return "help\\cbot\\send.txt";
+ if ( strcmp(token, "deleteinfo" ) == 0 ) return "help\\cbot\\delinfo.txt";
+ if ( strcmp(token, "testinfo" ) == 0 ) return "help\\cbot\\testinfo.txt";
+ if ( strcmp(token, "thump" ) == 0 ) return "help\\cbot\\thump.txt";
+ if ( strcmp(token, "recycle" ) == 0 ) return "help\\cbot\\recycle.txt";
+ if ( strcmp(token, "shield" ) == 0 ) return "help\\cbot\\shield.txt";
+ if ( strcmp(token, "fire" ) == 0 ) return "help\\cbot\\fire.txt";
+ if ( strcmp(token, "antfire" ) == 0 ) return "help\\cbot\\antfire.txt";
+ if ( strcmp(token, "aim" ) == 0 ) return "help\\cbot\\aim.txt";
+ if ( strcmp(token, "motor" ) == 0 ) return "help\\cbot\\motor.txt";
+ if ( strcmp(token, "jet" ) == 0 ) return "help\\cbot\\jet.txt";
+ if ( strcmp(token, "topo" ) == 0 ) return "help\\cbot\\topo.txt";
+ if ( strcmp(token, "message" ) == 0 ) return "help\\cbot\\message.txt";
+ if ( strcmp(token, "abstime" ) == 0 ) return "help\\cbot\\abstime.txt";
+ if ( strcmp(token, "BlackArrow" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "RedArrow" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "White" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Black" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Gray" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "LightGray" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Red" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Pink" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Purple" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Orange" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Yellow" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Beige" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Brown" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Skin" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Green" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "LightGreen" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Blue" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "LightBlue" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "InFront" ) == 0 ) return "help\\cbot\\grab.txt";
+ if ( strcmp(token, "Behind" ) == 0 ) return "help\\cbot\\grab.txt";
+ if ( strcmp(token, "EnergyCell" ) == 0 ) return "help\\cbot\\grab.txt";
+ if ( strcmp(token, "DisplayError" ) == 0 ) return "help\\cbot\\message.txt";
+ if ( strcmp(token, "DisplayWarning") == 0 ) return "help\\cbot\\message.txt";
+ if ( strcmp(token, "DisplayInfo" ) == 0 ) return "help\\cbot\\message.txt";
+ if ( strcmp(token, "DisplayMessage") == 0 ) return "help\\cbot\\message.txt";
+ if ( strcmp(token, "strlen" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strleft" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strright" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strmid" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strval" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strfind" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strlower" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strupper" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "open" ) == 0 ) return "help\\cbot\\open.txt";
+ if ( strcmp(token, "close" ) == 0 ) return "help\\cbot\\close.txt";
+ if ( strcmp(token, "writeln" ) == 0 ) return "help\\cbot\\writeln.txt";
+ if ( strcmp(token, "readln " ) == 0 ) return "help\\cbot\\readln.txt";
+ if ( strcmp(token, "eof" ) == 0 ) return "help\\cbot\\eof.txt";
+ if ( strcmp(token, "deletefile" ) == 0 ) return "help\\cbot\\deletef.txt";
+ if ( strcmp(token, "openfile" ) == 0 ) return "help\\cbot\\openfile.txt";
+ if ( strcmp(token, "pendown" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "penup" ) == 0 ) return "help\\cbot\\penup.txt";
+ if ( strcmp(token, "pencolor" ) == 0 ) return "help\\cbot\\pencolor.txt";
+ if ( strcmp(token, "penwidth" ) == 0 ) return "help\\cbot\\penwidth.txt";
+ if ( strcmp(token, "extern" ) == 0 ) return "help\\cbot\\extern.txt";
+ if ( strcmp(token, "class" ) == 0 ) return "help\\cbot\\class.txt";
+ if ( strcmp(token, "static" ) == 0 ) return "help\\cbot\\static.txt";
+ if ( strcmp(token, "public" ) == 0 ) return "help\\cbot\\public.txt";
+ if ( strcmp(token, "private" ) == 0 ) return "help\\cbot\\private.txt";
+ if ( strcmp(token, "synchronized" ) == 0 ) return "help\\cbot\\synchro.txt";
+ if ( strcmp(token, "new" ) == 0 ) return "help\\cbot\\new.txt";
+ if ( strcmp(token, "this" ) == 0 ) return "help\\cbot\\this.txt";
+ return "";
+}
+
+
+// Test if a keyword is a type of variable.
+
+BOOL IsType(const char *token)
+{
+ if ( strcmp(token, "void" ) == 0 ) return TRUE;
+ if ( strcmp(token, "int" ) == 0 ) return TRUE;
+ if ( strcmp(token, "float" ) == 0 ) return TRUE;
+ if ( strcmp(token, "bool" ) == 0 ) return TRUE;
+ if ( strcmp(token, "string" ) == 0 ) return TRUE;
+ if ( strcmp(token, "point" ) == 0 ) return TRUE;
+ if ( strcmp(token, "object" ) == 0 ) return TRUE;
+ if ( strcmp(token, "file" ) == 0 ) return TRUE;
+ if ( strcmp(token, "this" ) == 0 ) return TRUE;
+ return FALSE;
+}
+
+// Test if a keyword is a function.
+
+BOOL IsFunction(const char *token)
+{
+ if ( strcmp(token, "sin" ) == 0 ) return TRUE;
+ if ( strcmp(token, "cos" ) == 0 ) return TRUE;
+ if ( strcmp(token, "tan" ) == 0 ) return TRUE;
+ if ( strcmp(token, "asin" ) == 0 ) return TRUE;
+ if ( strcmp(token, "acos" ) == 0 ) return TRUE;
+ if ( strcmp(token, "atan" ) == 0 ) return TRUE;
+ if ( strcmp(token, "sqrt" ) == 0 ) return TRUE;
+ if ( strcmp(token, "pow" ) == 0 ) return TRUE;
+ if ( strcmp(token, "rand" ) == 0 ) return TRUE;
+ if ( strcmp(token, "abs" ) == 0 ) return TRUE;
+ if ( strcmp(token, "retobject" ) == 0 ) return TRUE;
+ if ( strcmp(token, "search" ) == 0 ) return TRUE;
+ if ( strcmp(token, "radar" ) == 0 ) return TRUE;
+ if ( strcmp(token, "detect" ) == 0 ) return TRUE;
+ if ( strcmp(token, "direction" ) == 0 ) return TRUE;
+ if ( strcmp(token, "distance" ) == 0 ) return TRUE;
+ if ( strcmp(token, "distance2d" ) == 0 ) return TRUE;
+ if ( strcmp(token, "space" ) == 0 ) return TRUE;
+ if ( strcmp(token, "flatground" ) == 0 ) return TRUE;
+ if ( strcmp(token, "wait" ) == 0 ) return TRUE;
+ if ( strcmp(token, "move" ) == 0 ) return TRUE;
+ if ( strcmp(token, "turn" ) == 0 ) return TRUE;
+ if ( strcmp(token, "goto" ) == 0 ) return TRUE;
+ if ( strcmp(token, "find" ) == 0 ) return TRUE;
+ if ( strcmp(token, "grab" ) == 0 ) return TRUE;
+ if ( strcmp(token, "drop" ) == 0 ) return TRUE;
+ if ( strcmp(token, "sniff" ) == 0 ) return TRUE;
+ if ( strcmp(token, "receive" ) == 0 ) return TRUE;
+ if ( strcmp(token, "send" ) == 0 ) return TRUE;
+ if ( strcmp(token, "deleteinfo" ) == 0 ) return TRUE;
+ if ( strcmp(token, "testinfo" ) == 0 ) return TRUE;
+ if ( strcmp(token, "thump" ) == 0 ) return TRUE;
+ if ( strcmp(token, "recycle" ) == 0 ) return TRUE;
+ if ( strcmp(token, "shield" ) == 0 ) return TRUE;
+ if ( strcmp(token, "fire" ) == 0 ) return TRUE;
+ if ( strcmp(token, "antfire" ) == 0 ) return TRUE;
+ if ( strcmp(token, "aim" ) == 0 ) return TRUE;
+ if ( strcmp(token, "motor" ) == 0 ) return TRUE;
+ if ( strcmp(token, "jet" ) == 0 ) return TRUE;
+ if ( strcmp(token, "topo" ) == 0 ) return TRUE;
+ if ( strcmp(token, "message" ) == 0 ) return TRUE;
+ if ( strcmp(token, "abstime" ) == 0 ) return TRUE;
+ if ( strcmp(token, "ismovie" ) == 0 ) return TRUE;
+ if ( strcmp(token, "errmode" ) == 0 ) return TRUE;
+ if ( strcmp(token, "ipf" ) == 0 ) return TRUE;
+ if ( strcmp(token, "strlen" ) == 0 ) return TRUE;
+ if ( strcmp(token, "strleft" ) == 0 ) return TRUE;
+ if ( strcmp(token, "strright" ) == 0 ) return TRUE;
+ if ( strcmp(token, "strmid" ) == 0 ) return TRUE;
+ if ( strcmp(token, "strval" ) == 0 ) return TRUE;
+ if ( strcmp(token, "strfind" ) == 0 ) return TRUE;
+ if ( strcmp(token, "strlower" ) == 0 ) return TRUE;
+ if ( strcmp(token, "strupper" ) == 0 ) return TRUE;
+ if ( strcmp(token, "open" ) == 0 ) return TRUE;
+ if ( strcmp(token, "close" ) == 0 ) return TRUE;
+ if ( strcmp(token, "writeln" ) == 0 ) return TRUE;
+ if ( strcmp(token, "readln" ) == 0 ) return TRUE;
+ if ( strcmp(token, "eof" ) == 0 ) return TRUE;
+ if ( strcmp(token, "deletefile" ) == 0 ) return TRUE;
+ if ( strcmp(token, "openfile" ) == 0 ) return TRUE;
+ if ( strcmp(token, "pendown" ) == 0 ) return TRUE;
+ if ( strcmp(token, "penup" ) == 0 ) return TRUE;
+ if ( strcmp(token, "pencolor" ) == 0 ) return TRUE;
+ if ( strcmp(token, "penwidth" ) == 0 ) return TRUE;
+ if ( strcmp(token, "sizeof" ) == 0 ) return TRUE;
+ return FALSE;
+}
+
+
+// Returns using a compact instruction.
+
+char* RetHelpText(const char *token)
+{
+ if ( strcmp(token, "if" ) == 0 ) return "if ( condition ) { bloc }";
+ if ( strcmp(token, "else" ) == 0 ) return "else { bloc }";
+ if ( strcmp(token, "repeat" ) == 0 ) return "repeat ( number )";
+ if ( strcmp(token, "for" ) == 0 ) return "for ( before ; condition ; end )";
+ if ( strcmp(token, "while" ) == 0 ) return "while ( condition ) { bloc }";
+ if ( strcmp(token, "do" ) == 0 ) return "do { bloc } while ( condition );";
+ if ( strcmp(token, "break" ) == 0 ) return "break;";
+ if ( strcmp(token, "continue" ) == 0 ) return "continue;";
+ if ( strcmp(token, "return" ) == 0 ) return "return;";
+ if ( strcmp(token, "sizeof" ) == 0 ) return "sizeof( array );";
+ if ( strcmp(token, "int" ) == 0 ) return "int";
+ if ( strcmp(token, "sin" ) == 0 ) return "sin ( angle );";
+ if ( strcmp(token, "cos" ) == 0 ) return "cos ( angle );";
+ if ( strcmp(token, "tan" ) == 0 ) return "tan ( angle );";
+ if ( strcmp(token, "asin" ) == 0 ) return "asin ( value );";
+ if ( strcmp(token, "acos" ) == 0 ) return "acos ( value );";
+ if ( strcmp(token, "atan" ) == 0 ) return "atan ( value );";
+ if ( strcmp(token, "sqrt" ) == 0 ) return "sqrt ( value );";
+ if ( strcmp(token, "pow" ) == 0 ) return "pow ( x, y );";
+ if ( strcmp(token, "rand" ) == 0 ) return "rand ( );";
+ if ( strcmp(token, "abs" ) == 0 ) return "abs ( value );";
+ if ( strcmp(token, "retobject" ) == 0 ) return "retobjet ( );";
+ if ( strcmp(token, "search" ) == 0 ) return "search ( );";
+ if ( strcmp(token, "radar" ) == 0 ) return "radar ( cat, angle, focus, min, max, sens );";
+ if ( strcmp(token, "detect" ) == 0 ) return "detect ( cat );";
+ if ( strcmp(token, "direction" ) == 0 ) return "direction ( position );";
+ if ( strcmp(token, "distance2d") == 0 ) return "distance2d ( p1, p2 );";
+ if ( strcmp(token, "distance" ) == 0 ) return "distance ( p1, p2 );";
+ if ( strcmp(token, "space" ) == 0 ) return "space ( center, rmin, rmax, dist );";
+ if ( strcmp(token, "flatground") == 0 ) return "flatground ( center, rmax );";
+ if ( strcmp(token, "wait" ) == 0 ) return "wait ( time );";
+ if ( strcmp(token, "move" ) == 0 ) return "move ( distance );";
+ if ( strcmp(token, "turn" ) == 0 ) return "turn ( angle );";
+ if ( strcmp(token, "goto" ) == 0 ) return "goto ( position, altitude );";
+ if ( strcmp(token, "find" ) == 0 ) return "find ( cat );";
+ if ( strcmp(token, "grab" ) == 0 ) return "grab ( order );";
+ if ( strcmp(token, "drop" ) == 0 ) return "drop ( order );";
+ if ( strcmp(token, "sniff" ) == 0 ) return "sniff ( );";
+ if ( strcmp(token, "receive" ) == 0 ) return "receive ( name, power );";
+ if ( strcmp(token, "send" ) == 0 ) return "send ( name, value, power );";
+ if ( strcmp(token, "deleteinfo") == 0 ) return "deleteinfo ( name, power );";
+ if ( strcmp(token, "testinfo" ) == 0 ) return "testinfo ( name, power );";
+ if ( strcmp(token, "thump" ) == 0 ) return "thump ( );";
+ if ( strcmp(token, "recycle" ) == 0 ) return "recycle ( );";
+ if ( strcmp(token, "shield" ) == 0 ) return "shield ( oper, radius );";
+ if ( strcmp(token, "fire" ) == 0 ) return "fire ( time );";
+ if ( strcmp(token, "antfire" ) == 0 ) return "antfire ( );";
+ if ( strcmp(token, "aim" ) == 0 ) return "aim ( angle );";
+ if ( strcmp(token, "motor" ) == 0 ) return "motor ( left, right );";
+ if ( strcmp(token, "jet" ) == 0 ) return "jet ( power );";
+ if ( strcmp(token, "topo" ) == 0 ) return "topo ( position );";
+ if ( strcmp(token, "message" ) == 0 ) return "message ( string, type );";
+ if ( strcmp(token, "abstime" ) == 0 ) return "abstime ( );";
+ if ( strcmp(token, "ismovie" ) == 0 ) return "ismovie ( );";
+ if ( strcmp(token, "errmode" ) == 0 ) return "errmode ( mdoe );";
+ if ( strcmp(token, "ipf" ) == 0 ) return "ipf ( number );";
+ if ( strcmp(token, "strlen" ) == 0 ) return "strlen ( string );";
+ if ( strcmp(token, "strleft" ) == 0 ) return "strleft ( string, len );";
+ if ( strcmp(token, "strright" ) == 0 ) return "strright ( string, len );";
+ if ( strcmp(token, "strmid" ) == 0 ) return "strmid ( string, pos, len );";
+ if ( strcmp(token, "strval" ) == 0 ) return "strval ( string );";
+ if ( strcmp(token, "strfind" ) == 0 ) return "strfind ( string, substring );";
+ if ( strcmp(token, "strlower" ) == 0 ) return "strlower ( string );";
+ if ( strcmp(token, "strupper" ) == 0 ) return "strupper ( string );";
+ if ( strcmp(token, "open" ) == 0 ) return "open ( filename, mode );";
+ if ( strcmp(token, "close" ) == 0 ) return "close ( );";
+ if ( strcmp(token, "writeln" ) == 0 ) return "writeln ( string );";
+ if ( strcmp(token, "readln" ) == 0 ) return "readln ( );";
+ if ( strcmp(token, "eof" ) == 0 ) return "eof ( );";
+ if ( strcmp(token, "deletefile") == 0 ) return "deletefile ( filename );";
+ if ( strcmp(token, "openfile" ) == 0 ) return "openfile ( filename, mode );";
+ if ( strcmp(token, "pendown" ) == 0 ) return "pendown ( color, width );";
+ if ( strcmp(token, "penup" ) == 0 ) return "penup ( );";
+ if ( strcmp(token, "pencolor" ) == 0 ) return "pencolor ( color );";
+ if ( strcmp(token, "penwidth" ) == 0 ) return "penwidth ( width );";
+ return "";
+}
+
+
diff --git a/src/script/cbottoken.h b/src/script/cbottoken.h
new file mode 100644
index 0000000..0767b04
--- /dev/null
+++ b/src/script/cbottoken.h
@@ -0,0 +1,39 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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://www.gnu.org/licenses/.
+
+// cbottoken.h
+
+#ifndef _CBOTTOKEN_H_
+#define _CBOTTOKEN_H_
+
+
+#include "object.h"
+
+
+
+// Procedures.
+
+extern char* RetObjectName(ObjectType type);
+extern char* RetObjectAlias(ObjectType type);
+extern char* RetHelpFilename(ObjectType type);
+extern char* RetHelpFilename(const char *token);
+extern BOOL IsType(const char *token);
+extern BOOL IsFunction(const char *token);
+extern char* RetHelpText(const char *token);
+
+
+
+#endif //_CBOTTOKEN_H_
diff --git a/src/script/cmdtoken.cpp b/src/script/cmdtoken.cpp
new file mode 100644
index 0000000..d5295c5
--- /dev/null
+++ b/src/script/cmdtoken.cpp
@@ -0,0 +1,978 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "language.h"
+#include "global.h"
+#include "event.h"
+#include "water.h"
+#include "pyro.h"
+#include "camera.h"
+#include "object.h"
+#include "cmdtoken.h"
+
+
+
+
+
+// Skips spaces.
+
+char* SkipSpace(char *line)
+{
+ while ( *line == ' ' )
+ {
+ line ++;
+ }
+ return line;
+}
+
+// Checks if a line contains a command.
+
+BOOL Cmd(char *line, char *token)
+{
+ char* p;
+
+ line = SkipSpace(line);
+ p = strstr(line, token);
+ return ( p == line ); // command at the beginning?
+}
+
+// Seeking an operator.
+
+char* SearchOp(char *line, char *op)
+{
+ char opeq[50];
+ char* p;
+
+ strcpy(opeq, " ");
+ strcat(opeq, op);
+ strcat(opeq, "=");
+
+ p = strstr(line, opeq);
+ if ( p == 0 ) // not found?
+ {
+ return line+strlen(line); // point zero terminator
+ }
+ return p+strlen(opeq); // after the point "="
+}
+
+// Seeks the argument.
+
+char* SearchArg(char *line, int rank)
+{
+ int i;
+ char c;
+
+ for ( i=0 ; i<rank ; i++ )
+ {
+ while ( TRUE )
+ {
+ c = *line++;
+ if ( c == ';' ) break;
+ if ( c == '=' ||
+ c == 0 ) return line+strlen(line);
+ }
+ }
+
+ line = SkipSpace(line);
+ return line;
+}
+
+// Reads an integer, eventually hexadecimal.
+
+int GetInt(char *line, int rank, int def)
+{
+ char* p;
+ int n = 0;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return def;
+
+ if ( p[0] == '0' &&
+ p[1] == 'x' ) // begins with "0x" (hexadecimal)?
+ {
+ p += 2;
+ while ( TRUE )
+ {
+ if ( *p >= '0' && *p <= '9' )
+ {
+ n *= 16;
+ n += (*p++)-'0';
+ continue;
+ }
+ if ( *p >= 'a' && *p <= 'f' )
+ {
+ n *= 16;
+ n += (*p++)-'a'+10;
+ continue;
+ }
+ break;
+ }
+ }
+ else // integer?
+ {
+ sscanf(p, "%d", &n);
+ }
+ return n;
+}
+
+// Reads a float number.
+
+float GetFloat(char *line, int rank, float def)
+{
+ char* p;
+ float n = 0.0f;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return def;
+
+ sscanf(p, "%f", &n);
+ return n;
+}
+
+// Reads a string.
+
+void GetString(char *line, int rank, char *buffer)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ *buffer = 0;
+ if ( *p++ != '"' ) return;
+
+ while ( p[0] != 0 )
+ {
+ if ( p[0] == '"' &&
+ p[1] == '"' )
+ {
+ *buffer++ = *p++;
+ p++;
+ continue;
+ }
+ if ( p[0] == '"' ) break;
+
+ *buffer++ = *p++;
+ }
+ *buffer = 0;
+}
+
+// Returns the type of an object.
+
+ObjectType GetTypeObject(char *line, int rank, ObjectType def)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return def;
+
+ if ( Cmd(p, "All" ) ) return OBJECT_NULL;
+ if ( Cmd(p, "Portico" ) ) return OBJECT_PORTICO;
+ if ( Cmd(p, "SpaceShip" ) ) return OBJECT_BASE;
+ if ( Cmd(p, "PracticeBot" ) ) return OBJECT_MOBILEwt;
+ if ( Cmd(p, "WingedGrabber" ) ) return OBJECT_MOBILEfa;
+ if ( Cmd(p, "TrackedGrabber" ) ) return OBJECT_MOBILEta;
+ if ( Cmd(p, "WheeledGrabber" ) ) return OBJECT_MOBILEwa;
+ if ( Cmd(p, "LeggedGrabber" ) ) return OBJECT_MOBILEia;
+ if ( Cmd(p, "WingedShooter" ) ) return OBJECT_MOBILEfc;
+ if ( Cmd(p, "TrackedShooter" ) ) return OBJECT_MOBILEtc;
+ if ( Cmd(p, "WheeledShooter" ) ) return OBJECT_MOBILEwc;
+ if ( Cmd(p, "LeggedShooter" ) ) return OBJECT_MOBILEic;
+ if ( Cmd(p, "WingedOrgaShooter" ) ) return OBJECT_MOBILEfi;
+ if ( Cmd(p, "TrackedOrgaShooter") ) return OBJECT_MOBILEti;
+ if ( Cmd(p, "WheeledOrgaShooter") ) return OBJECT_MOBILEwi;
+ if ( Cmd(p, "LeggedOrgaShooter" ) ) return OBJECT_MOBILEii;
+ if ( Cmd(p, "WingedSniffer" ) ) return OBJECT_MOBILEfs;
+ if ( Cmd(p, "TrackedSniffer" ) ) return OBJECT_MOBILEts;
+ if ( Cmd(p, "WheeledSniffer" ) ) return OBJECT_MOBILEws;
+ if ( Cmd(p, "LeggedSniffer" ) ) return OBJECT_MOBILEis;
+ if ( Cmd(p, "Thumper" ) ) return OBJECT_MOBILErt;
+ if ( Cmd(p, "PhazerShooter" ) ) return OBJECT_MOBILErc;
+ if ( Cmd(p, "Recycler" ) ) return OBJECT_MOBILErr;
+ if ( Cmd(p, "Shielder" ) ) return OBJECT_MOBILErs;
+ if ( Cmd(p, "Subber" ) ) return OBJECT_MOBILEsa;
+ if ( Cmd(p, "TargetBot" ) ) return OBJECT_MOBILEtg;
+ if ( Cmd(p, "Scribbler" ) ) return OBJECT_MOBILEdr;
+ if ( Cmd(p, "PowerSpot" ) ) return OBJECT_MARKPOWER;
+ if ( Cmd(p, "TitaniumSpot" ) ) return OBJECT_MARKSTONE;
+ if ( Cmd(p, "UraniumSpot" ) ) return OBJECT_MARKURANIUM;
+ if ( Cmd(p, "PlatinumSpot" ) ) return OBJECT_MARKURANIUM;
+ if ( Cmd(p, "KeyASpot" ) ) return OBJECT_MARKKEYa;
+ if ( Cmd(p, "KeyBSpot" ) ) return OBJECT_MARKKEYb;
+ if ( Cmd(p, "KeyCSpot" ) ) return OBJECT_MARKKEYc;
+ if ( Cmd(p, "KeyDSpot" ) ) return OBJECT_MARKKEYd;
+ if ( Cmd(p, "WayPoint" ) ) return OBJECT_WAYPOINT;
+ if ( Cmd(p, "BlueFlag" ) ) return OBJECT_FLAGb;
+ if ( Cmd(p, "RedFlag" ) ) return OBJECT_FLAGr;
+ if ( Cmd(p, "GreenFlag" ) ) return OBJECT_FLAGg;
+ if ( Cmd(p, "YellowFlag" ) ) return OBJECT_FLAGy;
+ if ( Cmd(p, "VioletFlag" ) ) return OBJECT_FLAGv;
+ if ( Cmd(p, "PowerCell" ) ) return OBJECT_POWER;
+ if ( Cmd(p, "FuelCellPlant" ) ) return OBJECT_NUCLEAR;
+ if ( Cmd(p, "FuelCell" ) ) return OBJECT_ATOMIC;
+ if ( Cmd(p, "NuclearCell" ) ) return OBJECT_ATOMIC;
+ if ( Cmd(p, "TitaniumOre" ) ) return OBJECT_STONE;
+ if ( Cmd(p, "UraniumOre" ) ) return OBJECT_URANIUM;
+ if ( Cmd(p, "PlatinumOre" ) ) return OBJECT_URANIUM;
+ if ( Cmd(p, "Titanium" ) ) return OBJECT_METAL;
+ if ( Cmd(p, "OrgaMatter" ) ) return OBJECT_BULLET;
+ if ( Cmd(p, "BlackBox" ) ) return OBJECT_BBOX;
+ if ( Cmd(p, "KeyA" ) ) return OBJECT_KEYa;
+ if ( Cmd(p, "KeyB" ) ) return OBJECT_KEYb;
+ if ( Cmd(p, "KeyC" ) ) return OBJECT_KEYc;
+ if ( Cmd(p, "KeyD" ) ) return OBJECT_KEYd;
+ if ( Cmd(p, "TNT" ) ) return OBJECT_TNT;
+ if ( Cmd(p, "Scrap1" ) ) return OBJECT_SCRAP1;
+ if ( Cmd(p, "Scrap2" ) ) return OBJECT_SCRAP2;
+ if ( Cmd(p, "Scrap3" ) ) return OBJECT_SCRAP3;
+ if ( Cmd(p, "Scrap4" ) ) return OBJECT_SCRAP4;
+ if ( Cmd(p, "Scrap5" ) ) return OBJECT_SCRAP5;
+ if ( Cmd(p, "Mine" ) ) return OBJECT_BOMB;
+ if ( Cmd(p, "Firework" ) ) return OBJECT_WINFIRE;
+ if ( Cmd(p, "Bag" ) ) return OBJECT_BAG;
+ if ( Cmd(p, "Greenery10" ) ) return OBJECT_PLANT10;
+ if ( Cmd(p, "Greenery11" ) ) return OBJECT_PLANT11;
+ if ( Cmd(p, "Greenery12" ) ) return OBJECT_PLANT12;
+ if ( Cmd(p, "Greenery13" ) ) return OBJECT_PLANT13;
+ if ( Cmd(p, "Greenery14" ) ) return OBJECT_PLANT14;
+ if ( Cmd(p, "Greenery15" ) ) return OBJECT_PLANT15;
+ if ( Cmd(p, "Greenery16" ) ) return OBJECT_PLANT16;
+ if ( Cmd(p, "Greenery17" ) ) return OBJECT_PLANT17;
+ if ( Cmd(p, "Greenery18" ) ) return OBJECT_PLANT18;
+ if ( Cmd(p, "Greenery19" ) ) return OBJECT_PLANT19;
+ if ( Cmd(p, "Greenery0" ) ) return OBJECT_PLANT0;
+ if ( Cmd(p, "Greenery1" ) ) return OBJECT_PLANT1;
+ if ( Cmd(p, "Greenery2" ) ) return OBJECT_PLANT2;
+ if ( Cmd(p, "Greenery3" ) ) return OBJECT_PLANT3;
+ if ( Cmd(p, "Greenery4" ) ) return OBJECT_PLANT4;
+ if ( Cmd(p, "Greenery5" ) ) return OBJECT_PLANT5;
+ if ( Cmd(p, "Greenery6" ) ) return OBJECT_PLANT6;
+ if ( Cmd(p, "Greenery7" ) ) return OBJECT_PLANT7;
+ if ( Cmd(p, "Greenery8" ) ) return OBJECT_PLANT8;
+ if ( Cmd(p, "Greenery9" ) ) return OBJECT_PLANT9;
+ if ( Cmd(p, "Tree0" ) ) return OBJECT_TREE0;
+ if ( Cmd(p, "Tree1" ) ) return OBJECT_TREE1;
+ if ( Cmd(p, "Tree2" ) ) return OBJECT_TREE2;
+ if ( Cmd(p, "Tree3" ) ) return OBJECT_TREE3;
+ if ( Cmd(p, "Tree4" ) ) return OBJECT_TREE4;
+ if ( Cmd(p, "Tree5" ) ) return OBJECT_TREE5;
+ if ( Cmd(p, "Tree6" ) ) return OBJECT_TREE6;
+ if ( Cmd(p, "Tree7" ) ) return OBJECT_TREE7;
+ if ( Cmd(p, "Tree8" ) ) return OBJECT_TREE8;
+ if ( Cmd(p, "Tree9" ) ) return OBJECT_TREE9;
+ if ( Cmd(p, "Mushroom0" ) ) return OBJECT_MUSHROOM0;
+ if ( Cmd(p, "Mushroom1" ) ) return OBJECT_MUSHROOM1;
+ if ( Cmd(p, "Mushroom2" ) ) return OBJECT_MUSHROOM2;
+ if ( Cmd(p, "Mushroom3" ) ) return OBJECT_MUSHROOM3;
+ if ( Cmd(p, "Mushroom4" ) ) return OBJECT_MUSHROOM4;
+ if ( Cmd(p, "Mushroom5" ) ) return OBJECT_MUSHROOM5;
+ if ( Cmd(p, "Mushroom6" ) ) return OBJECT_MUSHROOM6;
+ if ( Cmd(p, "Mushroom7" ) ) return OBJECT_MUSHROOM7;
+ if ( Cmd(p, "Mushroom8" ) ) return OBJECT_MUSHROOM8;
+ if ( Cmd(p, "Mushroom9" ) ) return OBJECT_MUSHROOM9;
+ if ( Cmd(p, "Home" ) ) return OBJECT_HOME1;
+ if ( Cmd(p, "Derrick" ) ) return OBJECT_DERRICK;
+ if ( Cmd(p, "BotFactory" ) ) return OBJECT_FACTORY;
+ if ( Cmd(p, "PowerStation" ) ) return OBJECT_STATION;
+ if ( Cmd(p, "Converter" ) ) return OBJECT_CONVERT;
+ if ( Cmd(p, "RepairCenter" ) ) return OBJECT_REPAIR;
+ if ( Cmd(p, "Destroyer" ) ) return OBJECT_DESTROYER;
+ if ( Cmd(p, "DefenseTower" ) ) return OBJECT_TOWER;
+ if ( Cmd(p, "AlienNest" ) ) return OBJECT_NEST;
+ if ( Cmd(p, "ResearchCenter" ) ) return OBJECT_RESEARCH;
+ if ( Cmd(p, "RadarStation" ) ) return OBJECT_RADAR;
+ if ( Cmd(p, "ExchangePost" ) ) return OBJECT_INFO;
+ if ( Cmd(p, "PowerPlant" ) ) return OBJECT_ENERGY;
+ if ( Cmd(p, "AutoLab" ) ) return OBJECT_LABO;
+ if ( Cmd(p, "NuclearPlant" ) ) return OBJECT_NUCLEAR;
+ if ( Cmd(p, "PowerCaptor" ) ) return OBJECT_PARA;
+ if ( Cmd(p, "Vault" ) ) return OBJECT_SAFE;
+ if ( Cmd(p, "Houston" ) ) return OBJECT_HUSTON;
+ if ( Cmd(p, "Target1" ) ) return OBJECT_TARGET1;
+ if ( Cmd(p, "Target2" ) ) return OBJECT_TARGET2;
+ if ( Cmd(p, "StartArea" ) ) return OBJECT_START;
+ if ( Cmd(p, "GoalArea" ) ) return OBJECT_END;
+ if ( Cmd(p, "AlienQueen" ) ) return OBJECT_MOTHER;
+ if ( Cmd(p, "AlienEgg" ) ) return OBJECT_EGG;
+ if ( Cmd(p, "AlienAnt" ) ) return OBJECT_ANT;
+ if ( Cmd(p, "AlienSpider" ) ) return OBJECT_SPIDER;
+ if ( Cmd(p, "AlienWasp" ) ) return OBJECT_BEE;
+ if ( Cmd(p, "AlienWorm" ) ) return OBJECT_WORM;
+ if ( Cmd(p, "WreckBotw1" ) ) return OBJECT_RUINmobilew1;
+ if ( Cmd(p, "WreckBotw2" ) ) return OBJECT_RUINmobilew2;
+ if ( Cmd(p, "WreckBott1" ) ) return OBJECT_RUINmobilet1;
+ if ( Cmd(p, "WreckBott2" ) ) return OBJECT_RUINmobilet2;
+ if ( Cmd(p, "WreckBotr1" ) ) return OBJECT_RUINmobiler1;
+ if ( Cmd(p, "WreckBotr2" ) ) return OBJECT_RUINmobiler2;
+ if ( Cmd(p, "RuinBotFactory" ) ) return OBJECT_RUINfactory;
+ if ( Cmd(p, "RuinDoor" ) ) return OBJECT_RUINdoor;
+ if ( Cmd(p, "RuinSupport" ) ) return OBJECT_RUINsupport;
+ if ( Cmd(p, "RuinRadar" ) ) return OBJECT_RUINradar;
+ if ( Cmd(p, "RuinConvert" ) ) return OBJECT_RUINconvert;
+ if ( Cmd(p, "RuinBaseCamp" ) ) return OBJECT_RUINbase;
+ if ( Cmd(p, "RuinHeadCamp" ) ) return OBJECT_RUINhead;
+ if ( Cmd(p, "Barrier0" ) ) return OBJECT_BARRIER0;
+ if ( Cmd(p, "Barrier1" ) ) return OBJECT_BARRIER1;
+ if ( Cmd(p, "Barrier2" ) ) return OBJECT_BARRIER2;
+ if ( Cmd(p, "Barrier3" ) ) return OBJECT_BARRIER3;
+ if ( Cmd(p, "Barrier4" ) ) return OBJECT_BARRIER4;
+ if ( Cmd(p, "Teen40" ) ) return OBJECT_TEEN40;
+ if ( Cmd(p, "Teen41" ) ) return OBJECT_TEEN41;
+ if ( Cmd(p, "Teen42" ) ) return OBJECT_TEEN42;
+ if ( Cmd(p, "Teen43" ) ) return OBJECT_TEEN43;
+ if ( Cmd(p, "Teen44" ) ) return OBJECT_TEEN44;
+ if ( Cmd(p, "Teen45" ) ) return OBJECT_TEEN45;
+ if ( Cmd(p, "Teen46" ) ) return OBJECT_TEEN46;
+ if ( Cmd(p, "Teen47" ) ) return OBJECT_TEEN47;
+ if ( Cmd(p, "Teen48" ) ) return OBJECT_TEEN48;
+ if ( Cmd(p, "Teen49" ) ) return OBJECT_TEEN49;
+ if ( Cmd(p, "Teen30" ) ) return OBJECT_TEEN30;
+ if ( Cmd(p, "Teen31" ) ) return OBJECT_TEEN31;
+ if ( Cmd(p, "Teen32" ) ) return OBJECT_TEEN32;
+ if ( Cmd(p, "Teen33" ) ) return OBJECT_TEEN33;
+ if ( Cmd(p, "Stone" ) ) return OBJECT_TEEN34;
+ if ( Cmd(p, "Teen35" ) ) return OBJECT_TEEN35;
+ if ( Cmd(p, "Teen36" ) ) return OBJECT_TEEN36;
+ if ( Cmd(p, "Teen37" ) ) return OBJECT_TEEN37;
+ if ( Cmd(p, "Teen38" ) ) return OBJECT_TEEN38;
+ if ( Cmd(p, "Teen39" ) ) return OBJECT_TEEN39;
+ if ( Cmd(p, "Teen20" ) ) return OBJECT_TEEN20;
+ if ( Cmd(p, "Teen21" ) ) return OBJECT_TEEN21;
+ if ( Cmd(p, "Teen22" ) ) return OBJECT_TEEN22;
+ if ( Cmd(p, "Teen23" ) ) return OBJECT_TEEN23;
+ if ( Cmd(p, "Teen24" ) ) return OBJECT_TEEN24;
+ if ( Cmd(p, "Teen25" ) ) return OBJECT_TEEN25;
+ if ( Cmd(p, "Teen26" ) ) return OBJECT_TEEN26;
+ if ( Cmd(p, "Teen27" ) ) return OBJECT_TEEN27;
+ if ( Cmd(p, "Teen28" ) ) return OBJECT_TEEN28;
+ if ( Cmd(p, "Teen29" ) ) return OBJECT_TEEN29;
+ if ( Cmd(p, "Teen10" ) ) return OBJECT_TEEN10;
+ if ( Cmd(p, "Teen11" ) ) return OBJECT_TEEN11;
+ if ( Cmd(p, "Teen12" ) ) return OBJECT_TEEN12;
+ if ( Cmd(p, "Teen13" ) ) return OBJECT_TEEN13;
+ if ( Cmd(p, "Teen14" ) ) return OBJECT_TEEN14;
+ if ( Cmd(p, "Teen15" ) ) return OBJECT_TEEN15;
+ if ( Cmd(p, "Teen16" ) ) return OBJECT_TEEN16;
+ if ( Cmd(p, "Teen17" ) ) return OBJECT_TEEN17;
+ if ( Cmd(p, "Teen18" ) ) return OBJECT_TEEN18;
+ if ( Cmd(p, "Teen19" ) ) return OBJECT_TEEN19;
+ if ( Cmd(p, "Teen0" ) ) return OBJECT_TEEN0;
+ if ( Cmd(p, "Teen1" ) ) return OBJECT_TEEN1;
+ if ( Cmd(p, "Teen2" ) ) return OBJECT_TEEN2;
+ if ( Cmd(p, "Teen3" ) ) return OBJECT_TEEN3;
+ if ( Cmd(p, "Teen4" ) ) return OBJECT_TEEN4;
+ if ( Cmd(p, "Teen5" ) ) return OBJECT_TEEN5;
+ if ( Cmd(p, "Teen6" ) ) return OBJECT_TEEN6;
+ if ( Cmd(p, "Teen7" ) ) return OBJECT_TEEN7;
+ if ( Cmd(p, "Teen8" ) ) return OBJECT_TEEN8;
+ if ( Cmd(p, "Teen9" ) ) return OBJECT_TEEN9;
+ if ( Cmd(p, "Quartz0" ) ) return OBJECT_QUARTZ0;
+ if ( Cmd(p, "Quartz1" ) ) return OBJECT_QUARTZ1;
+ if ( Cmd(p, "Quartz2" ) ) return OBJECT_QUARTZ2;
+ if ( Cmd(p, "Quartz3" ) ) return OBJECT_QUARTZ3;
+ if ( Cmd(p, "Quartz4" ) ) return OBJECT_QUARTZ4;
+ if ( Cmd(p, "Quartz5" ) ) return OBJECT_QUARTZ5;
+ if ( Cmd(p, "Quartz6" ) ) return OBJECT_QUARTZ6;
+ if ( Cmd(p, "Quartz7" ) ) return OBJECT_QUARTZ7;
+ if ( Cmd(p, "Quartz8" ) ) return OBJECT_QUARTZ8;
+ if ( Cmd(p, "Quartz9" ) ) return OBJECT_QUARTZ9;
+ if ( Cmd(p, "MegaStalk0" ) ) return OBJECT_ROOT0;
+ if ( Cmd(p, "MegaStalk1" ) ) return OBJECT_ROOT1;
+ if ( Cmd(p, "MegaStalk2" ) ) return OBJECT_ROOT2;
+ if ( Cmd(p, "MegaStalk3" ) ) return OBJECT_ROOT3;
+ if ( Cmd(p, "MegaStalk4" ) ) return OBJECT_ROOT4;
+ if ( Cmd(p, "MegaStalk5" ) ) return OBJECT_ROOT5;
+ if ( Cmd(p, "MegaStalk6" ) ) return OBJECT_ROOT6;
+ if ( Cmd(p, "MegaStalk7" ) ) return OBJECT_ROOT7;
+ if ( Cmd(p, "MegaStalk8" ) ) return OBJECT_ROOT8;
+ if ( Cmd(p, "MegaStalk9" ) ) return OBJECT_ROOT9;
+ if ( Cmd(p, "ApolloLEM" ) ) return OBJECT_APOLLO1;
+ if ( Cmd(p, "ApolloJeep" ) ) return OBJECT_APOLLO2;
+ if ( Cmd(p, "ApolloFlag" ) ) return OBJECT_APOLLO3;
+ if ( Cmd(p, "ApolloModule" ) ) return OBJECT_APOLLO4;
+ if ( Cmd(p, "ApolloAntenna" ) ) return OBJECT_APOLLO5;
+ if ( Cmd(p, "Me" ) ) return OBJECT_HUMAN;
+ if ( Cmd(p, "Tech" ) ) return OBJECT_TECH;
+
+ return def;
+}
+
+// Returns the name of an object type.
+
+char* GetTypeObject(ObjectType type)
+{
+ if ( type == OBJECT_PORTICO ) return "Portico";
+ if ( type == OBJECT_BASE ) return "SpaceShip";
+ if ( type == OBJECT_MOBILEwt ) return "PracticeBot";
+ if ( type == OBJECT_MOBILEfa ) return "WingedGrabber";
+ if ( type == OBJECT_MOBILEta ) return "TrackedGrabber";
+ if ( type == OBJECT_MOBILEwa ) return "WheeledGrabber";
+ if ( type == OBJECT_MOBILEia ) return "LeggedGrabber";
+ if ( type == OBJECT_MOBILEfc ) return "WingedShooter";
+ if ( type == OBJECT_MOBILEtc ) return "TrackedShooter";
+ if ( type == OBJECT_MOBILEwc ) return "WheeledShooter";
+ if ( type == OBJECT_MOBILEic ) return "LeggedShooter";
+ if ( type == OBJECT_MOBILEfi ) return "WingedOrgaShooter";
+ if ( type == OBJECT_MOBILEti ) return "TrackedOrgaShooter";
+ if ( type == OBJECT_MOBILEwi ) return "WheeledOrgaShooter";
+ if ( type == OBJECT_MOBILEii ) return "LeggedOrgaShooter";
+ if ( type == OBJECT_MOBILEfs ) return "WingedSniffer";
+ if ( type == OBJECT_MOBILEts ) return "TrackedSniffer";
+ if ( type == OBJECT_MOBILEws ) return "WheeledSniffer";
+ if ( type == OBJECT_MOBILEis ) return "LeggedSniffer";
+ if ( type == OBJECT_MOBILErt ) return "Thumper";
+ if ( type == OBJECT_MOBILErc ) return "PhazerShooter";
+ if ( type == OBJECT_MOBILErr ) return "Recycler";
+ if ( type == OBJECT_MOBILErs ) return "Shielder";
+ if ( type == OBJECT_MOBILEsa ) return "Subber";
+ if ( type == OBJECT_MOBILEtg ) return "TargetBot";
+ if ( type == OBJECT_MOBILEdr ) return "Scribbler";
+ if ( type == OBJECT_MARKPOWER ) return "PowerSpot";
+ if ( type == OBJECT_MARKSTONE ) return "TitaniumSpot";
+#if _GERMAN | _WG
+ if ( type == OBJECT_MARKURANIUM ) return "PlatinumSpot";
+#else
+ if ( type == OBJECT_MARKURANIUM ) return "UraniumSpot";
+#endif
+ if ( type == OBJECT_MARKKEYa ) return "KeyASpot";
+ if ( type == OBJECT_MARKKEYb ) return "KeyBSpot";
+ if ( type == OBJECT_MARKKEYc ) return "KeyCSpot";
+ if ( type == OBJECT_MARKKEYd ) return "KeyDSpot";
+ if ( type == OBJECT_WAYPOINT ) return "WayPoint";
+ if ( type == OBJECT_FLAGb ) return "BlueFlag";
+ if ( type == OBJECT_FLAGr ) return "RedFlag";
+ if ( type == OBJECT_FLAGg ) return "GreenFlag";
+ if ( type == OBJECT_FLAGy ) return "YellowFlag";
+ if ( type == OBJECT_FLAGv ) return "VioletFlag";
+ if ( type == OBJECT_POWER ) return "PowerCell";
+#if _GERMAN | _WG
+ if ( type == OBJECT_ATOMIC ) return "FuelCell";
+#else
+ if ( type == OBJECT_ATOMIC ) return "NuclearCell";
+#endif
+ if ( type == OBJECT_STONE ) return "TitaniumOre";
+#if _GERMAN | _WG
+ if ( type == OBJECT_URANIUM ) return "PlatinumOre";
+#else
+ if ( type == OBJECT_URANIUM ) return "UraniumOre";
+#endif
+ if ( type == OBJECT_METAL ) return "Titanium";
+ if ( type == OBJECT_BULLET ) return "OrgaMatter";
+ if ( type == OBJECT_BBOX ) return "BlackBox";
+ if ( type == OBJECT_KEYa ) return "KeyA";
+ if ( type == OBJECT_KEYb ) return "KeyB";
+ if ( type == OBJECT_KEYc ) return "KeyC";
+ if ( type == OBJECT_KEYd ) return "KeyD";
+ if ( type == OBJECT_TNT ) return "TNT";
+ if ( type == OBJECT_SCRAP1 ) return "Scrap1";
+ if ( type == OBJECT_SCRAP2 ) return "Scrap2";
+ if ( type == OBJECT_SCRAP3 ) return "Scrap3";
+ if ( type == OBJECT_SCRAP4 ) return "Scrap4";
+ if ( type == OBJECT_SCRAP5 ) return "Scrap5";
+ if ( type == OBJECT_BOMB ) return "Mine";
+ if ( type == OBJECT_WINFIRE ) return "Firework";
+ if ( type == OBJECT_BAG ) return "Bag";
+ if ( type == OBJECT_PLANT0 ) return "Greenery0";
+ if ( type == OBJECT_PLANT1 ) return "Greenery1";
+ if ( type == OBJECT_PLANT2 ) return "Greenery2";
+ if ( type == OBJECT_PLANT3 ) return "Greenery3";
+ if ( type == OBJECT_PLANT4 ) return "Greenery4";
+ if ( type == OBJECT_PLANT5 ) return "Greenery5";
+ if ( type == OBJECT_PLANT6 ) return "Greenery6";
+ if ( type == OBJECT_PLANT7 ) return "Greenery7";
+ if ( type == OBJECT_PLANT8 ) return "Greenery8";
+ if ( type == OBJECT_PLANT9 ) return "Greenery9";
+ if ( type == OBJECT_PLANT10 ) return "Greenery10";
+ if ( type == OBJECT_PLANT11 ) return "Greenery11";
+ if ( type == OBJECT_PLANT12 ) return "Greenery12";
+ if ( type == OBJECT_PLANT13 ) return "Greenery13";
+ if ( type == OBJECT_PLANT14 ) return "Greenery14";
+ if ( type == OBJECT_PLANT15 ) return "Greenery15";
+ if ( type == OBJECT_PLANT16 ) return "Greenery16";
+ if ( type == OBJECT_PLANT17 ) return "Greenery17";
+ if ( type == OBJECT_PLANT18 ) return "Greenery18";
+ if ( type == OBJECT_PLANT19 ) return "Greenery19";
+ if ( type == OBJECT_TREE0 ) return "Tree0";
+ if ( type == OBJECT_TREE1 ) return "Tree1";
+ if ( type == OBJECT_TREE2 ) return "Tree2";
+ if ( type == OBJECT_TREE3 ) return "Tree3";
+ if ( type == OBJECT_TREE4 ) return "Tree4";
+ if ( type == OBJECT_TREE5 ) return "Tree5";
+ if ( type == OBJECT_TREE6 ) return "Tree6";
+ if ( type == OBJECT_TREE7 ) return "Tree7";
+ if ( type == OBJECT_TREE8 ) return "Tree8";
+ if ( type == OBJECT_TREE9 ) return "Tree9";
+ if ( type == OBJECT_MUSHROOM0 ) return "Mushroom0";
+ if ( type == OBJECT_MUSHROOM1 ) return "Mushroom1";
+ if ( type == OBJECT_MUSHROOM2 ) return "Mushroom2";
+ if ( type == OBJECT_MUSHROOM3 ) return "Mushroom3";
+ if ( type == OBJECT_MUSHROOM4 ) return "Mushroom4";
+ if ( type == OBJECT_MUSHROOM5 ) return "Mushroom5";
+ if ( type == OBJECT_MUSHROOM6 ) return "Mushroom6";
+ if ( type == OBJECT_MUSHROOM7 ) return "Mushroom7";
+ if ( type == OBJECT_MUSHROOM8 ) return "Mushroom8";
+ if ( type == OBJECT_MUSHROOM9 ) return "Mushroom9";
+ if ( type == OBJECT_HOME1 ) return "Home";
+ if ( type == OBJECT_DERRICK ) return "Derrick";
+ if ( type == OBJECT_FACTORY ) return "BotFactory";
+ if ( type == OBJECT_STATION ) return "PowerStation";
+ if ( type == OBJECT_CONVERT ) return "Converter";
+ if ( type == OBJECT_REPAIR ) return "RepairCenter";
+ if ( type == OBJECT_DESTROYER ) return "Destroyer";
+ if ( type == OBJECT_TOWER ) return "DefenseTower";
+ if ( type == OBJECT_NEST ) return "AlienNest";
+ if ( type == OBJECT_RESEARCH ) return "ResearchCenter";
+ if ( type == OBJECT_RADAR ) return "RadarStation";
+ if ( type == OBJECT_INFO ) return "ExchangePost";
+ if ( type == OBJECT_ENERGY ) return "PowerPlant";
+ if ( type == OBJECT_LABO ) return "AutoLab";
+#if _GERMAN | _WG
+ if ( type == OBJECT_NUCLEAR ) return "FuelCellPlant";
+#else
+ if ( type == OBJECT_NUCLEAR ) return "NuclearPlant";
+#endif
+ if ( type == OBJECT_PARA ) return "PowerCaptor";
+ if ( type == OBJECT_SAFE ) return "Vault";
+ if ( type == OBJECT_HUSTON ) return "Houston";
+ if ( type == OBJECT_TARGET1 ) return "Target1";
+ if ( type == OBJECT_TARGET2 ) return "Target2";
+ if ( type == OBJECT_START ) return "StartArea";
+ if ( type == OBJECT_END ) return "GoalArea";
+ if ( type == OBJECT_MOTHER ) return "AlienQueen";
+ if ( type == OBJECT_EGG ) return "AlienEgg";
+ if ( type == OBJECT_ANT ) return "AlienAnt";
+ if ( type == OBJECT_SPIDER ) return "AlienSpider";
+ if ( type == OBJECT_BEE ) return "AlienWasp";
+ if ( type == OBJECT_WORM ) return "AlienWorm";
+ if ( type == OBJECT_RUINmobilew1 ) return "WreckBotw1";
+ if ( type == OBJECT_RUINmobilew2 ) return "WreckBotw2";
+ if ( type == OBJECT_RUINmobilet1 ) return "WreckBott1";
+ if ( type == OBJECT_RUINmobilet2 ) return "WreckBott2";
+ if ( type == OBJECT_RUINmobiler1 ) return "WreckBotr1";
+ if ( type == OBJECT_RUINmobiler2 ) return "WreckBotr2";
+ if ( type == OBJECT_RUINfactory ) return "RuinBotFactory";
+ if ( type == OBJECT_RUINdoor ) return "RuinDoor";
+ if ( type == OBJECT_RUINsupport ) return "RuinSupport";
+ if ( type == OBJECT_RUINradar ) return "RuinRadar";
+ if ( type == OBJECT_RUINconvert ) return "RuinConvert";
+ if ( type == OBJECT_RUINbase ) return "RuinBaseCamp";
+ if ( type == OBJECT_RUINhead ) return "RuinHeadCamp";
+ if ( type == OBJECT_BARRIER0 ) return "Barrier0";
+ if ( type == OBJECT_BARRIER1 ) return "Barrier1";
+ if ( type == OBJECT_BARRIER2 ) return "Barrier2";
+ if ( type == OBJECT_BARRIER3 ) return "Barrier3";
+ if ( type == OBJECT_BARRIER4 ) return "Barrier4";
+ if ( type == OBJECT_TEEN0 ) return "Teen0";
+ if ( type == OBJECT_TEEN1 ) return "Teen1";
+ if ( type == OBJECT_TEEN2 ) return "Teen2";
+ if ( type == OBJECT_TEEN3 ) return "Teen3";
+ if ( type == OBJECT_TEEN4 ) return "Teen4";
+ if ( type == OBJECT_TEEN5 ) return "Teen5";
+ if ( type == OBJECT_TEEN6 ) return "Teen6";
+ if ( type == OBJECT_TEEN7 ) return "Teen7";
+ if ( type == OBJECT_TEEN8 ) return "Teen8";
+ if ( type == OBJECT_TEEN9 ) return "Teen9";
+ if ( type == OBJECT_TEEN10 ) return "Teen10";
+ if ( type == OBJECT_TEEN11 ) return "Teen11";
+ if ( type == OBJECT_TEEN12 ) return "Teen12";
+ if ( type == OBJECT_TEEN13 ) return "Teen13";
+ if ( type == OBJECT_TEEN14 ) return "Teen14";
+ if ( type == OBJECT_TEEN15 ) return "Teen15";
+ if ( type == OBJECT_TEEN16 ) return "Teen16";
+ if ( type == OBJECT_TEEN17 ) return "Teen17";
+ if ( type == OBJECT_TEEN18 ) return "Teen18";
+ if ( type == OBJECT_TEEN19 ) return "Teen19";
+ if ( type == OBJECT_TEEN20 ) return "Teen20";
+ if ( type == OBJECT_TEEN21 ) return "Teen21";
+ if ( type == OBJECT_TEEN22 ) return "Teen22";
+ if ( type == OBJECT_TEEN23 ) return "Teen23";
+ if ( type == OBJECT_TEEN24 ) return "Teen24";
+ if ( type == OBJECT_TEEN25 ) return "Teen25";
+ if ( type == OBJECT_TEEN26 ) return "Teen26";
+ if ( type == OBJECT_TEEN27 ) return "Teen27";
+ if ( type == OBJECT_TEEN28 ) return "Teen28";
+ if ( type == OBJECT_TEEN29 ) return "Teen29";
+ if ( type == OBJECT_TEEN30 ) return "Teen30";
+ if ( type == OBJECT_TEEN31 ) return "Teen31";
+ if ( type == OBJECT_TEEN32 ) return "Teen32";
+ if ( type == OBJECT_TEEN33 ) return "Teen33";
+ if ( type == OBJECT_TEEN34 ) return "Stone";
+ if ( type == OBJECT_TEEN35 ) return "Teen35";
+ if ( type == OBJECT_TEEN36 ) return "Teen36";
+ if ( type == OBJECT_TEEN37 ) return "Teen37";
+ if ( type == OBJECT_TEEN38 ) return "Teen38";
+ if ( type == OBJECT_TEEN39 ) return "Teen39";
+ if ( type == OBJECT_TEEN40 ) return "Teen40";
+ if ( type == OBJECT_TEEN41 ) return "Teen41";
+ if ( type == OBJECT_TEEN42 ) return "Teen42";
+ if ( type == OBJECT_TEEN43 ) return "Teen43";
+ if ( type == OBJECT_TEEN44 ) return "Teen44";
+ if ( type == OBJECT_TEEN45 ) return "Teen45";
+ if ( type == OBJECT_TEEN46 ) return "Teen46";
+ if ( type == OBJECT_TEEN47 ) return "Teen47";
+ if ( type == OBJECT_TEEN48 ) return "Teen48";
+ if ( type == OBJECT_TEEN49 ) return "Teen49";
+ if ( type == OBJECT_QUARTZ0 ) return "Quartz0";
+ if ( type == OBJECT_QUARTZ1 ) return "Quartz1";
+ if ( type == OBJECT_QUARTZ2 ) return "Quartz2";
+ if ( type == OBJECT_QUARTZ3 ) return "Quartz3";
+ if ( type == OBJECT_QUARTZ4 ) return "Quartz4";
+ if ( type == OBJECT_QUARTZ5 ) return "Quartz5";
+ if ( type == OBJECT_QUARTZ6 ) return "Quartz6";
+ if ( type == OBJECT_QUARTZ7 ) return "Quartz7";
+ if ( type == OBJECT_QUARTZ8 ) return "Quartz8";
+ if ( type == OBJECT_QUARTZ9 ) return "Quartz9";
+ if ( type == OBJECT_ROOT0 ) return "MegaStalk0";
+ if ( type == OBJECT_ROOT1 ) return "MegaStalk1";
+ if ( type == OBJECT_ROOT2 ) return "MegaStalk2";
+ if ( type == OBJECT_ROOT3 ) return "MegaStalk3";
+ if ( type == OBJECT_ROOT4 ) return "MegaStalk4";
+ if ( type == OBJECT_ROOT5 ) return "MegaStalk5";
+ if ( type == OBJECT_ROOT6 ) return "MegaStalk6";
+ if ( type == OBJECT_ROOT7 ) return "MegaStalk7";
+ if ( type == OBJECT_ROOT8 ) return "MegaStalk8";
+ if ( type == OBJECT_ROOT9 ) return "MegaStalk9";
+ if ( type == OBJECT_APOLLO1 ) return "ApolloLEM";
+ if ( type == OBJECT_APOLLO2 ) return "ApolloJeep";
+ if ( type == OBJECT_APOLLO3 ) return "ApolloFlag";
+ if ( type == OBJECT_APOLLO4 ) return "ApolloModule";
+ if ( type == OBJECT_APOLLO5 ) return "ApolloAntenna";
+ if ( type == OBJECT_HUMAN ) return "Me";
+ if ( type == OBJECT_TECH ) return "Tech";
+ return "";
+}
+
+// Returns the type of water.
+
+WaterType GetTypeWater(char *line, int rank, WaterType def)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return def;
+
+ if ( Cmd(p, "NULL" ) ) return WATER_NULL;
+ if ( Cmd(p, "TT" ) ) return WATER_TT;
+ if ( Cmd(p, "TO" ) ) return WATER_TO;
+ if ( Cmd(p, "CT" ) ) return WATER_CT;
+ if ( Cmd(p, "CO" ) ) return WATER_CO;
+
+ return def;
+}
+
+// Returns the type of terrain.
+
+D3DTypeObj GetTypeTerrain(char *line, int rank, D3DTypeObj def)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return def;
+
+ if ( Cmd(p, "Terrain" ) ) return TYPETERRAIN;
+ if ( Cmd(p, "Object" ) ) return TYPEFIX;
+ if ( Cmd(p, "Quartz" ) ) return TYPEQUARTZ;
+ if ( Cmd(p, "Metal" ) ) return TYPEMETAL;
+
+ return def;
+}
+
+// Returns the type of a building.
+
+int GetBuild(char *line, int rank)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return 0;
+
+ if ( Cmd(p, "BotFactory" ) ) return BUILD_FACTORY;
+ if ( Cmd(p, "Derrick" ) ) return BUILD_DERRICK;
+ if ( Cmd(p, "Converter" ) ) return BUILD_CONVERT;
+ if ( Cmd(p, "RadarStation" ) ) return BUILD_RADAR;
+ if ( Cmd(p, "PowerPlant" ) ) return BUILD_ENERGY;
+ if ( Cmd(p, "NuclearPlant" ) ) return BUILD_NUCLEAR;
+ if ( Cmd(p, "FuelCellPlant" ) ) return BUILD_NUCLEAR;
+ if ( Cmd(p, "PowerStation" ) ) return BUILD_STATION;
+ if ( Cmd(p, "RepairCenter" ) ) return BUILD_REPAIR;
+ if ( Cmd(p, "DefenseTower" ) ) return BUILD_TOWER;
+ if ( Cmd(p, "ResearchCenter") ) return BUILD_RESEARCH;
+ if ( Cmd(p, "AutoLab" ) ) return BUILD_LABO;
+ if ( Cmd(p, "PowerCaptor" ) ) return BUILD_PARA;
+ if ( Cmd(p, "ExchangePost" ) ) return BUILD_INFO;
+ if ( Cmd(p, "FlatGround" ) ) return BUILD_GFLAT;
+ if ( Cmd(p, "Flag" ) ) return BUILD_FLAG;
+
+ return 0;
+}
+
+// Returns the type of search.
+
+int GetResearch(char *line, int rank)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return 0;
+
+ if ( Cmd(p, "TRACKER" ) ) return RESEARCH_TANK;
+ if ( Cmd(p, "WINGER" ) ) return RESEARCH_FLY;
+ if ( Cmd(p, "THUMPER" ) ) return RESEARCH_THUMP;
+ if ( Cmd(p, "SHOOTER" ) ) return RESEARCH_CANON;
+ if ( Cmd(p, "TOWER" ) ) return RESEARCH_TOWER;
+ if ( Cmd(p, "PHAZER" ) ) return RESEARCH_PHAZER;
+ if ( Cmd(p, "SHIELDER") ) return RESEARCH_SHIELD;
+ if ( Cmd(p, "ATOMIC" ) ) return RESEARCH_ATOMIC;
+ if ( Cmd(p, "iPAW" ) ) return RESEARCH_iPAW;
+ if ( Cmd(p, "iGUN" ) ) return RESEARCH_iGUN;
+ if ( Cmd(p, "RECYCLER") ) return RESEARCH_RECYCLER;
+ if ( Cmd(p, "SUBBER" ) ) return RESEARCH_SUBM;
+ if ( Cmd(p, "SNIFFER" ) ) return RESEARCH_SNIFFER;
+
+ return 0;
+}
+
+// Returns the type of pyrotechnic effect.
+
+PyroType GetPyro(char *line, int rank)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return PT_NULL;
+
+ if ( Cmd(p, "FRAGt" ) ) return PT_FRAGT;
+ if ( Cmd(p, "FRAGo" ) ) return PT_FRAGO;
+ if ( Cmd(p, "FRAGw" ) ) return PT_FRAGW;
+ if ( Cmd(p, "EXPLOt" ) ) return PT_EXPLOT;
+ if ( Cmd(p, "EXPLOo" ) ) return PT_EXPLOO;
+ if ( Cmd(p, "EXPLOw" ) ) return PT_EXPLOW;
+ if ( Cmd(p, "SHOTt" ) ) return PT_SHOTT;
+ if ( Cmd(p, "SHOTh" ) ) return PT_SHOTH;
+ if ( Cmd(p, "SHOTm" ) ) return PT_SHOTM;
+ if ( Cmd(p, "SHOTw" ) ) return PT_SHOTW;
+ if ( Cmd(p, "EGG" ) ) return PT_EGG;
+ if ( Cmd(p, "BURNt" ) ) return PT_BURNT;
+ if ( Cmd(p, "BURNo" ) ) return PT_BURNO;
+ if ( Cmd(p, "SPIDER" ) ) return PT_SPIDER;
+ if ( Cmd(p, "FALL" ) ) return PT_FALL;
+ if ( Cmd(p, "RESET" ) ) return PT_RESET;
+ if ( Cmd(p, "WIN" ) ) return PT_WIN;
+ if ( Cmd(p, "LOST" ) ) return PT_LOST;
+
+ return PT_NULL;
+}
+
+// Returns the type of camera.
+
+CameraType GetCamera(char *line, int rank)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return CAMERA_NULL;
+
+ if ( Cmd(p, "BACK" ) ) return CAMERA_BACK;
+ if ( Cmd(p, "PLANE" ) ) return CAMERA_PLANE;
+ if ( Cmd(p, "ONBOARD" ) ) return CAMERA_ONBOARD;
+ if ( Cmd(p, "FIX" ) ) return CAMERA_FIX;
+
+ return CAMERA_NULL;
+}
+
+// Returns the name of a camera.
+
+char* GetCamera(CameraType type)
+{
+ if ( type == CAMERA_ONBOARD ) return "ONBOARD";
+ if ( type == CAMERA_FIX ) return "FIX";
+ return "BACK";
+}
+
+// Returns an integer.
+
+int OpInt(char *line, char *op, int def)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+ return GetInt(line, 0, def);
+}
+
+// Returns a float number.
+
+float OpFloat(char *line, char *op, float def)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+ return GetFloat(line, 0, def);
+}
+
+// Returns a string.
+
+void OpString(char *line, char *op, char *buffer)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 )
+ {
+ buffer[0] = 0;
+ }
+ else
+ {
+ GetString(line, 0, buffer);
+ }
+}
+
+// Returns the type of an object.
+
+ObjectType OpTypeObject(char *line, char *op, ObjectType def)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+ return GetTypeObject(line, 0, def);
+}
+
+// Returns the type of a water.
+
+WaterType OpTypeWater(char *line, char *op, WaterType def)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+ return GetTypeWater(line, 0, def);
+}
+
+// Returns the type of a terrain.
+
+D3DTypeObj OpTypeTerrain(char *line, char *op, D3DTypeObj def)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+ return GetTypeTerrain(line, 0, def);
+}
+
+// Returns the type of research.
+
+int OpResearch(char *line, char *op)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return 0;
+ return GetResearch(line, 0);
+}
+
+// Returns the type of pyrotechnic effect.
+
+PyroType OpPyro(char *line, char *op)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return PT_NULL;
+ return GetPyro(line, 0);
+}
+
+// Returns the type of camera.
+
+CameraType OpCamera(char *line, char *op)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return CAMERA_NULL;
+ return GetCamera(line, 0);
+}
+
+// Returns the type of a building.
+
+int OpBuild(char *line, char *op)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return 0;
+ return GetBuild(line, 0);
+}
+
+// Returns a position in the XZ plane (top view).
+
+D3DVECTOR OpPos(char *line, char *op)
+{
+ D3DVECTOR pos;
+
+ line = SearchOp(line, op);
+ if ( *line == 0 )
+ {
+ pos = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ return pos;
+ }
+ pos.x = GetFloat(line, 0, 0.0f);
+ pos.y = 0.0f;
+ pos.z = GetFloat(line, 1, 0.0f);
+ return pos;
+}
+
+// Returns a direction.
+
+D3DVECTOR OpDir(char *line, char *op)
+{
+ D3DVECTOR dir;
+
+ line = SearchOp(line, op);
+ if ( *line == 0 )
+ {
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ return dir;
+ }
+ dir.x = GetFloat(line, 0, 0.0f);
+ dir.y = GetFloat(line, 1, 0.0f);
+ dir.z = GetFloat(line, 2, 0.0f);
+ return dir;
+}
+
+// Reads a color (0 .. 255).
+
+D3DCOLOR OpColor(char *line, char *op, D3DCOLOR def)
+{
+ D3DCOLOR color;
+
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+
+ color = 0;
+ color |= (GetInt(line, 0, 0)&0xff)<<16; // r
+ color |= (GetInt(line, 1, 0)&0xff)<<8; // g
+ color |= (GetInt(line, 2, 0)&0xff)<<0; // b
+ color |= (GetInt(line, 3, 0)&0xff)<<24; // a
+ return color;
+}
+
+// Reads a color (-1 .. 1).
+
+D3DCOLORVALUE OpColorValue(char *line, char *op, D3DCOLORVALUE def)
+{
+ D3DCOLORVALUE color;
+
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+
+ color.r = GetFloat(line, 0, 0.0f);
+ color.g = GetFloat(line, 1, 0.0f);
+ color.b = GetFloat(line, 2, 0.0f);
+ color.a = GetFloat(line, 3, 0.0f);
+ return color;
+}
+
+
diff --git a/src/script/cmdtoken.h b/src/script/cmdtoken.h
new file mode 100644
index 0000000..40fb36a
--- /dev/null
+++ b/src/script/cmdtoken.h
@@ -0,0 +1,67 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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://www.gnu.org/licenses/.
+
+// cmdtoken.h
+
+#ifndef _CMDTOKEN_H_
+#define _CMDTOKEN_H_
+
+
+#include "d3denum.h"
+#include "d3dengine.h"
+#include "object.h"
+#include "water.h"
+#include "pyro.h"
+#include "camera.h"
+
+
+
+// Procedures.
+
+extern BOOL Cmd(char *line, char *token);
+extern char* SearchOp(char *line, char *op);
+
+extern int GetInt(char *line, int rank, int def);
+extern float GetFloat(char *line, int rank, float def);
+extern void GetString(char *line, int rank, char *buffer);
+extern ObjectType GetTypeObject(char *line, int rank, ObjectType def);
+extern char* GetTypeObject(ObjectType type);
+extern WaterType GetTypeWater(char *line, int rank, WaterType def);
+extern D3DTypeObj GetTypeTerrain(char *line, int rank, D3DTypeObj def);
+extern int GetBuild(char *line, int rank);
+extern int GetResearch(char *line, int rank);
+extern PyroType GetPyro(char *line, int rank);
+extern CameraType GetCamera(char *line, int rank);
+extern char* GetCamera(CameraType type);
+
+extern int OpInt(char *line, char *op, int def);
+extern float OpFloat(char *line, char *op, float def);
+extern void OpString(char *line, char *op, char *buffer);
+extern ObjectType OpTypeObject(char *line, char *op, ObjectType def);
+extern WaterType OpTypeWater(char *line, char *op, WaterType def);
+extern D3DTypeObj OpTypeTerrain(char *line, char *op, D3DTypeObj def);
+extern int OpResearch(char *line, char *op);
+extern PyroType OpPyro(char *line, char *op);
+extern CameraType OpCamera(char *line, char *op);
+extern int OpBuild(char *line, char *op);
+extern D3DVECTOR OpPos(char *line, char *op);
+extern D3DVECTOR OpDir(char *line, char *op);
+extern D3DCOLOR OpColor(char *line, char *op, D3DCOLOR def);
+extern D3DCOLORVALUE OpColorValue(char *line, char *op, D3DCOLORVALUE def);
+
+
+
+#endif //_CMDTOKEN_H_
diff --git a/src/script/dd.cpp b/src/script/dd.cpp
new file mode 100644
index 0000000..75e332a
--- /dev/null
+++ b/src/script/dd.cpp
@@ -0,0 +1,175 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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://www.gnu.org/licenses/.
+
+// Compilation of a procedure with a "dot".
+
+int cPoint(CBotVar* &var, CBotString& retClass, void* user)
+{
+ if ( var == 0 ) return CBotErrLowParam;
+
+ if ( var->GivType() <= CBotTypDouble )
+ {
+ var = var->GivNext();
+ if ( var == 0 ) return CBotErrLowParam;
+ if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
+ var = var->GivNext();
+ if ( var == 0 ) return CBotErrLowParam;
+ if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
+ var = var->GivNext();
+ return 0;
+ }
+
+ if ( var->GivType() == CBotTypClass )
+ {
+ if ( !var->IsElemOfClass("point") ) return CBotErrBadParam;
+ var = var->GivNext();
+ return 0;
+ }
+
+ return CBotErrBadParam;
+}
+
+// Gives a parameter of type "point".
+
+BOOL GetPoint(CBotVar* &var, int& exception, D3DVECTOR& pos)
+{
+ CBotVar *pX, *pY, *pZ;
+
+ if ( var->GivType() <= CBotTypDouble )
+ {
+ pos.x = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+
+ pos.z = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+
+ pos.y = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+ }
+ else
+ {
+ pX = var->GivItem("x");
+ if ( pX == NULL )
+ {
+ exception = CBotErrUndefItem; return TRUE;
+ }
+ pos.x = pX->GivValFloat()*UNIT;
+
+ pY = var->GivItem("y");
+ if ( pY == NULL )
+ {
+ exception = CBotErrUndefItem; return TRUE;
+ }
+ pos.z = pY->GivValFloat()*UNIT; // attention y -> z !
+
+ pZ = var->GivItem("z");
+ if ( pZ == NULL )
+ {
+ exception = CBotErrUndefItem; return TRUE;
+ }
+ pos.y = pZ->GivValFloat()*UNIT; // attention z -> y !
+
+ var = var->GivNext();
+ }
+ return TRUE;
+}
+
+
+
+// Compilation of the instruction "space(center, rMin, rMax, dist)".
+
+int cSpace(CBotVar* &var, CBotString& retClass, void* user)
+{
+ int ret;
+
+ retClass = "point";
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ ret = cPoint(var, retClass, user);
+ if ( ret != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotErrOverParam;
+ return CBotTypIntrinsic;
+}
+
+// Instruction "space(center, rMin, rMax, dist)".
+
+BOOL rSpace(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CBotVar* pSub;
+ D3DVECTOR center;
+ float rMin, rMax, dist;
+
+ rMin = 5.0f*UNIT;
+ rMax = 50.0f*UNIT;
+ dist = 4.0f*UNIT;
+
+ if ( var == 0 )
+ {
+ center = pThis->RetPosition(0);
+ }
+ else
+ {
+ if ( !GetPoint(var, exception, center) ) return TRUE;
+
+ if ( var != 0 )
+ {
+ rMin = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+
+ if ( var != 0 )
+ {
+ rMax = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+
+ if ( var != 0 )
+ {
+ dist = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+ }
+ }
+ }
+ }
+ script->m_main->FreeSpace(center, rMin, rMax, dist, pThis);
+
+ if ( result != 0 )
+ {
+ pSub = result->GivItemList();
+ if ( pSub != 0 )
+ {
+ pSub->SetValFloat(center.x/UNIT);
+ pSub = pSub->GivNext(); // "y"
+ pSub->SetValFloat(center.z/UNIT);
+ pSub = pSub->GivNext(); // "z"
+ pSub->SetValFloat(center.y/UNIT);
+ }
+ }
+ return TRUE;
+}
diff --git a/src/script/script.cpp b/src/script/script.cpp
new file mode 100644
index 0000000..62b2d25
--- /dev/null
+++ b/src/script/script.cpp
@@ -0,0 +1,3777 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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://www.gnu.org/licenses/.
+
+// script.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "CBot/CBotDll.h"
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "global.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "restext.h"
+#include "math3d.h"
+#include "robotmain.h"
+#include "terrain.h"
+#include "water.h"
+#include "object.h"
+#include "physics.h"
+#include "interface.h"
+#include "edit.h"
+#include "list.h"
+#include "text.h"
+#include "displaytext.h"
+#include "taskmanager.h"
+#include "task.h"
+#include "taskmanip.h"
+#include "taskgoto.h"
+#include "taskshield.h"
+#include "cbottoken.h"
+#include "script.h"
+
+
+
+#define CBOT_IPF 100 // CBOT: number of instructions / frame
+
+#define ERM_CONT 0 // if error -> continue
+#define ERM_STOP 1 // if error -> stop
+
+
+
+
+// Compiling a procedure without any parameters.
+
+CBotTypResult cNull(CBotVar* &var, void* user)
+{
+ if ( var != 0 ) return CBotErrOverParam;
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Compiling a procedure with a single real number.
+
+CBotTypResult cOneFloat(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Compiling a procedure with two real numbers.
+
+CBotTypResult cTwoFloat(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Compiling a procedure with a "dot".
+
+CBotTypResult cPoint(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+
+ if ( var->GivType() <= CBotTypDouble )
+ {
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+//? if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+//? if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+//? var = var->GivNext();
+ return CBotTypResult(0);
+ }
+
+ if ( var->GivType() == CBotTypClass )
+ {
+ if ( !var->IsElemOfClass("point") ) return CBotTypResult(CBotErrBadParam);
+ var = var->GivNext();
+ return CBotTypResult(0);
+ }
+
+ return CBotTypResult(CBotErrBadParam);
+}
+
+// Compiling a procedure with a single "point".
+
+CBotTypResult cOnePoint(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Compiling a procedure with a single string.
+
+CBotTypResult cString(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString &&
+ var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+
+// Seeking value in an array of integers.
+
+BOOL FindList(CBotVar* array, int type)
+{
+ while ( array != 0 )
+ {
+ if ( type == array->GivValInt() ) return TRUE;
+ array = array->GivNext();
+ }
+ return FALSE;
+}
+
+
+// Gives a parameter of type "point".
+
+BOOL GetPoint(CBotVar* &var, int& exception, D3DVECTOR& pos)
+{
+ CBotVar *pX, *pY, *pZ;
+
+ if ( var->GivType() <= CBotTypDouble )
+ {
+ pos.x = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+
+ pos.z = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+
+ pos.y = 0.0f;
+ }
+ else
+ {
+ pX = var->GivItem("x");
+ if ( pX == NULL )
+ {
+ exception = CBotErrUndefItem; return TRUE;
+ }
+ pos.x = pX->GivValFloat()*g_unit;
+
+ pY = var->GivItem("y");
+ if ( pY == NULL )
+ {
+ exception = CBotErrUndefItem; return TRUE;
+ }
+ pos.z = pY->GivValFloat()*g_unit; // attention y -> z !
+
+ pZ = var->GivItem("z");
+ if ( pZ == NULL )
+ {
+ exception = CBotErrUndefItem; return TRUE;
+ }
+ pos.y = pZ->GivValFloat()*g_unit; // attention z -> y !
+
+ var = var->GivNext();
+ }
+ return TRUE;
+}
+
+
+// Instruction "sin(degrees)".
+
+BOOL rSin(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(sinf(value*PI/180.0f));
+ return TRUE;
+}
+
+// Instruction "cos(degrees)".
+
+BOOL rCos(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(cosf(value*PI/180.0f));
+ return TRUE;
+}
+
+// Instruction "tan(degrees)".
+
+BOOL rTan(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(tanf(value*PI/180.0f));
+ return TRUE;
+}
+
+// Instruction "asin(degrees)".
+
+BOOL raSin(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(asinf(value)*180.0f/PI);
+ return TRUE;
+}
+
+// Instruction "acos(degrees)".
+
+BOOL raCos(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(acosf(value)*180.0f/PI);
+ return TRUE;
+}
+
+// Instruction "atan(degrees)".
+
+BOOL raTan(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(atanf(value)*180.0f/PI);
+ return TRUE;
+}
+
+// Instruction "sqrt(value)".
+
+BOOL rSqrt(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(sqrtf(value));
+ return TRUE;
+}
+
+// Instruction "pow(x, y)".
+
+BOOL rPow(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float x, y;
+
+ x = var->GivValFloat();
+ var = var->GivNext();
+ y = var->GivValFloat();
+ result->SetValFloat(powf(x, y));
+ return TRUE;
+}
+
+// Instruction "rand()".
+
+BOOL rRand(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ result->SetValFloat(Rand());
+ return TRUE;
+}
+
+// Instruction "abs()".
+
+BOOL rAbs(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(Abs(value));
+ return TRUE;
+}
+
+
+// Compilation of the instruction "retobject(rank)".
+
+CBotTypResult cRetObject(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypPointer, "object");
+}
+
+// Instruction "retobject(rank)".
+
+BOOL rRetObject(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pObj;
+ int rank;
+
+ rank = var->GivValInt();
+
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, rank);
+ if ( pObj == 0 )
+ {
+ result->SetPointer(0);
+ }
+ else
+ {
+ result->SetPointer(pObj->RetBotVar());
+ }
+ return TRUE;
+}
+
+
+// Compilation of the instruction "search(type, pos)".
+
+CBotTypResult cSearch(CBotVar* &var, void* user)
+{
+ CBotVar* array;
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ if ( array == 0 ) return CBotTypResult(CBotTypPointer);
+ if ( array->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ }
+ else if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ }
+
+ return CBotTypResult(CBotTypPointer, "object");
+}
+
+// Instruction "search(type, pos)".
+
+BOOL rSearch(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject *pObj, *pBest;
+ CBotVar* array;
+ D3DVECTOR pos, oPos;
+ BOOL bNearest = FALSE;
+ BOOL bArray;
+ float min, dist;
+ int type, oType, i;
+
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ bArray = TRUE;
+ }
+ else
+ {
+ type = var->GivValInt();
+ bArray = FALSE;
+ }
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ if ( !GetPoint(var, exception, pos) ) return TRUE;
+ bNearest = TRUE;
+ }
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( !pObj->RetActif() ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( oType == OBJECT_RUINmobilew2 ||
+ oType == OBJECT_RUINmobilet1 ||
+ oType == OBJECT_RUINmobilet2 ||
+ oType == OBJECT_RUINmobiler1 ||
+ oType == OBJECT_RUINmobiler2 )
+ {
+ oType = OBJECT_RUINmobilew1; // any ruin
+ }
+
+ if ( oType == OBJECT_SCRAP2 ||
+ oType == OBJECT_SCRAP3 ||
+ oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // wastes?
+ {
+ oType = OBJECT_SCRAP1; // any waste
+ }
+
+ if ( oType == OBJECT_BARRIER2 ||
+ oType == OBJECT_BARRIER3 ) // barriers?
+ {
+ oType = OBJECT_BARRIER1; // any barrier
+ }
+
+ if ( bArray )
+ {
+ if ( !FindList(array, oType) ) continue;
+ }
+ else
+ {
+ if ( type != oType && type != OBJECT_NULL ) continue;
+ }
+
+ if ( bNearest )
+ {
+ oPos = pObj->RetPosition(0);
+ dist = Length2d(pos, oPos);
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ else
+ {
+ pBest = pObj;
+ break;
+ }
+ }
+
+ if ( pBest == 0 )
+ {
+ result->SetPointer(0);
+ }
+ else
+ {
+ result->SetPointer(pBest->RetBotVar());
+ }
+ return TRUE;
+}
+
+
+// Compilation of instruction "radar(type, angle, focus, min, max, sens)".
+
+CBotTypResult cRadar(CBotVar* &var, void* user)
+{
+ CBotVar* array;
+
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ if ( array == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( array->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
+ }
+ else if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // angle
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // focus
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ return CBotTypResult(CBotErrOverParam);
+}
+
+// Instruction "radar(type, angle, focus, min, max, sens, filter)".
+
+BOOL rRadar(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CObject *pObj, *pBest;
+ CPhysics* physics;
+ CBotVar* array;
+ D3DVECTOR iPos, oPos;
+ RadarFilter filter;
+ float best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
+ int type, oType, i;
+ BOOL bArray;
+
+ type = OBJECT_NULL;
+ angle = 0.0f;
+ focus = PI*2.0f;
+ minDist = 0.0f*g_unit;
+ maxDist = 1000.0f*g_unit;
+ sens = 1.0f;
+ filter = FILTER_NONE;
+
+ if ( var != 0 )
+ {
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ bArray = TRUE;
+ }
+ else
+ {
+ type = var->GivValInt();
+ bArray = FALSE;
+ }
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ angle = -var->GivValFloat()*PI/180.0f;
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ focus = var->GivValFloat()*PI/180.0f;
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ minDist = var->GivValFloat()*g_unit;
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ maxDist = var->GivValFloat()*g_unit;
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ sens = var->GivValFloat();
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ filter = (RadarFilter)var->GivValInt();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ iPos = pThis->RetPosition(0);
+ iAngle = pThis->RetAngleY(0)+angle;
+ iAngle = NormAngle(iAngle); // 0..2*PI
+
+ if ( sens >= 0.0f ) best = 100000.0f;
+ else best = 0.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj == pThis ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( oType == OBJECT_RUINmobilew2 ||
+ oType == OBJECT_RUINmobilet1 ||
+ oType == OBJECT_RUINmobilet2 ||
+ oType == OBJECT_RUINmobiler1 ||
+ oType == OBJECT_RUINmobiler2 )
+ {
+ oType = OBJECT_RUINmobilew1; // any ruin
+ }
+
+ if ( oType == OBJECT_SCRAP2 ||
+ oType == OBJECT_SCRAP3 ||
+ oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // wastes?
+ {
+ oType = OBJECT_SCRAP1; // any waste
+ }
+
+ if ( oType == OBJECT_BARRIER2 ||
+ oType == OBJECT_BARRIER3 ) // barriers?
+ {
+ oType = OBJECT_BARRIER1; // any barrier
+ }
+
+ if ( filter == FILTER_ONLYLANDING )
+ {
+ physics = pObj->RetPhysics();
+ if ( physics != 0 && !physics->RetLand() ) continue;
+ }
+ if ( filter == FILTER_ONLYFLYING )
+ {
+ physics = pObj->RetPhysics();
+ if ( physics != 0 && physics->RetLand() ) continue;
+ }
+
+ if ( bArray )
+ {
+ if ( !FindList(array, oType) ) continue;
+ }
+ else
+ {
+ if ( type != oType && type != OBJECT_NULL ) continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+ d = Length2d(iPos, oPos);
+ if ( d < minDist || d > maxDist ) continue; // too close or too far?
+
+ if ( focus >= PI*2.0f )
+ {
+ if ( (sens >= 0.0f && d < best) ||
+ (sens < 0.0f && d > best) )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ continue;
+ }
+
+ a = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) )
+ {
+ if ( (sens >= 0.0f && d < best) ||
+ (sens < 0.0f && d > best) )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ }
+ }
+
+ if ( pBest == 0 )
+ {
+ result->SetPointer(0);
+ }
+ else
+ {
+ result->SetPointer(pBest->RetBotVar());
+ }
+ return TRUE;
+}
+
+
+// Monitoring a task.
+
+BOOL Process(CScript* script, CBotVar* result, int &exception)
+{
+ Error err;
+
+ err = script->m_primaryTask->IsEnded();
+ if ( err != ERR_CONTINUE ) // task terminated?
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+
+ script->m_bContinue = FALSE;
+
+ if ( err == ERR_STOP ) err = ERR_OK;
+ result->SetValInt(err); // indicates the error or ok
+ if ( err != ERR_OK && script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE; // it's all over
+ }
+
+ script->m_primaryTask->EventProcess(script->m_event);
+ script->m_bContinue = TRUE;
+ return FALSE; // not done
+}
+
+
+// Compilation of the instruction "detect(type)".
+
+CBotTypResult cDetect(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypBoolean);
+}
+
+// Instruction "detect(type)".
+
+BOOL rDetect(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CObject *pObj, *pGoal, *pBest;
+ CPhysics* physics;
+ CBotVar* array;
+ D3DVECTOR iPos, oPos;
+ RadarFilter filter;
+ float bGoal, best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
+ int type, oType, i;
+ BOOL bArray;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ type = OBJECT_NULL;
+ angle = 0.0f;
+ focus = 45.0f*PI/180.0f;
+ minDist = 0.0f*g_unit;
+ maxDist = 20.0f*g_unit;
+ sens = 1.0f;
+ filter = FILTER_NONE;
+
+ if ( var != 0 )
+ {
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ bArray = TRUE;
+ }
+ else
+ {
+ type = var->GivValInt();
+ bArray = FALSE;
+ }
+ }
+
+ iPos = pThis->RetPosition(0);
+ iAngle = pThis->RetAngleY(0)+angle;
+ iAngle = NormAngle(iAngle); // 0..2*PI
+
+ bGoal = 100000.0f;
+ pGoal = 0;
+ if ( sens >= 0.0f ) best = 100000.0f;
+ else best = 0.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj == pThis ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( oType == OBJECT_RUINmobilew2 ||
+ oType == OBJECT_RUINmobilet1 ||
+ oType == OBJECT_RUINmobilet2 ||
+ oType == OBJECT_RUINmobiler1 ||
+ oType == OBJECT_RUINmobiler2 )
+ {
+ oType = OBJECT_RUINmobilew1; // any ruin
+ }
+
+ if ( oType == OBJECT_SCRAP2 ||
+ oType == OBJECT_SCRAP3 ||
+ oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // wastes?
+ {
+ oType = OBJECT_SCRAP1; // any waste
+ }
+
+ if ( oType == OBJECT_BARRIER2 ||
+ oType == OBJECT_BARRIER3 ) // barriers?
+ {
+ oType = OBJECT_BARRIER1; // any barrier
+ }
+
+ if ( filter == FILTER_ONLYLANDING )
+ {
+ physics = pObj->RetPhysics();
+ if ( physics != 0 && !physics->RetLand() ) continue;
+ }
+ if ( filter == FILTER_ONLYFLYING )
+ {
+ physics = pObj->RetPhysics();
+ if ( physics != 0 && physics->RetLand() ) continue;
+ }
+
+ if ( bArray )
+ {
+ if ( !FindList(array, oType) ) continue;
+ }
+ else
+ {
+ if ( type != oType && type != OBJECT_NULL ) continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+ d = Length2d(iPos, oPos);
+ a = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+
+ if ( d < bGoal &&
+ TestAngle(a, iAngle-(5.0f*PI/180.0f)/2.0f, iAngle+(5.0f*PI/180.0f)/2.0f) )
+ {
+ bGoal = d;
+ pGoal = pObj;
+ }
+
+ if ( d < minDist || d > maxDist ) continue; // too close or too far?
+
+ if ( focus >= PI*2.0f )
+ {
+ if ( (sens >= 0.0f && d < best) ||
+ (sens < 0.0f && d > best) )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ continue;
+ }
+
+ if ( TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) )
+ {
+ if ( (sens >= 0.0f && d < best) ||
+ (sens < 0.0f && d > best) )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ }
+ }
+
+ pThis->StartDetectEffect(pGoal, pBest!=0);
+
+ if ( pBest == 0 )
+ {
+ script->m_returnValue = 0.0f;
+ }
+ else
+ {
+ script->m_returnValue = 1.0f;
+ }
+
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskWait(0.3f);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ if ( !Process(script, result, exception) ) return FALSE; // not finished
+ result->SetValFloat(script->m_returnValue);
+ return TRUE;
+}
+
+
+// Compilation of the instruction "direction(pos)".
+
+CBotTypResult cDirection(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "direction(pos)".
+
+BOOL rDirection(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ D3DVECTOR iPos, oPos;
+ float a, g;
+
+ if ( !GetPoint(var, exception, oPos) ) return TRUE;
+
+ iPos = pThis->RetPosition(0);
+
+ a = pThis->RetAngleY(0);
+ g = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+
+ result->SetValFloat(-Direction(a, g)*180.0f/PI);
+ return TRUE;
+}
+
+
+// Compilation of the instruction "produce(pos, angle, type, scriptName)".
+
+CBotTypResult cProduce(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "produce(pos, angle, type, scriptName)".
+
+BOOL rProduce(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* object;
+ CBotString cbs;
+ const char* name;
+ D3DVECTOR pos;
+ float angle;
+ ObjectType type;
+
+ if ( !GetPoint(var, exception, pos) ) return TRUE;
+
+ angle = var->GivValFloat()*PI/180.0f;
+ var = var->GivNext();
+
+ type = (ObjectType)var->GivValInt();
+ var = var->GivNext();
+
+ cbs = var->GivValString();
+ name = cbs;
+
+ if ( type == OBJECT_FRET ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_TNT ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ||
+ type == OBJECT_BOMB ||
+ type == OBJECT_WAYPOINT ||
+ type == OBJECT_SHOW ||
+ type == OBJECT_WINFIRE )
+ {
+ object = new CObject(script->m_iMan);
+ if ( !object->CreateResource(pos, angle, type) )
+ {
+ delete object;
+ result->SetValInt(1); // error
+ return TRUE;
+ }
+ }
+ else
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM )
+ {
+ CObject* egg;
+
+ object = new CObject(script->m_iMan);
+ if ( !object->CreateInsect(pos, angle, type) )
+ {
+ delete object;
+ result->SetValInt(1); // error
+ return TRUE;
+ }
+
+ egg = new CObject(script->m_iMan);
+ if ( !egg->CreateResource(pos, angle, OBJECT_EGG, 0.0f) )
+ {
+ delete egg;
+ }
+ }
+ else
+ {
+ result->SetValInt(1); // impossible
+ return TRUE;
+ }
+ object->SetActivity(FALSE);
+ object->ReadProgram(0, (char*)name);
+ object->RunProgram(0);
+
+ result->SetValInt(0); // no error
+ return TRUE;
+}
+
+
+// Compilation of the instruction "distance(p1, p2)".
+
+CBotTypResult cDistance(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "distance(p1, p2)".
+
+BOOL rDistance(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ D3DVECTOR p1, p2;
+ float value;
+
+ if ( !GetPoint(var, exception, p1) ) return TRUE;
+ if ( !GetPoint(var, exception, p2) ) return TRUE;
+
+ value = Length(p1, p2);
+ result->SetValFloat(value/g_unit);
+ return TRUE;
+}
+
+// Instruction "distance2d(p1, p2)".
+
+BOOL rDistance2d(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ D3DVECTOR p1, p2;
+ float value;
+
+ if ( !GetPoint(var, exception, p1) ) return TRUE;
+ if ( !GetPoint(var, exception, p2) ) return TRUE;
+
+ value = Length2d(p1, p2);
+ result->SetValFloat(value/g_unit);
+ return TRUE;
+}
+
+
+// Compilation of the instruction "space(center, rMin, rMax, dist)".
+
+CBotTypResult cSpace(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypIntrinsic, "point");
+}
+
+// Instruction "space(center, rMin, rMax, dist)".
+
+BOOL rSpace(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CBotVar* pSub;
+ D3DVECTOR center;
+ float rMin, rMax, dist;
+
+ rMin = 10.0f*g_unit;
+ rMax = 50.0f*g_unit;
+ dist = 4.0f*g_unit;
+
+ if ( var == 0 )
+ {
+ center = pThis->RetPosition(0);
+ }
+ else
+ {
+ if ( !GetPoint(var, exception, center) ) return TRUE;
+
+ if ( var != 0 )
+ {
+ rMin = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+
+ if ( var != 0 )
+ {
+ rMax = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+
+ if ( var != 0 )
+ {
+ dist = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+ }
+ }
+ }
+ }
+ script->m_main->FreeSpace(center, rMin, rMax, dist, pThis);
+
+ if ( result != 0 )
+ {
+ pSub = result->GivItemList();
+ if ( pSub != 0 )
+ {
+ pSub->SetValFloat(center.x/g_unit);
+ pSub = pSub->GivNext(); // "y"
+ pSub->SetValFloat(center.z/g_unit);
+ pSub = pSub->GivNext(); // "z"
+ pSub->SetValFloat(center.y/g_unit);
+ }
+ }
+ return TRUE;
+}
+
+
+// Compilation of the instruction "flatground(center, rMax)".
+
+CBotTypResult cFlatGround(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "flatground(center, rMax)".
+
+BOOL rFlatGround(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ D3DVECTOR center;
+ float rMax, dist;
+
+ if ( !GetPoint(var, exception, center) ) return TRUE;
+ rMax = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+
+ dist = script->m_main->RetFlatZoneRadius(center, rMax, pThis);
+ result->SetValFloat(dist/g_unit);
+
+ return TRUE;
+}
+
+
+// Instruction "wait(t)".
+
+BOOL rWait(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ value = var->GivValFloat();
+ err = script->m_primaryTask->StartTaskWait(value);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "move(dist)".
+
+BOOL rMove(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ value = var->GivValFloat();
+ err = script->m_primaryTask->StartTaskAdvance(value*g_unit);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "turn(angle)".
+
+BOOL rTurn(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ value = var->GivValFloat();
+ err = script->m_primaryTask->StartTaskTurn(-value*PI/180.0f);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Compilation of the instruction "goto(pos, altitude, crash, goal)".
+
+CBotTypResult cGoto(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ return CBotTypResult(CBotErrOverParam);
+}
+
+// Instruction "goto(pos, altitude, mode)".
+
+BOOL rGoto(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ D3DVECTOR pos;
+ TaskGotoGoal goal;
+ TaskGotoCrash crash;
+ float altitude;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ if ( !GetPoint(var, exception, pos) ) return TRUE;
+
+ goal = TGG_DEFAULT;
+ crash = TGC_DEFAULT;
+ altitude = 0.0f*g_unit;
+
+ if ( var != 0 )
+ {
+ altitude = var->GivValFloat()*g_unit;
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ goal = (TaskGotoGoal)var->GivValInt();
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ crash = (TaskGotoCrash)var->GivValInt();
+ }
+ }
+ }
+
+ err = script->m_primaryTask->StartTaskGoto(pos, altitude, goal, crash);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "find(type)".
+
+BOOL rFind(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ D3DVECTOR pos;
+ TaskGotoGoal goal;
+ TaskGotoCrash crash;
+ float altitude;
+ Error err;
+ CObject* pThis = (CObject*)user;
+ CObject *pObj, *pBest;
+ CBotVar* array;
+ D3DVECTOR iPos, oPos;
+ float best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
+ int type, oType, i;
+ BOOL bArray;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ type = OBJECT_NULL;
+ angle = 0.0f;
+ focus = PI*2.0f;
+ minDist = 0.0f*g_unit;
+ maxDist = 1000.0f*g_unit;
+ sens = 1.0f;
+
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ bArray = TRUE;
+ }
+ else
+ {
+ type = var->GivValInt();
+ bArray = FALSE;
+ }
+
+ best = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj == pThis ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( oType == OBJECT_RUINmobilew2 ||
+ oType == OBJECT_RUINmobilet1 ||
+ oType == OBJECT_RUINmobilet2 ||
+ oType == OBJECT_RUINmobiler1 ||
+ oType == OBJECT_RUINmobiler2 )
+ {
+ oType = OBJECT_RUINmobilew1; // any ruin
+ }
+
+ if ( oType == OBJECT_SCRAP2 ||
+ oType == OBJECT_SCRAP3 ||
+ oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // wastes?
+ {
+ oType = OBJECT_SCRAP1; // any waste
+ }
+
+ if ( oType == OBJECT_BARRIER2 ||
+ oType == OBJECT_BARRIER3 ) // barriers?
+ {
+ oType = OBJECT_BARRIER1; // any barrier
+ }
+
+ if ( bArray )
+ {
+ if ( !FindList(array, oType) ) continue;
+ }
+ else
+ {
+ if ( type != oType && type != OBJECT_NULL ) continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+ d = Length2d(iPos, oPos);
+ if ( d < minDist || d > maxDist ) continue; // too close or too far?
+
+ if ( focus >= PI*2.0f )
+ {
+ if ( d < best )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ continue;
+ }
+
+ a = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) )
+ {
+ if ( d < best )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ }
+ }
+
+ if ( pBest == 0 )
+ {
+ exception = ERR_FIND_IMPOSSIBLE;
+ return FALSE;
+ }
+
+ pos = pBest->RetPosition(0);
+ goal = TGG_DEFAULT;
+ crash = TGC_DEFAULT;
+ altitude = 0.0f*g_unit;
+
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskGoto(pos, altitude, goal, crash);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Compilation "grab/drop(oper)".
+
+CBotTypResult cGrabDrop(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "grab(oper)".
+
+BOOL rGrab(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ ObjectType oType;
+ TaskManipArm type;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ if ( var == 0 ) type = TMA_FFRONT;
+ else type = (TaskManipArm)var->GivValInt();
+
+ oType = pThis->RetType();
+ if ( oType == OBJECT_HUMAN ||
+ oType == OBJECT_TECH )
+ {
+ err = script->m_primaryTask->StartTaskTake();
+ }
+ else
+ {
+ err = script->m_primaryTask->StartTaskManip(TMO_GRAB, type);
+ }
+
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "drop(oper)".
+
+BOOL rDrop(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ ObjectType oType;
+ TaskManipArm type;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ if ( var == 0 ) type = TMA_FFRONT;
+ else type = (TaskManipArm)var->GivValInt();
+
+ oType = pThis->RetType();
+ if ( oType == OBJECT_HUMAN ||
+ oType == OBJECT_TECH )
+ {
+ err = script->m_primaryTask->StartTaskTake();
+ }
+ else
+ {
+ err = script->m_primaryTask->StartTaskManip(TMO_DROP, type);
+ }
+
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "sniff()".
+
+BOOL rSniff(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskSearch();
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Compilation of the instruction "receive(nom, power)".
+
+CBotTypResult cReceive(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "receive(nom, power)".
+
+BOOL rReceive(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CBotString cbs;
+ Error err;
+ const char* p;
+ float value, power;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+
+ cbs = var->GivValString();
+ p = cbs;
+ var = var->GivNext();
+
+ power = 10.0f*g_unit;
+ if ( var != 0 )
+ {
+ power = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+ }
+
+ err = script->m_primaryTask->StartTaskInfo((char*)p, 0.0f, power, FALSE);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetInit(IS_NAN);
+ return TRUE;
+ }
+ }
+ if ( !Process(script, result, exception) ) return FALSE; // not finished
+
+ value = pThis->RetInfoReturn();
+ if ( value == NAN )
+ {
+ result->SetInit(IS_NAN);
+ }
+ else
+ {
+ result->SetValFloat(value);
+ }
+ return TRUE;
+}
+
+// Compilation of the instruction "send(nom, value, power)".
+
+CBotTypResult cSend(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "send(nom, value, power)".
+
+BOOL rSend(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CBotString cbs;
+ Error err;
+ const char* p;
+ float value, power;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+
+ cbs = var->GivValString();
+ p = cbs;
+ var = var->GivNext();
+
+ value = var->GivValFloat();
+ var = var->GivNext();
+
+ power = 10.0f*g_unit;
+ if ( var != 0 )
+ {
+ power = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+ }
+
+ err = script->m_primaryTask->StartTaskInfo((char*)p, value, power, TRUE);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Seeks the nearest information terminal.
+
+CObject* SearchInfo(CScript* script, CObject* object, float power)
+{
+ CObject *pObj, *pBest;
+ D3DVECTOR iPos, oPos;
+ ObjectType type;
+ float dist, min;
+ int i;
+
+ iPos = object->RetPosition(0);
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_INFO ) continue;
+
+ if ( !pObj->RetActif() ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Length(oPos, iPos);
+ if ( dist > power ) continue; // too far?
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+
+ return pBest;
+}
+
+// Compilation of the instruction "deleteinfo(nom, power)".
+
+CBotTypResult cDeleteInfo(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "deleteinfo(nom, power)".
+
+BOOL rDeleteInfo(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CObject* pInfo;
+ CBotString cbs;
+ Info info;
+ const char* p;
+ float power;
+ int i, total;
+
+ exception = 0;
+
+ cbs = var->GivValString();
+ p = cbs;
+ var = var->GivNext();
+
+ power = 10.0f*g_unit;
+ if ( var != 0 )
+ {
+ power = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+ }
+
+ pInfo = SearchInfo(script, pThis, power);
+ if ( pInfo == 0 )
+ {
+ result->SetValFloat(0.0f); // false
+ return TRUE;
+ }
+
+ total = pInfo->RetInfoTotal();
+ for ( i=0 ; i<total ; i++ )
+ {
+ info = pInfo->RetInfo(i);
+ if ( strcmp(info.name, p) == 0 )
+ {
+ pInfo->DeleteInfo(i);
+ result->SetValFloat(1.0f); // true
+ return TRUE;
+ }
+ }
+ result->SetValFloat(0.0f); // false
+ return TRUE;
+}
+
+// Compilation of the instruction "testinfo(nom, power)".
+
+CBotTypResult cTestInfo(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypBoolean);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypBoolean);
+}
+
+// Instruction "testinfo(nom, power)".
+
+BOOL rTestInfo(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CObject* pInfo;
+ CBotString cbs;
+ Info info;
+ const char* p;
+ float power;
+ int i, total;
+
+ exception = 0;
+
+ cbs = var->GivValString();
+ p = cbs;
+ var = var->GivNext();
+
+ power = 10.0f*g_unit;
+ if ( var != 0 )
+ {
+ power = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+ }
+
+ pInfo = SearchInfo(script, pThis, power);
+ if ( pInfo == 0 )
+ {
+ result->SetValInt(FALSE);
+ return TRUE;
+ }
+
+ total = pInfo->RetInfoTotal();
+ for ( i=0 ; i<total ; i++ )
+ {
+ info = pInfo->RetInfo(i);
+ if ( strcmp(info.name, p) == 0 )
+ {
+ result->SetValInt(TRUE);
+ return TRUE;
+ }
+ }
+ result->SetValInt(FALSE);
+ return TRUE;
+}
+
+// Instruction "thump()".
+
+BOOL rThump(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskTerraform();
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "recycle()".
+
+BOOL rRecycle(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskRecover();
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Compilation "shield(oper, radius)".
+
+CBotTypResult cShield(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "shield(oper, radius)".
+
+BOOL rShield(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ float oper, radius;
+ Error err;
+
+ oper = var->GivValFloat(); // 0=down, 1=up
+ var = var->GivNext();
+
+ radius = var->GivValFloat();
+ if ( radius < 10.0f ) radius = 10.0f;
+ if ( radius > 25.0f ) radius = 25.0f;
+ radius = (radius-10.0f)/15.0f;
+
+ if ( *script->m_secondaryTask == 0 ) // shield folds?
+ {
+ if ( oper == 0.0f ) // down?
+ {
+ result->SetValInt(1); // shows the error
+ }
+ else // up ?
+ {
+ pThis->SetParam(radius);
+
+ *script->m_secondaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = (*script->m_secondaryTask)->StartTaskShield(TSM_UP, 1000.0f);
+ if ( err != ERR_OK )
+ {
+ delete *script->m_secondaryTask;
+ *script->m_secondaryTask = 0;
+ result->SetValInt(err); // shows the error
+ }
+ }
+ }
+ else // shield deployed?
+ {
+ if ( oper == 0.0f ) // down?
+ {
+ (*script->m_secondaryTask)->StartTaskShield(TSM_DOWN, 0.0f);
+ }
+ else // up?
+ {
+//? result->SetValInt(1); // shows the error
+ pThis->SetParam(radius);
+ (*script->m_secondaryTask)->StartTaskShield(TSM_UPDATE, 0.0f);
+ }
+ }
+
+ return TRUE;
+}
+
+// Compilation "fire(delay)".
+
+CBotTypResult cFire(CBotVar* &var, void* user)
+{
+#if 0
+ CObject* pThis = (CObject*)user;
+ ObjectType type;
+
+ type = pThis->RetType();
+
+ if ( type == OBJECT_ANT )
+ {
+ return cOnePoint(var, user);
+ }
+ else if ( type == OBJECT_SPIDER )
+ {
+ return cNull(var, user);
+ }
+ else
+ {
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+ }
+#else
+ return CBotTypResult(CBotTypFloat);
+#endif
+}
+
+// Instruction "fire(delay)".
+
+BOOL rFire(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ float delay;
+ D3DVECTOR impact;
+ Error err;
+ ObjectType type;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+
+ type = pThis->RetType();
+
+ if ( type == OBJECT_ANT )
+ {
+ if ( !GetPoint(var, exception, impact) ) return TRUE;
+ impact.y += pThis->RetWaterLevel();
+ err = script->m_primaryTask->StartTaskFireAnt(impact);
+ }
+ else if ( type == OBJECT_SPIDER )
+ {
+ err = script->m_primaryTask->StartTaskSpiderExplo();
+ }
+ else
+ {
+ if ( var == 0 ) delay = 0.0f;
+ else delay = var->GivValFloat();
+ err = script->m_primaryTask->StartTaskFire(delay);
+ }
+
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "aim(dir)".
+
+BOOL rAim(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ value = var->GivValFloat();
+ err = script->m_primaryTask->StartTaskGunGoal(value*PI/180.0f, 0.0f);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Compilation of the instruction "motor(left, right)".
+
+CBotTypResult cMotor(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "motor(left, right)".
+
+BOOL rMotor(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CObject* pThis = (CObject*)user;
+ CPhysics* physics = ((CObject*)user)->RetPhysics();
+ float left, right, speed, turn;
+
+ left = var->GivValFloat();
+ var = var->GivNext();
+ right = var->GivValFloat();
+
+ speed = (left+right)/2.0f;
+ if ( speed < -1.0f ) speed = -1.0f;
+ if ( speed > 1.0f ) speed = 1.0f;
+
+ turn = left-right;
+ if ( turn < -1.0f ) turn = -1.0f;
+ if ( turn > 1.0f ) turn = 1.0f;
+
+ if ( pThis->RetFixed() ) // ant on the back?
+ {
+ speed = 0.0f;
+ turn = 0.0f;
+ }
+
+ physics->SetMotorSpeedX(speed); // forward/backward
+ physics->SetMotorSpeedZ(turn); // turns
+
+ return TRUE;
+}
+
+// Instruction "jet(power)".
+
+BOOL rJet(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CPhysics* physics = ((CObject*)user)->RetPhysics();
+ float value;
+
+ value = var->GivValFloat();
+ physics->SetMotorSpeedY(value);
+
+ return TRUE;
+}
+
+// Compilation of the instruction "topo(pos)".
+
+CBotTypResult cTopo(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ return CBotTypResult(CBotErrOverParam);
+}
+
+// Instruction "topo(pos)".
+
+BOOL rTopo(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ D3DVECTOR pos;
+ float level;
+
+ exception = 0;
+
+ if ( !GetPoint(var, exception, pos) ) return TRUE;
+
+ level = script->m_terrain->RetFloorLevel(pos);
+ level -= script->m_water->RetLevel();
+ result->SetValFloat(level/g_unit);
+ return TRUE;
+}
+
+// Compilation of the instruction "message(string, type)".
+
+CBotTypResult cMessage(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString &&
+ var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ return CBotTypResult(CBotErrOverParam);
+}
+
+// Instruction "message(string, type)".
+
+BOOL rMessage(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CBotString cbs;
+ const char* p;
+ TextType type;
+
+ cbs = var->GivValString();
+ p = cbs;
+
+ type = TT_MESSAGE;
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ type = (TextType)var->GivValInt();
+ }
+
+ script->m_displayText->DisplayText((char*)p, script->m_object, 10.0f, type);
+ script->m_main->CheckEndMessage((char*)p);
+
+ return TRUE;
+}
+
+// Instruction "cmdline(rank)".
+
+BOOL rCmdline(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ float value;
+ int rank;
+
+ rank = var->GivValInt();
+ value = pThis->RetCmdLine(rank);
+ result->SetValFloat(value);
+
+ return TRUE;
+}
+
+// Instruction "ismovie()".
+
+BOOL rIsMovie(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+
+ value = script->m_main->RetMovieLock()?1.0f:0.0f;
+ result->SetValFloat(value);
+
+ return TRUE;
+}
+
+// Instruction "errmode(mode)".
+
+BOOL rErrMode(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ int value;
+
+ value = var->GivValInt();
+ if ( value < 0 ) value = 0;
+ if ( value > 1 ) value = 1;
+ script->m_errMode = value;
+
+ return TRUE;
+}
+
+// Instruction "ipf(num)".
+
+BOOL rIPF(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ int value;
+
+ value = var->GivValInt();
+ if ( value < 1 ) value = 1;
+ if ( value > 10000 ) value = 10000;
+ script->m_ipf = value;
+
+ return TRUE;
+}
+
+// Instruction "abstime()".
+
+BOOL rAbsTime(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+
+ value = script->m_main->RetGameTime();
+ result->SetValFloat(value);
+ return TRUE;
+}
+
+
+// Prepares a file name.
+
+void PrepareFilename(CBotString &filename, char *dir)
+{
+ int pos;
+
+ pos = filename.ReverseFind('\\');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // removes folders
+ }
+
+ pos = filename.ReverseFind('/');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // also those with /
+ }
+
+ pos = filename.ReverseFind(':');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // also removes the drive letter C:
+ }
+
+ filename = CBotString(dir) + CBotString("\\") + filename;
+}
+
+// Instruction "deletefile(filename)".
+
+BOOL rDeleteFile(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CBotString cbs;
+ const char* p;
+ char* dir;
+
+ cbs = var->GivValString();
+ dir = script->m_main->RetFilesDir();
+ PrepareFilename(cbs, dir);
+ p = cbs;
+ DeleteFile(p);
+
+ return TRUE;
+}
+
+// Compilation of the instruction "pendown(color, width)".
+
+CBotTypResult cPenDown(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ return CBotTypResult(CBotErrOverParam);
+}
+
+// Instruction "pendown(color, width)".
+
+BOOL rPenDown(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ int color;
+ float width;
+ Error err;
+
+ if ( pThis->RetType() == OBJECT_MOBILEdr )
+ {
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ if ( var != 0 )
+ {
+ color = var->GivValInt();
+ if ( color < 0 ) color = 0;
+ if ( color > 17 ) color = 17;
+ pThis->SetTraceColor(color);
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ width = var->GivValFloat();
+ if ( width < 0.1f ) width = 0.1f;
+ if ( width > 1.0f ) width = 1.0f;
+ pThis->SetTraceWidth(width);
+ }
+ }
+ pThis->SetTraceDown(TRUE);
+
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor());
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+ }
+ else
+ {
+ if ( var != 0 )
+ {
+ color = var->GivValInt();
+ if ( color < 0 ) color = 0;
+ if ( color > 17 ) color = 17;
+ pThis->SetTraceColor(color);
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ width = var->GivValFloat();
+ if ( width < 0.1f ) width = 0.1f;
+ if ( width > 1.0f ) width = 1.0f;
+ pThis->SetTraceWidth(width);
+ }
+ }
+ pThis->SetTraceDown(TRUE);
+
+ return TRUE;
+ }
+}
+
+// Instruction "penup()".
+
+BOOL rPenUp(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ Error err;
+
+ if ( pThis->RetType() == OBJECT_MOBILEdr )
+ {
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ pThis->SetTraceDown(FALSE);
+
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor());
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+ }
+ else
+ {
+ pThis->SetTraceDown(FALSE);
+ return TRUE;
+ }
+}
+
+// Instruction "pencolor()".
+
+BOOL rPenColor(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CPhysics* physics = ((CObject*)user)->RetPhysics();
+ CObject* pThis = (CObject*)user;
+ int color;
+ Error err;
+
+ if ( pThis->RetType() == OBJECT_MOBILEdr )
+ {
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ color = var->GivValInt();
+ if ( color < 0 ) color = 0;
+ if ( color > 17 ) color = 17;
+ pThis->SetTraceColor(color);
+
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor());
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ return Process(script, result, exception);
+ }
+ else
+ {
+ color = var->GivValInt();
+ if ( color < 0 ) color = 0;
+ if ( color > 17 ) color = 17;
+ pThis->SetTraceColor(color);
+
+ return TRUE;
+ }
+}
+
+// Instruction "penwidth()".
+
+BOOL rPenWidth(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CObject* pThis = (CObject*)user;
+ float width;
+
+ width = var->GivValFloat();
+ if ( width < 0.1f ) width = 0.1f;
+ if ( width > 1.0f ) width = 1.0f;
+ pThis->SetTraceWidth(width);
+ return TRUE;
+}
+
+
+
+// Object's constructor.
+
+CScript::CScript(CInstanceManager* iMan, CObject* object, CTaskManager** secondaryTask)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_SCRIPT, this, 100);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_botProg = 0;
+ m_object = object;
+ m_primaryTask = 0;
+ m_secondaryTask = secondaryTask;
+
+ m_ipf = CBOT_IPF;
+ m_errMode = ERM_STOP;
+ m_len = 0;
+ m_script = 0;
+ m_bRun = FALSE;
+ m_bStepMode = FALSE;
+ m_bCompile = FALSE;
+ m_title[0] = 0;
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ m_filename[0] = 0;
+}
+
+// Initializes all functions for module CBOT.
+
+void CScript::InitFonctions()
+{
+ CBotProgram::AddFunction("sin", rSin, cOneFloat);
+ CBotProgram::AddFunction("cos", rCos, cOneFloat);
+ CBotProgram::AddFunction("tan", rTan, cOneFloat);
+ CBotProgram::AddFunction("asin", raSin, cOneFloat);
+ CBotProgram::AddFunction("acos", raCos, cOneFloat);
+ CBotProgram::AddFunction("atan", raTan, cOneFloat);
+ CBotProgram::AddFunction("sqrt", rSqrt, cOneFloat);
+ CBotProgram::AddFunction("pow", rPow, cTwoFloat);
+ CBotProgram::AddFunction("rand", rRand, cNull);
+ CBotProgram::AddFunction("abs", rAbs, cOneFloat);
+
+ CBotProgram::AddFunction("retobject", rRetObject, cRetObject);
+ CBotProgram::AddFunction("search", rSearch, cSearch);
+ CBotProgram::AddFunction("radar", rRadar, cRadar);
+ CBotProgram::AddFunction("detect", rDetect, cDetect);
+ CBotProgram::AddFunction("direction", rDirection, cDirection);
+ CBotProgram::AddFunction("produce", rProduce, cProduce);
+ CBotProgram::AddFunction("distance", rDistance, cDistance);
+ CBotProgram::AddFunction("distance2d",rDistance2d,cDistance);
+ CBotProgram::AddFunction("space", rSpace, cSpace);
+ CBotProgram::AddFunction("flatground",rFlatGround,cFlatGround);
+ CBotProgram::AddFunction("wait", rWait, cOneFloat);
+ CBotProgram::AddFunction("move", rMove, cOneFloat);
+ CBotProgram::AddFunction("turn", rTurn, cOneFloat);
+ CBotProgram::AddFunction("goto", rGoto, cGoto);
+ CBotProgram::AddFunction("find", rFind, cOneFloat);
+ CBotProgram::AddFunction("grab", rGrab, cGrabDrop);
+ CBotProgram::AddFunction("drop", rDrop, cGrabDrop);
+ CBotProgram::AddFunction("sniff", rSniff, cNull);
+ CBotProgram::AddFunction("receive", rReceive, cReceive);
+ CBotProgram::AddFunction("send", rSend, cSend);
+ CBotProgram::AddFunction("deleteinfo",rDeleteInfo,cDeleteInfo);
+ CBotProgram::AddFunction("testinfo", rTestInfo, cTestInfo);
+ CBotProgram::AddFunction("thump", rThump, cNull);
+ CBotProgram::AddFunction("recycle", rRecycle, cNull);
+ CBotProgram::AddFunction("shield", rShield, cShield);
+ CBotProgram::AddFunction("fire", rFire, cFire);
+ CBotProgram::AddFunction("aim", rAim, cOneFloat);
+ CBotProgram::AddFunction("motor", rMotor, cMotor);
+ CBotProgram::AddFunction("jet", rJet, cOneFloat);
+ CBotProgram::AddFunction("topo", rTopo, cTopo);
+ CBotProgram::AddFunction("message", rMessage, cMessage);
+ CBotProgram::AddFunction("cmdline", rCmdline, cOneFloat);
+ CBotProgram::AddFunction("ismovie", rIsMovie, cNull);
+ CBotProgram::AddFunction("errmode", rErrMode, cOneFloat);
+ CBotProgram::AddFunction("ipf", rIPF, cOneFloat);
+ CBotProgram::AddFunction("abstime", rAbsTime, cNull);
+ CBotProgram::AddFunction("deletefile",rDeleteFile,cString);
+ CBotProgram::AddFunction("pendown", rPenDown, cPenDown);
+ CBotProgram::AddFunction("penup", rPenUp, cNull);
+ CBotProgram::AddFunction("pencolor", rPenColor, cOneFloat);
+ CBotProgram::AddFunction("penwidth", rPenWidth, cOneFloat);
+}
+
+// Object's destructor.
+
+CScript::~CScript()
+{
+ delete m_botProg;
+ delete m_primaryTask;
+ delete m_script;
+ m_script = 0;
+ m_len = 0;
+
+ m_iMan->DeleteInstance(CLASS_SCRIPT, this);
+}
+
+
+// Gives the script editable block of text.
+
+void CScript::PutScript(CEdit* edit, char* name)
+{
+ if ( m_script == 0 )
+ {
+ New(edit, name);
+ }
+ else
+ {
+ edit->SetText(m_script);
+ edit->SetCursor(m_cursor2, m_cursor1);
+ edit->ShowSelect();
+ }
+ edit->SetFocus(TRUE);
+}
+
+// The script takes a paved text.
+
+BOOL CScript::GetScript(CEdit* edit)
+{
+ int len;
+
+ delete m_script;
+ m_script = 0;
+
+ len = edit->RetTextLength();
+ m_script = (char*)malloc(sizeof(char)*(len+1));
+
+ edit->GetText(m_script, len+1);
+ edit->GetCursor(m_cursor2, m_cursor1);
+ m_len = strlen(m_script);
+
+ if ( !CheckToken() )
+ {
+ edit->SetCursor(m_cursor2, m_cursor1);
+ edit->ShowSelect();
+ edit->SetFocus(TRUE);
+ return FALSE;
+ }
+
+ if ( !Compile() )
+ {
+ edit->SetCursor(m_cursor2, m_cursor1);
+ edit->ShowSelect();
+ edit->SetFocus(TRUE);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// Indicates whether a program is compiled correctly.
+
+BOOL CScript::RetCompile()
+{
+ return m_bCompile;
+}
+
+// Indicates whether the program is empty.
+
+BOOL CScript::IsEmpty()
+{
+ int i;
+
+ for ( i=0 ; i<m_len ; i++ )
+ {
+ if ( m_script[i] != ' ' &&
+ m_script[i] != '\n' ) return FALSE;
+ }
+ return TRUE;
+}
+
+// Checks if a program does not contain the prohibited instructions
+// and if it contains well at least once every mandatory instructions.
+
+BOOL CScript::CheckToken()
+{
+ CBotToken* bt;
+ CBotString bs;
+ const char* token;
+ int error, type, cursor1, cursor2, i;
+ char used[100];
+
+ if ( !m_object->RetCheckToken() ) return TRUE;
+
+ m_error = 0;
+ m_title[0] = 0;
+ m_token[0] = 0;
+ m_bCompile = FALSE;
+
+ for ( i=0 ; i<m_main->RetObligatoryToken() ; i++ )
+ {
+ used[i] = 0; // token not used
+ }
+
+ bt = CBotToken::CompileTokens(m_script, error);
+ while ( bt != 0 )
+ {
+ bs = bt->GivString();
+ token = bs;
+ type = bt->GivType();
+
+ cursor1 = bt->GivStart();
+ cursor2 = bt->GivEnd();
+
+ i = m_main->IsObligatoryToken((char*)token);
+ if ( i != -1 )
+ {
+ used[i] = 1; // token used
+ }
+
+ if ( !m_main->IsProhibitedToken((char*)token) )
+ {
+ m_error = ERR_PROHIBITEDTOKEN;
+ m_cursor1 = cursor1;
+ m_cursor2 = cursor2;
+ strcpy(m_title, "<erreur>");
+ CBotToken::Delete(bt);
+ return FALSE;
+ }
+
+ bt = bt->GivNext();
+ }
+
+ // At least once every obligatory instruction?
+ for ( i=0 ; i<m_main->RetObligatoryToken() ; i++ )
+ {
+ if ( used[i] == 0 ) // token not used?
+ {
+ strcpy(m_token, m_main->RetObligatoryToken(i));
+ m_error = ERR_OBLIGATORYTOKEN;
+ strcpy(m_title, "<erreur>");
+ CBotToken::Delete(bt);
+ return FALSE;
+ }
+ }
+
+ CBotToken::Delete(bt);
+ return TRUE;
+}
+
+// Compile the script of a paved text.
+
+BOOL CScript::Compile()
+{
+ CBotStringArray liste;
+ int i;
+ const char* p;
+
+ m_error = 0;
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ m_title[0] = 0;
+ m_bCompile = FALSE;
+
+ if ( IsEmpty() ) // program exist?
+ {
+ delete m_botProg;
+ m_botProg = 0;
+ return TRUE;
+ }
+
+ if ( m_botProg == 0 )
+ {
+ m_botProg = new CBotProgram(m_object->RetBotVar());
+ }
+
+ if ( m_botProg->Compile(m_script, liste, this) )
+ {
+ if ( liste.GivSize() == 0 )
+ {
+ strcpy(m_title, "<sans nom>");
+ }
+ else
+ {
+ p = liste[0];
+ i = 0;
+ while ( TRUE )
+ {
+ if ( p[i] == 0 || p[i] == '(' ) break;
+ if ( i >= 20 )
+ {
+ m_title[i++] = '.';
+ m_title[i++] = '.';
+ m_title[i++] = '.';
+ break;
+ }
+ m_title[i] = p[i];
+ i ++;
+ }
+ m_title[i] = 0;
+ }
+ m_bCompile = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ m_botProg->GetError(m_error, m_cursor1, m_cursor2);
+ if ( m_cursor1 < 0 || m_cursor1 > m_len ||
+ m_cursor2 < 0 || m_cursor2 > m_len )
+ {
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ }
+ if ( m_error == 0 )
+ {
+ m_cursor1 = m_cursor2 = 0;
+ }
+ strcpy(m_title, "<erreur>");
+ return FALSE;
+ }
+}
+
+
+// Returns the title of the script.
+
+void CScript::GetTitle(char* buffer)
+{
+ strcpy(buffer, m_title);
+}
+
+
+// Choice of mode of execution.
+
+void CScript::SetStepMode(BOOL bStep)
+{
+ m_bStepMode = bStep;
+}
+
+
+// Runs the program from the beginning.
+
+BOOL CScript::Run()
+{
+ if( m_botProg == 0 ) return FALSE;
+ if ( m_script == 0 || m_len == 0 ) return FALSE;
+
+ if ( !m_botProg->Start(m_title) ) return FALSE;
+
+ m_object->SetRunScript(this);
+ m_bRun = TRUE;
+ m_bContinue = FALSE;
+ m_ipf = CBOT_IPF;
+ m_errMode = ERM_STOP;
+
+ if ( m_bStepMode ) // step by step mode?
+ {
+ Event newEvent;
+ ZeroMemory(&newEvent, sizeof(Event));
+ Step(newEvent);
+ }
+
+ return TRUE;
+}
+
+// Continues the execution of current program.
+// Returns TRUE when execution is finished.
+
+BOOL CScript::Continue(const Event &event)
+{
+ if( m_botProg == 0 ) return TRUE;
+ if ( !m_bRun ) return TRUE;
+
+ m_event = event;
+
+ if ( m_bStepMode ) // step by step mode?
+ {
+ if ( m_bContinue ) // instuction "move", "goto", etc. ?
+ {
+ if ( m_botProg->Run(m_object, 0) )
+ {
+ m_botProg->GetError(m_error, m_cursor1, m_cursor2);
+ if ( m_cursor1 < 0 || m_cursor1 > m_len ||
+ m_cursor2 < 0 || m_cursor2 > m_len )
+ {
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ }
+ if ( m_error == 0 )
+ {
+ m_cursor1 = m_cursor2 = 0;
+ }
+ m_bRun = FALSE;
+
+ if ( m_error != 0 && m_errMode == ERM_STOP )
+ {
+ char s[100];
+ GetError(s);
+ m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR);
+ }
+ m_engine->SetPause(TRUE); // gives pause
+ return TRUE;
+ }
+ if ( !m_bContinue )
+ {
+ m_engine->SetPause(TRUE); // gives pause
+ }
+ }
+
+ return FALSE;
+ }
+
+ if ( m_botProg->Run(m_object, m_ipf) )
+ {
+ m_botProg->GetError(m_error, m_cursor1, m_cursor2);
+ if ( m_cursor1 < 0 || m_cursor1 > m_len ||
+ m_cursor2 < 0 || m_cursor2 > m_len )
+ {
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ }
+ if ( m_error == 0 )
+ {
+ m_cursor1 = m_cursor2 = 0;
+ }
+ m_bRun = FALSE;
+
+ if ( m_error != 0 && m_errMode == ERM_STOP )
+ {
+ char s[100];
+ GetError(s);
+ m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR);
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// Continues the execution of current program.
+// Returns TRUE when execution is finished.
+
+BOOL CScript::Step(const Event &event)
+{
+ if( m_botProg == 0 ) return TRUE;
+ if ( !m_bRun ) return TRUE;
+ if ( !m_bStepMode ) return FALSE;
+
+ m_engine->SetPause(FALSE);
+ m_engine->StepSimul(0.01f); // advance of 10ms
+ m_engine->SetPause(TRUE);
+
+ m_event = event;
+
+ if ( m_botProg->Run(m_object, 0) ) // step mode
+ {
+ m_botProg->GetError(m_error, m_cursor1, m_cursor2);
+ if ( m_cursor1 < 0 || m_cursor1 > m_len ||
+ m_cursor2 < 0 || m_cursor2 > m_len )
+ {
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ }
+ if ( m_error == 0 )
+ {
+ m_cursor1 = m_cursor2 = 0;
+ }
+ m_bRun = FALSE;
+
+ if ( m_error != 0 && m_errMode == ERM_STOP )
+ {
+ char s[100];
+ GetError(s);
+ m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR);
+ }
+ return TRUE;
+ }
+
+ if ( m_bContinue ) // instuction "move", "goto", etc. ?
+ {
+ m_engine->SetPause(FALSE); // removes the pause
+ }
+ return FALSE;
+}
+
+// Stops the program.
+
+void CScript::Stop()
+{
+ if ( !m_bRun ) return;
+
+ if( m_botProg != 0 )
+ {
+ m_botProg->Stop();
+ }
+
+ if ( m_primaryTask != 0 )
+ {
+ m_primaryTask->Abort();
+ delete m_primaryTask;
+ m_primaryTask = 0;
+ }
+
+ m_bRun = FALSE;
+}
+
+// Indicates whether the program runs.
+
+BOOL CScript::IsRunning()
+{
+ return m_bRun;
+}
+
+// Indicates whether the program continues a step.
+
+BOOL CScript::IsContinue()
+{
+ return m_bContinue;
+}
+
+
+// Gives the position of the cursor during the execution.
+
+BOOL CScript::GetCursor(int &cursor1, int &cursor2)
+{
+ const char* funcName;
+
+ cursor1 = cursor2 = 0;
+
+ if( m_botProg == 0 ) return FALSE;
+ if ( !m_bRun ) return FALSE;
+
+ m_botProg->GetRunPos(funcName, cursor1, cursor2);
+ if ( cursor1 < 0 || cursor1 > m_len ||
+ cursor2 < 0 || cursor2 > m_len )
+ {
+ cursor1 = 0;
+ cursor2 = 0;
+ }
+ return TRUE;
+}
+
+
+// Put of the variables in a list.
+
+void PutList(char *baseName, BOOL bArray, CBotVar *var, CList *list, int &rankList)
+{
+ CBotString bs;
+ CBotVar *svar, *pStatic;
+ char varName[100];
+ char buffer[100];
+ const char *p;
+ int index, type;
+
+ if ( var == 0 && baseName[0] != 0 )
+ {
+ sprintf(buffer, "%s = null;", baseName);
+ list->SetName(rankList++, buffer);
+ return;
+ }
+
+ index = 0;
+ while ( var != 0 )
+ {
+ var->Maj(NULL, FALSE);
+ pStatic = var->GivStaticVar(); // finds the static element
+
+ bs = pStatic->GivName(); // variable name
+ p = bs;
+//? if ( strcmp(p, "this") == 0 )
+//? {
+//? var = var->GivNext();
+//? continue;
+//? }
+
+ if ( baseName[0] == 0 )
+ {
+ sprintf(varName, "%s", p);
+ }
+ else
+ {
+ if ( bArray )
+ {
+ sprintf(varName, "%s[%d]", baseName, index);
+ }
+ else
+ {
+ sprintf(varName, "%s.%s", baseName, p);
+ }
+ }
+
+ type = pStatic->GivType();
+
+ if ( type < CBotTypBoolean )
+ {
+ CBotString value;
+ value = pStatic->GivValString();
+ p = value;
+ sprintf(buffer, "%s = %s;", varName, p);
+ list->SetName(rankList++, buffer);
+ }
+ else if ( type == CBotTypString )
+ {
+ CBotString value;
+ value = pStatic->GivValString();
+ p = value;
+ sprintf(buffer, "%s = \"%s\";", varName, p);
+ list->SetName(rankList++, buffer);
+ }
+ else if ( type == CBotTypArrayPointer )
+ {
+ svar = pStatic->GivItemList();
+ PutList(varName, TRUE, svar, list, rankList);
+ }
+ else if ( type == CBotTypClass ||
+ type == CBotTypPointer )
+ {
+ svar = pStatic->GivItemList();
+ PutList(varName, FALSE, svar, list, rankList);
+ }
+ else
+ {
+ sprintf(buffer, "%s = ?;", varName);
+ list->SetName(rankList++, buffer);
+ }
+
+ index ++;
+ var = var->GivNext();
+ }
+}
+
+// Fills a list with variables.
+
+void CScript::UpdateList(CList* list)
+{
+ CBotVar *var;
+ const char *progName, *funcName;
+ int total, select, level, cursor1, cursor2, rank;
+
+ if( m_botProg == 0 ) return;
+
+ total = list->RetTotal();
+ select = list->RetSelect();
+
+ list->Flush(); // empty list
+ m_botProg->GetRunPos(progName, cursor1, cursor2);
+ if ( progName == 0 ) return;
+
+ level = 0;
+ rank = 0;
+ while ( TRUE )
+ {
+ var = m_botProg->GivStackVars(funcName, level--);
+ if ( funcName != progName ) break;
+
+ PutList("", FALSE, var, list, rank);
+ }
+
+ if ( total == list->RetTotal() ) // same total?
+ {
+ list->SetSelect(select);
+ }
+
+ list->SetTooltip("");
+ list->SetState(STATE_ENABLE);
+}
+
+
+// Colorize the text according to syntax.
+
+void CScript::ColorizeScript(CEdit* edit)
+{
+ CBotToken* bt;
+ CBotString bs;
+ const char* token;
+ int error, type, cursor1, cursor2, color;
+
+ edit->ClearFormat();
+
+ bt = CBotToken::CompileTokens(edit->RetText(), error);
+ while ( bt != 0 )
+ {
+ bs = bt->GivString();
+ token = bs;
+ type = bt->GivType();
+
+ cursor1 = bt->GivStart();
+ cursor2 = bt->GivEnd();
+
+ color = 0;
+ if ( type >= TokenKeyWord && type < TokenKeyWord+100 )
+ {
+ color = COLOR_TOKEN;
+ }
+ if ( type >= TokenKeyDeclare && type < TokenKeyDeclare+100 )
+ {
+ color = COLOR_TYPE;
+ }
+ if ( type >= TokenKeyVal && type < TokenKeyVal+100 )
+ {
+ color = COLOR_CONST;
+ }
+ if ( type == TokenTypVar )
+ {
+ if ( IsType(token) )
+ {
+ color = COLOR_TYPE;
+ }
+ else if ( IsFunction(token) )
+ {
+ color = COLOR_TOKEN;
+ }
+ }
+ if ( type == TokenTypDef )
+ {
+ color = COLOR_CONST;
+ }
+
+ if ( cursor1 < cursor2 && color != 0 )
+ {
+ edit->SetFormat(cursor1, cursor2, color);
+ }
+
+ bt = bt->GivNext();
+ }
+
+ CBotToken::Delete(bt);
+}
+
+
+// Seeks a token at random in a script.
+// Returns the index of the start of the token found, or -1.
+
+int SearchToken(char* script, char* token)
+{
+ int lScript, lToken, i, iFound;
+ int found[100];
+ char* p;
+
+ lScript = strlen(script);
+ lToken = strlen(token);
+ iFound = 0;
+ for ( i=0 ; i<lScript-lToken ; i++ )
+ {
+ p = strstr(script+i, token);
+ if ( p != 0 )
+ {
+ found[iFound++] = p-script;
+ if ( iFound >= 100 ) break;
+ }
+ }
+
+ if ( iFound == 0 ) return -1;
+ return found[rand()%iFound];
+}
+
+// Removes a token in a script.
+
+void DeleteToken(char* script, int pos, int len)
+{
+ while ( TRUE )
+ {
+ script[pos] = script[pos+len];
+ if ( script[pos++] == 0 ) break;
+ }
+}
+
+// Inserts a token in a script.
+
+void InsertToken(char* script, int pos, char* token)
+{
+ int lScript, lToken, i;
+
+ lScript = strlen(script);
+ lToken = strlen(token);
+ for ( i=lScript ; i>=pos ; i-- )
+ {
+ script[i+lToken] = script[i];
+ }
+ memcpy(script+pos, token, lToken);
+}
+
+// Introduces a virus into a program.
+
+BOOL CScript::IntroduceVirus()
+{
+ int i, start, iFound;
+ int found[11*2];
+ char* newScript;
+
+ char* names[11*2] =
+ {
+ "==", "!=",
+ "!=", "==",
+ ">", "<",
+ "<", ">",
+ "true", "false",
+ "false", "true",
+ "grab", "drop",
+ "drop", "grab",
+ "InFront", "Behind",
+ "Behind", "EnergyCell",
+ "EnergyCell", "InFront",
+ };
+
+ iFound = 0;
+ for ( i=0 ; i<11 ; i++ )
+ {
+ start = SearchToken(m_script, names[i*2]);
+ if ( start != -1 )
+ {
+ found[iFound++] = i*2;
+ found[iFound++] = start;
+ }
+ }
+ if ( iFound == 0 ) return FALSE;
+
+ i = (rand()%(iFound/2))*2;
+ start = found[i+1];
+ i = found[i+0];
+
+ newScript = (char*)malloc(sizeof(char)*(m_len+strlen(names[i+1])+1));
+ strcpy(newScript, m_script);
+ delete m_script;
+ m_script = newScript;
+
+ DeleteToken(m_script, start, strlen(names[i]));
+ InsertToken(m_script, start, names[i+1]);
+ m_len = strlen(m_script);
+ Compile(); // recompile with the virus
+
+ return TRUE;
+}
+
+
+// Returns the number of the error.
+
+int CScript::RetError()
+{
+ return m_error;
+}
+
+// Returns the text of the error.
+
+void CScript::GetError(char* buffer)
+{
+ if ( m_error == 0 )
+ {
+ buffer[0] = 0;
+ }
+ else
+ {
+ if ( m_error == ERR_OBLIGATORYTOKEN )
+ {
+ char s[100];
+ GetResource(RES_ERR, m_error, s);
+ sprintf(buffer, s, m_token);
+ }
+ else if ( m_error < 1000 )
+ {
+ GetResource(RES_ERR, m_error, buffer);
+ }
+ else
+ {
+ GetResource(RES_CBOT, m_error, buffer);
+ }
+ }
+}
+
+
+// New program.
+
+void CScript::New(CEdit* edit, char* name)
+{
+ FILE *file = NULL;
+ char res[100];
+ char text[100];
+ char filename[100];
+ char script[500];
+ char buffer[500];
+ char *sf;
+ int cursor1, cursor2, len, i, j;
+
+ GetResource(RES_TEXT, RT_SCRIPT_NEW, res);
+ if ( name[0] == 0 ) strcpy(text, res);
+ else strcpy(text, name);
+
+ sprintf(script, "extern void object::%s()\n{\n\t\n\t\n\t\n}\n", text);
+ edit->SetText(script, FALSE);
+
+ if ( strcmp(text, res) == 0 )
+ {
+ cursor1 = 20;
+ cursor2 = 20+strlen(text); // update "New"
+ }
+ else
+ {
+ if ( edit->RetAutoIndent() )
+ {
+ cursor1 = 20+strlen(text)+6;
+ cursor2 = cursor1; // cursor in { }
+ }
+ else
+ {
+ cursor1 = 20+strlen(text)+8;
+ cursor2 = cursor1; // cursor in { }
+ }
+ }
+
+ edit->SetCursor(cursor2, cursor1);
+ edit->ShowSelect();
+ edit->SetFocus(TRUE);
+
+ sf = m_main->RetScriptFile();
+ if ( sf[0] != 0 ) // Load an empty program specific?
+ {
+ strcpy(filename, "script\\");
+ strcat(filename, sf);
+ file = fopen(filename, "rb");
+ if ( file != NULL )
+ {
+ fseek(file, 0, SEEK_END);
+ len = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ if ( len > 500-1 ) len = 500-1;
+ fread(buffer, 1, len, file);
+ buffer[len] = 0;
+ fclose(file);
+
+ cursor1 = 0;
+ i = 0;
+ j = 0;
+ while ( TRUE )
+ {
+ if ( buffer[i] == 0 ) break;
+
+ if ( buffer[i] == '\r' )
+ {
+ i ++;
+ continue;
+ }
+
+ if ( buffer[i] == '\t' && edit->RetAutoIndent() )
+ {
+ i ++;
+ continue;
+ }
+
+ if ( buffer[i+0] == '%' &&
+ buffer[i+1] == 's' )
+ {
+ strcpy(script+j, text);
+ j += strlen(text);
+ i += 2;
+ continue;
+ }
+
+ if ( buffer[i] == '#' )
+ {
+ cursor1 = j;
+ i ++;
+ continue;
+ }
+
+ script[j++] = buffer[i++];
+ }
+ script[j] = 0;
+ edit->SetText(script, FALSE);
+
+ cursor2 = cursor1;
+ edit->SetCursor(cursor2, cursor1);
+ edit->ShowSelect();
+ edit->SetFocus(TRUE);
+ }
+ }
+
+ ColorizeScript(edit);
+}
+
+
+// Provided a script for all parts.
+
+BOOL CScript::SendScript(char* text)
+{
+ m_len = strlen(text);
+ m_script = (char*)malloc(sizeof(char)*(m_len+1));
+ strcpy(m_script, text);
+ if ( !CheckToken() ) return FALSE;
+ if ( !Compile() ) return FALSE;
+
+ return TRUE;
+}
+
+// Reads a script as a text file.
+
+BOOL CScript::ReadScript(char* filename)
+{
+ FILE* file;
+ CEdit* edit;
+ char name[100];
+
+ if ( strchr(filename, '\\') == 0 )
+ {
+ strcpy(name, "script\\");
+ strcat(name, filename);
+ }
+ else
+ {
+//? strcpy(name, filename);
+ UserDir(name, filename, "");
+ }
+
+ file = fopen(name, "rb");
+ if ( file == NULL ) return FALSE;
+ fclose(file);
+
+ delete m_script;
+ m_script = 0;
+
+ edit = m_interface->CreateEdit(FPOINT(0.0f, 0.0f), FPOINT(0.0f, 0.0f), 0, EVENT_EDIT9);
+ edit->SetMaxChar(EDITSTUDIOMAX);
+ edit->SetAutoIndent(m_engine->RetEditIndentMode());
+ edit->ReadText(name);
+ GetScript(edit);
+ m_interface->DeleteControl(EVENT_EDIT9);
+ return TRUE;
+}
+
+// Writes a script as a text file.
+
+BOOL CScript::WriteScript(char* filename)
+{
+ CEdit* edit;
+ char name[100];
+
+ if ( strchr(filename, '\\') == 0 )
+ {
+ strcpy(name, "script\\");
+ strcat(name, filename);
+ }
+ else
+ {
+ strcpy(name, filename);
+ }
+
+ if ( m_script == 0 )
+ {
+ remove(filename);
+ return FALSE;
+ }
+
+ edit = m_interface->CreateEdit(FPOINT(0.0f, 0.0f), FPOINT(0.0f, 0.0f), 0, EVENT_EDIT9);
+ edit->SetMaxChar(EDITSTUDIOMAX);
+ edit->SetAutoIndent(m_engine->RetEditIndentMode());
+ edit->SetText(m_script);
+ edit->WriteText(name);
+ m_interface->DeleteControl(EVENT_EDIT9);
+ return TRUE;
+}
+
+
+// Reads a stack of script by execution as a file.
+
+BOOL CScript::ReadStack(FILE *file)
+{
+ int nb;
+
+ fRead(&nb, sizeof(int), 1, file);
+ fRead(&m_ipf, sizeof(int), 1, file);
+ fRead(&m_errMode, sizeof(int), 1, file);
+
+ if ( m_botProg == 0 ) return FALSE;
+ if ( !m_botProg->RestoreState(file) ) return FALSE;
+
+ m_object->SetRunScript(this);
+ m_bRun = TRUE;
+ m_bContinue = FALSE;
+ return TRUE;
+}
+
+// Writes a stack of script by execution as a file.
+
+BOOL CScript::WriteStack(FILE *file)
+{
+ int nb;
+
+ nb = 2;
+ fWrite(&nb, sizeof(int), 1, file);
+ fWrite(&m_ipf, sizeof(int), 1, file);
+ fWrite(&m_errMode, sizeof(int), 1, file);
+
+ return m_botProg->SaveState(file);
+}
+
+
+// Compares two scripts.
+
+BOOL CScript::Compare(CScript* other)
+{
+ if ( m_len != other->m_len ) return FALSE;
+
+ return ( strcmp(m_script, other->m_script) == 0 );
+}
+
+
+// Management of the file name when the script is saved.
+
+void CScript::SetFilename(char *filename)
+{
+ strcpy(m_filename, filename);
+}
+
+char* CScript::RetFilename()
+{
+ return m_filename;
+}
+
diff --git a/src/script/script.h b/src/script/script.h
new file mode 100644
index 0000000..eeb8ac8
--- /dev/null
+++ b/src/script/script.h
@@ -0,0 +1,118 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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://www.gnu.org/licenses/.
+
+// script.h
+
+#ifndef _SCRIPT_H_
+#define _SCRIPT_H_
+
+
+#include "event.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CInterface;
+class CDisplayText;
+class CEdit;
+class CList;
+class CObject;
+class CTaskManager;
+class CBotProgram;
+class CRobotMain;
+class CTerrain;
+class CWater;
+
+
+
+class CScript
+{
+public:
+ CScript(CInstanceManager* iMan, CObject* object, CTaskManager** secondaryTask);
+ ~CScript();
+
+ static void InitFonctions();
+
+ void PutScript(CEdit* edit, char* name);
+ BOOL GetScript(CEdit* edit);
+ BOOL RetCompile();
+
+ void GetTitle(char* buffer);
+
+ void SetStepMode(BOOL bStep);
+ BOOL Run();
+ BOOL Continue(const Event &event);
+ BOOL Step(const Event &event);
+ void Stop();
+ BOOL IsRunning();
+ BOOL IsContinue();
+ BOOL GetCursor(int &cursor1, int &cursor2);
+ void UpdateList(CList* list);
+ void ColorizeScript(CEdit* edit);
+ BOOL IntroduceVirus();
+
+ int RetError();
+ void GetError(char* buffer);
+
+ void New(CEdit* edit, char* name);
+ BOOL SendScript(char* text);
+ BOOL ReadScript(char* filename);
+ BOOL WriteScript(char* filename);
+ BOOL ReadStack(FILE *file);
+ BOOL WriteStack(FILE *file);
+ BOOL Compare(CScript* other);
+
+ void SetFilename(char *filename);
+ char* RetFilename();
+
+protected:
+ BOOL IsEmpty();
+ BOOL CheckToken();
+ BOOL Compile();
+
+public:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CInterface* m_interface;
+ CDisplayText* m_displayText;
+ CBotProgram* m_botProg;
+ CRobotMain* m_main;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CTaskManager* m_primaryTask;
+ CTaskManager** m_secondaryTask;
+ CObject* m_object;
+
+ int m_ipf; // number of instructions/second
+ int m_errMode; // what to do in case of error
+ int m_len; // length of the script (without <0>)
+ char* m_script; // script ends with <0>
+ BOOL m_bRun; // program during execution?
+ BOOL m_bStepMode; // step by step
+ BOOL m_bContinue; // external function to continue
+ BOOL m_bCompile; // compilation ok?
+ char m_title[50]; // script title
+ char m_filename[50]; // file name
+ char m_token[50]; // missing instruction
+ int m_error; // error (0=ok)
+ int m_cursor1;
+ int m_cursor2;
+ Event m_event;
+ float m_returnValue;
+};
+
+
+#endif //_SCRIPT_H_