From 8fc5bfaaa6c2a3b593c5bb8b5378a3f33f5fbeb1 Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Tue, 29 Oct 2024 18:22:50 +0200
Subject: [PATCH 53/53] Add comment field for enablers

See RM #1031

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 common/actions.c                   |  7 ++++++-
 common/actions.h                   | 12 ++++++++----
 data/alien/actions.ruleset         |  2 ++
 data/civ1/actions.ruleset          |  2 ++
 data/civ2/actions.ruleset          |  2 ++
 data/civ2civ3/actions.ruleset      |  2 ++
 data/classic/actions.ruleset       |  2 ++
 data/goldkeep/actions.ruleset      |  2 ++
 data/granularity/actions.ruleset   |  2 ++
 data/multiplayer/actions.ruleset   |  2 ++
 data/ruledit/comments-3.3.txt      |  2 ++
 data/sandbox/actions.ruleset       |  2 ++
 data/stub/actions.ruleset          |  2 ++
 data/webperimental/actions.ruleset |  2 ++
 server/ruleset/rscompat.c          | 10 +++++-----
 server/ruleset/ruleload.c          | 14 ++++++++++----
 tools/ruledit/tab_enablers.cpp     |  8 ++++----
 tools/ruleutil/rulesave.c          |  6 +++++-
 18 files changed, 62 insertions(+), 19 deletions(-)

diff --git a/common/actions.c b/common/actions.c
index 4356caf9f1..99656cf502 100644
--- a/common/actions.c
+++ b/common/actions.c
@@ -1457,7 +1457,8 @@ struct action_enabler *action_enabler_new(void)
   struct action_enabler *enabler;
 
   enabler = fc_malloc(sizeof(*enabler));
-  enabler->ruledit_disabled = FALSE;
+  enabler->rulesave.ruledit_disabled = FALSE;
+  enabler->rulesave.comment = nullptr;
   requirement_vector_init(&enabler->actor_reqs);
   requirement_vector_init(&enabler->target_reqs);
 
@@ -1473,6 +1474,10 @@ struct action_enabler *action_enabler_new(void)
 **************************************************************************/
 void action_enabler_free(struct action_enabler *enabler)
 {
+  if (enabler->rulesave.comment != nullptr) {
+    free(enabler->rulesave.comment);
+  }
+
   requirement_vector_free(&enabler->actor_reqs);
   requirement_vector_free(&enabler->target_reqs);
 
diff --git a/common/actions.h b/common/actions.h
index c1c2aff0e5..67ebb3b6f4 100644
--- a/common/actions.h
+++ b/common/actions.h
@@ -167,9 +167,13 @@ struct action_enabler
   struct requirement_vector actor_reqs;
   struct requirement_vector target_reqs;
 
-  /* Only relevant for ruledit and other rulesave users. Indicates that
-   * this action enabler is deleted and shouldn't be saved. */
-  bool ruledit_disabled;
+  struct {
+    /* Only relevant for ruledit and other rulesave users. Indicates that
+     * this action enabler is deleted and shouldn't be saved. */
+    bool ruledit_disabled;
+
+    char *comment;
+  } rulesave;
 };
 
 #define action_has_result(_act_, _res_) ((_act_)->result == (_res_))
