Exemplo n.º 1
0
/*****************************************************************************
  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;
Exemplo n.º 2
0
/*************************************************************************
  Callback from diplomat/spy dialog for "keep moving".
  (This should only occur when entering the tile of an allied unit.)
**************************************************************************/
static void diplomat_keep_moving_unit_callback(GtkWidget *w, gpointer data)
{
    struct unit *punit;
    struct unit *tunit;

    if ((punit = game_unit_by_number(diplomat_id))
            && (tunit = game_unit_by_number(diplomat_target_id[ATK_UNIT]))
            && !same_pos(unit_tile(punit), unit_tile(tunit))) {
        request_diplomat_action(DIPLOMAT_MOVE, diplomat_id,
                                diplomat_target_id[ATK_UNIT], ATK_UNIT);
    }
    gtk_widget_destroy(diplomat_dialog);
}
Exemplo n.º 3
0
/**************************************************************************
 Popup dialog where the user choose the name of the new city
 punit = (settler) unit which builds the city
 suggestname = suggetion of the new city's name
**************************************************************************/
void popup_newcity_dialog(struct unit *punit, const char *suggestname)
{
  input_dialog_create(GTK_WINDOW(toplevel), /*"shellnewcityname" */
                      _("Build New City"),
                      _("What should we call our new city?"), suggestname,
                      name_new_city_popup_callback,
                      GINT_TO_POINTER(tile_index(unit_tile(punit))));
}
Exemplo n.º 4
0
/**************************************************************************
  Callback from diplomat/spy dialog for "keep moving".
  (This should only occur when entering the tile of an allied unit..)
**************************************************************************/
static void diplomat_keep_moving_callback_unit(Widget w,
                                               XtPointer client_data,
                                               XtPointer call_data)
{
  struct unit *punit;
  struct unit *tunit;

  destroy_message_dialog(w);
  diplomat_dialog = NULL;

  if ((punit = game_unit_by_number(diplomat_id))
      && (tunit = game_unit_by_number(diplomat_target_id))
      && !same_pos(unit_tile(punit), unit_tile(tunit))) {
    request_diplomat_action(DIPLOMAT_MOVE, diplomat_id,
                            diplomat_target_id, ATK_UNIT);
  }
  process_diplomat_arrival(NULL, 0);
}
Exemplo n.º 5
0
/****************************************************************
  Callback from diplomat/spy dialog for "keep moving".
  (This should only occur when entering allied city.)
*****************************************************************/
static void diplomat_keep_moving_callback(GtkWidget *w, gpointer data)
{
  struct unit *punit;
  struct city *pcity;

  if ((punit = game_unit_by_number(diplomat_id))
      && (pcity = game_city_by_number(diplomat_target_id))
      && !same_pos(unit_tile(punit), city_tile(pcity))) {
    request_diplomat_action(DIPLOMAT_MOVE, diplomat_id,
                            diplomat_target_id, 0);
  }
  gtk_widget_destroy(diplomat_dialog);
}
Exemplo n.º 6
0
/****************************************************************
  Callback from diplomat/spy dialog for "keep moving".
  (This should only occur when entering allied city.)
*****************************************************************/
static int diplomat_keep_moving_callback(struct widget *pWidget)
{
  if (Main.event.button.button == SDL_BUTTON_LEFT) {
    struct unit *punit;
    struct city *pcity;

    if ((punit = game_unit_by_number(pDiplomat_Dlg->diplomat_id))
        && (pcity = game_city_by_number(pDiplomat_Dlg->diplomat_target_id))
        && !same_pos(unit_tile(punit), city_tile(pcity))) {
      request_diplomat_action(DIPLOMAT_MOVE, pDiplomat_Dlg->diplomat_id,
                              pDiplomat_Dlg->diplomat_target_id, 0);
    }
    
    popdown_diplomat_dialog();  
  }
  return -1;
}
Exemplo n.º 7
0
/**************************************************************************
  Log unit messages, they will appear like this
    2: Polish Archers[139] (5,35)->(0,0){0,0} stays to defend city
  where [] is unit id, ()->() are coordinates present and goto, and
  {,} contains bodyguard and ferryboat ids.
**************************************************************************/
void real_unit_log(const char *file, const char *function, int line,
                   enum log_level level,  bool notify,
                   const struct unit *punit, const char *msg, ...)
{
  char buffer[500];
  char buffer2[500];
  va_list ap;
  int gx, gy;
  char aibuf[500] = "\0";

  CALL_PLR_AI_FUNC(log_fragment_unit, unit_owner(punit), aibuf, sizeof(aibuf), punit);

  if (punit->goto_tile) {
    index_to_map_pos(&gx, &gy, tile_index(punit->goto_tile));
  } else {
    gx = gy = -1;
  }

  fc_snprintf(buffer, sizeof(buffer),
	      "%s %s[%d] %s (%d,%d)->(%d,%d){%s} ",
              nation_rule_name(nation_of_unit(punit)),
              unit_rule_name(punit),
              punit->id,
	      get_activity_text(punit->activity),
	      TILE_XY(unit_tile(punit)),
	      gx, gy, aibuf);

  va_start(ap, msg);
  fc_vsnprintf(buffer2, sizeof(buffer2), msg, ap);
  va_end(ap);

  cat_snprintf(buffer, sizeof(buffer), "%s", buffer2);
  if (notify) {
    notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buffer);
  }
  do_log(file, function, line, FALSE, level, "%s", buffer);
}
Exemplo n.º 8
0
/************************************************************************
  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(&parameter);
      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);
  }

}
Exemplo n.º 9
0
/**********************************************************************
  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;
}
Exemplo n.º 10
0
/**************************************************************************
  Popup a dialog giving a player choices when their caravan arrives at
  a city (other than its home city).  Example:
    - Establish trade route.
    - Help build wonder.
    - Keep moving.
**************************************************************************/
void popup_caravan_dialog(struct unit *pUnit,
			  struct city *pHomecity, struct city *pDestcity)
{
  struct widget *pWindow = NULL, *pBuf = NULL;
  SDL_String16 *pStr;
  struct CONTAINER *pCont;
  char cBuf[128];
  SDL_Rect area;
  
