void dllp::base_rbm_layer::print(std::ostream& out) const { out << "\n , dll::weight_decay<dll::decay_type::" << decay_to_str(decay) << ">"; out << "\n , dll::sparsity<dll::sparsity_method::" << sparsity_to_str(sparsity) << ">"; if (!visible_unit.empty()) { out << "\n , dll::visible<dll::unit_type::" << unit_type(visible_unit) << ">"; } if (!hidden_unit.empty()) { out << "\n , dll::hidden<dll::unit_type::" << unit_type(hidden_unit) << ">"; } if (batch_size > 0) { out << "\n , dll::batch_size<" << batch_size << ">"; } if (momentum != dll::processor::stupid_default) { out << "\n , dll::momentum"; } if (trainer == "pcd") { out << "\n , dll::trainer_rbm<dll::pcd1_trainer_t>"; } if (shuffle) { out << "\n , dll::shuffle"; } }
/*********************************************************************** Iterates through reachable cities and appraises them as a possible base for air operations by (air)unit punit. Returns NULL if not found. The path is stored in the path argument if not NULL. **********************************************************************/ static struct tile *dai_find_strategic_airbase(struct ai_type *ait, const struct unit *punit, struct pf_path **path) { struct player *pplayer = unit_owner(punit); struct pf_parameter parameter; struct pf_map *pfm; struct tile *best_tile = NULL; struct city *pcity; struct unit *pvirtual = NULL; int best_worth = 0, target_worth; pft_fill_unit_parameter(¶meter, punit); pfm = pf_map_new(¶meter); pf_map_move_costs_iterate(pfm, ptile, move_cost, FALSE) { if (move_cost >= punit->moves_left) { break; /* Too far! */ } if (!is_airunit_refuel_point(ptile, pplayer, unit_type(punit), FALSE)) { continue; /* Cannot refuel here. */ } if ((pcity = tile_city(ptile)) && def_ai_city_data(pcity, ait)->grave_danger != 0) { best_tile = ptile; break; /* Fly there immediately!! */ } if (!pvirtual) { pvirtual = unit_virtual_create(pplayer, player_city_by_number(pplayer, punit->homecity), unit_type(punit), punit->veteran); } unit_tile_set(pvirtual, ptile); target_worth = find_something_to_bomb(ait, pvirtual, NULL, NULL); if (target_worth > best_worth) { /* It's either a first find or it's better than the previous. */ best_worth = target_worth; best_tile = ptile; /* We can still look for something better. */ } } pf_map_move_costs_iterate_end; if (pvirtual) { unit_virtual_destroy(pvirtual); } if (path) { /* Stores the path. */ *path = best_tile ? pf_map_path(pfm, best_tile) : NULL; } pf_map_destroy(pfm); return best_tile; }
INIT_LOOP( r, c) { unsigned index = r*COLUMNS + c; op1_.push_back( unit_type(r*c)/unit_type(r+c+1)); op2_.push_back( unit_type(r+c)/unit_type(r*c+1)); added_.push_back( op1_[ index] + op2_[index]); subtracted_.push_back( op1_[index] - op2_[index]); scmul_.push_back( op1_[ index] * scalar_); scdiv_.push_back( op1_[ index] / scalar_); transposed_[ c*ROWS + r] = op1_.back(); }
/************************************************************************** Looks for nearest airbase for punit reachable imediatly. Returns NULL if not found. The path is stored in the path argument if not NULL. TODO: Special handicaps for planes running out of fuel IMO should be less restrictive than general H_MAP, H_FOG *************************************************************************/ static struct tile *find_nearest_airbase(const struct unit *punit, struct pf_path **path) { struct player *pplayer = unit_owner(punit); const struct unit_type *punittype = unit_type(punit); struct pf_parameter parameter; struct pf_map *pfm; pft_fill_unit_parameter(¶meter, punit); pfm = pf_map_new(¶meter); pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) { if (move_cost > punit->moves_left) { /* Too far! */ break; } if (is_airunit_refuel_point(ptile, pplayer, punittype, FALSE)) { if (path) { *path = pf_map_path(pfm, ptile); } pf_map_destroy(pfm); return ptile; } } pf_map_move_costs_iterate_end; pf_map_destroy(pfm); return NULL; }
/***************************************************************************** Find best tile the paratrooper should jump to. *****************************************************************************/ static struct tile *find_best_tile_to_paradrop_to(struct ai_type *ait, struct unit *punit) { int best = 0; int val; struct tile* best_tile = NULL; int range = unit_type(punit)->paratroopers_range; struct city* acity; struct player* pplayer = unit_owner(punit); /* First, we search for undefended cities in danger */ square_iterate(unit_tile(punit), range, ptile) { if (!map_is_known(ptile, pplayer)) { continue; } acity = tile_city(ptile); if (acity && city_owner(acity) == unit_owner(punit) && unit_list_size(ptile->units) == 0) { val = city_size_get(acity) * def_ai_city_data(acity, ait)->urgency; if (val > best) { best = val; best_tile = ptile; } } } square_iterate_end; if (best_tile != NULL) { acity = tile_city(best_tile); UNIT_LOG(LOGLEVEL_PARATROOPER, punit, "Choose to jump in order to protect allied city %s (%d %d). " "Benefit: %d", city_name(acity), TILE_XY(best_tile), best); return best_tile; } /* Second, we search for undefended enemy cities */ square_iterate(unit_tile(punit), range, ptile) { acity = tile_city(ptile); if (acity && pplayers_at_war(unit_owner(punit), city_owner(acity)) && (unit_list_size(ptile->units) == 0)) { if (!map_is_known_and_seen(ptile, pplayer, V_MAIN) && ai_handicap(pplayer, H_FOG)) { continue; } /* Prefer big cities on other continents */ val = city_size_get(acity) + (tile_continent(unit_tile(punit)) != tile_continent(ptile)); if (val > best) { best = val; best_tile = ptile; } } } square_iterate_end;
/************************************************************************ Trying to manage bombers and stuff. If we are in the open { if moving intelligently on a valid GOTO, { carry on doing it. } else { go refuel } } else { try to attack something } TODO: distant target selection, support for fuel > 2 ***********************************************************************/ void dai_manage_airunit(struct ai_type *ait, struct player *pplayer, struct unit *punit) { struct tile *dst_tile = unit_tile(punit); /* Loop prevention */ int moves = punit->moves_left; int id = punit->id; struct pf_parameter parameter; struct pf_map *pfm; struct pf_path *path; CHECK_UNIT(punit); if (!is_unit_being_refueled(punit)) { /* We are out in the open, what shall we do? */ if (punit->activity == ACTIVITY_GOTO /* We are on a GOTO. Check if it will get us anywhere */ && NULL != punit->goto_tile && !same_pos(unit_tile(punit), punit->goto_tile) && is_airunit_refuel_point(punit->goto_tile, pplayer, unit_type(punit), FALSE)) { pfm = pf_map_new(¶meter); path = pf_map_path(pfm, punit->goto_tile); if (path) { bool alive = adv_follow_path(punit, path, punit->goto_tile); pf_path_destroy(path); pf_map_destroy(pfm); if (alive && punit->moves_left > 0) { /* Maybe do something else. */ dai_manage_airunit(ait, pplayer, punit); } return; } pf_map_destroy(pfm); } else if ((dst_tile = find_nearest_airbase(punit, &path))) { /* Go refuelling */ if (!adv_follow_path(punit, path, dst_tile)) { pf_path_destroy(path); return; /* The unit died. */ } pf_path_destroy(path); } else { if (punit->fuel == 1) { UNIT_LOG(LOG_DEBUG, punit, "Oops, fallin outta the sky"); } def_ai_unit_data(punit, ait)->done = TRUE; /* Won't help trying again */ return; } } else if (punit->fuel == unit_type(punit)->fuel) { /* We only leave a refuel point when we are on full fuel */ if (find_something_to_bomb(ait, punit, &path, &dst_tile) > 0) { /* Found target, coordinates are in punit's goto_dest. * TODO: separate attacking into a function, check for the best * tile to attack from */ fc_assert_ret(path != NULL && dst_tile != NULL); if (!adv_follow_path(punit, path, dst_tile)) { pf_path_destroy(path); return; /* The unit died. */ } pf_path_destroy(path); /* goto would be aborted: "Aborting GOTO for AI attack procedures" * now actually need to attack */ /* We could use ai_military_findvictim here, but I don't trust it... */ unit_activity_handling(punit, ACTIVITY_IDLE); if (is_tiles_adjacent(unit_tile(punit), dst_tile)) { (void) unit_move_handling(punit, dst_tile, TRUE, FALSE); } } else if ((dst_tile = dai_find_strategic_airbase(ait, punit, &path))) { log_debug("%s will fly to (%i, %i) (%s) to fight there", unit_rule_name(punit), TILE_XY(dst_tile), tile_city(dst_tile) ? city_name(tile_city(dst_tile)) : ""); def_ai_unit_data(punit, ait)->done = TRUE; /* Wait for next turn */ if (!adv_follow_path(punit, path, dst_tile)) { pf_path_destroy(path); return; /* The unit died. */ } pf_path_destroy(path); } else { log_debug("%s cannot find anything to kill and is staying put", unit_rule_name(punit)); def_ai_unit_data(punit, ait)->done = TRUE; unit_activity_handling(punit, ACTIVITY_IDLE); } } if ((punit = game_unit_by_number(id)) != NULL && punit->moves_left > 0 && punit->moves_left != moves) { /* We have moved this turn, might have ended up stuck out in the fields * so, as a safety measure, let's manage again */ dai_manage_airunit(ait, pplayer, punit); } }
object::object(object&& other) : m_value(&s_unit), m_type(unit_type()) { swap(other); }
/********************************************************************** Returns an estimate for the profit gained through attack. Assumes that the victim is within one day's flight **********************************************************************/ static int dai_evaluate_tile_for_air_attack(struct unit *punit, struct tile *dst_tile) { struct unit *pdefender; /* unit costs in shields */ int balanced_cost, unit_cost, victim_cost = 0; /* unit stats */ int unit_attack, victim_defence; /* final answer */ int profit; /* time spent in the air */ int sortie_time; #define PROB_MULTIPLIER 100 /* should unify with those in combat.c */ if (!can_unit_attack_tile(punit, dst_tile) || !(pdefender = get_defender(punit, dst_tile))) { return 0; } /* Ok, we can attack, but is it worth it? */ /* Cost of our unit */ unit_cost = unit_build_shield_cost(punit); /* This is to say "wait, ill unit will get better!" */ unit_cost = unit_cost * unit_type(punit)->hp / punit->hp; /* Determine cost of enemy units */ victim_cost = stack_cost(punit, pdefender); if (0 == victim_cost) { return 0; } /* Missile would die 100% so we adjust the victim_cost -- GB */ if (uclass_has_flag(unit_class(punit), UCF_MISSILE)) { victim_cost -= unit_build_shield_cost(punit); } unit_attack = (int) (PROB_MULTIPLIER * unit_win_chance(punit, pdefender)); victim_defence = PROB_MULTIPLIER - unit_attack; balanced_cost = build_cost_balanced(unit_type(punit)); sortie_time = (unit_has_type_flag(punit, UTYF_ONEATTACK) ? 1 : 0); profit = kill_desire(victim_cost, unit_attack, unit_cost, victim_defence, 1) - SHIELD_WEIGHTING + 2 * TRADE_WEIGHTING; if (profit > 0) { profit = military_amortize(unit_owner(punit), game_city_by_number(punit->homecity), profit, sortie_time, balanced_cost); log_debug("%s at (%d, %d) is a worthy target with profit %d", unit_rule_name(pdefender), TILE_XY(dst_tile), profit); } else { log_debug("%s(%d, %d): %s at (%d, %d) is unworthy with profit %d", unit_rule_name(punit), TILE_XY(unit_tile(punit)), unit_rule_name(pdefender), TILE_XY(dst_tile), profit); profit = 0; } return profit; }
/** * Resets all data based on the provided config. * This includes some processing of the config, such as expanding base units. * A pointer to the config is stored, so the config must be persistent. */ void unit_type_data::set_config(config &cfg) { DBG_UT << "unit_type_data::set_config, name: " << cfg["name"] << "\n"; clear(); unit_cfg_ = &cfg; for (const config &mt : cfg.child_range("movetype")) { movement_types_.insert(std::make_pair(mt["name"].str(), movetype(mt))); gui2::tloadscreen::progress(); } for (const config &r : cfg.child_range("race")) { const unit_race race(r); races_.insert(std::pair<std::string,unit_race>(race.id(),race)); gui2::tloadscreen::progress(); } // Movetype resistance patching for (const config &r : cfg.child_range("resistance_defaults")) { const std::string& dmg_type = r["id"]; config temp_cfg; for (const config::attribute &attr : r.attribute_range()) { const std::string &mt = attr.first; if (mt == "id" || mt == "default" || movement_types_.find(mt) == movement_types_.end()) { continue; } patch_movetype(movement_types_[mt].get_resistances(), dmg_type, attr.second, 100, true); } if (r.has_attribute("default")) { for (movement_type_map::value_type &mt : movement_types_) { // Don't apply a default if a value is explicitly specified. if (r.has_attribute(mt.first)) { continue; } patch_movetype(mt.second.get_resistances(), dmg_type, r["default"], 100, false); } } } // Movetype move/defend patching for (const config &terrain : cfg.child_range("terrain_defaults")) { const std::string& ter_type = terrain["id"]; config temp_cfg; static const std::string terrain_info_tags[] = {"movement", "vision", "jamming", "defense"}; for (const std::string &tag : terrain_info_tags) { if (!terrain.has_child(tag)) { continue; } const config& info = terrain.child(tag); for (const config::attribute &attr : info.attribute_range()) { const std::string &mt = attr.first; if (mt == "default" || movement_types_.find(mt) == movement_types_.end()) { continue; } if (tag == "defense") { patch_movetype(movement_types_[mt].get_defense(), ter_type, attr.second, 100, true); } else if (tag == "vision") { patch_movetype(movement_types_[mt].get_vision(), ter_type, attr.second, 99, true); } else if (tag == "movement") { patch_movetype(movement_types_[mt].get_movement(), ter_type, attr.second, 99, true); } else if (tag == "jamming") { patch_movetype(movement_types_[mt].get_jamming(), ter_type, attr.second, 99, true); } } if (info.has_attribute("default")) { for (movement_type_map::value_type &mt : movement_types_) { // Don't apply a default if a value is explicitly specified. if (info.has_attribute(mt.first)) { continue; } if (tag == "defense") { patch_movetype(mt.second.get_defense(), ter_type, info["default"], 100, false); } else if (tag == "vision") { patch_movetype(mt.second.get_vision(), ter_type, info["default"], 99, false); } else if (tag == "movement") { patch_movetype(mt.second.get_movement(), ter_type, info["default"], 99, false); } else if (tag == "jamming") { patch_movetype(mt.second.get_jamming(), ter_type, info["default"], 99, false); } } } } } // Apply base units. for (config &ut : cfg.child_range("unit_type")) { if ( ut.has_child("base_unit") ) { // Derived units must specify a new id. // (An error message will be emitted later if id is empty.) const std::string id = ut["id"]; if ( !id.empty() ) { std::vector<std::string> base_tree(1, id); apply_base_unit(ut, cfg, base_tree); gui2::tloadscreen::progress(); } } } // Handle inheritance and recording of unit types. for (config &ut : cfg.child_range("unit_type")) { std::string id = ut["id"]; // Every type is required to have an id. if ( id.empty() ) { ERR_CF << "[unit_type] with empty id=, ignoring:\n" << ut.debug(); continue; } // Complete the gender-specific children of the config. if ( config &male_cfg = ut.child("male") ) { fill_unit_sub_type(male_cfg, ut, true); handle_variations(male_cfg); } if ( config &female_cfg = ut.child("female") ) { fill_unit_sub_type(female_cfg, ut, true); handle_variations(female_cfg); } // Complete the variation-defining children of the config. handle_variations(ut); // Record this unit type. if ( insert(std::make_pair(id, unit_type(ut))).second ) { LOG_CONFIG << "added " << id << " to unit_type list (unit_type_data.unit_types)\n"; } else { ERR_CF << "Multiple [unit_type]s with id=" << id << " encountered." << std::endl; } gui2::tloadscreen::progress(); } // Build all unit types. (This was not done within the loop for performance.) build_all(unit_type::CREATED); // Suppress some unit types (presumably used as base units) from the help. if (const config &hide_help = cfg.child("hide_help")) { hide_help_all_ = hide_help["all"].to_bool(); read_hide_help(hide_help); } }
int do_unitmenu(int type, int tx, int ty, int pturn) { const int x = 160, y = 70; static bool first = true; static bool ok[MAX_UNITS]; //each ok[] corresponds to a unit type static _button items[15]; //maximum number of buttons possible at once is 15 static _button pos[9]; static int lastitem, unittype, buildpos; static bool limit, buildable[9]; bool drewbuildpos; char tempchar[30]; int i, j, bx, by; DyBytes data; if (first) { limit = false; i = 0; while (i < 9) { bx = tx + (i % 3) - 1; by = ty + (i / 3) - 1; buildable[i] = true; if ((bx < 0) || (bx >= worldmap.l)) buildable[i] = false; if ((by < 0) || (by >= worldmap.h)) buildable[i] = false; if (any_unit_here(bx, by) != -1) buildable[i] = false; i++; } buildpos = random_buildpos(&buildable[0]); i = 0; while (i < NUM_UNITS) { ok[i] = false; switch(type) { case BASE: if (unitstats[i].basetype == LAND) ok[i] = true; break; case AIRPORT: if (unitstats[i].basetype == AIR) ok[i] = true; break; case PORT: if (unitstats[i].basetype == SEA) ok[i] = true; break; } if (!unitstats[i].isarmy[player[pturn].number]) { //if the player's army can't build this unit ok[i] = false; } if (unitstats[i].techlevel > var.techlevel) { ok[i] = false; } i++; } if (player[pturn].units_in_play() >= 50) //if the player cannot make more units { i = 0; while (i < NUM_UNITS) { ok[i] = false; i++; } buffer_textout_ex(normal, "Unit Limit Reached", 50, 290, BLACK); limit = true; } i = 0; j = 0; while (i < NUM_UNITS) { if (ok[i]) { items[j].init(x + 30, y + 78 + (20 * j), 100, 15, unit_name(i)); j++; } i++; } items[j].init(x + 8, y + 10, 22, 22, ""); //close button lastitem = j; position_mouse(220, 195); j = 0; while (j < 3) { i = 0; while (i < 3) { pos[i + j * 3].init(x + 80 + 19 * i, y + 10 + 19 * j, 18, 18); i++; } j++; } first = false; } buffer_draw_sprite(glb.bmp(35), x, y, 0.9); if (!limit) { i = 0; while (i < 9) { if (buildable[i]) { pos[i].check(); if (pos[i].clicked()) { buildpos = i; } } else { buffer_rectfill(x + 80 + (i % 3) * 19, y + 10 + (i / 3) * 19, x + 98 + (i % 3) * 19, y + 28 + (i / 3) * 19, makecol(128, 0, 0), 0.75); } i++; } } drewbuildpos = false; j = 0; i = 0; while ((i < lastitem) && (!limit)) { items[i].check(); if (items[i].mouseover() == 1) { j = 1; unittype = unit_type(items[i].get_text()); buffer_textout_centre_ex(med, unit_name(unittype), x + 225, y + 35, BLACK, 0.7); sprintf(tempchar, "Price: %-1d", unit_price(unittype, player[pturn].number)); if (unit_price(unittype, player[pturn].number) <= player[pturn].cash) { buffer_textout_centre_ex(normal, tempchar, x + 225, y + 55, BLACK); } else { buffer_textout_centre_ex(normal, tempchar, x + 225, y + 55, RED); } bigunits.draw(unittype, x + 175, y + 95); multiline_textout_ex(normal, unitstats[unittype].description, x + 160, y + 215, 130, BLACK); bx = tx + (buildpos % 3) - 1; by = ty + (buildpos / 3) - 1; if ((any_unit_here(bx, by) == -1) && (bx >= 0) && (bx < worldmap.l) && (by >= 0) && (by < worldmap.h) && (moves_needed(unitstats[unittype].movetype, bx, by, pturn) < 99)) { //if the selected unit can be built on the selected tile buffer_rectfill(x + 80 + (buildpos % 3) * 19, y + 10 + (buildpos / 3) * 19, x + 98 + (buildpos % 3) * 19, y + 28 + (buildpos / 3) * 19, GREEN, 0.75); } else { buffer_rectfill(x + 80 + (buildpos % 3) * 19, y + 10 + (buildpos / 3) * 19, x + 98 + (buildpos % 3) * 19, y + 28 + (buildpos / 3) * 19, RED, 0.75); } drewbuildpos = true; } if (items[i].clicked()) { if (player[pturn].cash >= unit_price(unittype, player[pturn].number)) { bx = tx + (buildpos % 3) - 1; by = ty + (buildpos / 3) - 1; if (moves_needed(unitstats[unittype].movetype, bx, by, pturn) < 99) { if ((bx >= 0) && (bx < worldmap.l) && (by >= 0) && (by < worldmap.h) && (any_unit_here(bx, by) == -1)) { if (!global.netgame) { player[pturn].cash -= unit_price(unittype, player[pturn].number); player[pturn].create_unit(unittype, bx, by, pturn); player[pturn].stats.produced++; player[pturn].stats.spent += unit_price(unittype, player[pturn].number); } else { if (!net.server) { //if it's not the network host, it just sends a request for a new unit here data.clear(); data.addByte(NET_CLIENT_NEWUNIT); data.addByte(unittype); data.addByte(bx); data.addByte(by); send_datablob(net.thread, &data); } else { player[pturn].cash -= unit_price(unittype, player[pturn].number); player[pturn].create_unit(unittype, bx, by, pturn); player[pturn].stats.spent += unit_price(unittype, player[pturn].number); player[pturn].stats.produced++; data.clear(); data.addByte(NET_PLAYERCASH); data.addByte(pturn); data.appendVariable(player[pturn].cash); broadcast_datablob(&data); data.clear(); data.addByte(NET_NEWUNIT); data.addByte(pturn); data.addByte(unittype); data.addByte(bx); data.addByte(by); broadcast_datablob(&data); } } position_mouse(var.oldmx, var.oldmy); first = true; return 1; } } } } i++; } if ((!limit) && (!drewbuildpos)) { buffer_rectfill(x + 80 + (buildpos % 3) * 19, y + 10 + (buildpos / 3) * 19, x + 98 + (buildpos % 3) * 19, y + 28 + (buildpos / 3) * 19, WHITE, 0.75); } if (limit) { //the 50-unit limit has been hit buffer_textout_ex(normal, "Unit Limit Reached", x + 160, y + 215, RED); } items[lastitem].check(); if (items[lastitem].clicked()) //cancel button { //set_mouse_range(0, 0, 639, 479); position_mouse(var.oldmx, var.oldmy); first = true; return -1; } return 0; }
// TODO: Support irrigation modes JNIEXPORT jbyteArray JNICALL Java_net_hackcasual_freeciv_NativeHarness_getAvailableCommandsForActiveUnit (JNIEnv * env, jobject obj) { struct unit * pUnit; char availCommands[COM_UNIT_LAST]; int commandCount = 0; pUnit = head_of_units_in_focus(); if (pUnit) { struct tile *pTile = pUnit->tile; struct city *pCity = tile_city(pTile); struct terrain *pTerrain = tile_terrain(pTile); struct base_type *pbase; struct unit_list *punits = get_units_in_focus(); if (can_unit_build_city(pUnit)) { availCommands[commandCount++] = COM_BUILD_CITY; } if (can_unit_do_activity(pUnit, ACTIVITY_GOTO)) { availCommands[commandCount++] = COM_GO_TO; availCommands[commandCount++] = COM_GO_TO_CITY; } if (can_unit_do_activity(pUnit, ACTIVITY_SENTRY)) { availCommands[commandCount++] = COM_SENTRY; } if (can_unit_do_activity(pUnit, ACTIVITY_FORTIFYING)) { availCommands[commandCount++] = COM_FORTIFY; } if (can_unit_do_activity(pUnit, ACTIVITY_EXPLORE)) { availCommands[commandCount++] = COM_EXPLORE; } availCommands[commandCount++] = COM_DISBAND; if (can_unit_do_activity(pUnit, ACTIVITY_ROAD) || can_unit_do_activity(pUnit, ACTIVITY_RAILROAD)) { availCommands[commandCount++] = COM_ROAD; } if (can_unit_do_activity(pUnit, ACTIVITY_IRRIGATE)) { availCommands[commandCount++] = COM_IRRIGATION; } if (can_unit_do_autosettlers(pUnit)) { availCommands[commandCount++] = COM_AUTO_WORKER; } if (can_unit_do_connect(pUnit, ACTIVITY_IRRIGATE)) { availCommands[commandCount++] = COM_CONNECT_IRRIGATION; } if (can_unit_do_connect(pUnit, ACTIVITY_ROAD)) { availCommands[commandCount++] = COM_CONNECT_ROAD; } if (can_unit_do_connect(pUnit, ACTIVITY_RAILROAD)) { availCommands[commandCount++] = COM_CONNECT_RAILROAD; } availCommands[commandCount++] = COM_WAIT; if (unit_can_help_build_wonder_here(pUnit)) { availCommands[commandCount++] = COM_BUILD_WONDER; } if (unit_can_est_trade_route_here(pUnit)) { availCommands[commandCount++] = COM_TRADE_ROUTE; } if (can_unit_do_activity(pUnit, ACTIVITY_MINE)) { availCommands[commandCount++] = COM_MINE; } if (can_unit_do_activity(pUnit, ACTIVITY_TRANSFORM)) { availCommands[commandCount++] = COM_TRANSFORM; } pbase = get_base_by_gui_type(BASE_GUI_FORTRESS, pUnit, pUnit->tile); if (!pCity && pbase) { availCommands[commandCount++] = COM_FORTRESS; } pbase = get_base_by_gui_type(BASE_GUI_AIRBASE, pUnit, pUnit->tile); if (!pCity && pbase) { availCommands[commandCount++] = COM_AIRBASE; } if (can_unit_do_activity(pUnit, ACTIVITY_POLLUTION)) { availCommands[commandCount++] = COM_POLLUTION; } if (can_unit_do_activity(pUnit, ACTIVITY_FALLOUT)) { availCommands[commandCount++] = COM_FALLOUT; } if (can_unit_paradrop(pUnit)) { availCommands[commandCount++] = COM_PARADROP; } if (can_unit_do_activity(pUnit, ACTIVITY_PILLAGE)) { availCommands[commandCount++] = COM_FALLOUT; } if (pCity && can_unit_change_homecity(pUnit) && pCity->id != pUnit->homecity) { availCommands[commandCount++] = COM_HOMECITY; } if (pUnit->occupy && get_transporter_occupancy(pUnit) > 0) { availCommands[commandCount++] = COM_UNLOAD_TRANSPORT; } if (units_can_load(punits)) { availCommands[commandCount++] = COM_LOAD; } if (units_can_unload(punits)) { availCommands[commandCount++] = COM_UNLOAD; } if (pCity && pCity->airlift) { availCommands[commandCount++] = COM_AIRLIFT; } if (pCity && can_upgrade_unittype(client.conn.playing, unit_type(pUnit))) { availCommands[commandCount++] = COM_UPGRADE; } if (diplomat_can_do_action(pUnit, DIPLOMAT_ANY_ACTION, pUnit->tile)) { availCommands[commandCount++] = COM_DIPLOMAT; } if (unit_has_type_flag(pUnit, F_NUCLEAR)) { availCommands[commandCount++] = COM_NUKE; } } jbyteArray commands; commands = (*env)->NewByteArray(env, commandCount); (*env)->SetByteArrayRegion(env, commands, 0, commandCount, (jbyte *)availCommands); return commands; }
/** * Partially load data into an empty unit_type (build to HELP_INDEXED). */ void unit_type::build_help_index(const movement_type_map &mv_types, const race_map &races, const config::const_child_itors &traits) { // Don't build twice. if ( HELP_INDEXED <= build_status_ ) return; // Make sure we are built to the preceding build level. build_created(mv_types, races, traits); type_name_ = cfg_["name"]; description_ = cfg_["description"]; hitpoints_ = cfg_["hitpoints"].to_int(1); level_ = cfg_["level"]; recall_cost_ = cfg_["recall_cost"].to_int(-1); movement_ = cfg_["movement"].to_int(1); vision_ = cfg_["vision"].to_int(-1); jamming_ = cfg_["jamming"].to_int(0); max_attacks_ = cfg_["attacks"].to_int(1); cost_ = cfg_["cost"].to_int(1); usage_ = cfg_["usage"].str(); undead_variation_ = cfg_["undead_variation"].str(); image_ = cfg_["image"].str(); icon_ = cfg_["image_icon"].str(); small_profile_ = cfg_["small_profile"].str(); profile_ = cfg_["profile"].str(); adjust_profile(profile_); alignment_ = unit_type::ALIGNMENT::NEUTRAL; alignment_.parse(cfg_["alignment"].str()); for (int i = 0; i < 2; ++i) { if (gender_types_[i]) gender_types_[i]->build_help_index(mv_types, races, traits); } const race_map::const_iterator race_it = races.find(cfg_["race"]); if(race_it != races.end()) { race_ = &race_it->second; } else { race_ = &unit_race::null_race; } // if num_traits is not defined, we use the num_traits from race num_traits_ = cfg_["num_traits"].to_int(race_->num_traits()); const std::vector<std::string> genders = utils::split(cfg_["gender"]); for(std::vector<std::string>::const_iterator g = genders.begin(); g != genders.end(); ++g) { genders_.push_back(string_gender(*g)); } // For simplicity in other parts of the code, we must have at least one gender. if(genders_.empty()) { genders_.push_back(unit_race::MALE); } if (const config &abil_cfg = cfg_.child("abilities")) { for (const config::any_child &ab : abil_cfg.all_children_range()) { const config::attribute_value &name = ab.cfg["name"]; if (!name.empty()) { abilities_.push_back(name.t_str()); ability_tooltips_.push_back( ab.cfg["description"].t_str() ); } } } for (const config &adv : cfg_.child_range("advancement")) { for (const config &effect : adv.child_range("effect")) { const config &abil_cfg = effect.child("abilities"); if (!abil_cfg || effect["apply_to"] != "new_ability") { continue; } for (const config::any_child &ab : abil_cfg.all_children_range()) { const config::attribute_value &name = ab.cfg["name"]; if (!name.empty()) { adv_abilities_.push_back(name.t_str()); adv_ability_tooltips_.push_back( ab.cfg["description"].t_str() ); } } } } // Set the movement type. const std::string move_type = cfg_["movement_type"]; const movement_type_map::const_iterator find_it = mv_types.find(move_type); if ( find_it != mv_types.end() ) { DBG_UT << "inheriting from movement_type '" << move_type << "'\n"; movement_type_ = find_it->second; } else if ( !move_type.empty() ) { DBG_UT << "movement_type '" << move_type << "' not found\n"; } // Override parts of the movement type with what is in our config. movement_type_.merge(cfg_); for (const config &t : traits) { possible_traits_.add_child("trait", t); } if ( race_ != &unit_race::null_race ) { if (!race_->uses_global_traits()) { possible_traits_.clear(); } if ( cfg_["ignore_race_traits"].to_bool() ) { possible_traits_.clear(); } else { for (const config &t : race_->additional_traits()) { if (alignment_ != unit_type::ALIGNMENT::NEUTRAL || t["id"] != "fearless") possible_traits_.add_child("trait", t); } } if (undead_variation_.empty()) { undead_variation_ = race_->undead_variation(); } } // Insert any traits that are just for this unit type for (const config &trait : cfg_.child_range("trait")) { possible_traits_.add_child("trait", trait); } for (const config &var_cfg : cfg_.child_range("variation")) { const std::string& var_id = var_cfg["variation_id"].empty() ? var_cfg["variation_name"] : var_cfg["variation_id"]; variations_map::iterator ut; bool success; std::tie(ut, success) = variations_.emplace(var_id, unit_type(var_cfg, id_)); if(success) { ut->second.debug_id_ = debug_id_ + " [" + var_id + "]"; ut->second.base_id_ = base_id_; // In case this is not id_. ut->second.build_help_index(mv_types, races, traits); } else { ERR_CF << "Skipping duplicate unit variation ID: " << var_id << "\n"; } } hide_help_= cfg_["hide_help"].to_bool(); build_status_ = HELP_INDEXED; }
object::object() : m_value(&s_unit), m_type(unit_type()) { }
/**************************************************************** popup the dialog 10% inside the main-window *****************************************************************/ void unit_select_dialog_popup(struct tile *ptile) { int i,n,r; char buffer[512]; Arg args[4]; int nargs; Widget unit_select_all_command, unit_select_close_command; Widget firstcolumn=0,column=0; Pixel bg; struct unit *unit_list[unit_list_size(ptile->units)]; XtSetSensitive(main_form, FALSE); unit_select_dialog_shell = I_T(XtCreatePopupShell("unitselectdialogshell", transientShellWidgetClass, toplevel, NULL, 0)); unit_select_form = XtVaCreateManagedWidget("unitselectform", formWidgetClass, unit_select_dialog_shell, NULL); XtVaGetValues(unit_select_form, XtNbackground, &bg, NULL); XSetForeground(display, fill_bg_gc, bg); n = MIN(MAX_SELECT_UNITS, unit_list_size(ptile->units)); r = number_of_rows(n); fill_tile_unit_list(ptile, unit_list); for(i=0; i<n; i++) { struct unit *punit = unit_list[i]; struct unit_type *punittemp=unit_type(punit); struct city *pcity; struct canvas store; if(!(i%r)) { nargs=0; if(i) { XtSetArg(args[nargs], XtNfromHoriz, column); nargs++;} column = XtCreateManagedWidget("column", formWidgetClass, unit_select_form, args, nargs); if(!i) firstcolumn=column; } unit_select_ids[i]=punit->id; pcity = player_city_by_number(client_player(), punit->homecity); fc_snprintf(buffer, sizeof(buffer), "%s(%s)\n%s", utype_name_translation(punittemp), pcity ? city_name(pcity) : "", unit_activity_text(punit)); unit_select_pixmaps[i]=XCreatePixmap(display, XtWindow(map_canvas), tileset_full_tile_width(tileset), tileset_full_tile_height(tileset), display_depth); XFillRectangle(display, unit_select_pixmaps[i], fill_bg_gc, 0, 0, tileset_full_tile_width(tileset), tileset_full_tile_height(tileset)); store.pixmap = unit_select_pixmaps[i]; put_unit(punit, &store, 0, 0); nargs=0; XtSetArg(args[nargs], XtNbitmap, (XtArgVal)unit_select_pixmaps[i]);nargs++; XtSetArg(args[nargs], XtNsensitive, can_unit_do_activity(punit, ACTIVITY_IDLE));nargs++; if(i%r) { XtSetArg(args[nargs], XtNfromVert, unit_select_commands[i-1]); nargs++; } unit_select_commands[i]=XtCreateManagedWidget("unitselectcommands", commandWidgetClass, column, args, nargs); nargs=0; XtSetArg(args[nargs], XtNlabel, (XtArgVal)buffer); nargs++; XtSetArg(args[nargs], XtNfromHoriz, unit_select_commands[i]); nargs++; if(i%r) { XtSetArg(args[nargs], XtNfromVert, unit_select_commands[i-1]); nargs++; } unit_select_labels[i]=XtCreateManagedWidget("unitselectlabels", labelWidgetClass, column, args, nargs); XtAddCallback(unit_select_commands[i], XtNdestroyCallback,free_bitmap_destroy_callback, NULL); XtAddCallback(unit_select_commands[i], XtNcallback, unit_select_callback, NULL); } unit_select_no=i; unit_select_close_command = I_L(XtVaCreateManagedWidget("unitselectclosecommand", commandWidgetClass, unit_select_form, XtNfromVert, firstcolumn, NULL)); unit_select_all_command = I_L(XtVaCreateManagedWidget("unitselectallcommand", commandWidgetClass, unit_select_form, XtNfromVert, firstcolumn, NULL)); XtAddCallback(unit_select_close_command, XtNcallback, unit_select_callback, NULL); XtAddCallback(unit_select_all_command, XtNcallback, unit_select_all_callback, NULL); xaw_set_relative_position(toplevel, unit_select_dialog_shell, 15, 10); XtPopup(unit_select_dialog_shell, XtGrabNone); }
bool can_unit_upgrade(struct unit* punit) { return can_upgrade_unittype(client_player(), unit_type(punit)); }
struct sprite* get_unit_image(const struct unit* u) { return get_unittype_sprite(tileset, unit_type(u)); }
const char* get_unit_name(const struct unit* u) { return utype_name_translation(unit_type(u)); }
/************************************************************************** ... **************************************************************************/ static int spy_steal_popup(struct widget *pWidget) { struct city *pVcity = pWidget->data.city; int id = MAX_ID - pWidget->ID; struct player *pVictim = NULL; struct CONTAINER *pCont; struct widget *pBuf = NULL; struct widget *pWindow; SDL_String16 *pStr; SDL_Surface *pSurf; int max_col, max_row, col, i, count = 0; SDL_Rect area; popdown_diplomat_dialog(); if(pVcity) { pVictim = city_owner(pVcity); } if (pDiplomat_Dlg || !pVictim) { return 1; } count = 0; advance_index_iterate(A_FIRST, i) { if (player_invention_reachable(client.conn.playing, i, FALSE) && TECH_KNOWN == player_invention_state(pVictim, i) && (TECH_UNKNOWN == player_invention_state(client.conn.playing, i) || TECH_PREREQS_KNOWN == player_invention_state(client.conn.playing, i))) { count++; } } advance_index_iterate_end; if(!count) { /* if there is no known tech to steal then send steal order at Spy's Discretion */ int target_id = pVcity->id; request_diplomat_action(DIPLOMAT_STEAL, id, target_id, advance_count()); return -1; } pCont = fc_calloc(1, sizeof(struct CONTAINER)); pCont->id0 = pVcity->id; pCont->id1 = id;/* spy id */ pDiplomat_Dlg = fc_calloc(1, sizeof(struct diplomat_dialog)); pDiplomat_Dlg->diplomat_id = id; pDiplomat_Dlg->diplomat_target_id = pVcity->id; pDiplomat_Dlg->pdialog = fc_calloc(1, sizeof(struct ADVANCED_DLG)); pStr = create_str16_from_char(_("Select Advance to Steal"), adj_font(12)); pStr->style |= TTF_STYLE_BOLD; pWindow = create_window_skeleton(NULL, pStr, 0); pWindow->action = spy_steal_dlg_window_callback; set_wstate(pWindow , FC_WS_NORMAL); add_to_gui_list(ID_DIPLOMAT_DLG_WINDOW, pWindow); pDiplomat_Dlg->pdialog->pEndWidgetList = pWindow; area = pWindow->area; area.w = MAX(area.w, adj_size(8)); /* ------------------ */ /* exit button */ pBuf = create_themeicon(pTheme->Small_CANCEL_Icon, pWindow->dst, WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND); pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"), adj_font(12)); area.w += pBuf->size.w + adj_size(10); pBuf->action = exit_spy_steal_dlg_callback; set_wstate(pBuf, FC_WS_NORMAL); pBuf->key = SDLK_ESCAPE; add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf); /* ------------------------- */ count++; /* count + at Spy's Discretion */ /* max col - 104 is steal tech widget width */ max_col = (Main.screen->w - (pWindow->size.w - pWindow->area.w) - adj_size(2)) / adj_size(104); /* max row - 204 is steal tech widget height */ max_row = (Main.screen->h - (pWindow->size.h - pWindow->area.h)) / adj_size(204); /* make space on screen for scrollbar */ if (max_col * max_row < count) { max_col--; } if (count < max_col + 1) { col = count; } else { if (count < max_col + adj_size(3)) { col = max_col - adj_size(2); } else { if (count < max_col + adj_size(5)) { col = max_col - 1; } else { col = max_col; } } } pStr = create_string16(NULL, 0, adj_font(10)); pStr->style |= (TTF_STYLE_BOLD | SF_CENTER); count = 0; advance_index_iterate(A_FIRST, i) { if (player_invention_reachable(client.conn.playing, i, FALSE) && TECH_KNOWN == player_invention_state(pVictim, i) && (TECH_UNKNOWN == player_invention_state(client.conn.playing, i) || TECH_PREREQS_KNOWN == player_invention_state(client.conn.playing, i))) { count++; copy_chars_to_string16(pStr, advance_name_translation(advance_by_number(i))); pSurf = create_sellect_tech_icon(pStr, i, FULL_MODE); pBuf = create_icon2(pSurf, pWindow->dst, WF_FREE_THEME | WF_RESTORE_BACKGROUND); set_wstate(pBuf, FC_WS_NORMAL); pBuf->action = spy_steal_callback; pBuf->data.cont = pCont; add_to_gui_list(MAX_ID - i, pBuf); if (count > (col * max_row)) { set_wflag(pBuf, WF_HIDDEN); } } } advance_index_iterate_end; /* get spy tech */ i = advance_number(unit_type(game_unit_by_number(id))->require_advance); copy_chars_to_string16(pStr, _("At Spy's Discretion")); pSurf = create_sellect_tech_icon(pStr, i, FULL_MODE); pBuf = create_icon2(pSurf, pWindow->dst, (WF_FREE_THEME | WF_RESTORE_BACKGROUND| WF_FREE_DATA)); set_wstate(pBuf, FC_WS_NORMAL); pBuf->action = spy_steal_callback; pBuf->data.cont = pCont; add_to_gui_list(MAX_ID - advance_count(), pBuf); count++; /* --------------------------------------------------------- */ FREESTRING16(pStr); pDiplomat_Dlg->pdialog->pBeginWidgetList = pBuf; pDiplomat_Dlg->pdialog->pBeginActiveWidgetList = pDiplomat_Dlg->pdialog->pBeginWidgetList; pDiplomat_Dlg->pdialog->pEndActiveWidgetList = pDiplomat_Dlg->pdialog->pEndWidgetList->prev->prev; /* -------------------------------------------------------------- */ i = 0; if (count > col) { count = (count + (col - 1)) / col; if (count > max_row) { pDiplomat_Dlg->pdialog->pActiveWidgetList = pDiplomat_Dlg->pdialog->pEndActiveWidgetList; count = max_row; i = create_vertical_scrollbar(pDiplomat_Dlg->pdialog, col, count, TRUE, TRUE); } } else { count = 1; } area.w = MAX(area.w, (col * pBuf->size.w + adj_size(2) + i)); area.h = count * pBuf->size.h + adj_size(2); /* alloca window theme and win background buffer */ pSurf = theme_get_background(theme, BACKGROUND_SPYSTEALDLG); if (resize_window(pWindow, pSurf, NULL, (pWindow->size.w - pWindow->area.w) + area.w, (pWindow->size.h - pWindow->area.h) + area.h)) { FREESURFACE(pSurf); } area = pWindow->area; widget_set_position(pWindow, (Main.screen->w - pWindow->size.w) / 2, (Main.screen->h - pWindow->size.h) / 2); /* exit button */ pBuf = pWindow->prev; pBuf->size.x = area.x + area.w - pBuf->size.w - 1; pBuf->size.y = pWindow->size.y + adj_size(2); setup_vertical_widgets_position(col, area.x + 1, area.y, 0, 0, pDiplomat_Dlg->pdialog->pBeginActiveWidgetList, pDiplomat_Dlg->pdialog->pEndActiveWidgetList); if(pDiplomat_Dlg->pdialog->pScroll) { setup_vertical_scrollbar_area(pDiplomat_Dlg->pdialog->pScroll, area.x + area.w, area.y, area.h, TRUE); } redraw_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow, FALSE); widget_mark_dirty(pWindow); return -1; }