[colobot] 59/145: Improvements to ObligatoryToken/ProhibitedToken

Didier Raboud odyx at moszumanska.debian.org
Mon Jul 11 12:56:17 UTC 2016


This is an automated email from the git hooks/post-receive script.

odyx pushed a commit to branch debian/master
in repository colobot.

commit 7f38aca7660f5ba80a259537d9bee7c0cecdb3f1
Author: krzys-h <krzys_h at interia.pl>
Date:   Fri Apr 8 22:15:54 2016 +0200

    Improvements to ObligatoryToken/ProhibitedToken
    
    Now you can specify exactly how many times given instruction can occur
---
 po/colobot.pot          | 12 ++++++---
 po/de.po                | 24 ++++++++++++-----
 po/fr.po                | 24 ++++++++++++-----
 po/pl.po                | 24 ++++++++++++-----
 po/ru.po                | 24 ++++++++++++-----
 src/common/restext.cpp  |  4 +--
 src/level/robotmain.cpp | 69 +++++++++++++++++--------------------------------
 src/level/robotmain.h   | 16 ++++++------
 src/script/script.cpp   | 58 ++++++++++++++++++++++-------------------
 src/script/script.h     |  3 ++-
 10 files changed, 143 insertions(+), 115 deletions(-)

diff --git a/po/colobot.pot b/po/colobot.pot
index 1c4e61e..442beb4 100644
--- a/po/colobot.pot
+++ b/po/colobot.pot
@@ -611,13 +611,13 @@ msgstr ""
 msgid "\\Face 1"
 msgstr ""
 
-msgid "\\Face 4"
+msgid "\\Face 2"
 msgstr ""
 
 msgid "\\Face 3"
 msgstr ""
 
-msgid "\\Face 2"
+msgid "\\Face 4"
 msgstr ""
 
 msgid "\\No eyeglasses"
@@ -1519,10 +1519,11 @@ msgid "Unable to control enemy objects"
 msgstr ""
 
 #, c-format
-msgid "\"%s\" missing in this exercise"
+msgid "You have to use \"%s\" at least %d times in this exercise (used: %d)"
 msgstr ""
 
-msgid "Do not use in this exercise"
+#, c-format
+msgid "You have to use \"%s\" at most %d times in this exercise (used: %d)"
 msgstr ""
 
 msgid "Inappropriate bot"
@@ -1738,6 +1739,9 @@ msgstr ""
 msgid "Public required"
 msgstr ""
 
+msgid "expression expected after ="
+msgstr ""
+
 msgid "Dividing by zero"
 msgstr ""
 
diff --git a/po/de.po b/po/de.po
index d008dfa..300d209 100644
--- a/po/de.po
+++ b/po/de.po
@@ -61,10 +61,6 @@ msgstr "Es fehlt eine offene eckige Klammer \" [ \""
 msgid "\" ] \" missing"
 msgstr "Es fehlt eine geschlossene eckige Klammer \" ] \""
 
-#, c-format
-msgid "\"%s\" missing in this exercise"
-msgstr "Es fehlt \"%s\" in Ihrem Programm"
-
 msgid "..behind"
 msgstr "..hinten"
 
@@ -491,9 +487,6 @@ msgstr "Bildschirm\\Driver und Bildschirmauflösung"
 msgid "Dividing by zero"
 msgstr "Teilung durch Null"
 
-msgid "Do not use in this exercise"
-msgstr "In dieser Übung verboten"
-
 msgid "Do you really want to destroy the selected building?"
 msgstr "Wollen Sie das angewählte Gebäude wirklich zerstören ?"
 
@@ -1715,6 +1708,14 @@ msgstr "Sie können unter Wasser nichts tragen"
 msgid "You found a usable object"
 msgstr "Sie haben ein brauchbares Objekt gefunden"
 
+#, c-format
+msgid "You have to use \"%s\" at least %d times in this exercise (used: %d)"
+msgstr ""
+
+#, c-format
+msgid "You have to use \"%s\" at most %d times in this exercise (used: %d)"
+msgstr ""
+
 msgid "You must get on the spaceship to take off "
 msgstr "Gehen Sie an Bord, bevor Sie abheben"
 
