Пример #1
0
	BlendEquation::BlendEquation(const variant& node)
		: rgb_(BlendEquationConstants::BE_ADD),
		  alpha_(BlendEquationConstants::BE_ADD)
	{
		if(node.is_map()) {
			if(node.has_key("rgba")) {
				rgb_ = alpha_ = convert_string_to_equation(node["rgba"].as_string());
			} 
			if(node.has_key("rgb")) {
				rgb_ = convert_string_to_equation(node["rgb"].as_string());
			}
			if(node.has_key("alpha")) {
				alpha_ = convert_string_to_equation(node["alpha"].as_string());
			}
			if(node.has_key("a")) {
				alpha_ = convert_string_to_equation(node["a"].as_string());
			}
		} else if(node.is_list()) {
			ASSERT_LOG(node.num_elements() > 0, "When using a list for blend equation must give at least one element");
			if(node.num_elements() == 1) {
				rgb_ = alpha_ = convert_string_to_equation(node[0].as_string());
			} else {
				rgb_   = convert_string_to_equation(node[0].as_string());
				alpha_ = convert_string_to_equation(node[1].as_string());
			}
		} else if(node.is_string()) {
			// simply setting the rgb/alpha values that same, from string
			rgb_ = alpha_ = convert_string_to_equation(node.as_string());
		} else {
			ASSERT_LOG(false, "Unrecognised type for blend equation: " << node.to_debug_string());
		}
	}
Пример #2
0
bool variant::operator<=(const variant& v) const
{
	if(type_ != v.type_) {
		if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) {
			return as_decimal() <= v.as_decimal();
		}

		return type_ < v.type_;
	}

	switch(type_) {
	case TYPE_NULL: {
		return true;
	}

	case TYPE_STRING: {
		return string_->str <= v.string_->str;
	}

	case TYPE_INT: {
		return int_value_ <= v.int_value_;
	}

	case TYPE_DECIMAL: {
		return decimal_value_ <= v.decimal_value_;
	}

	case TYPE_LIST: {
		for(size_t n = 0; n != num_elements() && n != v.num_elements(); ++n) {
			if((*this)[n] < v[n]) {
				return true;
			} else if((*this)[n] > v[n]) {
				return false;
			}
		}

		return num_elements() <= v.num_elements();
	}

	case TYPE_MAP: {
		return map_->elements <= v.map_->elements;
	}

	case TYPE_CALLABLE_LOADING: {
		return false;
	}

	case TYPE_CALLABLE: {
		return !v.callable_->less(callable_);
	}
	}

	assert(false);
	return false;
}
Пример #3
0
bool variant::operator==(const variant& v) const
{
	if(type_ != v.type_) {
		if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) {
			return as_decimal() == v.as_decimal();
		}

		return false;
	}

	switch(type_) {
	case TYPE_NULL: {
		return v.is_null();
	}

	case TYPE_STRING: {
		return string_->str == v.string_->str;
	}

	case TYPE_INT: {
		return int_value_ == v.int_value_;
	}

	case TYPE_DECIMAL: {
		return decimal_value_ == v.decimal_value_;
	}

	case TYPE_LIST: {
		if(num_elements() != v.num_elements()) {
			return false;
		}

		for(size_t n = 0; n != num_elements(); ++n) {
			if((*this)[n] != v[n]) {
				return false;
			}
		}

		return true;
	}

	case TYPE_MAP: {
		return map_->elements == v.map_->elements;
	}

	case TYPE_CALLABLE_LOADING: {
		return false;
	}

	case TYPE_CALLABLE: {
		return callable_->equals(v.callable_);
	}
	case TYPE_FUNCTION: {
		return fn_ == v.fn_;
	}
	}

	assert(false);
	return false;
}
Пример #4
0
	void BlendMode::set(const variant& node) 
	{
		if(node.is_string()) {
			const std::string& blend = node.as_string();
			if(blend == "add") {
				set(BlendModeConstants::BM_ONE, BlendModeConstants::BM_ONE);
			} else if(blend == "alpha_blend") {
				set(BlendModeConstants::BM_SRC_ALPHA, BlendModeConstants::BM_ONE_MINUS_SRC_ALPHA);
			} else if(blend == "colour_blend" || blend == "color_blend") {
				set(BlendModeConstants::BM_SRC_COLOR, BlendModeConstants::BM_ONE_MINUS_SRC_COLOR);
			} else if(blend == "modulate") {
				set(BlendModeConstants::BM_DST_COLOR, BlendModeConstants::BM_ZERO);
			} else if(blend == "src_colour one" || blend == "src_color one") {
				set(BlendModeConstants::BM_SRC_COLOR, BlendModeConstants::BM_ONE);
			} else if(blend == "src_colour zero" || blend == "src_color zero") {
				set(BlendModeConstants::BM_SRC_COLOR, BlendModeConstants::BM_ZERO);
			} else if(blend == "src_colour dest_colour" || blend == "src_color dest_color") {
				set(BlendModeConstants::BM_SRC_COLOR, BlendModeConstants::BM_DST_COLOR);
			} else if(blend == "dest_colour one" || blend == "dest_color one") {
				set(BlendModeConstants::BM_DST_COLOR, BlendModeConstants::BM_ONE);
			} else if(blend == "dest_colour src_colour" || blend == "dest_color src_color") {
				set(BlendModeConstants::BM_DST_COLOR, BlendModeConstants::BM_SRC_COLOR);
			} else {
				ASSERT_LOG(false, "BlendMode: Unrecognised scene_blend mode " << blend);
			}
		} else if(node.is_list() && node.num_elements() >= 2) {
			ASSERT_LOG(node[0].is_string() && node[1].is_string(), 
				"BlendMode: Blend mode must be specified by a list of two strings.");
			set(parse_blend_string(node[0].as_string()), parse_blend_string(node[1].as_string()));
		} else {
			ASSERT_LOG(false, "BlendMode: Setting blend requires either a string or a list of greater than two elements." << node.to_debug_string());
		}
	}