@@ -186,7 +190,7 @@ struct action_enabler
 
 #define action_enabler_list_re_iterate(action_enabler_list, aenabler) \
   action_enabler_list_iterate(action_enabler_list, aenabler) {        \
-    if (!aenabler->ruledit_disabled) {
+    if (!aenabler->rulesave.ruledit_disabled) {
 
 #define action_enabler_list_re_iterate_end                            \
     }                                                                 \
diff --git a/data/alien/actions.ruleset b/data/alien/actions.ruleset
index a6db6ac944..b3710a3530 100644
--- a/data/alien/actions.ruleset
+++ b/data/alien/actions.ruleset
@@ -375,6 +375,8 @@ quiet_actions = "Transport Disembark 2", "Enter Hut 2", "Unit Move"
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/data/civ1/actions.ruleset b/data/civ1/actions.ruleset
index 47e27958f6..4bc28437cc 100644
--- a/data/civ1/actions.ruleset
+++ b/data/civ1/actions.ruleset
@@ -356,6 +356,8 @@ quiet_actions = "Enter Hut 2", "Unit Move"
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/data/civ2/actions.ruleset b/data/civ2/actions.ruleset
index 5251849ffc..d1fa74ccd9 100644
--- a/data/civ2/actions.ruleset
+++ b/data/civ2/actions.ruleset
@@ -410,6 +410,8 @@ quiet_actions = "Unit Move"
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/data/civ2civ3/actions.ruleset b/data/civ2civ3/actions.ruleset
index 2fcd04a18a..8543214e7d 100644
--- a/data/civ2civ3/actions.ruleset
+++ b/data/civ2civ3/actions.ruleset
@@ -457,6 +457,8 @@ quiet_actions = "Transport Disembark 2", "Conquer City Shrink 2", "Enter Hut 2",
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/data/classic/actions.ruleset b/data/classic/actions.ruleset
index f9322c3460..bae2eaae90 100644
--- a/data/classic/actions.ruleset
+++ b/data/classic/actions.ruleset
@@ -449,6 +449,8 @@ quiet_actions = "Transport Disembark 2", "Conquer City Shrink 2", "Enter Hut 2",
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/data/goldkeep/actions.ruleset b/data/goldkeep/actions.ruleset
index 433c9f2a2d..8a8a48e381 100644
--- a/data/goldkeep/actions.ruleset
+++ b/data/goldkeep/actions.ruleset
@@ -449,6 +449,8 @@ quiet_actions = "Transport Disembark 2", "Conquer City Shrink 2", "Enter Hut 2",
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/data/granularity/actions.ruleset b/data/granularity/actions.ruleset
index e9a6e9733a..ff369edf32 100644
--- a/data/granularity/actions.ruleset
+++ b/data/granularity/actions.ruleset
@@ -242,6 +242,8 @@ quiet_actions = "Transport Disembark 2", "Unit Move"
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/data/multiplayer/actions.ruleset b/data/multiplayer/actions.ruleset
index 243d39d1cc..e72e3565a8 100644
--- a/data/multiplayer/actions.ruleset
+++ b/data/multiplayer/actions.ruleset
@@ -440,6 +440,8 @@ quiet_actions = "Transport Disembark 2", "Conquer City Shrink 2", "Enter Hut 2",
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/data/ruledit/comments-3.3.txt b/data/ruledit/comments-3.3.txt
index 6bc05e9c8b..f86d52e717 100644
--- a/data/ruledit/comments-3.3.txt
+++ b/data/ruledit/comments-3.3.txt
@@ -1153,6 +1153,8 @@ enablers = "\
 ; action               = the action to enable.\n\
 ; actor_reqs           = requirements that apply to the actor.\n\
 ; target_reqs          = requirements that apply to the target.\n\
+; comment              = Comment for the benefit to someone examining the ruleset\n\
+;                        Not used by freeciv any other way.\n\
 ;\n\
 ; README.actions lists the possible actions and their hard coded\n\
 ; requirements.\n\
diff --git a/data/sandbox/actions.ruleset b/data/sandbox/actions.ruleset
index 673fb2a578..4f3e185339 100644
--- a/data/sandbox/actions.ruleset
+++ b/data/sandbox/actions.ruleset
@@ -521,6 +521,8 @@ quiet_actions = "Transport Disembark 2", "Conquer City Shrink 2", "Enter Hut 2",
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/data/stub/actions.ruleset b/data/stub/actions.ruleset
index bf32446376..a5784ba9f5 100644
--- a/data/stub/actions.ruleset
+++ b/data/stub/actions.ruleset
@@ -182,6 +182,8 @@ found_city_consuming_always = TRUE
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/data/webperimental/actions.ruleset b/data/webperimental/actions.ruleset
index e896cd3de7..7115e0f5fb 100644
--- a/data/webperimental/actions.ruleset
+++ b/data/webperimental/actions.ruleset
@@ -410,6 +410,8 @@ quiet_actions = "Heal Unit", "Unit Move"
 ; action               = the action to enable.
 ; actor_reqs           = requirements that apply to the actor.
 ; target_reqs          = requirements that apply to the target.
+; comment              = Comment for the benefit to someone examining the ruleset
+;                        Not used by freeciv any other way.
 ;
 ; README.actions lists the possible actions and their hard coded
 ; requirements.
diff --git a/server/ruleset/rscompat.c b/server/ruleset/rscompat.c
index bfe695946f..156e62f070 100644
--- a/server/ruleset/rscompat.c
+++ b/server/ruleset/rscompat.c
@@ -189,7 +189,7 @@ rscompat_enabler_add_obligatory_hard_reqs(struct action_enabler *ae)
                  " Don't know how to fix it."
                  " Dropping it.",
                 action_rule_name(paction), problem->description);
-      ae->ruledit_disabled = TRUE;
+      ae->rulesave.ruledit_disabled = TRUE;
 
       req_vec_problem_free(problem);
       return TRUE;
@@ -223,7 +223,7 @@ rscompat_enabler_add_obligatory_hard_reqs(struct action_enabler *ae)
                  " for %s: %s"
                  " Dropping it.",
                  action_rule_name(paction), problem->description);
