Started intrepreter for tpt script and various things for console

This commit is contained in:
Simon Robertshaw 2012-02-05 16:37:36 +00:00
parent 8024caec55
commit 7ae5eaab79
13 changed files with 720 additions and 56 deletions

View File

@ -51,8 +51,8 @@ SDL_Surface * SDLOpen()
{
freopen("CON", "w", stdout);
freopen("con", "w", stderr);
fclose(console);
freopen("CON", "w", stderr);
//fclose(console);
}
#endif
#ifdef WIN32

View File

@ -0,0 +1,107 @@
/*
* Kitty.cpp
*
* Created on: Feb 2, 2012
* Author: Simon
*/
#include <iostream>
#include <string>
#include <string.h>
#include "CommandInterface.h"
#include "game/GameModel.h"
CommandInterface::CommandInterface() {
}
void CommandInterface::AttachGameModel(GameModel * m)
{
this->m = m;
}
int CommandInterface::Command(std::string command)
{
lastError = "No interpreter";
return -1;
}
std::string CommandInterface::FormatCommand(std::string command)
{
return command;
}
int CommandInterface::GetPropertyOffset(std::string key_, FormatType & format)
{
char * key = (char *)key_.c_str();
int offset;
if (strcmp(key, "type")==0){
offset = offsetof(Particle, type);
format = FormatInt;
} else if (strcmp(key, "life")==0){
offset = offsetof(Particle, life);
format = FormatInt;
} else if (strcmp(key, "ctype")==0){
offset = offsetof(Particle, ctype);
format = FormatInt;
} else if (strcmp(key, "temp")==0){
offset = offsetof(Particle, temp);
format = FormatFloat;
} else if (strcmp(key, "tmp")==0){
offset = offsetof(Particle, tmp);
format = FormatInt;
} else if (strcmp(key, "tmp2")==0){
offset = offsetof(Particle, tmp2);
format = FormatInt;
} else if (strcmp(key, "vy")==0){
offset = offsetof(Particle, vy);
format = FormatFloat;
} else if (strcmp(key, "vx")==0){
offset = offsetof(Particle, vx);
format = FormatFloat;
} else if (strcmp(key, "x")==0){
offset = offsetof(Particle, x);
format = FormatFloat;
} else if (strcmp(key, "y")==0){
offset = offsetof(Particle, y);
format = FormatFloat;
} else if (strcmp(key, "dcolour")==0){
offset = offsetof(Particle, dcolour);
format = FormatInt;
} else if (strcmp(key, "dcolor")==0){
offset = offsetof(Particle, dcolour);
format = FormatInt;
} else {
offset = -1;
}
return offset;
}
int CommandInterface::GetParticleType(std::string type)
{
int i = -1;
char * txt = (char*)type.c_str();
//Scope
part_type *ptypes = m->GetSimulation()->ptypes;
// alternative names for some elements
if (strcasecmp(txt,"C4")==0) i = PT_PLEX;
else if (strcasecmp(txt,"C5")==0) i = PT_C5;
else if (strcasecmp(txt,"NONE")==0) i = PT_NONE;
for (i=1; i<PT_NUM; i++) {
if (strcasecmp(txt, ptypes[i].name)==0 && ptypes[i].enabled)
{
return i;
}
}
return i;
}
std::string CommandInterface::GetLastError()
{
return lastError;
}
CommandInterface::~CommandInterface() {
}

View File

@ -0,0 +1,32 @@
/*
* Kitty.h
*
* Created on: Feb 2, 2012
* Author: Simon
*/
#ifndef KITTY_H_
#define KITTY_H_
#include <string>
//#include "game/GameModel.h"
class GameModel;
class CommandInterface {
protected:
enum FormatType { FormatInt, FormatString, FormatChar, FormatFloat };
std::string lastError;
GameModel * m;
public:
CommandInterface();
int GetPropertyOffset(std::string key_, FormatType & format);
int GetParticleType(std::string type);
void AttachGameModel(GameModel * m);
virtual void Tick() {}
virtual int Command(std::string command);
virtual std::string FormatCommand(std::string command);
std::string GetLastError();
virtual ~CommandInterface();
};
#endif /* KITTY_H_ */