  if (pCaravan_Dlg) {
    return;
  }

  caravan_unit_id=pUnit->id;
  caravan_city_id=pDestcity->id;
  
  pCont = fc_calloc(1, sizeof(struct CONTAINER));
  pCont->id0 = pUnit->id;
  pCont->id1 = pDestcity->id;
  
  pCaravan_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
  is_unit_move_blocked = TRUE;
      
  fc_snprintf(cBuf, sizeof(cBuf), _("Your %s has arrived at %s"),
              unit_name_translation(pUnit), city_name(pDestcity));

  /* window */
  pStr = create_str16_from_char(cBuf, adj_font(12));
  pStr->style |= TTF_STYLE_BOLD;
  
  pWindow = create_window_skeleton(NULL, pStr, 0);
    
  pWindow->action = caravan_dlg_window_callback;
  set_wstate(pWindow, FC_WS_NORMAL);
  
  add_to_gui_list(ID_CARAVAN_DLG_WINDOW, pWindow);
  pCaravan_Dlg->pEndWidgetList = pWindow;

  area = pWindow->area;
  area.h = MAX(area.h, adj_size(2));
  
  /* ---------- */
  if (can_cities_trade(pHomecity, pDestcity))
  {
    int revenue = get_caravan_enter_city_trade_bonus(pHomecity, pDestcity);
    
    if (can_establish_trade_route(pHomecity, pDestcity)) {
      fc_snprintf(cBuf, sizeof(cBuf),
                  _("Establish Trade route with %s ( %d R&G + %d trade )"),
                  city_name(pHomecity),
                  revenue,
                  trade_between_cities(pHomecity, pDestcity));
    } else {
      revenue = (revenue + 2) / 3;
      fc_snprintf(cBuf, sizeof(cBuf),
		_("Enter Marketplace ( %d R&G bonus )"), revenue);
    }

    create_active_iconlabel(pBuf, pWindow->dst, pStr,
	    cBuf, caravan_establish_trade_callback);
    pBuf->data.cont = pCont;
    set_wstate(pBuf, FC_WS_NORMAL);

    add_to_gui_list(ID_LABEL, pBuf);
    
    area.w = MAX(area.w, pBuf->size.w);
    area.h += pBuf->size.h;
  }
  
  /* ---------- */
  if (unit_can_help_build_wonder(pUnit, pDestcity)) {
        
    create_active_iconlabel(pBuf, pWindow->dst, pStr,
	_("Help build Wonder"), caravan_help_build_wonder_callback);
    
    pBuf->data.cont = pCont;
    set_wstate(pBuf, FC_WS_NORMAL);
  
    add_to_gui_list(ID_LABEL, pBuf);
    
    area.w = MAX(area.w, pBuf->size.w);
    area.h += pBuf->size.h;
  }
  /* ---------- */
  
  create_active_iconlabel(pBuf, pWindow->dst, pStr,
	    _("Keep moving"), exit_caravan_dlg_callback);
  
  pBuf->data.cont = pCont;
  set_wstate(pBuf, FC_WS_NORMAL);
  set_wflag(pBuf, WF_FREE_DATA);
  pBuf->key = SDLK_ESCAPE;
  
  add_to_gui_list(ID_LABEL, pBuf);
    
  area.w = MAX(area.w, pBuf->size.w);
  area.h += pBuf->size.h;
  /* ---------- */
  pCaravan_Dlg->pBeginWidgetList = pBuf;
  
  /* setup window size and start position */
  
  resize_window(pWindow, NULL, NULL,
                (pWindow->size.w - pWindow->area.w) + area.w,
                (pWindow->size.h - pWindow->area.h) + area.h);
  
  area = pWindow->area;
  