-        ae->ruledit_disabled = TRUE;
+        ae->rulesave.ruledit_disabled = TRUE;
         req_vec_problem_free(problem);
         return TRUE;
       }
@@ -249,7 +249,7 @@ rscompat_enabler_add_obligatory_hard_reqs(struct action_enabler *ae)
                   req_vec_change_translation(
                     &problem->suggested_solutions[i],
                     action_enabler_vector_by_number_name));
-        new_enabler->ruledit_disabled = TRUE;
+        new_enabler->rulesave.ruledit_disabled = TRUE;
         req_vec_problem_free(problem);
         return TRUE;
       }
@@ -257,7 +257,7 @@ rscompat_enabler_add_obligatory_hard_reqs(struct action_enabler *ae)
       if (problem->num_suggested_solutions - 1 == i) {
         /* The last modification is to the original enabler. */
         ae->action = new_enabler->action;
-        ae->ruledit_disabled = new_enabler->ruledit_disabled;
+        ae->rulesave.ruledit_disabled = new_enabler->rulesave.ruledit_disabled;
         requirement_vector_copy(&ae->actor_reqs,
                                 &new_enabler->actor_reqs);
         requirement_vector_copy(&ae->target_reqs,
@@ -315,7 +315,7 @@ void rscompat_enablers_add_obligatory_hard_reqs(void)
     do {
       restart_enablers_for_action = FALSE;
       action_enabler_list_iterate(action_enablers_for_action(act_id), ae) {
-        if (ae->ruledit_disabled) {
+        if (ae->rulesave.ruledit_disabled) {
           /* Ignore disabled enablers */
           continue;
         }
diff --git a/server/ruleset/ruleload.c b/server/ruleset/ruleload.c
index 3ff7d60893..ab4943e226 100644
--- a/server/ruleset/ruleload.c
+++ b/server/ruleset/ruleload.c
@@ -260,7 +260,7 @@ static int ruleset_purge_unused_enablers(void)
       /* Make sure that all action enablers are disabled. */
       action_enabler_list_iterate(action_enablers_for_action(paction->id),
                                   ae) {
-        ae->ruledit_disabled = TRUE;
+        ae->rulesave.ruledit_disabled = TRUE;
         purged++;
       } action_enabler_list_iterate_end;
 
@@ -271,10 +271,10 @@ static int ruleset_purge_unused_enablers(void)
     /* Impossible requirement vector requirement. */
     action_enabler_list_iterate(action_enablers_for_action(paction->id),
                                 ae) {
-      if (!ae->ruledit_disabled
+      if (!ae->rulesave.ruledit_disabled
           && (!action_enabler_possible_actor(ae)
               || req_vec_is_impossible_to_fulfill(&ae->target_reqs))) {
-        ae->ruledit_disabled = TRUE;
+        ae->rulesave.ruledit_disabled = TRUE;
         purged++;
         log_normal("Purged unused action enabler for %s",
                    action_rule_name(paction));
@@ -443,7 +443,7 @@ static int ruleset_purge_redundant_reqs_enablers(void)
     /* Do the purging. */
     action_enabler_list_iterate(action_enablers_for_action(paction->id),
                                 ae) {
-      while (!ae->ruledit_disabled
+      while (!ae->rulesave.ruledit_disabled
              && (purge_redundant_req_vec(&ae->actor_reqs, actor_reqs)
                  || purge_redundant_req_vec(&ae->target_reqs,
                                             target_reqs))) {
@@ -7868,6 +7868,7 @@ static bool load_ruleset_actions(struct section_file *file,
         struct requirement_vector *actor_reqs;
         struct requirement_vector *target_reqs;
         const char *action_text;
+        const char *comment;
 
         enabler = action_enabler_new();
 
@@ -7908,6 +7909,11 @@ static bool load_ruleset_actions(struct section_file *file,
 
         requirement_vector_copy(&enabler->target_reqs, target_reqs);
 
+        comment = secfile_lookup_str(file, "%s.comment", sec_name);
+        if (comment != nullptr) {
+          enabler->rulesave.comment = fc_strdup(comment);
+        }
+
         action_enabler_add(enabler);
       } section_list_iterate_end;
 
diff --git a/tools/ruledit/tab_enablers.cpp b/tools/ruledit/tab_enablers.cpp
index 66b95896fb..44a1d2dba5 100644
--- a/tools/ruledit/tab_enablers.cpp
+++ b/tools/ruledit/tab_enablers.cpp
@@ -182,7 +182,7 @@ void tab_enabler::refresh()
   enabler_list->clear();
 
   action_enablers_iterate(enabler) {
-    if (!enabler->ruledit_disabled) {
+    if (!enabler->rulesave.ruledit_disabled) {
       char buffer[512];
       QListWidgetItem *item;
 
@@ -284,7 +284,7 @@ void tab_enabler::select_enabler()
 void tab_enabler::delete_now()
 {
   if (selected != nullptr) {
-    selected->ruledit_disabled = true;
+    selected->rulesave.ruledit_disabled = true;
 
     refresh();
     update_enabler_info(nullptr);
@@ -308,9 +308,9 @@ void tab_enabler::add_now()
 
   // Try to reuse freed enabler slot
   action_enablers_iterate(enabler) {
-    if (enabler->ruledit_disabled) {
+    if (enabler->rulesave.ruledit_disabled) {
       if (initialize_new_enabler(enabler)) {
-        enabler->ruledit_disabled = false;
+        enabler->rulesave.ruledit_disabled = false;
         update_enabler_info(enabler);
         refresh();
       }
diff --git a/tools/ruleutil/rulesave.c b/tools/ruleutil/rulesave.c
index 8352a8633a..6dea0341ee 100644
--- a/tools/ruleutil/rulesave.c
+++ b/tools/ruleutil/rulesave.c
@@ -1233,7 +1233,7 @@ static bool save_actions_ruleset(const char *filename, const char *name)
   action_enablers_iterate(pae) {
     char path[512];
 
-    if (pae->ruledit_disabled) {
+    if (pae->rulesave.ruledit_disabled) {
       continue;
     }
 
@@ -1244,6 +1244,10 @@ static bool save_actions_ruleset(const char *filename, const char *name)
 
     save_reqs_vector(sfile, &(pae->actor_reqs), path, "actor_reqs");
     save_reqs_vector(sfile, &(pae->target_reqs), path, "target_reqs");
+
+    if (pae->rulesave.comment != nullptr) {
+      secfile_insert_str(sfile, pae->rulesave.comment, "%s.comment", path);
+    }
   } action_enablers_iterate_end;
 
   return save_ruleset_file(sfile, filename);
-- 
2.45.2