112
src/cat/TPTSTypes.cpp Normal file
View File

@ -0,0 +1,112 @@
/*
* TPTSTypes.cpp
*
* Created on: Feb 4, 2012
* Author: Simon
*/
#include <iostream>
#include <sstream>
#include "TPTSTypes.h"
AnyType::AnyType(ValueType type_, void * value_):
type(type_),
value(value_)
{
}
ValueType AnyType::GetType()
{
return type;
}
AnyType::AnyType(const AnyType & v):
type(v.type),
value(v.value)
{
if(type == TypeString)
{
value = new std::string(*((std::string*)value));
}
else if(type == TypePoint)
{
value = new ui::Point(*((ui::Point*)value));
}
}
AnyType::operator NumberType()
{
if(type != TypeNumber)
throw InvalidConversionException(type, TypeNumber);
else
return NumberType((int)value);
}
AnyType::operator StringType()
{
if(type == TypeNumber)
{
std::stringstream numberStream;
numberStream << ((NumberType*)this)->Value();
return StringType(numberStream.str());
}
else if(type == TypeString && value)
{
return StringType(*((std::string*)value));
}
else
throw InvalidConversionException(type, TypeString);
}
AnyType::operator PointType()
{
if(type == TypePoint)
{
return PointType(*((ui::Point*)value));
}
else if(type == TypeString)
{
ui::Point thisPoint = *((ui::Point*)value);
std::stringstream pointStream;
pointStream << thisPoint.X << "," << thisPoint.Y;
return StringType(pointStream.str());
}
else
throw InvalidConversionException(type, TypePoint);
}
AnyType::~AnyType()
{
if(type == TypeString || type == TypePoint)
delete value;
}
//Number Type
NumberType::NumberType(int number): AnyType(TypeNumber, (void*)number) { }
int NumberType::Value()
{
return (int)value;
}
//String type
StringType::StringType(std::string string): AnyType(TypeString, new std::string(string)) { }
std::string StringType::Value()
{
return std::string(*((std::string*)value));
}
//Point type
PointType::PointType(ui::Point point): AnyType(TypePoint, new ui::Point(point)) { }
PointType::PointType(int pointX, int pointY): AnyType(TypePoint, new ui::Point(pointX, pointY)) { }
ui::Point PointType::Value()
{
return ui::Point(*((ui::Point*)value));
}

80
src/cat/TPTSTypes.h Normal file
View File

@ -0,0 +1,80 @@
/*
* TPTSTypes.h
*
* Created on: Feb 4, 2012
* Author: Simon
*/
#ifndef TPTSTYPES_H_
#define TPTSTYPES_H_
#include <string>
#include "interface/Point.h"
enum ValueType { TypeNumber, TypePoint, TypeString, TypeNull, TypeFunction };
class GeneralException
{
protected:
std::string exception;
public:
GeneralException(std::string message){
exception = message;
}
std::string GetExceptionMessage() {
return exception;
}
};
class InvalidConversionException: public GeneralException
{
private:
ValueType from;
ValueType to;
public:
InvalidConversionException(ValueType from_, ValueType to_): GeneralException("Invalid conversion"), from(from_), to(to_) {
}
};
class NumberType;
class StringType;
class PointType;
class AnyType
{
protected:
ValueType type;
void * value;
public:
AnyType(ValueType type_, void * value_);
AnyType(const AnyType & v);
operator NumberType();
operator StringType();
operator PointType();
ValueType GetType();
~AnyType();
};
class NumberType: public AnyType
{
public:
NumberType(int number);
int Value();
};
class StringType: public AnyType
{
public:
StringType(std::string string);
std::string Value();
};
class PointType: public AnyType
{
public:
PointType(ui::Point point);
PointType(int pointX, int pointY);
ui::Point Value();
};
#endif /* TPTSTYPES_H_ */