  auto_center_on_focus_unit();
  put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
                           unit_tile(pUnit));

  /* setup widget size and start position */
    
  pBuf = pWindow->prev;
  setup_vertical_widgets_position(1,
	area.x,
  	area.y + 1, area.w, 0,
	pCaravan_Dlg->pBeginWidgetList, pBuf);
  /* --------------------- */
  /* redraw */
  redraw_group(pCaravan_Dlg->pBeginWidgetList, pWindow, 0);

  widget_flush(pWindow);
}
Exemplo n.º 11
0
/**************************************************************************
  Main handler for key presses
**************************************************************************/
static Uint16 main_key_down_handler(SDL_keysym Key, void *pData)
{
    static struct widget *pWidget;
    if ((pWidget = find_next_widget_for_key(NULL, Key)) != NULL) {
        return widget_pressed_action(pWidget);
    } else {
        if (Key.sym == SDLK_TAB) {
            /* input */
            popup_input_line();
        } else {
            if (map_event_handler(Key)
                    && C_S_RUNNING == client_state()) {
                switch (Key.sym) {
                case SDLK_RETURN:
                case SDLK_KP_ENTER:
                    if (LSHIFT || RSHIFT) {
                        disable_focus_animation();
                        key_end_turn();
                    } else {
                        struct unit *pUnit;
                        struct city *pCity;
                        if (NULL != (pUnit = head_of_units_in_focus()) &&
                                (pCity = tile_city(unit_tile(pUnit))) != NULL &&
                                city_owner(pCity) == client.conn.playing) {
                            popup_city_dialog(pCity);
                        }
                    }
                    return ID_ERROR;

                case SDLK_F2:
                    units_report_dialog_popup(FALSE);
                    return ID_ERROR;

                case SDLK_F4:
                    city_report_dialog_popup(FALSE);
                    return ID_ERROR;

                case SDLK_F7:
                    send_report_request(REPORT_WONDERS_OF_THE_WORLD);
                    return ID_ERROR;

                case SDLK_F8:
                    send_report_request(REPORT_TOP_5_CITIES);
                    return ID_ERROR;

                case SDLK_F9:
                    if (meswin_dialog_is_open()) {
                        meswin_dialog_popdown();
                    } else {
                        meswin_dialog_popup(TRUE);
                    }
                    flush_dirty();
                    return ID_ERROR;

                case SDLK_F11:
                    send_report_request(REPORT_DEMOGRAPHIC);
                    return ID_ERROR;

                case SDLK_F12:
                    popup_spaceship_dialog(client.conn.playing);
                    return ID_ERROR;

                default:
                    return ID_ERROR;
                }
            }
        }
    }

    return ID_ERROR;
}
Exemplo n.º 12
0
/**************************************************************************
  Click a link.
**************************************************************************/
static gboolean event_after(GtkWidget *text_view, GdkEventButton *event)
{
  GtkTextIter start, end, iter;
  GtkTextBuffer *buffer;
  GSList *tags, *tagp;
  gint x, y;
  struct tile *ptile = NULL;

  if (event->type != GDK_BUTTON_RELEASE || event->button != 1) {
    return FALSE;
  }

  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));

  /* We shouldn't follow a link if the user has selected something. */
  gtk_text_buffer_get_selection_bounds(buffer, &start, &end);
  if (gtk_text_iter_get_offset(&start) != gtk_text_iter_get_offset(&end)) {
    return FALSE;
  }

  gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW (text_view), 
                                        GTK_TEXT_WINDOW_WIDGET,
                                        event->x, event->y, &x, &y);

  gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(text_view), &iter, x, y);

  if ((tags = gtk_text_iter_get_tags(&iter))) {
    for (tagp = tags; tagp; tagp = tagp->next) {
      GtkTextTag *tag = tagp->data;
      enum text_link_type type =
        GPOINTER_TO_INT(g_object_get_data(G_OBJECT(tag), "type"));

      if (type != 0) {
        /* This is a link. */
        int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(tag), "id"));
        ptile = NULL;

        /* Real type is type - 1.
         * See comment in apply_text_tag() for g_object_set_data(). */
        type--;

        switch (type) {
        case TLT_CITY:
          {
            struct city *pcity = game_city_by_number(id);

            if (pcity) {
              ptile = client_city_tile(pcity);
            } else {
              output_window_append(ftc_client, _("This city isn't known!"));
            }
          }
          break;
        case TLT_TILE:
          ptile = index_to_tile(id);

          if (!ptile) {
            output_window_append(ftc_client,
                                 _("This tile doesn't exist in this game!"));
          }
          break;
        case TLT_UNIT:
          {
            struct unit *punit = game_unit_by_number(id);

            if (punit) {
              ptile = unit_tile(punit);
            } else {
              output_window_append(ftc_client, _("This unit isn't known!"));
            }
          }
          break;
        }

        if (ptile) {
          center_tile_mapcanvas(ptile);
          link_mark_restore(type, id);
          gtk_widget_grab_focus(GTK_WIDGET(map_canvas));
        }
      }
    }
    g_slist_free(tags);
  }

  return FALSE;
}