Пример #5
0
	void world::build_fixed(const variant& node)
	{
		for(int n = 0; n != node.num_elements(); ++n) {
			chunk_ptr cp = voxel::chunk_factory::create(shader_, logic_, node[n]);
			int wpx = node[n]["worldspace_position"][0].as_int() * logic_->scale_x();
			int wpy = node[n]["worldspace_position"][1].as_int() * logic_->scale_y();
			int wpz = node[n]["worldspace_position"][2].as_int() * logic_->scale_z();
			chunks_[position(wpx,wpy,wpz)] = cp;
		}
	}
Пример #6
0
void init_tables_for_module(const std::string& module, const variant& doc)
{
	for(int n = 0; n != doc.num_elements(); ++n) {
		variant v = doc[n];
		msg_type_info& info = message_type_index[module][v["name"].as_string()];
		info.name = v["name"].as_string();
		variant tables_v = v["tables"];
		for(int m = 0; m != tables_v.num_elements(); ++m) {
			info.tables.push_back(table_info(tables_v[m]));
		}
	}

	module_definitions[variant(module)] = doc;
}
Пример #7
0
void arrow_primitive::set_points(const variant& points)
{
	ASSERT_LOG(points.is_list(), "arrow points is not a list: " << points.debug_location());

	points_.clear();

	for(int n = 0; n != points.num_elements(); ++n) {
		variant p = points[n];
		ASSERT_LOG(p.is_list() && p.num_elements() == 2, "arrow points in invalid format: " << points.debug_location() << " : " << p.write_json());
		FPoint point;
		point[0] = p[0].as_int();
		point[1] = p[1].as_int();
		points_.push_back(point);
	}
}
Пример #8
0
variant variant_callable::create_for_list(const variant& value) const
{
	std::vector<variant> v;
	for(int n = 0; n != value.num_elements(); ++n) {
		const variant& item = value[n];
		if(item.is_list()) {
			v.push_back(create_for_list(item));
		} else if(item.is_map()) {
			v.push_back(variant(new variant_callable(item)));
		} else {
			v.push_back(item);
		}
	}

	return variant(&v);
}
Пример #9
0
void playable_custom_object::set_player_value_by_slot(int slot, const variant& value)
{
	switch(slot) {
	case CUSTOM_OBJECT_PLAYER_DIFFICULTY:
		difficulty_ = value.as_int();
	break;
	case CUSTOM_OBJECT_PLAYER_CAN_INTERACT:
		can_interact_ = value.as_int();
	break;
	case CUSTOM_OBJECT_PLAYER_UNDERWATER_CONTROLS:
		underwater_controls_ = value.as_bool();
	break;
	case CUSTOM_OBJECT_PLAYER_VERTICAL_LOOK:
		vertical_look_ = value.as_int();
	break;
	case CUSTOM_OBJECT_PLAYER_CONTROL_LOCK:
		if(value.is_null()) {
			control_lock_.reset();
		} else if(value.is_list()) {
			unsigned char state = 0;
			for(int n = 0; n != value.num_elements(); ++n) {
				ASSERT_LOG(value[n].is_string(), "MEMBER OF control_lock LIST NOT A STRING");
				const std::string& str = value[n].as_string();
				int control_key = -1;
				for(int m = 0; m != sizeof(ctrl)/sizeof(*ctrl); ++m) {
					if(ctrl[m] == str) {
						control_key = m;
						break;
					}
				}

				ASSERT_LOG(control_key != -1, "ILLEGAL STRING SET FOR control_lock: '" << str << "' LEGAL KEYS ARE ctrl_(up|down|left|right|attack|jump)");
				state |= 1 << control_key;
			}

			//destroy the old one before creating a new control_lock,
			//since control_lock objects must be constructed and destroyed
			//in FIFO order.
			control_lock_.reset();
			control_lock_.reset(new controls::local_controls_lock(state));
		} else {
			ASSERT_LOG(false, "BAD VALUE WHEN SETTING control_lock KEY. A LIST OR NULL IS REQUIRED: " << value.to_debug_string());
		}
	break;
	}
}
Пример #10
0
variant variant::list_elements_div(const variant& v) const
{
	must_be(TYPE_LIST);
	v.must_be(TYPE_LIST);

	if( num_elements() != v.num_elements() )
		throw type_error("Operator './' requires two lists of the same length");

	std::vector< variant > res;
	res.reserve(num_elements());

	for(size_t i = 0; i < num_elements(); ++i) {
		res.push_back( (*this)[i] / v[i] );
	}

	return variant( &res );
}
Пример #11
0
//commandline=true when we evaluate formula from commandline, false otherwise (default)
variant formula_ai::execute_variant(const variant& var, ai_context &ai_, bool commandline)
{
	std::stack<variant> vars;
	if(var.is_list()) {
		for(size_t n = 1; n <= var.num_elements() ; ++n) {
			vars.push(var[ var.num_elements() - n ]);
		}
	} else {
		vars.push(var);
	}

	std::vector<variant> made_moves;

	variant error;

	unit_map& units = *resources::units;

	while( !vars.empty() ) {

		if(vars.top().is_null()) {
			vars.pop();
			continue;
		}

		variant action = vars.top();
		vars.pop();

		game_logic::safe_call_callable* safe_call = try_convert_variant<game_logic::safe_call_callable>(action);

		if(safe_call) {
		    action = safe_call->get_main();
		}

		const move_callable* move = try_convert_variant<move_callable>(action);
		const move_partial_callable* move_partial = try_convert_variant<move_partial_callable>(action);
		const attack_callable* attack = try_convert_variant<attack_callable>(action);
		const attack_analysis* _attack_analysis = try_convert_variant<attack_analysis>(action);
		const recruit_callable* recruit_command = try_convert_variant<recruit_callable>(action);
		const recall_callable* recall_command = try_convert_variant<recall_callable>(action);
		const set_var_callable* set_var_command = try_convert_variant<set_var_callable>(action);
		const set_unit_var_callable* set_unit_var_command = try_convert_variant<set_unit_var_callable>(action);
		const fallback_callable* fallback_command = try_convert_variant<fallback_callable>(action);

		if( move || move_partial ) {
			move_result_ptr move_result;

			if(move)
				move_result = ai_.execute_move_action(move->src(), move->dst(), true);
			else
				move_result = ai_.execute_move_action(move_partial->src(), move_partial->dst(), false);

			if ( !move_result->is_ok() ) {
				if( move ) {
					LOG_AI << "ERROR #" << move_result->get_status() << " while executing 'move' formula function\n" << std::endl;

					if(safe_call) {
						//safe_call was called, prepare error information
						error = variant(new safe_call_result(move,
									move_result->get_status(), move_result->get_unit_location()));
					}
				} else {
					LOG_AI << "ERROR #" << move_result->get_status() << " while executing 'move_partial' formula function\n" << std::endl;

					if(safe_call) {
						//safe_call was called, prepare error information
						error = variant(new safe_call_result(move_partial,
									move_result->get_status(), move_result->get_unit_location()));
					}
				}
			}

			if( move_result->is_gamestate_changed() )
				made_moves.push_back(action);
		} else if(attack) {
			bool gamestate_changed = false;
			move_result_ptr move_result;

			if( attack->move_from() != attack->src() ) {
				move_result = ai_.execute_move_action(attack->move_from(), attack->src(), false);
				gamestate_changed |= move_result->is_gamestate_changed();

				if (!move_result->is_ok()) {
					//move part failed
					LOG_AI << "ERROR #" << move_result->get_status() << " while executing 'attack' formula function\n" << std::endl;

					if(safe_call) {
						//safe_call was called, prepare error information
						error = variant(new safe_call_result(attack,
								move_result->get_status(), move_result->get_unit_location()));
					}
				}
			}

			if (!move_result || move_result->is_ok() ) {
				//if move wasn't done at all or was done successfully
				attack_result_ptr attack_result = ai_.execute_attack_action(attack->src(), attack->dst(), attack->weapon() );
				gamestate_changed |= attack_result->is_gamestate_changed();
				if (!attack_result->is_ok()) {
					//attack failed

					LOG_AI << "ERROR #" << attack_result->get_status() << " while executing 'attack' formula function\n" << std::endl;

					if(safe_call) {
						//safe_call was called, prepare error information
						error = variant(new safe_call_result(attack, attack_result->get_status()));
					}
				}
			}

			if (gamestate_changed) {
			      made_moves.push_back(action);
			}
		} else if(_attack_analysis) {
			//If we get an attack analysis back we will do the first attack.
			//Then the AI can get run again and re-choose.
			assert(_attack_analysis->movements.empty() == false);

			//make sure that unit which has to attack is at given position and is able to attack
			unit_map::const_iterator unit = units.find(_attack_analysis->movements.front().first);
			if (!unit.valid() || unit->attacks_left() == 0)
				continue;

			const map_location& move_from = _attack_analysis->movements.front().first;
			const map_location& att_src = _attack_analysis->movements.front().second;
			const map_location& att_dst = _attack_analysis->target;

			//check if target is still valid
			unit = units.find(att_dst);
			if ( unit == units.end() )
				continue;

                        //check if we need to move
                        if( move_from != att_src ) {
                            //now check if location to which we want to move is still unoccupied
				unit = units.find(att_src);
				if ( unit != units.end() ) {
					continue;
				}

				ai_.execute_move_action(move_from, att_src);
                        }

			if(units.count(att_src)) {
				ai_.execute_attack_action(_attack_analysis->movements.front().second,_attack_analysis->target,-1);
			}
			made_moves.push_back(action);
		} else if(recall_command) {

			recall_result_ptr recall_result = ai_.check_recall_action(recall_command->id(), recall_command->loc());

			if( recall_result->is_ok() ) {
				recall_result->execute();
			}

			if (!recall_result->is_ok()) {

				if(safe_call) {
					//safe call was called, prepare error information
					error = variant(new safe_call_result(recall_command,
									recall_result->get_status()));

					LOG_AI << "ERROR #" <<recall_result->get_status() << " while executing 'recall' formula function\n"<<std::endl;
				} else {
					ERR_AI << "ERROR #" <<recall_result->get_status() << " while executing 'recall' formula function\n"<<std::endl;
				}
			}

			if( recall_result->is_gamestate_changed() ) {
				made_moves.push_back(action);
			}

		} else if(recruit_command) {
			recruit_result_ptr recruit_result = ai_.check_recruit_action(recruit_command->type(), recruit_command->loc());

			//is_ok()==true means that the action is successful (eg. no unexpected events)
			//is_ok() must be checked or the code will complain :)
			if( recruit_result->is_ok() )
				recruit_result->execute();

			if (!recruit_result->is_ok()) {

				if(safe_call) {
					//safe call was called, prepare error information
					error = variant(new safe_call_result(recruit_command,
									recruit_result->get_status()));

					LOG_AI << "ERROR #" <<recruit_result->get_status() << " while executing 'recruit' formula function\n"<<std::endl;
				} else {
					ERR_AI << "ERROR #" <<recruit_result->get_status() << " while executing 'recruit' formula function\n"<<std::endl;
				}
			}

			//is_gamestate_changed()==true means that the game state was somehow changed by action.
			//it is believed that during a turn, a game state can change only a finite number of times
			if( recruit_result->is_gamestate_changed() )
				made_moves.push_back(action);

		} else if(set_var_command) {
			if( infinite_loop_guardian_.set_var_check() ) {
				LOG_AI << "Setting variable: " << set_var_command->key() << " -> " << set_var_command->value().to_debug_string() << "\n";
				vars_.add(set_var_command->key(), set_var_command->value());
				made_moves.push_back(action);
			} else {
				//too many calls in a row - possible infinite loop
				ERR_AI << "ERROR #" << 5001 << " while executing 'set_var' formula function" << std::endl;

				if( safe_call )
					error = variant(new safe_call_result(set_var_command, 5001));
			}
		} else if(set_unit_var_command) {
			int status = 0;
			unit_map::iterator unit;

			if( !infinite_loop_guardian_.set_unit_var_check() ) {
			    status = 5001; //exceeded nmber of calls in a row - possible infinite loop
			} else if( (unit = units.find(set_unit_var_command->loc())) == units.end() ) {
			    status = 5002; //unit not found
			} else if (unit->side() != get_side()) {
			    status = 5003;//unit does not belong to our side
			}

			if( status == 0 ){
				LOG_AI << "Setting unit variable: " << set_unit_var_command->key() << " -> " << set_unit_var_command->value().to_debug_string() << "\n";
				unit->formula_manager().add_formula_var(set_unit_var_command->key(), set_unit_var_command->value());
				made_moves.push_back(action);
			} else {
				ERR_AI << "ERROR #" << status << " while executing 'set_unit_var' formula function" << std::endl;
				if(safe_call)
				    error = variant(new safe_call_result(set_unit_var_command,
									status));
			}

		} else if( action.is_string() && action.as_string() == "recruit") {
			stage_ptr r = get_recruitment(ai_);
			if (r) {
				if (r->play_stage()) {
					made_moves.push_back(action);
				}
			}
		} else if( action.is_string() && action.as_string() == "continue") {
			if( infinite_loop_guardian_.continue_check() ) {
				made_moves.push_back(action);
			} else {
				//too many calls in a row - possible infinite loop
				ERR_AI << "ERROR #" << 5001 << " while executing 'continue' formula keyword" << std::endl;

				if( safe_call )
					error = variant(new safe_call_result(NULL, 5001));
			}
		} else if( action.is_string() && (action.as_string() == "end_turn" || action.as_string() == "end" )  ) {
			return variant();
		} else if(fallback_command) {
			if(get_recursion_count()<recursion_counter::MAX_COUNTER_VALUE) {
				if(fallback_command->key() == "human")
				{
					//we want give control of the side to human for the rest of this turn
					throw fallback_ai_to_human_exception();
				} else
				{
					LOG_AI << "Explicit fallback to: " << fallback_command->key() << std::endl;
					ai_ptr fallback( manager::create_transient_ai(fallback_command->key(), config(), &ai_));
					if(fallback) {
						fallback->play_turn();
					}
				}
			}
			return variant();
		} else {
			//this information is unneded when evaluating formulas form commandline
			if (!commandline) {
				ERR_AI << "UNRECOGNIZED MOVE: " << action.to_debug_string() << std::endl;
			}
		}

		if( safe_call && (error != variant() || made_moves.empty() || made_moves.back() != action) ){
		    /*if we have safe_call formula and either error occurred, or current action
		     *was not reckognized, then evaluate backup formula from safe_call and execute it
		     *during the next loop
		     */

			game_logic::map_formula_callable callable(this);
			callable.add_ref();

			if(error != variant())
				callable.add("error", error);

			variant backup_result = safe_call->get_backup()->evaluate(callable);

			if(backup_result.is_list()) {
				for(size_t n = 1; n <= backup_result.num_elements() ; ++n) {
					vars.push(backup_result[ backup_result.num_elements() - n ]);
				}
			} else {
				vars.push(backup_result);
			}

			//store the result in safe_call_callable case we would like to display it to the user
			//for example if this formula was executed from commandline
			safe_call->set_backup_result(backup_result);

			error = variant();
		}
	}

	return variant(&made_moves);
}