Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doxygen improvements #2476

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ build.ninja

# Build directories
/build*
/doxygen
.flatpak-builder

# Nix build artifacts
Expand Down
9 changes: 9 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ build:
os: ubuntu-22.04
tools:
python: "3.10"
apt_packages:
- graphviz
jobs:
pre_build:
# Creates the documentation in the doxygen/ subfolder
- doxygen
post_build:
# Move the output to be hosted
- mv doxygen/html $READTHEDOCS_OUTPUT/html/Doxygen

# Build documentation in the docs/ directory with Sphinx
sphinx:
Expand Down
1,208 changes: 830 additions & 378 deletions doc/freeciv.doxygen → Doxyfile

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2518,7 +2518,7 @@ void do_map_click(struct tile *ptile, enum quickselect_type qtype)
}

/**
Quickselecting a unit is normally done with <control> left, right click,
Quickselecting a unit is normally done with [control] left, right click,
for the current tile. Bypassing the stack popup is quite convenient,
and can be tactically important in furious multiplayer games.
*/
Expand Down
2 changes: 1 addition & 1 deletion client/shortcuts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ void shortcut_edit::set_shortcut(const fc_shortcut &shortcut)
}

/**
* \reimp
* Reimplemented from QObject
*/
bool shortcut_edit::event(QEvent *event)
{
Expand Down
4 changes: 2 additions & 2 deletions client/tileset/drawn_sprite.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ class QRect;
struct tileset;

struct drawn_sprite {
explicit drawn_sprite(const tileset *ts, const QPixmap *sprite,
explicit drawn_sprite(const struct tileset *ts, const QPixmap *sprite,
bool foggable = true, int offset_x = 0,
int offset_y = 0);
explicit drawn_sprite(const tileset *ts, const QPixmap *sprite,
explicit drawn_sprite(const struct tileset *ts, const QPixmap *sprite,
bool foggable, const QPoint &offset);
drawn_sprite(const drawn_sprite &other) = default;
drawn_sprite(drawn_sprite &&other) = default;
Expand Down
2 changes: 1 addition & 1 deletion client/tileset/layer_base_flags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace freeciv {
/**
* @class layer_base_flags
*
* Map layer that draws flags for bases that have @ref EF_SHOW_FLAG set.
* Map layer that draws flags for bases that have EF_SHOW_FLAG set.
*/

layer_base_flags::layer_base_flags(struct tileset *ts, const QPoint &offset)
Expand Down
2 changes: 1 addition & 1 deletion client/utils/colorizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace freeciv {

/**
* @class colorizer Swaps colors in QPixmap
* @class colorizer colorizer.h Swaps colors in QPixmap
*
* Starting from a base pixmap, this class generates new pixmaps with one
* color replaced (for instance, all pink pixels changed to green).
Expand Down
2 changes: 1 addition & 1 deletion client/views/view_map_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ void set_mapview_origin(float gui_x0, float gui_y0)

/**
Return the scroll dimensions of the clipping window for the mapview
window..
window.

Imagine the entire map in scroll coordinates. It is a rectangle. Now
imagine the mapview "window" sliding around through this rectangle. How
Expand Down
4 changes: 2 additions & 2 deletions common/aicore/path_finding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,14 @@ struct pf_map {
/**
* Casts to `pf_map`
*
* \fixme Capitalized because this used to be a macro.
* \todo Capitalized because this used to be a macro.
*/
pf_map *PF_MAP(void *x) { return reinterpret_cast<pf_map *>(x); }

/**
* Casts to `pf_map`
*
* \fixme Capitalized because this used to be a macro.
* \todo Capitalized because this used to be a macro.
*/
const pf_map *PF_MAP(const void *x)
{
Expand Down
8 changes: 4 additions & 4 deletions common/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,10 +738,10 @@ static char *year_suffix()
Generate a default save file name and place it in the provided buffer.
Within the name the following custom formats are allowed:

%R = <reason>
%S = <suffix>
%T = <game.info.turn>
%Y = <game.info.year>
%R = [reason]
%S = [suffix]
%T = [game.info.turn]
%Y = [game.info.year]

Examples:
'freeciv-T%04T-Y%+04Y-%R' => 'freeciv-T0099-Y-0050-manual'
Expand Down
16 changes: 7 additions & 9 deletions common/mapimg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,8 +1042,8 @@ bool mapimg_id2str(int id, char *str, size_t str_len)

/**
Create the requested map image. The filename is created as
<basename as used for savegames>-<mapstr>.<mapext> where <mapstr>
contains the map definition and <mapext> the selected image extension.
`basename as used for savegames-mapstr.mapext` where `mapstr`
contains the map definition and `mapext` the selected image extension.
If 'force' is FALSE, the image is only created if game.info.turn is a
multiple of the map setting turns.
*/
Expand Down Expand Up @@ -1150,9 +1150,8 @@ bool mapimg_create(struct mapdef *pmapdef, bool force, const char *savename,

/**
Create images which shows all map colors (playercolor, terrain colors).
One image is created for each supported toolkit and image format. The
filename will be <basename as used for
savegames>-colortest-<toolkit>.<format>.
One image is created for each supported image format. The filename will be
[basename as used for savegames]-colortest.[format].
*/
bool mapimg_colortest(const char *savename, const char *path)
{
Expand Down Expand Up @@ -1413,11 +1412,10 @@ static void mapimg_log(const char *file, const char *function, int line,
/**
Generate an identifier for a map image.

M<map options>Z<zoom factor>P<players>
`M[map options]Z[zoom factor]P[players]`

<map options> map options
<zoom factor> zoom factor
<players> player ID or vector of size MAX_NUM_PLAYER_SLOTS [0/1]
Where `[players]` is the player ID or vector of size MAX_NUM_PLAYER_SLOTS
[0/1].

For the player bitvector all MAX_NUM_PLAYER_SLOTS values are used due to
the possibility of additional players during the game (civil war,
Expand Down
8 changes: 4 additions & 4 deletions common/rgbcolor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ void rgbcolor_destroy(struct rgbcolor *prgbcolor)
}

/**
Lookup an RGB color definition (<colorpath>.red, <colorpath>.green and
<colorpath>.blue). Returns TRUE on success and FALSE on error.
Lookup an RGB color definition (`[colorpath].red`, `[colorpath].green` and
`[colorpath].blue`). Returns TRUE on success and FALSE on error.
*/
bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor,
const char *path, ...)
Expand Down Expand Up @@ -103,8 +103,8 @@ bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor,
}

/**
Save an RGB color definition (<colorpath>.red, <colorpath>.green and
<colorpath>.blue).
Save an RGB color definition (`[colorpath].red`, `[colorpath].green` and
`[colorpath].blue`).
*/
void rgbcolor_save(struct section_file *file,
const struct rgbcolor *prgbcolor, const char *path, ...)
Expand Down
3 changes: 2 additions & 1 deletion common/scriptcore/luascript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ int luascript_error_vargs(lua_State *L, const char *format, va_list vargs)

/**
Like script_error, but using a prefix identifying the called lua function:
bad argument #narg to '<func>': msg

bad argument #narg to 'func': msg
*/
int luascript_arg_error(lua_State *L, int narg, const char *msg)
{
Expand Down
18 changes: 16 additions & 2 deletions docs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,29 @@ else()
find_package(Sphinx QUIET)
endif()

if(SPHINX_FOUND)
message(STATUS "Sphinx Found, configuring.")
find_package(Doxygen)

if (SPHINX_FOUND AND DOXYGEN_FOUND)
message(STATUS "Sphinx and Doxygen found, configuring.")

set(SPHINX_SOURCE ${CMAKE_SOURCE_DIR}/docs)
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR})
set(SPHINX_MAN ${CMAKE_CURRENT_BINARY_DIR}/man)

# We need to run doxygen before sphinx to update doxygen/tagfile.xml. This
# command does it. The output is a dummy one so the command always runs.
# doxygen has some level of caching so it doesn't take that long, and
# collecting a list of all source files would be cumbersome.
add_custom_command(OUTPUT dummy-doxygen
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not call this "dummy", I would simply call this what it is. You are building doxy. I'd prefer it be in /build tho, vs the root so we don't need another .gitignore.

Copy link
Contributor Author

@lmoureaux lmoureaux Dec 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not call this "dummy", I would simply call this what it is. You are building doxy.

The output is really a dummy one. CMake expects a file there, but I give something that never gets produced to force running doxygen every time. This is what the comment above tries to explain.

I'd prefer it be in /build tho, vs the root so we don't need another .gitignore.

The output folder is set in the Doxyfile and cannot be overridden in the Doxygen command line. I cannot easily change it because I need to run doxygen in the RTD builder, and installing all the dependencies there would be overkill. Maybe I can come up with some CMake magic to configure the Doxyfile on RTD...

COMMAND Doxygen::doxygen
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
COMMENT "Running Doxygen")

# This builds the main documentation website.
add_custom_target(docs
COMMAND
${SPHINX_EXECUTABLE} -b html ${SPHINX_SOURCE} ${SPHINX_BUILD}
DEPENDS dummy-doxygen
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating documentation with Sphinx")

Expand Down
40 changes: 20 additions & 20 deletions docs/Coding/ai.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The long-term goals for Freeciv21 :term:`AI` development are:
Want Calculations
=================

Build calculations are expressed through a structure called :code:`adv_choice`. This has a variable called
Build calculations are expressed through a structure called :freeciv21:`adv_choice`. This has a variable called
"want", which determines how much the :term:`AI` wants whatever item is pointed to by :code:`choice->type`.
:code:`choice->want` is:

Expand Down Expand Up @@ -69,36 +69,36 @@ Diplomats, in particular, seem to violate these standards.
Amortize
========

Hard fact: :code:`amortize(benefit, delay)` returns
Hard fact: :freeciv21:`amortize` returns
:math:`\texttt{benefit} \times \left(1 - \frac{1}{\texttt{MORT}}\right)^{\texttt{delay}}`.

Speculation: What is better... to receive $10 annually starting in 5 years from now or $5 annually starting
from this year? How can you take inflation into account? The function :code:`amortize()` is meant to help you
from this year? How can you take inflation into account? The function :freeciv21:`amortize` is meant to help you
answer these questions. To achieve this, it re-scales the future benefit in terms of today's money.

Suppose we have a constant rate of inflation, :math:`x` percent. Then in five years $10 will buy as much
as :math:`10\left(\frac{100}{100 + x}\right)^5` will buy today. Denoting :math:`\frac{100}{100+x}` by
:math:`q` we get the general formula, :math:`N` dollars, :math:`Y` years from now will be worth
:math:`N\times q^Y` in today's money. If we receive :math:`N` every year starting :math:`Y` years from now, the
total amount receivable (in today's money) is :math:`\frac{\,N\,\times\, q^Y}{1 - q}`. This is the sum of
infinite geometric series. This is exactly the operation that the :code:`amortize()` function performs, the
infinite geometric series. This is exactly the operation that the :code:`amortize` function performs, the
multiplication by some :math:`q < 1` raised to power :math:`Y`. Note that the factor :math:`\frac{1}{1 - q}`
does not depend on the parameters :math:`N` and :math:`Y`, and can be ignored. The connection between the
:math:`\texttt{MORT}` constant and the inflation rate :math:`x` is given by
:math:`\frac{\texttt{MORT} - 1}{\texttt{MORT}} = q = \frac{100}{100 + x}`. Thus the current value of
:math:`\texttt{MORT} = 24` corresponds to the inflation rate, or the rate of expansion of your civilization of
4.3%

Most likely this explanation is not what the authors of :code:`amortize()` had in mind, but the basic idea is
Most likely this explanation is not what the authors of :freeciv21:`amortize` had in mind, but the basic idea is
correct: the value of the payoff decays exponentially with the delay.

The version of amortize used in the military code (:code:`military_amortize()`) remains a complete mystery.
The version of amortize used in the military code (:freeciv21:`military_amortize`) remains a complete mystery.


Estimation of Profit From a Military Operation
==============================================

This estimation is implemented by the :code:`kill_desire()` function, which is not perfect, the
This estimation is implemented by the :freeciv21:`kill_desire` function, which is not perfect, the
:code:`multi-victim` part is flawed, plus some corrections. In general:

.. math::
Expand Down Expand Up @@ -126,7 +126,7 @@ Selecting Military Units

The code dealing with choosing military units to be built and targets for them is especially messy.

Military units are requested in the :code:`military_advisor_choose_build()` function. It first considers the
Military units are requested in the :freeciv21:`military_advisor_choose_build` function. It first considers the
defensive units and then ventures into selection of attackers (if home is safe). There are two possibilities
here: we just build a new attacker or we already have an attacker which was forced, for some reason, to defend.
In the second case it is easy: we calculate how good the existing attacker is and if it is good, we build a
Expand All @@ -135,17 +135,17 @@ defender to free it up.
Building a brand new attacker is more complicated. First, the :code:`ai_choose_attacker_*` functions are
called to find the first approximation to the best attacker that can be built here. This prototype attacker
is selected using very simple :math:`\texttt{attack\_power}\times\texttt{speed}` formula. Then, already in the
:code:`kill_something_with()` function, we search for targets for the prototype attacker using the
:code:`find_something_to_kill()` function. Having found a target, we do the last refinement by calling the
:code:`process_attacker_want()` function to look for the best attacker type to take out the target. This type
will be our attacker of choice. Note that the :code:`function process_attacker_want()` function has side-effects
:freeciv21:`kill_something_with` function, we search for targets for the prototype attacker using the
:freeciv21:`find_something_to_kill` function. Having found a target, we do the last refinement by calling the
:freeciv21:`process_attacker_want` function to look for the best attacker type to take out the target. This type
will be our attacker of choice. Note that the function :freeciv21:`process_attacker_want` function has side-effects
with regards to the Technology selection.

Here is an example:

First the :code:`ai_choose_attacker_land()` function selects a :unit:`Dragoon` because it is strong and fast.
Then the :code:`find_something_to_kill()` function finds a victim for the (virtual) :unit:`Dragoon`, an enemy
:unit:`Riflemen` standing right next to the city. Then the :code:`process_attacker_want()` function figures
First the :freeciv21:`dai_choose_attacker` function selects a :unit:`Dragoon` because it is strong and fast.
Then the :freeciv21:`find_something_to_kill` function finds a victim for the (virtual) :unit:`Dragoon`, an enemy
:unit:`Riflemen` standing right next to the city. Then the :freeciv21:`process_attacker_want` function figures
out that since the enemy is right beside us, it can be taken out easier using an :unit:`Artillery`. It also
figures that a :unit:`Howitzer` would do this job even better, so bumps up our desire for
:advance:`Robotics`.
Expand Down Expand Up @@ -232,7 +232,7 @@ There are currently seven difficulty levels:

The ``hard`` level is no-holds-barred. ``Cheating`` is the same except that it has ruleset defined extra
bonuses, while ``normal`` has a number of handicaps. In ``easy``, the :term:`AI` also does random stupid
things through the :code:`ai_fuzzy()` function. In ``novice`` the :term:`AI` researches slower than normal
things through the :freeciv21:`ai_fuzzy` function. In ``novice`` the :term:`AI` researches slower than normal
players. The ``experimental`` level is only for coding. You can gate new code with the ``H_EXPERIMENTAL``
handicap and test ``experimental`` level :term:`AI`'s against ``hard`` level :term:`AI`'s.

Expand Down Expand Up @@ -261,7 +261,7 @@ Other handicaps used are:
``H_DANGER`` Always thinks its city is in danger.
================= =======

For an up-to-date list of all handicaps and their use for each difficulty level see :file:`ai/handicaps.h`.
For an up-to-date list of all handicaps and their use for each difficulty level see :freeciv21:`handicaps.h`.


Things That Need To Be Fixed
Expand All @@ -278,15 +278,15 @@ Things That Need To Be Fixed
* :term:`AI` sometimes believes that wasting a horde of weak military units to kill one enemy is profitable.
* Stop building shore defense improvements in landlocked cities with a Lake adjacent.
* Fix the :term:`AI` valuation of :improvement:`Supermarket`. It currently never builds it. See the
:code:`farmland_food()` and :code:`ai_eval_buildings()` functions in :file:`advdomestic.cpp`.
:freeciv21:`building_advisor_choose` function in :freeciv21:`advbuilding.cpp`.
* Teach the :term:`AI` to coordinate the units in an attack.


Idea Space
==========

* Friendly cities can be used as beachheads.
* The :code:`Assess_danger()` function should acknowledge positive feedback between multiple attackers.
* The :freeciv21:`assess_danger` function should acknowledge positive feedback between multiple attackers.
* It would be nice for a bodyguard and charge to meet en-route more elegantly.
* The :code:`struct choice` should have a priority indicator in it. This will reduce the number of "special"
* The :freeciv21:`choice` struct should have a priority indicator in it. This will reduce the number of "special"
want values and remove the necessity to have want capped, thus reducing confusion.
Loading
Loading