View File

@ -0,0 +1,314 @@
/*
* TPTScriptInterface.cpp
*
* Created on: Feb 5, 2012
* Author: Simon
*/
#include <stack>
#include <iostream>
#include <string>
#include <deque>
#include <string.h>
#include <stdlib.h>
#include "TPTScriptInterface.h"
#include "game/GameModel.h"
TPTScriptInterface::TPTScriptInterface() {
}
int TPTScriptInterface::Command(std::string command)
{
lastError = "";
std::deque<std::string> words;
std::deque<AnyType> commandWords;
int retCode;
//Split command into words, put them on the stack
char * rawCommand;
rawCommand = (char*)calloc(command.length()+1, 1);
memcpy(rawCommand, (char*)command.c_str(), command.length());
char * currentWord = rawCommand;
char * currentCommand = rawCommand;
while((currentCommand = strchr(currentCommand, ' ')))
{
currentCommand[0] = 0;
words.push_back(std::string(currentWord));
currentWord = ++currentCommand;
}
words.push_back(std::string(currentWord));
while(!words.empty())
{
try
{
commandWords.push_back(eval(&words));
}
catch (GeneralException & e)
{
retCode = -1;
lastError = e.GetExceptionMessage();
break;
}
}
free(rawCommand);
if(commandWords.size())
{
retCode = 0;
lastError = ((StringType)commandWords.front()).Value();
}
//Evaluate
return 0;
}
ValueType TPTScriptInterface::testType(std::string word)
{
int i = 0;
char * rawWord = (char *)word.c_str();
//Function
if(word == "set")
return TypeFunction;
//Basic type
parseNumber:
for(i = 0; i < word.length(); i++)
if(!(rawWord[i] >= '0' && rawWord[i] <= '9'))
{
if(rawWord[i] == ',' && rawWord[i+1] >= '0' && rawWord[i+1] <= '9')
goto parsePoint;
else
goto parseString;
}
return TypeNumber;
parsePoint:
i++;
for(; i < word.length(); i++)
if(!(rawWord[i] >= '0' && rawWord[i] <= '9'))
{
goto parseString;
}
return TypePoint;
parseString:
return TypeString;
}
AnyType TPTScriptInterface::eval(std::deque<std::string> * words)
{
if(words->size() < 1)
return AnyType(TypeNull, NULL);
std::string word = words->front(); words->pop_front();
char * rawWord = (char *)word.c_str();
ValueType wordType = testType(word);
switch(wordType)
{
case TypeFunction:
if(word == "set")
return tptS_set(words);
break;
case TypeNumber:
return NumberType(atoi(rawWord));
case TypePoint:
{
int pointX, pointY;
sscanf(rawWord, "%d,%d", &pointX, &pointY);
return PointType(pointX, pointY);
}
case TypeString:
return StringType(word);
}
}
std::string TPTScriptInterface::FormatCommand(std::string command)
{
std::deque<std::string> words;
std::deque<AnyType> commandWords;
std::string outputData;
//Split command into words, put them on the stack
char * rawCommand;
rawCommand = (char*)calloc(command.length()+1, 1);
memcpy(rawCommand, (char*)command.c_str(), command.length());
char * currentWord = rawCommand;
char * currentCommand = rawCommand;
while((currentCommand = strchr(currentCommand, ' ')))
{
currentCommand[0] = 0;
words.push_back(std::string(currentWord));
currentWord = ++currentCommand;
}
words.push_back(std::string(currentWord));
while(!words.empty())
{
ValueType cType = testType(words.front());
switch(cType)
{
case TypeFunction:
outputData += "\bt";
break;
case TypeNumber:
case TypePoint:
outputData += "\bo";
break;
case TypeString:
outputData += "\bg";
break;
default:
outputData += "\bw";
break;
}
outputData += words.front() + " ";
words.pop_front();
}
/*char * rawText = (char*)command.c_str();
char * outputData = (char *)calloc(command.length()*6, 1);
int rawTextLoc = 0;
int outputDataLoc = 0;
std::stack<char> pstack;
while(rawText[rawTextLoc])
{
switch(rawText[rawTextLoc])
{
case '\\':
outputData[outputDataLoc++] = rawText[rawTextLoc++];
if(rawText[rawTextLoc])
outputData[outputDataLoc++] = rawText[rawTextLoc++];
break;
case '"':
if(pstack.size() && pstack.top() == '"')
{
pstack.pop();
outputData[outputDataLoc++] = rawText[rawTextLoc++];
outputData[outputDataLoc++] = '\b';
outputData[outputDataLoc++] = 'w';
}
else
{
pstack.push('"');
outputData[outputDataLoc++] = '\b';
outputData[outputDataLoc++] = 'o';
outputData[outputDataLoc++] = rawText[rawTextLoc++];
}
break;
default:
outputData[outputDataLoc++] = rawText[rawTextLoc++];
break;
}
}*/
return outputData;
}
AnyType TPTScriptInterface::tptS_set(std::deque<std::string> * words)
{
//Arguments from stack
StringType property = eval(words);
AnyType value = eval(words);
AnyType selector = eval(words);
Simulation * sim = m->GetSimulation();
int returnValue = 0;
FormatType propertyFormat;
int propertyOffset = GetPropertyOffset(property.Value(), propertyFormat);
if(propertyOffset==-1)
throw GeneralException("Invalid property");
if(selector.GetType() == TypePoint || selector.GetType() == TypeNumber)
{
int partIndex = -1;
if(selector.GetType() == TypePoint)
{
ui::Point tempPoint = ((PointType)selector).Value();
if(tempPoint.X<0 || tempPoint.Y<0 || tempPoint.Y >= YRES || tempPoint.X >= XRES)
throw GeneralException("Invalid particle");
}
else
partIndex = ((NumberType)selector).Value();
if(partIndex<0 || partIndex>NPART || sim->parts[partIndex].type==0)
throw GeneralException("Invalid particle");
switch(propertyFormat)
{
case FormatInt:
*((int*)(((void*)&sim->parts[partIndex])+propertyOffset)) = ((NumberType)value).Value();
break;
case FormatFloat:
*((float*)(((void*)&sim->parts[partIndex])+propertyOffset)) = ((NumberType)value).Value();
break;
}
returnValue = 1;
}
else if(selector.GetType() == TypeString && ((StringType)selector).Value() == "all")
{
switch(propertyFormat)
{
case FormatInt:
{
int tempNumber = ((NumberType)value).Value();
for(int j = 0; j < NPART; j++)
if(sim->parts[j].type)
{
returnValue++;
*((int*)(((void*)&sim->parts[j])+propertyOffset)) = tempNumber;
}
}
break;
case FormatFloat:
{
float tempNumber = ((NumberType)value).Value();
for(int j = 0; j < NPART; j++)
if(sim->parts[j].type)
{
returnValue++;
*((float*)(((void*)&sim->parts[j])+propertyOffset)) = tempNumber;
}
}
break;
}
}
else if(selector.GetType() == TypeString || selector.GetType() == TypeNumber)
{
int type;
if(selector.GetType() == TypeNumber)
type = ((NumberType)selector).Value();
else
type = GetParticleType(((StringType)selector).Value());
if(type<0 || type>=PT_NUM)
throw GeneralException("Invalid particle type");
switch(propertyFormat)
{
case FormatInt:
{
int tempNumber = ((NumberType)value).Value();
for(int j = 0; j < NPART; j++)
if(sim->parts[j].type == type)
{
returnValue++;
*((int*)(((void*)&sim->parts[j])+propertyOffset)) = tempNumber;
}
}
break;
case FormatFloat:
{
float tempNumber = ((NumberType)value).Value();
for(int j = 0; j < NPART; j++)
if(sim->parts[j].type == type)
{
returnValue++;
*((float*)(((void*)&sim->parts[j])+propertyOffset)) = tempNumber;
}
}
break;
}
}
else
throw GeneralException("Invalid selector");
return NumberType(returnValue);
}
TPTScriptInterface::~TPTScriptInterface() {
}

