//-------- 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; }
//--------- 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" ); }
// ------- 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(); } }
//------- 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; }