@@ -1821,6 +1822,9 @@ msgstr ""
 msgid "epsitec.com"
 msgstr "www.epsitec.com"
 
+msgid "expression expected after ="
+msgstr ""
+
 #~ msgid " "
 #~ msgstr " "
 
@@ -1830,6 +1834,9 @@ msgstr "www.epsitec.com"
 #~ msgid " Missions on this level:"
 #~ msgstr " Missionen des Userlevels:"
 
+#~ msgid "\"%s\" missing in this exercise"
+#~ msgstr "Es fehlt \"%s\" in Ihrem Programm"
+
 #~ msgid "3D sound\\3D positioning of the sound"
 #~ msgstr "3D-Geräusche\\Orten der Geräusche im Raum"
 
@@ -1863,6 +1870,9 @@ msgstr "www.epsitec.com"
 #~ msgid "Developed by :"
 #~ msgstr "Entwickelt von:"
 
+#~ msgid "Do not use in this exercise"
+#~ msgstr "In dieser Übung verboten"
+
 #, fuzzy
 #~ msgid "Do you want to quit Colobot: Gold Edition?"
 #~ msgstr "Wollen Sie COLOBOT schließen ?"
diff --git a/po/fr.po b/po/fr.po
index 5db35d4..a57ce32 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -54,10 +54,6 @@ msgstr "\" [ \" attendu"
 msgid "\" ] \" missing"
 msgstr "\" ] \" attendu"
 
-#, c-format
-msgid "\"%s\" missing in this exercise"
-msgstr "Il manque \"%s\" dans le programme"
-
 msgid "..behind"
 msgstr "..derrière"
 
@@ -486,9 +482,6 @@ msgstr "Affichage\\Pilote et résolution d'affichage"
 msgid "Dividing by zero"
 msgstr "Division par zéro"
 
-msgid "Do not use in this exercise"
-msgstr "Interdit dans cet exercice"
-
 msgid "Do you really want to destroy the selected building?"
 msgstr "Voulez-vous vraiment détruire le bâtiment sélectionné ?"
 
@@ -1701,6 +1694,14 @@ msgstr "Vous ne pouvez pas transporter un objet sous l'eau"
 msgid "You found a usable object"
 msgstr "Vous avez trouvé un objet utilisable"
 
+#, c-format
+msgid "You have to use \"%s\" at least %d times in this exercise (used: %d)"
+msgstr ""
+
+#, c-format
+msgid "You have to use \"%s\" at most %d times in this exercise (used: %d)"
+msgstr ""
+
 msgid "You must get on the spaceship to take off "
 msgstr "Vous devez embarquer pour pouvoir décoller"
 
@@ -1806,6 +1807,9 @@ msgstr "colobot.info"
 msgid "epsitec.com"
 msgstr "epsitec.com"
 
+msgid "expression expected after ="
+msgstr ""
+
 #~ msgid " "
 #~ msgstr " "
 
@@ -1815,6 +1819,9 @@ msgstr "epsitec.com"
 #~ msgid " Missions on this level:"
 #~ msgstr " Missions du niveau :"
 
+#~ msgid "\"%s\" missing in this exercise"
+#~ msgstr "Il manque \"%s\" dans le programme"
+
 #~ msgid "3D sound\\3D positioning of the sound"
 #~ msgstr "Bruitages 3D\\Positionnement sonore dans l'espace"
 
@@ -1848,6 +1855,9 @@ msgstr "epsitec.com"
 #~ msgid "Developed by :"
 #~ msgstr "Développé par :"
 
+#~ msgid "Do not use in this exercise"
+#~ msgstr "Interdit dans cet exercice"
+
 #, fuzzy
 #~ msgid "Do you want to quit Colobot: Gold Edition?"
 #~ msgstr "Voulez-vous quitter COLOBOT ?"
diff --git a/po/pl.po b/po/pl.po
index b4f079c..5bc0a58 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -60,10 +60,6 @@ msgstr "Oczekiwane \" [ \""
 msgid "\" ] \" missing"
 msgstr "Brak \" ] \""
 
-#, c-format
-msgid "\"%s\" missing in this exercise"
-msgstr "Brakuje \"%s\" w tym ćwiczeniu"
-
 msgid "..behind"
 msgstr "..za"
 
