Exemple #1
0
//-------- Begin of function Town::think_spying_town --------//
//
// Think about planting spies into independent towns and enemy towns.
//
int Town::think_spying_town()
{
	int majorityRace = majority_race();

	//---- don't recruit spy if we are low in cash or losing money ----//

	Nation* ownNation = nation_array[nation_recno];

	if( ownNation->total_population < 30-ownNation->pref_spy/10 )		// don't use spies if the population is too low, we need to use have people to grow population
		return 0;

	if( ownNation->total_spy_count > ownNation->total_population * (10+ownNation->pref_spy/5) / 100 )		// 10% to 30%
		return 0;

	if( !ownNation->ai_should_spend(ownNation->pref_spy/2) )		// 0 to 50
		return 0;

	//--- pick minority units first (also for increasing town harmony) ---//

	for( int raceId=1 ; raceId<=MAX_RACE ; raceId++ )
	{
		if( race_pop_array[raceId-1]==0 || raceId==majorityRace )
			continue;

		if( !can_recruit(raceId) )
			continue;

		if( think_spying_town_assign_to(raceId) )
			return 1;
	}

	//---- then think about assign spies of majority race ----//

	if( ownNation->pref_spy > 50 )		// only if pref_spy is > 50, it will consider using spies of majority race
	{
		if( can_recruit(majorityRace) )
		{
			if( think_spying_town_assign_to(majorityRace) )
				return 1;
		}
	}

	return 0;
}
Exemple #2
0
//--------- Begin of function FirmCamp::disp_camp_info ---------//
//
void FirmFort::disp_camp_info(int dispY1, int refreshFlag)
{
	FirmCamp::disp_camp_info(dispY1, refreshFlag);

	// ----- display train button -------//

	int x2 = INFO_X1 +13;
	int y2 = INFO_Y1 +281;
	if (!is_monster())
		button_train.create( INFO_X1+13, INFO_Y1+281, 'A', "TRAIN" );
	else
		button_train.create( INFO_X1+13, INFO_Y1+281, 'A', "F_TRAIN" );

	// scan any available population to train

	// ##### begin Gilbert 23/12 #######//
	if( (button_train.visible_flag = is_own()) )
	{
		button_train.enable_flag = can_recruit(active_link_town_recno);
		button_train.paint();
	}
	// ##### end Gilbert 23/12 #######//

	// ------- display tower count -----//

	button_tower_count.create( INFO_X1+13+3*BUTTON_DISTANCE+6, INFO_Y1+235+6,
		INFO_X1+13+3*BUTTON_DISTANCE+6+TOWER_COUNT_BUTTON_WIDTH-1,
		INFO_Y1+235+6+TOWER_COUNT_BUTTON_HEIGHT-1,
		disp_tower_count, ButtonCustomPara( NULL, 0 ) );

//#ifdef DEBUG
	// BUGHERE : ARM_TOWERS is longer than 8 characters
	// button_tower_count.set_help_code("ARM_TOWERS");
	button_tower_count.set_help_code("ARM_TOWE");
//#endif

	button_tower_count.enable_flag = is_own();
	button_tower_count.custom_para = ButtonCustomPara( NULL, target_archer_count );
	button_tower_count.paint();

	// ------- display towers ----------//

	err_when( !image_spict.read_all );			// must read_all
	char *towerFull = image_spict.read("TOWER-F");
	char *towerEmpty = image_spict.read("TOWER-E");
	char *towerBuilding = image_spict.read("TOWER-D");
	int towerHeight = ((Bitmap *)towerFull)->get_height();
	err_when( ((Bitmap *)towerEmpty)->get_height() != towerHeight );
	err_when( ((Bitmap *)towerBuilding)->get_height() != towerHeight );
	int towerWidth = ((Bitmap *)towerFull)->get_width();

//	static int towerXTable[MAX_FORT_ARCHER] = { 180, 202, 191, 180, 202 };
//	static int towerYTable[MAX_FORT_ARCHER] = { 280, 280, 292, 304, 304 };
	static int towerXTable[MAX_FORT_ARCHER] = { 180, 202, 191, 180, 202 };
	static int towerYTable[MAX_FORT_ARCHER] = { 304, 304, 292, 280, 280 };

	for( int i = 0; i < MAX_FORT_ARCHER; ++i )
	{
		int towerX = INFO_X1 + towerXTable[i];
		int towerY = INFO_Y1 + towerYTable[i];

		if( i < current_archer_count )
		{
			// display full tower
			vga.active_buf->put_bitmap( towerX, towerY, towerFull );
		}
		else if( i == current_archer_count )
		{
			// display building tower
			vga.active_buf->put_bitmap( towerX, towerY, towerEmpty );

			// display portion of towerFull at bottom
			int subTowerHeight = train_archer_progress * towerHeight / MAX_TRAIN_ARCHER_PROGRESS;
			if( subTowerHeight > 0 )
			{
				vga.active_buf->put_bitmap_area( towerX, towerY, towerBuilding, 
					0, towerHeight-subTowerHeight, towerWidth-1, towerHeight-1 );
			}
		}
		else
		{
			// display disabled tower	
			vga.active_buf->put_bitmap( towerX, towerY, towerEmpty );
		}
	}

	help.set_help( INFO_X1+176, INFO_Y1+278, INFO_X1+176+39, INFO_Y1+278+48, "TOWERS" );
}
Exemple #3
0
// ------- begin of function FirmMonsterTrain::disp_firm_info -------//
//
void FirmMonsterTrain::disp_firm_info(int dispY1, int refreshFlag )
{
	int i;

	if( refreshFlag == INFO_REPAINT )
	{
		button_mobilize.create( INFO_X1+13, INFO_Y1+235, 'A', "MOBILIZE" );
		button_mobilize.enable_flag = 0;
		if ((train_type_count == 1) && (train_unit_id[0] == UNIT_BEE))
			button_patrol.create( INFO_X1+13+BUTTON_DISTANCE, INFO_Y1+235, 'A', "PATROL-B" );
		else
		if ((train_type_count == 1) && (train_unit_id[0] == UNIT_TERMITE))
			button_patrol.create( INFO_X1+13+BUTTON_DISTANCE, INFO_Y1+235, 'A', "PATROL-T" );
		else
			button_patrol.create( INFO_X1+13+BUTTON_DISTANCE, INFO_Y1+235, 'A', "PATROL" );

		button_patrol.enable_flag = 0;
		for( i = 0; i < train_type_count; ++i )
		{
			if( i < 4 )		// 4 buttons at bottom line
			{
				if ((train_type_count == 1) && (train_unit_id[0] == UNIT_BEE))
					button_train[i].create( INFO_X1+13+i*BUTTON_DISTANCE, INFO_Y1+281, 'A', "TRAIN-B" );
				else
				if ((train_type_count == 1) && (train_unit_id[0] == UNIT_TERMITE))
					button_train[i].create( INFO_X1+13+i*BUTTON_DISTANCE, INFO_Y1+281, 'A', "TRAIN-T" );
				else
					button_train[i].create( INFO_X1+13+i*BUTTON_DISTANCE, INFO_Y1+281, 'A', "F_TRAIN" );
			}
			else
			{
				if ((train_type_count == 1) && (train_unit_id[0] == UNIT_BEE))
					button_train[i].create( INFO_X1+13+(7-i)*BUTTON_DISTANCE, INFO_Y1+235, 'A', "TRAIN-B" );
				else
				if ((train_type_count == 1) && (train_unit_id[0] == UNIT_TERMITE))
					button_train[i].create( INFO_X1+13+(7-i)*BUTTON_DISTANCE, INFO_Y1+235, 'A', "TRAIN-T" );
				else
					button_train[i].create( INFO_X1+13+(7-i)*BUTTON_DISTANCE, INFO_Y1+235, 'A', "F_TRAIN" );
			}
			button_train[i].enable_flag = 0;
		}

		// ###### begin Gilbert 11/3 ########//
		button_go_rally.create( INFO_X1+13+BUTTON_DISTANCE*2, INFO_Y1+235, 'A', "RALLY-GO" );
		button_clear_rally.create( INFO_X1+13+BUTTON_DISTANCE*3, INFO_Y1+235, 'A', "RALLY-NO" );
		// ###### end Gilbert 11/3 ########//
	}

	if( !should_show_info() )
		return;

	// ------ display mobilize button -------//

	button_mobilize.enable_flag = 0;

	if( is_own() )
	{
		if( selected_trainee_id > 0 && selected_trainee_id <= trainee_count )
		{
			MonsterTrainee *traineePtr = trainee_array + selected_trainee_id - 1;
			button_mobilize.enable_flag = !traineePtr->is_under_training();
		}

		button_mobilize.paint();

		// ----- display mobilize all button -------//

		for( i = 0; i < trainee_count && trainee_array[i].is_under_training(); ++i );
		button_patrol.enable_flag = i < trainee_count;
		button_patrol.paint();

		// ----- display train button ----------// 

		for( i = 0; i < train_type_count; ++i )
		{
			button_train[i].enable_flag = can_recruit(train_unit_id[i]);
			button_train[i].paint();
		}

		// ------- display rally points button ------//

		if( (button_go_rally.visible_flag = rally_enable_flag != 0) )
			button_go_rally.paint();

		if( (button_clear_rally.visible_flag = rally_enable_flag != 0) )
			button_clear_rally.paint();
	}
}
Exemple #4
0
//------- Begin of function Town::think_split_town -------//
//
// Split the town into two, migrating some population to the new
// town.
//
int Town::think_split_town()
{
	if( jobless_population==0 )			// cannot move if we don't have any mobilizable unit
		return 0;

	//--- split when the population is close to its limit ----//

	Nation* nationPtr = nation_array[nation_recno];

	if( population < 45 + nationPtr->pref_territorial_cohesiveness / 10 )
		return 0;

	//-------- think about which race to move --------//

	int mostRaceId1, mostRaceId2, raceId=0;

	get_most_populated_race(mostRaceId1, mostRaceId2);

	if( mostRaceId2 && jobless_race_pop_array[mostRaceId2-1] > 0 && can_recruit(mostRaceId2) )
		raceId = mostRaceId2;

	else if( mostRaceId1 && jobless_race_pop_array[mostRaceId1-1] > 0 && can_recruit(mostRaceId1) )
		raceId = mostRaceId1;

	else
		raceId = pick_random_race(0, 1);			// 0-recruitable only, 1-also pick spy.

	if( !raceId )
	{
		//---- if the racial mix favors a split of town -----//
		//
		// This is when there are two major races, both of significant
		// population in the town. This is a good time for us to move
		// the second major race to a new town.
		//
		//---------------------------------------------------//

		if( mostRaceId2 && jobless_race_pop_array[mostRaceId2] > 0 &&
			 race_pop_array[mostRaceId2] >= population/3 &&		// the race's has at least 1/3 of the town's total population
			 can_recruit(mostRaceId2) )
		{
			raceId = mostRaceId2;
		}
	}

	if( !raceId )
		return 0;

	//---- check if there is already a town of this race with low population linked to this town, then don't split a new one ---//

	Town* townPtr;

	for( int i=0 ; i<linked_town_count ; i++ )
	{
		townPtr = town_array[ linked_town_array[i] ];

		if( townPtr->nation_recno == nation_recno &&
			 townPtr->population < 20 &&
			 townPtr->majority_race() == raceId )
		{
			return 0;
		}
	}

	//-------- settle to a new town ---------//

	return ai_settle_new(raceId);
}
void drawable_unit::redraw_unit (display & disp) const
{
	const display_context & dc = disp.get_disp_context();
	const gamemap &map = dc.map();
	const std::vector<team> &teams = dc.teams();

	const team & viewing_team = teams[disp.viewing_team()];

	unit_animation_component & ac = *anim_comp_;

	if ( hidden_ || disp.is_blindfolded() || !is_visible_to_team(viewing_team,map, disp.show_everything()) )
	{
		ac.clear_haloes();
		if(ac.anim_) {
			ac.anim_->update_last_draw_time();
		}
		return;
	}

	if (!ac.anim_) {
		ac.set_standing();
		if (!ac.anim_) return;
	}

	if (ac.refreshing_) return;
	ac.refreshing_ = true;

	ac.anim_->update_last_draw_time();
	frame_parameters params;
	const t_translation::t_terrain terrain = map.get_terrain(loc_);
	const terrain_type& terrain_info = map.get_terrain_info(terrain);

	// do not set to 0 so we can distinguish the flying from the "not on submerge terrain"
	// instead use -1.0 (as in "negative depth", it will be ignored by rendering)
	params.submerge= is_flying() ? -1.0 : terrain_info.unit_submerge();

	if (invisible(loc_) &&
			params.highlight_ratio > 0.5) {
		params.highlight_ratio = 0.5;
	}
	if (loc_ == disp.selected_hex() && params.highlight_ratio == 1.0) {
		params.highlight_ratio = 1.5;
	}

	int height_adjust = static_cast<int>(terrain_info.unit_height_adjust() * disp.get_zoom_factor());
	if (is_flying() && height_adjust < 0) {
		height_adjust = 0;
	}
	params.y -= height_adjust;
	params.halo_y -= height_adjust;

	int red = 0,green = 0,blue = 0,tints = 0;
	double blend_ratio = 0;
	// Add future colored states here
	if(get_state(STATE_POISONED)) {
		green += 255;
		blend_ratio += 0.25;
		tints += 1;
	}
	if(get_state(STATE_SLOWED)) {
		red += 191;
		green += 191;
		blue += 255;
		blend_ratio += 0.25;
		tints += 1;
	}
	if(tints > 0) {
		params.blend_with = disp.rgb((red/tints),(green/tints),(blue/tints));
		params.blend_ratio = ((blend_ratio/tints));
	}

	//hackish : see unit_frame::merge_parameters
	// we use image_mod on the primary image
	// and halo_mod on secondary images and all haloes
	params.image_mod = image_mods();
	params.halo_mod = TC_image_mods();
	params.image= absolute_image();


	if(get_state(STATE_PETRIFIED)) params.image_mod +="~GS()";
	params.primary_frame = t_true;


	const frame_parameters adjusted_params = ac.anim_->get_current_params(params);

	const map_location dst = loc_.get_direction(facing_);
	const int xsrc = disp.get_location_x(loc_);
	const int ysrc = disp.get_location_y(loc_);
	const int xdst = disp.get_location_x(dst);
	const int ydst = disp.get_location_y(dst);
	int d2 = disp.hex_size() / 2;

	const int x = static_cast<int>(adjusted_params.offset * xdst + (1.0-adjusted_params.offset) * xsrc) + d2;
	const int y = static_cast<int>(adjusted_params.offset * ydst + (1.0-adjusted_params.offset) * ysrc) + d2;

	if(ac.unit_halo_ == halo::NO_HALO && !image_halo().empty()) {
		ac.unit_halo_ = halo::add(0, 0, image_halo()+TC_image_mods(), map_location(-1, -1));
	}
	if(ac.unit_halo_ != halo::NO_HALO && image_halo().empty()) {
		halo::remove(ac.unit_halo_);
		ac.unit_halo_ = halo::NO_HALO;
	} else if(ac.unit_halo_ != halo::NO_HALO) {
		halo::set_location(ac.unit_halo_, x, y - height_adjust);
	}



	// We draw bars only if wanted, visible on the map view
	bool draw_bars = ac.draw_bars_ ;
	if (draw_bars) {
		const int d = disp.hex_size();
		SDL_Rect unit_rect = sdl::create_rect(xsrc, ysrc +adjusted_params.y, d, d);
		draw_bars = sdl::rects_overlap(unit_rect, disp.map_outside_area());
	}

	surface ellipse_front(NULL);
	surface ellipse_back(NULL);
	int ellipse_floating = 0;
	// Always show the ellipse for selected units
	if(draw_bars && (preferences::show_side_colors() || disp.selected_hex() == loc_)) {
		if(adjusted_params.submerge > 0.0) {
			// The division by 2 seems to have no real meaning,
			// It just works fine with the current center of ellipse
			// and prevent a too large adjust if submerge = 1.0
			ellipse_floating = static_cast<int>(adjusted_params.submerge * disp.hex_size() / 2);
		}

		std::string ellipse=image_ellipse();
		if(ellipse.empty()){
			ellipse="misc/ellipse";
		}

		if(ellipse != "none") {
			// check if the unit has a ZoC or can recruit
			const char* const nozoc = emit_zoc_ ? "" : "nozoc-";
			const char* const leader = can_recruit() ? "leader-" : "";
			const char* const selected = disp.selected_hex() == loc_ ? "selected-" : "";

			// Load the ellipse parts recolored to match team color
			char buf[100];
			std::string tc=team::get_side_color_index(side_);

			snprintf(buf,sizeof(buf),"%s-%s%s%stop.png~RC(ellipse_red>%s)",ellipse.c_str(),leader,nozoc,selected,tc.c_str());
			ellipse_back.assign(image::get_image(image::locator(buf), image::SCALED_TO_ZOOM));
			snprintf(buf,sizeof(buf),"%s-%s%s%sbottom.png~RC(ellipse_red>%s)",ellipse.c_str(),leader,nozoc,selected,tc.c_str());
			ellipse_front.assign(image::get_image(image::locator(buf), image::SCALED_TO_ZOOM));
		}
	}

	if (ellipse_back != NULL) {
		//disp.drawing_buffer_add(display::LAYER_UNIT_BG, loc,
		disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc_,
			xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_back);
	}

	if (ellipse_front != NULL) {
		//disp.drawing_buffer_add(display::LAYER_UNIT_FG, loc,
		disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc_,
			xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_front);
	}
	if(draw_bars) {
		const image::locator* orb_img = NULL;
		/*static*/ const image::locator partmoved_orb(game_config::images::orb + "~RC(magenta>" +
						preferences::partial_color() + ")"  );
		/*static*/ const image::locator moved_orb(game_config::images::orb + "~RC(magenta>" +
						preferences::moved_color() + ")"  );
		/*static*/ const image::locator ally_orb(game_config::images::orb + "~RC(magenta>" +
						preferences::allied_color() + ")"  );
		/*static*/ const image::locator enemy_orb(game_config::images::orb + "~RC(magenta>" +
						preferences::enemy_color() + ")"  );
		/*static*/ const image::locator unmoved_orb(game_config::images::orb + "~RC(magenta>" +
						preferences::unmoved_color() + ")"  );

		const std::string* energy_file = &game_config::images::energy;

		if(size_t(side()) != disp.viewing_team()+1) {
			if(disp.team_valid() &&
			   viewing_team.is_enemy(side())) {
				if (preferences::show_enemy_orb() && !get_state(STATE_PETRIFIED))
					orb_img = &enemy_orb;
				else
					orb_img = NULL;
			} else {
				if (preferences::show_allied_orb())
					orb_img = &ally_orb;
				else orb_img = NULL;
			}
		} else {
			if (preferences::show_moved_orb())
				orb_img = &moved_orb;
			else orb_img = NULL;

			if(disp.playing_team() == disp.viewing_team() && !user_end_turn()) {
				if (movement_left() == total_movement()) {
					if (preferences::show_unmoved_orb())
						orb_img = &unmoved_orb;
					else orb_img = NULL;
				} else if ( dc.unit_can_move(*this) ) {
					if (preferences::show_partial_orb())
						orb_img = &partmoved_orb;
					else orb_img = NULL;
				}
			}
		}

		if (orb_img != NULL) {
			surface orb(image::get_image(*orb_img,image::SCALED_TO_ZOOM));
			disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
				loc_, xsrc, ysrc +adjusted_params.y, orb);
		}

		double unit_energy = 0.0;
		if(max_hitpoints() > 0) {
			unit_energy = double(hitpoints())/double(max_hitpoints());
		}
		const int bar_shift = static_cast<int>(-5*disp.get_zoom_factor());
		const int hp_bar_height = static_cast<int>(max_hitpoints() * hp_bar_scaling_);

		const fixed_t bar_alpha = (loc_ == disp.mouseover_hex() || loc_ == disp.selected_hex()) ? ftofxp(1.0): ftofxp(0.8);

		disp.draw_bar(*energy_file, xsrc+bar_shift, ysrc +adjusted_params.y,
			loc_, hp_bar_height, unit_energy,hp_color(), bar_alpha);

		if(experience() > 0 && can_advance()) {
			const double filled = double(experience())/double(max_experience());

			const int xp_bar_height = static_cast<int>(max_experience() * xp_bar_scaling_ / std::max<int>(level_,1));

			SDL_Color color=xp_color();
			disp.draw_bar(*energy_file, xsrc, ysrc +adjusted_params.y,
				loc_, xp_bar_height, filled, color, bar_alpha);
		}

		if (can_recruit()) {
			surface crown(image::get_image(leader_crown(),image::SCALED_TO_ZOOM));
			if(!crown.null()) {
				//if(bar_alpha != ftofxp(1.0)) {
				//	crown = adjust_surface_alpha(crown, bar_alpha);
				//}
				disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
					loc_, xsrc, ysrc +adjusted_params.y, crown);
			}
		}

		for(std::vector<std::string>::const_iterator ov = overlays().begin(); ov != overlays().end(); ++ov) {
			const surface ov_img(image::get_image(*ov, image::SCALED_TO_ZOOM));
			if(ov_img != NULL) {
				disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
					loc_, xsrc, ysrc +adjusted_params.y, ov_img);
			}
		}
	}

	// Smooth unit movements from terrain of different elevation.
	// Do this separately from above so that the health bar doesn't go up and down.

	const t_translation::t_terrain terrain_dst = map.get_terrain(dst);
	const terrain_type& terrain_dst_info = map.get_terrain_info(terrain_dst);

	int height_adjust_unit = static_cast<int>((terrain_info.unit_height_adjust() * (1.0 - adjusted_params.offset) +
											  terrain_dst_info.unit_height_adjust() * adjusted_params.offset) *
											  disp.get_zoom_factor());
	if (is_flying() && height_adjust_unit < 0) {
		height_adjust_unit = 0;
	}
	params.y -= height_adjust_unit - height_adjust;
	params.halo_y -= height_adjust_unit - height_adjust;

	ac.anim_->redraw(params);
	ac.refreshing_ = false;
}