1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

* partially done OB receiver

* minor structure imprevements
This commit is contained in:
mateuszb
2011-05-15 18:21:07 +00:00
parent 17290d4f0d
commit 4eef7aa83b
3 changed files with 227 additions and 48 deletions

View File

@@ -569,31 +569,86 @@ ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const
//code execution
struct VRPerformer;
struct VR_SPerformer : boost::static_visitor<>
{
VRPerformer & owner;
explicit VR_SPerformer(VRPerformer & _owner);
void operator()(TVarConcatString const& cmp) const;
void operator()(TStringConstant const& cmp) const;
void operator()(TCurriedString const& cmp) const;
void operator()(TSemiCompare const& cmp) const;
void operator()(TMacroUsage const& cmp) const;
void operator()(TMacroDef const& cmp) const;
void operator()(TIexp const& cmp) const;
void operator()(TVarpExp const& cmp) const;
void operator()(spirit::unused_type const& cmp) const;
template<typename OwnerType>
struct StandardBodyOptionItemVisitor : boost::static_visitor<>
{
OwnerType & owner;
explicit StandardBodyOptionItemVisitor(OwnerType & _owner) : owner(_owner)
{}
virtual void operator()(TVarConcatString const& cmp) const
{
throw EScriptExecError("String concatenation not allowed in this receiver");
}
virtual void operator()(TStringConstant const& cmp) const
{
throw EScriptExecError("String constant not allowed in this receiver");
}
virtual void operator()(TCurriedString const& cmp) const
{
throw EScriptExecError("Curried string not allowed in this receiver");
}
virtual void operator()(TSemiCompare const& cmp) const
{
throw EScriptExecError("Semi comparison not allowed in this receiver");
}
virtual void operator()(TMacroUsage const& cmp) const
{
throw EScriptExecError("Macro usage not allowed in this receiver");
}
virtual void operator()(TMacroDef const& cmp) const
{
throw EScriptExecError("Macro definition not allowed in this receiver");
}
virtual void operator()(TIexp const& cmp) const
{
throw EScriptExecError("i-expression not allowed in this receiver");
}
virtual void operator()(TVarpExp const& cmp) const
{
throw EScriptExecError("Varp expression not allowed in this receiver");
}
virtual void operator()(spirit::unused_type const& cmp) const
{
throw EScriptExecError("\'Nothing\' not allowed in this receiver");
}
};
struct VRPerformer : boost::static_visitor<>
template<typename T>
struct StandardReceiverVisitor : boost::static_visitor<>
{
ERMInterpreter * interp;
IexpValStr identifier;
VRPerformer(ERMInterpreter * _interpr, IexpValStr ident) : interp(_interpr), identifier(ident)
T identifier;
StandardReceiverVisitor(ERMInterpreter * _interpr, T ident) : interp(_interpr), identifier(ident)
{}
void operator()(TVRLogic const& trig) const
virtual void operator()(TVRLogic const& trig) const
{
throw EScriptExecError("VR logic not allowed in this receiver!");
}
virtual void operator()(TVRArithmetic const& trig) const
{
throw EScriptExecError("VR arithmetic not allowed in this receiver!");
}
virtual void operator()(TNormalBodyOption const& trig) const = 0;
};
struct VR_SPerformer : StandardBodyOptionItemVisitor<VRPerformer>
{
explicit VR_SPerformer(VRPerformer & _owner);
using StandardBodyOptionItemVisitor<VRPerformer>::operator();
void operator()(TStringConstant const& cmp) const OVERRIDE;
void operator()(TMacroUsage const& cmp) const OVERRIDE;
void operator()(TIexp const& cmp) const OVERRIDE;
};
struct VRPerformer : StandardReceiverVisitor<IexpValStr>
{
VRPerformer(ERMInterpreter * _interpr, IexpValStr ident) : StandardReceiverVisitor(_interpr, ident)
{}
void operator()(TVRLogic const& trig) const OVERRIDE
{
int valr = interp->getIexp(trig.var).getInt();
switch (trig.opcode)
@@ -612,7 +667,7 @@ struct VRPerformer : boost::static_visitor<>
break;
}
}
void operator()(TVRArithmetic const& trig) const
void operator()(TVRArithmetic const& trig) const OVERRIDE
{
IexpValStr rhs = interp->getIexp(trig.rhs);
switch (trig.opcode)
@@ -641,6 +696,26 @@ struct VRPerformer : boost::static_visitor<>
{
switch(trig.optionCode)
{
case 'C': //setting/checking v vars
{
//TODO
}
break;
case 'H': //checking if string is empty
{
//TODO
}
break;
case 'M': //string operations
{
//TODO
}
break;
case 'R': //random variables
{
//TODO
}
break;
case 'S': //setting variable
{
if(trig.params.size() == 1)
@@ -652,57 +727,113 @@ struct VRPerformer : boost::static_visitor<>
throw EScriptExecError("VR receiver S option takes exactly 1 parameter!");
}
break;
case 'T': //random variables
{
//TODO
}
break;
case 'U': //search for a substring
{
//TODO
}
break;
case 'V': //convert string to value
{
//TODO
}
break;
default:
//not supported or not allowed
throw EScriptExecError("Wrong VR receiver option!");
break;
}
}
};
VR_SPerformer::VR_SPerformer(VRPerformer & _owner) : owner(_owner)
VR_SPerformer::VR_SPerformer(VRPerformer & _owner) : StandardBodyOptionItemVisitor(_owner)
{}
void VR_SPerformer::operator()(ERM::TIexp const& trig) const
{
owner.identifier.setTo(owner.interp->getIexp(trig));
}
void VR_SPerformer::operator()(TVarConcatString const& cmp) const
{
throw EScriptExecError("String concatenation not allowed in VR S");
}
void VR_SPerformer::operator()(TStringConstant const& cmp) const
{
owner.identifier.setTo(cmp.str);
}
void VR_SPerformer::operator()(TCurriedString const& cmp) const
{
throw EScriptExecError("Curried string not allowed in VR S");
}
void VR_SPerformer::operator()(TSemiCompare const& cmp) const
{
throw EScriptExecError("Incomplete comparison not allowed in VR S");
}
void VR_SPerformer::operator()(TMacroUsage const& cmp) const
{
owner.identifier.setTo(owner.interp->getIexp(cmp));
}
void VR_SPerformer::operator()(TMacroDef const& cmp) const
{
throw EScriptExecError("Macro definition not allowed in VR S");
}
void VR_SPerformer::operator()(TVarpExp const& cmp) const
{
throw EScriptExecError("Write-only variable expression not allowed in VR S");
}
void VR_SPerformer::operator()(spirit::unused_type const& cmp) const
{
throw EScriptExecError("Expression not allowed in VR S");
}
struct ConditionDisemboweler;
struct OBPerformer : StandardReceiverVisitor<int3>
{
OBPerformer(ERMInterpreter * _interpr, int3 objPos) : StandardReceiverVisitor(_interpr, objPos)
{}
using StandardReceiverVisitor<int3>::operator(); //it removes compilation error... not sure why it *must* be here
void operator()(TNormalBodyOption const& trig) const
{
switch(trig.optionCode)
{
case 'B': //removes description hint
{
//TODO
}
break;
case 'C': //sgc of control word of object
{
//TODO
}
break;
case 'D': //disable gamer to use object
{
//TODO
}
break;
case 'E': //enable gamer to use object
{
//TODO
}
break;
case 'H': //replace hint for object
{
//TODO
}
break;
case 'M': //disabling messages and questions
{
//TODO
}
break;
case 'R': //eable all gamers to use object
{
//TODO
}
break;
case 'S': //disable all gamers to use object
{
//TODO
}
break;
case 'T': //sgc of obj type
{
//TODO
}
break;
case 'U': //sgc of obj subtype
{
//TODO
}
break;
default:
throw EScriptExecError("Wrong OB receiver option!");
break;
}
}
};
struct ERMExpDispatch : boost::static_visitor<>
{
@@ -781,6 +912,46 @@ struct ERMExpDispatch : boost::static_visitor<>
}
}
}
else if(trig.name == "OB")
{
int3 objPos;
if(trig.identifier.is_initialized())
{
ERM::Tidentifier tid = trig.identifier.get();
switch(tid.size())
{
case 1:
{
int num = owner->getIexp(tid[0]).getInt();
objPos = int3(owner->ermGlobalEnv->getStandardVar(num),
owner->ermGlobalEnv->getStandardVar(num+1),
owner->ermGlobalEnv->getStandardVar(num+2));
}
break;
case 3:
objPos = int3(owner->getIexp(tid[0]).getInt(),
owner->getIexp(tid[1]).getInt(),
owner->getIexp(tid[2]).getInt());
break;
default:
throw EScriptExecError("OB receiver takes 1 or 3 items in identifier!");
break;
}
//execute body
if(trig.body.is_initialized())
{
ERM::Tbody bo = trig.body.get();
for(int g=0; g<bo.size(); ++g)
{
boost::apply_visitor(OBPerformer(owner, objPos), bo[g]);
}
}
else
throw EScriptExecError("OB receiver must have body!");
}
else
throw EScriptExecError("OB receiver must have an identifier!");
}
else
{
//unsupported or invalid trigger
@@ -1307,6 +1478,13 @@ int ERMInterpreter::getRealLine(int lineNum)
return -1;
}
void ERMInterpreter::setCurrentlyVisitedObj( int3 pos )
{
ermGlobalEnv->getStandardVar(998) = pos.x;
ermGlobalEnv->getStandardVar(999) = pos.y;
ermGlobalEnv->getStandardVar(1000) = pos.z;
}
const std::string ERMInterpreter::triggerSymbol = "trigger";
const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
const std::string ERMInterpreter::defunSymbol = "defun";

View File

@@ -160,7 +160,7 @@ namespace VERMInterpreter
{
ERMEnvironment();
static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
int & getQuickVar(const char letter);
int & getQuickVar(const char letter); //'f' - 't' variables
int & getStandardVar(int num); //get v-variable
std::string & getZVar(int num);
bool & getFlag(int num);
@@ -515,6 +515,7 @@ public:
void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector<int> &funParams=std::vector<int>()); //use this to run triggers
void executeTriggerType(const char *trigger, int id); //convenience version of above, for pre-trigger when there is only one argument
void executeTriggerType(const char *trigger); //convenience version of above, for pre-trigger when there are no args
void setCurrentlyVisitedObj(int3 pos); //sets v998 - v1000 to given value
void init(); //sets up environment etc.
void scanForScripts();

View File

@@ -35,7 +35,7 @@ void CERMScriptModule::heroVisit(const CGHeroInstance *visitor, const CGObjectIn
{
if(!visitedObj)
return;
interpreter->setCurrentlyVisitedObj(visitedObj->pos);
ERMInterpreter::TIDPattern tip;
tip[1] = list_of(visitedObj->ID);
tip[2] = list_of(visitedObj->ID)(visitedObj->subID);