@@ -492,9 +488,6 @@ msgstr "Urządzenie\\Ustawienia sterownika i rozdzielczości"
 msgid "Dividing by zero"
 msgstr "Dzielenie przez zero"
 
-msgid "Do not use in this exercise"
-msgstr "Do not use in this exercise"
-
 msgid "Do you really want to destroy the selected building?"
 msgstr "Czy na pewno chcesz zniszczyć zaznaczony budynek?"
 
@@ -1709,6 +1702,14 @@ msgstr "Nie możesz przenosić przedmiotów pod wodą"
 msgid "You found a usable object"
 msgstr "Znaleziono użyteczny przedmiot"
 
+#, c-format
+msgid "You have to use \"%s\" at least %d times in this exercise (used: %d)"
+msgstr "Musisz użyć \"%s\" przynajmniej %d razy w tym ćwiczeniu (użyto: %d)"
+
+#, c-format
+msgid "You have to use \"%s\" at most %d times in this exercise (used: %d)"
+msgstr "Musisz użyć \"%s\" najwyżej %d razy w tym ćwiczeniu (użyto: %d)"
+
 msgid "You must get on the spaceship to take off "
 msgstr "Musisz być na statku kosmicznym aby nim odlecieć"
 
@@ -1814,9 +1815,15 @@ msgstr "colobot.info"
 msgid "epsitec.com"
 msgstr "epsitec.com"
 
+msgid "expression expected after ="
+msgstr ""
+
 #~ msgid " Drivers:"
 #~ msgstr " Sterowniki:"
 
+#~ msgid "\"%s\" missing in this exercise"
+#~ msgstr "Brakuje \"%s\" w tym ćwiczeniu"
+
 #~ msgid "3D sound\\3D positioning of the sound"
 #~ msgstr "Dźwięk 3D\\Przestrzenne pozycjonowanie dźwięków"
 
@@ -1844,6 +1851,9 @@ msgstr "epsitec.com"
 #~ msgid "Details\\Visual quality of 3D objects"
 #~ msgstr "Szczegóły\\Jakość wizualna obiektów 3D"
 
+#~ msgid "Do not use in this exercise"
+#~ msgstr "Do not use in this exercise"
+
 #~ msgid "Do you want to quit Colobot: Gold Edition?"
 #~ msgstr "Czy na pewno chcesz opuścić grę Colobot: Gold Edition?"
 
diff --git a/po/ru.po b/po/ru.po
index 16f252e..25bb06a 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -59,10 +59,6 @@ msgstr "Ожидалось \" [ \""
 msgid "\" ] \" missing"
 msgstr "Отсутствует \"]\" "
 
-#, c-format
-msgid "\"%s\" missing in this exercise"
-msgstr "\"%s\" отсутствует в этом упражнении"
-
 msgid "..behind"
 msgstr "Сзади"
 
@@ -484,9 +480,6 @@ msgstr "Устройство\\Драйвер и настройки разреш
 msgid "Dividing by zero"
 msgstr "Деление на ноль (запрещено!)"
 
-msgid "Do not use in this exercise"
-msgstr "Не используй в этом упражнении"
-
 msgid "Do you really want to destroy the selected building?"
 msgstr "Вы действительно хотите уничтожить выбранное здание?"
 
@@ -1706,6 +1699,14 @@ msgstr "Вы не можете нести объекты под водой"
 msgid "You found a usable object"
 msgstr "Вы нашли рабочий объект"
 
+#, c-format
+msgid "You have to use \"%s\" at least %d times in this exercise (used: %d)"
+msgstr ""
+
+#, c-format
+msgid "You have to use \"%s\" at most %d times in this exercise (used: %d)"
+msgstr ""
+
 msgid "You must get on the spaceship to take off "
 msgstr "Вы должны быть на борту корабля, чтобы взлететь"
 
@@ -1812,6 +1813,9 @@ msgstr ""
 msgid "epsitec.com"
 msgstr "www.epsitec.com"
 
+msgid "expression expected after ="
+msgstr ""
+
 #~ msgid " "
 #~ msgstr " "
 
