bool stage_unit_formulas::do_play_stage()
{
	//execute units formulas first
	wfl::unit_formula_set units_with_formulas;

	unit_map &units_ = resources::gameboard->units();

	for(unit_map::unit_iterator i = units_.begin() ; i != units_.end() ; ++i)
	{
		if (i->side() == get_side()) {
			if (i->formula_manager().has_formula() || i->formula_manager().has_loop_formula()) {
				int priority = 0;
				if (i->formula_manager().has_priority_formula()) {
					try {
						wfl::const_formula_ptr priority_formula(fai_.create_optional_formula(i->formula_manager().get_priority_formula()));
						if (priority_formula) {
							wfl::map_formula_callable callable(fai_.fake_ptr());
							callable.add("me", wfl::variant(std::make_shared<wfl::unit_callable>(*i)));
							priority = (wfl::formula::evaluate(priority_formula, callable)).as_int();
						} else {
							WRN_AI << "priority formula skipped, maybe it's empty or incorrect"<< std::endl;
						}
					} catch(wfl::formula_error& e) {
						if(e.filename == "formula")
							e.line = 0;
						fai_.handle_exception( e, "Unit priority formula error for unit: '" + i->type_id() + "' standing at (" + std::to_string(i->get_location().wml_x()) + "," + std::to_string(i->get_location().wml_y()) + ")");

						priority = 0;
					} catch(wfl::type_error& e) {
						priority = 0;
						ERR_AI << "formula type error while evaluating unit priority formula  " << e.message << std::endl;
					}
				}

				units_with_formulas.insert( wfl::unit_formula_pair( i, priority ) );
			}
		}
        }

	for(wfl::unit_formula_set::iterator pair_it = units_with_formulas.begin() ; pair_it != units_with_formulas.end() ; ++pair_it)
	{
		unit_map::iterator i = pair_it->first;

		if( i.valid() ) {

			if (i->formula_manager().has_formula()) {
				try {
					wfl::const_formula_ptr formula(fai_.create_optional_formula(i->formula_manager().get_formula()));
					if (formula) {
						wfl::map_formula_callable callable(fai_.fake_ptr());
						callable.add("me", wfl::variant(std::make_shared<wfl::unit_callable>(*i)));
						fai_.make_action(formula, callable);
					} else {
						WRN_AI << "unit formula skipped, maybe it's empty or incorrect" << std::endl;
					}
				}
				catch(wfl::formula_error& e) {
					if(e.filename == "formula") {
						e.line = 0;
					}
					fai_.handle_exception( e, "Unit formula error for unit: '" + i->type_id() + "' standing at (" + std::to_string(i->get_location().wml_x()) + "," + std::to_string(i->get_location().wml_y()) + ")");
				}
			}
		}

		if( i.valid() ) {
			if (i->formula_manager().has_loop_formula())
			{
				try {
					wfl::const_formula_ptr loop_formula(fai_.create_optional_formula(i->formula_manager().get_loop_formula()));
					if (loop_formula) {
						wfl::map_formula_callable callable(fai_.fake_ptr());
						callable.add("me", wfl::variant(std::make_shared<wfl::unit_callable>(*i)));
						while ( !fai_.make_action(loop_formula, callable).is_empty() && i.valid() )
						{
						}
					} else {
						WRN_AI << "Loop formula skipped, maybe it's empty or incorrect" << std::endl;
					}
				} catch(wfl::formula_error& e) {
					if (e.filename == "formula") {
						e.line = 0;
					}
					fai_.handle_exception( e, "Unit loop formula error for unit: '" + i->type_id() + "' standing at (" + std::to_string(i->get_location().wml_x()) + "," + std::to_string(i->get_location().wml_y()) + ")");
				}
			}
		}
	}
	return false;
}
bool stage_unit_formulas::do_play_stage()
{
	//execute units formulas first
	game_logic::unit_formula_set units_with_formulas;

	unit_map &units_ = get_info().units;

	for(unit_map::unit_iterator i = units_.begin() ; i != units_.end() ; ++i)
	{
		if ( (i->second.side() == get_side())  ) {
			if ( i->second.has_formula() || i->second.has_loop_formula()) {
				int priority = 0;
				if( i->second.has_priority_formula() ) {
					try {
						game_logic::const_formula_ptr priority_formula(fai_.create_optional_formula(i->second.get_priority_formula()));
						if (priority_formula) {
							game_logic::map_formula_callable callable(&fai_);
							callable.add_ref();
							callable.add("me", variant(new unit_callable(*i)));
							priority = (game_logic::formula::evaluate(priority_formula, callable)).as_int();
						} else {
							WRN_AI << "priority formula skipped, maybe it's empty or incorrect"<< std::endl;
						}
					} catch(game_logic::formula_error& e) {
						if(e.filename == "formula")
							e.line = 0;
						fai_.handle_exception( e, "Unit priority formula error for unit: '" + i->second.type_id() + "' standing at (" + boost::lexical_cast<std::string>(i->first.x+1) + "," + boost::lexical_cast<std::string>(i->first.y+1) + ")");

						priority = 0;
					} catch(type_error& e) {
						priority = 0;
						ERR_AI << "formula type error while evaluating unit priority formula  " << e.message << "\n";
					}
				}

				units_with_formulas.insert( game_logic::unit_formula_pair( i, priority ) );
			}
		}
        }

	for(game_logic::unit_formula_set::iterator pair_it = units_with_formulas.begin() ; pair_it != units_with_formulas.end() ; ++pair_it)
	{
		unit_map::iterator i = pair_it->first;

		if( i.valid() ) {

			if ( i->second.has_formula() ) {
				try {
					game_logic::const_formula_ptr formula(fai_.create_optional_formula(i->second.get_formula()));
					if (formula) {
						game_logic::map_formula_callable callable(&fai_);
						callable.add_ref();
						callable.add("me", variant(new unit_callable(*i)));
						fai_.make_action(formula, callable);
					} else {
						WRN_AI << "unit formula skipped, maybe it's empty or incorrect" << std::endl;
					}
				}
				catch(game_logic::formula_error& e) {
					if(e.filename == "formula") {
						e.line = 0;
					}
					fai_.handle_exception( e, "Unit formula error for unit: '" + i->second.type_id() + "' standing at (" + boost::lexical_cast<std::string>(i->first.x+1) + "," + boost::lexical_cast<std::string>(i->first.y+1) + ")");
				}
			}
		}

		if( i.valid() ) {
			if( i->second.has_loop_formula() )
			{
				try {
					game_logic::const_formula_ptr loop_formula(fai_.create_optional_formula(i->second.get_loop_formula()));
					if (loop_formula) {
						game_logic::map_formula_callable callable(&fai_);
						callable.add_ref();
						callable.add("me", variant(new unit_callable(*i)));
						while ( !fai_.make_action(loop_formula, callable).is_empty() && i.valid() )
						{
						}
					} else {
						WRN_AI << "Loop formula skipped, maybe it's empty or incorrect" << std::endl;
					}
				} catch(game_logic::formula_error& e) {
					if (e.filename == "formula") {
						e.line = 0;
					}
					fai_.handle_exception( e, "Unit loop formula error for unit: '" + i->second.type_id() + "' standing at (" + boost::lexical_cast<std::string>(i->first.x+1) + "," + boost::lexical_cast<std::string>(i->first.y+1) + ")");
				}
			}
		}
	}
	return false;
}