View File

@ -0,0 +1,27 @@
/*
* TPTScriptInterface.h
*
* Created on: Feb 5, 2012
* Author: Simon
*/
#ifndef TPTSCRIPTINTERFACE_H_
#define TPTSCRIPTINTERFACE_H_
#include "CommandInterface.h"
#include "TPTSTypes.h"
class TPTScriptInterface: public CommandInterface {
protected:
AnyType eval(std::deque<std::string> * words);
AnyType tptS_set(std::deque<std::string> * words);
ValueType testType(std::string word);
public:
TPTScriptInterface();
virtual void Tick() {}
virtual int Command(std::string command);
virtual std::string FormatCommand(std::string command);
virtual ~TPTScriptInterface();
};
#endif /* TPTSCRIPTINTERFACE_H_ */

View File

@ -8,7 +8,7 @@
#include <stack>
#include "ConsoleController.h"
ConsoleController::ConsoleController(ControllerCallback * callback):
ConsoleController::ConsoleController(ControllerCallback * callback, CommandInterface * commandInterface):
HasDone(false)
{
consoleModel = new ConsoleModel();
@ -17,55 +17,28 @@ ConsoleController::ConsoleController(ControllerCallback * callback):
consoleModel->AddObserver(consoleView);
this->callback = callback;
this->commandInterface = commandInterface;
}
void ConsoleController::EvaluateCommand(std::string command)
{
int returnCode = commandInterface->Command(command);
if(command.length())
consoleModel->AddLastCommand(ConsoleCommand(command, -1, "Syntax error"));
consoleModel->AddLastCommand(ConsoleCommand(command, returnCode, commandInterface->GetLastError()));
else
if(ui::Engine::Ref().GetWindow() == consoleView)
ui::Engine::Ref().CloseWindow();
}
void ConsoleController::CloseConsole()
{
if(ui::Engine::Ref().GetWindow() == consoleView)
ui::Engine::Ref().CloseWindow();
}
std::string ConsoleController::FormatCommand(std::string command)
{
char * rawText = (char*)command.c_str();
char * outputData = (char *)calloc(command.length()*6, 1);
int rawTextLoc = 0;
int outputDataLoc = 0;
std::stack<char> pstack;
while(rawText[rawTextLoc])
{
switch(rawText[rawTextLoc])
{
case '\\':
outputData[outputDataLoc++] = rawText[rawTextLoc++];
if(rawText[rawTextLoc])
outputData[outputDataLoc++] = rawText[rawTextLoc++];
break;
case '"':
if(pstack.size() && pstack.top() == '"')
{
pstack.pop();
outputData[outputDataLoc++] = rawText[rawTextLoc++];
outputData[outputDataLoc++] = '\b';
outputData[outputDataLoc++] = 'w';
}
else
{
pstack.push('"');
outputData[outputDataLoc++] = '\b';
outputData[outputDataLoc++] = 'o';
outputData[outputDataLoc++] = rawText[rawTextLoc++];
}
break;
default:
outputData[outputDataLoc++] = rawText[rawTextLoc++];
break;
}
}
return outputData;
return commandInterface->FormatCommand(command);
}
void ConsoleController::NextCommand()