@@ -1821,6 +1825,9 @@ msgstr "www.epsitec.com"
 #~ msgid " Missions on this level:"
 #~ msgstr " Миссии на этом уровне:"
 
+#~ msgid "\"%s\" missing in this exercise"
+#~ msgstr "\"%s\" отсутствует в этом упражнении"
+
 #~ msgid "3D sound\\3D positioning of the sound"
 #~ msgstr "3D-звук\\Стерео звук"
 
@@ -1854,6 +1861,9 @@ msgstr "www.epsitec.com"
 #~ msgid "Developed by :"
 #~ msgstr "Разработка :"
 
+#~ msgid "Do not use in this exercise"
+#~ msgstr "Не используй в этом упражнении"
+
 #, fuzzy
 #~ msgid "Do you want to quit Colobot: Gold Edition?"
 #~ msgstr "Вы хотите закрыть COLOBOT?"
diff --git a/src/common/restext.cpp b/src/common/restext.cpp
index 96e51e0..966f993 100644
--- a/src/common/restext.cpp
+++ b/src/common/restext.cpp
@@ -632,8 +632,8 @@ void InitializeRestext()
     stringsErr[ERR_DELETEMOBILE]    = TR("Bot destroyed");
     stringsErr[ERR_DELETEBUILDING]  = TR("Building destroyed");
     stringsErr[ERR_ENEMY_OBJECT]    = TR("Unable to control enemy objects");
-    stringsErr[ERR_OBLIGATORYTOKEN] = TR("\"%s\" missing in this exercise");
-    stringsErr[ERR_PROHIBITEDTOKEN] = TR("Do not use in this exercise");
+    stringsErr[ERR_OBLIGATORYTOKEN] = TR("You have to use \"%s\" at least %d times in this exercise (used: %d)");
+    stringsErr[ERR_PROHIBITEDTOKEN] = TR("You have to use \"%s\" at most %d times in this exercise (used: %d)");
     stringsErr[ERR_WRONG_BOT]       = TR("Inappropriate bot");
 
     stringsErr[INFO_BUILD]          = TR("Building completed");
diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp
index 07b64bb..b59cc1f 100644
--- a/src/level/robotmain.cpp
+++ b/src/level/robotmain.cpp
@@ -2839,8 +2839,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
         m_endTakeWinDelay = 2.0f;
         m_endTakeLostDelay = 2.0f;
         m_globalMagnifyDamage = 1.0f;
-        m_obligatoryTotal = 0;
-        m_prohibitedTotal = 0;
+        m_obligatoryTokens.clear();
         m_mapShow = true;
         m_mapImage = false;
         m_mapFilename[0] = 0;
@@ -3656,25 +3655,32 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
                 continue;
             }
 
-            if (line->GetCommand() == "ObligatoryToken" && !resetObject) // NOTE: This was used only in CeeBot, maybe we should add this to some Colobot exercises?
+            if (line->GetCommand() == "ObligatoryToken" && !resetObject)
             {
-                int i = m_obligatoryTotal;
-                if (i < 100) //TODO: remove the limit
+                std::string token = line->GetParam("text")->AsString();
+                if (!line->GetParam("min")->IsDefined() && !line->GetParam("max")->IsDefined())
+                    GetLogger()->Warn("ObligatoryToken without specifying min/max is provided only for backwards compatibility - instead, do this: ObligatoryToken text=\"%s\" min=1\n", token.c_str());
+                if (m_obligatoryTokens.count(token))
+                    throw CLevelParserException("Incorrect ObligatoryToken specification - you cannot define a token twice");
+
+                m_obligatoryTokens[token].min = line->GetParam("min")->AsInt(line->GetParam("max")->IsDefined() ? -1 : 1); // BACKWARDS COMPATIBILITY: if neither min or max are defined, default to min=1
+                m_obligatoryTokens[token].max = line->GetParam("max")->AsInt(-1);
+                if (m_obligatoryTokens[token].min >= 0 && m_obligatoryTokens[token].max >= 0 && m_obligatoryTokens[token].min > m_obligatoryTokens[token].max)
                 {
-                    strcpy(m_obligatoryToken[i], line->GetParam("text")->AsString().c_str());
-                    m_obligatoryTotal ++;
+                    throw CLevelParserException("Incorrect ObligatoryToken specification - min cannot be greater than max");
                 }
                 continue;
             }
 
