/************************************************************************** Marks all techs which are requirements for goal in pplayer->research->inventions[goal].required_techs. Works recursive. **************************************************************************/ static void build_required_techs_helper(struct player *pplayer, Tech_type_id tech, Tech_type_id goal) { /* The is_tech_a_req_for_goal condition is true if the tech is * already marked */ if (!player_invention_reachable(pplayer, tech, FALSE) || player_invention_state(pplayer, tech) == TECH_KNOWN || is_tech_a_req_for_goal(pplayer, tech, goal)) { return; } /* Mark the tech as required for the goal */ BV_SET(player_research_get(pplayer)->inventions[goal].required_techs, tech); if (advance_required(tech, AR_ONE) == goal || advance_required(tech, AR_TWO) == goal) { log_fatal("tech \"%s\": requires itself", advance_name_by_player(pplayer, goal)); exit(EXIT_FAILURE); } build_required_techs_helper(pplayer, advance_required(tech, AR_ONE), goal); build_required_techs_helper(pplayer, advance_required(tech, AR_TWO), goal); }
/**************************************************************************** Returns a bit vector of the roads present at the tile. ****************************************************************************/ bv_roads tile_roads(const struct tile *ptile) { if (!ptile) { bv_roads empty; BV_CLR_ALL(empty); return empty; } #if 0 /* TODO: Use this when tile roads vector always has correct information. * For now we have to construct vector by checking each road separately. */ return ptile->roads; #else { bv_roads roads; BV_CLR_ALL(roads); road_type_iterate(proad) { if (tile_has_road(ptile, proad)) { BV_SET(roads, road_index(proad)); } } road_type_iterate_end; return roads; } #endif }
/**************************************************************************** Set the given terrain at the specified tile. ****************************************************************************/ void tile_set_terrain(struct tile *ptile, struct terrain *pterrain) { /* The terrain change is valid if one of the following is TRUE: * - pterrain is NULL (= unknown terrain) * - ptile is a virtual tile * - pterrain does not has the flag TER_NO_CITIES * - there is no city on ptile. * This should be read as: The terrain change is INVALID if a terrain with * the flag TER_NO_CITIES is given for a real tile with a city (i.e. all * check evaluate to TRUE). */ fc_assert_msg(NULL == pterrain || tile_virtual_check(ptile) || !terrain_has_flag(pterrain, TER_NO_CITIES) || NULL == tile_city(ptile), "At (%d, %d), the terrain \"%s\" (nb %d) doesn't " "support cities, whereas \"%s\" (nb %d) is built there.", TILE_XY(ptile), terrain_rule_name(pterrain), terrain_number(pterrain), city_name(tile_city(ptile)), tile_city(ptile)->id); ptile->terrain = pterrain; if (NULL != pterrain && NULL != ptile->resource && terrain_has_resource(pterrain, ptile->resource)) { /* cannot use set_special() for internal values */ BV_SET(ptile->special, S_RESOURCE_VALID); } else { BV_CLR(ptile->special, S_RESOURCE_VALID); } }
/**************************************************************************** Set the given terrain at the specified tile. ****************************************************************************/ void tile_set_terrain(struct tile *ptile, struct terrain *pterrain) { ptile->terrain = pterrain; if (NULL != pterrain && NULL != ptile->resource && terrain_has_resource(pterrain, ptile->resource)) { /* cannot use set_special() for internal values */ BV_SET(ptile->special, S_RESOURCE_VALID); } else { BV_CLR(ptile->special, S_RESOURCE_VALID); } }
/************************************************************************** Place a spaceship part **************************************************************************/ bool do_spaceship_place(struct player *pplayer, bool user_initiated, enum spaceship_place_type type, int num) { struct player_spaceship *ship = &pplayer->spaceship; if (ship->state == SSHIP_NONE) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("Spaceship action received," " but you don't have a spaceship!")); } return FALSE; } if (ship->state >= SSHIP_LAUNCHED) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("You can't modify your spaceship after launch!")); } return FALSE; } if (type == SSHIP_PLACE_STRUCTURAL) { if (num < 0 || num >= NUM_SS_STRUCTURALS || BV_ISSET(ship->structure, num)) { return FALSE; } if (num_spaceship_structurals_placed(ship) >= ship->structurals) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("You don't have any unplaced Space Structurals!")); } return FALSE; } if (num != 0 && !BV_ISSET(ship->structure, structurals_info[num].required)) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("That Space Structural would not be connected!")); } return FALSE; } BV_SET(ship->structure, num); spaceship_calc_derived(ship); send_spaceship_info(pplayer, NULL); return TRUE; } if (type == SSHIP_PLACE_FUEL) { if (ship->fuel != num - 1) { return FALSE; } if (ship->fuel + ship->propulsion >= ship->components) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("You don't have any unplaced Space Components!")); } return FALSE; } if (num > NUM_SS_COMPONENTS/2) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("Your spaceship already has" " the maximum number of Fuel Components!")); } return FALSE; } ship->fuel++; spaceship_calc_derived(ship); send_spaceship_info(pplayer, NULL); return TRUE; } if (type == SSHIP_PLACE_PROPULSION) { if (ship->propulsion != num - 1) { return FALSE; } if (ship->fuel + ship->propulsion >= ship->components) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("You don't have any unplaced" " Space Components!")); } return FALSE; } if (num > NUM_SS_COMPONENTS/2) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("Your spaceship already has the" " maximum number of Propulsion Components!")); } return FALSE; } ship->propulsion++; spaceship_calc_derived(ship); send_spaceship_info(pplayer, NULL); return TRUE; } if (type == SSHIP_PLACE_HABITATION) { if (ship->habitation != num - 1) { return FALSE; } if (ship->habitation + ship->life_support + ship->solar_panels >= ship->modules) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("You don't have any unplaced Space Modules!")); } return FALSE; } if (num > NUM_SS_MODULES / 3) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("Your spaceship already has the" " maximum number of Habitation Modules!")); } return FALSE; } ship->habitation++; spaceship_calc_derived(ship); send_spaceship_info(pplayer, NULL); return TRUE; } if (type == SSHIP_PLACE_LIFE_SUPPORT) { if (ship->life_support != num - 1) { return FALSE; } if (ship->habitation + ship->life_support + ship->solar_panels >= ship->modules) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("You don't have any unplaced Space Modules!")); } return FALSE; } if (num > NUM_SS_MODULES / 3) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("Your spaceship already has the" " maximum number of Life Support Modules!")); } return FALSE; } ship->life_support++; spaceship_calc_derived(ship); send_spaceship_info(pplayer, NULL); return TRUE; } if (type == SSHIP_PLACE_SOLAR_PANELS) { if (ship->solar_panels != num - 1) { return FALSE; } if (ship->habitation + ship->life_support + ship->solar_panels >= ship->modules) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("You don't have any unplaced Space Modules!")); } return FALSE; } if (num > NUM_SS_MODULES / 3) { if (user_initiated) { notify_player(pplayer, NULL, E_SPACESHIP, ftc_server, _("Your spaceship already has the" " maximum number of Solar Panel Modules!")); } return FALSE; } ship->solar_panels++; spaceship_calc_derived(ship); send_spaceship_info(pplayer, NULL); return TRUE; } log_error("Received unknown spaceship place type %d from %s", type, player_name(pplayer)); return FALSE; }
/************************************************************************** Popup a dialog asking the unit which improvement they would like to pillage. **************************************************************************/ void popup_pillage_dialog(struct unit *punit, bv_special spe, bv_bases bases, bv_roads roads) { Widget shell, form, dlabel, button, prev; struct act_tgt tgt; if (is_showing_pillage_dialog) { return; } is_showing_pillage_dialog = TRUE; unit_to_use_to_pillage = punit->id; XtSetSensitive (toplevel, FALSE); shell = I_T(XtCreatePopupShell("pillagedialog", transientShellWidgetClass, toplevel, NULL, 0)); form = XtVaCreateManagedWidget ("form", formWidgetClass, shell, NULL); dlabel = I_L(XtVaCreateManagedWidget("dlabel", labelWidgetClass, form, NULL)); prev = dlabel; while (get_preferred_pillage(&tgt, spe, bases, roads)) { bv_special what_spe; bv_bases what_base; bv_roads what_road; int what = S_LAST; BV_CLR_ALL(what_spe); BV_CLR_ALL(what_base); BV_CLR_ALL(what_road); switch (tgt.type) { case ATT_SPECIAL: BV_SET(what_spe, tgt.obj.spe); what = tgt.obj.spe; clear_special(&spe, tgt.obj.spe); break; case ATT_BASE: BV_SET(what_base, tgt.obj.base); what = tgt.obj.base + S_LAST; BV_CLR(bases, tgt.obj.base); break; case ATT_ROAD: BV_SET(what_road, tgt.obj.road); what = tgt.obj.road + S_LAST + game.control.num_base_types; BV_CLR(roads, tgt.obj.road); break; } button = XtVaCreateManagedWidget ("button", commandWidgetClass, form, XtNfromVert, prev, XtNlabel, (XtArgVal)(get_infrastructure_text(what_spe, what_base, what_road)), NULL); XtAddCallback(button, XtNcallback, pillage_callback, INT_TO_XTPOINTER(what)); prev = button; } button = I_L(XtVaCreateManagedWidget("closebutton", commandWidgetClass, form, XtNfromVert, prev, NULL)); XtAddCallback (button, XtNcallback, pillage_callback, NULL); xaw_set_relative_position (toplevel, shell, 10, 0); XtPopup (shell, XtGrabNone); }
/**************************************************************************** Adds base to tile. FIXME: Should remove conflicting old base and return bool indicating that. ****************************************************************************/ void tile_add_base(struct tile *ptile, const struct base_type *pbase) { BV_SET(ptile->bases, base_index(pbase)); }