View File

@ -13,6 +13,7 @@
#include "ConsoleView.h"
#include "ConsoleModel.h"
#include "ConsoleCommand.h"
#include "cat/CommandInterface.h"
class ConsoleModel;
class ConsoleView;
@ -20,14 +21,16 @@ class ConsoleController {
ControllerCallback * callback;
ConsoleView * consoleView;
ConsoleModel * consoleModel;
CommandInterface * commandInterface;
public:
bool HasDone;
ConsoleController(ControllerCallback * callback);
ConsoleController(ControllerCallback * callback, CommandInterface * commandInterface);
std::string FormatCommand(std::string command);
void EvaluateCommand(std::string command);
void NextCommand();
void PreviousCommand();
void Exit();
void CloseConsole();
ConsoleView * GetView();
virtual ~ConsoleController();
};

View File

@ -34,6 +34,9 @@ void ConsoleView::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, b
{
switch(key)
{
case '`':
c->CloseConsole();
break;
case KEY_RETURN:
case KEY_ENTER:
c->EvaluateCommand(commandField->GetText());
@ -63,7 +66,11 @@ void ConsoleView::NotifyPreviousCommandsChanged(ConsoleModel * sender)
{
if(currentY <= 0)
break;
ui::Label * tempLabel = new ui::Label(ui::Point(0, currentY), ui::Point(Size.X, 16), commands[i].Command);
ui::Label * tempLabel = new ui::Label(ui::Point(Size.X/2, currentY), ui::Point(Size.X/2, 16), commands[i].ReturnValue);
tempLabel->SetAlignment(AlignLeft, AlignMiddle);
commandList.push_back(tempLabel);
AddComponent(tempLabel);
tempLabel = new ui::Label(ui::Point(0, currentY), ui::Point(Size.X/2, 16), commands[i].Command);
tempLabel->SetAlignment(AlignLeft, AlignMiddle);
commandList.push_back(tempLabel);
AddComponent(tempLabel);

View File

@ -70,7 +70,8 @@ GameController::GameController():
search(NULL),
renderOptions(NULL),
loginWindow(NULL),
ssave(NULL)
ssave(NULL),
console(NULL)
{
gameView = new GameView();
gameModel = new GameModel();
@ -78,6 +79,9 @@ GameController::GameController():
gameView->AttachController(this);
gameModel->AddObserver(gameView);
commandInterface = new TPTScriptInterface();
commandInterface->AttachGameModel(gameModel);
//sim = new Simulation();
}
@ -312,7 +316,8 @@ void GameController::OpenDisplayOptions()
void GameController::ShowConsole()
{
console = new ConsoleController(NULL);
if(!console)
console = new ConsoleController(NULL, commandInterface);
ui::Engine::Ref().ShowWindow(console->GetView());
}

View File

@ -11,12 +11,15 @@
#include "login/LoginController.h"
#include "ssave/SSaveController.h"
#include "console/ConsoleController.h"
#include "cat/TPTScriptInterface.h"
#include "Menu.h"
using namespace std;
class GameModel;
class GameView;
class CommandInterface;
class ConsoleController;
class GameController
{
private:
@ -28,6 +31,7 @@ private:
LoginController * loginWindow;
SSaveController * ssave;
ConsoleController * console;
CommandInterface * commandInterface;
public:
class LoginCallback;
class SearchCallback;

View File

@ -71,18 +71,8 @@ void Textbox::TextPosition()
void Textbox::SetText(std::string text)
{
cursor = text.length();
if(masked)
{
char tempText[text.length()];
memset(tempText, 0x8d, text.length());
tempText[text.length()] = 0;
displayText = tempText;
}
else
{
displayText = text;
}
this->text = text;
this->displayText = text;
TextPosition();
}
@ -168,7 +158,17 @@ void Textbox::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool
}
if(changed)
{
SetText(text);
if(masked)
{
char tempText[text.length()];
memset(tempText, 0x8d, text.length());
tempText[text.length()] = 0;
displayText = tempText;
}
else
{
displayText = text;
}
if(actionCallback)
actionCallback->TextChangedCallback(this);
}