-            if (line->GetCommand() == "ProhibitedToken" && !resetObject) // NOTE: This was used only in CeeBot, maybe we should add this to some Colobot exercises?
+            if (line->GetCommand() == "ProhibitedToken" && !resetObject) // NOTE: Kept only for backwards compatibility
             {
-                int i = m_prohibitedTotal;
-                if (i < 100) //TODO: remove the limit
-                {
-                    strcpy(m_prohibitedToken[i], line->GetParam("text")->AsString().c_str());
-                    m_prohibitedTotal ++;
-                }
+                std::string token = line->GetParam("text")->AsString();
+                GetLogger()->Warn("ProhibitedToken is only provided for backwards compatibility - instead, do this: ObligatoryToken text=\"%s\" max=0\n", token.c_str());
+                if (m_obligatoryTokens.count(token))
+                    throw CLevelParserException("Incorrect ObligatoryToken specification - you cannot define a token twice");
+
+                m_obligatoryTokens[token].min = -1;
+                m_obligatoryTokens[token].max = 0;
                 continue;
             }
 
@@ -5227,41 +5233,12 @@ Error CRobotMain::CheckEndMission(bool frame)
 }
 
 
-//! Returns the number of instructions required
-int CRobotMain::GetObligatoryToken()
-{
-    return m_obligatoryTotal;
-}
-
-//! Returns the name of a required instruction
-char* CRobotMain::GetObligatoryToken(int i)
+//! Returns the list instructions required in CBot program in level
+const std::map<std::string, MinMax>& CRobotMain::GetObligatoryTokenList()
 {
-    return m_obligatoryToken[i];
+    return m_obligatoryTokens;
 }
 
-//! Checks if an instruction is part of the obligatory list
-int CRobotMain::IsObligatoryToken(const char* token)
-{
-    for (int i = 0; i < m_obligatoryTotal; i++)
-    {
-        if (strcmp(token, m_obligatoryToken[i]) == 0)
-            return i;
-    }
-    return -1;
-}
-
-//! Checks if an instruction is not part of the banned list
-bool CRobotMain::IsProhibitedToken(const char* token)
-{
-    for (int i = 0; i < m_prohibitedTotal; i++)
-    {
-        if (strcmp(token, m_prohibitedToken[i]) == 0)
-            return false;
-    }
-    return true;
-}
-
-
 //! Indicates whether it is possible to control a driving robot
 bool CRobotMain::GetTrainerPilot()
 {
diff --git a/src/level/robotmain.h b/src/level/robotmain.h
index 4f78df3..3247813 100644
--- a/src/level/robotmain.h
+++ b/src/level/robotmain.h
@@ -141,6 +141,12 @@ struct ShowLimit
     float           time = 0.0f;
 };
 
+struct MinMax
+{
+    int min = -1;
+    int max = -1;
+};
+
 
 const int SATCOM_HUSTON     = 0;
 const int SATCOM_SAT        = 1;
@@ -199,10 +205,7 @@ public:
     Error       CheckEndMission(bool frame);
     Error       ProcessEndMissionTake();
     Error       ProcessEndMissionTakeForGroup(std::vector<CSceneEndCondition*>& endTakes);
-    int         GetObligatoryToken();
-    char*       GetObligatoryToken(int i);
-    int         IsObligatoryToken(const char* token);
-    bool        IsProhibitedToken(const char* token);
+    const std::map<std::string, MinMax>& GetObligatoryTokenList();
     void        UpdateMap();
     bool        GetShowMap();
 
@@ -552,10 +555,7 @@ protected:
 
     std::vector<std::unique_ptr<CAudioChangeCondition>> m_audioChange;
 
-    int             m_obligatoryTotal = 0;
-    char            m_obligatoryToken[100][20] = {};
-    int             m_prohibitedTotal = 0;
-    char            m_prohibitedToken[100][20] = {};
+    std::map<std::string, MinMax> m_obligatoryTokens;
 
     //! Enabled buildings
     int             m_build = 0;
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 3beac76..924081d 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -161,46 +161,52 @@ bool CScript::CheckToken()
     m_error = CBot::CBotNoErr;
     m_title[0] = 0;
     m_mainFunction[0] = 0;
