tags:

views:

296

answers:

8

I am creating a game that lets the player enter input, changes some states, then checks if a "goal value" is true (obviously this description is muchly simplified), and I want to be able to have that goal value be anything from if the players life is below a certain value to if the amount of enemies remaining is equal to zero. Is there any "expression class" that can hold a simple "value1 compare-operator value2" and check it? ie:

expression goal(x = 4);

if not, does anybody have any suggestions as to how I could develop an expression class?

EDIT: another (more towards what I am trying to achieve) example:

game.init(){ expression goal = FileRead(goalfile); }
game.checkstate(){ if(goal) exit(1); } //exit 1 is the games win state

//another more specific eg.:
class level1 { public: expression goal(total_enemies == 0); };
class level2 { public: expression goal(player.x == goal.x && player.y == goal.y); };
A: 

No, there isn't anything like that. Perhaps an expression class is a little too abstract. What about defining various Goal classes with an IsReached() method?

Peter Ruderman
A: 

C++ doesn't have this as part of the language -- there is no way to, at runtime, get access to the same stuff that parsed your program.

I'm sure there are numerous third-party arithmetic parser libraries you could use, however.

Jacob B
I don't think that's what he meant.
dss539
+5  A: 

Update: Dynamic vs. static expressions

If you want to input a string and built an expression from that (i.e. dynamically), you could look at embedding a scripting language (I don't know of any expression-only languages), such as Lua or Python. That keeps you from having to write your own parser, AST and evaluator. IIRC there's no thing in raw c++ nor in any easy lib.

For static expressions (known at compile time) you could look at function and bind, either in Boost or TR1 (available in recent compilers)

Also, Boost.Lambda might help here, to allow you to construct and store expressions for later evaluation. However, if you're not familiar with C++ and templates (or functional programming), it will likely scare you quite a bit.

With that you could write

using namespace boost::lambda;
boost::function<bool (int, int)> myexpr1 = (_1 + _2) > 20;
boost::function<bool (int, int)> myexpr2 = (_1 * _2) > 42;
std::cout << myexpr1(4,7) << " " << myexpr2(2,5);

with bind, it'd look like:

boost::function<bool (Player*)> check = bind(&Player::getHealth, _1) > 20;
Player p1;
if (check(p1)) { dostuff(); }

check = bind(&Player::getGold, _1) < 42;
if (check(p1)) { doOtherStuff(); }
Marcus Lindblom
unfortunately, this is entirely impractical for arbitrary expressions. Which i think is what the poster really wants (despite his example being of "val1 op val2").
Evan Teran
Is it? Using boost::lambda you can combine all sorts of expressions, and even statements and all. What do you mean?
Marcus Lindblom
well, since the boost lambdas are constructed at compile time and just used by the caller. what would you do if the user entered an op combination that you haven't accounted for. Since there is an infinite number of combinations of math operations...certainly you can't statically account for them all.
Evan Teran
ah.. I didn't see that the OP wanted to construct expressions dynamically. It's a bit unclear. I'll edit my post.
Marcus Lindblom
A: 

I'm thinking you can define your own class and work around using the 'assert' keyword, but I may have understood the question wrong.

http://www.cplusplus.com/reference/clibrary/cassert/assert/

Suvesh Pratapa
A: 

Why not build your own expression classes?

class GoalBase
{
    virtual bool goal() = 0;
};

class Enemies : public GoalBase 
{
   // ..
   private:
      int enemies_;

   public:
      Enemies(int start) : enemies_(start) {}
      void kill() { if (enemies_) --enemies_; }
      bool goal() { return enemies_ == 0; }
};

int main()
{
    Enemies enemiesToKill(5);
    enemiesToKill.kill();    

    // ..
    if (enemiesToKill.goal()) {
        // ..
    }

    return 0;
}

Other classes could have other methods, parameters, operators etc. Use your imagination.

Magnus Skog
A: 

There don't seem to be all that many recognised expression evaluation libraries for C++. I wrote my own for CSVfix which you can persuse by looking at the a_expr.h and a_expr.cpp files in the ALib library that forms part of the CSVfix source. The evaluator has not a great deal to recommend itself, except that it does the job and is (IMHO) fairly simple to understand.

Unfurtunately, there is currently no public documentation for the evaluator, and by my own rule of thumb, that which is not documented cannot be reused. However, the unit tests show how it can be used, and the source may give you some ideas on implementing your own evaluator, should the fancy take you.

anon
+2  A: 

There is no standard way to compile expressions during runtime. You'll have to do it some other way.

You might consider using a scripting language, like Lua or Python, and embed it in your C++. That would allow your players the ability to program to the extent you want them to.

David Thornley
+1 for Lua recommendation. Lua is becoming almost ubiquitous as the lightweight embeddable engine of choice for games and mobile devices.
Mike Ellery
A: 

There's no standard way to do it in C++. One solution is to write your own parser.

Another solution, that I'd recommend: embed a Lua interpreter in your program. Lua is a simple yet powerful programming language, that also has an extremely lightweight (<300kB) and easy-to-use interpreter. Read an introductory article here: http://www.ibm.com/developerworks/linux/library/l-embed-lua/index.html

Having Lua embedded in your game has a number of nice side advantages:

  • you can use it as a powerful configuration language for your game
  • with Lua, you can easily create a command-line interactive environment, which is nice for testing and experiements. For example, you will be able to change the game engine parameters and see the effect immediately, without recompiling. That's especially convenient for "researchy" projects or game programming.
Igor Krivokon