-    m_token[0] = 0;
+    m_token.clear();
     m_bCompile = false;
 
-    std::vector<bool> used(m_main->GetObligatoryToken(), false);
+    std::map<std::string, int> used;
+    std::map<std::string, int> cursor1;
+    std::map<std::string, int> cursor2;
 
     auto tokens = CBot::CBotToken::CompileTokens(m_script.get());
     CBot::CBotToken* bt = tokens.get();
     while ( bt != nullptr )
     {
         std::string token = bt->GetString();
-        int cursor1 = bt->GetStart();
-        int cursor2 = bt->GetEnd();
 
-        int i = m_main->IsObligatoryToken(token.c_str());
-        if ( i != -1 )
-        {
-            used[i] = true;  // token used
-        }
+        // Store only the last occurrence of the token
+        cursor1[token] = bt->GetStart();
+        cursor2[token] = bt->GetEnd();
 
-        if ( !m_main->IsProhibitedToken(token.c_str()) )
-        {
-            m_error = static_cast<CBot::CBotError>(ERR_PROHIBITEDTOKEN);
-            m_cursor1 = cursor1;
-            m_cursor2 = cursor2;
-            strcpy(m_title, "<prohibited>");
-            m_mainFunction[0] = 0;
-            return false;
-        }
+        used[token]++;
 
         bt = bt->GetNext();
     }
 
-    // At least once every obligatory instruction?
-    for (unsigned int i = 0; i < used.size(); i++)
+    for (const auto& it : m_main->GetObligatoryTokenList())
     {
-        if (!used[i])  // token not used?
+        Error error = ERR_OK;
+        int allowed = 0;
+        if (it.second.max >= 0 && used[it.first] > it.second.max)
+        {
+            error = ERR_PROHIBITEDTOKEN;
+            allowed = it.second.max;
+            m_cursor1 = cursor1[it.first];
+            m_cursor2 = cursor2[it.first];
+        }
+        if (it.second.min >= 0 && used[it.first] < it.second.min)
+        {
+            error = ERR_OBLIGATORYTOKEN;
+            allowed = it.second.min;
+        }
+
+        if (error != ERR_OK)
         {
-            strcpy(m_token, m_main->GetObligatoryToken(i));
-            m_error = static_cast<CBot::CBotError>(ERR_OBLIGATORYTOKEN);
-            strcpy(m_title, "<obligatory>");
+            m_token = it.first;
+            m_tokenUsed = used[it.first];
+            m_tokenAllowed = allowed;
+            m_error = static_cast<CBot::CBotError>(error);
+            strcpy(m_title, "<incorrect instructions>");
             m_mainFunction[0] = 0;
             return false;
         }
@@ -788,11 +794,11 @@ void CScript::GetError(std::string& error)
     }
     else
     {
-        if ( m_error == static_cast<CBot::CBotError>(ERR_OBLIGATORYTOKEN) )
+        if ( m_error == static_cast<CBot::CBotError>(ERR_OBLIGATORYTOKEN) || m_error == static_cast<CBot::CBotError>(ERR_PROHIBITEDTOKEN) )
         {
             std::string s;
             GetResource(RES_ERR, m_error, s);
-            error = StrUtils::Format(s.c_str(), m_token);
+            error = StrUtils::Format(s.c_str(), m_token.c_str(), m_tokenAllowed, m_tokenUsed);
         }
         else if ( m_error < 1000 )
         {
diff --git a/src/script/script.h b/src/script/script.h
index 50f279e..a114171 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -122,7 +122,8 @@ protected:
     char    m_title[50] = {};        // script title
     char    m_mainFunction[50] = {};
     char    m_filename[50] = {};     // file name
-    char    m_token[50] = {};        // missing instruction
+    std::string m_token = "";        // missing instruction
+    int m_tokenUsed = 0, m_tokenAllowed = 0;
     CBot::CBotError m_error = CBot::CBotNoErr;        // error (0=ok)
     int     m_cursor1 = 0;
     int     m_cursor2 = 0;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/colobot.git



More information about the Pkg-games-commits mailing list