<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://sleague.civfanatics.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Prof.+Garfield</id>
	<title>Scenario League Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://sleague.civfanatics.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Prof.+Garfield"/>
	<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php/Special:Contributions/Prof._Garfield"/>
	<updated>2026-07-04T02:51:53Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Sci-Fi_Units&amp;diff=5611</id>
		<title>Sci-Fi Units</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Sci-Fi_Units&amp;diff=5611"/>
		<updated>2023-01-12T17:27:10Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: Removed curtsibling category, since he requested his art be removed from this page.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Units]]&lt;br /&gt;
[[Category:Fairline]]&lt;br /&gt;
[[Category:Reno]]&lt;br /&gt;
[[Category:Hans99]]&lt;br /&gt;
== Dune ==&lt;br /&gt;
&lt;br /&gt;
[[File:Reno_Dune_Units.gif]]&lt;br /&gt;
&lt;br /&gt;
Author: [[Reno]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Hans99_Dune2_units.png]]&lt;br /&gt;
&lt;br /&gt;
Author: [[Hans99]].&lt;br /&gt;
&lt;br /&gt;
== Star Wars ==&lt;br /&gt;
&lt;br /&gt;
[[File:Fairline_sw6.png]]&lt;br /&gt;
&lt;br /&gt;
Author: [[Fairline]].&lt;br /&gt;
&lt;br /&gt;
== Star Control ==&lt;br /&gt;
&lt;br /&gt;
[[File:Hans99_StarControl2.png]]&lt;br /&gt;
&lt;br /&gt;
Author: [[Hans99]].&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Main_Page&amp;diff=5610</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Main_Page&amp;diff=5610"/>
		<updated>2023-01-12T17:16:52Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: Removed references to curtsibling work, since he requested his work be removed.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:CIV2TITLE.png|center]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hi! The Scenario League is alive and well. Be sure to check back regularly as we rebuild the wiki. If you would like to help please let us know in this thread [http://forums.civfanatics.com/showthread.php?t=409484| SL Wiki Upload List]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== NEWS ==&lt;br /&gt;
&lt;br /&gt;
[[Image:OTRpreview.png]] &#039;&#039;&#039;9th February 2020&#039;&#039;&#039; - John Petroski &amp;amp; Prof. Garfield release [https://forums.civfanatics.com/resources/over-the-reich.27172/ Over the Reich 4 ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:Techumseh_avatar.png ]] &#039;&#039;&#039;19th January 2020&#039;&#039;&#039; - Techumseh re-releases all his scenarios for Test of Time! [http://sleague.civfanatics.com/index.php?title=User:Techumseh]&lt;br /&gt;
&lt;br /&gt;
[[Image:OTRpreview.png]] &#039;&#039;&#039;20th December 2018&#039;&#039;&#039; - John Petroski &amp;amp; Prof. Garfield release [https://forums.civfanatics.com/threads/over-the-reich-a-multiplayer-scenario-for-totpp-and-lua-released.639907/#post-15313097 Over the Reich ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:Napoleon Icon.gif]] &#039;&#039;&#039;21st November 2018&#039;&#039;&#039; - Tootall_2012 releases [https://forums.civfanatics.com/threads/napol%C3%A9on-i-1805-1815-totpp-and-lua-scenario-released.638700/ Napoléon I 1805 - 1815 ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:Sealion.png]] &#039;&#039;&#039;19th June 2018&#039;&#039;&#039; - Techumseh releases [https://forums.civfanatics.com/threads/operation-seelowe-released.633642/ Operation Seelowe ToTPP]&lt;br /&gt;
&lt;br /&gt;
[[Image:Caesar1.png]] &#039;&#039;&#039;16th April 2018&#039;&#039;&#039; - John Petroski &amp;amp; Grishnach release [https://forums.civfanatics.com/threads/caesars-gallic-wars.628330//Caesar&#039;s Gallic Wars ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:4KOR.gif]] &#039;&#039;&#039;12th June 2017&#039;&#039;&#039; - Patine &amp;amp; McMonkey release [https://forums.civfanatics.com/threads/korean-war-revisited.452059//The_Korean_War_Redux_ToTPP_v1  The Korean War Redux ToTPP]&lt;br /&gt;
&lt;br /&gt;
[[Image:Nam65_Icon.png]] &#039;&#039;&#039;20th June 2017&#039;&#039;&#039; - Tootall_2012 releases [https://forums.civfanatics.com/threads/vietnam-war-development-thread.534783/  Vietnam 1965- 1975 ToTPP]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Anarchist.png]] &#039;&#039;&#039;30th March 2015&#039;&#039;&#039; - McMonkey releases [http://sleague.civfanatics.com/index.php/The_Spanish_Civil_War_ToTPP Spanish Civil War ToTPP]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Numidian.png]] &#039;&#039;&#039;12th November 2013&#039;&#039;&#039; - Nicheal releases [http://sleague.civfanatics.com/index.php/Ancient_Steel Ancient Steel]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Speeder.png]] &#039;&#039;&#039;12th November 2013&#039;&#039;&#039; - Nicheal releases [http://sleague.civfanatics.com/index.php/SubWar Sub War Deluxe]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:RomBr.png]] &#039;&#039;&#039;5th November 2013&#039;&#039;&#039; - committed hero (aka Michael Daumen) releases [http://forums.civfanatics.com/showthread.php?t=513967 Roman Britain]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:WWIB.png]] &#039;&#039;&#039;1st October 2013&#039;&#039;&#039; - Bultro releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=21851 Worldwar - In the Balance]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;March to October 2013&#039;&#039;&#039; - Petit&#039;s ToT Mods include Menilek II of Ethiopia, Unity of Italy, Fire and Roses, Four Sea Republic, Star Wars: Insurrection (version 1.3), Star Contact: Part 1 The Star Wars, Cold War Crisis, Timur, Spanish Civil War: The Defence of Madrid (version 2.1), Mamluks, Sparta, Hellenis, World War One, American Civil War, Komnenai, The Thirty Years War and Carolus [http://forums.civfanatics.com/showthread.php?t=410838&amp;amp;page=6 Petit&#039;s ToT Mods thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AHD.png]] &#039;&#039;&#039;13th July 2013&#039;&#039;&#039; - Tootall_2012 releases [http://sleague.civfanatics.com/index.php/A_House_Divided_1861_-1865 A House Divided 1861 - 1865]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:STM.png]] &#039;&#039;&#039;24th June 2013&#039;&#039;&#039; - Metro Polis releases [http://forums.civfanatics.com/showthread.php?t=466004 Star Trek Mod for ToT]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:LDoE.png]] &#039;&#039;&#039;19th April 2013&#039;&#039;&#039; - Dadais releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=21113 Last Days Of Empire]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;16th March 2013&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?p=10210259#post10210259 Modified Scenarios Workshop thread] at the SL Forum (post #79). &lt;br /&gt;
They include: The Peloponnesian War, Struggle for Empire, The Seven Years War, The Spanish-American War: The Carribean, Crises of the New World Order, 2013: A Union Divided, Moria A Journey in the Dark and The Lord of the Rings by Harlan Thompson.     &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;26th September 2012&#039;&#039;&#039; - Techumseh releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=20137 TechMod]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Blood.png]] &#039;&#039;&#039;7th October 2012&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/showthread.php?t=477405 Blood and Sieges]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:TechMod.png]] &#039;&#039;&#039;26th September 2012&#039;&#039;&#039; - Techumseh releases [http://forums.civfanatics.com/showthread.php?t=476516 TechMod]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SpaceMod.png]] &#039;&#039;&#039;18th September 2012&#039;&#039;&#039; - Skulb releases [http://forums.civfanatics.com/showthread.php?t=475802 Space Mod for ToT]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:IwoJima.png]] &#039;&#039;&#039;8th September 2012&#039;&#039;&#039; - Tootall_2012 releases [http://forums.civfanatics.com/showthread.php?t=474972 Battle of Iwo Jima 1945]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Curzan.png]] &#039;&#039;&#039;18th August 2012&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/showthread.php?t=459580 The Cruzan Colony (See post #12)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SciFi.png]] &#039;&#039;&#039;24th June 2012&#039;&#039;&#039; - Metro Polis releases [http://forums.civfanatics.com/showthread.php?t=466004 Star Trek Mod for ToT]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:BoF44DD.png]] &#039;&#039;&#039;12th February 2012&#039;&#039;&#039; - Tootall_2012 releases [http://sleague.civfanatics.com/index.php/Battle_of_France_1944 Battle for France 1944]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SilmarilSL.png]] &#039;&#039;&#039;3rd October 2011&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=17697 The Silmarillion]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Sobieski.png]] &#039;&#039;&#039;12th September 2011&#039;&#039;&#039; - Nikoagonistes (aka Ghost of Disco) releases [http://forums.civfanatics.com/showthread.php?t=428221 Jan III Sobieski v.1.0 (See post #11)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;24th June 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?t=410838&amp;amp;page=3 Modified Scenarios Workshop thread] at the SL Forum (post #53). &lt;br /&gt;
They include:      &lt;br /&gt;
Age of Crusades, In Nomine, Medium Aevum and Drole de Guerre&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:WSilverSkullSL.png]] &#039;&#039;&#039;15th March 2011&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/showthread.php?t=415363 The Lord of the Silver Skull]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;25th February 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?p=10210259#post10210259 Modified Scenarios Workshop thread] at the SL Forum (post #11). &lt;br /&gt;
They include:      &lt;br /&gt;
The Great War: Highway to Hell, How Few Remain, The War of Cuba and The Mongols: From Genghis to Kublai Khan.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:BeachAssault.png]] &#039;&#039;&#039;16th February 2011&#039;&#039;&#039; - Harry Tuttle re-releases [[Beach Assault]] [http://forums.civfanatics.com/showthread.php?t=412144 SL Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wMoscowSL.png]] &#039;&#039;&#039;15th February 2011&#039;&#039;&#039; - Keu releases a modified ToT version of Micheal Daumen&#039;s [http://forums.civfanatics.com/showthread.php?t=410764 Moscow - The Third Rome (post #17)] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wGermanicusSL.png]] &#039;&#039;&#039;13th February 2011&#039;&#039;&#039; - John Petroski releases [[Germanicus on the Rhine]] [http://forums.civfanatics.com/showthread.php?p=10213254#post10213254 SL Thread] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;12th February 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?p=10210259#post10210259 Modified Scenarios Workshop thread] at the SL Forum (post #7). &lt;br /&gt;
They include: The Age of Crusades, The Anglo-Boer War, Bonaparte II, Congo!, First Strike, The Lord of the Rings IV, The Russian Revolution and Yugoslavia: Suicide of a European Nation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wKoSSL.png]] &#039;&#039;&#039;12th February 2011&#039;&#039;&#039; - Custsibling re-releases [[Kingdoms of Steel]] [http://forums.civfanatics.com/showthread.php?p=10210185#post10210185 SL Thread] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;11th February 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversions / mods in the [http://forums.civfanatics.com/showthread.php?p=10208556#post10208556 Modified Scenarios Workshop thread] at the SL Forum (post#3).&lt;br /&gt;
They include: The Italian Wars, Historibus Europae, Hannibal&#039;s War, Gold Gulch, Struggle for Empire, Colonialism II, Carolus Invictissimus, The American Civil War and the Thirty Years War.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wGreatGameSL.png]] &#039;&#039;&#039;11th February 2011&#039;&#039;&#039; - Keu releases a modified ToT version of Micheal Daumen&#039;s [http://forums.civfanatics.com/showthread.php?p=10206652#post10206652 The Great Game] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wAWISL.png]] &#039;&#039;&#039;9th February 2011&#039;&#039;&#039; - civ2units releases [[American War of Independence]] [http://forums.civfanatics.com/showthread.php?t=411273 SL Thread]&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Sci-Fi_Units&amp;diff=5609</id>
		<title>Sci-Fi Units</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Sci-Fi_Units&amp;diff=5609"/>
		<updated>2023-01-12T17:15:06Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Doctor Who */ Removed section since curtsibling doesn&amp;#039;t want his work/art here anymore&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Units]]&lt;br /&gt;
[[Category:curtsibling]]&lt;br /&gt;
[[Category:Fairline]]&lt;br /&gt;
[[Category:Reno]]&lt;br /&gt;
[[Category:Hans99]]&lt;br /&gt;
== Dune ==&lt;br /&gt;
&lt;br /&gt;
[[File:Reno_Dune_Units.gif]]&lt;br /&gt;
&lt;br /&gt;
Author: [[Reno]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Hans99_Dune2_units.png]]&lt;br /&gt;
&lt;br /&gt;
Author: [[Hans99]].&lt;br /&gt;
&lt;br /&gt;
== Star Wars ==&lt;br /&gt;
&lt;br /&gt;
[[File:Fairline_sw6.png]]&lt;br /&gt;
&lt;br /&gt;
Author: [[Fairline]].&lt;br /&gt;
&lt;br /&gt;
== Star Control ==&lt;br /&gt;
&lt;br /&gt;
[[File:Hans99_StarControl2.png]]&lt;br /&gt;
&lt;br /&gt;
Author: [[Hans99]].&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=The_Age_of_Reformation&amp;diff=5551</id>
		<title>The Age of Reformation</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=The_Age_of_Reformation&amp;diff=5551"/>
		<updated>2021-09-16T22:49:27Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: Created Page, copied info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Civ2units]]&lt;br /&gt;
[[Category:Civilization II: Test of Time]]&lt;br /&gt;
[[File:Reformation_Title.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&#039;&#039;If you want to change the world, pick up your pen and write.&#039;&#039;&amp;quot;&lt;br /&gt;
- Martin Luther (1483-1546)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JANUARY 1517, EUROPE&#039;&#039;&#039; &lt;br /&gt;
  &lt;br /&gt;
Since Christopher Columbus journey in 1492, the World is another. Instead of finding a direct seaway to India, he discovered a complete new continent. Indigenous people, &lt;br /&gt;
who are thinking the people from the sea are gods welcomes the conquistadors without suspecting that they are not comming in peace. Rumours of large amounts of gold &lt;br /&gt;
and other riches allures more and more soldiers from Europe into the New World and leading finally into the conquest of the mighty empires of the Aztecs, Mayas and Incas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Europe itself awakens from its sleeping beauty after the medieval age and enters into a new era. People starts questioning the old world order, the kings realizing &lt;br /&gt;
that there is much more behind the horizen and the catholic church stands in front of a real threat: The Protestant Movement. Initiated by a young theology professor, &lt;br /&gt;
this movement will change complete Europe for ever and leading into one of the most devastating wars the continent ever saw.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Ottomans used them first time during the siege of Constantinople in 1453; giant cannons who damaged the until then undestroyed Theodosian Walls. After the &lt;br /&gt;
fall of Constantinople the black powder replaced arrows and bows, swords and shields on the battlefield. The feudal knights where replacde by modern armoured cavalry &lt;br /&gt;
and infantry equipped with a pike where accompanied from so called Arquebusiers, men armed with a firearm. Big cannons replaced the catapults and trebuchets and &lt;br /&gt;
therefore modernized the whole warfare.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You play as the Spanish-Habsburg Empire and your goal is to establish the Viceroyalty of New Spain. But don&#039;t concentrate too much on the New World, dark clouds are &lt;br /&gt;
gathering on Europe&#039;s horizen as the Reformation Movement finds more and more supporters. The power of the Catholic church is in danger and there is war in the air. &lt;br /&gt;
Can you face the threat and re-unite the Holy Roman Empire under one church? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Required Game Version ==&lt;br /&gt;
&lt;br /&gt;
This scenario requires the latest official Civilization II ToT patch as well as the ToTPP version 0.16&lt;br /&gt;
&lt;br /&gt;
You can find the latest official Civiliazion 2 ToT patch here:&lt;br /&gt;
&lt;br /&gt;
[http://forums.civfanatics.com/resources/test-of-time-v1-1-patch.59/ Official ToT patch 1.1]&lt;br /&gt;
&lt;br /&gt;
You can find the ToTPP version 0.16 here:&lt;br /&gt;
&lt;br /&gt;
[http://forums.civfanatics.com/threads/the-test-of-time-patch-project.517282/ ToTPP from TheNamelessOne]&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
Create a new folder called &amp;quot;&#039;&#039;&#039;Reformation&#039;&#039;&#039;&amp;quot; in your &amp;quot;&#039;&#039;&#039;The Test of Time/Original&#039;&#039;&#039;&amp;quot; directory.&lt;br /&gt;
Copy the following files into the &amp;quot;&#039;&#039;&#039;Reformation&#039;&#039;&#039;&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
Will be filled&lt;br /&gt;
&lt;br /&gt;
== Ingame Graphics ==&lt;br /&gt;
&lt;br /&gt;
Will be filled&lt;br /&gt;
&lt;br /&gt;
== Game Rules ==&lt;br /&gt;
&lt;br /&gt;
This scenario is designed for playing with the Spanish-Habsburg Empire only. Your goal ist to conquer Central and South America and the Holy Roman Empire.&lt;br /&gt;
&lt;br /&gt;
Will be filled&lt;br /&gt;
&lt;br /&gt;
== Victory Points ==&lt;br /&gt;
&lt;br /&gt;
The following cities must be under you control for a complete victory:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EUROPE:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
3x OBJECTIVE points =&amp;gt; Munich, Strasbourg, Frankfurt, Nuremberg, Dresden, Berlin, Stettin, Hanover, Hamburg, Cologne, Amsterdam, Antwerp&lt;br /&gt;
&lt;br /&gt;
1x OBJECTIVE points =&amp;gt; Zurich, Dijon, Brussels, Prague, Budapest, Zagreb, Trieste, Szeged, Debrecen, Belgrade&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NEW WORLD:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
3x OBJECTIVE points =&amp;gt; Tenochtitlan (Mexico City), Zacatecas, Tegucigalpa, Chorotega (San José), Quito, Tomebamba (Guayaquil), Bogota &lt;br /&gt;
&lt;br /&gt;
1x OBJECTIVE points =&amp;gt; Santarem, Habana (Havana), Camaguey, Moron (Santiago de Cuba), Santo Domingo, Angostura (Paramaribo), Guayana (Ciudad Guayana), Panama (Panama City), Chortli (La Ceiba), Jamaica (Kingston), Caguas (San Juan), Mayaro (San Fernando), Anguilla, Dominica, Tuxpan (Tampico), Xalapa (Veracruz), Tehuacan, Cihuatlan (Acapulco), Xicallancas (Villahermosa)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;AFRICA:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1x OBJECTIVE points =&amp;gt; Tunis, Tripolis, Alexandria, Cairo, Ondo, Abidjan, Accra  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The victory conditions are as followed:&lt;br /&gt;
&lt;br /&gt;
Decisive victory: &amp;gt;= 90 points&lt;br /&gt;
&lt;br /&gt;
Marginal Victory: &amp;gt;= 80 points&lt;br /&gt;
&lt;br /&gt;
Marginal Defeat: &amp;lt;= 50 points&lt;br /&gt;
&lt;br /&gt;
Decisive Defeat: &amp;lt;= 30 points&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5456</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5456"/>
		<updated>2020-07-05T17:06:56Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Barracks and Veteran Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].  (I provided them at the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the key &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [https://forums.civfanatics.com/threads/totpp-flags-and-counters-library.648757/ flags]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of the state table passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) &amp;lt;/code&amp;gt; to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
NOTE:  It was discovered that you can simply create a new unit and delete the produced unit in order to avoid bestowing veteran status from a barracks.  This will be much easier than saving stuff in tables. However, this example is still useful.&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
Civ.scen.onLoad and civ.scen.onScenarioLoaded appear at first glance to do the same thing.  When a game is loaded, they execute their code.  So what&#039;s the difference?  Well, the first difference is that the &amp;quot;buffer&amp;quot; that is attached to the end of a save game file (and which is used to re-create the state), is available to civ.scen.onLoad.  The other difference is timing.  civ.scen.onScenarioLoaded happens &#039;&#039;after&#039;&#039; the rules.txt information is accessed by the game, while onLoad happens before that.  That means, if you are interested in changing some feature of the game based on the season (such as the road multiplier), you will want to do that in civ.scen.onScenarioLoaded.  The code in events.lua (which is not part of a function definition) is executed before civ.scen.onLoad.  This is how the various tables and other data are built for the scenario.&lt;br /&gt;
&lt;br /&gt;
I mentioned the road multiplier in the last paragraph.  When you did testing in the Classic Rome scenario, you may have noticed that roads granted unlimited movement.  This is because when I converted the Rome scenario to Test of Time, I failed to include an @COSMIC2 line in the rules.txt, and due to a bug, TOTPP doesn&#039;t look at the @COSMIC value instead.  During my live creation of the munition library, I inserted a line &amp;lt;code&amp;gt;totpp.movementMultipliers.road=2&amp;lt;/code&amp;gt;, which counteracts the bug.  As I mentioned last paragraph, if I wanted to override rules.txt (rather than replace an omission), I would have had to put the line in the function supplied to civ.scen.onScenarioLoaded.&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;br /&gt;
&lt;br /&gt;
This concludes the last fundamental lesson for writing Civilization II Scenario Events with Lua.  I may, at some point, add some more material, but that will be to either re-visit stuff I mentioned in earlier lessons but then forgot about, or to add tips on how to do certain things or use certain functionality.  For the latter case, I may simply decide to write an independent document instead.&lt;br /&gt;
&lt;br /&gt;
Thank you for following these lessons and getting to the end.  If there are any improvements you think could be made to these lessons, please either let me know or just make them yourself.  My goal is to make it easy for others to use the tools lua provides for Civ II, and if a change would improve this product, then I&#039;d like to make it.  Feel free to redistribute and modify these lessons.  I would appreciate credit (and a notice that changes were made to the text if applicable), and maybe a PM in the civfanatics forums of what you did, but these aren&#039;t really essential.  After all, these lessons are only good for teaching Lua with Civilization II, so just about any use of them is likely to further that goal.&lt;br /&gt;
&lt;br /&gt;
Good luck with your projects.  Remember that you will gain confidence with practice and experience.  Ask for help if and when you need it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5455</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5455"/>
		<updated>2020-07-05T17:06:36Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Barracks and Veteran Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].  (I provided them at the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the key &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [https://forums.civfanatics.com/threads/totpp-flags-and-counters-library.648757/ flags]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of the state table passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) &amp;lt;/code&amp;gt; to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
NOTE:  It was discovered that you can simply create a new unit and delete the produced unit in order to avoid bestowing veteran status from a barracks.  This will be much easier than saving stuff in tables.&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
Civ.scen.onLoad and civ.scen.onScenarioLoaded appear at first glance to do the same thing.  When a game is loaded, they execute their code.  So what&#039;s the difference?  Well, the first difference is that the &amp;quot;buffer&amp;quot; that is attached to the end of a save game file (and which is used to re-create the state), is available to civ.scen.onLoad.  The other difference is timing.  civ.scen.onScenarioLoaded happens &#039;&#039;after&#039;&#039; the rules.txt information is accessed by the game, while onLoad happens before that.  That means, if you are interested in changing some feature of the game based on the season (such as the road multiplier), you will want to do that in civ.scen.onScenarioLoaded.  The code in events.lua (which is not part of a function definition) is executed before civ.scen.onLoad.  This is how the various tables and other data are built for the scenario.&lt;br /&gt;
&lt;br /&gt;
I mentioned the road multiplier in the last paragraph.  When you did testing in the Classic Rome scenario, you may have noticed that roads granted unlimited movement.  This is because when I converted the Rome scenario to Test of Time, I failed to include an @COSMIC2 line in the rules.txt, and due to a bug, TOTPP doesn&#039;t look at the @COSMIC value instead.  During my live creation of the munition library, I inserted a line &amp;lt;code&amp;gt;totpp.movementMultipliers.road=2&amp;lt;/code&amp;gt;, which counteracts the bug.  As I mentioned last paragraph, if I wanted to override rules.txt (rather than replace an omission), I would have had to put the line in the function supplied to civ.scen.onScenarioLoaded.&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;br /&gt;
&lt;br /&gt;
This concludes the last fundamental lesson for writing Civilization II Scenario Events with Lua.  I may, at some point, add some more material, but that will be to either re-visit stuff I mentioned in earlier lessons but then forgot about, or to add tips on how to do certain things or use certain functionality.  For the latter case, I may simply decide to write an independent document instead.&lt;br /&gt;
&lt;br /&gt;
Thank you for following these lessons and getting to the end.  If there are any improvements you think could be made to these lessons, please either let me know or just make them yourself.  My goal is to make it easy for others to use the tools lua provides for Civ II, and if a change would improve this product, then I&#039;d like to make it.  Feel free to redistribute and modify these lessons.  I would appreciate credit (and a notice that changes were made to the text if applicable), and maybe a PM in the civfanatics forums of what you did, but these aren&#039;t really essential.  After all, these lessons are only good for teaching Lua with Civilization II, so just about any use of them is likely to further that goal.&lt;br /&gt;
&lt;br /&gt;
Good luck with your projects.  Remember that you will gain confidence with practice and experience.  Ask for help if and when you need it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Main_Page&amp;diff=5434</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Main_Page&amp;diff=5434"/>
		<updated>2020-02-09T17:39:45Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* NEWS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:CIV2TITLE.png|center]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hi! The Scenario League is alive and well. Be sure to check back regularly as we rebuild the wiki. If you would like to help please let us know in this thread [http://forums.civfanatics.com/showthread.php?t=409484| SL Wiki Upload List]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== NEWS ==&lt;br /&gt;
&lt;br /&gt;
[[Image:OTRpreview.png]] &#039;&#039;&#039;9th February 2020&#039;&#039;&#039; - John Petroski &amp;amp; Prof. Garfield release [https://forums.civfanatics.com/resources/over-the-reich.27172/ Over the Reich 4 ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:Techumseh_avatar.png ]] &#039;&#039;&#039;19th January 2020&#039;&#039;&#039; - Techumseh re-releases all his scenarios for Test of Time! [http://sleague.civfanatics.com/index.php?title=User:Techumseh]&lt;br /&gt;
&lt;br /&gt;
[[Image:OTRpreview.png]] &#039;&#039;&#039;20th December 2018&#039;&#039;&#039; - John Petroski &amp;amp; Prof. Garfield release [https://forums.civfanatics.com/threads/over-the-reich-a-multiplayer-scenario-for-totpp-and-lua-released.639907/#post-15313097 Over the Reich ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:Napoleon Icon.gif]] &#039;&#039;&#039;21st November 2018&#039;&#039;&#039; - Tootall_2012 releases [https://forums.civfanatics.com/threads/napol%C3%A9on-i-1805-1815-totpp-and-lua-scenario-released.638700/ Napoléon I 1805 - 1815 ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:Sealion.png]] &#039;&#039;&#039;19th June 2018&#039;&#039;&#039; - Techumseh releases [https://forums.civfanatics.com/threads/operation-seelowe-released.633642/ Operation Seelowe ToTPP]&lt;br /&gt;
&lt;br /&gt;
[[Image:Caesar1.png]] &#039;&#039;&#039;16th April 2018&#039;&#039;&#039; - John Petroski &amp;amp; Grishnach release [https://forums.civfanatics.com/threads/caesars-gallic-wars.628330//Caesar&#039;s Gallic Wars ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:4KOR.gif]] &#039;&#039;&#039;12th June 2017&#039;&#039;&#039; - Patine &amp;amp; McMonkey release [https://forums.civfanatics.com/threads/korean-war-revisited.452059//The_Korean_War_Redux_ToTPP_v1  The Korean War Redux ToTPP]&lt;br /&gt;
&lt;br /&gt;
[[Image:Nam65_Icon.png]] &#039;&#039;&#039;20th June 2017&#039;&#039;&#039; - Tootall_2012 releases [https://forums.civfanatics.com/threads/vietnam-war-development-thread.534783/  Vietnam 1965- 1975 ToTPP]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Anarchist.png]] &#039;&#039;&#039;30th March 2015&#039;&#039;&#039; - McMonkey releases [http://sleague.civfanatics.com/index.php/The_Spanish_Civil_War_ToTPP Spanish Civil War ToTPP]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Numidian.png]] &#039;&#039;&#039;12th November 2013&#039;&#039;&#039; - Nicheal releases [http://sleague.civfanatics.com/index.php/Ancient_Steel Ancient Steel]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Speeder.png]] &#039;&#039;&#039;12th November 2013&#039;&#039;&#039; - Nicheal releases [http://sleague.civfanatics.com/index.php/SubWar Sub War Deluxe]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:RomBr.png]] &#039;&#039;&#039;5th November 2013&#039;&#039;&#039; - committed hero (aka Michael Daumen) releases [http://forums.civfanatics.com/showthread.php?t=513967 Roman Britain]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:WWIB.png]] &#039;&#039;&#039;1st October 2013&#039;&#039;&#039; - Bultro releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=21851 Worldwar - In the Balance]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;March to October 2013&#039;&#039;&#039; - Petit&#039;s ToT Mods include Menilek II of Ethiopia, Unity of Italy, Fire and Roses, Four Sea Republic, Star Wars: Insurrection (version 1.3), Star Contact: Part 1 The Star Wars, Cold War Crisis, Timur, Spanish Civil War: The Defence of Madrid (version 2.1), Mamluks, Sparta, Hellenis, World War One, American Civil War, Komnenai, The Thirty Years War and Carolus [http://forums.civfanatics.com/showthread.php?t=410838&amp;amp;page=6 Petit&#039;s ToT Mods thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AHD.png]] &#039;&#039;&#039;13th July 2013&#039;&#039;&#039; - Tootall_2012 releases [http://sleague.civfanatics.com/index.php/A_House_Divided_1861_-1865 A House Divided 1861 - 1865]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:STM.png]] &#039;&#039;&#039;24th June 2013&#039;&#039;&#039; - Metro Polis releases [http://forums.civfanatics.com/showthread.php?t=466004 Star Trek Mod for ToT]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Zarklaw2_Icon.gif]] &#039;&#039;&#039;30th April 2013&#039;&#039;&#039; - Curtsibling releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=21147 Battle fo Zarklaw II]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:LDoE.png]] &#039;&#039;&#039;19th April 2013&#039;&#039;&#039; - Dadais releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=21113 Last Days Of Empire]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;16th March 2013&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?p=10210259#post10210259 Modified Scenarios Workshop thread] at the SL Forum (post #79). &lt;br /&gt;
They include: The Peloponnesian War, Struggle for Empire, The Seven Years War, The Spanish-American War: The Carribean, Crises of the New World Order, 2013: A Union Divided, Moria A Journey in the Dark and The Lord of the Rings by Harlan Thompson.     &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;26th September 2012&#039;&#039;&#039; - Techumseh releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=20137 TechMod]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Blood.png]] &#039;&#039;&#039;7th October 2012&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/showthread.php?t=477405 Blood and Sieges]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:TechMod.png]] &#039;&#039;&#039;26th September 2012&#039;&#039;&#039; - Techumseh releases [http://forums.civfanatics.com/showthread.php?t=476516 TechMod]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SpaceMod.png]] &#039;&#039;&#039;18th September 2012&#039;&#039;&#039; - Skulb releases [http://forums.civfanatics.com/showthread.php?t=475802 Space Mod for ToT]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:IwoJima.png]] &#039;&#039;&#039;8th September 2012&#039;&#039;&#039; - Tootall_2012 releases [http://forums.civfanatics.com/showthread.php?t=474972 Battle of Iwo Jima 1945]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Curzan.png]] &#039;&#039;&#039;18th August 2012&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/showthread.php?t=459580 The Cruzan Colony (See post #12)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SciFi.png]] &#039;&#039;&#039;24th June 2012&#039;&#039;&#039; - Metro Polis releases [http://forums.civfanatics.com/showthread.php?t=466004 Star Trek Mod for ToT]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:BoF44DD.png]] &#039;&#039;&#039;12th February 2012&#039;&#039;&#039; - Tootall_2012 releases [http://sleague.civfanatics.com/index.php/Battle_of_France_1944 Battle for France 1944]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SilmarilSL.png]] &#039;&#039;&#039;3rd October 2011&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=17697 The Silmarillion]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Sobieski.png]] &#039;&#039;&#039;12th September 2011&#039;&#039;&#039; - Nikoagonistes (aka Ghost of Disco) releases [http://forums.civfanatics.com/showthread.php?t=428221 Jan III Sobieski v.1.0 (See post #11)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AmericanKingdomsSL.png]] &#039;&#039;&#039;14th August 2011&#039;&#039;&#039; - Curtsibling releases [http://forums.civfanatics.com/showthread.php?t=435870 American Kingdoms]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;24th June 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?t=410838&amp;amp;page=3 Modified Scenarios Workshop thread] at the SL Forum (post #53). &lt;br /&gt;
They include:      &lt;br /&gt;
Age of Crusades, In Nomine, Medium Aevum and Drole de Guerre&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:WSilverSkullSL.png]] &#039;&#039;&#039;15th March 2011&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/showthread.php?t=415363 The Lord of the Silver Skull]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;25th February 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?p=10210259#post10210259 Modified Scenarios Workshop thread] at the SL Forum (post #11). &lt;br /&gt;
They include:      &lt;br /&gt;
The Great War: Highway to Hell, How Few Remain, The War of Cuba and The Mongols: From Genghis to Kublai Khan.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:WBattleOfZarklawSL.png]] &#039;&#039;&#039;19th February 2011&#039;&#039;&#039; - Curtsibling releases [http://forums.civfanatics.com/showthread.php?p=10233571#post10233571 Battle of Zarklaw]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:BeachAssault.png]] &#039;&#039;&#039;16th February 2011&#039;&#039;&#039; - Harry Tuttle re-releases [[Beach Assault]] [http://forums.civfanatics.com/showthread.php?t=412144 SL Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wMoscowSL.png]] &#039;&#039;&#039;15th February 2011&#039;&#039;&#039; - Keu releases a modified ToT version of Micheal Daumen&#039;s [http://forums.civfanatics.com/showthread.php?t=410764 Moscow - The Third Rome (post #17)] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wGermanicusSL.png]] &#039;&#039;&#039;13th February 2011&#039;&#039;&#039; - John Petroski releases [[Germanicus on the Rhine]] [http://forums.civfanatics.com/showthread.php?p=10213254#post10213254 SL Thread] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;12th February 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?p=10210259#post10210259 Modified Scenarios Workshop thread] at the SL Forum (post #7). &lt;br /&gt;
They include: The Age of Crusades, The Anglo-Boer War, Bonaparte II, Congo!, First Strike, The Lord of the Rings IV, The Russian Revolution and Yugoslavia: Suicide of a European Nation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wKoSSL.png]] &#039;&#039;&#039;12th February 2011&#039;&#039;&#039; - Custsibling re-releases [[Kingdoms of Steel]] [http://forums.civfanatics.com/showthread.php?p=10210185#post10210185 SL Thread] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;11th February 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversions / mods in the [http://forums.civfanatics.com/showthread.php?p=10208556#post10208556 Modified Scenarios Workshop thread] at the SL Forum (post#3).&lt;br /&gt;
They include: The Italian Wars, Historibus Europae, Hannibal&#039;s War, Gold Gulch, Struggle for Empire, Colonialism II, Carolus Invictissimus, The American Civil War and the Thirty Years War.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wGreatGameSL.png]] &#039;&#039;&#039;11th February 2011&#039;&#039;&#039; - Keu releases a modified ToT version of Micheal Daumen&#039;s [http://forums.civfanatics.com/showthread.php?p=10206652#post10206652 The Great Game] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wAWISL.png]] &#039;&#039;&#039;9th February 2011&#039;&#039;&#039; - civ2units releases [[American War of Independence]] [http://forums.civfanatics.com/showthread.php?t=411273 SL Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wSovietSteelSL.png]] &#039;&#039;&#039;4th February 2011&#039;&#039;&#039; - Curtsibling re-releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=16511 Soviet Steel for MGE]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wBitterMGE.png]] &#039;&#039;&#039;3rd February 2011&#039;&#039;&#039; - Curtsibling re-releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=16500 Bitterfrost for MGE]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wKaiserSL.png]] &#039;&#039;&#039;29th January 2011&#039;&#039;&#039; - Curtsibling re-releases [http://forums.civfanatics.com/showthread.php?t=409947 Kaiser]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wDalekSL.png]] &#039;&#039;&#039;28th January 2011&#039;&#039;&#039; - Curtsibling releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=16446 Dalek Tyranny]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wDictator_2011SL.png]] &#039;&#039;&#039;27th January 2011&#039;&#039;&#039; - Curtsibling releases [[The Eurasian Wars]] [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=16437 SL Thread] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wExterminateSL.png]] &#039;&#039;&#039;27th January 2011&#039;&#039;&#039; - Curtsibling releases [[Extermination]] [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=16438 SL Thread]&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Main_Page&amp;diff=5433</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Main_Page&amp;diff=5433"/>
		<updated>2020-02-09T17:37:48Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* NEWS */  Over the Reich 4 release announcement&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:CIV2TITLE.png|center]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hi! The Scenario League is alive and well. Be sure to check back regularly as we rebuild the wiki. If you would like to help please let us know in this thread [http://forums.civfanatics.com/showthread.php?t=409484| SL Wiki Upload List]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== NEWS ==&lt;br /&gt;
&lt;br /&gt;
[[Image:OTRpreview.png]] &#039;&#039;&#039;9th December 2020&#039;&#039;&#039; - John Petroski &amp;amp; Prof. Garfield release [https://forums.civfanatics.com/resources/over-the-reich.27172/ Over the Reich 4 ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:Techumseh_avatar.png ]] &#039;&#039;&#039;19th January 2020&#039;&#039;&#039; - Techumseh re-releases all his scenarios for Test of Time! [http://sleague.civfanatics.com/index.php?title=User:Techumseh]&lt;br /&gt;
&lt;br /&gt;
[[Image:OTRpreview.png]] &#039;&#039;&#039;20th December 2018&#039;&#039;&#039; - John Petroski &amp;amp; Prof. Garfield release [https://forums.civfanatics.com/threads/over-the-reich-a-multiplayer-scenario-for-totpp-and-lua-released.639907/#post-15313097 Over the Reich ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:Napoleon Icon.gif]] &#039;&#039;&#039;21st November 2018&#039;&#039;&#039; - Tootall_2012 releases [https://forums.civfanatics.com/threads/napol%C3%A9on-i-1805-1815-totpp-and-lua-scenario-released.638700/ Napoléon I 1805 - 1815 ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:Sealion.png]] &#039;&#039;&#039;19th June 2018&#039;&#039;&#039; - Techumseh releases [https://forums.civfanatics.com/threads/operation-seelowe-released.633642/ Operation Seelowe ToTPP]&lt;br /&gt;
&lt;br /&gt;
[[Image:Caesar1.png]] &#039;&#039;&#039;16th April 2018&#039;&#039;&#039; - John Petroski &amp;amp; Grishnach release [https://forums.civfanatics.com/threads/caesars-gallic-wars.628330//Caesar&#039;s Gallic Wars ToTPP and Lua]&lt;br /&gt;
&lt;br /&gt;
[[Image:4KOR.gif]] &#039;&#039;&#039;12th June 2017&#039;&#039;&#039; - Patine &amp;amp; McMonkey release [https://forums.civfanatics.com/threads/korean-war-revisited.452059//The_Korean_War_Redux_ToTPP_v1  The Korean War Redux ToTPP]&lt;br /&gt;
&lt;br /&gt;
[[Image:Nam65_Icon.png]] &#039;&#039;&#039;20th June 2017&#039;&#039;&#039; - Tootall_2012 releases [https://forums.civfanatics.com/threads/vietnam-war-development-thread.534783/  Vietnam 1965- 1975 ToTPP]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Anarchist.png]] &#039;&#039;&#039;30th March 2015&#039;&#039;&#039; - McMonkey releases [http://sleague.civfanatics.com/index.php/The_Spanish_Civil_War_ToTPP Spanish Civil War ToTPP]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Numidian.png]] &#039;&#039;&#039;12th November 2013&#039;&#039;&#039; - Nicheal releases [http://sleague.civfanatics.com/index.php/Ancient_Steel Ancient Steel]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Speeder.png]] &#039;&#039;&#039;12th November 2013&#039;&#039;&#039; - Nicheal releases [http://sleague.civfanatics.com/index.php/SubWar Sub War Deluxe]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:RomBr.png]] &#039;&#039;&#039;5th November 2013&#039;&#039;&#039; - committed hero (aka Michael Daumen) releases [http://forums.civfanatics.com/showthread.php?t=513967 Roman Britain]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:WWIB.png]] &#039;&#039;&#039;1st October 2013&#039;&#039;&#039; - Bultro releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=21851 Worldwar - In the Balance]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;March to October 2013&#039;&#039;&#039; - Petit&#039;s ToT Mods include Menilek II of Ethiopia, Unity of Italy, Fire and Roses, Four Sea Republic, Star Wars: Insurrection (version 1.3), Star Contact: Part 1 The Star Wars, Cold War Crisis, Timur, Spanish Civil War: The Defence of Madrid (version 2.1), Mamluks, Sparta, Hellenis, World War One, American Civil War, Komnenai, The Thirty Years War and Carolus [http://forums.civfanatics.com/showthread.php?t=410838&amp;amp;page=6 Petit&#039;s ToT Mods thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AHD.png]] &#039;&#039;&#039;13th July 2013&#039;&#039;&#039; - Tootall_2012 releases [http://sleague.civfanatics.com/index.php/A_House_Divided_1861_-1865 A House Divided 1861 - 1865]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:STM.png]] &#039;&#039;&#039;24th June 2013&#039;&#039;&#039; - Metro Polis releases [http://forums.civfanatics.com/showthread.php?t=466004 Star Trek Mod for ToT]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Zarklaw2_Icon.gif]] &#039;&#039;&#039;30th April 2013&#039;&#039;&#039; - Curtsibling releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=21147 Battle fo Zarklaw II]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:LDoE.png]] &#039;&#039;&#039;19th April 2013&#039;&#039;&#039; - Dadais releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=21113 Last Days Of Empire]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;16th March 2013&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?p=10210259#post10210259 Modified Scenarios Workshop thread] at the SL Forum (post #79). &lt;br /&gt;
They include: The Peloponnesian War, Struggle for Empire, The Seven Years War, The Spanish-American War: The Carribean, Crises of the New World Order, 2013: A Union Divided, Moria A Journey in the Dark and The Lord of the Rings by Harlan Thompson.     &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;26th September 2012&#039;&#039;&#039; - Techumseh releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=20137 TechMod]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Blood.png]] &#039;&#039;&#039;7th October 2012&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/showthread.php?t=477405 Blood and Sieges]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:TechMod.png]] &#039;&#039;&#039;26th September 2012&#039;&#039;&#039; - Techumseh releases [http://forums.civfanatics.com/showthread.php?t=476516 TechMod]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SpaceMod.png]] &#039;&#039;&#039;18th September 2012&#039;&#039;&#039; - Skulb releases [http://forums.civfanatics.com/showthread.php?t=475802 Space Mod for ToT]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:IwoJima.png]] &#039;&#039;&#039;8th September 2012&#039;&#039;&#039; - Tootall_2012 releases [http://forums.civfanatics.com/showthread.php?t=474972 Battle of Iwo Jima 1945]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Curzan.png]] &#039;&#039;&#039;18th August 2012&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/showthread.php?t=459580 The Cruzan Colony (See post #12)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SciFi.png]] &#039;&#039;&#039;24th June 2012&#039;&#039;&#039; - Metro Polis releases [http://forums.civfanatics.com/showthread.php?t=466004 Star Trek Mod for ToT]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:BoF44DD.png]] &#039;&#039;&#039;12th February 2012&#039;&#039;&#039; - Tootall_2012 releases [http://sleague.civfanatics.com/index.php/Battle_of_France_1944 Battle for France 1944]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SilmarilSL.png]] &#039;&#039;&#039;3rd October 2011&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=17697 The Silmarillion]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Sobieski.png]] &#039;&#039;&#039;12th September 2011&#039;&#039;&#039; - Nikoagonistes (aka Ghost of Disco) releases [http://forums.civfanatics.com/showthread.php?t=428221 Jan III Sobieski v.1.0 (See post #11)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AmericanKingdomsSL.png]] &#039;&#039;&#039;14th August 2011&#039;&#039;&#039; - Curtsibling releases [http://forums.civfanatics.com/showthread.php?t=435870 American Kingdoms]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;24th June 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?t=410838&amp;amp;page=3 Modified Scenarios Workshop thread] at the SL Forum (post #53). &lt;br /&gt;
They include:      &lt;br /&gt;
Age of Crusades, In Nomine, Medium Aevum and Drole de Guerre&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:WSilverSkullSL.png]] &#039;&#039;&#039;15th March 2011&#039;&#039;&#039; - Nicheal releases [http://forums.civfanatics.com/showthread.php?t=415363 The Lord of the Silver Skull]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;25th February 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?p=10210259#post10210259 Modified Scenarios Workshop thread] at the SL Forum (post #11). &lt;br /&gt;
They include:      &lt;br /&gt;
The Great War: Highway to Hell, How Few Remain, The War of Cuba and The Mongols: From Genghis to Kublai Khan.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:WBattleOfZarklawSL.png]] &#039;&#039;&#039;19th February 2011&#039;&#039;&#039; - Curtsibling releases [http://forums.civfanatics.com/showthread.php?p=10233571#post10233571 Battle of Zarklaw]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:BeachAssault.png]] &#039;&#039;&#039;16th February 2011&#039;&#039;&#039; - Harry Tuttle re-releases [[Beach Assault]] [http://forums.civfanatics.com/showthread.php?t=412144 SL Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wMoscowSL.png]] &#039;&#039;&#039;15th February 2011&#039;&#039;&#039; - Keu releases a modified ToT version of Micheal Daumen&#039;s [http://forums.civfanatics.com/showthread.php?t=410764 Moscow - The Third Rome (post #17)] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wGermanicusSL.png]] &#039;&#039;&#039;13th February 2011&#039;&#039;&#039; - John Petroski releases [[Germanicus on the Rhine]] [http://forums.civfanatics.com/showthread.php?p=10213254#post10213254 SL Thread] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;12th February 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversuons / mods in the [http://forums.civfanatics.com/showthread.php?p=10210259#post10210259 Modified Scenarios Workshop thread] at the SL Forum (post #7). &lt;br /&gt;
They include: The Age of Crusades, The Anglo-Boer War, Bonaparte II, Congo!, First Strike, The Lord of the Rings IV, The Russian Revolution and Yugoslavia: Suicide of a European Nation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wKoSSL.png]] &#039;&#039;&#039;12th February 2011&#039;&#039;&#039; - Custsibling re-releases [[Kingdoms of Steel]] [http://forums.civfanatics.com/showthread.php?p=10210185#post10210185 SL Thread] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ToT1.png]] &#039;&#039;&#039;11th February 2011&#039;&#039;&#039; - Petit releases a collection of ToT conversions / mods in the [http://forums.civfanatics.com/showthread.php?p=10208556#post10208556 Modified Scenarios Workshop thread] at the SL Forum (post#3).&lt;br /&gt;
They include: The Italian Wars, Historibus Europae, Hannibal&#039;s War, Gold Gulch, Struggle for Empire, Colonialism II, Carolus Invictissimus, The American Civil War and the Thirty Years War.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wGreatGameSL.png]] &#039;&#039;&#039;11th February 2011&#039;&#039;&#039; - Keu releases a modified ToT version of Micheal Daumen&#039;s [http://forums.civfanatics.com/showthread.php?p=10206652#post10206652 The Great Game] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wAWISL.png]] &#039;&#039;&#039;9th February 2011&#039;&#039;&#039; - civ2units releases [[American War of Independence]] [http://forums.civfanatics.com/showthread.php?t=411273 SL Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wSovietSteelSL.png]] &#039;&#039;&#039;4th February 2011&#039;&#039;&#039; - Curtsibling re-releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=16511 Soviet Steel for MGE]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wBitterMGE.png]] &#039;&#039;&#039;3rd February 2011&#039;&#039;&#039; - Curtsibling re-releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=16500 Bitterfrost for MGE]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wKaiserSL.png]] &#039;&#039;&#039;29th January 2011&#039;&#039;&#039; - Curtsibling re-releases [http://forums.civfanatics.com/showthread.php?t=409947 Kaiser]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wDalekSL.png]] &#039;&#039;&#039;28th January 2011&#039;&#039;&#039; - Curtsibling releases [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=16446 Dalek Tyranny]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wDictator_2011SL.png]] &#039;&#039;&#039;27th January 2011&#039;&#039;&#039; - Curtsibling releases [[The Eurasian Wars]] [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=16437 SL Thread] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:wExterminateSL.png]] &#039;&#039;&#039;27th January 2011&#039;&#039;&#039; - Curtsibling releases [[Extermination]] [http://forums.civfanatics.com/downloads.php?do=file&amp;amp;id=16438 SL Thread]&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=User:Techumseh&amp;diff=5220</id>
		<title>User:Techumseh</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=User:Techumseh&amp;diff=5220"/>
		<updated>2020-01-05T22:43:21Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: Trying to get same message as Techumseh.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Just trying to create this page to see if I get the same message as Techumseh.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_1:_%22Hello_World%22&amp;diff=5219</id>
		<title>Get Started With Lua Events Lesson 1: &quot;Hello World&quot;</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_1:_%22Hello_World%22&amp;diff=5219"/>
		<updated>2020-01-05T17:10:08Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back To [[Get Started With Lua Events by Prof. Garfield | Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is currently in the thread [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/ Get Started With Lua Events].  If someone were to copy it here, it would be much appreciated.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=The_spaceship_object&amp;diff=5218</id>
		<title>The spaceship object</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=The_spaceship_object&amp;diff=5218"/>
		<updated>2019-08-18T03:38:23Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back To [[TOTPP Functions]]&lt;br /&gt;
&lt;br /&gt;
As of ToTPP v0.15.1 there is nothing in the spaceship object.  (Or, there is something, but it is not documented in the Lua Function Reference.)&lt;br /&gt;
&lt;br /&gt;
Try these:&lt;br /&gt;
&lt;br /&gt;
spaceship.owner&lt;br /&gt;
&lt;br /&gt;
spaceship.structural&lt;br /&gt;
&lt;br /&gt;
spaceship.propulsion&lt;br /&gt;
&lt;br /&gt;
spaceship.fuel&lt;br /&gt;
&lt;br /&gt;
spaceship.habitation&lt;br /&gt;
&lt;br /&gt;
spaceship.lifesupport&lt;br /&gt;
&lt;br /&gt;
spaceship.solar&lt;br /&gt;
&lt;br /&gt;
spaceship.launched&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=The_spaceship_object&amp;diff=5217</id>
		<title>The spaceship object</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=The_spaceship_object&amp;diff=5217"/>
		<updated>2019-08-18T03:38:04Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back To [[TOTPP Functions]]&lt;br /&gt;
&lt;br /&gt;
As of ToTPP v0.15.1 there is nothing in the spaceship object.  (Or, there is something, but it is not documented in the Lua Function Reference.)&lt;br /&gt;
&lt;br /&gt;
Try these:&lt;br /&gt;
&lt;br /&gt;
spaceship.owner&lt;br /&gt;
spaceship.structural&lt;br /&gt;
spaceship.propulsion&lt;br /&gt;
spaceship.fuel&lt;br /&gt;
spaceship.habitation&lt;br /&gt;
spaceship.lifesupport&lt;br /&gt;
spaceship.solar&lt;br /&gt;
spaceship.launched&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5216</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5216"/>
		<updated>2019-08-16T02:19:53Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].  (I provided them at the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the key &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [https://forums.civfanatics.com/threads/totpp-flags-and-counters-library.648757/ flags]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of the state table passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) &amp;lt;/code&amp;gt; to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
Civ.scen.onLoad and civ.scen.onScenarioLoaded appear at first glance to do the same thing.  When a game is loaded, they execute their code.  So what&#039;s the difference?  Well, the first difference is that the &amp;quot;buffer&amp;quot; that is attached to the end of a save game file (and which is used to re-create the state), is available to civ.scen.onLoad.  The other difference is timing.  civ.scen.onScenarioLoaded happens &#039;&#039;after&#039;&#039; the rules.txt information is accessed by the game, while onLoad happens before that.  That means, if you are interested in changing some feature of the game based on the season (such as the road multiplier), you will want to do that in civ.scen.onScenarioLoaded.  The code in events.lua (which is not part of a function definition) is executed before civ.scen.onLoad.  This is how the various tables and other data are built for the scenario.&lt;br /&gt;
&lt;br /&gt;
I mentioned the road multiplier in the last paragraph.  When you did testing in the Classic Rome scenario, you may have noticed that roads granted unlimited movement.  This is because when I converted the Rome scenario to Test of Time, I failed to include an @COSMIC2 line in the rules.txt, and due to a bug, TOTPP doesn&#039;t look at the @COSMIC value instead.  During my live creation of the munition library, I inserted a line &amp;lt;code&amp;gt;totpp.movementMultipliers.road=2&amp;lt;/code&amp;gt;, which counteracts the bug.  As I mentioned last paragraph, if I wanted to override rules.txt (rather than replace an omission), I would have had to put the line in the function supplied to civ.scen.onScenarioLoaded.&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;br /&gt;
&lt;br /&gt;
This concludes the last fundamental lesson for writing Civilization II Scenario Events with Lua.  I may, at some point, add some more material, but that will be to either re-visit stuff I mentioned in earlier lessons but then forgot about, or to add tips on how to do certain things or use certain functionality.  For the latter case, I may simply decide to write an independent document instead.&lt;br /&gt;
&lt;br /&gt;
Thank you for following these lessons and getting to the end.  If there are any improvements you think could be made to these lessons, please either let me know or just make them yourself.  My goal is to make it easy for others to use the tools lua provides for Civ II, and if a change would improve this product, then I&#039;d like to make it.  Feel free to redistribute and modify these lessons.  I would appreciate credit (and a notice that changes were made to the text if applicable), and maybe a PM in the civfanatics forums of what you did, but these aren&#039;t really essential.  After all, these lessons are only good for teaching Lua with Civilization II, so just about any use of them is likely to further that goal.&lt;br /&gt;
&lt;br /&gt;
Good luck with your projects.  Remember that you will gain confidence with practice and experience.  Ask for help if and when you need it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5215</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5215"/>
		<updated>2019-08-16T02:15:57Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Conclusion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is still under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].  (I provided them at the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the key &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [https://forums.civfanatics.com/threads/totpp-flags-and-counters-library.648757/ flags]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of the state table passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) &amp;lt;/code&amp;gt; to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
Civ.scen.onLoad and civ.scen.onScenarioLoaded appear at first glance to do the same thing.  When a game is loaded, they execute their code.  So what&#039;s the difference?  Well, the first difference is that the &amp;quot;buffer&amp;quot; that is attached to the end of a save game file (and which is used to re-create the state), is available to civ.scen.onLoad.  The other difference is timing.  civ.scen.onScenarioLoaded happens &#039;&#039;after&#039;&#039; the rules.txt information is accessed by the game, while onLoad happens before that.  That means, if you are interested in changing some feature of the game based on the season (such as the road multiplier), you will want to do that in civ.scen.onScenarioLoaded.  The code in events.lua (which is not part of a function definition) is executed before civ.scen.onLoad.  This is how the various tables and other data are built for the scenario.&lt;br /&gt;
&lt;br /&gt;
I mentioned the road multiplier in the last paragraph.  When you did testing in the Classic Rome scenario, you may have noticed that roads granted unlimited movement.  This is because when I converted the Rome scenario to Test of Time, I failed to include an @COSMIC2 line in the rules.txt, and due to a bug, TOTPP doesn&#039;t look at the @COSMIC value instead.  During my live creation of the munition library, I inserted a line &amp;lt;code&amp;gt;totpp.movementMultipliers.road=2&amp;lt;/code&amp;gt;, which counteracts the bug.  As I mentioned last paragraph, if I wanted to override rules.txt (rather than replace an omission), I would have had to put the line in the function supplied to civ.scen.onScenarioLoaded.&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;br /&gt;
&lt;br /&gt;
This concludes the last fundamental lesson for writing Civilization II Scenario Events with Lua.  I may, at some point, add some more material, but that will be to either re-visit stuff I mentioned in earlier lessons but then forgot about, or to add tips on how to do certain things or use certain functionality.  For the latter case, I may simply decide to write an independent document instead.&lt;br /&gt;
&lt;br /&gt;
Thank you for following these lessons and getting to the end.  If there are any improvements you think could be made to these lessons, please either let me know or just make them yourself.  My goal is to make it easy for others to use the tools lua provides for Civ II, and if a change would improve this product, then I&#039;d like to make it.  Feel free to redistribute and modify these lessons.  I would appreciate credit (and a notice that changes were made to the text if applicable), and maybe a PM in the civfanatics forums of what you did, but these aren&#039;t really essential.  After all, these lessons are only good for teaching Lua with Civilization II, so just about any use of them is likely to further that goal.&lt;br /&gt;
&lt;br /&gt;
Good luck with your projects.  Remember that you will gain confidence with practice and experience.  Ask for help if and when you need it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5214</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5214"/>
		<updated>2019-08-16T02:10:36Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Flags and Accessing State from Modules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is still under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].  (I provided them at the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the key &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [https://forums.civfanatics.com/threads/totpp-flags-and-counters-library.648757/ flags]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of the state table passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) &amp;lt;/code&amp;gt; to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
Civ.scen.onLoad and civ.scen.onScenarioLoaded appear at first glance to do the same thing.  When a game is loaded, they execute their code.  So what&#039;s the difference?  Well, the first difference is that the &amp;quot;buffer&amp;quot; that is attached to the end of a save game file (and which is used to re-create the state), is available to civ.scen.onLoad.  The other difference is timing.  civ.scen.onScenarioLoaded happens &#039;&#039;after&#039;&#039; the rules.txt information is accessed by the game, while onLoad happens before that.  That means, if you are interested in changing some feature of the game based on the season (such as the road multiplier), you will want to do that in civ.scen.onScenarioLoaded.  The code in events.lua (which is not part of a function definition) is executed before civ.scen.onLoad.  This is how the various tables and other data are built for the scenario.&lt;br /&gt;
&lt;br /&gt;
I mentioned the road multiplier in the last paragraph.  When you did testing in the Classic Rome scenario, you may have noticed that roads granted unlimited movement.  This is because when I converted the Rome scenario to Test of Time, I failed to include an @COSMIC2 line in the rules.txt, and due to a bug, TOTPP doesn&#039;t look at the @COSMIC value instead.  During my live creation of the munition library, I inserted a line &amp;lt;code&amp;gt;totpp.movementMultipliers.road=2&amp;lt;/code&amp;gt;, which counteracts the bug.  As I mentioned last paragraph, if I wanted to override rules.txt (rather than replace an omission), I would have had to put the line in the function supplied to civ.scen.onScenarioLoaded.&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;br /&gt;
&lt;br /&gt;
This concludes the last fundamental lesson for writing Civilization II Scenario Events with Lua.  I may, at some point, add some more material, but that will be to either re-visit stuff I mentioned in earlier lessons but then forgot about, or to add tips on how to do certain things or use certain functionality.  For the latter case, I may simply decide to write an independent document instead.&lt;br /&gt;
&lt;br /&gt;
Thank you for following these lessons and getting to the end.  If there are any improvements you think could be made to these lessons, please either let me know or just make them yourself.  My goal is to make it easy for others to use the tools lua provides for Civ II, and if a change would improve this product, then I&#039;d like to make it.  Feel free to redistribute and modify these lessons.  I would appreciate credit (and a notice that changes were made to the text if applicable), and maybe a PM in the civfanatics forums of what you did, but these aren&#039;t really essential.  After all, these lessons are only good for teaching Lua with Civilization II, so just about any use of them is likely to further that goal.&lt;br /&gt;
&lt;br /&gt;
Good luck with your projects.  Remember that you may be writing mediocre code before you write good code, and accept that.  You will improve with practice.  Ask for help if and when you need it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5213</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5213"/>
		<updated>2019-08-16T02:09:45Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Flags and Accessing State from Modules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is still under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].  (I provided them at the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the key &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [https://forums.civfanatics.com/threads/totpp-flags-and-counters-library.648757/ flags]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of the state table passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
Civ.scen.onLoad and civ.scen.onScenarioLoaded appear at first glance to do the same thing.  When a game is loaded, they execute their code.  So what&#039;s the difference?  Well, the first difference is that the &amp;quot;buffer&amp;quot; that is attached to the end of a save game file (and which is used to re-create the state), is available to civ.scen.onLoad.  The other difference is timing.  civ.scen.onScenarioLoaded happens &#039;&#039;after&#039;&#039; the rules.txt information is accessed by the game, while onLoad happens before that.  That means, if you are interested in changing some feature of the game based on the season (such as the road multiplier), you will want to do that in civ.scen.onScenarioLoaded.  The code in events.lua (which is not part of a function definition) is executed before civ.scen.onLoad.  This is how the various tables and other data are built for the scenario.&lt;br /&gt;
&lt;br /&gt;
I mentioned the road multiplier in the last paragraph.  When you did testing in the Classic Rome scenario, you may have noticed that roads granted unlimited movement.  This is because when I converted the Rome scenario to Test of Time, I failed to include an @COSMIC2 line in the rules.txt, and due to a bug, TOTPP doesn&#039;t look at the @COSMIC value instead.  During my live creation of the munition library, I inserted a line &amp;lt;code&amp;gt;totpp.movementMultipliers.road=2&amp;lt;/code&amp;gt;, which counteracts the bug.  As I mentioned last paragraph, if I wanted to override rules.txt (rather than replace an omission), I would have had to put the line in the function supplied to civ.scen.onScenarioLoaded.&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;br /&gt;
&lt;br /&gt;
This concludes the last fundamental lesson for writing Civilization II Scenario Events with Lua.  I may, at some point, add some more material, but that will be to either re-visit stuff I mentioned in earlier lessons but then forgot about, or to add tips on how to do certain things or use certain functionality.  For the latter case, I may simply decide to write an independent document instead.&lt;br /&gt;
&lt;br /&gt;
Thank you for following these lessons and getting to the end.  If there are any improvements you think could be made to these lessons, please either let me know or just make them yourself.  My goal is to make it easy for others to use the tools lua provides for Civ II, and if a change would improve this product, then I&#039;d like to make it.  Feel free to redistribute and modify these lessons.  I would appreciate credit (and a notice that changes were made to the text if applicable), and maybe a PM in the civfanatics forums of what you did, but these aren&#039;t really essential.  After all, these lessons are only good for teaching Lua with Civilization II, so just about any use of them is likely to further that goal.&lt;br /&gt;
&lt;br /&gt;
Good luck with your projects.  Remember that you may be writing mediocre code before you write good code, and accept that.  You will improve with practice.  Ask for help if and when you need it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5212</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5212"/>
		<updated>2019-08-16T01:49:57Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Counting Unit Kills */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is still under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].  (I provided them at the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the key &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [[flags.lua]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of it passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
Civ.scen.onLoad and civ.scen.onScenarioLoaded appear at first glance to do the same thing.  When a game is loaded, they execute their code.  So what&#039;s the difference?  Well, the first difference is that the &amp;quot;buffer&amp;quot; that is attached to the end of a save game file (and which is used to re-create the state), is available to civ.scen.onLoad.  The other difference is timing.  civ.scen.onScenarioLoaded happens &#039;&#039;after&#039;&#039; the rules.txt information is accessed by the game, while onLoad happens before that.  That means, if you are interested in changing some feature of the game based on the season (such as the road multiplier), you will want to do that in civ.scen.onScenarioLoaded.  The code in events.lua (which is not part of a function definition) is executed before civ.scen.onLoad.  This is how the various tables and other data are built for the scenario.&lt;br /&gt;
&lt;br /&gt;
I mentioned the road multiplier in the last paragraph.  When you did testing in the Classic Rome scenario, you may have noticed that roads granted unlimited movement.  This is because when I converted the Rome scenario to Test of Time, I failed to include an @COSMIC2 line in the rules.txt, and due to a bug, TOTPP doesn&#039;t look at the @COSMIC value instead.  During my live creation of the munition library, I inserted a line &amp;lt;code&amp;gt;totpp.movementMultipliers.road=2&amp;lt;/code&amp;gt;, which counteracts the bug.  As I mentioned last paragraph, if I wanted to override rules.txt (rather than replace an omission), I would have had to put the line in the function supplied to civ.scen.onScenarioLoaded.&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;br /&gt;
&lt;br /&gt;
This concludes the last fundamental lesson for writing Civilization II Scenario Events with Lua.  I may, at some point, add some more material, but that will be to either re-visit stuff I mentioned in earlier lessons but then forgot about, or to add tips on how to do certain things or use certain functionality.  For the latter case, I may simply decide to write an independent document instead.&lt;br /&gt;
&lt;br /&gt;
Thank you for following these lessons and getting to the end.  If there are any improvements you think could be made to these lessons, please either let me know or just make them yourself.  My goal is to make it easy for others to use the tools lua provides for Civ II, and if a change would improve this product, then I&#039;d like to make it.  Feel free to redistribute and modify these lessons.  I would appreciate credit (and a notice that changes were made to the text if applicable), and maybe a PM in the civfanatics forums of what you did, but these aren&#039;t really essential.  After all, these lessons are only good for teaching Lua with Civilization II, so just about any use of them is likely to further that goal.&lt;br /&gt;
&lt;br /&gt;
Good luck with your projects.  Remember that you may be writing mediocre code before you write good code, and accept that.  You will improve with practice.  Ask for help if and when you need it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5211</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5211"/>
		<updated>2019-08-16T01:44:56Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is still under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].  (I provided them at the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the value &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [[flags.lua]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of it passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
Civ.scen.onLoad and civ.scen.onScenarioLoaded appear at first glance to do the same thing.  When a game is loaded, they execute their code.  So what&#039;s the difference?  Well, the first difference is that the &amp;quot;buffer&amp;quot; that is attached to the end of a save game file (and which is used to re-create the state), is available to civ.scen.onLoad.  The other difference is timing.  civ.scen.onScenarioLoaded happens &#039;&#039;after&#039;&#039; the rules.txt information is accessed by the game, while onLoad happens before that.  That means, if you are interested in changing some feature of the game based on the season (such as the road multiplier), you will want to do that in civ.scen.onScenarioLoaded.  The code in events.lua (which is not part of a function definition) is executed before civ.scen.onLoad.  This is how the various tables and other data are built for the scenario.&lt;br /&gt;
&lt;br /&gt;
I mentioned the road multiplier in the last paragraph.  When you did testing in the Classic Rome scenario, you may have noticed that roads granted unlimited movement.  This is because when I converted the Rome scenario to Test of Time, I failed to include an @COSMIC2 line in the rules.txt, and due to a bug, TOTPP doesn&#039;t look at the @COSMIC value instead.  During my live creation of the munition library, I inserted a line &amp;lt;code&amp;gt;totpp.movementMultipliers.road=2&amp;lt;/code&amp;gt;, which counteracts the bug.  As I mentioned last paragraph, if I wanted to override rules.txt (rather than replace an omission), I would have had to put the line in the function supplied to civ.scen.onScenarioLoaded.&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;br /&gt;
&lt;br /&gt;
This concludes the last fundamental lesson for writing Civilization II Scenario Events with Lua.  I may, at some point, add some more material, but that will be to either re-visit stuff I mentioned in earlier lessons but then forgot about, or to add tips on how to do certain things or use certain functionality.  For the latter case, I may simply decide to write an independent document instead.&lt;br /&gt;
&lt;br /&gt;
Thank you for following these lessons and getting to the end.  If there are any improvements you think could be made to these lessons, please either let me know or just make them yourself.  My goal is to make it easy for others to use the tools lua provides for Civ II, and if a change would improve this product, then I&#039;d like to make it.  Feel free to redistribute and modify these lessons.  I would appreciate credit (and a notice that changes were made to the text if applicable), and maybe a PM in the civfanatics forums of what you did, but these aren&#039;t really essential.  After all, these lessons are only good for teaching Lua with Civilization II, so just about any use of them is likely to further that goal.&lt;br /&gt;
&lt;br /&gt;
Good luck with your projects.  Remember that you may be writing mediocre code before you write good code, and accept that.  You will improve with practice.  Ask for help if and when you need it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5210</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5210"/>
		<updated>2019-08-15T23:57:40Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* civ.scen.onLoad vs. civ.scen.onScenarioLoaded */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is still under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [[here]].  (These are the same as I provided for the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the value &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [[flags.lua]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of it passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
Civ.scen.onLoad and civ.scen.onScenarioLoaded appear at first glance to do the same thing.  When a game is loaded, they execute their code.  So what&#039;s the difference?  Well, the first difference is that the &amp;quot;buffer&amp;quot; that is attached to the end of a save game file (and which is used to re-create the state), is available to civ.scen.onLoad.  The other difference is timing.  civ.scen.onScenarioLoaded happens &#039;&#039;after&#039;&#039; the rules.txt information is accessed by the game, while onLoad happens before that.  That means, if you are interested in changing some feature of the game based on the season (such as the road multiplier), you will want to do that in civ.scen.onScenarioLoaded.  The code in events.lua (which is not part of a function definition) is executed before civ.scen.onLoad.  This is how the various tables and other data are built for the scenario.&lt;br /&gt;
&lt;br /&gt;
I mentioned the road multiplier in the last paragraph.  When you did testing in the Classic Rome scenario, you may have noticed that roads granted unlimited movement.  This is because when I converted the Rome scenario to Test of Time, I failed to include an @COSMIC2 line in the rules.txt, and due to a bug, TOTPP doesn&#039;t look at the @COSMIC value instead.  During my live creation of the munition library, I inserted a line &amp;lt;code&amp;gt;totpp.movementMultipliers.road=2&amp;lt;/code&amp;gt;, which counteracts the bug.  As I mentioned last paragraph, if I wanted to override rules.txt (rather than replace an omission), I would have had to put the line in the function supplied to civ.scen.onScenarioLoaded.&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;br /&gt;
&lt;br /&gt;
This concludes the last fundamental lesson for writing Civilization II Scenario Events with Lua.  I may, at some point, add some more material, but that will be to either re-visit stuff I mentioned in earlier lessons but then forgot about, or to add tips on how to do certain things or use certain functionality.  For the latter case, I may simply decide to write an independent document instead.&lt;br /&gt;
&lt;br /&gt;
Thank you for following these lessons and getting to the end.  If there are any improvements you think could be made to these lessons, please either let me know or just make them yourself.  My goal is to make it easy for others to use the tools lua provides for Civ II, and if a change would improve this product, then I&#039;d like to make it.  Feel free to redistribute and modify these lessons.  I would appreciate credit (and a notice that changes were made to the text if applicable), and maybe a PM in the civfanatics forums of what you did, but these aren&#039;t really essential.  After all, these lessons are only good for teaching Lua with Civilization II, so just about any use of them is likely to further that goal.&lt;br /&gt;
&lt;br /&gt;
Good luck with your projects.  Remember that you may be writing mediocre code before you write good code, and accept that.  You will improve with practice.  Ask for help if and when you need it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5209</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5209"/>
		<updated>2019-08-15T23:57:15Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Conclusion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is still under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [[here]].  (These are the same as I provided for the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the value &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [[flags.lua]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of it passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;br /&gt;
&lt;br /&gt;
This concludes the last fundamental lesson for writing Civilization II Scenario Events with Lua.  I may, at some point, add some more material, but that will be to either re-visit stuff I mentioned in earlier lessons but then forgot about, or to add tips on how to do certain things or use certain functionality.  For the latter case, I may simply decide to write an independent document instead.&lt;br /&gt;
&lt;br /&gt;
Thank you for following these lessons and getting to the end.  If there are any improvements you think could be made to these lessons, please either let me know or just make them yourself.  My goal is to make it easy for others to use the tools lua provides for Civ II, and if a change would improve this product, then I&#039;d like to make it.  Feel free to redistribute and modify these lessons.  I would appreciate credit (and a notice that changes were made to the text if applicable), and maybe a PM in the civfanatics forums of what you did, but these aren&#039;t really essential.  After all, these lessons are only good for teaching Lua with Civilization II, so just about any use of them is likely to further that goal.&lt;br /&gt;
&lt;br /&gt;
Good luck with your projects.  Remember that you may be writing mediocre code before you write good code, and accept that.  You will improve with practice.  Ask for help if and when you need it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5208</id>
		<title>Get Started With Lua Events Lesson 6: Splitting Code into Multiple Files</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5208"/>
		<updated>2019-08-15T23:49:55Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* A Munition Generation Module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
In this lesson, we will take a look at how to split the code for a scenario&#039;s events into multiple files.  There are several reasons to consider doing this.&lt;br /&gt;
&lt;br /&gt;
The first reason is simply to organize your work.  If you have a series of complicated events, the events.lua file can become very large very quickly. Once your events.lua file has thousands of lines of code in it, it may not be very obvious where the best place is to put that next helper function, or where to implement the function that runs a complicated event.  Sometimes even finding the piece of code that has to be changed can be a bit of a hassle.  In Over the Reich, I sometimes search for the associated civ.scen line, and then search for the exact name of the function I need.  Occasionally, there may even be more searching to find what I actually have to change.  With multiple files, it becomes easier to find things.&lt;br /&gt;
&lt;br /&gt;
Another aspect of using multiple files is that you can make certain changes without worrying about breaking things elsewhere.  If myBigComplicatedFunction relies on aModestHelperFunction for a certain part of its functionality, and a change to myBigComplicatedFunction also requires a change to aModestHelperFunction, you have to make sure that nothing else in your code also uses aModestHelperFunction, or, if something else does depend on it, that aModestHelperFunction either still provides the original functionality, or that all other functions that use aModestHelperFunction are suitably modified.  If myBigComplicatedFunction is defined in its own lua module, then you don&#039;t have to worry about forgetting that aModestHelperFunction was used elsewhere, since it can&#039;t be accessed outside the module unless you specifically allow it to be.&lt;br /&gt;
&lt;br /&gt;
A second reason to split events code into multiple files is to facilitate collaboration.  If all of the events are in a single file, then only one person can make changes to the file at a time.  If one partner starts changing an event, but has to do something else before finishing, everyone waits on one person&#039;s delay.  However, if most aspects of the scenario are separated into individual files, everyone can work on his or her own piece of the puzzle without depriving others of the opportunity to work at that time.&lt;br /&gt;
&lt;br /&gt;
A third reason to split events into multiple modules is to facilitate reusing code.  If everything required to implement an event is in its own file (or files), it becomes much easier for other creators to use your functionality in their scenario.  Since everything they need is already in one place, they don&#039;t have to find every last helper function, or concern themselves with naming conflicts.&lt;br /&gt;
&lt;br /&gt;
===Two Simple Examples===&lt;br /&gt;
&lt;br /&gt;
Let us look at the top of the events.lua file.  You can get the version that I started lesson 6 with [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-01-DefaultRequire.jpg]]&lt;br /&gt;
&lt;br /&gt;
We get code from other files by using the command &amp;lt;code&amp;gt;require&amp;lt;/code&amp;gt; along with a string specifying the file name (except for the .lua extension).  At the moment, we can only get code stored in the lua folder in the Test of Time directory.  This is inconvenient if we&#039;re trying to distribute a scenario, since installing a scenario would require moving certain files to the lua directory, and those file names might conflict.  Instead, we need to tell the Lua interpreter to search in the same folder that the events.lua folder is in.&lt;br /&gt;
&lt;br /&gt;
To do this, we need the following code:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local eventsPath = string.gsub(debug.getinfo(1).source, &amp;quot;@&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 local scenarioFolderPath = string.gsub(eventsPath, &amp;quot;events.lua&amp;quot;, &amp;quot;?.lua&amp;quot;)&lt;br /&gt;
 if string.find(package.path, scenarioFolderPath, 1, true) == nil then&lt;br /&gt;
    package.path = package.path .. &amp;quot;;&amp;quot; .. scenarioFolderPath&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can probably cut and paste this code before the require lines in your events.lua file and not worry about how it works.  However, I&#039;ll provide a brief explanation for reference.&lt;br /&gt;
&lt;br /&gt;
The first line stores the location of the of the current file as a string in eventsPath.&lt;br /&gt;
&lt;br /&gt;
The second line replaces events.lua in the eventsPath with ?.lua, which will tell the Lua interpreter to look for .lua files in the current directory (that is to say, the directory with the events.lua file).  &lt;br /&gt;
&lt;br /&gt;
The if statement adds scenarioFolderPath to the places for the Lua interpreter to search for code, if that directory is not already in the search path.  Since the search path is kept active by the Lua interpreter, it will not be necessary to repeat these lines of code in every file that performs a require action as long as you are running the file as part of events.  If you are writing some other kind of code, you will need to substitute &amp;quot;events.lua&amp;quot; with the name of the file with the code you are running.  Note that for some reason, events.lua is always provided in lower case.  However, for use in other situations, debug.getinfo(1).source uses the correct case for event files. I have only briefly tested this, so you may have to do some testing yourself if this situation comes up (or ask for help in the forums).&lt;br /&gt;
&lt;br /&gt;
Now that we&#039;ve told Lua where to look for our extra code, we can begin moving code to other files.  Think of require as telling Lua to run the entire contents of another file as a function.  We can then assign a value to whatever that file returns, which will usually be a table.  A couple of examples will clarify.&lt;br /&gt;
&lt;br /&gt;
For our first example, we will move our scenario&#039;s parameters to a separate file, and access it via require.  This may not seem worthwhile in this example, but tables like this can get large in a hurry.  At the time of writing, Over the Reich has over 100 lines of parameters (&amp;quot;specialNumbers&amp;quot;), and parameters are something that a designer might like to play with while collaborators make other implementations.  Also, parameters will have to be referenced by other parts of the code, and a file that is required by events.lua cannot, in turn, require events.lua in order to get information.  That means that we&#039;ll have to keep our parameters in a separate file anyway.&lt;br /&gt;
&lt;br /&gt;
Cut the parameters table definition and paste it into a new file, classicRomeParameters.lua.  For the last line, write&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return parameters&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, Near the top of events.lua, where the existing require lines are, add the eventsPath code from above and also the line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local parameters = require(&amp;quot;classicRomeParameters&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
[[File:GetStartedWithLuaLesson6-02-RequireParameters.jpg]]&lt;br /&gt;
&lt;br /&gt;
Open the classicRome scenario and test out a couple of events to make sure everything is the same.&lt;br /&gt;
&lt;br /&gt;
We might find it convenient to put a few tables into the same file.  For this, we will simply return a table containing these tables, and give each table a name in the events.lua file.&lt;br /&gt;
&lt;br /&gt;
Create a file classicRomeAliases.lua and move all the &amp;quot;aliases&amp;quot; tables to that file.  Also move the getCityAt function.&lt;br /&gt;
&lt;br /&gt;
At the bottom of the file, put the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 unitAliases=unitAliases,&lt;br /&gt;
 tribeAliases=tribeAliases,&lt;br /&gt;
 tileAliases=tileAliases,&lt;br /&gt;
 cityAliases=cityAliases,&lt;br /&gt;
 textAliases=textAliases,&lt;br /&gt;
 terrainAliases=terrainAliases,&lt;br /&gt;
 improvementAliases=improvementAliases,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following lines to events.lua (in the require section)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local aliases = require(&amp;quot;classicRomeAliases&amp;quot;)&lt;br /&gt;
 local unitAliases,tribeAliases,tileAliases,cityAliases,textAliases,&lt;br /&gt;
 		terrainAliases,improvementAliases=aliases.unitAliases,aliases.tribeAliases,&lt;br /&gt;
 		aliases.tileAliases,aliases.cityAliases, aliases.textAliases,aliases.terrainAliases,&lt;br /&gt;
 		aliases.improvementAliases&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, our classicRomeAliases module is returning a table with our &amp;quot;alias&amp;quot; tables.  We then assign the entries in this returned table to local variables with the desired names.  Here, I use multiple variable assignment, which I don&#039;t believe I&#039;ve used before (even though Lua allows it), but these could just as simply have been assigned line by line.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-03-RequireAliases.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now, let us move the legion plundering code into its own file, which we&#039;ll call plunder.lua.  First, copy over the legionPlunder function, and paste it near the bottom of the new file.&lt;br /&gt;
&lt;br /&gt;
Now, let us go through the code of this function, and figure out what else we need in our plunder.lua module.&lt;br /&gt;
&lt;br /&gt;
The very first part of the function is a check against unitAliases.legion.  This means we need the unitAliases table, and so we copy the aliases require code to the top of plunder.lua.  We don&#039;t need the path information, since that will be added in events.lua.&lt;br /&gt;
&lt;br /&gt;
A few more lines down, we find that the function cityRadius is also used in legionPlunder.  Therefore, we move that over as well.  We also need the plunderValue function, so copy that over as well.&lt;br /&gt;
&lt;br /&gt;
Next, we check if cityRadius relies on anything, but it doesn&#039;t.&lt;br /&gt;
&lt;br /&gt;
Proceeding to plunderValue, we find that it relies on the parameters table, so require that as well.  The function plunderValue does not appear to depend on anything else, so we&#039;re done moving functionality.  If we missed something, the Lua interpreter will complain at some point anyway.&lt;br /&gt;
&lt;br /&gt;
Next, we require the plunder module in events.lua, with the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local plunder = require(&amp;quot;plunder&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, for each of the functions in plunder.lua, we check if it is used somewhere in events.lua.  We can do this by searching.  plunderValue isn&#039;t used anywhere, so we&#039;re done with that.  City radius is used.  At the bottom of plunder.lua, we begin our return table, and have&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 cityRadius=cityRadius,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, in events.lua, we replace the ocurance of cityRadius with plunder.cityRadius.  Alternatively, we could have put &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local cityRadius=plunder.cityRadius&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
after the line requiring plunder.&lt;br /&gt;
&lt;br /&gt;
Similarly, for legionPlunder, we add &amp;lt;code&amp;gt;legionPlunder=legionPlunder&amp;lt;/code&amp;gt; to the table that plunder.lua returns, and pre-append plunder. to legionPlunder in the one location where it occurs.&lt;br /&gt;
&lt;br /&gt;
Now, we test the legion plunder function and the press 4 generate archers function to make sure everything works.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-04-RequirePlunder.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Working With a Library===&lt;br /&gt;
&lt;br /&gt;
In programming terms, a &amp;quot;library&amp;quot; is a collection of code that can provide some specified functionality to a programmer without that programmer having to modify the code in the library.  Thus far, you have been using the &amp;quot;civ&amp;quot; library to interact with the game, and there has been no need modify it in order to use it in our own events.  (Unfortunately, in the case of the civ library, we don&#039;t actually know how to modify it.)  This is in contrast to much of the code we have written thus far.  For example, the code we wrote last lesson to make Selucid elephants attack Egypt is highly specific.  You couldn&#039;t just cut and paste that code, change the argument of a single function, and get your own goto event.  It is still a good example for how to write a goto event, but a user would still have to actually write the event.&lt;br /&gt;
&lt;br /&gt;
If you plan to write some functionality for your scenario that others might find useful, it is worth spending a little extra effort to see if you can write that functionality in a form that will allow others to use it with minimal effort.  If you can, then a little extra work on your part might save someone else the trouble of re-inventing the wheel, and allow them to complete their project sooner, or to work on some new feature for you to enjoy.  Unfortunately, the Lua scenarios that have been completed at the time of writing haven&#039;t been that good at creating re-usable code, at least in part since we were all getting used to Lua.  This will hopefully be improved in the future.&lt;br /&gt;
&lt;br /&gt;
For now, we&#039;re going to look at a library which is called the General Library (unless someone comes up with a better name) and which can be found [https://forums.civfanatics.com/threads/totpp-the-general-library.647583/ here].  The purpose of this module is to provide relatively simple functionality that probably shouldn&#039;t be implemented every time it is needed.  This is useful for our purposes, since we can look at relatively self contained and simple functions for our first examples.  We&#039;ll create a library for generating munitions later.&lt;br /&gt;
&lt;br /&gt;
This library would be used by invoking the line &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local gen = require(&amp;quot;generalLibrary&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to make these functions available to the console for testing purposes, you would simply omit the local, thereby making gen a global variable.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at a function provided by the General Library &amp;lt;code&amp;gt; gen.hasIrrigation(tile)--&amp;gt;boolean&amp;lt;/code&amp;gt;.  The very first line references the helper function &amp;lt;code&amp;gt; toTile(tile or table)--&amp;gt;tile&amp;lt;/code&amp;gt;, so let us include that code, and look at it first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 -- toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- gen.toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- If given a tile object, returns the tile&lt;br /&gt;
 -- If given coordinates for a tile, returns the tile&lt;br /&gt;
 -- Causes error otherwise&lt;br /&gt;
 -- Helper Function (provided to this library as toTile and gen.toTile)&lt;br /&gt;
 local function toTile(input)&lt;br /&gt;
     if civ.isTile(input) then&lt;br /&gt;
         return input&lt;br /&gt;
     elseif type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         local xVal = input[1] or input[&amp;quot;x&amp;quot;]&lt;br /&gt;
         local yVal = input[2] or input[&amp;quot;y&amp;quot;]&lt;br /&gt;
         local zVal = input[3] or input[&amp;quot;z&amp;quot;] or 0&lt;br /&gt;
         if type(xVal)==&amp;quot;number&amp;quot; and type(yVal)==&amp;quot;number&amp;quot; and type(zVal)==&amp;quot;number&amp;quot; then&lt;br /&gt;
             if civ.getTile(xVal,yVal,zVal) then&lt;br /&gt;
                 return civ.getTile(xVal,yVal,zVal)&lt;br /&gt;
             else&lt;br /&gt;
                 error(&amp;quot;Table with values {&amp;quot;..tostring(xVal)..&amp;quot;,&amp;quot;..tostring(yVal)..&lt;br /&gt;
                         &amp;quot;,&amp;quot;..tostring(zVal)..&amp;quot;} does not correspond to a valid tile.&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
         else&lt;br /&gt;
             error(&amp;quot;Table did not correspond to tile coordinates&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;Did not receive a tile object or table of coordinates.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 gen.toTile = toTile&lt;br /&gt;
 &lt;br /&gt;
 -- gen.hasIrrigation(tile)--&amp;gt;boolean&lt;br /&gt;
 -- returns true if tile has irrigation but no farm&lt;br /&gt;
 -- returns false otherwise&lt;br /&gt;
 function gen.hasIrrigation(tile)&lt;br /&gt;
     tile = toTile(tile)&lt;br /&gt;
     local improvements = tile.improvements&lt;br /&gt;
     -- irrigation, but no mining, so not farmland&lt;br /&gt;
     if improvements &amp;amp; 0x04 == 0x04 and improvements &amp;amp; 0x08 == 0 then&lt;br /&gt;
         return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-05-HasIrrigation.jpg]]&lt;br /&gt;
&lt;br /&gt;
Let us begin by looking at the function &amp;lt;code&amp;gt;toTile&amp;lt;/code&amp;gt;.  The purpose of this function is to allow other functions to accept tile coordinates in a table instead of an actual tile object.  The function tries to be reasonably permissive in the coordinates it will accept, allowing both integer indices and lowercase string indices, and by assuming that a missing z value corresponds to map 0.  The function also tries to give reasonably helpful errors.&lt;br /&gt;
&lt;br /&gt;
This brings up something that should be considered when making reusable code: what to do if you don&#039;t get values you were expecting.  One option is to throw an error and bring up the Lua console.  This is good for scenario creators, so they know something is wrong, but not so great for end users because the error stops the rest of the event from happening, should the mistake slip through playtesting.&lt;br /&gt;
&lt;br /&gt;
The other option is for the code to fail silently, and try to do what it can.  This is the way the old Test of Time macro system often fails.  If Civ II doesn&#039;t &amp;quot;understand&amp;quot; the event, it just doesn&#039;t happen, and doesn&#039;t bother the player with the error.  This means that the scenario will still mostly work, but it is harder to catch issues during playtesting.  Sometimes, this means doing something &amp;quot;sensible&amp;quot; if the input isn&#039;t of the expected type, and might make the code easier to write, since you don&#039;t have to handle inputs differently.&lt;br /&gt;
&lt;br /&gt;
A third option is to write your code such that both things can be done.  At the top of your code, you put in a variable named &amp;quot;debugMode&amp;quot; or something, and make all the functions throw errors when true, and fail silently when false.  Then you playtest with debugMode set to true, and release with debug mode set to false.  However, this means extra work in writing your code and you also have to test everything with debug mode off.&lt;br /&gt;
&lt;br /&gt;
For toTile, I went with the fail with error option, since that will allow every function that uses toTile to assume it is receiving proper data.  It also seems unlikely that people will be regularly trying to check tiles that don&#039;t exist or have tables with tiles and units and improvement objects all in one.  And if they do, &amp;quot;guarding&amp;quot; is fairly straightforward anyway (as we&#039;ve done in previous lessons).&lt;br /&gt;
&lt;br /&gt;
Although toTile is mainly meant to be a helper function for the General Library, it is also put into the gen table to be made available to end users, since it offers useful functionality.  Hence, &amp;lt;code&amp;gt; gen.toTile=toTile&amp;lt;/code&amp;gt;.  Note that we could have given toTile a different name in the gen table that this module will return, such as gen.tableToTile=toTile.  In fact, we could refer to the same function with multiple keys in the gen table, if we want to.&lt;br /&gt;
&lt;br /&gt;
Next, we will look at gen.hasIrrigation.&lt;br /&gt;
&lt;br /&gt;
The first thing to notice is that local is not being used to define this function.  That is because we&#039;re putting the function for gen.hasIrrigation directly into the gen table that this module will return.  We could define hasIrrigation as a local variable and then copy it into the gen table.  However, there is a decent chance that the General Library will have more than 200 functions by the time everything is complete, since it is meant to provide a lot of building block functionality and keep it in one place, and we will run into trouble if we assign 200 local variables in a single function (which a required lua file acts as).&lt;br /&gt;
&lt;br /&gt;
Perhaps the most striking thing is that we begin by changing the value of tile, the argument of the function.  It looks like we&#039;re making a global variable named tile, but we&#039;re not.  When you specify the names of the arguments for a function (in this case tile), you create local variables for that function, which can be given new values just as if you had explicitly used the local keyword.&lt;br /&gt;
&lt;br /&gt;
Beyond that, we extract the integer representing the tile improvements into a local variable (which upon later reflection isn&#039;t really necessary), and check that the irrigation bit is set to 1 and the mining bit is set to 0.  Refer to lesson 5 for why this works.  In fact, we could have simply returned the value of the if statement, rather than specifying return true and return false, although it is very slightly clearer what is going on in the expanded version of the code.&lt;br /&gt;
&lt;br /&gt;
Now, let us write a function to place irrigation on a square.  It seems pretty clear that we should do nothing if the tile has a city, but we also have to decide what to do if there is mining or farmland on the tile, since those interfere with placing irrigation.  We&#039;ll just remove them, on the basis that if we&#039;re trying to &amp;quot;place irrigation,&amp;quot; then we want irrigation to be there when we are finished.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function gen.placeIrrigation(tile)&lt;br /&gt;
    tile = toTile(tile)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These lines open the function and convert a table of coordinates to a tile if necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 if tile.city then&lt;br /&gt;
    return&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the tile has a city, return so nothing else is done in the function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     -- Set irrigation bit to 1&lt;br /&gt;
     tile.improvements = tile.improvements | 0x04&lt;br /&gt;
     -- Set mining bit to 0&lt;br /&gt;
     tile.improvements = tile.improvements &amp;amp; ~0x08&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the irrigation bit to 1 and the mining bit to 0.&lt;br /&gt;
&lt;br /&gt;
The functions in this library don&#039;t have to be complex, and in fact, most probably shouldn&#039;t be.  They just have to make life easier for the end user.  If you reach this lesson before the General Library is considered &amp;quot;complete,&amp;quot; your assignment now is to submit some work for it.  If you don&#039;t feel comfortable doing bitwise operations, you can test the work of others or submit functions that simplify other tasks.  However, there are also some helper functions in the library to facilitate changing bits, so you might also consider working on the unit type flags functions.  Remember, if you want to make functions available to the console for testing purposes, they must be global variables.&lt;br /&gt;
&lt;br /&gt;
=== The Threshold Table and First Look at Metatables===&lt;br /&gt;
&lt;br /&gt;
Consider a scenario design situation that occurred in Over the Reich: a bomber is generating some bombs via a key press, and the number of bombs it should generate is dependant on its current remaining hitpoints.  The more hitpoints the bomber has, the more bombs it should generate.  What we want is to specify that if a bomber has between x and y hitpoints, it should produce 2 bombs.  That is, for a given type of bomber, we want to have, for example,&lt;br /&gt;
&lt;br /&gt;
hp &amp;gt;= 16 --&amp;gt; 4 bombs&lt;br /&gt;
16 &amp;gt; hp &amp;gt;= 12 --&amp;gt; 3 bombs&lt;br /&gt;
12 &amp;gt; hp &amp;gt;= 9 --&amp;gt; 2 bombs&lt;br /&gt;
9 &amp;gt; hp &amp;gt;= 4 --&amp;gt; 1 bomb&lt;br /&gt;
4 &amp;gt; hp &amp;gt;= 0 --&amp;gt; 0 bombs&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Lua tables do not naturally encode this kind of association by default.  However, Lua does have a feature called metatables, which allows us to change the behaviour of tables.  (This will be a much better way to make the specification than I ended up writing in Over the Reich.)&lt;br /&gt;
&lt;br /&gt;
A metatable is a table that we can &amp;quot;attach&amp;quot; to another table, and then the metatable changes the behaviour of that table.  We&#039;ll only look at metatables briefly here, but more information can be found [https://www.tutorialspoint.com/lua/lua_metatables.htm here].&lt;br /&gt;
&lt;br /&gt;
What we want is a data structure that can accept numerical &amp;quot;key values&amp;quot; that are between the key values explicitly specified, and return the appropriate value for those keys.  We will call this data structure a threshold table, since we are specifying threshold values as keys.  We can do this by assigning the following metatable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local mt = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we run &amp;lt;code&amp;gt; setmetatable(myTable,mt)&amp;lt;/code&amp;gt;, then whenever we ask for an index from myTable and that index doesn&#039;t currently exist in myTable, the function assigned to __index will run.  Now let us examine the function.&lt;br /&gt;
&lt;br /&gt;
If the type of the key is not a number, then we return whatever the table value is for that key.  We use the function rawget, because the standard &amp;lt;code&amp;gt;thresholdTable[key]&amp;lt;/code&amp;gt; will invoke this function again if the key doesn&#039;t exist, and so never return an answer (when we want it to return nil).&lt;br /&gt;
&lt;br /&gt;
If the key type is a number, then we look for the largest numerical index that is also less than or equal to the key value.  We return a default value of false if the key submitted is smaller than all numerical values.  False is chosen over nil, so that a maximum value can be set by setting the value of a numerical index to false.  Using the key [-math.huge] allows a return value to be set for all numbers (since all numbers are greater than -math.huge).&lt;br /&gt;
&lt;br /&gt;
Since we don&#039;t want scenario creators to have to re-create threshold tables every time they need them, we&#039;ll add this functionality to the General Library&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local thresholdTableMetatable = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 -- gen.makeThresholdTable(table or nil)--&amp;gt;thresholdTable&lt;br /&gt;
 function gen.makeThresholdTable(inputTable)&lt;br /&gt;
     inputTable = inputTable or {}&lt;br /&gt;
     return setmetatable(inputTable,thresholdTableMetatable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-06-ThresholdTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
===A Munition Generation Module===&lt;br /&gt;
&lt;br /&gt;
Now, let us write some re-usable code for a human player to generate units by pressing a key while an appropriate unit is active.  This sort of code could be used for ranged attacks (generating a &amp;quot;munition&amp;quot;) and also for recruiting mercenaries by paying gold.&lt;br /&gt;
&lt;br /&gt;
The first thing we will want to do is to decide how our code will be used by the end user.  This will, perhaps, change by the time we finish writing the code, but it will at least give us a starting point.&lt;br /&gt;
&lt;br /&gt;
spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&lt;br /&gt;
&lt;br /&gt;
Our goal is that when a player attempts to generate a unit using another unit, they will provide the unit spawning the new unit, and a table of information specifying if a unit (or units) can be spawned and anything else that must happen while spawning (like paying money, expending movement points, etc.).&lt;br /&gt;
&lt;br /&gt;
We have an option here.  We could have the scenario creator provide the specification table as a required file for our module, or the creator can provide it at the time spawnUnit is called.  I choose the latter for a couple of reasons.  The first is that it allows the player to have more than one specification table, either because more than one key can spawn a unit, or because the specification can change over time.  The other is reason is so that the creator can make the table in the events.lua file if desired (since our module can&#039;t require information from events.lua).&lt;br /&gt;
&lt;br /&gt;
Having decided that our generateUnit events are going to be specified by a table, we have to decide what the contents of that table should be.  It seems pretty reasonable to index the specificationTable with the index of the unit type of each unit that can generate using the information in the table.  If a unit type id number is missing, that unit doesn&#039;t generate a munition (or recruit a unit).&lt;br /&gt;
&lt;br /&gt;
The value for each unit type id in the specification table will be a table that specifies how and if that unit generates other units.&lt;br /&gt;
&lt;br /&gt;
 --specificationTable[unitType.id]={&lt;br /&gt;
 --&lt;br /&gt;
 -- goldCost = integer or nil&lt;br /&gt;
 --      amount of gold it costs to generate a unit&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minTreasury = integer or nil&lt;br /&gt;
 --      minimum amount of gold in treasury to generate a unit&lt;br /&gt;
 --      absent means refer to gold cost&lt;br /&gt;
 --      (tribe will generate and be set to 0 if treasury is less than goldCost)&lt;br /&gt;
 -- treasuryFailMessage = string or nil&lt;br /&gt;
 --      A message to be displayed if the unit fails to spawn a unit due to an &lt;br /&gt;
 --      insufficient treasury&lt;br /&gt;
 --      nil means no message&lt;br /&gt;
&lt;br /&gt;
 -- There are three ways to specify move costs, in full movement points,&lt;br /&gt;
 -- in &amp;quot;atomic&amp;quot; movement points, and as a fraction of total movement points for the&lt;br /&gt;
 -- unit type.  Use only one kind per unit type &lt;br /&gt;
 &lt;br /&gt;
 -- moveCost = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMove = integer or nil&lt;br /&gt;
 --      minimum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means any movement points for land/sea, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMove = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostAtomic = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      refers to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveAtomic = integer or nil&lt;br /&gt;
 --      minumum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      referes to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMoveAtomic = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points expended generating the unit&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points that must remain to be allowed&lt;br /&gt;
 --      to generate a unit&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 -- postGenMinMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function, round up to nearest &amp;quot;atomic&amp;quot; move point&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- roundFractionFull = bool or nil&lt;br /&gt;
 --      fractional movement cost and minimum are rounded up to full movement point&lt;br /&gt;
 --      instead of atomic movement point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- roundFractionFullDown = bool or nil&lt;br /&gt;
 --      fractional cost and minimum are rounded down to full move point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- minMoveFailMessage = string or nil&lt;br /&gt;
 --      a message to be displayed if a unit is not generated due to insufficient&lt;br /&gt;
 --      movement points.&lt;br /&gt;
 --      nil means no message &lt;br /&gt;
&lt;br /&gt;
 -- allowedTerrainTypes = table of integers or nil&lt;br /&gt;
 --      a unit may only be generated if the tile it is standing on&lt;br /&gt;
 --      corresponds to one of numbers in the table&lt;br /&gt;
 --      nil means the unit can be generated on any terrain type&lt;br /&gt;
 -- terrainTypeFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to standing&lt;br /&gt;
 --      on the incorrect terrain &lt;br /&gt;
&lt;br /&gt;
 -- requiredTech = tech object or nil&lt;br /&gt;
 --      the generating civ must have this technology in order to generate&lt;br /&gt;
 --      the unit&lt;br /&gt;
 --      nil means no requirement&lt;br /&gt;
 -- techFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to not having&lt;br /&gt;
 --      the correct technology &lt;br /&gt;
&lt;br /&gt;
 -- payload = boolean or string&lt;br /&gt;
 --      if true, unit must have a home city in order to generate munitions&lt;br /&gt;
 --      and generating munitions sets the home city to NONE&lt;br /&gt;
 -- payloadFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to the &lt;br /&gt;
 --      payload restriction&lt;br /&gt;
 -- payloadRestrictionCheck = nil or function(unit)--&amp;gt;boolean&lt;br /&gt;
 --      If function returns false, the home city is not valid for giving the&lt;br /&gt;
 --      unit a payload.  This will be checked when the unit is activated, when&lt;br /&gt;
 --      the unit is given a new home city with the &#039;h&#039; key and when the unit&lt;br /&gt;
 --      tries to generate a munition&lt;br /&gt;
 --      nil means no restriction&lt;br /&gt;
 -- payloadRestrictionMessage = nil or string&lt;br /&gt;
 --      message to show if a unit fails the payloadRestrictionCheck&lt;br /&gt;
&lt;br /&gt;
 -- canGenerateFunction = nil or function(unit)--&amp;gt;boolean &lt;br /&gt;
 --      This function applied to the generating unit must return true in order&lt;br /&gt;
 --      for a unit to be spawned.  All other conditions still apply.&lt;br /&gt;
 --      any failure message should be part of canGenerateFunction&lt;br /&gt;
 --      absent means no extra conditions &lt;br /&gt;
&lt;br /&gt;
 -- generateUnitFunction = nil or function(unit)--&amp;gt;table of unit&lt;br /&gt;
 --      This function creates the unit or units to be generated&lt;br /&gt;
 --      and returns a table containing those units&lt;br /&gt;
 --      Ignore any specifications prefixed with * if this is used&lt;br /&gt;
 --      nil means use other specifications &lt;br /&gt;
&lt;br /&gt;
 --*generatedUnitType = unitType&lt;br /&gt;
 --      The type of unit to be generated&lt;br /&gt;
 --      can&#039;t be nil unless generateUnitFunction is used instead &lt;br /&gt;
&lt;br /&gt;
 --*giveVeteran = bool or nil&lt;br /&gt;
 --      generated unit(s) given veteran status if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
 --      if true, overrides copyVeteranStatus&lt;br /&gt;
&lt;br /&gt;
 --*copyVeteranStatus = bool or nil&lt;br /&gt;
 --      generated unit(s) copy veteran status of generating unit if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
&lt;br /&gt;
 --*setHomeCityFunction = nil or function(generatingUnit)--&amp;gt;cityObject&lt;br /&gt;
 --      determines what home city the spawned unit should have&lt;br /&gt;
 --      nil means a home city of NONE &lt;br /&gt;
&lt;br /&gt;
 --*numberToGenerate = nil or number or thresholdTable or function(generatingUnit)--&amp;gt;number&lt;br /&gt;
 --      if nil, generate 1 unit in all circumstances&lt;br /&gt;
 --      if integer, generate that many units (generate 0 if number less than 0)&lt;br /&gt;
 --      if number not integer, generate floor(number), and 1 more with&lt;br /&gt;
 --      probability number-floor(number)&lt;br /&gt;
 --      if thresholdTable, use remaining hp as the key, to get the number to create&lt;br /&gt;
 --      if function, get the number as the returned value of the function &lt;br /&gt;
&lt;br /&gt;
 -- activate = bool or nil&lt;br /&gt;
 --      Activates one of the generated units if true.  If generateUnitFunction was used,&lt;br /&gt;
 --      the unit at index 1 is activated, if index 1 has a value.  (if not, any unit in&lt;br /&gt;
 --      the list might be chosen)&lt;br /&gt;
&lt;br /&gt;
The very last entry brings forward a change that must be made to our unit generation specification.  Lua&#039;s activate unit command doesn&#039;t run the unit activation trigger, even though the active unit is changed.  Therefore, we must do that manually.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
becomes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit,specificationTable,unitActivationCode)--&amp;gt;table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Perhaps we will change it again later.&lt;br /&gt;
&lt;br /&gt;
I&#039;ve decided to try a different instructional technique for this section.  Instead of writing the code and then going through it section by section, I&#039;ve recorded a video of my coding and testing this module, and I attempt to explain some of the stuff that I do along the way.&lt;br /&gt;
&lt;br /&gt;
I&#039;m not sure of the value of the video.  If you find that there seems to be little useful content relative to the time it takes to watch, then feel free to skip it and continue the lesson.  I don&#039;t teach anything &amp;quot;new&amp;quot; in it, so you won&#039;t miss anything crucial, although I do add a line &amp;lt;code&amp;gt;totpp.movementMultipliers.road = 2&amp;lt;/code&amp;gt;, which fixes a bug when @COSMIC2 is not defined in the rules.txt.  However, the video should be pretty close to how programming Lua can actually happen in the &amp;quot;real world.&amp;quot;  While I did give some thought to how to write the module before I started, I do attempt to solve problems in real time, and make mistakes that are not discovered for a while (including one where I try to explain how I solve a problem and then not actually do a crucial part).&lt;br /&gt;
&lt;br /&gt;
You can find the code [https://forums.civfanatics.com/threads/totpp-the-munitions-library.647910/ here].  Even if you decide not to watch the video, download the code and try testing some of the features based on the specification above.  If you find any bugs, submit a fix (or at least report the issue).&lt;br /&gt;
&lt;br /&gt;
The video can be found [https://youtu.be/XxPyNknGlAo here].&lt;br /&gt;
&lt;br /&gt;
===A Unit Attack Bonus for Complementary Units in Square===&lt;br /&gt;
&lt;br /&gt;
Something we might like to do is to give units an attack bonus if they attack from a square with some special unit, for example a &amp;quot;leader&amp;quot; unit.  The [[Napoléon I]] scenario, for example, gives an attack bonus to units if a commander unit, such as Napoleon, is in the square when the unit is activated (the unit can subsequently move and still retain the bonus as long as no other unit is selected).  We will now make a module providing the same functionality.&lt;br /&gt;
&lt;br /&gt;
We first have to have a basic idea of how this functionality should work.  When a unit is activated, the onActivateUnit event checks if the newly activated unit should get an attack bonus, based on the other units in the square.  If the unit deserves an attack bonus, the corresponding unitType.attack entry is changed, and all the attack value of all other units is reset to the default value.  If the activated unit also does not deserve an attack bonus, that value is also set to the default value.&lt;br /&gt;
&lt;br /&gt;
This now leads us to some more possibilities.  Should multiple bonus units lead to multiple bonuses or only apply the best one?  For example, suppose a legion gets a bonus if an archer is also in the same square.  Should two archers provide twice the bonus?  Perhaps two archers should provide a larger bonus than one, but not twice as much.  Perhaps a legion should also get a bonus if there is a catapult in the square, but that bonus should apply even if the maximum archer bonus is already achieved.  It seems like perhaps there should be a &amp;quot;ranged unit&amp;quot; bonus, an &amp;quot;artillery unit&amp;quot; bonus and maybe a &amp;quot;cavalry&amp;quot; bonus which should all impact the legion&#039;s attack value.  It&#039;s looking like we might end up demanding that a scenario creator make a big complicated table in order to use this functionality, even if they only have simple needs.&lt;br /&gt;
&lt;br /&gt;
What we can do to alleviate this is to write a &amp;quot;simple&amp;quot; version of the event that is easy to use (and program), and also write a more complicated version that gives the expanded capability.&lt;br /&gt;
&lt;br /&gt;
Specification Table for simpleAttackBonus&lt;br /&gt;
&lt;br /&gt;
 --simpleAttackBonusTable[activeUnit.type.id] ={[bonusUnitType.id]=bonusNumber}&lt;br /&gt;
 --simpleAttackBonusTable.type = string&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- if simpleAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- if simpleAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 --simpleAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise &lt;br /&gt;
&lt;br /&gt;
The relevant first draft of the code is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function simpleAttackBonus(activeUnit,simpleAttackBonusTable,defaultAttackTable)&lt;br /&gt;
     -- reset all unit attack values&lt;br /&gt;
     for unitTypeID,attackValue in pairs(defaultAttackTable) do&lt;br /&gt;
         civ.getUnitType(unitTypeID).attack = attackValue&lt;br /&gt;
     end&lt;br /&gt;
     local unitBonusTable = simpleAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
     if not unitBonusTable then&lt;br /&gt;
         -- unitBonusTable is nil (or false), so the active unit can&#039;t&lt;br /&gt;
         -- get a bonus&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
     -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
     for unit in activeUnit.location.units do&lt;br /&gt;
         if unitBonusTable[unit.type.id] and unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
             bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     if bestBonusSoFar == 0 then&lt;br /&gt;
         -- If no bonus unit is found, this will be true, so do nothing else&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- set the new attack and return&lt;br /&gt;
     if string.lower(simpleAttackBonusTable.type) == &amp;quot;addBonus&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = activeUnit.type.attack+bestBonusSoFar&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     local attackMultiplier = 1&lt;br /&gt;
     if type(simpleAttackBonusTable.type) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = (100+bestBonusSoFar)/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
         attackMultiplier = 1+bestBonusSoFar&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar&lt;br /&gt;
     else&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     end&lt;br /&gt;
     -- apply the bonus and round as appropriate&lt;br /&gt;
     if type(simpleAttackBonusTable.round) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;up&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.ceil(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;down&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     else&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now let us go over this section by section.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-07-AttackBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The first thing we do is to reset all the attack values of all the unit types.  That way, if a bonus existed for the last unit activated, that bonus no longer applies.  If a unit type is not in the defaultAttackTable, then we don&#039;t have the information to reset the attack value anyway, so we can safely ignore it by using the pairs function to iterate over the table.&lt;br /&gt;
&lt;br /&gt;
Now, we must find out if the newly activated unit deserves a bonus.  For that, we get the table associated with the active unit&#039;s type.  If the value is nil instead of a table, then the unit&#039;s type is not in the simpleAttackBonusTable, so there is no bonus to apply and the function returns.&lt;br /&gt;
&lt;br /&gt;
If the unit is eligible for bonuses, we then check the units in the square to see if any bonuses actually apply.  We&#039;ve seen this kind of code before.  If the unit in the stack can provide a bonus, and that bonus is better than the best bonus already found, the unit now provides the best bonus.  All bonus types that we can have are better if they are larger, and we are not comparing between bonus types, so a simple numerical comparison will do.  All bonuses are larger than 0 in our formulation, so 0 is a good starting value in the search.&lt;br /&gt;
&lt;br /&gt;
If the best bonus so far is still 0, there is no bonus, so the function can return.&lt;br /&gt;
&lt;br /&gt;
At this point, it occurs to me that when searching for the best bonus, we should exclude the active unit from the search.  That way, you can have a &amp;quot;strength in numbers&amp;quot; bonus, for example.  The relevant change to the code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    for unit in activeUnit.location.units do&lt;br /&gt;
        if unit ~= activeUnit and unitBonusTable[unit.type.id] and &lt;br /&gt;
 			unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, consider&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-08-AttackBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we apply the bonus that we&#039;ve found.  We use string.lower on simpleAttackBonusTable.type so that we don&#039;t have to worry about capitalization.  That does, however, require a correction to &amp;quot;addBonus&amp;quot;, since a lower case string will never be equal to that.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;addbonus&amp;quot; is the only type of bonus that is directly added to the existing attack value.  All other bonus types are a form of multiplication.  Since the addition is straightforward and doesn&#039;t require any rounding, the activeUnit&#039;s type attack value can be changed immediately, and the function execution ended with return.&lt;br /&gt;
&lt;br /&gt;
When there is only one bonus being applied, all other types of bonus are different ways of expressing how to multiply the existing attack value to get a new one, so we simply convert to the appropriate multiplier, and provide an error message if the type of bonus is not one of the valid possibilities.&lt;br /&gt;
&lt;br /&gt;
Finally, we round the attack value to an appropriate integer (since unit attack values must be integers), change the attack value of the active unit&#039;s type, and return to end the function execution.&lt;br /&gt;
&lt;br /&gt;
Now, we integrate into events.lua by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus = require(&amp;quot;attackBonus&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The relevant integration code for events.lua is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local defaultAttackValueTable = {[unitAliases.legion.id]=4}&lt;br /&gt;
 local simpleAttackBonusTable ={}&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=3,[unitAliases.musketeer.id]=4}&lt;br /&gt;
 &lt;br /&gt;
 local function doOnActivation(unit,source)&lt;br /&gt;
     munitions.payloadRestrictionCheck(unit,munitionSpecificationTable)&lt;br /&gt;
 	attackBonus.simpleAttackBonus(unit,simpleAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can check that the bonus is being applied correctly by checking the Civlopedia entry for legion and looking at the attack value.  The following cases must be tested (remember that activating a unit from the city screen doesn&#039;t run the onActivation event, so activate from the map).&lt;br /&gt;
&lt;br /&gt;
 Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
 Legion activated with archer, but no musketeer (7 attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (8 attack)&lt;br /&gt;
 Legion activated with archer and musketeer (8 attack)&lt;br /&gt;
 Legion activated with 2 archer, no musketeer (7 attack)&lt;br /&gt;
 Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
 Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
I recommend making a stack for each of these cases and activating them one by one.&lt;br /&gt;
To facilitate the test, add the following line to doOnActivation&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.ui.text(tostring(unit.type.attack))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You will want to comment out this line after testing.&lt;br /&gt;
&lt;br /&gt;
Next, change simpleAttackBonusTable to do &amp;quot;addpercent&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=30,[unitAliases.musketeer.id]=70}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With no rounding set, standard rounding is used&lt;br /&gt;
 Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
 Legion activated with archer and musketeer (7 attack)&lt;br /&gt;
 Legion activated with 2 archer, no musketeer (5 attack)&lt;br /&gt;
 Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
 Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
These numbers test both rounding up and rounding down.&lt;br /&gt;
&lt;br /&gt;
Now, use&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (6 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next,&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (6 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;standard&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next, we test &amp;quot;addfraction&amp;quot;.  Since we&#039;ve tested all the rounding options, we don&#039;t have to do that again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=0.3,[unitAliases.musketeer.id]=0.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=130,[unitAliases.musketeer.id]=170}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiply&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Before we finish, we should test a legion bonus for the legion.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.legion.id]=2,[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Legion alone should have 4 attack.&lt;br /&gt;
 A second legion on the square should provide 8 attack instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, let us try to formulate a more complicated bonus system.  One thing we mentioned is that we&#039;d like the ability to get bonuses from multiple units, and to be able to get bonuses from different &amp;quot;classes&amp;quot; of units (like &amp;quot;artillery,&amp;quot; &amp;quot;cavalry,&amp;quot; and &amp;quot;ranged attackers.&amp;quot;  Something else we might want to do is to allow different kinds of bonuses.  That is, maybe some units should provide a fixed +2 to any unit receiving the bonus, so that it is better at improving units with a low attack value, while other units should provide a percentage bonus (making them better at supporting units with an already high attack value).  It turns out that both of these ideas are not too difficult to implement individually, but that trying to implement them together makes it problematic to find the best bonus.&lt;br /&gt;
&lt;br /&gt;
Let us implement a bonus system with multiple categories but only one bonus type.  In our specification, we will first specify a data type called &amp;quot;bonusCategory.&amp;quot;  It is still just a table (though we could add a metatable if we wanted), but it will help us make our specification clearer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- A &amp;quot;bonusCategory&amp;quot; is a table&lt;br /&gt;
 -- bonusCategory = {[bonusUnitType.id]=bonusNumber, maxBonusUnits=integer or nil, nextBonusValue = fraction or nil}&lt;br /&gt;
 -- In a bonusCategory, the value for bonusUnitType.id tells what the base bonus for that unit type is,&lt;br /&gt;
 -- maxBonusUnits is the maximum number of units that can provide a bonus in this category,&lt;br /&gt;
 -- nextBonusValue tells how much to reduce the bonus for each subsequent unit,&lt;br /&gt;
 -- e.g. nextBonusValue = 0.7, and 5 units, which each have a bonusNumber=1&lt;br /&gt;
 -- The total bonus is 1(0.7)^0+.7+(.7)(.7)+(.7)^3+(.7)^4 = 1+.7+.49+.343+.2401=2.7731&lt;br /&gt;
 -- (which would be rounded as specified)&lt;br /&gt;
 -- nil means nextBonusValue=1&lt;br /&gt;
 --&lt;br /&gt;
 -- If a unit type is in two bonus categories for the same unit, there is no guarantee that the&lt;br /&gt;
 -- best bonus will be achieved&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, the bonus category is indexed by unitType id numbers for units that can give a bonus, and the corresponding bonus.  It also specifies the maximum number of units that can give a bonus, and a number that governs how to reduce a bonus for extra units.  That way, there can be diminishing returns for bonuses.&lt;br /&gt;
&lt;br /&gt;
Next, we look at the specification for the categoryAttackBonusTable&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 --categoryAttackBonusTable[activeUnit.type.id] =table of bonusCategory&lt;br /&gt;
 --categoryAttackBonusTable.type = string&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up all the percents, then compute the bonus&lt;br /&gt;
 -- i.e. 50% bonus and 50% bonus is 100% bonus, not 125%&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 50% bonus units become 50% + 25% &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up the fractions, then compute the bonus&lt;br /&gt;
 -- i.e. .5 bonus and .5 bonus is 1+.5+.5= 2x bonus, not 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 .5 bonus units become .5+.25 &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 150% and 150% yields 225% of original value&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 100, i.e. nextBonusValue=.5 2 150% bonuses become 150% and 125%&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 1.5 and 1.5 yields 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 1, i.e. nextBonusValue=.5 and two 1.5 bonuses become 1.5 and 1.25&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 --categoryAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise&lt;br /&gt;
 &lt;br /&gt;
 -- If the active unit can get a bonus, go through each category and compute the bonus for that category.&lt;br /&gt;
 -- Then, combine the bonuses for all categories to get the overall bonus, and round the result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With the bonusCategory defined, the value of the unit indices of categoryAttackBonusTable become easy to define.  Most of the specification is showing what exactly the different bonus categories mean, so the end user can use them properly.  It&#039;s not strictly necessary to offer so many choices to the end user on how to specify data, but it can be more convenient.&lt;br /&gt;
&lt;br /&gt;
Here is the actual code (before testing) to implement this more general version of attack bonuses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- HELPER FUNCTION&lt;br /&gt;
 -- findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable) --&amp;gt; number or false&lt;br /&gt;
 -- usedUnitTable is indexed by the i.d. number of units, and if the value for a unit is true,&lt;br /&gt;
 -- then it has already been used for a bonus (and, so, is not eligible)&lt;br /&gt;
 -- The function returns the bonus (before nextBonusValue is applied) if there is one, and marks the &lt;br /&gt;
 -- unit as used in the usedUnitTable&lt;br /&gt;
 -- returns false if no unit qualifies&lt;br /&gt;
 local function findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable)&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
    local bestUnitSoFar = nil&lt;br /&gt;
    -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
    -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
    for unit in tile.units do&lt;br /&gt;
        if not usedUnitTable[unit.id] and bonusCategory[unit.type.id] &lt;br /&gt;
            and bonusCategory[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestUnitSoFar = unit&lt;br /&gt;
            bestBonusSoFar = bonusCategory[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if bestUnitSoFar then&lt;br /&gt;
        usedUnitTable[bestUnitSoFar.id] = true&lt;br /&gt;
        return bestBonusSoFar&lt;br /&gt;
    else&lt;br /&gt;
        return false&lt;br /&gt;
    end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 -- HELPER FUNCTION&lt;br /&gt;
 -- computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
 -- Computes the bonus that the active unit will receive from this category, taking into &lt;br /&gt;
 -- account the type of bonus for the table&lt;br /&gt;
 local function computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local bonusThusFar = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then &lt;br /&gt;
        bonusThusFar = 1&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        bonusThusFar = 100&lt;br /&gt;
    else&lt;br /&gt;
        bonusThusFar = 0&lt;br /&gt;
    end&lt;br /&gt;
    local bonusDiscount = 1&lt;br /&gt;
    for i=1,(bonusCategory.maxBonusUnits or 10000) do&lt;br /&gt;
        local currentBonus =findBestBonusInUnitStack(activeUnit.location,bonusCategory,usedUnitTable) &lt;br /&gt;
        if not currentBonus then&lt;br /&gt;
            -- no more valid bonuses for this category&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
        if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-1)*bonusDiscount+1)&lt;br /&gt;
        elseif bonusType ==&amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
        else&lt;br /&gt;
            bonusThusFar = bonusThusFar+currentBonus*bonusDiscount&lt;br /&gt;
        end&lt;br /&gt;
        bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
    end&lt;br /&gt;
    return bonusThusFar&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 local function categoryAttackBonus(activeUnit,categoryAttackBonusTable,defaultAttackTable)&lt;br /&gt;
    local bonusInfoTable = categoryAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
    if not bonusInfoTable then&lt;br /&gt;
        -- unit doesn&#039;t get a bonus&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
    -- keep track of bonuses already computed&lt;br /&gt;
    local bonusResultsTable = {}&lt;br /&gt;
    -- keep track of units that have already been &amp;quot;used&amp;quot; for a bonus&lt;br /&gt;
    local usedUnitTable = {[activeUnit.id]=true}&lt;br /&gt;
    for index,bonusCategory in pairs(bonusInfoTable) do&lt;br /&gt;
        bonusResultsTable[index]=computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    end&lt;br /&gt;
    -- compute the bonus&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local resultAttackBeforeRounding = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult/100&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack+bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+(bonusResult/100)&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    else&lt;br /&gt;
        error(&amp;quot;categoryAttackBonus: categoryAttackBonusTable.type is not a valid value.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    -- apply the bonus and round as appropriate&lt;br /&gt;
    local roundType = categoryAttackBonusTable.round&lt;br /&gt;
    if type(roundType) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;up&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.ceil(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;down&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    else&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two helper functions for computeCategoryBonus are only used once each in the code, so making them helper functions does not help us re-use code.  However, what it does do is to break down the function design process into smaller tasks, which are each more manageable to complete.  If you&#039;re trying to keep track of too many things in your program, try writing a few helper functions to handle individual tasks.  We&#039;ll look at the helper functions when we actually arrive at them in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-09-CategoryAtkBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If there is no entry in the categoryAttackBonusTable or the active unit&#039;s type, then the function returns without doing anything further.&lt;br /&gt;
&lt;br /&gt;
The bonusResultsTable keeps track of the total bonus from each category, so they can be added or multiplied together after all the category bonuses are applied.  The usedUnitsTable keeps track of units that are no longer eligible to contribute to a bonus (such as if they have already contributed), and we initialize it with the active unit, so that it doesn&#039;t provide a bonus to itself.&lt;br /&gt;
&lt;br /&gt;
The for loop computes the bonus for every category, and stores the value in the bonusResultsTable, for use later.Now, let us look at the helper functions.&lt;br /&gt;
&lt;br /&gt;
First up is findBestBonusInUnitStack&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-10-CategoryAtkBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This basically does what it says in the name.  For a bonusCategory, it finds the unit in the tile that provides the best bonus, and has not already provided a bonus elsewhere.  If there is no qualifying unit, false is returned.  If there is, that unit&#039;s bonus is returned, and the unit&#039;s id is entered into the usedUnitTable, so that unit can&#039;t provide another bonus for the active unit.  We&#039;ve searched for the best of something before, so there is little need to go over it again.&lt;br /&gt;
&lt;br /&gt;
Next is computeCategoryBonus&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-11-CategoryAtkBonus3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we&#039;re computing the bonus for the entire bonusCategory.  We need the bonus type in order to know what kind of math to do.  The math itself is not very interesting.  We also initialize the bonusDiscount, which keeps track of the fraction of the next unit&#039;s bonus that will actually be applied.&lt;br /&gt;
&lt;br /&gt;
Next, we enter a for loop that will run one time for each possible bonus that there can be in a bonus category.  If bonusCategory.maxBonusUnits is nil, then we set an arbitrary limit of 10000 units, which is very unlikely to happen in practice.&lt;br /&gt;
&lt;br /&gt;
At each iteration of the loop, the best available bonus in the stack is found.  If no unit was eligible to provide a bonus, then the current bonus is false, and the &amp;quot;break&amp;quot; command is issued.  Break immediately exits the current loop.  So, our program doesn&#039;t run 10000 loops if there is no maximum number of bonus units, it just breaks at an appropriate time.&lt;br /&gt;
&lt;br /&gt;
After the bonus is found, it is added to or multiplied with the bonus already found.  The bonus computed in this way will be the largest possible, since the bonus provided does not depend on the other units chosen (so we don&#039;t have a situation where &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; are both useless, but &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; chosen together are best).  Also, since the best bonus is chosen first, the smallest bonus discount applies to it, so the cost imposed by the discounting is smallest.&lt;br /&gt;
&lt;br /&gt;
Finally, we update the bonusDisount.  Here, I notice a problem in the code as written, since bonusCategory.nextBonusValue is allowed to be nil.  Replace&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
with &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*(bonusCategory.nextBonusValue or 1) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
so that if there is no nextBonusValue, a default of 1 is used, and the bonusDiscount stays at 1 (i.e. no discount is applied).&lt;br /&gt;
&lt;br /&gt;
We return to categoryAttackBonus to see&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-12-CategoryAtkBonus4.jpg]]&lt;br /&gt;
&lt;br /&gt;
From here, we combine the bonuses stored in bonusResultsTable, the exact way of doing so being dependant on the type of bonus involved.  The math itself isn&#039;t very interesting, and doesn&#039;t seem all that likely to come up in this exact form elsewhere.  If you need help with the mathematical details of some event you want to write, ask in the forums.  There&#039;s a good chance someone has the skills to help you solve your specific problem.&lt;br /&gt;
&lt;br /&gt;
For every type of bonus, the result is stored in resultAttackBeforeRounding, so that variable can be rounded up or down as specified by the rounding type.&lt;br /&gt;
&lt;br /&gt;
Here, I notice another error.  We should restrict the attack value for a unit to not exceed 98.  We can do that with a math.min(value, 98).&lt;br /&gt;
&lt;br /&gt;
Now, we need to test the various aspects of the attack bonus program, so we need an appropriate table&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addbonus&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=2,[unitAliases.chariot.id]=4,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=2,[unitAliases.musketeer.id]=4,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Also, comment out the old attack bonus line, and put in a new one&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus.categoryAttackBonus(unit,categoryAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
Already, we find a problem.  Although there were no syntax errors to fix, I forgot to reset unit attack values.  So, very quickly, the legions keep gathering extra attack values when they are activated (since the base attack is not reset to 4).  Since this is happening anyway, I&#039;ll test the 98 attack value maximum.  That appears to work, at least in the case of no specified rounding.&lt;br /&gt;
&lt;br /&gt;
Cut and paste the appropriate lines from the simpleAttackBonus to the categoryAttackBonus, and save.&lt;br /&gt;
&lt;br /&gt;
With that bug fixed, everything works as expected.&lt;br /&gt;
&lt;br /&gt;
Next, we change the categoryAttackBonusTable to &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addpercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=50,[unitAliases.chariot.id]=100,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=50,[unitAliases.musketeer.id]=100,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addpercent&amp;quot;.  These are the same, since adding we&#039;re adding percentages of the same base value of 4.  So a value of 2 is the same as adding 50% of 4.&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
The results are the same.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addfraction&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=.50,[unitAliases.chariot.id]=1.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.50,[unitAliases.musketeer.id]=1.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
We&#039;ll have to do some new calculations, now, since multiply and multiplyfraction give different results than the various adding formulations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiply&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=1.50,[unitAliases.chariot.id]=2.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=1.50,[unitAliases.musketeer.id]=2.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 12 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
 Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Finally, we use multiplyPercent, and check for the same results&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=150,[unitAliases.musketeer.id]=200,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 12 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
 Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Quickly, I find that if a bonus applies, that bonus makes the attack value of a legion 98.  I failed to multiply percents correctly in computeCategoryBonus.  The Line &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Is changed to &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+100)/100&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, Change archer bonus to 110 and musketeer bonus to 120 (so a unit will make a legion have 4.4 and 4.8 value before rounding), and test the rounding options.  You will find they all work.&lt;br /&gt;
&lt;br /&gt;
At the moment, we don&#039;t have a way to mix different types of bonuses.  As said earlier, we might want this so that some units can be better at giving bonuses to low attack units than to high attack units, while others give a percentage bonus to everything.  We could now write a bonus system that allows for multiple types of bonuses. However, the current bonus system allows for the bonus to change per unit.  This means that we can, for example, convert a +2 attack bonus to a plus 100% bonus for a unit with 2 attack, and a plus 50% bonus for a unit with 4 attack.  In the case of the multiplied bonuses, this will make the bonus more powerful if there is more than one.  That is, 2 attack, +2 twice is 6, but if +2 is changed to x2, then the multiplied bonus brings the attack up to 8.  However, this seems like it would be a relatively unlikely problem, and there are other things this code can&#039;t handle, so we&#039;ll let someone else make the code if they actually need it.&lt;br /&gt;
&lt;br /&gt;
So, what we&#039;ll do is write a function that will change all appropriate entries in the categoryAttackBonusTable to reflect a different value.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed(unitType,number,categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unit type to any unit to be equivalent&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, an issue with tables arises.  It is very likely that when someone defines their cateogryAttackBonusTable, they&#039;ll define it something like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.25,[unitAliases.musketeer.id]=.5}&lt;br /&gt;
 local bonusTableForInfantry = {rangeBonusCategory}&lt;br /&gt;
 local cABT = {type=&amp;quot;addfraction&amp;quot;}&lt;br /&gt;
 cABT[unitAliases.phalanx.id]=bonusTableForInfantry&lt;br /&gt;
 cABT[unitAliases.legion.id] = bonusTableForInfantry&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
However, this means that both &amp;lt;code&amp;gt; cABT[unitAliases.legion.id]  &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt; cABT[unitAliases.phalanx.id] &amp;lt;/code&amp;gt; actually refer to the same piece of memory, and changing cABT[unitAliases.legion.id][1][unitAliases.archer.id] will also change the value at cABT[unitAliases.phalanx.id][1][unitAliases.archer.id].  This is because of the way lua tables are designed.  This design can be useful, for example it allowed us to make changes to usedUnitsTable in the last function without having to copy the table, make changes to the copy of the table, and then replace the original table with that copy as a return value.  However, it also requires us to be careful when we make changes to entries in tables.  In this case, we&#039;ll simply copy the table and all its sub values into a new table.&lt;br /&gt;
&lt;br /&gt;
The code to do this is given by&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will explain this code in the next section, since it involves a programming technique which we haven&#039;t discussed before.&lt;br /&gt;
&lt;br /&gt;
For now, we analyze plusFixed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed({[unitType1.id]=fixedBonus,[unitType2.id]=fixedBonus},categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unitTypeI.id to a unit to be equivalent to&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power.  If the unit doesn&#039;t receive a bonus&lt;br /&gt;
 -- from the unitType, then it won&#039;t after applying plusFixed.&lt;br /&gt;
 -- The value of the existing bonus is ignored.&lt;br /&gt;
 &lt;br /&gt;
 local function plusFixed(fixedUnitBonusTable,categoryAttackBonusTable)&lt;br /&gt;
     local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
     for bonusReceivingUnitTypeID,bonusTable in pairs(categoryAttackBonusTable) do&lt;br /&gt;
         -- replace bonusTable with an equivalent table that is not referened&lt;br /&gt;
         -- anywhere else, so that changes to it can be made without impacting&lt;br /&gt;
         -- data elsewhere&lt;br /&gt;
         categoryAttackBonusTable[bonusReceivingUnitTypeID] = duplicateTable(bonusTable)&lt;br /&gt;
         -- make bonusTable refer to the &amp;quot;current&amp;quot; bonus table for the unit type&lt;br /&gt;
         bonusTable =categoryAttackBonusTable[bonusReceivingUnitTypeID] &lt;br /&gt;
         -- For each unit type in the fixedUnitBonusTable, check if any bonus category&lt;br /&gt;
         -- in the bonusTable corresponds to it.  If so, make the change&lt;br /&gt;
         for bonusGivingUnitTypeID,fixedBonusValue in pairs(fixedUnitBonusTable) do&lt;br /&gt;
             -- get the attack of the unit type &lt;br /&gt;
             local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
             -- in each bonus category, check if the giver&#039;s unit type id is there,&lt;br /&gt;
             -- if so, change to the correct attack&lt;br /&gt;
             for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
                 if bonusCategory[bonusGivingUnitTypeID] then&lt;br /&gt;
                 -- change the bonus appropriately&lt;br /&gt;
                     if bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue&lt;br /&gt;
                     elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*(fixedBonusValue+baseAttack)/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=(fixedBonusValue+baseAttack)/baseAttach&lt;br /&gt;
                     else&lt;br /&gt;
                         error(&amp;quot;pluxFixed: categoryAttackBonusTable.type does not have an acceptable value.&amp;quot;)&lt;br /&gt;
                     end&lt;br /&gt;
                 end&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-13-plusFixed1.jpg]]&lt;br /&gt;
&lt;br /&gt;
As before, we save the bonusType in lower case, since we&#039;ll be using it a lot later.  Next, we open a for loop, where the index is the id of the unit type receiving the bonus, and the value is the bonus table for that unit type.  Next, we duplicate the bonus table, so that we have a table we can change without impacting anything elsewhere, and we store the duplicated table in categoryAttackBonusTable in place of the original bonusTable for the current bonus receiving unit id.  Next, we assign this duplicated table to the variable bonusTable, so we can refer to it later in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-14-plusFixed2.jpg]]&lt;br /&gt;
&lt;br /&gt;
We now perform the following actions for each unitType.id and corresponding fixedBonusValue submitted in the fixedUnitBonusTable.&lt;br /&gt;
&lt;br /&gt;
First, get the attack of the bonus receiving unit, since we&#039;ll need that in order to customize the bonus.  Next, check each bonus category in the bonus table.  If the bonus category has the current unitTypeID as a key, then replace the existing value with a bonus equivalent to adding a fixed value to the receiving unit&#039;s attack.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all that must be done, so end all the loops.&lt;br /&gt;
&lt;br /&gt;
Now we test the function.&lt;br /&gt;
&lt;br /&gt;
Add unitAliases.phalanx = civ.getUnitType(3) to the appropriate file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 defaultAttackValueTable[unitAliases.phalanx.id]=1&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,&lt;br /&gt;
 								nextBonusValue=0.5,maxBonusUnits=1}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=125,[unitAliases.musketeer.id]=150,&lt;br /&gt;
 								nextBonusValue=0.75,maxBonusUnits=1}&lt;br /&gt;
 local standardBonus = {cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.phalanx.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 attackBonus.plusFixed({[unitAliases.chariot.id]=2,[unitAliases.musketeer.id]=2},&lt;br /&gt;
 						categoryAttackBonusTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The chariot and the musketeer individually should each add 2 to both a phalanx and a legion,&lt;br /&gt;
so the phalanx should have an attack of 3, and the legion should have an attack of 6, if one bonus&lt;br /&gt;
is applied.&lt;br /&gt;
&lt;br /&gt;
Since the bonus type is multiplypercent, together the phalanx would have an attack of 9, and the legion will also have an attack of 9.&lt;br /&gt;
&lt;br /&gt;
In testing, we quickly get this error&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
You should see this in lua console if this worked&lt;br /&gt;
...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: bad argument #1 to &#039;getUnitType&#039; (number expected, got string)&lt;br /&gt;
stack traceback:&lt;br /&gt;
	[C]: in function &#039;civ.getUnitType&#039;&lt;br /&gt;
	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At line 356, which is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This must mean that bonusReceivingUnitTypeID is not a number.  This is because we&#039;re looping over categoryAttackBonusTable, and that table has a couple of entries that are not integers (&amp;quot;type&amp;quot; and &amp;quot;round&amp;quot;).  Therefore, we have to insert code to deal with this eventuality.&lt;br /&gt;
&lt;br /&gt;
The simplest way is to put everything in the loop body into an if statement, so that it only runs when bonusGivingUnitTypeID is actually a number.  You should be able to do this without detailed instructions, so do so (hint: use type function).&lt;br /&gt;
&lt;br /&gt;
The next error is &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: bad argument #1 to &#039;pairs&#039; (table expected, got nil)&lt;br /&gt;
 stack traceback:&lt;br /&gt;
 	[C]: in function &#039;pairs&#039;&lt;br /&gt;
 	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
 	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 360 for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we have a nil value for bonusTable.  This turns out to be an error in duplicateTable.  When I duplicated the table, I forgot to return that table.  That is, both the if and else statement in that function need a return command, and I forgot to add &amp;lt;code&amp;gt; return duplicatedTable &amp;lt;/code&amp;gt; in the if portion.  Add this to the duplicate table function.&lt;br /&gt;
&lt;br /&gt;
After this, our predictions are true.  Testing the other types of bonus is left as an assignment.  You can find the completed code [https://forums.civfanatics.com/threads/totpp-attack-bonus-library.648093/ here].&lt;br /&gt;
&lt;br /&gt;
===Recursive Functions===&lt;br /&gt;
&lt;br /&gt;
Let us return to the duplicateTable function.  Recall that in the last section we added a line to it, so we&#039;ll restate it here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
 		return duplicatedTable&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-16-duplicateTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
The interesting thing about duplicateTable is that it invokes duplicateTable within its code.  When we copy the key-value pairs into the new table, we run duplicateTable on the value.  If the value is not a table, then we are in the else case, and the value is immediately returned to be inserted into the duplicated table.  If the value is a table, that table is duplicated before anything else is done.&lt;br /&gt;
&lt;br /&gt;
Let us look at a simple example of a recursive function, the factorial function N!.  In lesson 3, we discussed the factorial function in the context of loops.  Since N!=N*(N-1)*(N-2)*...*3*2*1, we can give another definition of N!:&lt;br /&gt;
 N!=1 if N = 1&lt;br /&gt;
 N!=N*(N-1)! if N &amp;gt; 1&lt;br /&gt;
Or, using the convention that 0!=1, we can state&lt;br /&gt;
 N!=1 if N = 0&lt;br /&gt;
 N!=N*(N-1)! if N &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
The case where N =1 or N=0 is called the &amp;quot;base case.&amp;quot;  If we keep substituting N! as N*(N-1)!, then we won&#039;t go on forever, because we will eventually reach a point where N=0, and N! can be substituted as 1 instead of N*(N-1)!.  As long as there is a base case, our program will eventually reach the base case(s), and begin &amp;quot;completing&amp;quot; evaluation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function factorial(N)&lt;br /&gt;
 if N&amp;gt;0 then&lt;br /&gt;
     return N*factorial(N-1)&lt;br /&gt;
 else&lt;br /&gt;
     return 1&lt;br /&gt;
 end&lt;br /&gt;
 end&lt;br /&gt;
 print(factorial(5))&lt;br /&gt;
 print(factorial(6))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run this in code in the lua demo website, or using the TOTPP lua interpreter.&lt;br /&gt;
&lt;br /&gt;
Returning to our duplicateTable function, the base case is any time a table value is not itself a table.  When that happens, the recursion &amp;quot;chain&amp;quot; ends, and everything can evaluated.&lt;br /&gt;
&lt;br /&gt;
Although is shouldn&#039;t be a problem in this particular case, it should be noted that it is possible for there to not be a &amp;quot;base case&amp;quot; in the recursion style: if table, recur, if not return a value.  Consider the following table system&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 a={}&lt;br /&gt;
 b={[1]=a}&lt;br /&gt;
 a[1]=b&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In this case, the code would never end.&lt;br /&gt;
&lt;br /&gt;
It is possible that even if the code could &amp;quot;theoretically&amp;quot; execute to completion, you run out of memory before that.  This is called a &amp;quot;stack overflow,&amp;quot; and if it occurs, you will have to think of an alternate way to solve your problem.  It will probably be best to ask for help in that case (and it might be useful to provide others with an example of a problem that results in a stack overflow), but you might also look into &amp;quot;tail recursion&amp;quot;, including http://www.lua.org/pil/6.3.html .&lt;br /&gt;
&lt;br /&gt;
===Conclusion===&lt;br /&gt;
&lt;br /&gt;
With the skills covered in this chapter, you now have the tools to split a large events file into multiple files that are more manageable.  You also have the basics for how to write re-useable modules for your events, so that your work can be used by others.  Remember that if someone else uses your implementation of a feature, they will spend much less time coding and testing it, allowing them to either finish the scenario sooner, or to introduce some other feature.  So, it might very well pay to spend at least a little effort making your code into a reusable module.  Perhaps you have an idea for a cool scenario mechanic, but don&#039;t have a scenario for it (or don&#039;t want to take the time to make it).  If that&#039;s the case, just make the module and test it in a &amp;quot;toy&amp;quot; scenario (like Classic Rome) so that it can be used more or less &amp;quot;off the shelf&amp;quot; when someone needs it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5207</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5207"/>
		<updated>2019-08-15T21:05:33Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is still under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [[here]].  (These are the same as I provided for the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the value &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [[flags.lua]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of it passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;br /&gt;
&lt;br /&gt;
=== Conclusion ===&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_by_Prof._Garfield&amp;diff=5206</id>
		<title>Get Started With Lua Events by Prof. Garfield</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_by_Prof._Garfield&amp;diff=5206"/>
		<updated>2019-08-15T21:04:32Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
&lt;br /&gt;
Back To [[:Category:Lua Resources|Lua Resources]]&lt;br /&gt;
&lt;br /&gt;
[https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/ Get Started With Lua Events] thread at the Civfanatics Forums.&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 1: &amp;quot;Hello World&amp;quot;|Lesson 1: &amp;quot;Hello World&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 2: Giving Instructions to Your Computer|Lesson 2: Giving Instructions to Your Computer]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 3: Tables, Loops, Logic, and Debugging|Lesson 3: Tables, Loops, Logic, and Debugging]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 4: Examples and More Examples| Lesson 4: Examples and More Examples]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 5: Even More Examples| Lesson 5: Even More Examples]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 6: Splitting Code into Multiple Files| Lesson 6: Splitting Code into Multiple Files]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 7: Saving Data in the State Table| Lesson 7: Saving Data in the State Table]]&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5205</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5205"/>
		<updated>2019-08-15T20:25:03Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Just Once */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is still under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [[here]].  (These are the same as I provided for the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the value &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;/code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [[flags.lua]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of it passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg&amp;diff=5204</id>
		<title>File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg&amp;diff=5204"/>
		<updated>2019-08-15T20:17:07Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg&amp;diff=5203</id>
		<title>File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg&amp;diff=5203"/>
		<updated>2019-08-15T20:16:53Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg&amp;diff=5202</id>
		<title>File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg&amp;diff=5202"/>
		<updated>2019-08-15T20:16:43Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-13-FlagTest3.jpg&amp;diff=5201</id>
		<title>File:GetStartedWithLuaLesson7-13-FlagTest3.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-13-FlagTest3.jpg&amp;diff=5201"/>
		<updated>2019-08-15T20:16:32Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-12-FlagTest2.jpg&amp;diff=5200</id>
		<title>File:GetStartedWithLuaLesson7-12-FlagTest2.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-12-FlagTest2.jpg&amp;diff=5200"/>
		<updated>2019-08-15T20:16:21Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-11-FlagTest1.jpg&amp;diff=5199</id>
		<title>File:GetStartedWithLuaLesson7-11-FlagTest1.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-11-FlagTest1.jpg&amp;diff=5199"/>
		<updated>2019-08-15T20:16:10Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-10-Flags5.jpg&amp;diff=5198</id>
		<title>File:GetStartedWithLuaLesson7-10-Flags5.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-10-Flags5.jpg&amp;diff=5198"/>
		<updated>2019-08-15T20:15:55Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-09-Flags4.jpg&amp;diff=5197</id>
		<title>File:GetStartedWithLuaLesson7-09-Flags4.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-09-Flags4.jpg&amp;diff=5197"/>
		<updated>2019-08-15T20:15:42Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-08-Flags3.jpg&amp;diff=5196</id>
		<title>File:GetStartedWithLuaLesson7-08-Flags3.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-08-Flags3.jpg&amp;diff=5196"/>
		<updated>2019-08-15T20:15:28Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-07-Flags2.jpg&amp;diff=5195</id>
		<title>File:GetStartedWithLuaLesson7-07-Flags2.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-07-Flags2.jpg&amp;diff=5195"/>
		<updated>2019-08-15T20:15:18Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-06-Flags1.jpg&amp;diff=5194</id>
		<title>File:GetStartedWithLuaLesson7-06-Flags1.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-06-Flags1.jpg&amp;diff=5194"/>
		<updated>2019-08-15T20:15:06Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-05-JustOnce.jpg&amp;diff=5193</id>
		<title>File:GetStartedWithLuaLesson7-05-JustOnce.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-05-JustOnce.jpg&amp;diff=5193"/>
		<updated>2019-08-15T20:14:53Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg&amp;diff=5192</id>
		<title>File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg&amp;diff=5192"/>
		<updated>2019-08-15T20:14:40Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg&amp;diff=5191</id>
		<title>File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg&amp;diff=5191"/>
		<updated>2019-08-15T20:13:23Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg&amp;diff=5190</id>
		<title>File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg&amp;diff=5190"/>
		<updated>2019-08-15T20:12:01Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg&amp;diff=5189</id>
		<title>File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg&amp;diff=5189"/>
		<updated>2019-08-15T20:11:18Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5188</id>
		<title>Get Started With Lua Events Lesson 7: Saving Data in the State Table</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_7:_Saving_Data_in_the_State_Table&amp;diff=5188"/>
		<updated>2019-08-15T20:10:15Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: Put in much of lesson&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This lesson is still under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Thus far in these lessons we have used Lua to alter the state of the active civilization game.  That is, we can create or delete units via events, grant or remove technologies, make adjustments to cities and so forth.  However, what we have not done is to keep a record of previous events in order to change how events execute.  In this respect, the old macro events system can still do things that we can&#039;t, by using functionality such as flags and the justonce modifier.  This lesson will remedy the deficiency.&lt;br /&gt;
&lt;br /&gt;
You can get the events for the start of lesson 7 [[here]].  (These are the same as I provided for the end of lesson 6.)&lt;br /&gt;
&lt;br /&gt;
===The &#039;state&#039; Table===&lt;br /&gt;
&lt;br /&gt;
The Lua Events system allows us to store extra information in a saved game and retrieve it later.  The information that we intend to store and retrieve is kept in a table, which is, by convention, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, and usually referred to as the &amp;quot;state table.&amp;quot;  The state table got its name from an example events.lua file provided by The Nameless One, but you can change the name if you really want to.  It is probably best to follow convention, however, especially if you are using code written by others.&lt;br /&gt;
&lt;br /&gt;
The code to save the state table information to a file is given by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onSave(function () return civlua.serialize(state) end) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civlua.serialize(state)&amp;lt;/code&amp;gt; turns the state table into a string, and the event trigger &amp;lt;code&amp;gt;civ.scen.onSave&amp;lt;/code&amp;gt; appends that string to the end of the saved game file.  To get that information back, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.scen.onLoad(function (buffer) state = civlua.unserialize(buffer) end)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-01-SaveAndLoad.jpg]]&lt;br /&gt;
&lt;br /&gt;
is used to turn the &amp;quot;buffer&amp;quot; back into a table, named &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;, when a game is loaded.&lt;br /&gt;
&lt;br /&gt;
===Counting Unit Kills===&lt;br /&gt;
&lt;br /&gt;
In the old macro system, counting things is rather laborious.  The following is macro code from an American Civil War scenario that requires 5 Confederate CSA Infantry units to be killed in order to issue the Emancipation Proclamation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=12 ; Activates Antietam Unit KIA Counter&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 LINCOLN REQUIRES MILTIARY SUCCESS ON THE BATTLEFIELD TO AVERT EUROPEAN INTERVENTION!&lt;br /&gt;
 ^&lt;br /&gt;
 As the Commander-in-chief, you need to demonstrate to the European powers that you are&lt;br /&gt;
 fighting for more then the preservation of the Union but for a higher moral cause, i.e. the &lt;br /&gt;
 abolition of slavery on the continent through the Emancipation Proclamation.&lt;br /&gt;
 ^&lt;br /&gt;
 But you cannot emit the Proclamation without gaining a victory on the battlefield and &lt;br /&gt;
 thereby demonstrating that your ability to emancipate the slaves is backed by more than &lt;br /&gt;
 words...&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 TURN&lt;br /&gt;
 turn=12&lt;br /&gt;
 @THEN&lt;br /&gt;
 TEXT&lt;br /&gt;
 ... As such you have till the end of September 1862 to defeat 5 CSA Infantry units. Failure to &lt;br /&gt;
 do so will prevent you from emitting the Proclamation in a timely manner and bring France and &lt;br /&gt;
 England on the side of the Confederacy. &lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=12 ; &lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=13 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 1st CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=13 ; 1st CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=14 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 2nd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=14 ; 2nd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=15 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 3rd CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=15 ; 3rd CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=16 ; &lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 4th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 UNITKILLED&lt;br /&gt;
 unit=CSA Infantry&lt;br /&gt;
 attacker=Union&lt;br /&gt;
 defender=Confederates&lt;br /&gt;
 @AND&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=16 ; 4th CSA Infantry Killed&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 Flag&lt;br /&gt;
 Continuous&lt;br /&gt;
 Who=Union&lt;br /&gt;
 State=On&lt;br /&gt;
 Flag=17 ; Emancipation Proclamation Given&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 5th CSA Infantry killed!&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
 &lt;br /&gt;
 @IF&lt;br /&gt;
 CheckFlag&lt;br /&gt;
 Who=Union&lt;br /&gt;
 Flag=17 ; Union kills 5th CSA Infantry starting January 1862&lt;br /&gt;
 State=On&lt;br /&gt;
 @THEN&lt;br /&gt;
 GIVETECHNOLOGY&lt;br /&gt;
 technology=82&lt;br /&gt;
 receiver=Union&lt;br /&gt;
 JUSTONCE&lt;br /&gt;
 TEXT&lt;br /&gt;
 EMANCIPATION PROCLAMATION ISSUED!&lt;br /&gt;
 ^&lt;br /&gt;
 President Abraham Lincoln issues the Emancipation Proclamation, which declares the &lt;br /&gt;
 freedom of all slaves in any state of the Confederate States of America.&lt;br /&gt;
 ENDTEXT&lt;br /&gt;
 @ENDIF&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Lua, we can do much better.  Let us write an event that requires the Romans to kill some Celtic chariots, will display a message with the current tally when one is killed, and will display a message when an adequate number are killed, after which no more messages will be displayed.&lt;br /&gt;
&lt;br /&gt;
A state table has already been in our events.lua file since the beginning of these lessons, along with a justOnce function (which we&#039;ll discuss later).&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-02-StateJustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
We&#039;ll store the count of Celtic chariots killed in the value &amp;quot;celticChariotsKilledByRomans&amp;quot;.  We should initialize this value to 0 by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.celticChariotsKilledByRomans = state.celticChariotsKilledByRomans or 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that if there is no value associated with the key &amp;quot;celticChariotsKilledByRomans&amp;quot; then the key is created and the value set to 0.  If there already is a value, then that value is preserved.&lt;br /&gt;
&lt;br /&gt;
We need to make this initialization in 2 places.  The first is in the main body of our events.lua script, which is to say not in any particular function or table in the script.  Just after the state table is created is a good idea.&lt;br /&gt;
&lt;br /&gt;
The second place is in the function run by &amp;lt;code&amp;gt;civ.scen.onLoad&amp;lt;/code&amp;gt;, after the state table is created from the buffer.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-03-initializeChariotCounter.jpg]]&lt;br /&gt;
&lt;br /&gt;
It is important to make the initialization at both places.  If the game has never been saved (or not saved with the state table), then the only way to have a state table is to initialize it in the main body of the events.lua.  If, however, the game has been saved, onLoad (which will run after the code in events.lua is run) will replace the state table created by events.lua, and so render invalid any initializations done in the body of the events.  This means that if you change the state initialization after having saved the game (such as if you add a new state entry during construction of your scenario), that entry will be erased when the state table is unserialized from the data stored in the saved game, so you will have to re-initialize it at least once.  Just make the initialization in both places, and you won&#039;t have to worry about the meaning of this paragraph.&lt;br /&gt;
&lt;br /&gt;
Let us make a parameter &amp;quot;chariotsToKill&amp;quot; and set it to 5.  That means, we&#039;ll do something after the fifth chariot is killed.&lt;br /&gt;
&lt;br /&gt;
In doWhenUnitKilled, when a Celtic chariot is killed by a Roman unit, we&#039;ll show a message with the number of chariots killed, and a different message when the threshold is reached.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doWhenUnitKilled(loser,winner)&lt;br /&gt;
     --[[loser.owner.money = math.max(loser.owner.money -campaignCost,0)&lt;br /&gt;
     winner.owner.money = math.max(winner.owner.money-campaignCost,0)]]&lt;br /&gt;
 	if loser.type == unitAliases.chariot and loser.owner == tribeAliases.celts &lt;br /&gt;
 		and winner.owner == tribeAliases.romans &lt;br /&gt;
 		and state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 		state.celticChariotsKilledByRomans = 1 + state.celticChariotsKilledByRomans&lt;br /&gt;
 		if state.celticChariotsKilledByRomans &amp;lt; parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(state.celticChariotsKilledByRomans)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.&amp;quot;)&lt;br /&gt;
 		elseif state.celticChariotsKilledByRomans == parameters.chariotsToKill then&lt;br /&gt;
 			civ.ui.text(&amp;quot;The &amp;quot;..tribeAliases.romans.name..&amp;quot; have now defeated &amp;quot;..&lt;br /&gt;
 				tostring(parameters.chariotsToKill)..&amp;quot; &amp;quot;..tribeAliases.celts.adjective&lt;br /&gt;
 				..&amp;quot; &amp;quot;..unitAliases.chariot.name..&amp;quot;s.  Something good happens.&amp;quot;)&lt;br /&gt;
 		end&lt;br /&gt;
 	end&lt;br /&gt;
 -- more code&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-04-ChariotCounterCode.jpg]]&lt;br /&gt;
&lt;br /&gt;
There isn&#039;t much to say about this code.  The &amp;quot;outer&amp;quot; if statement checks if the unit that was killed was a chariot, if the unit was owned by the Celts, if the winning unit was owned by the Romans, and if the number of chariots killed is less than 5 (or whatever the parameter is set to).&lt;br /&gt;
&lt;br /&gt;
If so, then we add 1 to the total of chariots killed.  If the total is still less than 5, we display a message with the current number of chariots killed.  If the last chariot killed brought the total to 5, a different message is displayed.  We could get fancier and have a separate message for the first chariot killed, or whatever.&lt;br /&gt;
&lt;br /&gt;
Note that by using the name and adjective of the tribes and unit types, we can make changes to the names of things without having to go back to our events and rewrite all the text.&lt;br /&gt;
&lt;br /&gt;
Test this code, and make sure it works, even after saving and loading.&lt;br /&gt;
&lt;br /&gt;
===Just Once===&lt;br /&gt;
&lt;br /&gt;
Now let us take a look at &amp;lt;code&amp;gt;justOnce(key,f)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fundamentally, &amp;lt;code&amp;gt;justOnce&amp;lt;/code&amp;gt; works by checking if &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table.  If it is not, then the function &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is executed (with no arguments), and &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is added to the state table with the value true.  If &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is already in the state table, then &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; is not executed.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to choose your keys so that they don&#039;t conflict with any other key in the state table (either for other justOnce instances or for other things in the state table, such as counter values), unless you specifically want them to.  For example, you might have event A and event B, and you want only one of them to happen, and to happen only once.  By giving them the same key for justOnce, you will ensure that only one of them happens.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at how justOnce is implemented.  In the civlua module, we have this code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Wraps getting and setting of key `n` in table `t`.&lt;br /&gt;
 local function property(t, n)&lt;br /&gt;
   return {get = function () return t[n] end,&lt;br /&gt;
           set = function (v) t[n] = v end}&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- When property `guard` is false, runs `f` and sets `guard` to true, otherwise does nothing. &lt;br /&gt;
 local function justOnce(guard, f)&lt;br /&gt;
   if not guard.get() then&lt;br /&gt;
     f()&lt;br /&gt;
     guard.set(true)&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in events.lua we have:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
local justOnce = function (key, f) civlua.justOnce(civlua.property(state, key), f)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-05-JustOnce.jpg]]&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.property(t,n)&amp;lt;/code&amp;gt; returns two functions, one that gets the value of &amp;lt;code&amp;gt;t[n]&amp;lt;/code&amp;gt; and the other that sets &amp;lt;code&amp;gt;t[n]=v&amp;lt;/code&amp;gt; for a value v given as an argument to the function.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;civlua.justOnce(guard,f)&amp;lt;code&amp;gt; takes a table {get=function,set=function(v)} and a function f.  If guard.get is nil or false, then the function f is executed and guard.set(true) is run.  Basically, the property function returns an appropriate table for civlua.justOnce to use as the guard entry.&lt;br /&gt;
&lt;br /&gt;
Finally, the justOnce function defined in events.lua &amp;quot;wraps&amp;quot; civlua.justOnce.  At every instance of justOnce, we need to specify the key and function f, but we always want to use the same table, the state table.  So, civlua.property(state,key) returns an appropriate guard value for civlua.justOnce every time, and then civlua.justOnce can be run with the correct guard and function.&lt;br /&gt;
&lt;br /&gt;
I will not provide an example of the usage of justOnce.  There should be enough information here for you to figure out how to use it, and you won&#039;t always find documentation with examples on how to use code.  If you have trouble, ask in the forums.&lt;br /&gt;
&lt;br /&gt;
===Flags and Accessing State from Modules===&lt;br /&gt;
&lt;br /&gt;
When we counted chariot kills, we saw how to define and use our own counter in the state table.  We could have made a &amp;quot;flag&amp;quot; by setting true or false values instead.  While we certainly can write our events by directly manipulating and accessing the state table to use flags and counters, it will be more convenient to define some functions to do this for us.  The scenario Over The Reich has the functions for flags and counters defined directly in the events.lua file, if you want to have a look.  For this lesson, however, we&#039;re going to define a flags  module that can be used from any file.&lt;br /&gt;
&lt;br /&gt;
This raises a question: how can a function in our flag module make changes to the state table, which is local to events.lua?  One solution is to make state global (by removing the &#039;local&#039; when it is defined).  That way, any module can access the state table by simply writing &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.  This has a couple downsides.  One is that this forces &amp;quot;state&amp;quot; to be the only name for the state table.  This is probably not a huge problem.  The other reason is that by giving every module direct access to the state table, you run into the problem that multiple modules might try to use the same key values without realizing it.  Of course, it might be useful to make state global if you&#039;ve split your code into multiple files anyway, setting aside modules written by others.&lt;br /&gt;
&lt;br /&gt;
So, what can we do?  The first thing to realize is that tables are fundamentally global.  Any part of the program can access a table as long as it has the &amp;quot;name&amp;quot; of the table.  If I write &amp;lt;code&amp;gt;local myTable={}&amp;lt;/code&amp;gt;, what is stored in the variable myTable is the &amp;quot;name&amp;quot; of the table, not all the key-value pairs of the table.  The variable myTable just tells the program where to find the table in memory.  If we can provide the value in myTable to another part of the program, then that part of the program can access myTable, even though it was defined locally.&lt;br /&gt;
&lt;br /&gt;
Of course, if we simply write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 globalState=state&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then all we have done is to allow the writer of events.lua to use a different name for the state table, without any other benefit.  However, we can do something else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local state= state or {}&lt;br /&gt;
 state.moduleOneState = state.moduleOneState or {}&lt;br /&gt;
 globalModuleOneState = state.moduleOneState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is create a new table in the state table at the key &amp;quot;moduleOneState&amp;quot;, unless something already exists at that key, and &#039;&#039;that&#039;&#039; table is provided to moduleOne via the global variable globalModuleOneState.  Then, to prevent conflicts, the scenario designer only has to make sure that the key &amp;quot;moduleOneState&amp;quot; is not used for any other purpose in the state table, and that globalModuleOneState is not used anywhere other than in ModuleOne.&lt;br /&gt;
&lt;br /&gt;
However, if we like, we can be even cleverer.  Consider this module, [[flags.lua]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
 &lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
 &lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
 &lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
 &lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
 &lt;br /&gt;
 return flag&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s first look at this part&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flagState = &amp;quot;flagState not linked&amp;quot;&lt;br /&gt;
 -- the module name for flags if moduleName is not specified&lt;br /&gt;
 -- moduleName allows the use of flags in other modules or libraries&lt;br /&gt;
 -- without worrying about name conflicts&lt;br /&gt;
 local defaultModuleName = &amp;quot;events.lua&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 -- a table of flag keys and their initialized values&lt;br /&gt;
 local initializeFlagList = {}&lt;br /&gt;
 &lt;br /&gt;
 -- table of flag functions to be returned with the module&lt;br /&gt;
 local flag = {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-06-Flags1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The variables flag is a table to hold the functions this module will provide, and is not very interesting.  Default module name is just a substitute for the string &amp;quot;events.lua&amp;quot;, so that it is only defined in one place (on the off chance that we might want to change it).&lt;br /&gt;
&lt;br /&gt;
The variables flagState and initializeFlagList are more interesting to us.  Although they are local variables within this module, the functions &#039;&#039;within&#039;&#039; flags.lua will treat them as global variables.  And these are not just constants that we&#039;ve defined in one place for consistency and ease of making changes; we&#039;re actually going to change them as the program runs.&lt;br /&gt;
&lt;br /&gt;
Recall the following code in lesson 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function buggy(input)&lt;br /&gt;
     j = 3&lt;br /&gt;
     print(input)&lt;br /&gt;
 end&lt;br /&gt;
 print(j)&lt;br /&gt;
 j = 7&lt;br /&gt;
 buggy(8)&lt;br /&gt;
 print(j) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code prints&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 nil&lt;br /&gt;
 8&lt;br /&gt;
 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since the variable j is changed to 3 whenever buggy is run.  We are going to do that on purpose to the variable flagState.&lt;br /&gt;
&lt;br /&gt;
When the module is first loaded, flagState is set to the string &amp;quot;flagState not linked&amp;quot;.  This is simply so that we have an easy error check.&lt;br /&gt;
&lt;br /&gt;
Now, consider the next function that was written&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function linkState(tableInStateTable)&lt;br /&gt;
     if type(tableInStateTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         flagState = tableInStateTable&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;linkState: linkState takes a table as an argument.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 flag.linkState = linkState&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-07-Flags2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This function takes the &amp;quot;name&amp;quot; of a table as input, and stores that name in the flagState variable, so that the table can be accessed by other functions in this module.  If the state table is passed to this function, or, preferably, a table stored as a value in the state table, then all the functions in this module can write to the state table, or at least the part of it passed as an argument to linkState.  Hence, we have achieved access to the state table without defining a global variable or by requiring that the state table be passed as an argument for every single function provided.&lt;br /&gt;
&lt;br /&gt;
Now, look at &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- Specifies a key for a flag, and that flag&#039;s initial value.&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function define(key,initialValue,moduleName)&lt;br /&gt;
     if type(initialValue) ~= &amp;quot;boolean&amp;quot; then&lt;br /&gt;
         error(&amp;quot;A flag in the flag module must have an initial value of true or false.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     if type(key) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error(&amp;quot;The flag module only allows strings for flag names.  Consider using the function tostring to make the conversion if necessary.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     -- the moduleName is prefixed to prevent conflicts in different modules&lt;br /&gt;
     -- define is only meant to be used in actual scenarios, not in library modules&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     -- if this key hasn&#039;t been used for a flag yet, then&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
         initializeFlagList[moduleName..key] = initialValue&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..tostring(key)..&amp;quot; has already been used for a flag.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.define = define&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-08-Flags3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Much of this function is error checking, to make sure that appropriate values are given.  The name of the flag (or the key) must be a string, and the initial value for the flag must be a boolean.&lt;br /&gt;
&lt;br /&gt;
The moduleName variable is optional.  If it is nil (which is the same as not being provided at all), then defaultModuleName is used.  Basically, this allows a someone writing a module to use the flag library without worrying about writing flag names that will conflict with the flag names written by some scenario designer.  Since the &amp;quot;true&amp;quot; key is the moduleName prefixed to the actual key, as long as moduleName is different in each module (and none are &amp;quot;events.lua&amp;quot;), there will be no conflict.  This way, the scenario designer doesn&#039;t have to worry about the name at all, and module writers just have to add an extra argument to their function calls, and everything will work well &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     if initializeFlagList[moduleName..key] == nil then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
checks to make sure that the flag key in question has not already been used elsewhere.  If it has, then its value will not be nil, and so an error can be given.  Note that since false is a valid initialization, we must specify whether the value is nil or not.&lt;br /&gt;
&lt;br /&gt;
If the key is not already in the table, it is added, with the initial value specified as the value.  Each use of define permanently changes initializeFlagList, by adding a value to the table.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- makes sure all flags are in the state table&lt;br /&gt;
 -- if a flag is not in the state table, it is inserted&lt;br /&gt;
 -- and initialized to the correct value&lt;br /&gt;
 local function initializeFlags()&lt;br /&gt;
     if type(flagState) == &amp;quot;string&amp;quot; and flagState == &amp;quot;flagState not linked&amp;quot; then&lt;br /&gt;
         error(&amp;quot;Use the function linkState before trying to initialize flags&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     for key,initialValue in pairs(initializeFlagList) do&lt;br /&gt;
         if flagState[key] == nil then&lt;br /&gt;
             flagState[key] = initialValue&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.initializeFlags = initializeFlags&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-09-Flags4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we first check that flagState has actually been replaced with a table.  Next, we go through all the key-value pairs in initializeFlagList.  If the key is not already in flagState, the key is added along with the initial value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- returns the current state (i.e. true or false) of the flag with the key&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function value(key,moduleName)&lt;br /&gt;
     moduleName = moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
     return flagState[moduleName..key]&lt;br /&gt;
 end&lt;br /&gt;
 flag.value = value&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setTrue(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = true&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setTrue = setTrue&lt;br /&gt;
 &lt;br /&gt;
 -- sets the flag&#039;s value to false&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function setFalse(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.setFalse = setFalse&lt;br /&gt;
 &lt;br /&gt;
 -- changes the flag&#039;s value from true to false or false to true&lt;br /&gt;
 -- optional parameter moduleName prevents name conflicts if&lt;br /&gt;
 -- flags are used in a module or library&lt;br /&gt;
 local function toggle(key,moduleName)&lt;br /&gt;
     moduleName=moduleName or defaultModuleName&lt;br /&gt;
     if flagState[moduleName..key] == nil then&lt;br /&gt;
         error(&amp;quot;The key &amp;quot;..key..&amp;quot; has not been initialized.  Check your flag definitions and &amp;quot;..&lt;br /&gt;
         &amp;quot;that the initializeFlags function has been executed.&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         flagState[moduleName..key] = not(flagState[moduleName..key])&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 flag.toggle = toggle&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-10-Flags5.jpg]]&lt;br /&gt;
&lt;br /&gt;
All of these functions simply provide access to the flagState table, adding the moduleName and producing an error if the flag doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
Now, let us do some tests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false)&lt;br /&gt;
 flag.define(&amp;quot;phalanxKilled&amp;quot;,false)&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in onLoad&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 state.flagState=state.flagState or {}&lt;br /&gt;
 flag.linkState(state.flagState)&lt;br /&gt;
 flag.initializeFlags()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-11-FlagTest1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add a warrior alias to classicRomeAliases, and the following code to doWhenUnitKilled&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if loser.type == unitAliases.warrior and not flag.value(&amp;quot;warriorKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Warrior Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 	if loser.type == unitAliases.phalanx and not flag.value(&amp;quot;phalanxKilled&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Phalanx Killed&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;phalanxKilled&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-12-FlagTest2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Test this by killing warriors and phalanxes (suicide attacks are effective here).  Only the first one killed should show a message.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a little addendum to the plunder module, to test flags in separate modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 flag = require(&amp;quot;flags&amp;quot;)&lt;br /&gt;
 flag.define(&amp;quot;warriorKilled&amp;quot;,false,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 local function firstLegion(loser)&lt;br /&gt;
 	if loser.type == unitAliases.legion and &lt;br /&gt;
 	not flag.value(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;) then&lt;br /&gt;
 		civ.ui.text(&amp;quot;First Legion Killed.&amp;quot;)&lt;br /&gt;
 		flag.setTrue(&amp;quot;warriorKilled&amp;quot;,&amp;quot;plunder.lua&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 return {&lt;br /&gt;
 firstLegion=firstLegion,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-13-FlagTest3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt; plunder.firstLegion(loser) to the doWhenUnitKilled function.&lt;br /&gt;
&lt;br /&gt;
It should have the same effect as the warrior and phalanx events, but for legions.  This is true even though we reused the &amp;quot;warriorKilled&amp;quot; string for a flag name.  Note that to use flags in a module, the flag module must also be set up in events.lua.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== After Production Events ===&lt;br /&gt;
&lt;br /&gt;
With flag functionality, we can now introduce a new event trigger, the &amp;quot;afterProduction&amp;quot; trigger.  This event trigger takes place after city production is complete for the turn, but before unit movement begins.  This is not a built in event trigger from the civ.scen library, however.  Instead, what we&#039;re going to do is use the civ.scen.onActivateUnit trigger to achieve it.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make this trigger by running our &amp;quot;doAfterProduction&amp;quot; function the first time a unit is activated for a player during a turn.  So that doAfterProduction is only run once per tribe per turn, we&#039;ll have flags that tell if the afterProduction event has been run.  If it has, the onActivateUnit code will ignore it.  Then, the flags are reset each turn.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll make a simple after production event&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function doAfterProduction(turn,tribe)&lt;br /&gt;
     civ.ui.text(tribe.name..&amp;quot; is the active tribe.&amp;quot;)&lt;br /&gt;
     if tribe.isHuman then&lt;br /&gt;
         civ.ui.text(tribe.leader.name..&amp;quot; is a human.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our flag definitions, we add the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 for i=0,7 do&lt;br /&gt;
 	flag.define(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;,true)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In our doOnActivation function, we add the lines&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if flag.value(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;) then&lt;br /&gt;
 		doAfterProduction(civ.getTurn(),civ.getCurrentTribe())&lt;br /&gt;
 		flag.setFalse(&amp;quot;afterProductionForTribe&amp;quot;..tostring(civ.getCurrentTribe().id)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in doThisOnTurn, we add the loop&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	for i=0,7 do&lt;br /&gt;
 		flag.setTrue(&amp;quot;afterProductionForTribe&amp;quot;..tostring(i)..&amp;quot;NotDone&amp;quot;)&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loop will reset the flags to true each turn, so that after production will run every turn.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-14-AfterProduction1.jpg]]&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-15-AfterProduction2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now we try it out.  One message should appear for each tribe every turn, but the other message should appear only for the human owned tribe.&lt;br /&gt;
&lt;br /&gt;
Note that the after production event won&#039;t run if a player has no active units after city production.  If this is a likely possibility for your scenario, you will have to account for that.  For example, during the after production event, you could create a unit for the next tribe in a remote corner of the map, and delete the guaranteeing unit for the current tribe.&lt;br /&gt;
&lt;br /&gt;
===Barracks and Veteran Status===&lt;br /&gt;
&lt;br /&gt;
Back in Lesson 4, I mentioned that we couldn&#039;t remove veteran status from newly created units (bestowed by a barracks) because the veteran status was not applied until &#039;&#039;after&#039;&#039; the on production event was completed.  However, now that we have the afterProduction functionality, we can make the change.&lt;br /&gt;
&lt;br /&gt;
What we&#039;ll do is keep a list of all (ground) units produced in cities with barracks, and remove veteran status for those units after production.  We won&#039;t bother checking if Sun Tzu is built or anything else.&lt;br /&gt;
&lt;br /&gt;
The code in doOnCityProduciton is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	if civ.isUnit(prod) then&lt;br /&gt;
 		if civ.hasImprovement(city,improvementAliases.barracks) and prod.type.domain == 0 then&lt;br /&gt;
 			state.vetStatusToRemove = state.vetStatusToRemove or {}&lt;br /&gt;
 			state.vetStatusToRemove[#state.vetStatusToRemove+1] = prod&lt;br /&gt;
 		end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code in doAfterProduction is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 	state.vetStatusToRemove=state.vetStatusToRemove or {}&lt;br /&gt;
 	for index,unit in pairs(state.vetStatusToRemove) do&lt;br /&gt;
 		unit.veteran = false&lt;br /&gt;
 		state.vetStatusToRemove[index] = nil&lt;br /&gt;
 	end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson7-16-NoBarracksVet.jpg]]&lt;br /&gt;
&lt;br /&gt;
Something to note is that before referring to state.vetStatusToRemove, we make sure that it exists, and create it if it doesn&#039;t.  This ensures that there will not be any errors trying to index a nil value.  We might want to make functions to add, check, and remove things from the state table (and, more particularly, any subtables in state) so that we don&#039;t have to write the checks that all the tables exist manually each time.&lt;br /&gt;
&lt;br /&gt;
Try this code.  It should work perfectly fine (except that it will remove the effect of Sun Tzu&#039;s from cities with barracks).  Be sure to test that units produced in previous turns that have subsequently gained veteran status keep it, and test that sea units produced in a city with a port facility and barracks still retain the port facility advantage.&lt;br /&gt;
&lt;br /&gt;
=== civ.scen.onLoad vs. civ.scen.onScenarioLoaded ===&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_by_Prof._Garfield&amp;diff=5187</id>
		<title>Get Started With Lua Events by Prof. Garfield</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_by_Prof._Garfield&amp;diff=5187"/>
		<updated>2019-08-15T20:08:00Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
&lt;br /&gt;
Back To [[:Category:Lua Resources|Lua Resources]]&lt;br /&gt;
&lt;br /&gt;
[https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/ Get Started With Lua Events] thread at the Civfanatics Forums.&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 1: &amp;quot;Hello World&amp;quot;|Lesson 1: &amp;quot;Hello World&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 2: Giving Instructions to Your Computer|Lesson 2: Giving Instructions to Your Computer]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 3: Tables, Loops, Logic, and Debugging|Lesson 3: Tables, Loops, Logic, and Debugging]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 4: Examples and More Examples| Lesson 4: Examples and More Examples]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 5: Even More Examples| Lesson 5: Even More Examples]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 6: Splitting Code into Multiple Files| Lesson 6: Splitting Code into Multiple Files]]&lt;br /&gt;
&lt;br /&gt;
[[Get Started With Lua Events Lesson 7: Saving Data in the State Table| Lesson 7: Saving Data in the State Table]]&lt;br /&gt;
&lt;br /&gt;
[[Testing Page]]  A page where I test functionality.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=The_scenario_library&amp;diff=5186</id>
		<title>The scenario library</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=The_scenario_library&amp;diff=5186"/>
		<updated>2019-08-15T20:05:08Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: Added onLoad and OnSave events&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back To [[TOTPP Functions]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onTurn|onTurn]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onTurn(function (turn) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onUnitKilled|onUnitKilled]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onUnitKilled(function (loser, winner) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onLoad|onLoad]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onLoad(function (buffer) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Buffer is a string attached to the end of a saved game file.  It can be unserialized back into a state table.&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onSave|onSave]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;civ.scen.onSave( function () --&amp;gt; string)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The string returned is attached to the end of the saved game file.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onScenarioLoaded|onScenarioLoaded]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onScenarioLoaded(function () -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onNegotiation|onNegotiation]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onNegotiation(function (talker, listener) -&amp;gt; boolean)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onSchism|onSchism]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onSchism(function (tribe) -&amp;gt; boolean)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onCityTaken|onCityTaken]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onCityTaken(function (city, defender) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onCityProduction|onCityProduction]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onCityProduction(function (city, prod) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onCentauriArrival|onCentauriArrival]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onCentauriArrival(function (tribe) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onCityDestroyed|onCityDestroyed]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onCityDestroyed(function (city) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onBribeUnit|onBribeUnit]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onBribeUnit(function (unit, previousOwner) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onGameEnds|onGameEnds]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onGameEnds(function (reason) -&amp;gt; boolean)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onKeyPress|onKeyPress]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onKeyPress(function (keyCode) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Registers a function to be called every time a key is pressed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onActivateUnit|onActivateUnit]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onActivateUnit(function (unit, source) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Registers a function to be called every time a unit is activated. The callback takes the unit activated as a parameter, and the source of unit activation. Source is `true` if activated by keyboard or mouse click, `false` if activated by the game itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onCityFounded|onCityFounded]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onCityFounded(function (city) -&amp;gt; void)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Registers a function to be called every time a city is founded. The callback takes the city as a parameter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onResolveCombat|onResolveCombat]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onResolveCombat(function (defaultResolutionFunction, defender, attacker) -&amp;gt; boolean)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Registers a function to be called during every combat turn. The first parameter of the callback is the default resolution function, as implemented by the game. It takes the attacker and defender as parameters. You can call this to produce a result for cases you don&#039;t need to handle yourself.&lt;br /&gt;
Return `true` to continue combat, `false` to stop.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[civ.scen.onCanBuild|onCanBuild]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;civ.scen.onCanBuild(function (defaultBuildFunction, city, item) -&amp;gt; boolean)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Registers a function to be called every time a check is done whether a city can build something or not. It is called for all unit types, improvements and wonders. The first parameter of the callback is the default build function, as implemented by the game. It takes the city and item as parameters. You can call this to produce a result for cases you don&#039;t need to handle yourself. `item` can be a unittype, improvement or wonder.&lt;br /&gt;
Return `true` if `city` is allowed to produce `item`, `false` if not.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5185</id>
		<title>Get Started With Lua Events Lesson 6: Splitting Code into Multiple Files</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5185"/>
		<updated>2019-07-26T16:19:51Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
In this lesson, we will take a look at how to split the code for a scenario&#039;s events into multiple files.  There are several reasons to consider doing this.&lt;br /&gt;
&lt;br /&gt;
The first reason is simply to organize your work.  If you have a series of complicated events, the events.lua file can become very large very quickly. Once your events.lua file has thousands of lines of code in it, it may not be very obvious where the best place is to put that next helper function, or where to implement the function that runs a complicated event.  Sometimes even finding the piece of code that has to be changed can be a bit of a hassle.  In Over the Reich, I sometimes search for the associated civ.scen line, and then search for the exact name of the function I need.  Occasionally, there may even be more searching to find what I actually have to change.  With multiple files, it becomes easier to find things.&lt;br /&gt;
&lt;br /&gt;
Another aspect of using multiple files is that you can make certain changes without worrying about breaking things elsewhere.  If myBigComplicatedFunction relies on aModestHelperFunction for a certain part of its functionality, and a change to myBigComplicatedFunction also requires a change to aModestHelperFunction, you have to make sure that nothing else in your code also uses aModestHelperFunction, or, if something else does depend on it, that aModestHelperFunction either still provides the original functionality, or that all other functions that use aModestHelperFunction are suitably modified.  If myBigComplicatedFunction is defined in its own lua module, then you don&#039;t have to worry about forgetting that aModestHelperFunction was used elsewhere, since it can&#039;t be accessed outside the module unless you specifically allow it to be.&lt;br /&gt;
&lt;br /&gt;
A second reason to split events code into multiple files is to facilitate collaboration.  If all of the events are in a single file, then only one person can make changes to the file at a time.  If one partner starts changing an event, but has to do something else before finishing, everyone waits on one person&#039;s delay.  However, if most aspects of the scenario are separated into individual files, everyone can work on his or her own piece of the puzzle without depriving others of the opportunity to work at that time.&lt;br /&gt;
&lt;br /&gt;
A third reason to split events into multiple modules is to facilitate reusing code.  If everything required to implement an event is in its own file (or files), it becomes much easier for other creators to use your functionality in their scenario.  Since everything they need is already in one place, they don&#039;t have to find every last helper function, or concern themselves with naming conflicts.&lt;br /&gt;
&lt;br /&gt;
===Two Simple Examples===&lt;br /&gt;
&lt;br /&gt;
Let us look at the top of the events.lua file.  You can get the version that I started lesson 6 with [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-01-DefaultRequire.jpg]]&lt;br /&gt;
&lt;br /&gt;
We get code from other files by using the command &amp;lt;code&amp;gt;require&amp;lt;/code&amp;gt; along with a string specifying the file name (except for the .lua extension).  At the moment, we can only get code stored in the lua folder in the Test of Time directory.  This is inconvenient if we&#039;re trying to distribute a scenario, since installing a scenario would require moving certain files to the lua directory, and those file names might conflict.  Instead, we need to tell the Lua interpreter to search in the same folder that the events.lua folder is in.&lt;br /&gt;
&lt;br /&gt;
To do this, we need the following code:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local eventsPath = string.gsub(debug.getinfo(1).source, &amp;quot;@&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 local scenarioFolderPath = string.gsub(eventsPath, &amp;quot;events.lua&amp;quot;, &amp;quot;?.lua&amp;quot;)&lt;br /&gt;
 if string.find(package.path, scenarioFolderPath, 1, true) == nil then&lt;br /&gt;
    package.path = package.path .. &amp;quot;;&amp;quot; .. scenarioFolderPath&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can probably cut and paste this code before the require lines in your events.lua file and not worry about how it works.  However, I&#039;ll provide a brief explanation for reference.&lt;br /&gt;
&lt;br /&gt;
The first line stores the location of the of the current file as a string in eventsPath.&lt;br /&gt;
&lt;br /&gt;
The second line replaces events.lua in the eventsPath with ?.lua, which will tell the Lua interpreter to look for .lua files in the current directory (that is to say, the directory with the events.lua file).  &lt;br /&gt;
&lt;br /&gt;
The if statement adds scenarioFolderPath to the places for the Lua interpreter to search for code, if that directory is not already in the search path.  Since the search path is kept active by the Lua interpreter, it will not be necessary to repeat these lines of code in every file that performs a require action as long as you are running the file as part of events.  If you are writing some other kind of code, you will need to substitute &amp;quot;events.lua&amp;quot; with the name of the file with the code you are running.  Note that for some reason, events.lua is always provided in lower case.  However, for use in other situations, debug.getinfo(1).source uses the correct case for event files. I have only briefly tested this, so you may have to do some testing yourself if this situation comes up (or ask for help in the forums).&lt;br /&gt;
&lt;br /&gt;
Now that we&#039;ve told Lua where to look for our extra code, we can begin moving code to other files.  Think of require as telling Lua to run the entire contents of another file as a function.  We can then assign a value to whatever that file returns, which will usually be a table.  A couple of examples will clarify.&lt;br /&gt;
&lt;br /&gt;
For our first example, we will move our scenario&#039;s parameters to a separate file, and access it via require.  This may not seem worthwhile in this example, but tables like this can get large in a hurry.  At the time of writing, Over the Reich has over 100 lines of parameters (&amp;quot;specialNumbers&amp;quot;), and parameters are something that a designer might like to play with while collaborators make other implementations.  Also, parameters will have to be referenced by other parts of the code, and a file that is required by events.lua cannot, in turn, require events.lua in order to get information.  That means that we&#039;ll have to keep our parameters in a separate file anyway.&lt;br /&gt;
&lt;br /&gt;
Cut the parameters table definition and paste it into a new file, classicRomeParameters.lua.  For the last line, write&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return parameters&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, Near the top of events.lua, where the existing require lines are, add the eventsPath code from above and also the line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local parameters = require(&amp;quot;classicRomeParameters&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
[[File:GetStartedWithLuaLesson6-02-RequireParameters.jpg]]&lt;br /&gt;
&lt;br /&gt;
Open the classicRome scenario and test out a couple of events to make sure everything is the same.&lt;br /&gt;
&lt;br /&gt;
We might find it convenient to put a few tables into the same file.  For this, we will simply return a table containing these tables, and give each table a name in the events.lua file.&lt;br /&gt;
&lt;br /&gt;
Create a file classicRomeAliases.lua and move all the &amp;quot;aliases&amp;quot; tables to that file.  Also move the getCityAt function.&lt;br /&gt;
&lt;br /&gt;
At the bottom of the file, put the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 unitAliases=unitAliases,&lt;br /&gt;
 tribeAliases=tribeAliases,&lt;br /&gt;
 tileAliases=tileAliases,&lt;br /&gt;
 cityAliases=cityAliases,&lt;br /&gt;
 textAliases=textAliases,&lt;br /&gt;
 terrainAliases=terrainAliases,&lt;br /&gt;
 improvementAliases=improvementAliases,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following lines to events.lua (in the require section)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local aliases = require(&amp;quot;classicRomeAliases&amp;quot;)&lt;br /&gt;
 local unitAliases,tribeAliases,tileAliases,cityAliases,textAliases,&lt;br /&gt;
 		terrainAliases,improvementAliases=aliases.unitAliases,aliases.tribeAliases,&lt;br /&gt;
 		aliases.tileAliases,aliases.cityAliases, aliases.textAliases,aliases.terrainAliases,&lt;br /&gt;
 		aliases.improvementAliases&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, our classicRomeAliases module is returning a table with our &amp;quot;alias&amp;quot; tables.  We then assign the entries in this returned table to local variables with the desired names.  Here, I use multiple variable assignment, which I don&#039;t believe I&#039;ve used before (even though Lua allows it), but these could just as simply have been assigned line by line.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-03-RequireAliases.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now, let us move the legion plundering code into its own file, which we&#039;ll call plunder.lua.  First, copy over the legionPlunder function, and paste it near the bottom of the new file.&lt;br /&gt;
&lt;br /&gt;
Now, let us go through the code of this function, and figure out what else we need in our plunder.lua module.&lt;br /&gt;
&lt;br /&gt;
The very first part of the function is a check against unitAliases.legion.  This means we need the unitAliases table, and so we copy the aliases require code to the top of plunder.lua.  We don&#039;t need the path information, since that will be added in events.lua.&lt;br /&gt;
&lt;br /&gt;
A few more lines down, we find that the function cityRadius is also used in legionPlunder.  Therefore, we move that over as well.  We also need the plunderValue function, so copy that over as well.&lt;br /&gt;
&lt;br /&gt;
Next, we check if cityRadius relies on anything, but it doesn&#039;t.&lt;br /&gt;
&lt;br /&gt;
Proceeding to plunderValue, we find that it relies on the parameters table, so require that as well.  The function plunderValue does not appear to depend on anything else, so we&#039;re done moving functionality.  If we missed something, the Lua interpreter will complain at some point anyway.&lt;br /&gt;
&lt;br /&gt;
Next, we require the plunder module in events.lua, with the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local plunder = require(&amp;quot;plunder&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, for each of the functions in plunder.lua, we check if it is used somewhere in events.lua.  We can do this by searching.  plunderValue isn&#039;t used anywhere, so we&#039;re done with that.  City radius is used.  At the bottom of plunder.lua, we begin our return table, and have&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 cityRadius=cityRadius,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, in events.lua, we replace the ocurance of cityRadius with plunder.cityRadius.  Alternatively, we could have put &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local cityRadius=plunder.cityRadius&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
after the line requiring plunder.&lt;br /&gt;
&lt;br /&gt;
Similarly, for legionPlunder, we add &amp;lt;code&amp;gt;legionPlunder=legionPlunder&amp;lt;/code&amp;gt; to the table that plunder.lua returns, and pre-append plunder. to legionPlunder in the one location where it occurs.&lt;br /&gt;
&lt;br /&gt;
Now, we test the legion plunder function and the press 4 generate archers function to make sure everything works.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-04-RequirePlunder.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Working With a Library===&lt;br /&gt;
&lt;br /&gt;
In programming terms, a &amp;quot;library&amp;quot; is a collection of code that can provide some specified functionality to a programmer without that programmer having to modify the code in the library.  Thus far, you have been using the &amp;quot;civ&amp;quot; library to interact with the game, and there has been no need modify it in order to use it in our own events.  (Unfortunately, in the case of the civ library, we don&#039;t actually know how to modify it.)  This is in contrast to much of the code we have written thus far.  For example, the code we wrote last lesson to make Selucid elephants attack Egypt is highly specific.  You couldn&#039;t just cut and paste that code, change the argument of a single function, and get your own goto event.  It is still a good example for how to write a goto event, but a user would still have to actually write the event.&lt;br /&gt;
&lt;br /&gt;
If you plan to write some functionality for your scenario that others might find useful, it is worth spending a little extra effort to see if you can write that functionality in a form that will allow others to use it with minimal effort.  If you can, then a little extra work on your part might save someone else the trouble of re-inventing the wheel, and allow them to complete their project sooner, or to work on some new feature for you to enjoy.  Unfortunately, the Lua scenarios that have been completed at the time of writing haven&#039;t been that good at creating re-usable code, at least in part since we were all getting used to Lua.  This will hopefully be improved in the future.&lt;br /&gt;
&lt;br /&gt;
For now, we&#039;re going to look at a library which is called the General Library (unless someone comes up with a better name) and which can be found [https://forums.civfanatics.com/threads/totpp-the-general-library.647583/ here].  The purpose of this module is to provide relatively simple functionality that probably shouldn&#039;t be implemented every time it is needed.  This is useful for our purposes, since we can look at relatively self contained and simple functions for our first examples.  We&#039;ll create a library for generating munitions later.&lt;br /&gt;
&lt;br /&gt;
This library would be used by invoking the line &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local gen = require(&amp;quot;generalLibrary&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to make these functions available to the console for testing purposes, you would simply omit the local, thereby making gen a global variable.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at a function provided by the General Library &amp;lt;code&amp;gt; gen.hasIrrigation(tile)--&amp;gt;boolean&amp;lt;/code&amp;gt;.  The very first line references the helper function &amp;lt;code&amp;gt; toTile(tile or table)--&amp;gt;tile&amp;lt;/code&amp;gt;, so let us include that code, and look at it first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 -- toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- gen.toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- If given a tile object, returns the tile&lt;br /&gt;
 -- If given coordinates for a tile, returns the tile&lt;br /&gt;
 -- Causes error otherwise&lt;br /&gt;
 -- Helper Function (provided to this library as toTile and gen.toTile)&lt;br /&gt;
 local function toTile(input)&lt;br /&gt;
     if civ.isTile(input) then&lt;br /&gt;
         return input&lt;br /&gt;
     elseif type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         local xVal = input[1] or input[&amp;quot;x&amp;quot;]&lt;br /&gt;
         local yVal = input[2] or input[&amp;quot;y&amp;quot;]&lt;br /&gt;
         local zVal = input[3] or input[&amp;quot;z&amp;quot;] or 0&lt;br /&gt;
         if type(xVal)==&amp;quot;number&amp;quot; and type(yVal)==&amp;quot;number&amp;quot; and type(zVal)==&amp;quot;number&amp;quot; then&lt;br /&gt;
             if civ.getTile(xVal,yVal,zVal) then&lt;br /&gt;
                 return civ.getTile(xVal,yVal,zVal)&lt;br /&gt;
             else&lt;br /&gt;
                 error(&amp;quot;Table with values {&amp;quot;..tostring(xVal)..&amp;quot;,&amp;quot;..tostring(yVal)..&lt;br /&gt;
                         &amp;quot;,&amp;quot;..tostring(zVal)..&amp;quot;} does not correspond to a valid tile.&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
         else&lt;br /&gt;
             error(&amp;quot;Table did not correspond to tile coordinates&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;Did not receive a tile object or table of coordinates.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 gen.toTile = toTile&lt;br /&gt;
 &lt;br /&gt;
 -- gen.hasIrrigation(tile)--&amp;gt;boolean&lt;br /&gt;
 -- returns true if tile has irrigation but no farm&lt;br /&gt;
 -- returns false otherwise&lt;br /&gt;
 function gen.hasIrrigation(tile)&lt;br /&gt;
     tile = toTile(tile)&lt;br /&gt;
     local improvements = tile.improvements&lt;br /&gt;
     -- irrigation, but no mining, so not farmland&lt;br /&gt;
     if improvements &amp;amp; 0x04 == 0x04 and improvements &amp;amp; 0x08 == 0 then&lt;br /&gt;
         return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-05-HasIrrigation.jpg]]&lt;br /&gt;
&lt;br /&gt;
Let us begin by looking at the function &amp;lt;code&amp;gt;toTile&amp;lt;/code&amp;gt;.  The purpose of this function is to allow other functions to accept tile coordinates in a table instead of an actual tile object.  The function tries to be reasonably permissive in the coordinates it will accept, allowing both integer indices and lowercase string indices, and by assuming that a missing z value corresponds to map 0.  The function also tries to give reasonably helpful errors.&lt;br /&gt;
&lt;br /&gt;
This brings up something that should be considered when making reusable code: what to do if you don&#039;t get values you were expecting.  One option is to throw an error and bring up the Lua console.  This is good for scenario creators, so they know something is wrong, but not so great for end users because the error stops the rest of the event from happening, should the mistake slip through playtesting.&lt;br /&gt;
&lt;br /&gt;
The other option is for the code to fail silently, and try to do what it can.  This is the way the old Test of Time macro system often fails.  If Civ II doesn&#039;t &amp;quot;understand&amp;quot; the event, it just doesn&#039;t happen, and doesn&#039;t bother the player with the error.  This means that the scenario will still mostly work, but it is harder to catch issues during playtesting.  Sometimes, this means doing something &amp;quot;sensible&amp;quot; if the input isn&#039;t of the expected type, and might make the code easier to write, since you don&#039;t have to handle inputs differently.&lt;br /&gt;
&lt;br /&gt;
A third option is to write your code such that both things can be done.  At the top of your code, you put in a variable named &amp;quot;debugMode&amp;quot; or something, and make all the functions throw errors when true, and fail silently when false.  Then you playtest with debugMode set to true, and release with debug mode set to false.  However, this means extra work in writing your code and you also have to test everything with debug mode off.&lt;br /&gt;
&lt;br /&gt;
For toTile, I went with the fail with error option, since that will allow every function that uses toTile to assume it is receiving proper data.  It also seems unlikely that people will be regularly trying to check tiles that don&#039;t exist or have tables with tiles and units and improvement objects all in one.  And if they do, &amp;quot;guarding&amp;quot; is fairly straightforward anyway (as we&#039;ve done in previous lessons).&lt;br /&gt;
&lt;br /&gt;
Although toTile is mainly meant to be a helper function for the General Library, it is also put into the gen table to be made available to end users, since it offers useful functionality.  Hence, &amp;lt;code&amp;gt; gen.toTile=toTile&amp;lt;/code&amp;gt;.  Note that we could have given toTile a different name in the gen table that this module will return, such as gen.tableToTile=toTile.  In fact, we could refer to the same function with multiple keys in the gen table, if we want to.&lt;br /&gt;
&lt;br /&gt;
Next, we will look at gen.hasIrrigation.&lt;br /&gt;
&lt;br /&gt;
The first thing to notice is that local is not being used to define this function.  That is because we&#039;re putting the function for gen.hasIrrigation directly into the gen table that this module will return.  We could define hasIrrigation as a local variable and then copy it into the gen table.  However, there is a decent chance that the General Library will have more than 200 functions by the time everything is complete, since it is meant to provide a lot of building block functionality and keep it in one place, and we will run into trouble if we assign 200 local variables in a single function (which a required lua file acts as).&lt;br /&gt;
&lt;br /&gt;
Perhaps the most striking thing is that we begin by changing the value of tile, the argument of the function.  It looks like we&#039;re making a global variable named tile, but we&#039;re not.  When you specify the names of the arguments for a function (in this case tile), you create local variables for that function, which can be given new values just as if you had explicitly used the local keyword.&lt;br /&gt;
&lt;br /&gt;
Beyond that, we extract the integer representing the tile improvements into a local variable (which upon later reflection isn&#039;t really necessary), and check that the irrigation bit is set to 1 and the mining bit is set to 0.  Refer to lesson 5 for why this works.  In fact, we could have simply returned the value of the if statement, rather than specifying return true and return false, although it is very slightly clearer what is going on in the expanded version of the code.&lt;br /&gt;
&lt;br /&gt;
Now, let us write a function to place irrigation on a square.  It seems pretty clear that we should do nothing if the tile has a city, but we also have to decide what to do if there is mining or farmland on the tile, since those interfere with placing irrigation.  We&#039;ll just remove them, on the basis that if we&#039;re trying to &amp;quot;place irrigation,&amp;quot; then we want irrigation to be there when we are finished.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function gen.placeIrrigation(tile)&lt;br /&gt;
    tile = toTile(tile)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These lines open the function and convert a table of coordinates to a tile if necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 if tile.city then&lt;br /&gt;
    return&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the tile has a city, return so nothing else is done in the function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     -- Set irrigation bit to 1&lt;br /&gt;
     tile.improvements = tile.improvements | 0x04&lt;br /&gt;
     -- Set mining bit to 0&lt;br /&gt;
     tile.improvements = tile.improvements &amp;amp; ~0x08&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the irrigation bit to 1 and the mining bit to 0.&lt;br /&gt;
&lt;br /&gt;
The functions in this library don&#039;t have to be complex, and in fact, most probably shouldn&#039;t be.  They just have to make life easier for the end user.  If you reach this lesson before the General Library is considered &amp;quot;complete,&amp;quot; your assignment now is to submit some work for it.  If you don&#039;t feel comfortable doing bitwise operations, you can test the work of others or submit functions that simplify other tasks.  However, there are also some helper functions in the library to facilitate changing bits, so you might also consider working on the unit type flags functions.  Remember, if you want to make functions available to the console for testing purposes, they must be global variables.&lt;br /&gt;
&lt;br /&gt;
=== The Threshold Table and First Look at Metatables===&lt;br /&gt;
&lt;br /&gt;
Consider a scenario design situation that occurred in Over the Reich: a bomber is generating some bombs via a key press, and the number of bombs it should generate is dependant on its current remaining hitpoints.  The more hitpoints the bomber has, the more bombs it should generate.  What we want is to specify that if a bomber has between x and y hitpoints, it should produce 2 bombs.  That is, for a given type of bomber, we want to have, for example,&lt;br /&gt;
&lt;br /&gt;
hp &amp;gt;= 16 --&amp;gt; 4 bombs&lt;br /&gt;
16 &amp;gt; hp &amp;gt;= 12 --&amp;gt; 3 bombs&lt;br /&gt;
12 &amp;gt; hp &amp;gt;= 9 --&amp;gt; 2 bombs&lt;br /&gt;
9 &amp;gt; hp &amp;gt;= 4 --&amp;gt; 1 bomb&lt;br /&gt;
4 &amp;gt; hp &amp;gt;= 0 --&amp;gt; 0 bombs&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Lua tables do not naturally encode this kind of association by default.  However, Lua does have a feature called metatables, which allows us to change the behaviour of tables.  (This will be a much better way to make the specification than I ended up writing in Over the Reich.)&lt;br /&gt;
&lt;br /&gt;
A metatable is a table that we can &amp;quot;attach&amp;quot; to another table, and then the metatable changes the behaviour of that table.  We&#039;ll only look at metatables briefly here, but more information can be found [https://www.tutorialspoint.com/lua/lua_metatables.htm here].&lt;br /&gt;
&lt;br /&gt;
What we want is a data structure that can accept numerical &amp;quot;key values&amp;quot; that are between the key values explicitly specified, and return the appropriate value for those keys.  We will call this data structure a threshold table, since we are specifying threshold values as keys.  We can do this by assigning the following metatable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local mt = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we run &amp;lt;code&amp;gt; setmetatable(myTable,mt)&amp;lt;/code&amp;gt;, then whenever we ask for an index from myTable and that index doesn&#039;t currently exist in myTable, the function assigned to __index will run.  Now let us examine the function.&lt;br /&gt;
&lt;br /&gt;
If the type of the key is not a number, then we return whatever the table value is for that key.  We use the function rawget, because the standard &amp;lt;code&amp;gt;thresholdTable[key]&amp;lt;/code&amp;gt; will invoke this function again if the key doesn&#039;t exist, and so never return an answer (when we want it to return nil).&lt;br /&gt;
&lt;br /&gt;
If the key type is a number, then we look for the largest numerical index that is also less than or equal to the key value.  We return a default value of false if the key submitted is smaller than all numerical values.  False is chosen over nil, so that a maximum value can be set by setting the value of a numerical index to false.  Using the key [-math.huge] allows a return value to be set for all numbers (since all numbers are greater than -math.huge).&lt;br /&gt;
&lt;br /&gt;
Since we don&#039;t want scenario creators to have to re-create threshold tables every time they need them, we&#039;ll add this functionality to the General Library&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local thresholdTableMetatable = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 -- gen.makeThresholdTable(table or nil)--&amp;gt;thresholdTable&lt;br /&gt;
 function gen.makeThresholdTable(inputTable)&lt;br /&gt;
     inputTable = inputTable or {}&lt;br /&gt;
     return setmetatable(inputTable,thresholdTableMetatable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-06-ThresholdTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
===A Munition Generation Module===&lt;br /&gt;
&lt;br /&gt;
Now, let us write some re-usable code for a human player to generate units by pressing a key while an appropriate unit is active.  This sort of code could be used for ranged attacks (generating a &amp;quot;munition&amp;quot;) and also for recruiting mercenaries by paying gold.&lt;br /&gt;
&lt;br /&gt;
The first thing we will want to do is to decide how our code will be used by the end user.  This will, perhaps, change by the time we finish writing the code, but it will at least give us a starting point.&lt;br /&gt;
&lt;br /&gt;
spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&lt;br /&gt;
&lt;br /&gt;
Our goal is that when a player attempts to generate a unit using another unit, they will provide the unit spawning the new unit, and a table of information specifying if a unit (or units) can be spawned and anything else that must happen while spawning (like paying money, expending movement points, etc.).&lt;br /&gt;
&lt;br /&gt;
We have an option here.  We could have the scenario creator provide the specification table as a required file for our module, or the creator can provide it at the time spawnUnit is called.  I choose the latter for a couple of reasons.  The first is that it allows the player to have more than one specification table, either because more than one key can spawn a unit, or because the specification can change over time.  The other is reason is so that the creator can make the table in the events.lua file if desired (since our module can&#039;t require information from events.lua).&lt;br /&gt;
&lt;br /&gt;
Having decided that our generateUnit events are going to be specified by a table, we have to decide what the contents of that table should be.  It seems pretty reasonable to index the specificationTable with the index of the unit type of each unit that can generate using the information in the table.  If a unit type id number is missing, that unit doesn&#039;t generate a munition (or recruit a unit).&lt;br /&gt;
&lt;br /&gt;
The value for each unit type id in the specification table will be a table that specifies how and if that unit generates other units.&lt;br /&gt;
&lt;br /&gt;
 --specificationTable[unitType.id]={&lt;br /&gt;
 --&lt;br /&gt;
 -- goldCost = integer or nil&lt;br /&gt;
 --      amount of gold it costs to generate a unit&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minTreasury = integer or nil&lt;br /&gt;
 --      minimum amount of gold in treasury to generate a unit&lt;br /&gt;
 --      absent means refer to gold cost&lt;br /&gt;
 --      (tribe will generate and be set to 0 if treasury is less than goldCost)&lt;br /&gt;
 -- treasuryFailMessage = string or nil&lt;br /&gt;
 --      A message to be displayed if the unit fails to spawn a unit due to an &lt;br /&gt;
 --      insufficient treasury&lt;br /&gt;
 --      nil means no message&lt;br /&gt;
&lt;br /&gt;
 -- There are three ways to specify move costs, in full movement points,&lt;br /&gt;
 -- in &amp;quot;atomic&amp;quot; movement points, and as a fraction of total movement points for the&lt;br /&gt;
 -- unit type.  Use only one kind per unit type &lt;br /&gt;
 &lt;br /&gt;
 -- moveCost = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMove = integer or nil&lt;br /&gt;
 --      minimum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means any movement points for land/sea, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMove = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostAtomic = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      refers to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveAtomic = integer or nil&lt;br /&gt;
 --      minumum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      referes to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMoveAtomic = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points expended generating the unit&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points that must remain to be allowed&lt;br /&gt;
 --      to generate a unit&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 -- postGenMinMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function, round up to nearest &amp;quot;atomic&amp;quot; move point&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- roundFractionFull = bool or nil&lt;br /&gt;
 --      fractional movement cost and minimum are rounded up to full movement point&lt;br /&gt;
 --      instead of atomic movement point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- roundFractionFullDown = bool or nil&lt;br /&gt;
 --      fractional cost and minimum are rounded down to full move point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- minMoveFailMessage = string or nil&lt;br /&gt;
 --      a message to be displayed if a unit is not generated due to insufficient&lt;br /&gt;
 --      movement points.&lt;br /&gt;
 --      nil means no message &lt;br /&gt;
&lt;br /&gt;
 -- allowedTerrainTypes = table of integers or nil&lt;br /&gt;
 --      a unit may only be generated if the tile it is standing on&lt;br /&gt;
 --      corresponds to one of numbers in the table&lt;br /&gt;
 --      nil means the unit can be generated on any terrain type&lt;br /&gt;
 -- terrainTypeFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to standing&lt;br /&gt;
 --      on the incorrect terrain &lt;br /&gt;
&lt;br /&gt;
 -- requiredTech = tech object or nil&lt;br /&gt;
 --      the generating civ must have this technology in order to generate&lt;br /&gt;
 --      the unit&lt;br /&gt;
 --      nil means no requirement&lt;br /&gt;
 -- techFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to not having&lt;br /&gt;
 --      the correct technology &lt;br /&gt;
&lt;br /&gt;
 -- payload = boolean or string&lt;br /&gt;
 --      if true, unit must have a home city in order to generate munitions&lt;br /&gt;
 --      and generating munitions sets the home city to NONE&lt;br /&gt;
 -- payloadFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to the &lt;br /&gt;
 --      payload restriction&lt;br /&gt;
 -- payloadRestrictionCheck = nil or function(unit)--&amp;gt;boolean&lt;br /&gt;
 --      If function returns false, the home city is not valid for giving the&lt;br /&gt;
 --      unit a payload.  This will be checked when the unit is activated, when&lt;br /&gt;
 --      the unit is given a new home city with the &#039;h&#039; key and when the unit&lt;br /&gt;
 --      tries to generate a munition&lt;br /&gt;
 --      nil means no restriction&lt;br /&gt;
 -- payloadRestrictionMessage = nil or string&lt;br /&gt;
 --      message to show if a unit fails the payloadRestrictionCheck&lt;br /&gt;
&lt;br /&gt;
 -- canGenerateFunction = nil or function(unit)--&amp;gt;boolean &lt;br /&gt;
 --      This function applied to the generating unit must return true in order&lt;br /&gt;
 --      for a unit to be spawned.  All other conditions still apply.&lt;br /&gt;
 --      any failure message should be part of canGenerateFunction&lt;br /&gt;
 --      absent means no extra conditions &lt;br /&gt;
&lt;br /&gt;
 -- generateUnitFunction = nil or function(unit)--&amp;gt;table of unit&lt;br /&gt;
 --      This function creates the unit or units to be generated&lt;br /&gt;
 --      and returns a table containing those units&lt;br /&gt;
 --      Ignore any specifications prefixed with * if this is used&lt;br /&gt;
 --      nil means use other specifications &lt;br /&gt;
&lt;br /&gt;
 --*generatedUnitType = unitType&lt;br /&gt;
 --      The type of unit to be generated&lt;br /&gt;
 --      can&#039;t be nil unless generateUnitFunction is used instead &lt;br /&gt;
&lt;br /&gt;
 --*giveVeteran = bool or nil&lt;br /&gt;
 --      generated unit(s) given veteran status if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
 --      if true, overrides copyVeteranStatus&lt;br /&gt;
&lt;br /&gt;
 --*copyVeteranStatus = bool or nil&lt;br /&gt;
 --      generated unit(s) copy veteran status of generating unit if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
&lt;br /&gt;
 --*setHomeCityFunction = nil or function(generatingUnit)--&amp;gt;cityObject&lt;br /&gt;
 --      determines what home city the spawned unit should have&lt;br /&gt;
 --      nil means a home city of NONE &lt;br /&gt;
&lt;br /&gt;
 --*numberToGenerate = nil or number or thresholdTable or function(generatingUnit)--&amp;gt;number&lt;br /&gt;
 --      if nil, generate 1 unit in all circumstances&lt;br /&gt;
 --      if integer, generate that many units (generate 0 if number less than 0)&lt;br /&gt;
 --      if number not integer, generate floor(number), and 1 more with&lt;br /&gt;
 --      probability number-floor(number)&lt;br /&gt;
 --      if thresholdTable, use remaining hp as the key, to get the number to create&lt;br /&gt;
 --      if function, get the number as the returned value of the function &lt;br /&gt;
&lt;br /&gt;
 -- activate = bool or nil&lt;br /&gt;
 --      Activates one of the generated units if true.  If generateUnitFunction was used,&lt;br /&gt;
 --      the unit at index 1 is activated, if index 1 has a value.  (if not, any unit in&lt;br /&gt;
 --      the list might be chosen)&lt;br /&gt;
&lt;br /&gt;
The very last entry brings forward a change that must be made to our unit generation specification.  Lua&#039;s activate unit command doesn&#039;t run the unit activation trigger, even though the active unit is changed.  Therefore, we must do that manually.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
becomes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit,specificationTable,unitActivationCode)--&amp;gt;table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Perhaps we will change it again later.&lt;br /&gt;
&lt;br /&gt;
I&#039;ve decided to try a different instructional technique for this section.  Instead of writing the code and then going through it section by section, I&#039;ve recorded a video of my coding and testing this module, and I attempt to explain some of the stuff that I do along the way.&lt;br /&gt;
&lt;br /&gt;
I&#039;m not sure of the value of the video.  If you find that there seems to be little useful content relative to the time it takes to watch, then feel free to skip it and continue the lesson.  I don&#039;t teach anything &amp;quot;new&amp;quot; in it, so you won&#039;t miss anything crucial.  However, it should be pretty close to how programming Lua can actually happen in the &amp;quot;real world.&amp;quot;  While I did give some thought to how to write the module before I started, I do attempt to solve problems in real time, and make mistakes that are not discovered for a while (including one where I try to explain how I solve a problem and then not actually do a crucial part).&lt;br /&gt;
&lt;br /&gt;
You can find the code [https://forums.civfanatics.com/threads/totpp-the-munitions-library.647910/ here].  Even if you decide not to watch the video, download the code and try testing some of the features based on the specification above.  If you find any bugs, submit a fix (or at least report the issue).&lt;br /&gt;
&lt;br /&gt;
The video can be found [https://youtu.be/XxPyNknGlAo here].&lt;br /&gt;
&lt;br /&gt;
===A Unit Attack Bonus for Complementary Units in Square===&lt;br /&gt;
&lt;br /&gt;
Something we might like to do is to give units an attack bonus if they attack from a square with some special unit, for example a &amp;quot;leader&amp;quot; unit.  The [[Napoléon I]] scenario, for example, gives an attack bonus to units if a commander unit, such as Napoleon, is in the square when the unit is activated (the unit can subsequently move and still retain the bonus as long as no other unit is selected).  We will now make a module providing the same functionality.&lt;br /&gt;
&lt;br /&gt;
We first have to have a basic idea of how this functionality should work.  When a unit is activated, the onActivateUnit event checks if the newly activated unit should get an attack bonus, based on the other units in the square.  If the unit deserves an attack bonus, the corresponding unitType.attack entry is changed, and all the attack value of all other units is reset to the default value.  If the activated unit also does not deserve an attack bonus, that value is also set to the default value.&lt;br /&gt;
&lt;br /&gt;
This now leads us to some more possibilities.  Should multiple bonus units lead to multiple bonuses or only apply the best one?  For example, suppose a legion gets a bonus if an archer is also in the same square.  Should two archers provide twice the bonus?  Perhaps two archers should provide a larger bonus than one, but not twice as much.  Perhaps a legion should also get a bonus if there is a catapult in the square, but that bonus should apply even if the maximum archer bonus is already achieved.  It seems like perhaps there should be a &amp;quot;ranged unit&amp;quot; bonus, an &amp;quot;artillery unit&amp;quot; bonus and maybe a &amp;quot;cavalry&amp;quot; bonus which should all impact the legion&#039;s attack value.  It&#039;s looking like we might end up demanding that a scenario creator make a big complicated table in order to use this functionality, even if they only have simple needs.&lt;br /&gt;
&lt;br /&gt;
What we can do to alleviate this is to write a &amp;quot;simple&amp;quot; version of the event that is easy to use (and program), and also write a more complicated version that gives the expanded capability.&lt;br /&gt;
&lt;br /&gt;
Specification Table for simpleAttackBonus&lt;br /&gt;
&lt;br /&gt;
 --simpleAttackBonusTable[activeUnit.type.id] ={[bonusUnitType.id]=bonusNumber}&lt;br /&gt;
 --simpleAttackBonusTable.type = string&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- if simpleAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- if simpleAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 --simpleAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise &lt;br /&gt;
&lt;br /&gt;
The relevant first draft of the code is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function simpleAttackBonus(activeUnit,simpleAttackBonusTable,defaultAttackTable)&lt;br /&gt;
     -- reset all unit attack values&lt;br /&gt;
     for unitTypeID,attackValue in pairs(defaultAttackTable) do&lt;br /&gt;
         civ.getUnitType(unitTypeID).attack = attackValue&lt;br /&gt;
     end&lt;br /&gt;
     local unitBonusTable = simpleAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
     if not unitBonusTable then&lt;br /&gt;
         -- unitBonusTable is nil (or false), so the active unit can&#039;t&lt;br /&gt;
         -- get a bonus&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
     -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
     for unit in activeUnit.location.units do&lt;br /&gt;
         if unitBonusTable[unit.type.id] and unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
             bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     if bestBonusSoFar == 0 then&lt;br /&gt;
         -- If no bonus unit is found, this will be true, so do nothing else&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- set the new attack and return&lt;br /&gt;
     if string.lower(simpleAttackBonusTable.type) == &amp;quot;addBonus&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = activeUnit.type.attack+bestBonusSoFar&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     local attackMultiplier = 1&lt;br /&gt;
     if type(simpleAttackBonusTable.type) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = (100+bestBonusSoFar)/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
         attackMultiplier = 1+bestBonusSoFar&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar&lt;br /&gt;
     else&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     end&lt;br /&gt;
     -- apply the bonus and round as appropriate&lt;br /&gt;
     if type(simpleAttackBonusTable.round) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;up&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.ceil(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;down&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     else&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now let us go over this section by section.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-07-AttackBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The first thing we do is to reset all the attack values of all the unit types.  That way, if a bonus existed for the last unit activated, that bonus no longer applies.  If a unit type is not in the defaultAttackTable, then we don&#039;t have the information to reset the attack value anyway, so we can safely ignore it by using the pairs function to iterate over the table.&lt;br /&gt;
&lt;br /&gt;
Now, we must find out if the newly activated unit deserves a bonus.  For that, we get the table associated with the active unit&#039;s type.  If the value is nil instead of a table, then the unit&#039;s type is not in the simpleAttackBonusTable, so there is no bonus to apply and the function returns.&lt;br /&gt;
&lt;br /&gt;
If the unit is eligible for bonuses, we then check the units in the square to see if any bonuses actually apply.  We&#039;ve seen this kind of code before.  If the unit in the stack can provide a bonus, and that bonus is better than the best bonus already found, the unit now provides the best bonus.  All bonus types that we can have are better if they are larger, and we are not comparing between bonus types, so a simple numerical comparison will do.  All bonuses are larger than 0 in our formulation, so 0 is a good starting value in the search.&lt;br /&gt;
&lt;br /&gt;
If the best bonus so far is still 0, there is no bonus, so the function can return.&lt;br /&gt;
&lt;br /&gt;
At this point, it occurs to me that when searching for the best bonus, we should exclude the active unit from the search.  That way, you can have a &amp;quot;strength in numbers&amp;quot; bonus, for example.  The relevant change to the code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    for unit in activeUnit.location.units do&lt;br /&gt;
        if unit ~= activeUnit and unitBonusTable[unit.type.id] and &lt;br /&gt;
 			unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, consider&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-08-AttackBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we apply the bonus that we&#039;ve found.  We use string.lower on simpleAttackBonusTable.type so that we don&#039;t have to worry about capitalization.  That does, however, require a correction to &amp;quot;addBonus&amp;quot;, since a lower case string will never be equal to that.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;addbonus&amp;quot; is the only type of bonus that is directly added to the existing attack value.  All other bonus types are a form of multiplication.  Since the addition is straightforward and doesn&#039;t require any rounding, the activeUnit&#039;s type attack value can be changed immediately, and the function execution ended with return.&lt;br /&gt;
&lt;br /&gt;
When there is only one bonus being applied, all other types of bonus are different ways of expressing how to multiply the existing attack value to get a new one, so we simply convert to the appropriate multiplier, and provide an error message if the type of bonus is not one of the valid possibilities.&lt;br /&gt;
&lt;br /&gt;
Finally, we round the attack value to an appropriate integer (since unit attack values must be integers), change the attack value of the active unit&#039;s type, and return to end the function execution.&lt;br /&gt;
&lt;br /&gt;
Now, we integrate into events.lua by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus = require(&amp;quot;attackBonus&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The relevant integration code for events.lua is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local defaultAttackValueTable = {[unitAliases.legion.id]=4}&lt;br /&gt;
 local simpleAttackBonusTable ={}&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=3,[unitAliases.musketeer.id]=4}&lt;br /&gt;
 &lt;br /&gt;
 local function doOnActivation(unit,source)&lt;br /&gt;
     munitions.payloadRestrictionCheck(unit,munitionSpecificationTable)&lt;br /&gt;
 	attackBonus.simpleAttackBonus(unit,simpleAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can check that the bonus is being applied correctly by checking the Civlopedia entry for legion and looking at the attack value.  The following cases must be tested (remember that activating a unit from the city screen doesn&#039;t run the onActivation event, so activate from the map).&lt;br /&gt;
&lt;br /&gt;
 Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
 Legion activated with archer, but no musketeer (7 attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (8 attack)&lt;br /&gt;
 Legion activated with archer and musketeer (8 attack)&lt;br /&gt;
 Legion activated with 2 archer, no musketeer (7 attack)&lt;br /&gt;
 Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
 Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
I recommend making a stack for each of these cases and activating them one by one.&lt;br /&gt;
To facilitate the test, add the following line to doOnActivation&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.ui.text(tostring(unit.type.attack))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You will want to comment out this line after testing.&lt;br /&gt;
&lt;br /&gt;
Next, change simpleAttackBonusTable to do &amp;quot;addpercent&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=30,[unitAliases.musketeer.id]=70}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With no rounding set, standard rounding is used&lt;br /&gt;
 Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
 Legion activated with archer and musketeer (7 attack)&lt;br /&gt;
 Legion activated with 2 archer, no musketeer (5 attack)&lt;br /&gt;
 Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
 Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
These numbers test both rounding up and rounding down.&lt;br /&gt;
&lt;br /&gt;
Now, use&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (6 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next,&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (6 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;standard&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next, we test &amp;quot;addfraction&amp;quot;.  Since we&#039;ve tested all the rounding options, we don&#039;t have to do that again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=0.3,[unitAliases.musketeer.id]=0.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=130,[unitAliases.musketeer.id]=170}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiply&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Before we finish, we should test a legion bonus for the legion.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.legion.id]=2,[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Legion alone should have 4 attack.&lt;br /&gt;
 A second legion on the square should provide 8 attack instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, let us try to formulate a more complicated bonus system.  One thing we mentioned is that we&#039;d like the ability to get bonuses from multiple units, and to be able to get bonuses from different &amp;quot;classes&amp;quot; of units (like &amp;quot;artillery,&amp;quot; &amp;quot;cavalry,&amp;quot; and &amp;quot;ranged attackers.&amp;quot;  Something else we might want to do is to allow different kinds of bonuses.  That is, maybe some units should provide a fixed +2 to any unit receiving the bonus, so that it is better at improving units with a low attack value, while other units should provide a percentage bonus (making them better at supporting units with an already high attack value).  It turns out that both of these ideas are not too difficult to implement individually, but that trying to implement them together makes it problematic to find the best bonus.&lt;br /&gt;
&lt;br /&gt;
Let us implement a bonus system with multiple categories but only one bonus type.  In our specification, we will first specify a data type called &amp;quot;bonusCategory.&amp;quot;  It is still just a table (though we could add a metatable if we wanted), but it will help us make our specification clearer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- A &amp;quot;bonusCategory&amp;quot; is a table&lt;br /&gt;
 -- bonusCategory = {[bonusUnitType.id]=bonusNumber, maxBonusUnits=integer or nil, nextBonusValue = fraction or nil}&lt;br /&gt;
 -- In a bonusCategory, the value for bonusUnitType.id tells what the base bonus for that unit type is,&lt;br /&gt;
 -- maxBonusUnits is the maximum number of units that can provide a bonus in this category,&lt;br /&gt;
 -- nextBonusValue tells how much to reduce the bonus for each subsequent unit,&lt;br /&gt;
 -- e.g. nextBonusValue = 0.7, and 5 units, which each have a bonusNumber=1&lt;br /&gt;
 -- The total bonus is 1(0.7)^0+.7+(.7)(.7)+(.7)^3+(.7)^4 = 1+.7+.49+.343+.2401=2.7731&lt;br /&gt;
 -- (which would be rounded as specified)&lt;br /&gt;
 -- nil means nextBonusValue=1&lt;br /&gt;
 --&lt;br /&gt;
 -- If a unit type is in two bonus categories for the same unit, there is no guarantee that the&lt;br /&gt;
 -- best bonus will be achieved&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, the bonus category is indexed by unitType id numbers for units that can give a bonus, and the corresponding bonus.  It also specifies the maximum number of units that can give a bonus, and a number that governs how to reduce a bonus for extra units.  That way, there can be diminishing returns for bonuses.&lt;br /&gt;
&lt;br /&gt;
Next, we look at the specification for the categoryAttackBonusTable&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 --categoryAttackBonusTable[activeUnit.type.id] =table of bonusCategory&lt;br /&gt;
 --categoryAttackBonusTable.type = string&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up all the percents, then compute the bonus&lt;br /&gt;
 -- i.e. 50% bonus and 50% bonus is 100% bonus, not 125%&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 50% bonus units become 50% + 25% &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up the fractions, then compute the bonus&lt;br /&gt;
 -- i.e. .5 bonus and .5 bonus is 1+.5+.5= 2x bonus, not 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 .5 bonus units become .5+.25 &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 150% and 150% yields 225% of original value&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 100, i.e. nextBonusValue=.5 2 150% bonuses become 150% and 125%&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 1.5 and 1.5 yields 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 1, i.e. nextBonusValue=.5 and two 1.5 bonuses become 1.5 and 1.25&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 --categoryAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise&lt;br /&gt;
 &lt;br /&gt;
 -- If the active unit can get a bonus, go through each category and compute the bonus for that category.&lt;br /&gt;
 -- Then, combine the bonuses for all categories to get the overall bonus, and round the result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With the bonusCategory defined, the value of the unit indices of categoryAttackBonusTable become easy to define.  Most of the specification is showing what exactly the different bonus categories mean, so the end user can use them properly.  It&#039;s not strictly necessary to offer so many choices to the end user on how to specify data, but it can be more convenient.&lt;br /&gt;
&lt;br /&gt;
Here is the actual code (before testing) to implement this more general version of attack bonuses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- HELPER FUNCTION&lt;br /&gt;
 -- findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable) --&amp;gt; number or false&lt;br /&gt;
 -- usedUnitTable is indexed by the i.d. number of units, and if the value for a unit is true,&lt;br /&gt;
 -- then it has already been used for a bonus (and, so, is not eligible)&lt;br /&gt;
 -- The function returns the bonus (before nextBonusValue is applied) if there is one, and marks the &lt;br /&gt;
 -- unit as used in the usedUnitTable&lt;br /&gt;
 -- returns false if no unit qualifies&lt;br /&gt;
 local function findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable)&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
    local bestUnitSoFar = nil&lt;br /&gt;
    -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
    -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
    for unit in tile.units do&lt;br /&gt;
        if not usedUnitTable[unit.id] and bonusCategory[unit.type.id] &lt;br /&gt;
            and bonusCategory[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestUnitSoFar = unit&lt;br /&gt;
            bestBonusSoFar = bonusCategory[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if bestUnitSoFar then&lt;br /&gt;
        usedUnitTable[bestUnitSoFar.id] = true&lt;br /&gt;
        return bestBonusSoFar&lt;br /&gt;
    else&lt;br /&gt;
        return false&lt;br /&gt;
    end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 -- HELPER FUNCTION&lt;br /&gt;
 -- computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
 -- Computes the bonus that the active unit will receive from this category, taking into &lt;br /&gt;
 -- account the type of bonus for the table&lt;br /&gt;
 local function computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local bonusThusFar = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then &lt;br /&gt;
        bonusThusFar = 1&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        bonusThusFar = 100&lt;br /&gt;
    else&lt;br /&gt;
        bonusThusFar = 0&lt;br /&gt;
    end&lt;br /&gt;
    local bonusDiscount = 1&lt;br /&gt;
    for i=1,(bonusCategory.maxBonusUnits or 10000) do&lt;br /&gt;
        local currentBonus =findBestBonusInUnitStack(activeUnit.location,bonusCategory,usedUnitTable) &lt;br /&gt;
        if not currentBonus then&lt;br /&gt;
            -- no more valid bonuses for this category&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
        if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-1)*bonusDiscount+1)&lt;br /&gt;
        elseif bonusType ==&amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
        else&lt;br /&gt;
            bonusThusFar = bonusThusFar+currentBonus*bonusDiscount&lt;br /&gt;
        end&lt;br /&gt;
        bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
    end&lt;br /&gt;
    return bonusThusFar&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 local function categoryAttackBonus(activeUnit,categoryAttackBonusTable,defaultAttackTable)&lt;br /&gt;
    local bonusInfoTable = categoryAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
    if not bonusInfoTable then&lt;br /&gt;
        -- unit doesn&#039;t get a bonus&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
    -- keep track of bonuses already computed&lt;br /&gt;
    local bonusResultsTable = {}&lt;br /&gt;
    -- keep track of units that have already been &amp;quot;used&amp;quot; for a bonus&lt;br /&gt;
    local usedUnitTable = {[activeUnit.id]=true}&lt;br /&gt;
    for index,bonusCategory in pairs(bonusInfoTable) do&lt;br /&gt;
        bonusResultsTable[index]=computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    end&lt;br /&gt;
    -- compute the bonus&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local resultAttackBeforeRounding = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult/100&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack+bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+(bonusResult/100)&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    else&lt;br /&gt;
        error(&amp;quot;categoryAttackBonus: categoryAttackBonusTable.type is not a valid value.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    -- apply the bonus and round as appropriate&lt;br /&gt;
    local roundType = categoryAttackBonusTable.round&lt;br /&gt;
    if type(roundType) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;up&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.ceil(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;down&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    else&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two helper functions for computeCategoryBonus are only used once each in the code, so making them helper functions does not help us re-use code.  However, what it does do is to break down the function design process into smaller tasks, which are each more manageable to complete.  If you&#039;re trying to keep track of too many things in your program, try writing a few helper functions to handle individual tasks.  We&#039;ll look at the helper functions when we actually arrive at them in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-09-CategoryAtkBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If there is no entry in the categoryAttackBonusTable or the active unit&#039;s type, then the function returns without doing anything further.&lt;br /&gt;
&lt;br /&gt;
The bonusResultsTable keeps track of the total bonus from each category, so they can be added or multiplied together after all the category bonuses are applied.  The usedUnitsTable keeps track of units that are no longer eligible to contribute to a bonus (such as if they have already contributed), and we initialize it with the active unit, so that it doesn&#039;t provide a bonus to itself.&lt;br /&gt;
&lt;br /&gt;
The for loop computes the bonus for every category, and stores the value in the bonusResultsTable, for use later.Now, let us look at the helper functions.&lt;br /&gt;
&lt;br /&gt;
First up is findBestBonusInUnitStack&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-10-CategoryAtkBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This basically does what it says in the name.  For a bonusCategory, it finds the unit in the tile that provides the best bonus, and has not already provided a bonus elsewhere.  If there is no qualifying unit, false is returned.  If there is, that unit&#039;s bonus is returned, and the unit&#039;s id is entered into the usedUnitTable, so that unit can&#039;t provide another bonus for the active unit.  We&#039;ve searched for the best of something before, so there is little need to go over it again.&lt;br /&gt;
&lt;br /&gt;
Next is computeCategoryBonus&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-11-CategoryAtkBonus3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we&#039;re computing the bonus for the entire bonusCategory.  We need the bonus type in order to know what kind of math to do.  The math itself is not very interesting.  We also initialize the bonusDiscount, which keeps track of the fraction of the next unit&#039;s bonus that will actually be applied.&lt;br /&gt;
&lt;br /&gt;
Next, we enter a for loop that will run one time for each possible bonus that there can be in a bonus category.  If bonusCategory.maxBonusUnits is nil, then we set an arbitrary limit of 10000 units, which is very unlikely to happen in practice.&lt;br /&gt;
&lt;br /&gt;
At each iteration of the loop, the best available bonus in the stack is found.  If no unit was eligible to provide a bonus, then the current bonus is false, and the &amp;quot;break&amp;quot; command is issued.  Break immediately exits the current loop.  So, our program doesn&#039;t run 10000 loops if there is no maximum number of bonus units, it just breaks at an appropriate time.&lt;br /&gt;
&lt;br /&gt;
After the bonus is found, it is added to or multiplied with the bonus already found.  The bonus computed in this way will be the largest possible, since the bonus provided does not depend on the other units chosen (so we don&#039;t have a situation where &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; are both useless, but &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; chosen together are best).  Also, since the best bonus is chosen first, the smallest bonus discount applies to it, so the cost imposed by the discounting is smallest.&lt;br /&gt;
&lt;br /&gt;
Finally, we update the bonusDisount.  Here, I notice a problem in the code as written, since bonusCategory.nextBonusValue is allowed to be nil.  Replace&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
with &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*(bonusCategory.nextBonusValue or 1) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
so that if there is no nextBonusValue, a default of 1 is used, and the bonusDiscount stays at 1 (i.e. no discount is applied).&lt;br /&gt;
&lt;br /&gt;
We return to categoryAttackBonus to see&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-12-CategoryAtkBonus4.jpg]]&lt;br /&gt;
&lt;br /&gt;
From here, we combine the bonuses stored in bonusResultsTable, the exact way of doing so being dependant on the type of bonus involved.  The math itself isn&#039;t very interesting, and doesn&#039;t seem all that likely to come up in this exact form elsewhere.  If you need help with the mathematical details of some event you want to write, ask in the forums.  There&#039;s a good chance someone has the skills to help you solve your specific problem.&lt;br /&gt;
&lt;br /&gt;
For every type of bonus, the result is stored in resultAttackBeforeRounding, so that variable can be rounded up or down as specified by the rounding type.&lt;br /&gt;
&lt;br /&gt;
Here, I notice another error.  We should restrict the attack value for a unit to not exceed 98.  We can do that with a math.min(value, 98).&lt;br /&gt;
&lt;br /&gt;
Now, we need to test the various aspects of the attack bonus program, so we need an appropriate table&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addbonus&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=2,[unitAliases.chariot.id]=4,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=2,[unitAliases.musketeer.id]=4,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Also, comment out the old attack bonus line, and put in a new one&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus.categoryAttackBonus(unit,categoryAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
Already, we find a problem.  Although there were no syntax errors to fix, I forgot to reset unit attack values.  So, very quickly, the legions keep gathering extra attack values when they are activated (since the base attack is not reset to 4).  Since this is happening anyway, I&#039;ll test the 98 attack value maximum.  That appears to work, at least in the case of no specified rounding.&lt;br /&gt;
&lt;br /&gt;
Cut and paste the appropriate lines from the simpleAttackBonus to the categoryAttackBonus, and save.&lt;br /&gt;
&lt;br /&gt;
With that bug fixed, everything works as expected.&lt;br /&gt;
&lt;br /&gt;
Next, we change the categoryAttackBonusTable to &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addpercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=50,[unitAliases.chariot.id]=100,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=50,[unitAliases.musketeer.id]=100,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addpercent&amp;quot;.  These are the same, since adding we&#039;re adding percentages of the same base value of 4.  So a value of 2 is the same as adding 50% of 4.&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
The results are the same.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addfraction&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=.50,[unitAliases.chariot.id]=1.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.50,[unitAliases.musketeer.id]=1.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
We&#039;ll have to do some new calculations, now, since multiply and multiplyfraction give different results than the various adding formulations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiply&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=1.50,[unitAliases.chariot.id]=2.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=1.50,[unitAliases.musketeer.id]=2.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 12 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
 Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Finally, we use multiplyPercent, and check for the same results&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=150,[unitAliases.musketeer.id]=200,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 12 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
 Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Quickly, I find that if a bonus applies, that bonus makes the attack value of a legion 98.  I failed to multiply percents correctly in computeCategoryBonus.  The Line &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Is changed to &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+100)/100&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, Change archer bonus to 110 and musketeer bonus to 120 (so a unit will make a legion have 4.4 and 4.8 value before rounding), and test the rounding options.  You will find they all work.&lt;br /&gt;
&lt;br /&gt;
At the moment, we don&#039;t have a way to mix different types of bonuses.  As said earlier, we might want this so that some units can be better at giving bonuses to low attack units than to high attack units, while others give a percentage bonus to everything.  We could now write a bonus system that allows for multiple types of bonuses. However, the current bonus system allows for the bonus to change per unit.  This means that we can, for example, convert a +2 attack bonus to a plus 100% bonus for a unit with 2 attack, and a plus 50% bonus for a unit with 4 attack.  In the case of the multiplied bonuses, this will make the bonus more powerful if there is more than one.  That is, 2 attack, +2 twice is 6, but if +2 is changed to x2, then the multiplied bonus brings the attack up to 8.  However, this seems like it would be a relatively unlikely problem, and there are other things this code can&#039;t handle, so we&#039;ll let someone else make the code if they actually need it.&lt;br /&gt;
&lt;br /&gt;
So, what we&#039;ll do is write a function that will change all appropriate entries in the categoryAttackBonusTable to reflect a different value.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed(unitType,number,categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unit type to any unit to be equivalent&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, an issue with tables arises.  It is very likely that when someone defines their cateogryAttackBonusTable, they&#039;ll define it something like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.25,[unitAliases.musketeer.id]=.5}&lt;br /&gt;
 local bonusTableForInfantry = {rangeBonusCategory}&lt;br /&gt;
 local cABT = {type=&amp;quot;addfraction&amp;quot;}&lt;br /&gt;
 cABT[unitAliases.phalanx.id]=bonusTableForInfantry&lt;br /&gt;
 cABT[unitAliases.legion.id] = bonusTableForInfantry&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
However, this means that both &amp;lt;code&amp;gt; cABT[unitAliases.legion.id]  &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt; cABT[unitAliases.phalanx.id] &amp;lt;/code&amp;gt; actually refer to the same piece of memory, and changing cABT[unitAliases.legion.id][1][unitAliases.archer.id] will also change the value at cABT[unitAliases.phalanx.id][1][unitAliases.archer.id].  This is because of the way lua tables are designed.  This design can be useful, for example it allowed us to make changes to usedUnitsTable in the last function without having to copy the table, make changes to the copy of the table, and then replace the original table with that copy as a return value.  However, it also requires us to be careful when we make changes to entries in tables.  In this case, we&#039;ll simply copy the table and all its sub values into a new table.&lt;br /&gt;
&lt;br /&gt;
The code to do this is given by&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will explain this code in the next section, since it involves a programming technique which we haven&#039;t discussed before.&lt;br /&gt;
&lt;br /&gt;
For now, we analyze plusFixed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed({[unitType1.id]=fixedBonus,[unitType2.id]=fixedBonus},categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unitTypeI.id to a unit to be equivalent to&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power.  If the unit doesn&#039;t receive a bonus&lt;br /&gt;
 -- from the unitType, then it won&#039;t after applying plusFixed.&lt;br /&gt;
 -- The value of the existing bonus is ignored.&lt;br /&gt;
 &lt;br /&gt;
 local function plusFixed(fixedUnitBonusTable,categoryAttackBonusTable)&lt;br /&gt;
     local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
     for bonusReceivingUnitTypeID,bonusTable in pairs(categoryAttackBonusTable) do&lt;br /&gt;
         -- replace bonusTable with an equivalent table that is not referened&lt;br /&gt;
         -- anywhere else, so that changes to it can be made without impacting&lt;br /&gt;
         -- data elsewhere&lt;br /&gt;
         categoryAttackBonusTable[bonusReceivingUnitTypeID] = duplicateTable(bonusTable)&lt;br /&gt;
         -- make bonusTable refer to the &amp;quot;current&amp;quot; bonus table for the unit type&lt;br /&gt;
         bonusTable =categoryAttackBonusTable[bonusReceivingUnitTypeID] &lt;br /&gt;
         -- For each unit type in the fixedUnitBonusTable, check if any bonus category&lt;br /&gt;
         -- in the bonusTable corresponds to it.  If so, make the change&lt;br /&gt;
         for bonusGivingUnitTypeID,fixedBonusValue in pairs(fixedUnitBonusTable) do&lt;br /&gt;
             -- get the attack of the unit type &lt;br /&gt;
             local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
             -- in each bonus category, check if the giver&#039;s unit type id is there,&lt;br /&gt;
             -- if so, change to the correct attack&lt;br /&gt;
             for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
                 if bonusCategory[bonusGivingUnitTypeID] then&lt;br /&gt;
                 -- change the bonus appropriately&lt;br /&gt;
                     if bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue&lt;br /&gt;
                     elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*(fixedBonusValue+baseAttack)/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=(fixedBonusValue+baseAttack)/baseAttach&lt;br /&gt;
                     else&lt;br /&gt;
                         error(&amp;quot;pluxFixed: categoryAttackBonusTable.type does not have an acceptable value.&amp;quot;)&lt;br /&gt;
                     end&lt;br /&gt;
                 end&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-13-plusFixed1.jpg]]&lt;br /&gt;
&lt;br /&gt;
As before, we save the bonusType in lower case, since we&#039;ll be using it a lot later.  Next, we open a for loop, where the index is the id of the unit type receiving the bonus, and the value is the bonus table for that unit type.  Next, we duplicate the bonus table, so that we have a table we can change without impacting anything elsewhere, and we store the duplicated table in categoryAttackBonusTable in place of the original bonusTable for the current bonus receiving unit id.  Next, we assign this duplicated table to the variable bonusTable, so we can refer to it later in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-14-plusFixed2.jpg]]&lt;br /&gt;
&lt;br /&gt;
We now perform the following actions for each unitType.id and corresponding fixedBonusValue submitted in the fixedUnitBonusTable.&lt;br /&gt;
&lt;br /&gt;
First, get the attack of the bonus receiving unit, since we&#039;ll need that in order to customize the bonus.  Next, check each bonus category in the bonus table.  If the bonus category has the current unitTypeID as a key, then replace the existing value with a bonus equivalent to adding a fixed value to the receiving unit&#039;s attack.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all that must be done, so end all the loops.&lt;br /&gt;
&lt;br /&gt;
Now we test the function.&lt;br /&gt;
&lt;br /&gt;
Add unitAliases.phalanx = civ.getUnitType(3) to the appropriate file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 defaultAttackValueTable[unitAliases.phalanx.id]=1&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,&lt;br /&gt;
 								nextBonusValue=0.5,maxBonusUnits=1}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=125,[unitAliases.musketeer.id]=150,&lt;br /&gt;
 								nextBonusValue=0.75,maxBonusUnits=1}&lt;br /&gt;
 local standardBonus = {cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.phalanx.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 attackBonus.plusFixed({[unitAliases.chariot.id]=2,[unitAliases.musketeer.id]=2},&lt;br /&gt;
 						categoryAttackBonusTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The chariot and the musketeer individually should each add 2 to both a phalanx and a legion,&lt;br /&gt;
so the phalanx should have an attack of 3, and the legion should have an attack of 6, if one bonus&lt;br /&gt;
is applied.&lt;br /&gt;
&lt;br /&gt;
Since the bonus type is multiplypercent, together the phalanx would have an attack of 9, and the legion will also have an attack of 9.&lt;br /&gt;
&lt;br /&gt;
In testing, we quickly get this error&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
You should see this in lua console if this worked&lt;br /&gt;
...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: bad argument #1 to &#039;getUnitType&#039; (number expected, got string)&lt;br /&gt;
stack traceback:&lt;br /&gt;
	[C]: in function &#039;civ.getUnitType&#039;&lt;br /&gt;
	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At line 356, which is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This must mean that bonusReceivingUnitTypeID is not a number.  This is because we&#039;re looping over categoryAttackBonusTable, and that table has a couple of entries that are not integers (&amp;quot;type&amp;quot; and &amp;quot;round&amp;quot;).  Therefore, we have to insert code to deal with this eventuality.&lt;br /&gt;
&lt;br /&gt;
The simplest way is to put everything in the loop body into an if statement, so that it only runs when bonusGivingUnitTypeID is actually a number.  You should be able to do this without detailed instructions, so do so (hint: use type function).&lt;br /&gt;
&lt;br /&gt;
The next error is &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: bad argument #1 to &#039;pairs&#039; (table expected, got nil)&lt;br /&gt;
 stack traceback:&lt;br /&gt;
 	[C]: in function &#039;pairs&#039;&lt;br /&gt;
 	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
 	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 360 for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we have a nil value for bonusTable.  This turns out to be an error in duplicateTable.  When I duplicated the table, I forgot to return that table.  That is, both the if and else statement in that function need a return command, and I forgot to add &amp;lt;code&amp;gt; return duplicatedTable &amp;lt;/code&amp;gt; in the if portion.  Add this to the duplicate table function.&lt;br /&gt;
&lt;br /&gt;
After this, our predictions are true.  Testing the other types of bonus is left as an assignment.  You can find the completed code [https://forums.civfanatics.com/threads/totpp-attack-bonus-library.648093/ here].&lt;br /&gt;
&lt;br /&gt;
===Recursive Functions===&lt;br /&gt;
&lt;br /&gt;
Let us return to the duplicateTable function.  Recall that in the last section we added a line to it, so we&#039;ll restate it here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
 		return duplicatedTable&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-16-duplicateTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
The interesting thing about duplicateTable is that it invokes duplicateTable within its code.  When we copy the key-value pairs into the new table, we run duplicateTable on the value.  If the value is not a table, then we are in the else case, and the value is immediately returned to be inserted into the duplicated table.  If the value is a table, that table is duplicated before anything else is done.&lt;br /&gt;
&lt;br /&gt;
Let us look at a simple example of a recursive function, the factorial function N!.  In lesson 3, we discussed the factorial function in the context of loops.  Since N!=N*(N-1)*(N-2)*...*3*2*1, we can give another definition of N!:&lt;br /&gt;
 N!=1 if N = 1&lt;br /&gt;
 N!=N*(N-1)! if N &amp;gt; 1&lt;br /&gt;
Or, using the convention that 0!=1, we can state&lt;br /&gt;
 N!=1 if N = 0&lt;br /&gt;
 N!=N*(N-1)! if N &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
The case where N =1 or N=0 is called the &amp;quot;base case.&amp;quot;  If we keep substituting N! as N*(N-1)!, then we won&#039;t go on forever, because we will eventually reach a point where N=0, and N! can be substituted as 1 instead of N*(N-1)!.  As long as there is a base case, our program will eventually reach the base case(s), and begin &amp;quot;completing&amp;quot; evaluation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function factorial(N)&lt;br /&gt;
 if N&amp;gt;0 then&lt;br /&gt;
     return N*factorial(N-1)&lt;br /&gt;
 else&lt;br /&gt;
     return 1&lt;br /&gt;
 end&lt;br /&gt;
 end&lt;br /&gt;
 print(factorial(5))&lt;br /&gt;
 print(factorial(6))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run this in code in the lua demo website, or using the TOTPP lua interpreter.&lt;br /&gt;
&lt;br /&gt;
Returning to our duplicateTable function, the base case is any time a table value is not itself a table.  When that happens, the recursion &amp;quot;chain&amp;quot; ends, and everything can evaluated.&lt;br /&gt;
&lt;br /&gt;
Although is shouldn&#039;t be a problem in this particular case, it should be noted that it is possible for there to not be a &amp;quot;base case&amp;quot; in the recursion style: if table, recur, if not return a value.  Consider the following table system&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 a={}&lt;br /&gt;
 b={[1]=a}&lt;br /&gt;
 a[1]=b&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In this case, the code would never end.&lt;br /&gt;
&lt;br /&gt;
It is possible that even if the code could &amp;quot;theoretically&amp;quot; execute to completion, you run out of memory before that.  This is called a &amp;quot;stack overflow,&amp;quot; and if it occurs, you will have to think of an alternate way to solve your problem.  It will probably be best to ask for help in that case (and it might be useful to provide others with an example of a problem that results in a stack overflow), but you might also look into &amp;quot;tail recursion&amp;quot;, including http://www.lua.org/pil/6.3.html .&lt;br /&gt;
&lt;br /&gt;
===Conclusion===&lt;br /&gt;
&lt;br /&gt;
With the skills covered in this chapter, you now have the tools to split a large events file into multiple files that are more manageable.  You also have the basics for how to write re-useable modules for your events, so that your work can be used by others.  Remember that if someone else uses your implementation of a feature, they will spend much less time coding and testing it, allowing them to either finish the scenario sooner, or to introduce some other feature.  So, it might very well pay to spend at least a little effort making your code into a reusable module.  Perhaps you have an idea for a cool scenario mechanic, but don&#039;t have a scenario for it (or don&#039;t want to take the time to make it).  If that&#039;s the case, just make the module and test it in a &amp;quot;toy&amp;quot; scenario (like Classic Rome) so that it can be used more or less &amp;quot;off the shelf&amp;quot; when someone needs it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5184</id>
		<title>Get Started With Lua Events Lesson 6: Splitting Code into Multiple Files</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5184"/>
		<updated>2019-07-26T16:19:03Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Two Simple Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This Lesson is under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
In this lesson, we will take a look at how to split the code for a scenario&#039;s events into multiple files.  There are several reasons to consider doing this.&lt;br /&gt;
&lt;br /&gt;
The first reason is simply to organize your work.  If you have a series of complicated events, the events.lua file can become very large very quickly. Once your events.lua file has thousands of lines of code in it, it may not be very obvious where the best place is to put that next helper function, or where to implement the function that runs a complicated event.  Sometimes even finding the piece of code that has to be changed can be a bit of a hassle.  In Over the Reich, I sometimes search for the associated civ.scen line, and then search for the exact name of the function I need.  Occasionally, there may even be more searching to find what I actually have to change.  With multiple files, it becomes easier to find things.&lt;br /&gt;
&lt;br /&gt;
Another aspect of using multiple files is that you can make certain changes without worrying about breaking things elsewhere.  If myBigComplicatedFunction relies on aModestHelperFunction for a certain part of its functionality, and a change to myBigComplicatedFunction also requires a change to aModestHelperFunction, you have to make sure that nothing else in your code also uses aModestHelperFunction, or, if something else does depend on it, that aModestHelperFunction either still provides the original functionality, or that all other functions that use aModestHelperFunction are suitably modified.  If myBigComplicatedFunction is defined in its own lua module, then you don&#039;t have to worry about forgetting that aModestHelperFunction was used elsewhere, since it can&#039;t be accessed outside the module unless you specifically allow it to be.&lt;br /&gt;
&lt;br /&gt;
A second reason to split events code into multiple files is to facilitate collaboration.  If all of the events are in a single file, then only one person can make changes to the file at a time.  If one partner starts changing an event, but has to do something else before finishing, everyone waits on one person&#039;s delay.  However, if most aspects of the scenario are separated into individual files, everyone can work on his or her own piece of the puzzle without depriving others of the opportunity to work at that time.&lt;br /&gt;
&lt;br /&gt;
A third reason to split events into multiple modules is to facilitate reusing code.  If everything required to implement an event is in its own file (or files), it becomes much easier for other creators to use your functionality in their scenario.  Since everything they need is already in one place, they don&#039;t have to find every last helper function, or concern themselves with naming conflicts.&lt;br /&gt;
&lt;br /&gt;
===Two Simple Examples===&lt;br /&gt;
&lt;br /&gt;
Let us look at the top of the events.lua file.  You can get the version that I started lesson 6 with [https://forums.civfanatics.com/threads/totpp-get-started-with-lua-events.636192/#post-15212114 here].&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-01-DefaultRequire.jpg]]&lt;br /&gt;
&lt;br /&gt;
We get code from other files by using the command &amp;lt;code&amp;gt;require&amp;lt;/code&amp;gt; along with a string specifying the file name (except for the .lua extension).  At the moment, we can only get code stored in the lua folder in the Test of Time directory.  This is inconvenient if we&#039;re trying to distribute a scenario, since installing a scenario would require moving certain files to the lua directory, and those file names might conflict.  Instead, we need to tell the Lua interpreter to search in the same folder that the events.lua folder is in.&lt;br /&gt;
&lt;br /&gt;
To do this, we need the following code:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local eventsPath = string.gsub(debug.getinfo(1).source, &amp;quot;@&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 local scenarioFolderPath = string.gsub(eventsPath, &amp;quot;events.lua&amp;quot;, &amp;quot;?.lua&amp;quot;)&lt;br /&gt;
 if string.find(package.path, scenarioFolderPath, 1, true) == nil then&lt;br /&gt;
    package.path = package.path .. &amp;quot;;&amp;quot; .. scenarioFolderPath&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can probably cut and paste this code before the require lines in your events.lua file and not worry about how it works.  However, I&#039;ll provide a brief explanation for reference.&lt;br /&gt;
&lt;br /&gt;
The first line stores the location of the of the current file as a string in eventsPath.&lt;br /&gt;
&lt;br /&gt;
The second line replaces events.lua in the eventsPath with ?.lua, which will tell the Lua interpreter to look for .lua files in the current directory (that is to say, the directory with the events.lua file).  &lt;br /&gt;
&lt;br /&gt;
The if statement adds scenarioFolderPath to the places for the Lua interpreter to search for code, if that directory is not already in the search path.  Since the search path is kept active by the Lua interpreter, it will not be necessary to repeat these lines of code in every file that performs a require action as long as you are running the file as part of events.  If you are writing some other kind of code, you will need to substitute &amp;quot;events.lua&amp;quot; with the name of the file with the code you are running.  Note that for some reason, events.lua is always provided in lower case.  However, for use in other situations, debug.getinfo(1).source uses the correct case for event files. I have only briefly tested this, so you may have to do some testing yourself if this situation comes up (or ask for help in the forums).&lt;br /&gt;
&lt;br /&gt;
Now that we&#039;ve told Lua where to look for our extra code, we can begin moving code to other files.  Think of require as telling Lua to run the entire contents of another file as a function.  We can then assign a value to whatever that file returns, which will usually be a table.  A couple of examples will clarify.&lt;br /&gt;
&lt;br /&gt;
For our first example, we will move our scenario&#039;s parameters to a separate file, and access it via require.  This may not seem worthwhile in this example, but tables like this can get large in a hurry.  At the time of writing, Over the Reich has over 100 lines of parameters (&amp;quot;specialNumbers&amp;quot;), and parameters are something that a designer might like to play with while collaborators make other implementations.  Also, parameters will have to be referenced by other parts of the code, and a file that is required by events.lua cannot, in turn, require events.lua in order to get information.  That means that we&#039;ll have to keep our parameters in a separate file anyway.&lt;br /&gt;
&lt;br /&gt;
Cut the parameters table definition and paste it into a new file, classicRomeParameters.lua.  For the last line, write&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return parameters&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, Near the top of events.lua, where the existing require lines are, add the eventsPath code from above and also the line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local parameters = require(&amp;quot;classicRomeParameters&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
[[File:GetStartedWithLuaLesson6-02-RequireParameters.jpg]]&lt;br /&gt;
&lt;br /&gt;
Open the classicRome scenario and test out a couple of events to make sure everything is the same.&lt;br /&gt;
&lt;br /&gt;
We might find it convenient to put a few tables into the same file.  For this, we will simply return a table containing these tables, and give each table a name in the events.lua file.&lt;br /&gt;
&lt;br /&gt;
Create a file classicRomeAliases.lua and move all the &amp;quot;aliases&amp;quot; tables to that file.  Also move the getCityAt function.&lt;br /&gt;
&lt;br /&gt;
At the bottom of the file, put the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 unitAliases=unitAliases,&lt;br /&gt;
 tribeAliases=tribeAliases,&lt;br /&gt;
 tileAliases=tileAliases,&lt;br /&gt;
 cityAliases=cityAliases,&lt;br /&gt;
 textAliases=textAliases,&lt;br /&gt;
 terrainAliases=terrainAliases,&lt;br /&gt;
 improvementAliases=improvementAliases,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following lines to events.lua (in the require section)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local aliases = require(&amp;quot;classicRomeAliases&amp;quot;)&lt;br /&gt;
 local unitAliases,tribeAliases,tileAliases,cityAliases,textAliases,&lt;br /&gt;
 		terrainAliases,improvementAliases=aliases.unitAliases,aliases.tribeAliases,&lt;br /&gt;
 		aliases.tileAliases,aliases.cityAliases, aliases.textAliases,aliases.terrainAliases,&lt;br /&gt;
 		aliases.improvementAliases&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, our classicRomeAliases module is returning a table with our &amp;quot;alias&amp;quot; tables.  We then assign the entries in this returned table to local variables with the desired names.  Here, I use multiple variable assignment, which I don&#039;t believe I&#039;ve used before (even though Lua allows it), but these could just as simply have been assigned line by line.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-03-RequireAliases.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now, let us move the legion plundering code into its own file, which we&#039;ll call plunder.lua.  First, copy over the legionPlunder function, and paste it near the bottom of the new file.&lt;br /&gt;
&lt;br /&gt;
Now, let us go through the code of this function, and figure out what else we need in our plunder.lua module.&lt;br /&gt;
&lt;br /&gt;
The very first part of the function is a check against unitAliases.legion.  This means we need the unitAliases table, and so we copy the aliases require code to the top of plunder.lua.  We don&#039;t need the path information, since that will be added in events.lua.&lt;br /&gt;
&lt;br /&gt;
A few more lines down, we find that the function cityRadius is also used in legionPlunder.  Therefore, we move that over as well.  We also need the plunderValue function, so copy that over as well.&lt;br /&gt;
&lt;br /&gt;
Next, we check if cityRadius relies on anything, but it doesn&#039;t.&lt;br /&gt;
&lt;br /&gt;
Proceeding to plunderValue, we find that it relies on the parameters table, so require that as well.  The function plunderValue does not appear to depend on anything else, so we&#039;re done moving functionality.  If we missed something, the Lua interpreter will complain at some point anyway.&lt;br /&gt;
&lt;br /&gt;
Next, we require the plunder module in events.lua, with the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local plunder = require(&amp;quot;plunder&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, for each of the functions in plunder.lua, we check if it is used somewhere in events.lua.  We can do this by searching.  plunderValue isn&#039;t used anywhere, so we&#039;re done with that.  City radius is used.  At the bottom of plunder.lua, we begin our return table, and have&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 cityRadius=cityRadius,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, in events.lua, we replace the ocurance of cityRadius with plunder.cityRadius.  Alternatively, we could have put &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local cityRadius=plunder.cityRadius&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
after the line requiring plunder.&lt;br /&gt;
&lt;br /&gt;
Similarly, for legionPlunder, we add &amp;lt;code&amp;gt;legionPlunder=legionPlunder&amp;lt;/code&amp;gt; to the table that plunder.lua returns, and pre-append plunder. to legionPlunder in the one location where it occurs.&lt;br /&gt;
&lt;br /&gt;
Now, we test the legion plunder function and the press 4 generate archers function to make sure everything works.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-04-RequirePlunder.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Working With a Library===&lt;br /&gt;
&lt;br /&gt;
In programming terms, a &amp;quot;library&amp;quot; is a collection of code that can provide some specified functionality to a programmer without that programmer having to modify the code in the library.  Thus far, you have been using the &amp;quot;civ&amp;quot; library to interact with the game, and there has been no need modify it in order to use it in our own events.  (Unfortunately, in the case of the civ library, we don&#039;t actually know how to modify it.)  This is in contrast to much of the code we have written thus far.  For example, the code we wrote last lesson to make Selucid elephants attack Egypt is highly specific.  You couldn&#039;t just cut and paste that code, change the argument of a single function, and get your own goto event.  It is still a good example for how to write a goto event, but a user would still have to actually write the event.&lt;br /&gt;
&lt;br /&gt;
If you plan to write some functionality for your scenario that others might find useful, it is worth spending a little extra effort to see if you can write that functionality in a form that will allow others to use it with minimal effort.  If you can, then a little extra work on your part might save someone else the trouble of re-inventing the wheel, and allow them to complete their project sooner, or to work on some new feature for you to enjoy.  Unfortunately, the Lua scenarios that have been completed at the time of writing haven&#039;t been that good at creating re-usable code, at least in part since we were all getting used to Lua.  This will hopefully be improved in the future.&lt;br /&gt;
&lt;br /&gt;
For now, we&#039;re going to look at a library which is called the General Library (unless someone comes up with a better name) and which can be found [https://forums.civfanatics.com/threads/totpp-the-general-library.647583/ here].  The purpose of this module is to provide relatively simple functionality that probably shouldn&#039;t be implemented every time it is needed.  This is useful for our purposes, since we can look at relatively self contained and simple functions for our first examples.  We&#039;ll create a library for generating munitions later.&lt;br /&gt;
&lt;br /&gt;
This library would be used by invoking the line &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local gen = require(&amp;quot;generalLibrary&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to make these functions available to the console for testing purposes, you would simply omit the local, thereby making gen a global variable.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at a function provided by the General Library &amp;lt;code&amp;gt; gen.hasIrrigation(tile)--&amp;gt;boolean&amp;lt;/code&amp;gt;.  The very first line references the helper function &amp;lt;code&amp;gt; toTile(tile or table)--&amp;gt;tile&amp;lt;/code&amp;gt;, so let us include that code, and look at it first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 -- toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- gen.toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- If given a tile object, returns the tile&lt;br /&gt;
 -- If given coordinates for a tile, returns the tile&lt;br /&gt;
 -- Causes error otherwise&lt;br /&gt;
 -- Helper Function (provided to this library as toTile and gen.toTile)&lt;br /&gt;
 local function toTile(input)&lt;br /&gt;
     if civ.isTile(input) then&lt;br /&gt;
         return input&lt;br /&gt;
     elseif type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         local xVal = input[1] or input[&amp;quot;x&amp;quot;]&lt;br /&gt;
         local yVal = input[2] or input[&amp;quot;y&amp;quot;]&lt;br /&gt;
         local zVal = input[3] or input[&amp;quot;z&amp;quot;] or 0&lt;br /&gt;
         if type(xVal)==&amp;quot;number&amp;quot; and type(yVal)==&amp;quot;number&amp;quot; and type(zVal)==&amp;quot;number&amp;quot; then&lt;br /&gt;
             if civ.getTile(xVal,yVal,zVal) then&lt;br /&gt;
                 return civ.getTile(xVal,yVal,zVal)&lt;br /&gt;
             else&lt;br /&gt;
                 error(&amp;quot;Table with values {&amp;quot;..tostring(xVal)..&amp;quot;,&amp;quot;..tostring(yVal)..&lt;br /&gt;
                         &amp;quot;,&amp;quot;..tostring(zVal)..&amp;quot;} does not correspond to a valid tile.&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
         else&lt;br /&gt;
             error(&amp;quot;Table did not correspond to tile coordinates&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;Did not receive a tile object or table of coordinates.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 gen.toTile = toTile&lt;br /&gt;
 &lt;br /&gt;
 -- gen.hasIrrigation(tile)--&amp;gt;boolean&lt;br /&gt;
 -- returns true if tile has irrigation but no farm&lt;br /&gt;
 -- returns false otherwise&lt;br /&gt;
 function gen.hasIrrigation(tile)&lt;br /&gt;
     tile = toTile(tile)&lt;br /&gt;
     local improvements = tile.improvements&lt;br /&gt;
     -- irrigation, but no mining, so not farmland&lt;br /&gt;
     if improvements &amp;amp; 0x04 == 0x04 and improvements &amp;amp; 0x08 == 0 then&lt;br /&gt;
         return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-05-HasIrrigation.jpg]]&lt;br /&gt;
&lt;br /&gt;
Let us begin by looking at the function &amp;lt;code&amp;gt;toTile&amp;lt;/code&amp;gt;.  The purpose of this function is to allow other functions to accept tile coordinates in a table instead of an actual tile object.  The function tries to be reasonably permissive in the coordinates it will accept, allowing both integer indices and lowercase string indices, and by assuming that a missing z value corresponds to map 0.  The function also tries to give reasonably helpful errors.&lt;br /&gt;
&lt;br /&gt;
This brings up something that should be considered when making reusable code: what to do if you don&#039;t get values you were expecting.  One option is to throw an error and bring up the Lua console.  This is good for scenario creators, so they know something is wrong, but not so great for end users because the error stops the rest of the event from happening, should the mistake slip through playtesting.&lt;br /&gt;
&lt;br /&gt;
The other option is for the code to fail silently, and try to do what it can.  This is the way the old Test of Time macro system often fails.  If Civ II doesn&#039;t &amp;quot;understand&amp;quot; the event, it just doesn&#039;t happen, and doesn&#039;t bother the player with the error.  This means that the scenario will still mostly work, but it is harder to catch issues during playtesting.  Sometimes, this means doing something &amp;quot;sensible&amp;quot; if the input isn&#039;t of the expected type, and might make the code easier to write, since you don&#039;t have to handle inputs differently.&lt;br /&gt;
&lt;br /&gt;
A third option is to write your code such that both things can be done.  At the top of your code, you put in a variable named &amp;quot;debugMode&amp;quot; or something, and make all the functions throw errors when true, and fail silently when false.  Then you playtest with debugMode set to true, and release with debug mode set to false.  However, this means extra work in writing your code and you also have to test everything with debug mode off.&lt;br /&gt;
&lt;br /&gt;
For toTile, I went with the fail with error option, since that will allow every function that uses toTile to assume it is receiving proper data.  It also seems unlikely that people will be regularly trying to check tiles that don&#039;t exist or have tables with tiles and units and improvement objects all in one.  And if they do, &amp;quot;guarding&amp;quot; is fairly straightforward anyway (as we&#039;ve done in previous lessons).&lt;br /&gt;
&lt;br /&gt;
Although toTile is mainly meant to be a helper function for the General Library, it is also put into the gen table to be made available to end users, since it offers useful functionality.  Hence, &amp;lt;code&amp;gt; gen.toTile=toTile&amp;lt;/code&amp;gt;.  Note that we could have given toTile a different name in the gen table that this module will return, such as gen.tableToTile=toTile.  In fact, we could refer to the same function with multiple keys in the gen table, if we want to.&lt;br /&gt;
&lt;br /&gt;
Next, we will look at gen.hasIrrigation.&lt;br /&gt;
&lt;br /&gt;
The first thing to notice is that local is not being used to define this function.  That is because we&#039;re putting the function for gen.hasIrrigation directly into the gen table that this module will return.  We could define hasIrrigation as a local variable and then copy it into the gen table.  However, there is a decent chance that the General Library will have more than 200 functions by the time everything is complete, since it is meant to provide a lot of building block functionality and keep it in one place, and we will run into trouble if we assign 200 local variables in a single function (which a required lua file acts as).&lt;br /&gt;
&lt;br /&gt;
Perhaps the most striking thing is that we begin by changing the value of tile, the argument of the function.  It looks like we&#039;re making a global variable named tile, but we&#039;re not.  When you specify the names of the arguments for a function (in this case tile), you create local variables for that function, which can be given new values just as if you had explicitly used the local keyword.&lt;br /&gt;
&lt;br /&gt;
Beyond that, we extract the integer representing the tile improvements into a local variable (which upon later reflection isn&#039;t really necessary), and check that the irrigation bit is set to 1 and the mining bit is set to 0.  Refer to lesson 5 for why this works.  In fact, we could have simply returned the value of the if statement, rather than specifying return true and return false, although it is very slightly clearer what is going on in the expanded version of the code.&lt;br /&gt;
&lt;br /&gt;
Now, let us write a function to place irrigation on a square.  It seems pretty clear that we should do nothing if the tile has a city, but we also have to decide what to do if there is mining or farmland on the tile, since those interfere with placing irrigation.  We&#039;ll just remove them, on the basis that if we&#039;re trying to &amp;quot;place irrigation,&amp;quot; then we want irrigation to be there when we are finished.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function gen.placeIrrigation(tile)&lt;br /&gt;
    tile = toTile(tile)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These lines open the function and convert a table of coordinates to a tile if necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 if tile.city then&lt;br /&gt;
    return&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the tile has a city, return so nothing else is done in the function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     -- Set irrigation bit to 1&lt;br /&gt;
     tile.improvements = tile.improvements | 0x04&lt;br /&gt;
     -- Set mining bit to 0&lt;br /&gt;
     tile.improvements = tile.improvements &amp;amp; ~0x08&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the irrigation bit to 1 and the mining bit to 0.&lt;br /&gt;
&lt;br /&gt;
The functions in this library don&#039;t have to be complex, and in fact, most probably shouldn&#039;t be.  They just have to make life easier for the end user.  If you reach this lesson before the General Library is considered &amp;quot;complete,&amp;quot; your assignment now is to submit some work for it.  If you don&#039;t feel comfortable doing bitwise operations, you can test the work of others or submit functions that simplify other tasks.  However, there are also some helper functions in the library to facilitate changing bits, so you might also consider working on the unit type flags functions.  Remember, if you want to make functions available to the console for testing purposes, they must be global variables.&lt;br /&gt;
&lt;br /&gt;
=== The Threshold Table and First Look at Metatables===&lt;br /&gt;
&lt;br /&gt;
Consider a scenario design situation that occurred in Over the Reich: a bomber is generating some bombs via a key press, and the number of bombs it should generate is dependant on its current remaining hitpoints.  The more hitpoints the bomber has, the more bombs it should generate.  What we want is to specify that if a bomber has between x and y hitpoints, it should produce 2 bombs.  That is, for a given type of bomber, we want to have, for example,&lt;br /&gt;
&lt;br /&gt;
hp &amp;gt;= 16 --&amp;gt; 4 bombs&lt;br /&gt;
16 &amp;gt; hp &amp;gt;= 12 --&amp;gt; 3 bombs&lt;br /&gt;
12 &amp;gt; hp &amp;gt;= 9 --&amp;gt; 2 bombs&lt;br /&gt;
9 &amp;gt; hp &amp;gt;= 4 --&amp;gt; 1 bomb&lt;br /&gt;
4 &amp;gt; hp &amp;gt;= 0 --&amp;gt; 0 bombs&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Lua tables do not naturally encode this kind of association by default.  However, Lua does have a feature called metatables, which allows us to change the behaviour of tables.  (This will be a much better way to make the specification than I ended up writing in Over the Reich.)&lt;br /&gt;
&lt;br /&gt;
A metatable is a table that we can &amp;quot;attach&amp;quot; to another table, and then the metatable changes the behaviour of that table.  We&#039;ll only look at metatables briefly here, but more information can be found [https://www.tutorialspoint.com/lua/lua_metatables.htm here].&lt;br /&gt;
&lt;br /&gt;
What we want is a data structure that can accept numerical &amp;quot;key values&amp;quot; that are between the key values explicitly specified, and return the appropriate value for those keys.  We will call this data structure a threshold table, since we are specifying threshold values as keys.  We can do this by assigning the following metatable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local mt = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we run &amp;lt;code&amp;gt; setmetatable(myTable,mt)&amp;lt;/code&amp;gt;, then whenever we ask for an index from myTable and that index doesn&#039;t currently exist in myTable, the function assigned to __index will run.  Now let us examine the function.&lt;br /&gt;
&lt;br /&gt;
If the type of the key is not a number, then we return whatever the table value is for that key.  We use the function rawget, because the standard &amp;lt;code&amp;gt;thresholdTable[key]&amp;lt;/code&amp;gt; will invoke this function again if the key doesn&#039;t exist, and so never return an answer (when we want it to return nil).&lt;br /&gt;
&lt;br /&gt;
If the key type is a number, then we look for the largest numerical index that is also less than or equal to the key value.  We return a default value of false if the key submitted is smaller than all numerical values.  False is chosen over nil, so that a maximum value can be set by setting the value of a numerical index to false.  Using the key [-math.huge] allows a return value to be set for all numbers (since all numbers are greater than -math.huge).&lt;br /&gt;
&lt;br /&gt;
Since we don&#039;t want scenario creators to have to re-create threshold tables every time they need them, we&#039;ll add this functionality to the General Library&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local thresholdTableMetatable = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 -- gen.makeThresholdTable(table or nil)--&amp;gt;thresholdTable&lt;br /&gt;
 function gen.makeThresholdTable(inputTable)&lt;br /&gt;
     inputTable = inputTable or {}&lt;br /&gt;
     return setmetatable(inputTable,thresholdTableMetatable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-06-ThresholdTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
===A Munition Generation Module===&lt;br /&gt;
&lt;br /&gt;
Now, let us write some re-usable code for a human player to generate units by pressing a key while an appropriate unit is active.  This sort of code could be used for ranged attacks (generating a &amp;quot;munition&amp;quot;) and also for recruiting mercenaries by paying gold.&lt;br /&gt;
&lt;br /&gt;
The first thing we will want to do is to decide how our code will be used by the end user.  This will, perhaps, change by the time we finish writing the code, but it will at least give us a starting point.&lt;br /&gt;
&lt;br /&gt;
spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&lt;br /&gt;
&lt;br /&gt;
Our goal is that when a player attempts to generate a unit using another unit, they will provide the unit spawning the new unit, and a table of information specifying if a unit (or units) can be spawned and anything else that must happen while spawning (like paying money, expending movement points, etc.).&lt;br /&gt;
&lt;br /&gt;
We have an option here.  We could have the scenario creator provide the specification table as a required file for our module, or the creator can provide it at the time spawnUnit is called.  I choose the latter for a couple of reasons.  The first is that it allows the player to have more than one specification table, either because more than one key can spawn a unit, or because the specification can change over time.  The other is reason is so that the creator can make the table in the events.lua file if desired (since our module can&#039;t require information from events.lua).&lt;br /&gt;
&lt;br /&gt;
Having decided that our generateUnit events are going to be specified by a table, we have to decide what the contents of that table should be.  It seems pretty reasonable to index the specificationTable with the index of the unit type of each unit that can generate using the information in the table.  If a unit type id number is missing, that unit doesn&#039;t generate a munition (or recruit a unit).&lt;br /&gt;
&lt;br /&gt;
The value for each unit type id in the specification table will be a table that specifies how and if that unit generates other units.&lt;br /&gt;
&lt;br /&gt;
 --specificationTable[unitType.id]={&lt;br /&gt;
 --&lt;br /&gt;
 -- goldCost = integer or nil&lt;br /&gt;
 --      amount of gold it costs to generate a unit&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minTreasury = integer or nil&lt;br /&gt;
 --      minimum amount of gold in treasury to generate a unit&lt;br /&gt;
 --      absent means refer to gold cost&lt;br /&gt;
 --      (tribe will generate and be set to 0 if treasury is less than goldCost)&lt;br /&gt;
 -- treasuryFailMessage = string or nil&lt;br /&gt;
 --      A message to be displayed if the unit fails to spawn a unit due to an &lt;br /&gt;
 --      insufficient treasury&lt;br /&gt;
 --      nil means no message&lt;br /&gt;
&lt;br /&gt;
 -- There are three ways to specify move costs, in full movement points,&lt;br /&gt;
 -- in &amp;quot;atomic&amp;quot; movement points, and as a fraction of total movement points for the&lt;br /&gt;
 -- unit type.  Use only one kind per unit type &lt;br /&gt;
 &lt;br /&gt;
 -- moveCost = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMove = integer or nil&lt;br /&gt;
 --      minimum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means any movement points for land/sea, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMove = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostAtomic = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      refers to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveAtomic = integer or nil&lt;br /&gt;
 --      minumum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      referes to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMoveAtomic = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points expended generating the unit&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points that must remain to be allowed&lt;br /&gt;
 --      to generate a unit&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 -- postGenMinMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function, round up to nearest &amp;quot;atomic&amp;quot; move point&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- roundFractionFull = bool or nil&lt;br /&gt;
 --      fractional movement cost and minimum are rounded up to full movement point&lt;br /&gt;
 --      instead of atomic movement point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- roundFractionFullDown = bool or nil&lt;br /&gt;
 --      fractional cost and minimum are rounded down to full move point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- minMoveFailMessage = string or nil&lt;br /&gt;
 --      a message to be displayed if a unit is not generated due to insufficient&lt;br /&gt;
 --      movement points.&lt;br /&gt;
 --      nil means no message &lt;br /&gt;
&lt;br /&gt;
 -- allowedTerrainTypes = table of integers or nil&lt;br /&gt;
 --      a unit may only be generated if the tile it is standing on&lt;br /&gt;
 --      corresponds to one of numbers in the table&lt;br /&gt;
 --      nil means the unit can be generated on any terrain type&lt;br /&gt;
 -- terrainTypeFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to standing&lt;br /&gt;
 --      on the incorrect terrain &lt;br /&gt;
&lt;br /&gt;
 -- requiredTech = tech object or nil&lt;br /&gt;
 --      the generating civ must have this technology in order to generate&lt;br /&gt;
 --      the unit&lt;br /&gt;
 --      nil means no requirement&lt;br /&gt;
 -- techFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to not having&lt;br /&gt;
 --      the correct technology &lt;br /&gt;
&lt;br /&gt;
 -- payload = boolean or string&lt;br /&gt;
 --      if true, unit must have a home city in order to generate munitions&lt;br /&gt;
 --      and generating munitions sets the home city to NONE&lt;br /&gt;
 -- payloadFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to the &lt;br /&gt;
 --      payload restriction&lt;br /&gt;
 -- payloadRestrictionCheck = nil or function(unit)--&amp;gt;boolean&lt;br /&gt;
 --      If function returns false, the home city is not valid for giving the&lt;br /&gt;
 --      unit a payload.  This will be checked when the unit is activated, when&lt;br /&gt;
 --      the unit is given a new home city with the &#039;h&#039; key and when the unit&lt;br /&gt;
 --      tries to generate a munition&lt;br /&gt;
 --      nil means no restriction&lt;br /&gt;
 -- payloadRestrictionMessage = nil or string&lt;br /&gt;
 --      message to show if a unit fails the payloadRestrictionCheck&lt;br /&gt;
&lt;br /&gt;
 -- canGenerateFunction = nil or function(unit)--&amp;gt;boolean &lt;br /&gt;
 --      This function applied to the generating unit must return true in order&lt;br /&gt;
 --      for a unit to be spawned.  All other conditions still apply.&lt;br /&gt;
 --      any failure message should be part of canGenerateFunction&lt;br /&gt;
 --      absent means no extra conditions &lt;br /&gt;
&lt;br /&gt;
 -- generateUnitFunction = nil or function(unit)--&amp;gt;table of unit&lt;br /&gt;
 --      This function creates the unit or units to be generated&lt;br /&gt;
 --      and returns a table containing those units&lt;br /&gt;
 --      Ignore any specifications prefixed with * if this is used&lt;br /&gt;
 --      nil means use other specifications &lt;br /&gt;
&lt;br /&gt;
 --*generatedUnitType = unitType&lt;br /&gt;
 --      The type of unit to be generated&lt;br /&gt;
 --      can&#039;t be nil unless generateUnitFunction is used instead &lt;br /&gt;
&lt;br /&gt;
 --*giveVeteran = bool or nil&lt;br /&gt;
 --      generated unit(s) given veteran status if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
 --      if true, overrides copyVeteranStatus&lt;br /&gt;
&lt;br /&gt;
 --*copyVeteranStatus = bool or nil&lt;br /&gt;
 --      generated unit(s) copy veteran status of generating unit if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
&lt;br /&gt;
 --*setHomeCityFunction = nil or function(generatingUnit)--&amp;gt;cityObject&lt;br /&gt;
 --      determines what home city the spawned unit should have&lt;br /&gt;
 --      nil means a home city of NONE &lt;br /&gt;
&lt;br /&gt;
 --*numberToGenerate = nil or number or thresholdTable or function(generatingUnit)--&amp;gt;number&lt;br /&gt;
 --      if nil, generate 1 unit in all circumstances&lt;br /&gt;
 --      if integer, generate that many units (generate 0 if number less than 0)&lt;br /&gt;
 --      if number not integer, generate floor(number), and 1 more with&lt;br /&gt;
 --      probability number-floor(number)&lt;br /&gt;
 --      if thresholdTable, use remaining hp as the key, to get the number to create&lt;br /&gt;
 --      if function, get the number as the returned value of the function &lt;br /&gt;
&lt;br /&gt;
 -- activate = bool or nil&lt;br /&gt;
 --      Activates one of the generated units if true.  If generateUnitFunction was used,&lt;br /&gt;
 --      the unit at index 1 is activated, if index 1 has a value.  (if not, any unit in&lt;br /&gt;
 --      the list might be chosen)&lt;br /&gt;
&lt;br /&gt;
The very last entry brings forward a change that must be made to our unit generation specification.  Lua&#039;s activate unit command doesn&#039;t run the unit activation trigger, even though the active unit is changed.  Therefore, we must do that manually.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
becomes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit,specificationTable,unitActivationCode)--&amp;gt;table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Perhaps we will change it again later.&lt;br /&gt;
&lt;br /&gt;
I&#039;ve decided to try a different instructional technique for this section.  Instead of writing the code and then going through it section by section, I&#039;ve recorded a video of my coding and testing this module, and I attempt to explain some of the stuff that I do along the way.&lt;br /&gt;
&lt;br /&gt;
I&#039;m not sure of the value of the video.  If you find that there seems to be little useful content relative to the time it takes to watch, then feel free to skip it and continue the lesson.  I don&#039;t teach anything &amp;quot;new&amp;quot; in it, so you won&#039;t miss anything crucial.  However, it should be pretty close to how programming Lua can actually happen in the &amp;quot;real world.&amp;quot;  While I did give some thought to how to write the module before I started, I do attempt to solve problems in real time, and make mistakes that are not discovered for a while (including one where I try to explain how I solve a problem and then not actually do a crucial part).&lt;br /&gt;
&lt;br /&gt;
You can find the code [https://forums.civfanatics.com/threads/totpp-the-munitions-library.647910/ here].  Even if you decide not to watch the video, download the code and try testing some of the features based on the specification above.  If you find any bugs, submit a fix (or at least report the issue).&lt;br /&gt;
&lt;br /&gt;
The video can be found [https://youtu.be/XxPyNknGlAo here].&lt;br /&gt;
&lt;br /&gt;
===A Unit Attack Bonus for Complementary Units in Square===&lt;br /&gt;
&lt;br /&gt;
Something we might like to do is to give units an attack bonus if they attack from a square with some special unit, for example a &amp;quot;leader&amp;quot; unit.  The [[Napoléon I]] scenario, for example, gives an attack bonus to units if a commander unit, such as Napoleon, is in the square when the unit is activated (the unit can subsequently move and still retain the bonus as long as no other unit is selected).  We will now make a module providing the same functionality.&lt;br /&gt;
&lt;br /&gt;
We first have to have a basic idea of how this functionality should work.  When a unit is activated, the onActivateUnit event checks if the newly activated unit should get an attack bonus, based on the other units in the square.  If the unit deserves an attack bonus, the corresponding unitType.attack entry is changed, and all the attack value of all other units is reset to the default value.  If the activated unit also does not deserve an attack bonus, that value is also set to the default value.&lt;br /&gt;
&lt;br /&gt;
This now leads us to some more possibilities.  Should multiple bonus units lead to multiple bonuses or only apply the best one?  For example, suppose a legion gets a bonus if an archer is also in the same square.  Should two archers provide twice the bonus?  Perhaps two archers should provide a larger bonus than one, but not twice as much.  Perhaps a legion should also get a bonus if there is a catapult in the square, but that bonus should apply even if the maximum archer bonus is already achieved.  It seems like perhaps there should be a &amp;quot;ranged unit&amp;quot; bonus, an &amp;quot;artillery unit&amp;quot; bonus and maybe a &amp;quot;cavalry&amp;quot; bonus which should all impact the legion&#039;s attack value.  It&#039;s looking like we might end up demanding that a scenario creator make a big complicated table in order to use this functionality, even if they only have simple needs.&lt;br /&gt;
&lt;br /&gt;
What we can do to alleviate this is to write a &amp;quot;simple&amp;quot; version of the event that is easy to use (and program), and also write a more complicated version that gives the expanded capability.&lt;br /&gt;
&lt;br /&gt;
Specification Table for simpleAttackBonus&lt;br /&gt;
&lt;br /&gt;
 --simpleAttackBonusTable[activeUnit.type.id] ={[bonusUnitType.id]=bonusNumber}&lt;br /&gt;
 --simpleAttackBonusTable.type = string&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- if simpleAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- if simpleAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 --simpleAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise &lt;br /&gt;
&lt;br /&gt;
The relevant first draft of the code is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function simpleAttackBonus(activeUnit,simpleAttackBonusTable,defaultAttackTable)&lt;br /&gt;
     -- reset all unit attack values&lt;br /&gt;
     for unitTypeID,attackValue in pairs(defaultAttackTable) do&lt;br /&gt;
         civ.getUnitType(unitTypeID).attack = attackValue&lt;br /&gt;
     end&lt;br /&gt;
     local unitBonusTable = simpleAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
     if not unitBonusTable then&lt;br /&gt;
         -- unitBonusTable is nil (or false), so the active unit can&#039;t&lt;br /&gt;
         -- get a bonus&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
     -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
     for unit in activeUnit.location.units do&lt;br /&gt;
         if unitBonusTable[unit.type.id] and unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
             bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     if bestBonusSoFar == 0 then&lt;br /&gt;
         -- If no bonus unit is found, this will be true, so do nothing else&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- set the new attack and return&lt;br /&gt;
     if string.lower(simpleAttackBonusTable.type) == &amp;quot;addBonus&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = activeUnit.type.attack+bestBonusSoFar&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     local attackMultiplier = 1&lt;br /&gt;
     if type(simpleAttackBonusTable.type) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = (100+bestBonusSoFar)/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
         attackMultiplier = 1+bestBonusSoFar&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar&lt;br /&gt;
     else&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     end&lt;br /&gt;
     -- apply the bonus and round as appropriate&lt;br /&gt;
     if type(simpleAttackBonusTable.round) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;up&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.ceil(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;down&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     else&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now let us go over this section by section.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-07-AttackBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The first thing we do is to reset all the attack values of all the unit types.  That way, if a bonus existed for the last unit activated, that bonus no longer applies.  If a unit type is not in the defaultAttackTable, then we don&#039;t have the information to reset the attack value anyway, so we can safely ignore it by using the pairs function to iterate over the table.&lt;br /&gt;
&lt;br /&gt;
Now, we must find out if the newly activated unit deserves a bonus.  For that, we get the table associated with the active unit&#039;s type.  If the value is nil instead of a table, then the unit&#039;s type is not in the simpleAttackBonusTable, so there is no bonus to apply and the function returns.&lt;br /&gt;
&lt;br /&gt;
If the unit is eligible for bonuses, we then check the units in the square to see if any bonuses actually apply.  We&#039;ve seen this kind of code before.  If the unit in the stack can provide a bonus, and that bonus is better than the best bonus already found, the unit now provides the best bonus.  All bonus types that we can have are better if they are larger, and we are not comparing between bonus types, so a simple numerical comparison will do.  All bonuses are larger than 0 in our formulation, so 0 is a good starting value in the search.&lt;br /&gt;
&lt;br /&gt;
If the best bonus so far is still 0, there is no bonus, so the function can return.&lt;br /&gt;
&lt;br /&gt;
At this point, it occurs to me that when searching for the best bonus, we should exclude the active unit from the search.  That way, you can have a &amp;quot;strength in numbers&amp;quot; bonus, for example.  The relevant change to the code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    for unit in activeUnit.location.units do&lt;br /&gt;
        if unit ~= activeUnit and unitBonusTable[unit.type.id] and &lt;br /&gt;
 			unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, consider&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-08-AttackBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we apply the bonus that we&#039;ve found.  We use string.lower on simpleAttackBonusTable.type so that we don&#039;t have to worry about capitalization.  That does, however, require a correction to &amp;quot;addBonus&amp;quot;, since a lower case string will never be equal to that.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;addbonus&amp;quot; is the only type of bonus that is directly added to the existing attack value.  All other bonus types are a form of multiplication.  Since the addition is straightforward and doesn&#039;t require any rounding, the activeUnit&#039;s type attack value can be changed immediately, and the function execution ended with return.&lt;br /&gt;
&lt;br /&gt;
When there is only one bonus being applied, all other types of bonus are different ways of expressing how to multiply the existing attack value to get a new one, so we simply convert to the appropriate multiplier, and provide an error message if the type of bonus is not one of the valid possibilities.&lt;br /&gt;
&lt;br /&gt;
Finally, we round the attack value to an appropriate integer (since unit attack values must be integers), change the attack value of the active unit&#039;s type, and return to end the function execution.&lt;br /&gt;
&lt;br /&gt;
Now, we integrate into events.lua by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus = require(&amp;quot;attackBonus&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The relevant integration code for events.lua is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local defaultAttackValueTable = {[unitAliases.legion.id]=4}&lt;br /&gt;
 local simpleAttackBonusTable ={}&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=3,[unitAliases.musketeer.id]=4}&lt;br /&gt;
 &lt;br /&gt;
 local function doOnActivation(unit,source)&lt;br /&gt;
     munitions.payloadRestrictionCheck(unit,munitionSpecificationTable)&lt;br /&gt;
 	attackBonus.simpleAttackBonus(unit,simpleAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can check that the bonus is being applied correctly by checking the Civlopedia entry for legion and looking at the attack value.  The following cases must be tested (remember that activating a unit from the city screen doesn&#039;t run the onActivation event, so activate from the map).&lt;br /&gt;
&lt;br /&gt;
 Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
 Legion activated with archer, but no musketeer (7 attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (8 attack)&lt;br /&gt;
 Legion activated with archer and musketeer (8 attack)&lt;br /&gt;
 Legion activated with 2 archer, no musketeer (7 attack)&lt;br /&gt;
 Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
 Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
I recommend making a stack for each of these cases and activating them one by one.&lt;br /&gt;
To facilitate the test, add the following line to doOnActivation&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.ui.text(tostring(unit.type.attack))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You will want to comment out this line after testing.&lt;br /&gt;
&lt;br /&gt;
Next, change simpleAttackBonusTable to do &amp;quot;addpercent&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=30,[unitAliases.musketeer.id]=70}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With no rounding set, standard rounding is used&lt;br /&gt;
 Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
 Legion activated with archer and musketeer (7 attack)&lt;br /&gt;
 Legion activated with 2 archer, no musketeer (5 attack)&lt;br /&gt;
 Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
 Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
These numbers test both rounding up and rounding down.&lt;br /&gt;
&lt;br /&gt;
Now, use&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (6 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next,&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (6 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;standard&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next, we test &amp;quot;addfraction&amp;quot;.  Since we&#039;ve tested all the rounding options, we don&#039;t have to do that again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=0.3,[unitAliases.musketeer.id]=0.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=130,[unitAliases.musketeer.id]=170}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiply&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Before we finish, we should test a legion bonus for the legion.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.legion.id]=2,[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Legion alone should have 4 attack.&lt;br /&gt;
 A second legion on the square should provide 8 attack instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, let us try to formulate a more complicated bonus system.  One thing we mentioned is that we&#039;d like the ability to get bonuses from multiple units, and to be able to get bonuses from different &amp;quot;classes&amp;quot; of units (like &amp;quot;artillery,&amp;quot; &amp;quot;cavalry,&amp;quot; and &amp;quot;ranged attackers.&amp;quot;  Something else we might want to do is to allow different kinds of bonuses.  That is, maybe some units should provide a fixed +2 to any unit receiving the bonus, so that it is better at improving units with a low attack value, while other units should provide a percentage bonus (making them better at supporting units with an already high attack value).  It turns out that both of these ideas are not too difficult to implement individually, but that trying to implement them together makes it problematic to find the best bonus.&lt;br /&gt;
&lt;br /&gt;
Let us implement a bonus system with multiple categories but only one bonus type.  In our specification, we will first specify a data type called &amp;quot;bonusCategory.&amp;quot;  It is still just a table (though we could add a metatable if we wanted), but it will help us make our specification clearer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- A &amp;quot;bonusCategory&amp;quot; is a table&lt;br /&gt;
 -- bonusCategory = {[bonusUnitType.id]=bonusNumber, maxBonusUnits=integer or nil, nextBonusValue = fraction or nil}&lt;br /&gt;
 -- In a bonusCategory, the value for bonusUnitType.id tells what the base bonus for that unit type is,&lt;br /&gt;
 -- maxBonusUnits is the maximum number of units that can provide a bonus in this category,&lt;br /&gt;
 -- nextBonusValue tells how much to reduce the bonus for each subsequent unit,&lt;br /&gt;
 -- e.g. nextBonusValue = 0.7, and 5 units, which each have a bonusNumber=1&lt;br /&gt;
 -- The total bonus is 1(0.7)^0+.7+(.7)(.7)+(.7)^3+(.7)^4 = 1+.7+.49+.343+.2401=2.7731&lt;br /&gt;
 -- (which would be rounded as specified)&lt;br /&gt;
 -- nil means nextBonusValue=1&lt;br /&gt;
 --&lt;br /&gt;
 -- If a unit type is in two bonus categories for the same unit, there is no guarantee that the&lt;br /&gt;
 -- best bonus will be achieved&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, the bonus category is indexed by unitType id numbers for units that can give a bonus, and the corresponding bonus.  It also specifies the maximum number of units that can give a bonus, and a number that governs how to reduce a bonus for extra units.  That way, there can be diminishing returns for bonuses.&lt;br /&gt;
&lt;br /&gt;
Next, we look at the specification for the categoryAttackBonusTable&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 --categoryAttackBonusTable[activeUnit.type.id] =table of bonusCategory&lt;br /&gt;
 --categoryAttackBonusTable.type = string&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up all the percents, then compute the bonus&lt;br /&gt;
 -- i.e. 50% bonus and 50% bonus is 100% bonus, not 125%&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 50% bonus units become 50% + 25% &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up the fractions, then compute the bonus&lt;br /&gt;
 -- i.e. .5 bonus and .5 bonus is 1+.5+.5= 2x bonus, not 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 .5 bonus units become .5+.25 &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 150% and 150% yields 225% of original value&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 100, i.e. nextBonusValue=.5 2 150% bonuses become 150% and 125%&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 1.5 and 1.5 yields 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 1, i.e. nextBonusValue=.5 and two 1.5 bonuses become 1.5 and 1.25&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 --categoryAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise&lt;br /&gt;
 &lt;br /&gt;
 -- If the active unit can get a bonus, go through each category and compute the bonus for that category.&lt;br /&gt;
 -- Then, combine the bonuses for all categories to get the overall bonus, and round the result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With the bonusCategory defined, the value of the unit indices of categoryAttackBonusTable become easy to define.  Most of the specification is showing what exactly the different bonus categories mean, so the end user can use them properly.  It&#039;s not strictly necessary to offer so many choices to the end user on how to specify data, but it can be more convenient.&lt;br /&gt;
&lt;br /&gt;
Here is the actual code (before testing) to implement this more general version of attack bonuses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- HELPER FUNCTION&lt;br /&gt;
 -- findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable) --&amp;gt; number or false&lt;br /&gt;
 -- usedUnitTable is indexed by the i.d. number of units, and if the value for a unit is true,&lt;br /&gt;
 -- then it has already been used for a bonus (and, so, is not eligible)&lt;br /&gt;
 -- The function returns the bonus (before nextBonusValue is applied) if there is one, and marks the &lt;br /&gt;
 -- unit as used in the usedUnitTable&lt;br /&gt;
 -- returns false if no unit qualifies&lt;br /&gt;
 local function findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable)&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
    local bestUnitSoFar = nil&lt;br /&gt;
    -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
    -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
    for unit in tile.units do&lt;br /&gt;
        if not usedUnitTable[unit.id] and bonusCategory[unit.type.id] &lt;br /&gt;
            and bonusCategory[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestUnitSoFar = unit&lt;br /&gt;
            bestBonusSoFar = bonusCategory[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if bestUnitSoFar then&lt;br /&gt;
        usedUnitTable[bestUnitSoFar.id] = true&lt;br /&gt;
        return bestBonusSoFar&lt;br /&gt;
    else&lt;br /&gt;
        return false&lt;br /&gt;
    end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 -- HELPER FUNCTION&lt;br /&gt;
 -- computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
 -- Computes the bonus that the active unit will receive from this category, taking into &lt;br /&gt;
 -- account the type of bonus for the table&lt;br /&gt;
 local function computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local bonusThusFar = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then &lt;br /&gt;
        bonusThusFar = 1&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        bonusThusFar = 100&lt;br /&gt;
    else&lt;br /&gt;
        bonusThusFar = 0&lt;br /&gt;
    end&lt;br /&gt;
    local bonusDiscount = 1&lt;br /&gt;
    for i=1,(bonusCategory.maxBonusUnits or 10000) do&lt;br /&gt;
        local currentBonus =findBestBonusInUnitStack(activeUnit.location,bonusCategory,usedUnitTable) &lt;br /&gt;
        if not currentBonus then&lt;br /&gt;
            -- no more valid bonuses for this category&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
        if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-1)*bonusDiscount+1)&lt;br /&gt;
        elseif bonusType ==&amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
        else&lt;br /&gt;
            bonusThusFar = bonusThusFar+currentBonus*bonusDiscount&lt;br /&gt;
        end&lt;br /&gt;
        bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
    end&lt;br /&gt;
    return bonusThusFar&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 local function categoryAttackBonus(activeUnit,categoryAttackBonusTable,defaultAttackTable)&lt;br /&gt;
    local bonusInfoTable = categoryAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
    if not bonusInfoTable then&lt;br /&gt;
        -- unit doesn&#039;t get a bonus&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
    -- keep track of bonuses already computed&lt;br /&gt;
    local bonusResultsTable = {}&lt;br /&gt;
    -- keep track of units that have already been &amp;quot;used&amp;quot; for a bonus&lt;br /&gt;
    local usedUnitTable = {[activeUnit.id]=true}&lt;br /&gt;
    for index,bonusCategory in pairs(bonusInfoTable) do&lt;br /&gt;
        bonusResultsTable[index]=computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    end&lt;br /&gt;
    -- compute the bonus&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local resultAttackBeforeRounding = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult/100&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack+bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+(bonusResult/100)&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    else&lt;br /&gt;
        error(&amp;quot;categoryAttackBonus: categoryAttackBonusTable.type is not a valid value.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    -- apply the bonus and round as appropriate&lt;br /&gt;
    local roundType = categoryAttackBonusTable.round&lt;br /&gt;
    if type(roundType) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;up&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.ceil(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;down&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    else&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two helper functions for computeCategoryBonus are only used once each in the code, so making them helper functions does not help us re-use code.  However, what it does do is to break down the function design process into smaller tasks, which are each more manageable to complete.  If you&#039;re trying to keep track of too many things in your program, try writing a few helper functions to handle individual tasks.  We&#039;ll look at the helper functions when we actually arrive at them in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-09-CategoryAtkBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If there is no entry in the categoryAttackBonusTable or the active unit&#039;s type, then the function returns without doing anything further.&lt;br /&gt;
&lt;br /&gt;
The bonusResultsTable keeps track of the total bonus from each category, so they can be added or multiplied together after all the category bonuses are applied.  The usedUnitsTable keeps track of units that are no longer eligible to contribute to a bonus (such as if they have already contributed), and we initialize it with the active unit, so that it doesn&#039;t provide a bonus to itself.&lt;br /&gt;
&lt;br /&gt;
The for loop computes the bonus for every category, and stores the value in the bonusResultsTable, for use later.Now, let us look at the helper functions.&lt;br /&gt;
&lt;br /&gt;
First up is findBestBonusInUnitStack&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-10-CategoryAtkBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This basically does what it says in the name.  For a bonusCategory, it finds the unit in the tile that provides the best bonus, and has not already provided a bonus elsewhere.  If there is no qualifying unit, false is returned.  If there is, that unit&#039;s bonus is returned, and the unit&#039;s id is entered into the usedUnitTable, so that unit can&#039;t provide another bonus for the active unit.  We&#039;ve searched for the best of something before, so there is little need to go over it again.&lt;br /&gt;
&lt;br /&gt;
Next is computeCategoryBonus&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-11-CategoryAtkBonus3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we&#039;re computing the bonus for the entire bonusCategory.  We need the bonus type in order to know what kind of math to do.  The math itself is not very interesting.  We also initialize the bonusDiscount, which keeps track of the fraction of the next unit&#039;s bonus that will actually be applied.&lt;br /&gt;
&lt;br /&gt;
Next, we enter a for loop that will run one time for each possible bonus that there can be in a bonus category.  If bonusCategory.maxBonusUnits is nil, then we set an arbitrary limit of 10000 units, which is very unlikely to happen in practice.&lt;br /&gt;
&lt;br /&gt;
At each iteration of the loop, the best available bonus in the stack is found.  If no unit was eligible to provide a bonus, then the current bonus is false, and the &amp;quot;break&amp;quot; command is issued.  Break immediately exits the current loop.  So, our program doesn&#039;t run 10000 loops if there is no maximum number of bonus units, it just breaks at an appropriate time.&lt;br /&gt;
&lt;br /&gt;
After the bonus is found, it is added to or multiplied with the bonus already found.  The bonus computed in this way will be the largest possible, since the bonus provided does not depend on the other units chosen (so we don&#039;t have a situation where &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; are both useless, but &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; chosen together are best).  Also, since the best bonus is chosen first, the smallest bonus discount applies to it, so the cost imposed by the discounting is smallest.&lt;br /&gt;
&lt;br /&gt;
Finally, we update the bonusDisount.  Here, I notice a problem in the code as written, since bonusCategory.nextBonusValue is allowed to be nil.  Replace&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
with &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*(bonusCategory.nextBonusValue or 1) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
so that if there is no nextBonusValue, a default of 1 is used, and the bonusDiscount stays at 1 (i.e. no discount is applied).&lt;br /&gt;
&lt;br /&gt;
We return to categoryAttackBonus to see&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-12-CategoryAtkBonus4.jpg]]&lt;br /&gt;
&lt;br /&gt;
From here, we combine the bonuses stored in bonusResultsTable, the exact way of doing so being dependant on the type of bonus involved.  The math itself isn&#039;t very interesting, and doesn&#039;t seem all that likely to come up in this exact form elsewhere.  If you need help with the mathematical details of some event you want to write, ask in the forums.  There&#039;s a good chance someone has the skills to help you solve your specific problem.&lt;br /&gt;
&lt;br /&gt;
For every type of bonus, the result is stored in resultAttackBeforeRounding, so that variable can be rounded up or down as specified by the rounding type.&lt;br /&gt;
&lt;br /&gt;
Here, I notice another error.  We should restrict the attack value for a unit to not exceed 98.  We can do that with a math.min(value, 98).&lt;br /&gt;
&lt;br /&gt;
Now, we need to test the various aspects of the attack bonus program, so we need an appropriate table&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addbonus&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=2,[unitAliases.chariot.id]=4,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=2,[unitAliases.musketeer.id]=4,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Also, comment out the old attack bonus line, and put in a new one&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus.categoryAttackBonus(unit,categoryAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
Already, we find a problem.  Although there were no syntax errors to fix, I forgot to reset unit attack values.  So, very quickly, the legions keep gathering extra attack values when they are activated (since the base attack is not reset to 4).  Since this is happening anyway, I&#039;ll test the 98 attack value maximum.  That appears to work, at least in the case of no specified rounding.&lt;br /&gt;
&lt;br /&gt;
Cut and paste the appropriate lines from the simpleAttackBonus to the categoryAttackBonus, and save.&lt;br /&gt;
&lt;br /&gt;
With that bug fixed, everything works as expected.&lt;br /&gt;
&lt;br /&gt;
Next, we change the categoryAttackBonusTable to &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addpercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=50,[unitAliases.chariot.id]=100,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=50,[unitAliases.musketeer.id]=100,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addpercent&amp;quot;.  These are the same, since adding we&#039;re adding percentages of the same base value of 4.  So a value of 2 is the same as adding 50% of 4.&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
The results are the same.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addfraction&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=.50,[unitAliases.chariot.id]=1.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.50,[unitAliases.musketeer.id]=1.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
We&#039;ll have to do some new calculations, now, since multiply and multiplyfraction give different results than the various adding formulations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiply&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=1.50,[unitAliases.chariot.id]=2.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=1.50,[unitAliases.musketeer.id]=2.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 12 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
 Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Finally, we use multiplyPercent, and check for the same results&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=150,[unitAliases.musketeer.id]=200,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 12 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
 Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Quickly, I find that if a bonus applies, that bonus makes the attack value of a legion 98.  I failed to multiply percents correctly in computeCategoryBonus.  The Line &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Is changed to &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+100)/100&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, Change archer bonus to 110 and musketeer bonus to 120 (so a unit will make a legion have 4.4 and 4.8 value before rounding), and test the rounding options.  You will find they all work.&lt;br /&gt;
&lt;br /&gt;
At the moment, we don&#039;t have a way to mix different types of bonuses.  As said earlier, we might want this so that some units can be better at giving bonuses to low attack units than to high attack units, while others give a percentage bonus to everything.  We could now write a bonus system that allows for multiple types of bonuses. However, the current bonus system allows for the bonus to change per unit.  This means that we can, for example, convert a +2 attack bonus to a plus 100% bonus for a unit with 2 attack, and a plus 50% bonus for a unit with 4 attack.  In the case of the multiplied bonuses, this will make the bonus more powerful if there is more than one.  That is, 2 attack, +2 twice is 6, but if +2 is changed to x2, then the multiplied bonus brings the attack up to 8.  However, this seems like it would be a relatively unlikely problem, and there are other things this code can&#039;t handle, so we&#039;ll let someone else make the code if they actually need it.&lt;br /&gt;
&lt;br /&gt;
So, what we&#039;ll do is write a function that will change all appropriate entries in the categoryAttackBonusTable to reflect a different value.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed(unitType,number,categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unit type to any unit to be equivalent&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, an issue with tables arises.  It is very likely that when someone defines their cateogryAttackBonusTable, they&#039;ll define it something like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.25,[unitAliases.musketeer.id]=.5}&lt;br /&gt;
 local bonusTableForInfantry = {rangeBonusCategory}&lt;br /&gt;
 local cABT = {type=&amp;quot;addfraction&amp;quot;}&lt;br /&gt;
 cABT[unitAliases.phalanx.id]=bonusTableForInfantry&lt;br /&gt;
 cABT[unitAliases.legion.id] = bonusTableForInfantry&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
However, this means that both &amp;lt;code&amp;gt; cABT[unitAliases.legion.id]  &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt; cABT[unitAliases.phalanx.id] &amp;lt;/code&amp;gt; actually refer to the same piece of memory, and changing cABT[unitAliases.legion.id][1][unitAliases.archer.id] will also change the value at cABT[unitAliases.phalanx.id][1][unitAliases.archer.id].  This is because of the way lua tables are designed.  This design can be useful, for example it allowed us to make changes to usedUnitsTable in the last function without having to copy the table, make changes to the copy of the table, and then replace the original table with that copy as a return value.  However, it also requires us to be careful when we make changes to entries in tables.  In this case, we&#039;ll simply copy the table and all its sub values into a new table.&lt;br /&gt;
&lt;br /&gt;
The code to do this is given by&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will explain this code in the next section, since it involves a programming technique which we haven&#039;t discussed before.&lt;br /&gt;
&lt;br /&gt;
For now, we analyze plusFixed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed({[unitType1.id]=fixedBonus,[unitType2.id]=fixedBonus},categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unitTypeI.id to a unit to be equivalent to&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power.  If the unit doesn&#039;t receive a bonus&lt;br /&gt;
 -- from the unitType, then it won&#039;t after applying plusFixed.&lt;br /&gt;
 -- The value of the existing bonus is ignored.&lt;br /&gt;
 &lt;br /&gt;
 local function plusFixed(fixedUnitBonusTable,categoryAttackBonusTable)&lt;br /&gt;
     local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
     for bonusReceivingUnitTypeID,bonusTable in pairs(categoryAttackBonusTable) do&lt;br /&gt;
         -- replace bonusTable with an equivalent table that is not referened&lt;br /&gt;
         -- anywhere else, so that changes to it can be made without impacting&lt;br /&gt;
         -- data elsewhere&lt;br /&gt;
         categoryAttackBonusTable[bonusReceivingUnitTypeID] = duplicateTable(bonusTable)&lt;br /&gt;
         -- make bonusTable refer to the &amp;quot;current&amp;quot; bonus table for the unit type&lt;br /&gt;
         bonusTable =categoryAttackBonusTable[bonusReceivingUnitTypeID] &lt;br /&gt;
         -- For each unit type in the fixedUnitBonusTable, check if any bonus category&lt;br /&gt;
         -- in the bonusTable corresponds to it.  If so, make the change&lt;br /&gt;
         for bonusGivingUnitTypeID,fixedBonusValue in pairs(fixedUnitBonusTable) do&lt;br /&gt;
             -- get the attack of the unit type &lt;br /&gt;
             local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
             -- in each bonus category, check if the giver&#039;s unit type id is there,&lt;br /&gt;
             -- if so, change to the correct attack&lt;br /&gt;
             for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
                 if bonusCategory[bonusGivingUnitTypeID] then&lt;br /&gt;
                 -- change the bonus appropriately&lt;br /&gt;
                     if bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue&lt;br /&gt;
                     elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*(fixedBonusValue+baseAttack)/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=(fixedBonusValue+baseAttack)/baseAttach&lt;br /&gt;
                     else&lt;br /&gt;
                         error(&amp;quot;pluxFixed: categoryAttackBonusTable.type does not have an acceptable value.&amp;quot;)&lt;br /&gt;
                     end&lt;br /&gt;
                 end&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-13-plusFixed1.jpg]]&lt;br /&gt;
&lt;br /&gt;
As before, we save the bonusType in lower case, since we&#039;ll be using it a lot later.  Next, we open a for loop, where the index is the id of the unit type receiving the bonus, and the value is the bonus table for that unit type.  Next, we duplicate the bonus table, so that we have a table we can change without impacting anything elsewhere, and we store the duplicated table in categoryAttackBonusTable in place of the original bonusTable for the current bonus receiving unit id.  Next, we assign this duplicated table to the variable bonusTable, so we can refer to it later in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-14-plusFixed2.jpg]]&lt;br /&gt;
&lt;br /&gt;
We now perform the following actions for each unitType.id and corresponding fixedBonusValue submitted in the fixedUnitBonusTable.&lt;br /&gt;
&lt;br /&gt;
First, get the attack of the bonus receiving unit, since we&#039;ll need that in order to customize the bonus.  Next, check each bonus category in the bonus table.  If the bonus category has the current unitTypeID as a key, then replace the existing value with a bonus equivalent to adding a fixed value to the receiving unit&#039;s attack.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all that must be done, so end all the loops.&lt;br /&gt;
&lt;br /&gt;
Now we test the function.&lt;br /&gt;
&lt;br /&gt;
Add unitAliases.phalanx = civ.getUnitType(3) to the appropriate file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 defaultAttackValueTable[unitAliases.phalanx.id]=1&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,&lt;br /&gt;
 								nextBonusValue=0.5,maxBonusUnits=1}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=125,[unitAliases.musketeer.id]=150,&lt;br /&gt;
 								nextBonusValue=0.75,maxBonusUnits=1}&lt;br /&gt;
 local standardBonus = {cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.phalanx.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 attackBonus.plusFixed({[unitAliases.chariot.id]=2,[unitAliases.musketeer.id]=2},&lt;br /&gt;
 						categoryAttackBonusTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The chariot and the musketeer individually should each add 2 to both a phalanx and a legion,&lt;br /&gt;
so the phalanx should have an attack of 3, and the legion should have an attack of 6, if one bonus&lt;br /&gt;
is applied.&lt;br /&gt;
&lt;br /&gt;
Since the bonus type is multiplypercent, together the phalanx would have an attack of 9, and the legion will also have an attack of 9.&lt;br /&gt;
&lt;br /&gt;
In testing, we quickly get this error&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
You should see this in lua console if this worked&lt;br /&gt;
...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: bad argument #1 to &#039;getUnitType&#039; (number expected, got string)&lt;br /&gt;
stack traceback:&lt;br /&gt;
	[C]: in function &#039;civ.getUnitType&#039;&lt;br /&gt;
	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At line 356, which is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This must mean that bonusReceivingUnitTypeID is not a number.  This is because we&#039;re looping over categoryAttackBonusTable, and that table has a couple of entries that are not integers (&amp;quot;type&amp;quot; and &amp;quot;round&amp;quot;).  Therefore, we have to insert code to deal with this eventuality.&lt;br /&gt;
&lt;br /&gt;
The simplest way is to put everything in the loop body into an if statement, so that it only runs when bonusGivingUnitTypeID is actually a number.  You should be able to do this without detailed instructions, so do so (hint: use type function).&lt;br /&gt;
&lt;br /&gt;
The next error is &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: bad argument #1 to &#039;pairs&#039; (table expected, got nil)&lt;br /&gt;
 stack traceback:&lt;br /&gt;
 	[C]: in function &#039;pairs&#039;&lt;br /&gt;
 	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
 	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 360 for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we have a nil value for bonusTable.  This turns out to be an error in duplicateTable.  When I duplicated the table, I forgot to return that table.  That is, both the if and else statement in that function need a return command, and I forgot to add &amp;lt;code&amp;gt; return duplicatedTable &amp;lt;/code&amp;gt; in the if portion.  Add this to the duplicate table function.&lt;br /&gt;
&lt;br /&gt;
After this, our predictions are true.  Testing the other types of bonus is left as an assignment.  You can find the completed code [https://forums.civfanatics.com/threads/totpp-attack-bonus-library.648093/ here].&lt;br /&gt;
&lt;br /&gt;
===Recursive Functions===&lt;br /&gt;
&lt;br /&gt;
Let us return to the duplicateTable function.  Recall that in the last section we added a line to it, so we&#039;ll restate it here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
 		return duplicatedTable&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-16-duplicateTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
The interesting thing about duplicateTable is that it invokes duplicateTable within its code.  When we copy the key-value pairs into the new table, we run duplicateTable on the value.  If the value is not a table, then we are in the else case, and the value is immediately returned to be inserted into the duplicated table.  If the value is a table, that table is duplicated before anything else is done.&lt;br /&gt;
&lt;br /&gt;
Let us look at a simple example of a recursive function, the factorial function N!.  In lesson 3, we discussed the factorial function in the context of loops.  Since N!=N*(N-1)*(N-2)*...*3*2*1, we can give another definition of N!:&lt;br /&gt;
 N!=1 if N = 1&lt;br /&gt;
 N!=N*(N-1)! if N &amp;gt; 1&lt;br /&gt;
Or, using the convention that 0!=1, we can state&lt;br /&gt;
 N!=1 if N = 0&lt;br /&gt;
 N!=N*(N-1)! if N &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
The case where N =1 or N=0 is called the &amp;quot;base case.&amp;quot;  If we keep substituting N! as N*(N-1)!, then we won&#039;t go on forever, because we will eventually reach a point where N=0, and N! can be substituted as 1 instead of N*(N-1)!.  As long as there is a base case, our program will eventually reach the base case(s), and begin &amp;quot;completing&amp;quot; evaluation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function factorial(N)&lt;br /&gt;
 if N&amp;gt;0 then&lt;br /&gt;
     return N*factorial(N-1)&lt;br /&gt;
 else&lt;br /&gt;
     return 1&lt;br /&gt;
 end&lt;br /&gt;
 end&lt;br /&gt;
 print(factorial(5))&lt;br /&gt;
 print(factorial(6))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run this in code in the lua demo website, or using the TOTPP lua interpreter.&lt;br /&gt;
&lt;br /&gt;
Returning to our duplicateTable function, the base case is any time a table value is not itself a table.  When that happens, the recursion &amp;quot;chain&amp;quot; ends, and everything can evaluated.&lt;br /&gt;
&lt;br /&gt;
Although is shouldn&#039;t be a problem in this particular case, it should be noted that it is possible for there to not be a &amp;quot;base case&amp;quot; in the recursion style: if table, recur, if not return a value.  Consider the following table system&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 a={}&lt;br /&gt;
 b={[1]=a}&lt;br /&gt;
 a[1]=b&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In this case, the code would never end.&lt;br /&gt;
&lt;br /&gt;
It is possible that even if the code could &amp;quot;theoretically&amp;quot; execute to completion, you run out of memory before that.  This is called a &amp;quot;stack overflow,&amp;quot; and if it occurs, you will have to think of an alternate way to solve your problem.  It will probably be best to ask for help in that case (and it might be useful to provide others with an example of a problem that results in a stack overflow), but you might also look into &amp;quot;tail recursion&amp;quot;, including http://www.lua.org/pil/6.3.html .&lt;br /&gt;
&lt;br /&gt;
===Conclusion===&lt;br /&gt;
&lt;br /&gt;
With the skills covered in this chapter, you now have the tools to split a large events file into multiple files that are more manageable.  You also have the basics for how to write re-useable modules for your events, so that your work can be used by others.  Remember that if someone else uses your implementation of a feature, they will spend much less time coding and testing it, allowing them to either finish the scenario sooner, or to introduce some other feature.  So, it might very well pay to spend at least a little effort making your code into a reusable module.  Perhaps you have an idea for a cool scenario mechanic, but don&#039;t have a scenario for it (or don&#039;t want to take the time to make it).  If that&#039;s the case, just make the module and test it in a &amp;quot;toy&amp;quot; scenario (like Classic Rome) so that it can be used more or less &amp;quot;off the shelf&amp;quot; when someone needs it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5183</id>
		<title>Get Started With Lua Events Lesson 6: Splitting Code into Multiple Files</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5183"/>
		<updated>2019-07-26T15:16:05Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* Recursive Functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This Lesson is under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
In this lesson, we will take a look at how to split the code for a scenario&#039;s events into multiple files.  There are several reasons to consider doing this.&lt;br /&gt;
&lt;br /&gt;
The first reason is simply to organize your work.  If you have a series of complicated events, the events.lua file can become very large very quickly. Once your events.lua file has thousands of lines of code in it, it may not be very obvious where the best place is to put that next helper function, or where to implement the function that runs a complicated event.  Sometimes even finding the piece of code that has to be changed can be a bit of a hassle.  In Over the Reich, I sometimes search for the associated civ.scen line, and then search for the exact name of the function I need.  Occasionally, there may even be more searching to find what I actually have to change.  With multiple files, it becomes easier to find things.&lt;br /&gt;
&lt;br /&gt;
Another aspect of using multiple files is that you can make certain changes without worrying about breaking things elsewhere.  If myBigComplicatedFunction relies on aModestHelperFunction for a certain part of its functionality, and a change to myBigComplicatedFunction also requires a change to aModestHelperFunction, you have to make sure that nothing else in your code also uses aModestHelperFunction, or, if something else does depend on it, that aModestHelperFunction either still provides the original functionality, or that all other functions that use aModestHelperFunction are suitably modified.  If myBigComplicatedFunction is defined in its own lua module, then you don&#039;t have to worry about forgetting that aModestHelperFunction was used elsewhere, since it can&#039;t be accessed outside the module unless you specifically allow it to be.&lt;br /&gt;
&lt;br /&gt;
A second reason to split events code into multiple files is to facilitate collaboration.  If all of the events are in a single file, then only one person can make changes to the file at a time.  If one partner starts changing an event, but has to do something else before finishing, everyone waits on one person&#039;s delay.  However, if most aspects of the scenario are separated into individual files, everyone can work on his or her own piece of the puzzle without depriving others of the opportunity to work at that time.&lt;br /&gt;
&lt;br /&gt;
A third reason to split events into multiple modules is to facilitate reusing code.  If everything required to implement an event is in its own file (or files), it becomes much easier for other creators to use your functionality in their scenario.  Since everything they need is already in one place, they don&#039;t have to find every last helper function, or concern themselves with naming conflicts.&lt;br /&gt;
&lt;br /&gt;
===Two Simple Examples===&lt;br /&gt;
&lt;br /&gt;
Let us look at the top of the events.lua file.  You can get the version that I started lesson 6 with [[here]].&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-01-DefaultRequire.jpg]]&lt;br /&gt;
&lt;br /&gt;
We get code from other files by using the command &amp;lt;code&amp;gt;require&amp;lt;/code&amp;gt; along with a string specifying the file name (except for the .lua extension).  At the moment, we can only get code stored in the lua folder in the Test of Time directory.  This is inconvenient if we&#039;re trying to distribute a scenario, since installing a scenario would require moving certain files to the lua directory, and those file names might conflict.  Instead, we need to tell the Lua interpreter to search in the same folder that the events.lua folder is in.&lt;br /&gt;
&lt;br /&gt;
To do this, we need the following code:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local eventsPath = string.gsub(debug.getinfo(1).source, &amp;quot;@&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 local scenarioFolderPath = string.gsub(eventsPath, &amp;quot;events.lua&amp;quot;, &amp;quot;?.lua&amp;quot;)&lt;br /&gt;
 if string.find(package.path, scenarioFolderPath, 1, true) == nil then&lt;br /&gt;
    package.path = package.path .. &amp;quot;;&amp;quot; .. scenarioFolderPath&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can probably cut and paste this code before the require lines in your events.lua file and not worry about how it works.  However, I&#039;ll provide a brief explanation for reference.&lt;br /&gt;
&lt;br /&gt;
The first line stores the location of the of the current file as a string in eventsPath.&lt;br /&gt;
&lt;br /&gt;
The second line replaces events.lua in the eventsPath with ?.lua, which will tell the Lua interpreter to look for .lua files in the current directory (that is to say, the directory with the events.lua file).  &lt;br /&gt;
&lt;br /&gt;
The if statement adds scenarioFolderPath to the places for the Lua interpreter to search for code, if that directory is not already in the search path.  Since the search path is kept active by the Lua interpreter, it will not be necessary to repeat these lines of code in every file that performs a require action as long as you are running the file as part of events.  If you are writing some other kind of code, you will need to substitute &amp;quot;events.lua&amp;quot; with the name of the file with the code you are running.  Note that for some reason, events.lua is always provided in lower case.  However, for use in other situations, debug.getinfo(1).source uses the correct case for event files. I have only briefly tested this, so you may have to do some testing yourself if this situation comes up (or ask for help in the forums).&lt;br /&gt;
&lt;br /&gt;
Now that we&#039;ve told Lua where to look for our extra code, we can begin moving code to other files.  Think of require as telling Lua to run the entire contents of another file as a function.  We can then assign a value to whatever that file returns, which will usually be a table.  A couple of examples will clarify.&lt;br /&gt;
&lt;br /&gt;
For our first example, we will move our scenario&#039;s parameters to a separate file, and access it via require.  This may not seem worthwhile in this example, but tables like this can get large in a hurry.  At the time of writing, Over the Reich has over 100 lines of parameters (&amp;quot;specialNumbers&amp;quot;), and parameters are something that a designer might like to play with while collaborators make other implementations.  Also, parameters will have to be referenced by other parts of the code, and a file that is required by events.lua cannot, in turn, require events.lua in order to get information.  That means that we&#039;ll have to keep our parameters in a separate file anyway.&lt;br /&gt;
&lt;br /&gt;
Cut the parameters table definition and paste it into a new file, classicRomeParameters.lua.  For the last line, write&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return parameters&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, Near the top of events.lua, where the existing require lines are, add the eventsPath code from above and also the line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local parameters = require(&amp;quot;classicRomeParameters&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
[[File:GetStartedWithLuaLesson6-02-RequireParameters.jpg]]&lt;br /&gt;
&lt;br /&gt;
Open the classicRome scenario and test out a couple of events to make sure everything is the same.&lt;br /&gt;
&lt;br /&gt;
We might find it convenient to put a few tables into the same file.  For this, we will simply return a table containing these tables, and give each table a name in the events.lua file.&lt;br /&gt;
&lt;br /&gt;
Create a file classicRomeAliases.lua and move all the &amp;quot;aliases&amp;quot; tables to that file.  Also move the getCityAt function.&lt;br /&gt;
&lt;br /&gt;
At the bottom of the file, put the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 unitAliases=unitAliases,&lt;br /&gt;
 tribeAliases=tribeAliases,&lt;br /&gt;
 tileAliases=tileAliases,&lt;br /&gt;
 cityAliases=cityAliases,&lt;br /&gt;
 textAliases=textAliases,&lt;br /&gt;
 terrainAliases=terrainAliases,&lt;br /&gt;
 improvementAliases=improvementAliases,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following lines to events.lua (in the require section)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local aliases = require(&amp;quot;classicRomeAliases&amp;quot;)&lt;br /&gt;
 local unitAliases,tribeAliases,tileAliases,cityAliases,textAliases,&lt;br /&gt;
 		terrainAliases,improvementAliases=aliases.unitAliases,aliases.tribeAliases,&lt;br /&gt;
 		aliases.tileAliases,aliases.cityAliases, aliases.textAliases,aliases.terrainAliases,&lt;br /&gt;
 		aliases.improvementAliases&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, our classicRomeAliases module is returning a table with our &amp;quot;alias&amp;quot; tables.  We then assign the entries in this returned table to local variables with the desired names.  Here, I use multiple variable assignment, which I don&#039;t believe I&#039;ve used before (even though Lua allows it), but these could just as simply have been assigned line by line.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-03-RequireAliases.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now, let us move the legion plundering code into its own file, which we&#039;ll call plunder.lua.  First, copy over the legionPlunder function, and paste it near the bottom of the new file.&lt;br /&gt;
&lt;br /&gt;
Now, let us go through the code of this function, and figure out what else we need in our plunder.lua module.&lt;br /&gt;
&lt;br /&gt;
The very first part of the function is a check against unitAliases.legion.  This means we need the unitAliases table, and so we copy the aliases require code to the top of plunder.lua.  We don&#039;t need the path information, since that will be added in events.lua.&lt;br /&gt;
&lt;br /&gt;
A few more lines down, we find that the function cityRadius is also used in legionPlunder.  Therefore, we move that over as well.  We also need the plunderValue function, so copy that over as well.&lt;br /&gt;
&lt;br /&gt;
Next, we check if cityRadius relies on anything, but it doesn&#039;t.&lt;br /&gt;
&lt;br /&gt;
Proceeding to plunderValue, we find that it relies on the parameters table, so require that as well.  The function plunderValue does not appear to depend on anything else, so we&#039;re done moving functionality.  If we missed something, the Lua interpreter will complain at some point anyway.&lt;br /&gt;
&lt;br /&gt;
Next, we require the plunder module in events.lua, with the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local plunder = require(&amp;quot;plunder&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, for each of the functions in plunder.lua, we check if it is used somewhere in events.lua.  We can do this by searching.  plunderValue isn&#039;t used anywhere, so we&#039;re done with that.  City radius is used.  At the bottom of plunder.lua, we begin our return table, and have&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 cityRadius=cityRadius,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, in events.lua, we replace the ocurance of cityRadius with plunder.cityRadius.  Alternatively, we could have put &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local cityRadius=plunder.cityRadius&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
after the line requiring plunder.&lt;br /&gt;
&lt;br /&gt;
Similarly, for legionPlunder, we add &amp;lt;code&amp;gt;legionPlunder=legionPlunder&amp;lt;/code&amp;gt; to the table that plunder.lua returns, and pre-append plunder. to legionPlunder in the one location where it occurs.&lt;br /&gt;
&lt;br /&gt;
Now, we test the legion plunder function and the press 4 generate archers function to make sure everything works.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-04-RequirePlunder.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Working With a Library===&lt;br /&gt;
&lt;br /&gt;
In programming terms, a &amp;quot;library&amp;quot; is a collection of code that can provide some specified functionality to a programmer without that programmer having to modify the code in the library.  Thus far, you have been using the &amp;quot;civ&amp;quot; library to interact with the game, and there has been no need modify it in order to use it in our own events.  (Unfortunately, in the case of the civ library, we don&#039;t actually know how to modify it.)  This is in contrast to much of the code we have written thus far.  For example, the code we wrote last lesson to make Selucid elephants attack Egypt is highly specific.  You couldn&#039;t just cut and paste that code, change the argument of a single function, and get your own goto event.  It is still a good example for how to write a goto event, but a user would still have to actually write the event.&lt;br /&gt;
&lt;br /&gt;
If you plan to write some functionality for your scenario that others might find useful, it is worth spending a little extra effort to see if you can write that functionality in a form that will allow others to use it with minimal effort.  If you can, then a little extra work on your part might save someone else the trouble of re-inventing the wheel, and allow them to complete their project sooner, or to work on some new feature for you to enjoy.  Unfortunately, the Lua scenarios that have been completed at the time of writing haven&#039;t been that good at creating re-usable code, at least in part since we were all getting used to Lua.  This will hopefully be improved in the future.&lt;br /&gt;
&lt;br /&gt;
For now, we&#039;re going to look at a library which is called the General Library (unless someone comes up with a better name) and which can be found [https://forums.civfanatics.com/threads/totpp-the-general-library.647583/ here].  The purpose of this module is to provide relatively simple functionality that probably shouldn&#039;t be implemented every time it is needed.  This is useful for our purposes, since we can look at relatively self contained and simple functions for our first examples.  We&#039;ll create a library for generating munitions later.&lt;br /&gt;
&lt;br /&gt;
This library would be used by invoking the line &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local gen = require(&amp;quot;generalLibrary&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to make these functions available to the console for testing purposes, you would simply omit the local, thereby making gen a global variable.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at a function provided by the General Library &amp;lt;code&amp;gt; gen.hasIrrigation(tile)--&amp;gt;boolean&amp;lt;/code&amp;gt;.  The very first line references the helper function &amp;lt;code&amp;gt; toTile(tile or table)--&amp;gt;tile&amp;lt;/code&amp;gt;, so let us include that code, and look at it first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 -- toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- gen.toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- If given a tile object, returns the tile&lt;br /&gt;
 -- If given coordinates for a tile, returns the tile&lt;br /&gt;
 -- Causes error otherwise&lt;br /&gt;
 -- Helper Function (provided to this library as toTile and gen.toTile)&lt;br /&gt;
 local function toTile(input)&lt;br /&gt;
     if civ.isTile(input) then&lt;br /&gt;
         return input&lt;br /&gt;
     elseif type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         local xVal = input[1] or input[&amp;quot;x&amp;quot;]&lt;br /&gt;
         local yVal = input[2] or input[&amp;quot;y&amp;quot;]&lt;br /&gt;
         local zVal = input[3] or input[&amp;quot;z&amp;quot;] or 0&lt;br /&gt;
         if type(xVal)==&amp;quot;number&amp;quot; and type(yVal)==&amp;quot;number&amp;quot; and type(zVal)==&amp;quot;number&amp;quot; then&lt;br /&gt;
             if civ.getTile(xVal,yVal,zVal) then&lt;br /&gt;
                 return civ.getTile(xVal,yVal,zVal)&lt;br /&gt;
             else&lt;br /&gt;
                 error(&amp;quot;Table with values {&amp;quot;..tostring(xVal)..&amp;quot;,&amp;quot;..tostring(yVal)..&lt;br /&gt;
                         &amp;quot;,&amp;quot;..tostring(zVal)..&amp;quot;} does not correspond to a valid tile.&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
         else&lt;br /&gt;
             error(&amp;quot;Table did not correspond to tile coordinates&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;Did not receive a tile object or table of coordinates.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 gen.toTile = toTile&lt;br /&gt;
 &lt;br /&gt;
 -- gen.hasIrrigation(tile)--&amp;gt;boolean&lt;br /&gt;
 -- returns true if tile has irrigation but no farm&lt;br /&gt;
 -- returns false otherwise&lt;br /&gt;
 function gen.hasIrrigation(tile)&lt;br /&gt;
     tile = toTile(tile)&lt;br /&gt;
     local improvements = tile.improvements&lt;br /&gt;
     -- irrigation, but no mining, so not farmland&lt;br /&gt;
     if improvements &amp;amp; 0x04 == 0x04 and improvements &amp;amp; 0x08 == 0 then&lt;br /&gt;
         return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-05-HasIrrigation.jpg]]&lt;br /&gt;
&lt;br /&gt;
Let us begin by looking at the function &amp;lt;code&amp;gt;toTile&amp;lt;/code&amp;gt;.  The purpose of this function is to allow other functions to accept tile coordinates in a table instead of an actual tile object.  The function tries to be reasonably permissive in the coordinates it will accept, allowing both integer indices and lowercase string indices, and by assuming that a missing z value corresponds to map 0.  The function also tries to give reasonably helpful errors.&lt;br /&gt;
&lt;br /&gt;
This brings up something that should be considered when making reusable code: what to do if you don&#039;t get values you were expecting.  One option is to throw an error and bring up the Lua console.  This is good for scenario creators, so they know something is wrong, but not so great for end users because the error stops the rest of the event from happening, should the mistake slip through playtesting.&lt;br /&gt;
&lt;br /&gt;
The other option is for the code to fail silently, and try to do what it can.  This is the way the old Test of Time macro system often fails.  If Civ II doesn&#039;t &amp;quot;understand&amp;quot; the event, it just doesn&#039;t happen, and doesn&#039;t bother the player with the error.  This means that the scenario will still mostly work, but it is harder to catch issues during playtesting.  Sometimes, this means doing something &amp;quot;sensible&amp;quot; if the input isn&#039;t of the expected type, and might make the code easier to write, since you don&#039;t have to handle inputs differently.&lt;br /&gt;
&lt;br /&gt;
A third option is to write your code such that both things can be done.  At the top of your code, you put in a variable named &amp;quot;debugMode&amp;quot; or something, and make all the functions throw errors when true, and fail silently when false.  Then you playtest with debugMode set to true, and release with debug mode set to false.  However, this means extra work in writing your code and you also have to test everything with debug mode off.&lt;br /&gt;
&lt;br /&gt;
For toTile, I went with the fail with error option, since that will allow every function that uses toTile to assume it is receiving proper data.  It also seems unlikely that people will be regularly trying to check tiles that don&#039;t exist or have tables with tiles and units and improvement objects all in one.  And if they do, &amp;quot;guarding&amp;quot; is fairly straightforward anyway (as we&#039;ve done in previous lessons).&lt;br /&gt;
&lt;br /&gt;
Although toTile is mainly meant to be a helper function for the General Library, it is also put into the gen table to be made available to end users, since it offers useful functionality.  Hence, &amp;lt;code&amp;gt; gen.toTile=toTile&amp;lt;/code&amp;gt;.  Note that we could have given toTile a different name in the gen table that this module will return, such as gen.tableToTile=toTile.  In fact, we could refer to the same function with multiple keys in the gen table, if we want to.&lt;br /&gt;
&lt;br /&gt;
Next, we will look at gen.hasIrrigation.&lt;br /&gt;
&lt;br /&gt;
The first thing to notice is that local is not being used to define this function.  That is because we&#039;re putting the function for gen.hasIrrigation directly into the gen table that this module will return.  We could define hasIrrigation as a local variable and then copy it into the gen table.  However, there is a decent chance that the General Library will have more than 200 functions by the time everything is complete, since it is meant to provide a lot of building block functionality and keep it in one place, and we will run into trouble if we assign 200 local variables in a single function (which a required lua file acts as).&lt;br /&gt;
&lt;br /&gt;
Perhaps the most striking thing is that we begin by changing the value of tile, the argument of the function.  It looks like we&#039;re making a global variable named tile, but we&#039;re not.  When you specify the names of the arguments for a function (in this case tile), you create local variables for that function, which can be given new values just as if you had explicitly used the local keyword.&lt;br /&gt;
&lt;br /&gt;
Beyond that, we extract the integer representing the tile improvements into a local variable (which upon later reflection isn&#039;t really necessary), and check that the irrigation bit is set to 1 and the mining bit is set to 0.  Refer to lesson 5 for why this works.  In fact, we could have simply returned the value of the if statement, rather than specifying return true and return false, although it is very slightly clearer what is going on in the expanded version of the code.&lt;br /&gt;
&lt;br /&gt;
Now, let us write a function to place irrigation on a square.  It seems pretty clear that we should do nothing if the tile has a city, but we also have to decide what to do if there is mining or farmland on the tile, since those interfere with placing irrigation.  We&#039;ll just remove them, on the basis that if we&#039;re trying to &amp;quot;place irrigation,&amp;quot; then we want irrigation to be there when we are finished.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function gen.placeIrrigation(tile)&lt;br /&gt;
    tile = toTile(tile)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These lines open the function and convert a table of coordinates to a tile if necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 if tile.city then&lt;br /&gt;
    return&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the tile has a city, return so nothing else is done in the function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     -- Set irrigation bit to 1&lt;br /&gt;
     tile.improvements = tile.improvements | 0x04&lt;br /&gt;
     -- Set mining bit to 0&lt;br /&gt;
     tile.improvements = tile.improvements &amp;amp; ~0x08&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the irrigation bit to 1 and the mining bit to 0.&lt;br /&gt;
&lt;br /&gt;
The functions in this library don&#039;t have to be complex, and in fact, most probably shouldn&#039;t be.  They just have to make life easier for the end user.  If you reach this lesson before the General Library is considered &amp;quot;complete,&amp;quot; your assignment now is to submit some work for it.  If you don&#039;t feel comfortable doing bitwise operations, you can test the work of others or submit functions that simplify other tasks.  However, there are also some helper functions in the library to facilitate changing bits, so you might also consider working on the unit type flags functions.  Remember, if you want to make functions available to the console for testing purposes, they must be global variables.&lt;br /&gt;
&lt;br /&gt;
=== The Threshold Table and First Look at Metatables===&lt;br /&gt;
&lt;br /&gt;
Consider a scenario design situation that occurred in Over the Reich: a bomber is generating some bombs via a key press, and the number of bombs it should generate is dependant on its current remaining hitpoints.  The more hitpoints the bomber has, the more bombs it should generate.  What we want is to specify that if a bomber has between x and y hitpoints, it should produce 2 bombs.  That is, for a given type of bomber, we want to have, for example,&lt;br /&gt;
&lt;br /&gt;
hp &amp;gt;= 16 --&amp;gt; 4 bombs&lt;br /&gt;
16 &amp;gt; hp &amp;gt;= 12 --&amp;gt; 3 bombs&lt;br /&gt;
12 &amp;gt; hp &amp;gt;= 9 --&amp;gt; 2 bombs&lt;br /&gt;
9 &amp;gt; hp &amp;gt;= 4 --&amp;gt; 1 bomb&lt;br /&gt;
4 &amp;gt; hp &amp;gt;= 0 --&amp;gt; 0 bombs&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Lua tables do not naturally encode this kind of association by default.  However, Lua does have a feature called metatables, which allows us to change the behaviour of tables.  (This will be a much better way to make the specification than I ended up writing in Over the Reich.)&lt;br /&gt;
&lt;br /&gt;
A metatable is a table that we can &amp;quot;attach&amp;quot; to another table, and then the metatable changes the behaviour of that table.  We&#039;ll only look at metatables briefly here, but more information can be found [https://www.tutorialspoint.com/lua/lua_metatables.htm here].&lt;br /&gt;
&lt;br /&gt;
What we want is a data structure that can accept numerical &amp;quot;key values&amp;quot; that are between the key values explicitly specified, and return the appropriate value for those keys.  We will call this data structure a threshold table, since we are specifying threshold values as keys.  We can do this by assigning the following metatable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local mt = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we run &amp;lt;code&amp;gt; setmetatable(myTable,mt)&amp;lt;/code&amp;gt;, then whenever we ask for an index from myTable and that index doesn&#039;t currently exist in myTable, the function assigned to __index will run.  Now let us examine the function.&lt;br /&gt;
&lt;br /&gt;
If the type of the key is not a number, then we return whatever the table value is for that key.  We use the function rawget, because the standard &amp;lt;code&amp;gt;thresholdTable[key]&amp;lt;/code&amp;gt; will invoke this function again if the key doesn&#039;t exist, and so never return an answer (when we want it to return nil).&lt;br /&gt;
&lt;br /&gt;
If the key type is a number, then we look for the largest numerical index that is also less than or equal to the key value.  We return a default value of false if the key submitted is smaller than all numerical values.  False is chosen over nil, so that a maximum value can be set by setting the value of a numerical index to false.  Using the key [-math.huge] allows a return value to be set for all numbers (since all numbers are greater than -math.huge).&lt;br /&gt;
&lt;br /&gt;
Since we don&#039;t want scenario creators to have to re-create threshold tables every time they need them, we&#039;ll add this functionality to the General Library&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local thresholdTableMetatable = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 -- gen.makeThresholdTable(table or nil)--&amp;gt;thresholdTable&lt;br /&gt;
 function gen.makeThresholdTable(inputTable)&lt;br /&gt;
     inputTable = inputTable or {}&lt;br /&gt;
     return setmetatable(inputTable,thresholdTableMetatable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-06-ThresholdTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
===A Munition Generation Module===&lt;br /&gt;
&lt;br /&gt;
Now, let us write some re-usable code for a human player to generate units by pressing a key while an appropriate unit is active.  This sort of code could be used for ranged attacks (generating a &amp;quot;munition&amp;quot;) and also for recruiting mercenaries by paying gold.&lt;br /&gt;
&lt;br /&gt;
The first thing we will want to do is to decide how our code will be used by the end user.  This will, perhaps, change by the time we finish writing the code, but it will at least give us a starting point.&lt;br /&gt;
&lt;br /&gt;
spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&lt;br /&gt;
&lt;br /&gt;
Our goal is that when a player attempts to generate a unit using another unit, they will provide the unit spawning the new unit, and a table of information specifying if a unit (or units) can be spawned and anything else that must happen while spawning (like paying money, expending movement points, etc.).&lt;br /&gt;
&lt;br /&gt;
We have an option here.  We could have the scenario creator provide the specification table as a required file for our module, or the creator can provide it at the time spawnUnit is called.  I choose the latter for a couple of reasons.  The first is that it allows the player to have more than one specification table, either because more than one key can spawn a unit, or because the specification can change over time.  The other is reason is so that the creator can make the table in the events.lua file if desired (since our module can&#039;t require information from events.lua).&lt;br /&gt;
&lt;br /&gt;
Having decided that our generateUnit events are going to be specified by a table, we have to decide what the contents of that table should be.  It seems pretty reasonable to index the specificationTable with the index of the unit type of each unit that can generate using the information in the table.  If a unit type id number is missing, that unit doesn&#039;t generate a munition (or recruit a unit).&lt;br /&gt;
&lt;br /&gt;
The value for each unit type id in the specification table will be a table that specifies how and if that unit generates other units.&lt;br /&gt;
&lt;br /&gt;
 --specificationTable[unitType.id]={&lt;br /&gt;
 --&lt;br /&gt;
 -- goldCost = integer or nil&lt;br /&gt;
 --      amount of gold it costs to generate a unit&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minTreasury = integer or nil&lt;br /&gt;
 --      minimum amount of gold in treasury to generate a unit&lt;br /&gt;
 --      absent means refer to gold cost&lt;br /&gt;
 --      (tribe will generate and be set to 0 if treasury is less than goldCost)&lt;br /&gt;
 -- treasuryFailMessage = string or nil&lt;br /&gt;
 --      A message to be displayed if the unit fails to spawn a unit due to an &lt;br /&gt;
 --      insufficient treasury&lt;br /&gt;
 --      nil means no message&lt;br /&gt;
&lt;br /&gt;
 -- There are three ways to specify move costs, in full movement points,&lt;br /&gt;
 -- in &amp;quot;atomic&amp;quot; movement points, and as a fraction of total movement points for the&lt;br /&gt;
 -- unit type.  Use only one kind per unit type &lt;br /&gt;
 &lt;br /&gt;
 -- moveCost = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMove = integer or nil&lt;br /&gt;
 --      minimum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means any movement points for land/sea, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMove = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostAtomic = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      refers to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveAtomic = integer or nil&lt;br /&gt;
 --      minumum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      referes to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMoveAtomic = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points expended generating the unit&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points that must remain to be allowed&lt;br /&gt;
 --      to generate a unit&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 -- postGenMinMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function, round up to nearest &amp;quot;atomic&amp;quot; move point&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- roundFractionFull = bool or nil&lt;br /&gt;
 --      fractional movement cost and minimum are rounded up to full movement point&lt;br /&gt;
 --      instead of atomic movement point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- roundFractionFullDown = bool or nil&lt;br /&gt;
 --      fractional cost and minimum are rounded down to full move point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- minMoveFailMessage = string or nil&lt;br /&gt;
 --      a message to be displayed if a unit is not generated due to insufficient&lt;br /&gt;
 --      movement points.&lt;br /&gt;
 --      nil means no message &lt;br /&gt;
&lt;br /&gt;
 -- allowedTerrainTypes = table of integers or nil&lt;br /&gt;
 --      a unit may only be generated if the tile it is standing on&lt;br /&gt;
 --      corresponds to one of numbers in the table&lt;br /&gt;
 --      nil means the unit can be generated on any terrain type&lt;br /&gt;
 -- terrainTypeFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to standing&lt;br /&gt;
 --      on the incorrect terrain &lt;br /&gt;
&lt;br /&gt;
 -- requiredTech = tech object or nil&lt;br /&gt;
 --      the generating civ must have this technology in order to generate&lt;br /&gt;
 --      the unit&lt;br /&gt;
 --      nil means no requirement&lt;br /&gt;
 -- techFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to not having&lt;br /&gt;
 --      the correct technology &lt;br /&gt;
&lt;br /&gt;
 -- payload = boolean or string&lt;br /&gt;
 --      if true, unit must have a home city in order to generate munitions&lt;br /&gt;
 --      and generating munitions sets the home city to NONE&lt;br /&gt;
 -- payloadFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to the &lt;br /&gt;
 --      payload restriction&lt;br /&gt;
 -- payloadRestrictionCheck = nil or function(unit)--&amp;gt;boolean&lt;br /&gt;
 --      If function returns false, the home city is not valid for giving the&lt;br /&gt;
 --      unit a payload.  This will be checked when the unit is activated, when&lt;br /&gt;
 --      the unit is given a new home city with the &#039;h&#039; key and when the unit&lt;br /&gt;
 --      tries to generate a munition&lt;br /&gt;
 --      nil means no restriction&lt;br /&gt;
 -- payloadRestrictionMessage = nil or string&lt;br /&gt;
 --      message to show if a unit fails the payloadRestrictionCheck&lt;br /&gt;
&lt;br /&gt;
 -- canGenerateFunction = nil or function(unit)--&amp;gt;boolean &lt;br /&gt;
 --      This function applied to the generating unit must return true in order&lt;br /&gt;
 --      for a unit to be spawned.  All other conditions still apply.&lt;br /&gt;
 --      any failure message should be part of canGenerateFunction&lt;br /&gt;
 --      absent means no extra conditions &lt;br /&gt;
&lt;br /&gt;
 -- generateUnitFunction = nil or function(unit)--&amp;gt;table of unit&lt;br /&gt;
 --      This function creates the unit or units to be generated&lt;br /&gt;
 --      and returns a table containing those units&lt;br /&gt;
 --      Ignore any specifications prefixed with * if this is used&lt;br /&gt;
 --      nil means use other specifications &lt;br /&gt;
&lt;br /&gt;
 --*generatedUnitType = unitType&lt;br /&gt;
 --      The type of unit to be generated&lt;br /&gt;
 --      can&#039;t be nil unless generateUnitFunction is used instead &lt;br /&gt;
&lt;br /&gt;
 --*giveVeteran = bool or nil&lt;br /&gt;
 --      generated unit(s) given veteran status if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
 --      if true, overrides copyVeteranStatus&lt;br /&gt;
&lt;br /&gt;
 --*copyVeteranStatus = bool or nil&lt;br /&gt;
 --      generated unit(s) copy veteran status of generating unit if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
&lt;br /&gt;
 --*setHomeCityFunction = nil or function(generatingUnit)--&amp;gt;cityObject&lt;br /&gt;
 --      determines what home city the spawned unit should have&lt;br /&gt;
 --      nil means a home city of NONE &lt;br /&gt;
&lt;br /&gt;
 --*numberToGenerate = nil or number or thresholdTable or function(generatingUnit)--&amp;gt;number&lt;br /&gt;
 --      if nil, generate 1 unit in all circumstances&lt;br /&gt;
 --      if integer, generate that many units (generate 0 if number less than 0)&lt;br /&gt;
 --      if number not integer, generate floor(number), and 1 more with&lt;br /&gt;
 --      probability number-floor(number)&lt;br /&gt;
 --      if thresholdTable, use remaining hp as the key, to get the number to create&lt;br /&gt;
 --      if function, get the number as the returned value of the function &lt;br /&gt;
&lt;br /&gt;
 -- activate = bool or nil&lt;br /&gt;
 --      Activates one of the generated units if true.  If generateUnitFunction was used,&lt;br /&gt;
 --      the unit at index 1 is activated, if index 1 has a value.  (if not, any unit in&lt;br /&gt;
 --      the list might be chosen)&lt;br /&gt;
&lt;br /&gt;
The very last entry brings forward a change that must be made to our unit generation specification.  Lua&#039;s activate unit command doesn&#039;t run the unit activation trigger, even though the active unit is changed.  Therefore, we must do that manually.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
becomes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit,specificationTable,unitActivationCode)--&amp;gt;table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Perhaps we will change it again later.&lt;br /&gt;
&lt;br /&gt;
I&#039;ve decided to try a different instructional technique for this section.  Instead of writing the code and then going through it section by section, I&#039;ve recorded a video of my coding and testing this module, and I attempt to explain some of the stuff that I do along the way.&lt;br /&gt;
&lt;br /&gt;
I&#039;m not sure of the value of the video.  If you find that there seems to be little useful content relative to the time it takes to watch, then feel free to skip it and continue the lesson.  I don&#039;t teach anything &amp;quot;new&amp;quot; in it, so you won&#039;t miss anything crucial.  However, it should be pretty close to how programming Lua can actually happen in the &amp;quot;real world.&amp;quot;  While I did give some thought to how to write the module before I started, I do attempt to solve problems in real time, and make mistakes that are not discovered for a while (including one where I try to explain how I solve a problem and then not actually do a crucial part).&lt;br /&gt;
&lt;br /&gt;
You can find the code [https://forums.civfanatics.com/threads/totpp-the-munitions-library.647910/ here].  Even if you decide not to watch the video, download the code and try testing some of the features based on the specification above.  If you find any bugs, submit a fix (or at least report the issue).&lt;br /&gt;
&lt;br /&gt;
The video can be found [https://youtu.be/XxPyNknGlAo here].&lt;br /&gt;
&lt;br /&gt;
===A Unit Attack Bonus for Complementary Units in Square===&lt;br /&gt;
&lt;br /&gt;
Something we might like to do is to give units an attack bonus if they attack from a square with some special unit, for example a &amp;quot;leader&amp;quot; unit.  The [[Napoléon I]] scenario, for example, gives an attack bonus to units if a commander unit, such as Napoleon, is in the square when the unit is activated (the unit can subsequently move and still retain the bonus as long as no other unit is selected).  We will now make a module providing the same functionality.&lt;br /&gt;
&lt;br /&gt;
We first have to have a basic idea of how this functionality should work.  When a unit is activated, the onActivateUnit event checks if the newly activated unit should get an attack bonus, based on the other units in the square.  If the unit deserves an attack bonus, the corresponding unitType.attack entry is changed, and all the attack value of all other units is reset to the default value.  If the activated unit also does not deserve an attack bonus, that value is also set to the default value.&lt;br /&gt;
&lt;br /&gt;
This now leads us to some more possibilities.  Should multiple bonus units lead to multiple bonuses or only apply the best one?  For example, suppose a legion gets a bonus if an archer is also in the same square.  Should two archers provide twice the bonus?  Perhaps two archers should provide a larger bonus than one, but not twice as much.  Perhaps a legion should also get a bonus if there is a catapult in the square, but that bonus should apply even if the maximum archer bonus is already achieved.  It seems like perhaps there should be a &amp;quot;ranged unit&amp;quot; bonus, an &amp;quot;artillery unit&amp;quot; bonus and maybe a &amp;quot;cavalry&amp;quot; bonus which should all impact the legion&#039;s attack value.  It&#039;s looking like we might end up demanding that a scenario creator make a big complicated table in order to use this functionality, even if they only have simple needs.&lt;br /&gt;
&lt;br /&gt;
What we can do to alleviate this is to write a &amp;quot;simple&amp;quot; version of the event that is easy to use (and program), and also write a more complicated version that gives the expanded capability.&lt;br /&gt;
&lt;br /&gt;
Specification Table for simpleAttackBonus&lt;br /&gt;
&lt;br /&gt;
 --simpleAttackBonusTable[activeUnit.type.id] ={[bonusUnitType.id]=bonusNumber}&lt;br /&gt;
 --simpleAttackBonusTable.type = string&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- if simpleAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- if simpleAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 --simpleAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise &lt;br /&gt;
&lt;br /&gt;
The relevant first draft of the code is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function simpleAttackBonus(activeUnit,simpleAttackBonusTable,defaultAttackTable)&lt;br /&gt;
     -- reset all unit attack values&lt;br /&gt;
     for unitTypeID,attackValue in pairs(defaultAttackTable) do&lt;br /&gt;
         civ.getUnitType(unitTypeID).attack = attackValue&lt;br /&gt;
     end&lt;br /&gt;
     local unitBonusTable = simpleAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
     if not unitBonusTable then&lt;br /&gt;
         -- unitBonusTable is nil (or false), so the active unit can&#039;t&lt;br /&gt;
         -- get a bonus&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
     -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
     for unit in activeUnit.location.units do&lt;br /&gt;
         if unitBonusTable[unit.type.id] and unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
             bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     if bestBonusSoFar == 0 then&lt;br /&gt;
         -- If no bonus unit is found, this will be true, so do nothing else&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- set the new attack and return&lt;br /&gt;
     if string.lower(simpleAttackBonusTable.type) == &amp;quot;addBonus&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = activeUnit.type.attack+bestBonusSoFar&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     local attackMultiplier = 1&lt;br /&gt;
     if type(simpleAttackBonusTable.type) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = (100+bestBonusSoFar)/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
         attackMultiplier = 1+bestBonusSoFar&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar&lt;br /&gt;
     else&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     end&lt;br /&gt;
     -- apply the bonus and round as appropriate&lt;br /&gt;
     if type(simpleAttackBonusTable.round) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;up&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.ceil(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;down&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     else&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now let us go over this section by section.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-07-AttackBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The first thing we do is to reset all the attack values of all the unit types.  That way, if a bonus existed for the last unit activated, that bonus no longer applies.  If a unit type is not in the defaultAttackTable, then we don&#039;t have the information to reset the attack value anyway, so we can safely ignore it by using the pairs function to iterate over the table.&lt;br /&gt;
&lt;br /&gt;
Now, we must find out if the newly activated unit deserves a bonus.  For that, we get the table associated with the active unit&#039;s type.  If the value is nil instead of a table, then the unit&#039;s type is not in the simpleAttackBonusTable, so there is no bonus to apply and the function returns.&lt;br /&gt;
&lt;br /&gt;
If the unit is eligible for bonuses, we then check the units in the square to see if any bonuses actually apply.  We&#039;ve seen this kind of code before.  If the unit in the stack can provide a bonus, and that bonus is better than the best bonus already found, the unit now provides the best bonus.  All bonus types that we can have are better if they are larger, and we are not comparing between bonus types, so a simple numerical comparison will do.  All bonuses are larger than 0 in our formulation, so 0 is a good starting value in the search.&lt;br /&gt;
&lt;br /&gt;
If the best bonus so far is still 0, there is no bonus, so the function can return.&lt;br /&gt;
&lt;br /&gt;
At this point, it occurs to me that when searching for the best bonus, we should exclude the active unit from the search.  That way, you can have a &amp;quot;strength in numbers&amp;quot; bonus, for example.  The relevant change to the code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    for unit in activeUnit.location.units do&lt;br /&gt;
        if unit ~= activeUnit and unitBonusTable[unit.type.id] and &lt;br /&gt;
 			unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, consider&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-08-AttackBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we apply the bonus that we&#039;ve found.  We use string.lower on simpleAttackBonusTable.type so that we don&#039;t have to worry about capitalization.  That does, however, require a correction to &amp;quot;addBonus&amp;quot;, since a lower case string will never be equal to that.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;addbonus&amp;quot; is the only type of bonus that is directly added to the existing attack value.  All other bonus types are a form of multiplication.  Since the addition is straightforward and doesn&#039;t require any rounding, the activeUnit&#039;s type attack value can be changed immediately, and the function execution ended with return.&lt;br /&gt;
&lt;br /&gt;
When there is only one bonus being applied, all other types of bonus are different ways of expressing how to multiply the existing attack value to get a new one, so we simply convert to the appropriate multiplier, and provide an error message if the type of bonus is not one of the valid possibilities.&lt;br /&gt;
&lt;br /&gt;
Finally, we round the attack value to an appropriate integer (since unit attack values must be integers), change the attack value of the active unit&#039;s type, and return to end the function execution.&lt;br /&gt;
&lt;br /&gt;
Now, we integrate into events.lua by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus = require(&amp;quot;attackBonus&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The relevant integration code for events.lua is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local defaultAttackValueTable = {[unitAliases.legion.id]=4}&lt;br /&gt;
 local simpleAttackBonusTable ={}&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=3,[unitAliases.musketeer.id]=4}&lt;br /&gt;
 &lt;br /&gt;
 local function doOnActivation(unit,source)&lt;br /&gt;
     munitions.payloadRestrictionCheck(unit,munitionSpecificationTable)&lt;br /&gt;
 	attackBonus.simpleAttackBonus(unit,simpleAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can check that the bonus is being applied correctly by checking the Civlopedia entry for legion and looking at the attack value.  The following cases must be tested (remember that activating a unit from the city screen doesn&#039;t run the onActivation event, so activate from the map).&lt;br /&gt;
&lt;br /&gt;
 Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
 Legion activated with archer, but no musketeer (7 attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (8 attack)&lt;br /&gt;
 Legion activated with archer and musketeer (8 attack)&lt;br /&gt;
 Legion activated with 2 archer, no musketeer (7 attack)&lt;br /&gt;
 Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
 Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
I recommend making a stack for each of these cases and activating them one by one.&lt;br /&gt;
To facilitate the test, add the following line to doOnActivation&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.ui.text(tostring(unit.type.attack))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You will want to comment out this line after testing.&lt;br /&gt;
&lt;br /&gt;
Next, change simpleAttackBonusTable to do &amp;quot;addpercent&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=30,[unitAliases.musketeer.id]=70}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With no rounding set, standard rounding is used&lt;br /&gt;
 Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
 Legion activated with archer and musketeer (7 attack)&lt;br /&gt;
 Legion activated with 2 archer, no musketeer (5 attack)&lt;br /&gt;
 Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
 Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
These numbers test both rounding up and rounding down.&lt;br /&gt;
&lt;br /&gt;
Now, use&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (6 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next,&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (6 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;standard&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next, we test &amp;quot;addfraction&amp;quot;.  Since we&#039;ve tested all the rounding options, we don&#039;t have to do that again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=0.3,[unitAliases.musketeer.id]=0.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=130,[unitAliases.musketeer.id]=170}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiply&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Before we finish, we should test a legion bonus for the legion.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.legion.id]=2,[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Legion alone should have 4 attack.&lt;br /&gt;
 A second legion on the square should provide 8 attack instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, let us try to formulate a more complicated bonus system.  One thing we mentioned is that we&#039;d like the ability to get bonuses from multiple units, and to be able to get bonuses from different &amp;quot;classes&amp;quot; of units (like &amp;quot;artillery,&amp;quot; &amp;quot;cavalry,&amp;quot; and &amp;quot;ranged attackers.&amp;quot;  Something else we might want to do is to allow different kinds of bonuses.  That is, maybe some units should provide a fixed +2 to any unit receiving the bonus, so that it is better at improving units with a low attack value, while other units should provide a percentage bonus (making them better at supporting units with an already high attack value).  It turns out that both of these ideas are not too difficult to implement individually, but that trying to implement them together makes it problematic to find the best bonus.&lt;br /&gt;
&lt;br /&gt;
Let us implement a bonus system with multiple categories but only one bonus type.  In our specification, we will first specify a data type called &amp;quot;bonusCategory.&amp;quot;  It is still just a table (though we could add a metatable if we wanted), but it will help us make our specification clearer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- A &amp;quot;bonusCategory&amp;quot; is a table&lt;br /&gt;
 -- bonusCategory = {[bonusUnitType.id]=bonusNumber, maxBonusUnits=integer or nil, nextBonusValue = fraction or nil}&lt;br /&gt;
 -- In a bonusCategory, the value for bonusUnitType.id tells what the base bonus for that unit type is,&lt;br /&gt;
 -- maxBonusUnits is the maximum number of units that can provide a bonus in this category,&lt;br /&gt;
 -- nextBonusValue tells how much to reduce the bonus for each subsequent unit,&lt;br /&gt;
 -- e.g. nextBonusValue = 0.7, and 5 units, which each have a bonusNumber=1&lt;br /&gt;
 -- The total bonus is 1(0.7)^0+.7+(.7)(.7)+(.7)^3+(.7)^4 = 1+.7+.49+.343+.2401=2.7731&lt;br /&gt;
 -- (which would be rounded as specified)&lt;br /&gt;
 -- nil means nextBonusValue=1&lt;br /&gt;
 --&lt;br /&gt;
 -- If a unit type is in two bonus categories for the same unit, there is no guarantee that the&lt;br /&gt;
 -- best bonus will be achieved&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, the bonus category is indexed by unitType id numbers for units that can give a bonus, and the corresponding bonus.  It also specifies the maximum number of units that can give a bonus, and a number that governs how to reduce a bonus for extra units.  That way, there can be diminishing returns for bonuses.&lt;br /&gt;
&lt;br /&gt;
Next, we look at the specification for the categoryAttackBonusTable&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 --categoryAttackBonusTable[activeUnit.type.id] =table of bonusCategory&lt;br /&gt;
 --categoryAttackBonusTable.type = string&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up all the percents, then compute the bonus&lt;br /&gt;
 -- i.e. 50% bonus and 50% bonus is 100% bonus, not 125%&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 50% bonus units become 50% + 25% &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up the fractions, then compute the bonus&lt;br /&gt;
 -- i.e. .5 bonus and .5 bonus is 1+.5+.5= 2x bonus, not 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 .5 bonus units become .5+.25 &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 150% and 150% yields 225% of original value&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 100, i.e. nextBonusValue=.5 2 150% bonuses become 150% and 125%&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 1.5 and 1.5 yields 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 1, i.e. nextBonusValue=.5 and two 1.5 bonuses become 1.5 and 1.25&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 --categoryAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise&lt;br /&gt;
 &lt;br /&gt;
 -- If the active unit can get a bonus, go through each category and compute the bonus for that category.&lt;br /&gt;
 -- Then, combine the bonuses for all categories to get the overall bonus, and round the result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With the bonusCategory defined, the value of the unit indices of categoryAttackBonusTable become easy to define.  Most of the specification is showing what exactly the different bonus categories mean, so the end user can use them properly.  It&#039;s not strictly necessary to offer so many choices to the end user on how to specify data, but it can be more convenient.&lt;br /&gt;
&lt;br /&gt;
Here is the actual code (before testing) to implement this more general version of attack bonuses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- HELPER FUNCTION&lt;br /&gt;
 -- findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable) --&amp;gt; number or false&lt;br /&gt;
 -- usedUnitTable is indexed by the i.d. number of units, and if the value for a unit is true,&lt;br /&gt;
 -- then it has already been used for a bonus (and, so, is not eligible)&lt;br /&gt;
 -- The function returns the bonus (before nextBonusValue is applied) if there is one, and marks the &lt;br /&gt;
 -- unit as used in the usedUnitTable&lt;br /&gt;
 -- returns false if no unit qualifies&lt;br /&gt;
 local function findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable)&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
    local bestUnitSoFar = nil&lt;br /&gt;
    -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
    -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
    for unit in tile.units do&lt;br /&gt;
        if not usedUnitTable[unit.id] and bonusCategory[unit.type.id] &lt;br /&gt;
            and bonusCategory[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestUnitSoFar = unit&lt;br /&gt;
            bestBonusSoFar = bonusCategory[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if bestUnitSoFar then&lt;br /&gt;
        usedUnitTable[bestUnitSoFar.id] = true&lt;br /&gt;
        return bestBonusSoFar&lt;br /&gt;
    else&lt;br /&gt;
        return false&lt;br /&gt;
    end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 -- HELPER FUNCTION&lt;br /&gt;
 -- computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
 -- Computes the bonus that the active unit will receive from this category, taking into &lt;br /&gt;
 -- account the type of bonus for the table&lt;br /&gt;
 local function computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local bonusThusFar = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then &lt;br /&gt;
        bonusThusFar = 1&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        bonusThusFar = 100&lt;br /&gt;
    else&lt;br /&gt;
        bonusThusFar = 0&lt;br /&gt;
    end&lt;br /&gt;
    local bonusDiscount = 1&lt;br /&gt;
    for i=1,(bonusCategory.maxBonusUnits or 10000) do&lt;br /&gt;
        local currentBonus =findBestBonusInUnitStack(activeUnit.location,bonusCategory,usedUnitTable) &lt;br /&gt;
        if not currentBonus then&lt;br /&gt;
            -- no more valid bonuses for this category&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
        if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-1)*bonusDiscount+1)&lt;br /&gt;
        elseif bonusType ==&amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
        else&lt;br /&gt;
            bonusThusFar = bonusThusFar+currentBonus*bonusDiscount&lt;br /&gt;
        end&lt;br /&gt;
        bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
    end&lt;br /&gt;
    return bonusThusFar&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 local function categoryAttackBonus(activeUnit,categoryAttackBonusTable,defaultAttackTable)&lt;br /&gt;
    local bonusInfoTable = categoryAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
    if not bonusInfoTable then&lt;br /&gt;
        -- unit doesn&#039;t get a bonus&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
    -- keep track of bonuses already computed&lt;br /&gt;
    local bonusResultsTable = {}&lt;br /&gt;
    -- keep track of units that have already been &amp;quot;used&amp;quot; for a bonus&lt;br /&gt;
    local usedUnitTable = {[activeUnit.id]=true}&lt;br /&gt;
    for index,bonusCategory in pairs(bonusInfoTable) do&lt;br /&gt;
        bonusResultsTable[index]=computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    end&lt;br /&gt;
    -- compute the bonus&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local resultAttackBeforeRounding = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult/100&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack+bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+(bonusResult/100)&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    else&lt;br /&gt;
        error(&amp;quot;categoryAttackBonus: categoryAttackBonusTable.type is not a valid value.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    -- apply the bonus and round as appropriate&lt;br /&gt;
    local roundType = categoryAttackBonusTable.round&lt;br /&gt;
    if type(roundType) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;up&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.ceil(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;down&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    else&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two helper functions for computeCategoryBonus are only used once each in the code, so making them helper functions does not help us re-use code.  However, what it does do is to break down the function design process into smaller tasks, which are each more manageable to complete.  If you&#039;re trying to keep track of too many things in your program, try writing a few helper functions to handle individual tasks.  We&#039;ll look at the helper functions when we actually arrive at them in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-09-CategoryAtkBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If there is no entry in the categoryAttackBonusTable or the active unit&#039;s type, then the function returns without doing anything further.&lt;br /&gt;
&lt;br /&gt;
The bonusResultsTable keeps track of the total bonus from each category, so they can be added or multiplied together after all the category bonuses are applied.  The usedUnitsTable keeps track of units that are no longer eligible to contribute to a bonus (such as if they have already contributed), and we initialize it with the active unit, so that it doesn&#039;t provide a bonus to itself.&lt;br /&gt;
&lt;br /&gt;
The for loop computes the bonus for every category, and stores the value in the bonusResultsTable, for use later.Now, let us look at the helper functions.&lt;br /&gt;
&lt;br /&gt;
First up is findBestBonusInUnitStack&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-10-CategoryAtkBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This basically does what it says in the name.  For a bonusCategory, it finds the unit in the tile that provides the best bonus, and has not already provided a bonus elsewhere.  If there is no qualifying unit, false is returned.  If there is, that unit&#039;s bonus is returned, and the unit&#039;s id is entered into the usedUnitTable, so that unit can&#039;t provide another bonus for the active unit.  We&#039;ve searched for the best of something before, so there is little need to go over it again.&lt;br /&gt;
&lt;br /&gt;
Next is computeCategoryBonus&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-11-CategoryAtkBonus3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we&#039;re computing the bonus for the entire bonusCategory.  We need the bonus type in order to know what kind of math to do.  The math itself is not very interesting.  We also initialize the bonusDiscount, which keeps track of the fraction of the next unit&#039;s bonus that will actually be applied.&lt;br /&gt;
&lt;br /&gt;
Next, we enter a for loop that will run one time for each possible bonus that there can be in a bonus category.  If bonusCategory.maxBonusUnits is nil, then we set an arbitrary limit of 10000 units, which is very unlikely to happen in practice.&lt;br /&gt;
&lt;br /&gt;
At each iteration of the loop, the best available bonus in the stack is found.  If no unit was eligible to provide a bonus, then the current bonus is false, and the &amp;quot;break&amp;quot; command is issued.  Break immediately exits the current loop.  So, our program doesn&#039;t run 10000 loops if there is no maximum number of bonus units, it just breaks at an appropriate time.&lt;br /&gt;
&lt;br /&gt;
After the bonus is found, it is added to or multiplied with the bonus already found.  The bonus computed in this way will be the largest possible, since the bonus provided does not depend on the other units chosen (so we don&#039;t have a situation where &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; are both useless, but &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; chosen together are best).  Also, since the best bonus is chosen first, the smallest bonus discount applies to it, so the cost imposed by the discounting is smallest.&lt;br /&gt;
&lt;br /&gt;
Finally, we update the bonusDisount.  Here, I notice a problem in the code as written, since bonusCategory.nextBonusValue is allowed to be nil.  Replace&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
with &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*(bonusCategory.nextBonusValue or 1) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
so that if there is no nextBonusValue, a default of 1 is used, and the bonusDiscount stays at 1 (i.e. no discount is applied).&lt;br /&gt;
&lt;br /&gt;
We return to categoryAttackBonus to see&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-12-CategoryAtkBonus4.jpg]]&lt;br /&gt;
&lt;br /&gt;
From here, we combine the bonuses stored in bonusResultsTable, the exact way of doing so being dependant on the type of bonus involved.  The math itself isn&#039;t very interesting, and doesn&#039;t seem all that likely to come up in this exact form elsewhere.  If you need help with the mathematical details of some event you want to write, ask in the forums.  There&#039;s a good chance someone has the skills to help you solve your specific problem.&lt;br /&gt;
&lt;br /&gt;
For every type of bonus, the result is stored in resultAttackBeforeRounding, so that variable can be rounded up or down as specified by the rounding type.&lt;br /&gt;
&lt;br /&gt;
Here, I notice another error.  We should restrict the attack value for a unit to not exceed 98.  We can do that with a math.min(value, 98).&lt;br /&gt;
&lt;br /&gt;
Now, we need to test the various aspects of the attack bonus program, so we need an appropriate table&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addbonus&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=2,[unitAliases.chariot.id]=4,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=2,[unitAliases.musketeer.id]=4,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Also, comment out the old attack bonus line, and put in a new one&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus.categoryAttackBonus(unit,categoryAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
Already, we find a problem.  Although there were no syntax errors to fix, I forgot to reset unit attack values.  So, very quickly, the legions keep gathering extra attack values when they are activated (since the base attack is not reset to 4).  Since this is happening anyway, I&#039;ll test the 98 attack value maximum.  That appears to work, at least in the case of no specified rounding.&lt;br /&gt;
&lt;br /&gt;
Cut and paste the appropriate lines from the simpleAttackBonus to the categoryAttackBonus, and save.&lt;br /&gt;
&lt;br /&gt;
With that bug fixed, everything works as expected.&lt;br /&gt;
&lt;br /&gt;
Next, we change the categoryAttackBonusTable to &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addpercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=50,[unitAliases.chariot.id]=100,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=50,[unitAliases.musketeer.id]=100,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addpercent&amp;quot;.  These are the same, since adding we&#039;re adding percentages of the same base value of 4.  So a value of 2 is the same as adding 50% of 4.&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
The results are the same.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addfraction&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=.50,[unitAliases.chariot.id]=1.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.50,[unitAliases.musketeer.id]=1.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
We&#039;ll have to do some new calculations, now, since multiply and multiplyfraction give different results than the various adding formulations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiply&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=1.50,[unitAliases.chariot.id]=2.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=1.50,[unitAliases.musketeer.id]=2.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 12 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
 Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Finally, we use multiplyPercent, and check for the same results&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=150,[unitAliases.musketeer.id]=200,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 12 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
 Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Quickly, I find that if a bonus applies, that bonus makes the attack value of a legion 98.  I failed to multiply percents correctly in computeCategoryBonus.  The Line &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Is changed to &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+100)/100&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, Change archer bonus to 110 and musketeer bonus to 120 (so a unit will make a legion have 4.4 and 4.8 value before rounding), and test the rounding options.  You will find they all work.&lt;br /&gt;
&lt;br /&gt;
At the moment, we don&#039;t have a way to mix different types of bonuses.  As said earlier, we might want this so that some units can be better at giving bonuses to low attack units than to high attack units, while others give a percentage bonus to everything.  We could now write a bonus system that allows for multiple types of bonuses. However, the current bonus system allows for the bonus to change per unit.  This means that we can, for example, convert a +2 attack bonus to a plus 100% bonus for a unit with 2 attack, and a plus 50% bonus for a unit with 4 attack.  In the case of the multiplied bonuses, this will make the bonus more powerful if there is more than one.  That is, 2 attack, +2 twice is 6, but if +2 is changed to x2, then the multiplied bonus brings the attack up to 8.  However, this seems like it would be a relatively unlikely problem, and there are other things this code can&#039;t handle, so we&#039;ll let someone else make the code if they actually need it.&lt;br /&gt;
&lt;br /&gt;
So, what we&#039;ll do is write a function that will change all appropriate entries in the categoryAttackBonusTable to reflect a different value.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed(unitType,number,categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unit type to any unit to be equivalent&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, an issue with tables arises.  It is very likely that when someone defines their cateogryAttackBonusTable, they&#039;ll define it something like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.25,[unitAliases.musketeer.id]=.5}&lt;br /&gt;
 local bonusTableForInfantry = {rangeBonusCategory}&lt;br /&gt;
 local cABT = {type=&amp;quot;addfraction&amp;quot;}&lt;br /&gt;
 cABT[unitAliases.phalanx.id]=bonusTableForInfantry&lt;br /&gt;
 cABT[unitAliases.legion.id] = bonusTableForInfantry&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
However, this means that both &amp;lt;code&amp;gt; cABT[unitAliases.legion.id]  &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt; cABT[unitAliases.phalanx.id] &amp;lt;/code&amp;gt; actually refer to the same piece of memory, and changing cABT[unitAliases.legion.id][1][unitAliases.archer.id] will also change the value at cABT[unitAliases.phalanx.id][1][unitAliases.archer.id].  This is because of the way lua tables are designed.  This design can be useful, for example it allowed us to make changes to usedUnitsTable in the last function without having to copy the table, make changes to the copy of the table, and then replace the original table with that copy as a return value.  However, it also requires us to be careful when we make changes to entries in tables.  In this case, we&#039;ll simply copy the table and all its sub values into a new table.&lt;br /&gt;
&lt;br /&gt;
The code to do this is given by&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will explain this code in the next section, since it involves a programming technique which we haven&#039;t discussed before.&lt;br /&gt;
&lt;br /&gt;
For now, we analyze plusFixed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed({[unitType1.id]=fixedBonus,[unitType2.id]=fixedBonus},categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unitTypeI.id to a unit to be equivalent to&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power.  If the unit doesn&#039;t receive a bonus&lt;br /&gt;
 -- from the unitType, then it won&#039;t after applying plusFixed.&lt;br /&gt;
 -- The value of the existing bonus is ignored.&lt;br /&gt;
 &lt;br /&gt;
 local function plusFixed(fixedUnitBonusTable,categoryAttackBonusTable)&lt;br /&gt;
     local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
     for bonusReceivingUnitTypeID,bonusTable in pairs(categoryAttackBonusTable) do&lt;br /&gt;
         -- replace bonusTable with an equivalent table that is not referened&lt;br /&gt;
         -- anywhere else, so that changes to it can be made without impacting&lt;br /&gt;
         -- data elsewhere&lt;br /&gt;
         categoryAttackBonusTable[bonusReceivingUnitTypeID] = duplicateTable(bonusTable)&lt;br /&gt;
         -- make bonusTable refer to the &amp;quot;current&amp;quot; bonus table for the unit type&lt;br /&gt;
         bonusTable =categoryAttackBonusTable[bonusReceivingUnitTypeID] &lt;br /&gt;
         -- For each unit type in the fixedUnitBonusTable, check if any bonus category&lt;br /&gt;
         -- in the bonusTable corresponds to it.  If so, make the change&lt;br /&gt;
         for bonusGivingUnitTypeID,fixedBonusValue in pairs(fixedUnitBonusTable) do&lt;br /&gt;
             -- get the attack of the unit type &lt;br /&gt;
             local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
             -- in each bonus category, check if the giver&#039;s unit type id is there,&lt;br /&gt;
             -- if so, change to the correct attack&lt;br /&gt;
             for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
                 if bonusCategory[bonusGivingUnitTypeID] then&lt;br /&gt;
                 -- change the bonus appropriately&lt;br /&gt;
                     if bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue&lt;br /&gt;
                     elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*(fixedBonusValue+baseAttack)/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=(fixedBonusValue+baseAttack)/baseAttach&lt;br /&gt;
                     else&lt;br /&gt;
                         error(&amp;quot;pluxFixed: categoryAttackBonusTable.type does not have an acceptable value.&amp;quot;)&lt;br /&gt;
                     end&lt;br /&gt;
                 end&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-13-plusFixed1.jpg]]&lt;br /&gt;
&lt;br /&gt;
As before, we save the bonusType in lower case, since we&#039;ll be using it a lot later.  Next, we open a for loop, where the index is the id of the unit type receiving the bonus, and the value is the bonus table for that unit type.  Next, we duplicate the bonus table, so that we have a table we can change without impacting anything elsewhere, and we store the duplicated table in categoryAttackBonusTable in place of the original bonusTable for the current bonus receiving unit id.  Next, we assign this duplicated table to the variable bonusTable, so we can refer to it later in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-14-plusFixed2.jpg]]&lt;br /&gt;
&lt;br /&gt;
We now perform the following actions for each unitType.id and corresponding fixedBonusValue submitted in the fixedUnitBonusTable.&lt;br /&gt;
&lt;br /&gt;
First, get the attack of the bonus receiving unit, since we&#039;ll need that in order to customize the bonus.  Next, check each bonus category in the bonus table.  If the bonus category has the current unitTypeID as a key, then replace the existing value with a bonus equivalent to adding a fixed value to the receiving unit&#039;s attack.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all that must be done, so end all the loops.&lt;br /&gt;
&lt;br /&gt;
Now we test the function.&lt;br /&gt;
&lt;br /&gt;
Add unitAliases.phalanx = civ.getUnitType(3) to the appropriate file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 defaultAttackValueTable[unitAliases.phalanx.id]=1&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,&lt;br /&gt;
 								nextBonusValue=0.5,maxBonusUnits=1}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=125,[unitAliases.musketeer.id]=150,&lt;br /&gt;
 								nextBonusValue=0.75,maxBonusUnits=1}&lt;br /&gt;
 local standardBonus = {cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.phalanx.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 attackBonus.plusFixed({[unitAliases.chariot.id]=2,[unitAliases.musketeer.id]=2},&lt;br /&gt;
 						categoryAttackBonusTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The chariot and the musketeer individually should each add 2 to both a phalanx and a legion,&lt;br /&gt;
so the phalanx should have an attack of 3, and the legion should have an attack of 6, if one bonus&lt;br /&gt;
is applied.&lt;br /&gt;
&lt;br /&gt;
Since the bonus type is multiplypercent, together the phalanx would have an attack of 9, and the legion will also have an attack of 9.&lt;br /&gt;
&lt;br /&gt;
In testing, we quickly get this error&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
You should see this in lua console if this worked&lt;br /&gt;
...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: bad argument #1 to &#039;getUnitType&#039; (number expected, got string)&lt;br /&gt;
stack traceback:&lt;br /&gt;
	[C]: in function &#039;civ.getUnitType&#039;&lt;br /&gt;
	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At line 356, which is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This must mean that bonusReceivingUnitTypeID is not a number.  This is because we&#039;re looping over categoryAttackBonusTable, and that table has a couple of entries that are not integers (&amp;quot;type&amp;quot; and &amp;quot;round&amp;quot;).  Therefore, we have to insert code to deal with this eventuality.&lt;br /&gt;
&lt;br /&gt;
The simplest way is to put everything in the loop body into an if statement, so that it only runs when bonusGivingUnitTypeID is actually a number.  You should be able to do this without detailed instructions, so do so (hint: use type function).&lt;br /&gt;
&lt;br /&gt;
The next error is &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: bad argument #1 to &#039;pairs&#039; (table expected, got nil)&lt;br /&gt;
 stack traceback:&lt;br /&gt;
 	[C]: in function &#039;pairs&#039;&lt;br /&gt;
 	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
 	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 360 for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we have a nil value for bonusTable.  This turns out to be an error in duplicateTable.  When I duplicated the table, I forgot to return that table.  That is, both the if and else statement in that function need a return command, and I forgot to add &amp;lt;code&amp;gt; return duplicatedTable &amp;lt;/code&amp;gt; in the if portion.  Add this to the duplicate table function.&lt;br /&gt;
&lt;br /&gt;
After this, our predictions are true.  Testing the other types of bonus is left as an assignment.  You can find the completed code [https://forums.civfanatics.com/threads/totpp-attack-bonus-library.648093/ here].&lt;br /&gt;
&lt;br /&gt;
===Recursive Functions===&lt;br /&gt;
&lt;br /&gt;
Let us return to the duplicateTable function.  Recall that in the last section we added a line to it, so we&#039;ll restate it here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
 		return duplicatedTable&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-16-duplicateTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
The interesting thing about duplicateTable is that it invokes duplicateTable within its code.  When we copy the key-value pairs into the new table, we run duplicateTable on the value.  If the value is not a table, then we are in the else case, and the value is immediately returned to be inserted into the duplicated table.  If the value is a table, that table is duplicated before anything else is done.&lt;br /&gt;
&lt;br /&gt;
Let us look at a simple example of a recursive function, the factorial function N!.  In lesson 3, we discussed the factorial function in the context of loops.  Since N!=N*(N-1)*(N-2)*...*3*2*1, we can give another definition of N!:&lt;br /&gt;
 N!=1 if N = 1&lt;br /&gt;
 N!=N*(N-1)! if N &amp;gt; 1&lt;br /&gt;
Or, using the convention that 0!=1, we can state&lt;br /&gt;
 N!=1 if N = 0&lt;br /&gt;
 N!=N*(N-1)! if N &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
The case where N =1 or N=0 is called the &amp;quot;base case.&amp;quot;  If we keep substituting N! as N*(N-1)!, then we won&#039;t go on forever, because we will eventually reach a point where N=0, and N! can be substituted as 1 instead of N*(N-1)!.  As long as there is a base case, our program will eventually reach the base case(s), and begin &amp;quot;completing&amp;quot; evaluation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function factorial(N)&lt;br /&gt;
 if N&amp;gt;0 then&lt;br /&gt;
     return N*factorial(N-1)&lt;br /&gt;
 else&lt;br /&gt;
     return 1&lt;br /&gt;
 end&lt;br /&gt;
 end&lt;br /&gt;
 print(factorial(5))&lt;br /&gt;
 print(factorial(6))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run this in code in the lua demo website, or using the TOTPP lua interpreter.&lt;br /&gt;
&lt;br /&gt;
Returning to our duplicateTable function, the base case is any time a table value is not itself a table.  When that happens, the recursion &amp;quot;chain&amp;quot; ends, and everything can evaluated.&lt;br /&gt;
&lt;br /&gt;
Although is shouldn&#039;t be a problem in this particular case, it should be noted that it is possible for there to not be a &amp;quot;base case&amp;quot; in the recursion style: if table, recur, if not return a value.  Consider the following table system&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 a={}&lt;br /&gt;
 b={[1]=a}&lt;br /&gt;
 a[1]=b&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In this case, the code would never end.&lt;br /&gt;
&lt;br /&gt;
It is possible that even if the code could &amp;quot;theoretically&amp;quot; execute to completion, you run out of memory before that.  This is called a &amp;quot;stack overflow,&amp;quot; and if it occurs, you will have to think of an alternate way to solve your problem.  It will probably be best to ask for help in that case (and it might be useful to provide others with an example of a problem that results in a stack overflow), but you might also look into &amp;quot;tail recursion&amp;quot;, including http://www.lua.org/pil/6.3.html .&lt;br /&gt;
&lt;br /&gt;
===Conclusion===&lt;br /&gt;
&lt;br /&gt;
With the skills covered in this chapter, you now have the tools to split a large events file into multiple files that are more manageable.  You also have the basics for how to write re-useable modules for your events, so that your work can be used by others.  Remember that if someone else uses your implementation of a feature, they will spend much less time coding and testing it, allowing them to either finish the scenario sooner, or to introduce some other feature.  So, it might very well pay to spend at least a little effort making your code into a reusable module.  Perhaps you have an idea for a cool scenario mechanic, but don&#039;t have a scenario for it (or don&#039;t want to take the time to make it).  If that&#039;s the case, just make the module and test it in a &amp;quot;toy&amp;quot; scenario (like Classic Rome) so that it can be used more or less &amp;quot;off the shelf&amp;quot; when someone needs it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5182</id>
		<title>Get Started With Lua Events Lesson 6: Splitting Code into Multiple Files</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5182"/>
		<updated>2019-07-26T15:09:13Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* A Unit Attack Bonus for Complementary Units in Square */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This Lesson is under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
In this lesson, we will take a look at how to split the code for a scenario&#039;s events into multiple files.  There are several reasons to consider doing this.&lt;br /&gt;
&lt;br /&gt;
The first reason is simply to organize your work.  If you have a series of complicated events, the events.lua file can become very large very quickly. Once your events.lua file has thousands of lines of code in it, it may not be very obvious where the best place is to put that next helper function, or where to implement the function that runs a complicated event.  Sometimes even finding the piece of code that has to be changed can be a bit of a hassle.  In Over the Reich, I sometimes search for the associated civ.scen line, and then search for the exact name of the function I need.  Occasionally, there may even be more searching to find what I actually have to change.  With multiple files, it becomes easier to find things.&lt;br /&gt;
&lt;br /&gt;
Another aspect of using multiple files is that you can make certain changes without worrying about breaking things elsewhere.  If myBigComplicatedFunction relies on aModestHelperFunction for a certain part of its functionality, and a change to myBigComplicatedFunction also requires a change to aModestHelperFunction, you have to make sure that nothing else in your code also uses aModestHelperFunction, or, if something else does depend on it, that aModestHelperFunction either still provides the original functionality, or that all other functions that use aModestHelperFunction are suitably modified.  If myBigComplicatedFunction is defined in its own lua module, then you don&#039;t have to worry about forgetting that aModestHelperFunction was used elsewhere, since it can&#039;t be accessed outside the module unless you specifically allow it to be.&lt;br /&gt;
&lt;br /&gt;
A second reason to split events code into multiple files is to facilitate collaboration.  If all of the events are in a single file, then only one person can make changes to the file at a time.  If one partner starts changing an event, but has to do something else before finishing, everyone waits on one person&#039;s delay.  However, if most aspects of the scenario are separated into individual files, everyone can work on his or her own piece of the puzzle without depriving others of the opportunity to work at that time.&lt;br /&gt;
&lt;br /&gt;
A third reason to split events into multiple modules is to facilitate reusing code.  If everything required to implement an event is in its own file (or files), it becomes much easier for other creators to use your functionality in their scenario.  Since everything they need is already in one place, they don&#039;t have to find every last helper function, or concern themselves with naming conflicts.&lt;br /&gt;
&lt;br /&gt;
===Two Simple Examples===&lt;br /&gt;
&lt;br /&gt;
Let us look at the top of the events.lua file.  You can get the version that I started lesson 6 with [[here]].&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-01-DefaultRequire.jpg]]&lt;br /&gt;
&lt;br /&gt;
We get code from other files by using the command &amp;lt;code&amp;gt;require&amp;lt;/code&amp;gt; along with a string specifying the file name (except for the .lua extension).  At the moment, we can only get code stored in the lua folder in the Test of Time directory.  This is inconvenient if we&#039;re trying to distribute a scenario, since installing a scenario would require moving certain files to the lua directory, and those file names might conflict.  Instead, we need to tell the Lua interpreter to search in the same folder that the events.lua folder is in.&lt;br /&gt;
&lt;br /&gt;
To do this, we need the following code:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local eventsPath = string.gsub(debug.getinfo(1).source, &amp;quot;@&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 local scenarioFolderPath = string.gsub(eventsPath, &amp;quot;events.lua&amp;quot;, &amp;quot;?.lua&amp;quot;)&lt;br /&gt;
 if string.find(package.path, scenarioFolderPath, 1, true) == nil then&lt;br /&gt;
    package.path = package.path .. &amp;quot;;&amp;quot; .. scenarioFolderPath&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can probably cut and paste this code before the require lines in your events.lua file and not worry about how it works.  However, I&#039;ll provide a brief explanation for reference.&lt;br /&gt;
&lt;br /&gt;
The first line stores the location of the of the current file as a string in eventsPath.&lt;br /&gt;
&lt;br /&gt;
The second line replaces events.lua in the eventsPath with ?.lua, which will tell the Lua interpreter to look for .lua files in the current directory (that is to say, the directory with the events.lua file).  &lt;br /&gt;
&lt;br /&gt;
The if statement adds scenarioFolderPath to the places for the Lua interpreter to search for code, if that directory is not already in the search path.  Since the search path is kept active by the Lua interpreter, it will not be necessary to repeat these lines of code in every file that performs a require action as long as you are running the file as part of events.  If you are writing some other kind of code, you will need to substitute &amp;quot;events.lua&amp;quot; with the name of the file with the code you are running.  Note that for some reason, events.lua is always provided in lower case.  However, for use in other situations, debug.getinfo(1).source uses the correct case for event files. I have only briefly tested this, so you may have to do some testing yourself if this situation comes up (or ask for help in the forums).&lt;br /&gt;
&lt;br /&gt;
Now that we&#039;ve told Lua where to look for our extra code, we can begin moving code to other files.  Think of require as telling Lua to run the entire contents of another file as a function.  We can then assign a value to whatever that file returns, which will usually be a table.  A couple of examples will clarify.&lt;br /&gt;
&lt;br /&gt;
For our first example, we will move our scenario&#039;s parameters to a separate file, and access it via require.  This may not seem worthwhile in this example, but tables like this can get large in a hurry.  At the time of writing, Over the Reich has over 100 lines of parameters (&amp;quot;specialNumbers&amp;quot;), and parameters are something that a designer might like to play with while collaborators make other implementations.  Also, parameters will have to be referenced by other parts of the code, and a file that is required by events.lua cannot, in turn, require events.lua in order to get information.  That means that we&#039;ll have to keep our parameters in a separate file anyway.&lt;br /&gt;
&lt;br /&gt;
Cut the parameters table definition and paste it into a new file, classicRomeParameters.lua.  For the last line, write&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return parameters&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, Near the top of events.lua, where the existing require lines are, add the eventsPath code from above and also the line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local parameters = require(&amp;quot;classicRomeParameters&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
[[File:GetStartedWithLuaLesson6-02-RequireParameters.jpg]]&lt;br /&gt;
&lt;br /&gt;
Open the classicRome scenario and test out a couple of events to make sure everything is the same.&lt;br /&gt;
&lt;br /&gt;
We might find it convenient to put a few tables into the same file.  For this, we will simply return a table containing these tables, and give each table a name in the events.lua file.&lt;br /&gt;
&lt;br /&gt;
Create a file classicRomeAliases.lua and move all the &amp;quot;aliases&amp;quot; tables to that file.  Also move the getCityAt function.&lt;br /&gt;
&lt;br /&gt;
At the bottom of the file, put the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 unitAliases=unitAliases,&lt;br /&gt;
 tribeAliases=tribeAliases,&lt;br /&gt;
 tileAliases=tileAliases,&lt;br /&gt;
 cityAliases=cityAliases,&lt;br /&gt;
 textAliases=textAliases,&lt;br /&gt;
 terrainAliases=terrainAliases,&lt;br /&gt;
 improvementAliases=improvementAliases,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following lines to events.lua (in the require section)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local aliases = require(&amp;quot;classicRomeAliases&amp;quot;)&lt;br /&gt;
 local unitAliases,tribeAliases,tileAliases,cityAliases,textAliases,&lt;br /&gt;
 		terrainAliases,improvementAliases=aliases.unitAliases,aliases.tribeAliases,&lt;br /&gt;
 		aliases.tileAliases,aliases.cityAliases, aliases.textAliases,aliases.terrainAliases,&lt;br /&gt;
 		aliases.improvementAliases&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, our classicRomeAliases module is returning a table with our &amp;quot;alias&amp;quot; tables.  We then assign the entries in this returned table to local variables with the desired names.  Here, I use multiple variable assignment, which I don&#039;t believe I&#039;ve used before (even though Lua allows it), but these could just as simply have been assigned line by line.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-03-RequireAliases.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now, let us move the legion plundering code into its own file, which we&#039;ll call plunder.lua.  First, copy over the legionPlunder function, and paste it near the bottom of the new file.&lt;br /&gt;
&lt;br /&gt;
Now, let us go through the code of this function, and figure out what else we need in our plunder.lua module.&lt;br /&gt;
&lt;br /&gt;
The very first part of the function is a check against unitAliases.legion.  This means we need the unitAliases table, and so we copy the aliases require code to the top of plunder.lua.  We don&#039;t need the path information, since that will be added in events.lua.&lt;br /&gt;
&lt;br /&gt;
A few more lines down, we find that the function cityRadius is also used in legionPlunder.  Therefore, we move that over as well.  We also need the plunderValue function, so copy that over as well.&lt;br /&gt;
&lt;br /&gt;
Next, we check if cityRadius relies on anything, but it doesn&#039;t.&lt;br /&gt;
&lt;br /&gt;
Proceeding to plunderValue, we find that it relies on the parameters table, so require that as well.  The function plunderValue does not appear to depend on anything else, so we&#039;re done moving functionality.  If we missed something, the Lua interpreter will complain at some point anyway.&lt;br /&gt;
&lt;br /&gt;
Next, we require the plunder module in events.lua, with the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local plunder = require(&amp;quot;plunder&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, for each of the functions in plunder.lua, we check if it is used somewhere in events.lua.  We can do this by searching.  plunderValue isn&#039;t used anywhere, so we&#039;re done with that.  City radius is used.  At the bottom of plunder.lua, we begin our return table, and have&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 cityRadius=cityRadius,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, in events.lua, we replace the ocurance of cityRadius with plunder.cityRadius.  Alternatively, we could have put &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local cityRadius=plunder.cityRadius&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
after the line requiring plunder.&lt;br /&gt;
&lt;br /&gt;
Similarly, for legionPlunder, we add &amp;lt;code&amp;gt;legionPlunder=legionPlunder&amp;lt;/code&amp;gt; to the table that plunder.lua returns, and pre-append plunder. to legionPlunder in the one location where it occurs.&lt;br /&gt;
&lt;br /&gt;
Now, we test the legion plunder function and the press 4 generate archers function to make sure everything works.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-04-RequirePlunder.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Working With a Library===&lt;br /&gt;
&lt;br /&gt;
In programming terms, a &amp;quot;library&amp;quot; is a collection of code that can provide some specified functionality to a programmer without that programmer having to modify the code in the library.  Thus far, you have been using the &amp;quot;civ&amp;quot; library to interact with the game, and there has been no need modify it in order to use it in our own events.  (Unfortunately, in the case of the civ library, we don&#039;t actually know how to modify it.)  This is in contrast to much of the code we have written thus far.  For example, the code we wrote last lesson to make Selucid elephants attack Egypt is highly specific.  You couldn&#039;t just cut and paste that code, change the argument of a single function, and get your own goto event.  It is still a good example for how to write a goto event, but a user would still have to actually write the event.&lt;br /&gt;
&lt;br /&gt;
If you plan to write some functionality for your scenario that others might find useful, it is worth spending a little extra effort to see if you can write that functionality in a form that will allow others to use it with minimal effort.  If you can, then a little extra work on your part might save someone else the trouble of re-inventing the wheel, and allow them to complete their project sooner, or to work on some new feature for you to enjoy.  Unfortunately, the Lua scenarios that have been completed at the time of writing haven&#039;t been that good at creating re-usable code, at least in part since we were all getting used to Lua.  This will hopefully be improved in the future.&lt;br /&gt;
&lt;br /&gt;
For now, we&#039;re going to look at a library which is called the General Library (unless someone comes up with a better name) and which can be found [https://forums.civfanatics.com/threads/totpp-the-general-library.647583/ here].  The purpose of this module is to provide relatively simple functionality that probably shouldn&#039;t be implemented every time it is needed.  This is useful for our purposes, since we can look at relatively self contained and simple functions for our first examples.  We&#039;ll create a library for generating munitions later.&lt;br /&gt;
&lt;br /&gt;
This library would be used by invoking the line &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local gen = require(&amp;quot;generalLibrary&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to make these functions available to the console for testing purposes, you would simply omit the local, thereby making gen a global variable.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at a function provided by the General Library &amp;lt;code&amp;gt; gen.hasIrrigation(tile)--&amp;gt;boolean&amp;lt;/code&amp;gt;.  The very first line references the helper function &amp;lt;code&amp;gt; toTile(tile or table)--&amp;gt;tile&amp;lt;/code&amp;gt;, so let us include that code, and look at it first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 -- toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- gen.toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- If given a tile object, returns the tile&lt;br /&gt;
 -- If given coordinates for a tile, returns the tile&lt;br /&gt;
 -- Causes error otherwise&lt;br /&gt;
 -- Helper Function (provided to this library as toTile and gen.toTile)&lt;br /&gt;
 local function toTile(input)&lt;br /&gt;
     if civ.isTile(input) then&lt;br /&gt;
         return input&lt;br /&gt;
     elseif type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         local xVal = input[1] or input[&amp;quot;x&amp;quot;]&lt;br /&gt;
         local yVal = input[2] or input[&amp;quot;y&amp;quot;]&lt;br /&gt;
         local zVal = input[3] or input[&amp;quot;z&amp;quot;] or 0&lt;br /&gt;
         if type(xVal)==&amp;quot;number&amp;quot; and type(yVal)==&amp;quot;number&amp;quot; and type(zVal)==&amp;quot;number&amp;quot; then&lt;br /&gt;
             if civ.getTile(xVal,yVal,zVal) then&lt;br /&gt;
                 return civ.getTile(xVal,yVal,zVal)&lt;br /&gt;
             else&lt;br /&gt;
                 error(&amp;quot;Table with values {&amp;quot;..tostring(xVal)..&amp;quot;,&amp;quot;..tostring(yVal)..&lt;br /&gt;
                         &amp;quot;,&amp;quot;..tostring(zVal)..&amp;quot;} does not correspond to a valid tile.&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
         else&lt;br /&gt;
             error(&amp;quot;Table did not correspond to tile coordinates&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;Did not receive a tile object or table of coordinates.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 gen.toTile = toTile&lt;br /&gt;
 &lt;br /&gt;
 -- gen.hasIrrigation(tile)--&amp;gt;boolean&lt;br /&gt;
 -- returns true if tile has irrigation but no farm&lt;br /&gt;
 -- returns false otherwise&lt;br /&gt;
 function gen.hasIrrigation(tile)&lt;br /&gt;
     tile = toTile(tile)&lt;br /&gt;
     local improvements = tile.improvements&lt;br /&gt;
     -- irrigation, but no mining, so not farmland&lt;br /&gt;
     if improvements &amp;amp; 0x04 == 0x04 and improvements &amp;amp; 0x08 == 0 then&lt;br /&gt;
         return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-05-HasIrrigation.jpg]]&lt;br /&gt;
&lt;br /&gt;
Let us begin by looking at the function &amp;lt;code&amp;gt;toTile&amp;lt;/code&amp;gt;.  The purpose of this function is to allow other functions to accept tile coordinates in a table instead of an actual tile object.  The function tries to be reasonably permissive in the coordinates it will accept, allowing both integer indices and lowercase string indices, and by assuming that a missing z value corresponds to map 0.  The function also tries to give reasonably helpful errors.&lt;br /&gt;
&lt;br /&gt;
This brings up something that should be considered when making reusable code: what to do if you don&#039;t get values you were expecting.  One option is to throw an error and bring up the Lua console.  This is good for scenario creators, so they know something is wrong, but not so great for end users because the error stops the rest of the event from happening, should the mistake slip through playtesting.&lt;br /&gt;
&lt;br /&gt;
The other option is for the code to fail silently, and try to do what it can.  This is the way the old Test of Time macro system often fails.  If Civ II doesn&#039;t &amp;quot;understand&amp;quot; the event, it just doesn&#039;t happen, and doesn&#039;t bother the player with the error.  This means that the scenario will still mostly work, but it is harder to catch issues during playtesting.  Sometimes, this means doing something &amp;quot;sensible&amp;quot; if the input isn&#039;t of the expected type, and might make the code easier to write, since you don&#039;t have to handle inputs differently.&lt;br /&gt;
&lt;br /&gt;
A third option is to write your code such that both things can be done.  At the top of your code, you put in a variable named &amp;quot;debugMode&amp;quot; or something, and make all the functions throw errors when true, and fail silently when false.  Then you playtest with debugMode set to true, and release with debug mode set to false.  However, this means extra work in writing your code and you also have to test everything with debug mode off.&lt;br /&gt;
&lt;br /&gt;
For toTile, I went with the fail with error option, since that will allow every function that uses toTile to assume it is receiving proper data.  It also seems unlikely that people will be regularly trying to check tiles that don&#039;t exist or have tables with tiles and units and improvement objects all in one.  And if they do, &amp;quot;guarding&amp;quot; is fairly straightforward anyway (as we&#039;ve done in previous lessons).&lt;br /&gt;
&lt;br /&gt;
Although toTile is mainly meant to be a helper function for the General Library, it is also put into the gen table to be made available to end users, since it offers useful functionality.  Hence, &amp;lt;code&amp;gt; gen.toTile=toTile&amp;lt;/code&amp;gt;.  Note that we could have given toTile a different name in the gen table that this module will return, such as gen.tableToTile=toTile.  In fact, we could refer to the same function with multiple keys in the gen table, if we want to.&lt;br /&gt;
&lt;br /&gt;
Next, we will look at gen.hasIrrigation.&lt;br /&gt;
&lt;br /&gt;
The first thing to notice is that local is not being used to define this function.  That is because we&#039;re putting the function for gen.hasIrrigation directly into the gen table that this module will return.  We could define hasIrrigation as a local variable and then copy it into the gen table.  However, there is a decent chance that the General Library will have more than 200 functions by the time everything is complete, since it is meant to provide a lot of building block functionality and keep it in one place, and we will run into trouble if we assign 200 local variables in a single function (which a required lua file acts as).&lt;br /&gt;
&lt;br /&gt;
Perhaps the most striking thing is that we begin by changing the value of tile, the argument of the function.  It looks like we&#039;re making a global variable named tile, but we&#039;re not.  When you specify the names of the arguments for a function (in this case tile), you create local variables for that function, which can be given new values just as if you had explicitly used the local keyword.&lt;br /&gt;
&lt;br /&gt;
Beyond that, we extract the integer representing the tile improvements into a local variable (which upon later reflection isn&#039;t really necessary), and check that the irrigation bit is set to 1 and the mining bit is set to 0.  Refer to lesson 5 for why this works.  In fact, we could have simply returned the value of the if statement, rather than specifying return true and return false, although it is very slightly clearer what is going on in the expanded version of the code.&lt;br /&gt;
&lt;br /&gt;
Now, let us write a function to place irrigation on a square.  It seems pretty clear that we should do nothing if the tile has a city, but we also have to decide what to do if there is mining or farmland on the tile, since those interfere with placing irrigation.  We&#039;ll just remove them, on the basis that if we&#039;re trying to &amp;quot;place irrigation,&amp;quot; then we want irrigation to be there when we are finished.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function gen.placeIrrigation(tile)&lt;br /&gt;
    tile = toTile(tile)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These lines open the function and convert a table of coordinates to a tile if necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 if tile.city then&lt;br /&gt;
    return&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the tile has a city, return so nothing else is done in the function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     -- Set irrigation bit to 1&lt;br /&gt;
     tile.improvements = tile.improvements | 0x04&lt;br /&gt;
     -- Set mining bit to 0&lt;br /&gt;
     tile.improvements = tile.improvements &amp;amp; ~0x08&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the irrigation bit to 1 and the mining bit to 0.&lt;br /&gt;
&lt;br /&gt;
The functions in this library don&#039;t have to be complex, and in fact, most probably shouldn&#039;t be.  They just have to make life easier for the end user.  If you reach this lesson before the General Library is considered &amp;quot;complete,&amp;quot; your assignment now is to submit some work for it.  If you don&#039;t feel comfortable doing bitwise operations, you can test the work of others or submit functions that simplify other tasks.  However, there are also some helper functions in the library to facilitate changing bits, so you might also consider working on the unit type flags functions.  Remember, if you want to make functions available to the console for testing purposes, they must be global variables.&lt;br /&gt;
&lt;br /&gt;
=== The Threshold Table and First Look at Metatables===&lt;br /&gt;
&lt;br /&gt;
Consider a scenario design situation that occurred in Over the Reich: a bomber is generating some bombs via a key press, and the number of bombs it should generate is dependant on its current remaining hitpoints.  The more hitpoints the bomber has, the more bombs it should generate.  What we want is to specify that if a bomber has between x and y hitpoints, it should produce 2 bombs.  That is, for a given type of bomber, we want to have, for example,&lt;br /&gt;
&lt;br /&gt;
hp &amp;gt;= 16 --&amp;gt; 4 bombs&lt;br /&gt;
16 &amp;gt; hp &amp;gt;= 12 --&amp;gt; 3 bombs&lt;br /&gt;
12 &amp;gt; hp &amp;gt;= 9 --&amp;gt; 2 bombs&lt;br /&gt;
9 &amp;gt; hp &amp;gt;= 4 --&amp;gt; 1 bomb&lt;br /&gt;
4 &amp;gt; hp &amp;gt;= 0 --&amp;gt; 0 bombs&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Lua tables do not naturally encode this kind of association by default.  However, Lua does have a feature called metatables, which allows us to change the behaviour of tables.  (This will be a much better way to make the specification than I ended up writing in Over the Reich.)&lt;br /&gt;
&lt;br /&gt;
A metatable is a table that we can &amp;quot;attach&amp;quot; to another table, and then the metatable changes the behaviour of that table.  We&#039;ll only look at metatables briefly here, but more information can be found [https://www.tutorialspoint.com/lua/lua_metatables.htm here].&lt;br /&gt;
&lt;br /&gt;
What we want is a data structure that can accept numerical &amp;quot;key values&amp;quot; that are between the key values explicitly specified, and return the appropriate value for those keys.  We will call this data structure a threshold table, since we are specifying threshold values as keys.  We can do this by assigning the following metatable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local mt = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we run &amp;lt;code&amp;gt; setmetatable(myTable,mt)&amp;lt;/code&amp;gt;, then whenever we ask for an index from myTable and that index doesn&#039;t currently exist in myTable, the function assigned to __index will run.  Now let us examine the function.&lt;br /&gt;
&lt;br /&gt;
If the type of the key is not a number, then we return whatever the table value is for that key.  We use the function rawget, because the standard &amp;lt;code&amp;gt;thresholdTable[key]&amp;lt;/code&amp;gt; will invoke this function again if the key doesn&#039;t exist, and so never return an answer (when we want it to return nil).&lt;br /&gt;
&lt;br /&gt;
If the key type is a number, then we look for the largest numerical index that is also less than or equal to the key value.  We return a default value of false if the key submitted is smaller than all numerical values.  False is chosen over nil, so that a maximum value can be set by setting the value of a numerical index to false.  Using the key [-math.huge] allows a return value to be set for all numbers (since all numbers are greater than -math.huge).&lt;br /&gt;
&lt;br /&gt;
Since we don&#039;t want scenario creators to have to re-create threshold tables every time they need them, we&#039;ll add this functionality to the General Library&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local thresholdTableMetatable = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 -- gen.makeThresholdTable(table or nil)--&amp;gt;thresholdTable&lt;br /&gt;
 function gen.makeThresholdTable(inputTable)&lt;br /&gt;
     inputTable = inputTable or {}&lt;br /&gt;
     return setmetatable(inputTable,thresholdTableMetatable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-06-ThresholdTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
===A Munition Generation Module===&lt;br /&gt;
&lt;br /&gt;
Now, let us write some re-usable code for a human player to generate units by pressing a key while an appropriate unit is active.  This sort of code could be used for ranged attacks (generating a &amp;quot;munition&amp;quot;) and also for recruiting mercenaries by paying gold.&lt;br /&gt;
&lt;br /&gt;
The first thing we will want to do is to decide how our code will be used by the end user.  This will, perhaps, change by the time we finish writing the code, but it will at least give us a starting point.&lt;br /&gt;
&lt;br /&gt;
spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&lt;br /&gt;
&lt;br /&gt;
Our goal is that when a player attempts to generate a unit using another unit, they will provide the unit spawning the new unit, and a table of information specifying if a unit (or units) can be spawned and anything else that must happen while spawning (like paying money, expending movement points, etc.).&lt;br /&gt;
&lt;br /&gt;
We have an option here.  We could have the scenario creator provide the specification table as a required file for our module, or the creator can provide it at the time spawnUnit is called.  I choose the latter for a couple of reasons.  The first is that it allows the player to have more than one specification table, either because more than one key can spawn a unit, or because the specification can change over time.  The other is reason is so that the creator can make the table in the events.lua file if desired (since our module can&#039;t require information from events.lua).&lt;br /&gt;
&lt;br /&gt;
Having decided that our generateUnit events are going to be specified by a table, we have to decide what the contents of that table should be.  It seems pretty reasonable to index the specificationTable with the index of the unit type of each unit that can generate using the information in the table.  If a unit type id number is missing, that unit doesn&#039;t generate a munition (or recruit a unit).&lt;br /&gt;
&lt;br /&gt;
The value for each unit type id in the specification table will be a table that specifies how and if that unit generates other units.&lt;br /&gt;
&lt;br /&gt;
 --specificationTable[unitType.id]={&lt;br /&gt;
 --&lt;br /&gt;
 -- goldCost = integer or nil&lt;br /&gt;
 --      amount of gold it costs to generate a unit&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minTreasury = integer or nil&lt;br /&gt;
 --      minimum amount of gold in treasury to generate a unit&lt;br /&gt;
 --      absent means refer to gold cost&lt;br /&gt;
 --      (tribe will generate and be set to 0 if treasury is less than goldCost)&lt;br /&gt;
 -- treasuryFailMessage = string or nil&lt;br /&gt;
 --      A message to be displayed if the unit fails to spawn a unit due to an &lt;br /&gt;
 --      insufficient treasury&lt;br /&gt;
 --      nil means no message&lt;br /&gt;
&lt;br /&gt;
 -- There are three ways to specify move costs, in full movement points,&lt;br /&gt;
 -- in &amp;quot;atomic&amp;quot; movement points, and as a fraction of total movement points for the&lt;br /&gt;
 -- unit type.  Use only one kind per unit type &lt;br /&gt;
 &lt;br /&gt;
 -- moveCost = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMove = integer or nil&lt;br /&gt;
 --      minimum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means any movement points for land/sea, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMove = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostAtomic = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      refers to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveAtomic = integer or nil&lt;br /&gt;
 --      minumum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      referes to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMoveAtomic = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points expended generating the unit&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points that must remain to be allowed&lt;br /&gt;
 --      to generate a unit&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 -- postGenMinMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function, round up to nearest &amp;quot;atomic&amp;quot; move point&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- roundFractionFull = bool or nil&lt;br /&gt;
 --      fractional movement cost and minimum are rounded up to full movement point&lt;br /&gt;
 --      instead of atomic movement point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- roundFractionFullDown = bool or nil&lt;br /&gt;
 --      fractional cost and minimum are rounded down to full move point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- minMoveFailMessage = string or nil&lt;br /&gt;
 --      a message to be displayed if a unit is not generated due to insufficient&lt;br /&gt;
 --      movement points.&lt;br /&gt;
 --      nil means no message &lt;br /&gt;
&lt;br /&gt;
 -- allowedTerrainTypes = table of integers or nil&lt;br /&gt;
 --      a unit may only be generated if the tile it is standing on&lt;br /&gt;
 --      corresponds to one of numbers in the table&lt;br /&gt;
 --      nil means the unit can be generated on any terrain type&lt;br /&gt;
 -- terrainTypeFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to standing&lt;br /&gt;
 --      on the incorrect terrain &lt;br /&gt;
&lt;br /&gt;
 -- requiredTech = tech object or nil&lt;br /&gt;
 --      the generating civ must have this technology in order to generate&lt;br /&gt;
 --      the unit&lt;br /&gt;
 --      nil means no requirement&lt;br /&gt;
 -- techFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to not having&lt;br /&gt;
 --      the correct technology &lt;br /&gt;
&lt;br /&gt;
 -- payload = boolean or string&lt;br /&gt;
 --      if true, unit must have a home city in order to generate munitions&lt;br /&gt;
 --      and generating munitions sets the home city to NONE&lt;br /&gt;
 -- payloadFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to the &lt;br /&gt;
 --      payload restriction&lt;br /&gt;
 -- payloadRestrictionCheck = nil or function(unit)--&amp;gt;boolean&lt;br /&gt;
 --      If function returns false, the home city is not valid for giving the&lt;br /&gt;
 --      unit a payload.  This will be checked when the unit is activated, when&lt;br /&gt;
 --      the unit is given a new home city with the &#039;h&#039; key and when the unit&lt;br /&gt;
 --      tries to generate a munition&lt;br /&gt;
 --      nil means no restriction&lt;br /&gt;
 -- payloadRestrictionMessage = nil or string&lt;br /&gt;
 --      message to show if a unit fails the payloadRestrictionCheck&lt;br /&gt;
&lt;br /&gt;
 -- canGenerateFunction = nil or function(unit)--&amp;gt;boolean &lt;br /&gt;
 --      This function applied to the generating unit must return true in order&lt;br /&gt;
 --      for a unit to be spawned.  All other conditions still apply.&lt;br /&gt;
 --      any failure message should be part of canGenerateFunction&lt;br /&gt;
 --      absent means no extra conditions &lt;br /&gt;
&lt;br /&gt;
 -- generateUnitFunction = nil or function(unit)--&amp;gt;table of unit&lt;br /&gt;
 --      This function creates the unit or units to be generated&lt;br /&gt;
 --      and returns a table containing those units&lt;br /&gt;
 --      Ignore any specifications prefixed with * if this is used&lt;br /&gt;
 --      nil means use other specifications &lt;br /&gt;
&lt;br /&gt;
 --*generatedUnitType = unitType&lt;br /&gt;
 --      The type of unit to be generated&lt;br /&gt;
 --      can&#039;t be nil unless generateUnitFunction is used instead &lt;br /&gt;
&lt;br /&gt;
 --*giveVeteran = bool or nil&lt;br /&gt;
 --      generated unit(s) given veteran status if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
 --      if true, overrides copyVeteranStatus&lt;br /&gt;
&lt;br /&gt;
 --*copyVeteranStatus = bool or nil&lt;br /&gt;
 --      generated unit(s) copy veteran status of generating unit if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
&lt;br /&gt;
 --*setHomeCityFunction = nil or function(generatingUnit)--&amp;gt;cityObject&lt;br /&gt;
 --      determines what home city the spawned unit should have&lt;br /&gt;
 --      nil means a home city of NONE &lt;br /&gt;
&lt;br /&gt;
 --*numberToGenerate = nil or number or thresholdTable or function(generatingUnit)--&amp;gt;number&lt;br /&gt;
 --      if nil, generate 1 unit in all circumstances&lt;br /&gt;
 --      if integer, generate that many units (generate 0 if number less than 0)&lt;br /&gt;
 --      if number not integer, generate floor(number), and 1 more with&lt;br /&gt;
 --      probability number-floor(number)&lt;br /&gt;
 --      if thresholdTable, use remaining hp as the key, to get the number to create&lt;br /&gt;
 --      if function, get the number as the returned value of the function &lt;br /&gt;
&lt;br /&gt;
 -- activate = bool or nil&lt;br /&gt;
 --      Activates one of the generated units if true.  If generateUnitFunction was used,&lt;br /&gt;
 --      the unit at index 1 is activated, if index 1 has a value.  (if not, any unit in&lt;br /&gt;
 --      the list might be chosen)&lt;br /&gt;
&lt;br /&gt;
The very last entry brings forward a change that must be made to our unit generation specification.  Lua&#039;s activate unit command doesn&#039;t run the unit activation trigger, even though the active unit is changed.  Therefore, we must do that manually.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
becomes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit,specificationTable,unitActivationCode)--&amp;gt;table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Perhaps we will change it again later.&lt;br /&gt;
&lt;br /&gt;
I&#039;ve decided to try a different instructional technique for this section.  Instead of writing the code and then going through it section by section, I&#039;ve recorded a video of my coding and testing this module, and I attempt to explain some of the stuff that I do along the way.&lt;br /&gt;
&lt;br /&gt;
I&#039;m not sure of the value of the video.  If you find that there seems to be little useful content relative to the time it takes to watch, then feel free to skip it and continue the lesson.  I don&#039;t teach anything &amp;quot;new&amp;quot; in it, so you won&#039;t miss anything crucial.  However, it should be pretty close to how programming Lua can actually happen in the &amp;quot;real world.&amp;quot;  While I did give some thought to how to write the module before I started, I do attempt to solve problems in real time, and make mistakes that are not discovered for a while (including one where I try to explain how I solve a problem and then not actually do a crucial part).&lt;br /&gt;
&lt;br /&gt;
You can find the code [https://forums.civfanatics.com/threads/totpp-the-munitions-library.647910/ here].  Even if you decide not to watch the video, download the code and try testing some of the features based on the specification above.  If you find any bugs, submit a fix (or at least report the issue).&lt;br /&gt;
&lt;br /&gt;
The video can be found [https://youtu.be/XxPyNknGlAo here].&lt;br /&gt;
&lt;br /&gt;
===A Unit Attack Bonus for Complementary Units in Square===&lt;br /&gt;
&lt;br /&gt;
Something we might like to do is to give units an attack bonus if they attack from a square with some special unit, for example a &amp;quot;leader&amp;quot; unit.  The [[Napoléon I]] scenario, for example, gives an attack bonus to units if a commander unit, such as Napoleon, is in the square when the unit is activated (the unit can subsequently move and still retain the bonus as long as no other unit is selected).  We will now make a module providing the same functionality.&lt;br /&gt;
&lt;br /&gt;
We first have to have a basic idea of how this functionality should work.  When a unit is activated, the onActivateUnit event checks if the newly activated unit should get an attack bonus, based on the other units in the square.  If the unit deserves an attack bonus, the corresponding unitType.attack entry is changed, and all the attack value of all other units is reset to the default value.  If the activated unit also does not deserve an attack bonus, that value is also set to the default value.&lt;br /&gt;
&lt;br /&gt;
This now leads us to some more possibilities.  Should multiple bonus units lead to multiple bonuses or only apply the best one?  For example, suppose a legion gets a bonus if an archer is also in the same square.  Should two archers provide twice the bonus?  Perhaps two archers should provide a larger bonus than one, but not twice as much.  Perhaps a legion should also get a bonus if there is a catapult in the square, but that bonus should apply even if the maximum archer bonus is already achieved.  It seems like perhaps there should be a &amp;quot;ranged unit&amp;quot; bonus, an &amp;quot;artillery unit&amp;quot; bonus and maybe a &amp;quot;cavalry&amp;quot; bonus which should all impact the legion&#039;s attack value.  It&#039;s looking like we might end up demanding that a scenario creator make a big complicated table in order to use this functionality, even if they only have simple needs.&lt;br /&gt;
&lt;br /&gt;
What we can do to alleviate this is to write a &amp;quot;simple&amp;quot; version of the event that is easy to use (and program), and also write a more complicated version that gives the expanded capability.&lt;br /&gt;
&lt;br /&gt;
Specification Table for simpleAttackBonus&lt;br /&gt;
&lt;br /&gt;
 --simpleAttackBonusTable[activeUnit.type.id] ={[bonusUnitType.id]=bonusNumber}&lt;br /&gt;
 --simpleAttackBonusTable.type = string&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 --if simpleAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- if simpleAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- if simpleAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 --simpleAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise &lt;br /&gt;
&lt;br /&gt;
The relevant first draft of the code is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function simpleAttackBonus(activeUnit,simpleAttackBonusTable,defaultAttackTable)&lt;br /&gt;
     -- reset all unit attack values&lt;br /&gt;
     for unitTypeID,attackValue in pairs(defaultAttackTable) do&lt;br /&gt;
         civ.getUnitType(unitTypeID).attack = attackValue&lt;br /&gt;
     end&lt;br /&gt;
     local unitBonusTable = simpleAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
     if not unitBonusTable then&lt;br /&gt;
         -- unitBonusTable is nil (or false), so the active unit can&#039;t&lt;br /&gt;
         -- get a bonus&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
     -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
     for unit in activeUnit.location.units do&lt;br /&gt;
         if unitBonusTable[unit.type.id] and unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
             bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     if bestBonusSoFar == 0 then&lt;br /&gt;
         -- If no bonus unit is found, this will be true, so do nothing else&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- set the new attack and return&lt;br /&gt;
     if string.lower(simpleAttackBonusTable.type) == &amp;quot;addBonus&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = activeUnit.type.attack+bestBonusSoFar&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     local attackMultiplier = 1&lt;br /&gt;
     if type(simpleAttackBonusTable.type) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = (100+bestBonusSoFar)/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
         attackMultiplier = 1+bestBonusSoFar&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar&lt;br /&gt;
     else&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     end&lt;br /&gt;
     -- apply the bonus and round as appropriate&lt;br /&gt;
     if type(simpleAttackBonusTable.round) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;up&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.ceil(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;down&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     else&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now let us go over this section by section.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-07-AttackBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The first thing we do is to reset all the attack values of all the unit types.  That way, if a bonus existed for the last unit activated, that bonus no longer applies.  If a unit type is not in the defaultAttackTable, then we don&#039;t have the information to reset the attack value anyway, so we can safely ignore it by using the pairs function to iterate over the table.&lt;br /&gt;
&lt;br /&gt;
Now, we must find out if the newly activated unit deserves a bonus.  For that, we get the table associated with the active unit&#039;s type.  If the value is nil instead of a table, then the unit&#039;s type is not in the simpleAttackBonusTable, so there is no bonus to apply and the function returns.&lt;br /&gt;
&lt;br /&gt;
If the unit is eligible for bonuses, we then check the units in the square to see if any bonuses actually apply.  We&#039;ve seen this kind of code before.  If the unit in the stack can provide a bonus, and that bonus is better than the best bonus already found, the unit now provides the best bonus.  All bonus types that we can have are better if they are larger, and we are not comparing between bonus types, so a simple numerical comparison will do.  All bonuses are larger than 0 in our formulation, so 0 is a good starting value in the search.&lt;br /&gt;
&lt;br /&gt;
If the best bonus so far is still 0, there is no bonus, so the function can return.&lt;br /&gt;
&lt;br /&gt;
At this point, it occurs to me that when searching for the best bonus, we should exclude the active unit from the search.  That way, you can have a &amp;quot;strength in numbers&amp;quot; bonus, for example.  The relevant change to the code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    for unit in activeUnit.location.units do&lt;br /&gt;
        if unit ~= activeUnit and unitBonusTable[unit.type.id] and &lt;br /&gt;
 			unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, consider&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-08-AttackBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we apply the bonus that we&#039;ve found.  We use string.lower on simpleAttackBonusTable.type so that we don&#039;t have to worry about capitalization.  That does, however, require a correction to &amp;quot;addBonus&amp;quot;, since a lower case string will never be equal to that.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;addbonus&amp;quot; is the only type of bonus that is directly added to the existing attack value.  All other bonus types are a form of multiplication.  Since the addition is straightforward and doesn&#039;t require any rounding, the activeUnit&#039;s type attack value can be changed immediately, and the function execution ended with return.&lt;br /&gt;
&lt;br /&gt;
When there is only one bonus being applied, all other types of bonus are different ways of expressing how to multiply the existing attack value to get a new one, so we simply convert to the appropriate multiplier, and provide an error message if the type of bonus is not one of the valid possibilities.&lt;br /&gt;
&lt;br /&gt;
Finally, we round the attack value to an appropriate integer (since unit attack values must be integers), change the attack value of the active unit&#039;s type, and return to end the function execution.&lt;br /&gt;
&lt;br /&gt;
Now, we integrate into events.lua by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus = require(&amp;quot;attackBonus&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The relevant integration code for events.lua is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local defaultAttackValueTable = {[unitAliases.legion.id]=4}&lt;br /&gt;
 local simpleAttackBonusTable ={}&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=3,[unitAliases.musketeer.id]=4}&lt;br /&gt;
 &lt;br /&gt;
 local function doOnActivation(unit,source)&lt;br /&gt;
     munitions.payloadRestrictionCheck(unit,munitionSpecificationTable)&lt;br /&gt;
 	attackBonus.simpleAttackBonus(unit,simpleAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can check that the bonus is being applied correctly by checking the Civlopedia entry for legion and looking at the attack value.  The following cases must be tested (remember that activating a unit from the city screen doesn&#039;t run the onActivation event, so activate from the map).&lt;br /&gt;
&lt;br /&gt;
 Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
 Legion activated with archer, but no musketeer (7 attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (8 attack)&lt;br /&gt;
 Legion activated with archer and musketeer (8 attack)&lt;br /&gt;
 Legion activated with 2 archer, no musketeer (7 attack)&lt;br /&gt;
 Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
 Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
I recommend making a stack for each of these cases and activating them one by one.&lt;br /&gt;
To facilitate the test, add the following line to doOnActivation&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.ui.text(tostring(unit.type.attack))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You will want to comment out this line after testing.&lt;br /&gt;
&lt;br /&gt;
Next, change simpleAttackBonusTable to do &amp;quot;addpercent&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=30,[unitAliases.musketeer.id]=70}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With no rounding set, standard rounding is used&lt;br /&gt;
 Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
 Legion activated with archer and musketeer (7 attack)&lt;br /&gt;
 Legion activated with 2 archer, no musketeer (5 attack)&lt;br /&gt;
 Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
 Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
These numbers test both rounding up and rounding down.&lt;br /&gt;
&lt;br /&gt;
Now, use&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (6 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next,&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (6 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 simpleAttackBonusTable.round=&amp;quot;standard&amp;quot;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next, we test &amp;quot;addfraction&amp;quot;.  Since we&#039;ve tested all the rounding options, we don&#039;t have to do that again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=0.3,[unitAliases.musketeer.id]=0.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=130,[unitAliases.musketeer.id]=170}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiply&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
 Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Before we finish, we should test a legion bonus for the legion.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.legion.id]=2,[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Legion alone should have 4 attack.&lt;br /&gt;
 A second legion on the square should provide 8 attack instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, let us try to formulate a more complicated bonus system.  One thing we mentioned is that we&#039;d like the ability to get bonuses from multiple units, and to be able to get bonuses from different &amp;quot;classes&amp;quot; of units (like &amp;quot;artillery,&amp;quot; &amp;quot;cavalry,&amp;quot; and &amp;quot;ranged attackers.&amp;quot;  Something else we might want to do is to allow different kinds of bonuses.  That is, maybe some units should provide a fixed +2 to any unit receiving the bonus, so that it is better at improving units with a low attack value, while other units should provide a percentage bonus (making them better at supporting units with an already high attack value).  It turns out that both of these ideas are not too difficult to implement individually, but that trying to implement them together makes it problematic to find the best bonus.&lt;br /&gt;
&lt;br /&gt;
Let us implement a bonus system with multiple categories but only one bonus type.  In our specification, we will first specify a data type called &amp;quot;bonusCategory.&amp;quot;  It is still just a table (though we could add a metatable if we wanted), but it will help us make our specification clearer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- A &amp;quot;bonusCategory&amp;quot; is a table&lt;br /&gt;
 -- bonusCategory = {[bonusUnitType.id]=bonusNumber, maxBonusUnits=integer or nil, nextBonusValue = fraction or nil}&lt;br /&gt;
 -- In a bonusCategory, the value for bonusUnitType.id tells what the base bonus for that unit type is,&lt;br /&gt;
 -- maxBonusUnits is the maximum number of units that can provide a bonus in this category,&lt;br /&gt;
 -- nextBonusValue tells how much to reduce the bonus for each subsequent unit,&lt;br /&gt;
 -- e.g. nextBonusValue = 0.7, and 5 units, which each have a bonusNumber=1&lt;br /&gt;
 -- The total bonus is 1(0.7)^0+.7+(.7)(.7)+(.7)^3+(.7)^4 = 1+.7+.49+.343+.2401=2.7731&lt;br /&gt;
 -- (which would be rounded as specified)&lt;br /&gt;
 -- nil means nextBonusValue=1&lt;br /&gt;
 --&lt;br /&gt;
 -- If a unit type is in two bonus categories for the same unit, there is no guarantee that the&lt;br /&gt;
 -- best bonus will be achieved&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, the bonus category is indexed by unitType id numbers for units that can give a bonus, and the corresponding bonus.  It also specifies the maximum number of units that can give a bonus, and a number that governs how to reduce a bonus for extra units.  That way, there can be diminishing returns for bonuses.&lt;br /&gt;
&lt;br /&gt;
Next, we look at the specification for the categoryAttackBonusTable&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 --categoryAttackBonusTable[activeUnit.type.id] =table of bonusCategory&lt;br /&gt;
 --categoryAttackBonusTable.type = string&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up all the percents, then compute the bonus&lt;br /&gt;
 -- i.e. 50% bonus and 50% bonus is 100% bonus, not 125%&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 50% bonus units become 50% + 25% &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up the fractions, then compute the bonus&lt;br /&gt;
 -- i.e. .5 bonus and .5 bonus is 1+.5+.5= 2x bonus, not 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 .5 bonus units become .5+.25 &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 150% and 150% yields 225% of original value&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 100, i.e. nextBonusValue=.5 2 150% bonuses become 150% and 125%&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 1.5 and 1.5 yields 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 1, i.e. nextBonusValue=.5 and two 1.5 bonuses become 1.5 and 1.25&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 --categoryAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise&lt;br /&gt;
 &lt;br /&gt;
 -- If the active unit can get a bonus, go through each category and compute the bonus for that category.&lt;br /&gt;
 -- Then, combine the bonuses for all categories to get the overall bonus, and round the result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With the bonusCategory defined, the value of the unit indices of categoryAttackBonusTable become easy to define.  Most of the specification is showing what exactly the different bonus categories mean, so the end user can use them properly.  It&#039;s not strictly necessary to offer so many choices to the end user on how to specify data, but it can be more convenient.&lt;br /&gt;
&lt;br /&gt;
Here is the actual code (before testing) to implement this more general version of attack bonuses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- HELPER FUNCTION&lt;br /&gt;
 -- findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable) --&amp;gt; number or false&lt;br /&gt;
 -- usedUnitTable is indexed by the i.d. number of units, and if the value for a unit is true,&lt;br /&gt;
 -- then it has already been used for a bonus (and, so, is not eligible)&lt;br /&gt;
 -- The function returns the bonus (before nextBonusValue is applied) if there is one, and marks the &lt;br /&gt;
 -- unit as used in the usedUnitTable&lt;br /&gt;
 -- returns false if no unit qualifies&lt;br /&gt;
 local function findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable)&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
    local bestUnitSoFar = nil&lt;br /&gt;
    -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
    -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
    for unit in tile.units do&lt;br /&gt;
        if not usedUnitTable[unit.id] and bonusCategory[unit.type.id] &lt;br /&gt;
            and bonusCategory[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestUnitSoFar = unit&lt;br /&gt;
            bestBonusSoFar = bonusCategory[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if bestUnitSoFar then&lt;br /&gt;
        usedUnitTable[bestUnitSoFar.id] = true&lt;br /&gt;
        return bestBonusSoFar&lt;br /&gt;
    else&lt;br /&gt;
        return false&lt;br /&gt;
    end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 -- HELPER FUNCTION&lt;br /&gt;
 -- computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
 -- Computes the bonus that the active unit will receive from this category, taking into &lt;br /&gt;
 -- account the type of bonus for the table&lt;br /&gt;
 local function computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local bonusThusFar = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then &lt;br /&gt;
        bonusThusFar = 1&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        bonusThusFar = 100&lt;br /&gt;
    else&lt;br /&gt;
        bonusThusFar = 0&lt;br /&gt;
    end&lt;br /&gt;
    local bonusDiscount = 1&lt;br /&gt;
    for i=1,(bonusCategory.maxBonusUnits or 10000) do&lt;br /&gt;
        local currentBonus =findBestBonusInUnitStack(activeUnit.location,bonusCategory,usedUnitTable) &lt;br /&gt;
        if not currentBonus then&lt;br /&gt;
            -- no more valid bonuses for this category&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
        if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-1)*bonusDiscount+1)&lt;br /&gt;
        elseif bonusType ==&amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
        else&lt;br /&gt;
            bonusThusFar = bonusThusFar+currentBonus*bonusDiscount&lt;br /&gt;
        end&lt;br /&gt;
        bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
    end&lt;br /&gt;
    return bonusThusFar&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 local function categoryAttackBonus(activeUnit,categoryAttackBonusTable,defaultAttackTable)&lt;br /&gt;
    local bonusInfoTable = categoryAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
    if not bonusInfoTable then&lt;br /&gt;
        -- unit doesn&#039;t get a bonus&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
    -- keep track of bonuses already computed&lt;br /&gt;
    local bonusResultsTable = {}&lt;br /&gt;
    -- keep track of units that have already been &amp;quot;used&amp;quot; for a bonus&lt;br /&gt;
    local usedUnitTable = {[activeUnit.id]=true}&lt;br /&gt;
    for index,bonusCategory in pairs(bonusInfoTable) do&lt;br /&gt;
        bonusResultsTable[index]=computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    end&lt;br /&gt;
    -- compute the bonus&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local resultAttackBeforeRounding = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult/100&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack+bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+(bonusResult/100)&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    else&lt;br /&gt;
        error(&amp;quot;categoryAttackBonus: categoryAttackBonusTable.type is not a valid value.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    -- apply the bonus and round as appropriate&lt;br /&gt;
    local roundType = categoryAttackBonusTable.round&lt;br /&gt;
    if type(roundType) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;up&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.ceil(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;down&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    else&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two helper functions for computeCategoryBonus are only used once each in the code, so making them helper functions does not help us re-use code.  However, what it does do is to break down the function design process into smaller tasks, which are each more manageable to complete.  If you&#039;re trying to keep track of too many things in your program, try writing a few helper functions to handle individual tasks.  We&#039;ll look at the helper functions when we actually arrive at them in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-09-CategoryAtkBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If there is no entry in the categoryAttackBonusTable or the active unit&#039;s type, then the function returns without doing anything further.&lt;br /&gt;
&lt;br /&gt;
The bonusResultsTable keeps track of the total bonus from each category, so they can be added or multiplied together after all the category bonuses are applied.  The usedUnitsTable keeps track of units that are no longer eligible to contribute to a bonus (such as if they have already contributed), and we initialize it with the active unit, so that it doesn&#039;t provide a bonus to itself.&lt;br /&gt;
&lt;br /&gt;
The for loop computes the bonus for every category, and stores the value in the bonusResultsTable, for use later.Now, let us look at the helper functions.&lt;br /&gt;
&lt;br /&gt;
First up is findBestBonusInUnitStack&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-10-CategoryAtkBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This basically does what it says in the name.  For a bonusCategory, it finds the unit in the tile that provides the best bonus, and has not already provided a bonus elsewhere.  If there is no qualifying unit, false is returned.  If there is, that unit&#039;s bonus is returned, and the unit&#039;s id is entered into the usedUnitTable, so that unit can&#039;t provide another bonus for the active unit.  We&#039;ve searched for the best of something before, so there is little need to go over it again.&lt;br /&gt;
&lt;br /&gt;
Next is computeCategoryBonus&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-11-CategoryAtkBonus3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we&#039;re computing the bonus for the entire bonusCategory.  We need the bonus type in order to know what kind of math to do.  The math itself is not very interesting.  We also initialize the bonusDiscount, which keeps track of the fraction of the next unit&#039;s bonus that will actually be applied.&lt;br /&gt;
&lt;br /&gt;
Next, we enter a for loop that will run one time for each possible bonus that there can be in a bonus category.  If bonusCategory.maxBonusUnits is nil, then we set an arbitrary limit of 10000 units, which is very unlikely to happen in practice.&lt;br /&gt;
&lt;br /&gt;
At each iteration of the loop, the best available bonus in the stack is found.  If no unit was eligible to provide a bonus, then the current bonus is false, and the &amp;quot;break&amp;quot; command is issued.  Break immediately exits the current loop.  So, our program doesn&#039;t run 10000 loops if there is no maximum number of bonus units, it just breaks at an appropriate time.&lt;br /&gt;
&lt;br /&gt;
After the bonus is found, it is added to or multiplied with the bonus already found.  The bonus computed in this way will be the largest possible, since the bonus provided does not depend on the other units chosen (so we don&#039;t have a situation where &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; are both useless, but &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; chosen together are best).  Also, since the best bonus is chosen first, the smallest bonus discount applies to it, so the cost imposed by the discounting is smallest.&lt;br /&gt;
&lt;br /&gt;
Finally, we update the bonusDisount.  Here, I notice a problem in the code as written, since bonusCategory.nextBonusValue is allowed to be nil.  Replace&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
with &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*(bonusCategory.nextBonusValue or 1) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
so that if there is no nextBonusValue, a default of 1 is used, and the bonusDiscount stays at 1 (i.e. no discount is applied).&lt;br /&gt;
&lt;br /&gt;
We return to categoryAttackBonus to see&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-12-CategoryAtkBonus4.jpg]]&lt;br /&gt;
&lt;br /&gt;
From here, we combine the bonuses stored in bonusResultsTable, the exact way of doing so being dependant on the type of bonus involved.  The math itself isn&#039;t very interesting, and doesn&#039;t seem all that likely to come up in this exact form elsewhere.  If you need help with the mathematical details of some event you want to write, ask in the forums.  There&#039;s a good chance someone has the skills to help you solve your specific problem.&lt;br /&gt;
&lt;br /&gt;
For every type of bonus, the result is stored in resultAttackBeforeRounding, so that variable can be rounded up or down as specified by the rounding type.&lt;br /&gt;
&lt;br /&gt;
Here, I notice another error.  We should restrict the attack value for a unit to not exceed 98.  We can do that with a math.min(value, 98).&lt;br /&gt;
&lt;br /&gt;
Now, we need to test the various aspects of the attack bonus program, so we need an appropriate table&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addbonus&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=2,[unitAliases.chariot.id]=4,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=2,[unitAliases.musketeer.id]=4,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Also, comment out the old attack bonus line, and put in a new one&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus.categoryAttackBonus(unit,categoryAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
Already, we find a problem.  Although there were no syntax errors to fix, I forgot to reset unit attack values.  So, very quickly, the legions keep gathering extra attack values when they are activated (since the base attack is not reset to 4).  Since this is happening anyway, I&#039;ll test the 98 attack value maximum.  That appears to work, at least in the case of no specified rounding.&lt;br /&gt;
&lt;br /&gt;
Cut and paste the appropriate lines from the simpleAttackBonus to the categoryAttackBonus, and save.&lt;br /&gt;
&lt;br /&gt;
With that bug fixed, everything works as expected.&lt;br /&gt;
&lt;br /&gt;
Next, we change the categoryAttackBonusTable to &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addpercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=50,[unitAliases.chariot.id]=100,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=50,[unitAliases.musketeer.id]=100,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addpercent&amp;quot;.  These are the same, since adding we&#039;re adding percentages of the same base value of 4.  So a value of 2 is the same as adding 50% of 4.&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
The results are the same.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addfraction&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=.50,[unitAliases.chariot.id]=1.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.50,[unitAliases.musketeer.id]=1.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 10 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
 Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
We&#039;ll have to do some new calculations, now, since multiply and multiplyfraction give different results than the various adding formulations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiply&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=1.50,[unitAliases.chariot.id]=2.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=1.50,[unitAliases.musketeer.id]=2.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 12 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
 Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Finally, we use multiplyPercent, and check for the same results&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=150,[unitAliases.musketeer.id]=200,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 Legion:4attack&lt;br /&gt;
 Legion+chariot:8 attack&lt;br /&gt;
 Legion+chariot+chariot: 12 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
 Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
 Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
 Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Quickly, I find that if a bonus applies, that bonus makes the attack value of a legion 98.  I failed to multiply percents correctly in computeCategoryBonus.  The Line &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Is changed to &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+100)/100&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, Change archer bonus to 110 and musketeer bonus to 120 (so a unit will make a legion have 4.4 and 4.8 value before rounding), and test the rounding options.  You will find they all work.&lt;br /&gt;
&lt;br /&gt;
At the moment, we don&#039;t have a way to mix different types of bonuses.  As said earlier, we might want this so that some units can be better at giving bonuses to low attack units than to high attack units, while others give a percentage bonus to everything.  We could now write a bonus system that allows for multiple types of bonuses. However, the current bonus system allows for the bonus to change per unit.  This means that we can, for example, convert a +2 attack bonus to a plus 100% bonus for a unit with 2 attack, and a plus 50% bonus for a unit with 4 attack.  In the case of the multiplied bonuses, this will make the bonus more powerful if there is more than one.  That is, 2 attack, +2 twice is 6, but if +2 is changed to x2, then the multiplied bonus brings the attack up to 8.  However, this seems like it would be a relatively unlikely problem, and there are other things this code can&#039;t handle, so we&#039;ll let someone else make the code if they actually need it.&lt;br /&gt;
&lt;br /&gt;
So, what we&#039;ll do is write a function that will change all appropriate entries in the categoryAttackBonusTable to reflect a different value.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed(unitType,number,categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unit type to any unit to be equivalent&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, an issue with tables arises.  It is very likely that when someone defines their cateogryAttackBonusTable, they&#039;ll define it something like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.25,[unitAliases.musketeer.id]=.5}&lt;br /&gt;
 local bonusTableForInfantry = {rangeBonusCategory}&lt;br /&gt;
 local cABT = {type=&amp;quot;addfraction&amp;quot;}&lt;br /&gt;
 cABT[unitAliases.phalanx.id]=bonusTableForInfantry&lt;br /&gt;
 cABT[unitAliases.legion.id] = bonusTableForInfantry&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
However, this means that both &amp;lt;code&amp;gt; cABT[unitAliases.legion.id]  &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt; cABT[unitAliases.phalanx.id] &amp;lt;/code&amp;gt; actually refer to the same piece of memory, and changing cABT[unitAliases.legion.id][1][unitAliases.archer.id] will also change the value at cABT[unitAliases.phalanx.id][1][unitAliases.archer.id].  This is because of the way lua tables are designed.  This design can be useful, for example it allowed us to make changes to usedUnitsTable in the last function without having to copy the table, make changes to the copy of the table, and then replace the original table with that copy as a return value.  However, it also requires us to be careful when we make changes to entries in tables.  In this case, we&#039;ll simply copy the table and all its sub values into a new table.&lt;br /&gt;
&lt;br /&gt;
The code to do this is given by&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will explain this code in the next section, since it involves a programming technique which we haven&#039;t discussed before.&lt;br /&gt;
&lt;br /&gt;
For now, we analyze plusFixed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed({[unitType1.id]=fixedBonus,[unitType2.id]=fixedBonus},categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unitTypeI.id to a unit to be equivalent to&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power.  If the unit doesn&#039;t receive a bonus&lt;br /&gt;
 -- from the unitType, then it won&#039;t after applying plusFixed.&lt;br /&gt;
 -- The value of the existing bonus is ignored.&lt;br /&gt;
 &lt;br /&gt;
 local function plusFixed(fixedUnitBonusTable,categoryAttackBonusTable)&lt;br /&gt;
     local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
     for bonusReceivingUnitTypeID,bonusTable in pairs(categoryAttackBonusTable) do&lt;br /&gt;
         -- replace bonusTable with an equivalent table that is not referened&lt;br /&gt;
         -- anywhere else, so that changes to it can be made without impacting&lt;br /&gt;
         -- data elsewhere&lt;br /&gt;
         categoryAttackBonusTable[bonusReceivingUnitTypeID] = duplicateTable(bonusTable)&lt;br /&gt;
         -- make bonusTable refer to the &amp;quot;current&amp;quot; bonus table for the unit type&lt;br /&gt;
         bonusTable =categoryAttackBonusTable[bonusReceivingUnitTypeID] &lt;br /&gt;
         -- For each unit type in the fixedUnitBonusTable, check if any bonus category&lt;br /&gt;
         -- in the bonusTable corresponds to it.  If so, make the change&lt;br /&gt;
         for bonusGivingUnitTypeID,fixedBonusValue in pairs(fixedUnitBonusTable) do&lt;br /&gt;
             -- get the attack of the unit type &lt;br /&gt;
             local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
             -- in each bonus category, check if the giver&#039;s unit type id is there,&lt;br /&gt;
             -- if so, change to the correct attack&lt;br /&gt;
             for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
                 if bonusCategory[bonusGivingUnitTypeID] then&lt;br /&gt;
                 -- change the bonus appropriately&lt;br /&gt;
                     if bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue&lt;br /&gt;
                     elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*(fixedBonusValue+baseAttack)/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=(fixedBonusValue+baseAttack)/baseAttach&lt;br /&gt;
                     else&lt;br /&gt;
                         error(&amp;quot;pluxFixed: categoryAttackBonusTable.type does not have an acceptable value.&amp;quot;)&lt;br /&gt;
                     end&lt;br /&gt;
                 end&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-13-plusFixed1.jpg]]&lt;br /&gt;
&lt;br /&gt;
As before, we save the bonusType in lower case, since we&#039;ll be using it a lot later.  Next, we open a for loop, where the index is the id of the unit type receiving the bonus, and the value is the bonus table for that unit type.  Next, we duplicate the bonus table, so that we have a table we can change without impacting anything elsewhere, and we store the duplicated table in categoryAttackBonusTable in place of the original bonusTable for the current bonus receiving unit id.  Next, we assign this duplicated table to the variable bonusTable, so we can refer to it later in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-14-plusFixed2.jpg]]&lt;br /&gt;
&lt;br /&gt;
We now perform the following actions for each unitType.id and corresponding fixedBonusValue submitted in the fixedUnitBonusTable.&lt;br /&gt;
&lt;br /&gt;
First, get the attack of the bonus receiving unit, since we&#039;ll need that in order to customize the bonus.  Next, check each bonus category in the bonus table.  If the bonus category has the current unitTypeID as a key, then replace the existing value with a bonus equivalent to adding a fixed value to the receiving unit&#039;s attack.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all that must be done, so end all the loops.&lt;br /&gt;
&lt;br /&gt;
Now we test the function.&lt;br /&gt;
&lt;br /&gt;
Add unitAliases.phalanx = civ.getUnitType(3) to the appropriate file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 defaultAttackValueTable[unitAliases.phalanx.id]=1&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,&lt;br /&gt;
 								nextBonusValue=0.5,maxBonusUnits=1}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=125,[unitAliases.musketeer.id]=150,&lt;br /&gt;
 								nextBonusValue=0.75,maxBonusUnits=1}&lt;br /&gt;
 local standardBonus = {cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.phalanx.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 attackBonus.plusFixed({[unitAliases.chariot.id]=2,[unitAliases.musketeer.id]=2},&lt;br /&gt;
 						categoryAttackBonusTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The chariot and the musketeer individually should each add 2 to both a phalanx and a legion,&lt;br /&gt;
so the phalanx should have an attack of 3, and the legion should have an attack of 6, if one bonus&lt;br /&gt;
is applied.&lt;br /&gt;
&lt;br /&gt;
Since the bonus type is multiplypercent, together the phalanx would have an attack of 9, and the legion will also have an attack of 9.&lt;br /&gt;
&lt;br /&gt;
In testing, we quickly get this error&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
You should see this in lua console if this worked&lt;br /&gt;
...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: bad argument #1 to &#039;getUnitType&#039; (number expected, got string)&lt;br /&gt;
stack traceback:&lt;br /&gt;
	[C]: in function &#039;civ.getUnitType&#039;&lt;br /&gt;
	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At line 356, which is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This must mean that bonusReceivingUnitTypeID is not a number.  This is because we&#039;re looping over categoryAttackBonusTable, and that table has a couple of entries that are not integers (&amp;quot;type&amp;quot; and &amp;quot;round&amp;quot;).  Therefore, we have to insert code to deal with this eventuality.&lt;br /&gt;
&lt;br /&gt;
The simplest way is to put everything in the loop body into an if statement, so that it only runs when bonusGivingUnitTypeID is actually a number.  You should be able to do this without detailed instructions, so do so (hint: use type function).&lt;br /&gt;
&lt;br /&gt;
The next error is &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: bad argument #1 to &#039;pairs&#039; (table expected, got nil)&lt;br /&gt;
 stack traceback:&lt;br /&gt;
 	[C]: in function &#039;pairs&#039;&lt;br /&gt;
 	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
 	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 360 for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we have a nil value for bonusTable.  This turns out to be an error in duplicateTable.  When I duplicated the table, I forgot to return that table.  That is, both the if and else statement in that function need a return command, and I forgot to add &amp;lt;code&amp;gt; return duplicatedTable &amp;lt;/code&amp;gt; in the if portion.  Add this to the duplicate table function.&lt;br /&gt;
&lt;br /&gt;
After this, our predictions are true.  Testing the other types of bonus is left as an assignment.  You can find the completed code [https://forums.civfanatics.com/threads/totpp-attack-bonus-library.648093/ here].&lt;br /&gt;
&lt;br /&gt;
===Recursive Functions===&lt;br /&gt;
&lt;br /&gt;
Let us return to the duplicateTable function.  Recall that in the last section we added a line to it, so we&#039;ll restate it here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
 		return duplicatedTable&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-16-duplicateTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
The interesting thing about duplicateTable is that it invokes duplicateTable within its code.  When we copy the key-value pairs into the new table, we run duplicateTable on the value.  If the value is not a table, then we are in the else case, and the value is immediately returned to be inserted into the duplicated table.  If the value is a table, that table is duplicated before anything else is done.&lt;br /&gt;
&lt;br /&gt;
Let us look at a simple example of a recursive function, the factorial function N!.  In lesson 3, we discussed the factorial function in the context of loops.  Since N!=N*(N-1)*(N-2)*...*3*2*1, we can give another definition of N!:&lt;br /&gt;
N!=1 if N = 1&lt;br /&gt;
N!=N*(N-1)! if N &amp;gt; 1&lt;br /&gt;
Or, using the convention that 0!=1, we can state&lt;br /&gt;
N!=1 if N = 0&lt;br /&gt;
N!=N*(N-1)! if N &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
The case where N =1 or N=0 is called the &amp;quot;base case.&amp;quot;  If we keep substituting N! as N*(N-1)!, then we won&#039;t go on forever, because we will eventually reach a point where N=0, and N! can be substituted as 1 instead of N*(N-1)!.  As long as there is a base case, our program will eventually reach the base case(s), and begin &amp;quot;completing&amp;quot; evaluation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
function factorial(N)&lt;br /&gt;
if N&amp;gt;0 then&lt;br /&gt;
    return N*factorial(N-1)&lt;br /&gt;
else&lt;br /&gt;
    return 1&lt;br /&gt;
end&lt;br /&gt;
end&lt;br /&gt;
print(factorial(5))&lt;br /&gt;
print(factorial(6))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run this in code in the lua demo website, or using the TOTPP lua interpreter.&lt;br /&gt;
&lt;br /&gt;
Returning to our duplicateTable function, the base case is any time a table value is not itself a table.  When that happens, the recursion &amp;quot;chain&amp;quot; ends, and everything can evaluated.&lt;br /&gt;
&lt;br /&gt;
Although is shouldn&#039;t be a problem in this particular case, it should be noted that it is possible for there to not be a &amp;quot;base case&amp;quot; in the recursion style: if table, recur, if not return a value.  Consider the following table system&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
a={}&lt;br /&gt;
b={[1]=a}&lt;br /&gt;
a[1]=b&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In this case, the code would never end.&lt;br /&gt;
&lt;br /&gt;
It is possible that even if the code could &amp;quot;theoretically&amp;quot; execute to completion, you run out of memory before that.  This is called a &amp;quot;stack overflow,&amp;quot; and if it occurs, you will have to think of an alternate way to solve your problem.  It will probably be best to ask for help in that case (and it might be useful to provide others with an example of a problem that results in a stack overflow), but you might also look into &amp;quot;tail recursion&amp;quot;, including http://www.lua.org/pil/6.3.html .&lt;br /&gt;
&lt;br /&gt;
===Conclusion===&lt;br /&gt;
&lt;br /&gt;
With the skills covered in this chapter, you now have the tools to split a large events file into multiple files that are more manageable.  You also have the basics for how to write re-useable modules for your events, so that your work can be used by others.  Remember that if someone else uses your implementation of a feature, they will spend much less time coding and testing it, allowing them to either finish the scenario sooner, or to introduce some other feature.  So, it might very well pay to spend at least a little effort making your code into a reusable module.  Perhaps you have an idea for a cool scenario mechanic, but don&#039;t have a scenario for it (or don&#039;t want to take the time to make it).  If that&#039;s the case, just make the module and test it in a &amp;quot;toy&amp;quot; scenario (like Classic Rome) so that it can be used more or less &amp;quot;off the shelf&amp;quot; when someone needs it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5181</id>
		<title>Get Started With Lua Events Lesson 6: Splitting Code into Multiple Files</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5181"/>
		<updated>2019-07-26T14:38:01Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* A Munition Generation Module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This Lesson is under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
In this lesson, we will take a look at how to split the code for a scenario&#039;s events into multiple files.  There are several reasons to consider doing this.&lt;br /&gt;
&lt;br /&gt;
The first reason is simply to organize your work.  If you have a series of complicated events, the events.lua file can become very large very quickly. Once your events.lua file has thousands of lines of code in it, it may not be very obvious where the best place is to put that next helper function, or where to implement the function that runs a complicated event.  Sometimes even finding the piece of code that has to be changed can be a bit of a hassle.  In Over the Reich, I sometimes search for the associated civ.scen line, and then search for the exact name of the function I need.  Occasionally, there may even be more searching to find what I actually have to change.  With multiple files, it becomes easier to find things.&lt;br /&gt;
&lt;br /&gt;
Another aspect of using multiple files is that you can make certain changes without worrying about breaking things elsewhere.  If myBigComplicatedFunction relies on aModestHelperFunction for a certain part of its functionality, and a change to myBigComplicatedFunction also requires a change to aModestHelperFunction, you have to make sure that nothing else in your code also uses aModestHelperFunction, or, if something else does depend on it, that aModestHelperFunction either still provides the original functionality, or that all other functions that use aModestHelperFunction are suitably modified.  If myBigComplicatedFunction is defined in its own lua module, then you don&#039;t have to worry about forgetting that aModestHelperFunction was used elsewhere, since it can&#039;t be accessed outside the module unless you specifically allow it to be.&lt;br /&gt;
&lt;br /&gt;
A second reason to split events code into multiple files is to facilitate collaboration.  If all of the events are in a single file, then only one person can make changes to the file at a time.  If one partner starts changing an event, but has to do something else before finishing, everyone waits on one person&#039;s delay.  However, if most aspects of the scenario are separated into individual files, everyone can work on his or her own piece of the puzzle without depriving others of the opportunity to work at that time.&lt;br /&gt;
&lt;br /&gt;
A third reason to split events into multiple modules is to facilitate reusing code.  If everything required to implement an event is in its own file (or files), it becomes much easier for other creators to use your functionality in their scenario.  Since everything they need is already in one place, they don&#039;t have to find every last helper function, or concern themselves with naming conflicts.&lt;br /&gt;
&lt;br /&gt;
===Two Simple Examples===&lt;br /&gt;
&lt;br /&gt;
Let us look at the top of the events.lua file.  You can get the version that I started lesson 6 with [[here]].&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-01-DefaultRequire.jpg]]&lt;br /&gt;
&lt;br /&gt;
We get code from other files by using the command &amp;lt;code&amp;gt;require&amp;lt;/code&amp;gt; along with a string specifying the file name (except for the .lua extension).  At the moment, we can only get code stored in the lua folder in the Test of Time directory.  This is inconvenient if we&#039;re trying to distribute a scenario, since installing a scenario would require moving certain files to the lua directory, and those file names might conflict.  Instead, we need to tell the Lua interpreter to search in the same folder that the events.lua folder is in.&lt;br /&gt;
&lt;br /&gt;
To do this, we need the following code:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local eventsPath = string.gsub(debug.getinfo(1).source, &amp;quot;@&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 local scenarioFolderPath = string.gsub(eventsPath, &amp;quot;events.lua&amp;quot;, &amp;quot;?.lua&amp;quot;)&lt;br /&gt;
 if string.find(package.path, scenarioFolderPath, 1, true) == nil then&lt;br /&gt;
    package.path = package.path .. &amp;quot;;&amp;quot; .. scenarioFolderPath&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can probably cut and paste this code before the require lines in your events.lua file and not worry about how it works.  However, I&#039;ll provide a brief explanation for reference.&lt;br /&gt;
&lt;br /&gt;
The first line stores the location of the of the current file as a string in eventsPath.&lt;br /&gt;
&lt;br /&gt;
The second line replaces events.lua in the eventsPath with ?.lua, which will tell the Lua interpreter to look for .lua files in the current directory (that is to say, the directory with the events.lua file).  &lt;br /&gt;
&lt;br /&gt;
The if statement adds scenarioFolderPath to the places for the Lua interpreter to search for code, if that directory is not already in the search path.  Since the search path is kept active by the Lua interpreter, it will not be necessary to repeat these lines of code in every file that performs a require action as long as you are running the file as part of events.  If you are writing some other kind of code, you will need to substitute &amp;quot;events.lua&amp;quot; with the name of the file with the code you are running.  Note that for some reason, events.lua is always provided in lower case.  However, for use in other situations, debug.getinfo(1).source uses the correct case for event files. I have only briefly tested this, so you may have to do some testing yourself if this situation comes up (or ask for help in the forums).&lt;br /&gt;
&lt;br /&gt;
Now that we&#039;ve told Lua where to look for our extra code, we can begin moving code to other files.  Think of require as telling Lua to run the entire contents of another file as a function.  We can then assign a value to whatever that file returns, which will usually be a table.  A couple of examples will clarify.&lt;br /&gt;
&lt;br /&gt;
For our first example, we will move our scenario&#039;s parameters to a separate file, and access it via require.  This may not seem worthwhile in this example, but tables like this can get large in a hurry.  At the time of writing, Over the Reich has over 100 lines of parameters (&amp;quot;specialNumbers&amp;quot;), and parameters are something that a designer might like to play with while collaborators make other implementations.  Also, parameters will have to be referenced by other parts of the code, and a file that is required by events.lua cannot, in turn, require events.lua in order to get information.  That means that we&#039;ll have to keep our parameters in a separate file anyway.&lt;br /&gt;
&lt;br /&gt;
Cut the parameters table definition and paste it into a new file, classicRomeParameters.lua.  For the last line, write&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return parameters&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, Near the top of events.lua, where the existing require lines are, add the eventsPath code from above and also the line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local parameters = require(&amp;quot;classicRomeParameters&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
[[File:GetStartedWithLuaLesson6-02-RequireParameters.jpg]]&lt;br /&gt;
&lt;br /&gt;
Open the classicRome scenario and test out a couple of events to make sure everything is the same.&lt;br /&gt;
&lt;br /&gt;
We might find it convenient to put a few tables into the same file.  For this, we will simply return a table containing these tables, and give each table a name in the events.lua file.&lt;br /&gt;
&lt;br /&gt;
Create a file classicRomeAliases.lua and move all the &amp;quot;aliases&amp;quot; tables to that file.  Also move the getCityAt function.&lt;br /&gt;
&lt;br /&gt;
At the bottom of the file, put the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 unitAliases=unitAliases,&lt;br /&gt;
 tribeAliases=tribeAliases,&lt;br /&gt;
 tileAliases=tileAliases,&lt;br /&gt;
 cityAliases=cityAliases,&lt;br /&gt;
 textAliases=textAliases,&lt;br /&gt;
 terrainAliases=terrainAliases,&lt;br /&gt;
 improvementAliases=improvementAliases,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following lines to events.lua (in the require section)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local aliases = require(&amp;quot;classicRomeAliases&amp;quot;)&lt;br /&gt;
 local unitAliases,tribeAliases,tileAliases,cityAliases,textAliases,&lt;br /&gt;
 		terrainAliases,improvementAliases=aliases.unitAliases,aliases.tribeAliases,&lt;br /&gt;
 		aliases.tileAliases,aliases.cityAliases, aliases.textAliases,aliases.terrainAliases,&lt;br /&gt;
 		aliases.improvementAliases&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, our classicRomeAliases module is returning a table with our &amp;quot;alias&amp;quot; tables.  We then assign the entries in this returned table to local variables with the desired names.  Here, I use multiple variable assignment, which I don&#039;t believe I&#039;ve used before (even though Lua allows it), but these could just as simply have been assigned line by line.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-03-RequireAliases.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now, let us move the legion plundering code into its own file, which we&#039;ll call plunder.lua.  First, copy over the legionPlunder function, and paste it near the bottom of the new file.&lt;br /&gt;
&lt;br /&gt;
Now, let us go through the code of this function, and figure out what else we need in our plunder.lua module.&lt;br /&gt;
&lt;br /&gt;
The very first part of the function is a check against unitAliases.legion.  This means we need the unitAliases table, and so we copy the aliases require code to the top of plunder.lua.  We don&#039;t need the path information, since that will be added in events.lua.&lt;br /&gt;
&lt;br /&gt;
A few more lines down, we find that the function cityRadius is also used in legionPlunder.  Therefore, we move that over as well.  We also need the plunderValue function, so copy that over as well.&lt;br /&gt;
&lt;br /&gt;
Next, we check if cityRadius relies on anything, but it doesn&#039;t.&lt;br /&gt;
&lt;br /&gt;
Proceeding to plunderValue, we find that it relies on the parameters table, so require that as well.  The function plunderValue does not appear to depend on anything else, so we&#039;re done moving functionality.  If we missed something, the Lua interpreter will complain at some point anyway.&lt;br /&gt;
&lt;br /&gt;
Next, we require the plunder module in events.lua, with the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local plunder = require(&amp;quot;plunder&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, for each of the functions in plunder.lua, we check if it is used somewhere in events.lua.  We can do this by searching.  plunderValue isn&#039;t used anywhere, so we&#039;re done with that.  City radius is used.  At the bottom of plunder.lua, we begin our return table, and have&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 cityRadius=cityRadius,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, in events.lua, we replace the ocurance of cityRadius with plunder.cityRadius.  Alternatively, we could have put &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local cityRadius=plunder.cityRadius&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
after the line requiring plunder.&lt;br /&gt;
&lt;br /&gt;
Similarly, for legionPlunder, we add &amp;lt;code&amp;gt;legionPlunder=legionPlunder&amp;lt;/code&amp;gt; to the table that plunder.lua returns, and pre-append plunder. to legionPlunder in the one location where it occurs.&lt;br /&gt;
&lt;br /&gt;
Now, we test the legion plunder function and the press 4 generate archers function to make sure everything works.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-04-RequirePlunder.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Working With a Library===&lt;br /&gt;
&lt;br /&gt;
In programming terms, a &amp;quot;library&amp;quot; is a collection of code that can provide some specified functionality to a programmer without that programmer having to modify the code in the library.  Thus far, you have been using the &amp;quot;civ&amp;quot; library to interact with the game, and there has been no need modify it in order to use it in our own events.  (Unfortunately, in the case of the civ library, we don&#039;t actually know how to modify it.)  This is in contrast to much of the code we have written thus far.  For example, the code we wrote last lesson to make Selucid elephants attack Egypt is highly specific.  You couldn&#039;t just cut and paste that code, change the argument of a single function, and get your own goto event.  It is still a good example for how to write a goto event, but a user would still have to actually write the event.&lt;br /&gt;
&lt;br /&gt;
If you plan to write some functionality for your scenario that others might find useful, it is worth spending a little extra effort to see if you can write that functionality in a form that will allow others to use it with minimal effort.  If you can, then a little extra work on your part might save someone else the trouble of re-inventing the wheel, and allow them to complete their project sooner, or to work on some new feature for you to enjoy.  Unfortunately, the Lua scenarios that have been completed at the time of writing haven&#039;t been that good at creating re-usable code, at least in part since we were all getting used to Lua.  This will hopefully be improved in the future.&lt;br /&gt;
&lt;br /&gt;
For now, we&#039;re going to look at a library which is called the General Library (unless someone comes up with a better name) and which can be found [https://forums.civfanatics.com/threads/totpp-the-general-library.647583/ here].  The purpose of this module is to provide relatively simple functionality that probably shouldn&#039;t be implemented every time it is needed.  This is useful for our purposes, since we can look at relatively self contained and simple functions for our first examples.  We&#039;ll create a library for generating munitions later.&lt;br /&gt;
&lt;br /&gt;
This library would be used by invoking the line &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local gen = require(&amp;quot;generalLibrary&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to make these functions available to the console for testing purposes, you would simply omit the local, thereby making gen a global variable.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at a function provided by the General Library &amp;lt;code&amp;gt; gen.hasIrrigation(tile)--&amp;gt;boolean&amp;lt;/code&amp;gt;.  The very first line references the helper function &amp;lt;code&amp;gt; toTile(tile or table)--&amp;gt;tile&amp;lt;/code&amp;gt;, so let us include that code, and look at it first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 -- toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- gen.toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- If given a tile object, returns the tile&lt;br /&gt;
 -- If given coordinates for a tile, returns the tile&lt;br /&gt;
 -- Causes error otherwise&lt;br /&gt;
 -- Helper Function (provided to this library as toTile and gen.toTile)&lt;br /&gt;
 local function toTile(input)&lt;br /&gt;
     if civ.isTile(input) then&lt;br /&gt;
         return input&lt;br /&gt;
     elseif type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         local xVal = input[1] or input[&amp;quot;x&amp;quot;]&lt;br /&gt;
         local yVal = input[2] or input[&amp;quot;y&amp;quot;]&lt;br /&gt;
         local zVal = input[3] or input[&amp;quot;z&amp;quot;] or 0&lt;br /&gt;
         if type(xVal)==&amp;quot;number&amp;quot; and type(yVal)==&amp;quot;number&amp;quot; and type(zVal)==&amp;quot;number&amp;quot; then&lt;br /&gt;
             if civ.getTile(xVal,yVal,zVal) then&lt;br /&gt;
                 return civ.getTile(xVal,yVal,zVal)&lt;br /&gt;
             else&lt;br /&gt;
                 error(&amp;quot;Table with values {&amp;quot;..tostring(xVal)..&amp;quot;,&amp;quot;..tostring(yVal)..&lt;br /&gt;
                         &amp;quot;,&amp;quot;..tostring(zVal)..&amp;quot;} does not correspond to a valid tile.&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
         else&lt;br /&gt;
             error(&amp;quot;Table did not correspond to tile coordinates&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;Did not receive a tile object or table of coordinates.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 gen.toTile = toTile&lt;br /&gt;
 &lt;br /&gt;
 -- gen.hasIrrigation(tile)--&amp;gt;boolean&lt;br /&gt;
 -- returns true if tile has irrigation but no farm&lt;br /&gt;
 -- returns false otherwise&lt;br /&gt;
 function gen.hasIrrigation(tile)&lt;br /&gt;
     tile = toTile(tile)&lt;br /&gt;
     local improvements = tile.improvements&lt;br /&gt;
     -- irrigation, but no mining, so not farmland&lt;br /&gt;
     if improvements &amp;amp; 0x04 == 0x04 and improvements &amp;amp; 0x08 == 0 then&lt;br /&gt;
         return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-05-HasIrrigation.jpg]]&lt;br /&gt;
&lt;br /&gt;
Let us begin by looking at the function &amp;lt;code&amp;gt;toTile&amp;lt;/code&amp;gt;.  The purpose of this function is to allow other functions to accept tile coordinates in a table instead of an actual tile object.  The function tries to be reasonably permissive in the coordinates it will accept, allowing both integer indices and lowercase string indices, and by assuming that a missing z value corresponds to map 0.  The function also tries to give reasonably helpful errors.&lt;br /&gt;
&lt;br /&gt;
This brings up something that should be considered when making reusable code: what to do if you don&#039;t get values you were expecting.  One option is to throw an error and bring up the Lua console.  This is good for scenario creators, so they know something is wrong, but not so great for end users because the error stops the rest of the event from happening, should the mistake slip through playtesting.&lt;br /&gt;
&lt;br /&gt;
The other option is for the code to fail silently, and try to do what it can.  This is the way the old Test of Time macro system often fails.  If Civ II doesn&#039;t &amp;quot;understand&amp;quot; the event, it just doesn&#039;t happen, and doesn&#039;t bother the player with the error.  This means that the scenario will still mostly work, but it is harder to catch issues during playtesting.  Sometimes, this means doing something &amp;quot;sensible&amp;quot; if the input isn&#039;t of the expected type, and might make the code easier to write, since you don&#039;t have to handle inputs differently.&lt;br /&gt;
&lt;br /&gt;
A third option is to write your code such that both things can be done.  At the top of your code, you put in a variable named &amp;quot;debugMode&amp;quot; or something, and make all the functions throw errors when true, and fail silently when false.  Then you playtest with debugMode set to true, and release with debug mode set to false.  However, this means extra work in writing your code and you also have to test everything with debug mode off.&lt;br /&gt;
&lt;br /&gt;
For toTile, I went with the fail with error option, since that will allow every function that uses toTile to assume it is receiving proper data.  It also seems unlikely that people will be regularly trying to check tiles that don&#039;t exist or have tables with tiles and units and improvement objects all in one.  And if they do, &amp;quot;guarding&amp;quot; is fairly straightforward anyway (as we&#039;ve done in previous lessons).&lt;br /&gt;
&lt;br /&gt;
Although toTile is mainly meant to be a helper function for the General Library, it is also put into the gen table to be made available to end users, since it offers useful functionality.  Hence, &amp;lt;code&amp;gt; gen.toTile=toTile&amp;lt;/code&amp;gt;.  Note that we could have given toTile a different name in the gen table that this module will return, such as gen.tableToTile=toTile.  In fact, we could refer to the same function with multiple keys in the gen table, if we want to.&lt;br /&gt;
&lt;br /&gt;
Next, we will look at gen.hasIrrigation.&lt;br /&gt;
&lt;br /&gt;
The first thing to notice is that local is not being used to define this function.  That is because we&#039;re putting the function for gen.hasIrrigation directly into the gen table that this module will return.  We could define hasIrrigation as a local variable and then copy it into the gen table.  However, there is a decent chance that the General Library will have more than 200 functions by the time everything is complete, since it is meant to provide a lot of building block functionality and keep it in one place, and we will run into trouble if we assign 200 local variables in a single function (which a required lua file acts as).&lt;br /&gt;
&lt;br /&gt;
Perhaps the most striking thing is that we begin by changing the value of tile, the argument of the function.  It looks like we&#039;re making a global variable named tile, but we&#039;re not.  When you specify the names of the arguments for a function (in this case tile), you create local variables for that function, which can be given new values just as if you had explicitly used the local keyword.&lt;br /&gt;
&lt;br /&gt;
Beyond that, we extract the integer representing the tile improvements into a local variable (which upon later reflection isn&#039;t really necessary), and check that the irrigation bit is set to 1 and the mining bit is set to 0.  Refer to lesson 5 for why this works.  In fact, we could have simply returned the value of the if statement, rather than specifying return true and return false, although it is very slightly clearer what is going on in the expanded version of the code.&lt;br /&gt;
&lt;br /&gt;
Now, let us write a function to place irrigation on a square.  It seems pretty clear that we should do nothing if the tile has a city, but we also have to decide what to do if there is mining or farmland on the tile, since those interfere with placing irrigation.  We&#039;ll just remove them, on the basis that if we&#039;re trying to &amp;quot;place irrigation,&amp;quot; then we want irrigation to be there when we are finished.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function gen.placeIrrigation(tile)&lt;br /&gt;
    tile = toTile(tile)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These lines open the function and convert a table of coordinates to a tile if necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 if tile.city then&lt;br /&gt;
    return&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the tile has a city, return so nothing else is done in the function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     -- Set irrigation bit to 1&lt;br /&gt;
     tile.improvements = tile.improvements | 0x04&lt;br /&gt;
     -- Set mining bit to 0&lt;br /&gt;
     tile.improvements = tile.improvements &amp;amp; ~0x08&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the irrigation bit to 1 and the mining bit to 0.&lt;br /&gt;
&lt;br /&gt;
The functions in this library don&#039;t have to be complex, and in fact, most probably shouldn&#039;t be.  They just have to make life easier for the end user.  If you reach this lesson before the General Library is considered &amp;quot;complete,&amp;quot; your assignment now is to submit some work for it.  If you don&#039;t feel comfortable doing bitwise operations, you can test the work of others or submit functions that simplify other tasks.  However, there are also some helper functions in the library to facilitate changing bits, so you might also consider working on the unit type flags functions.  Remember, if you want to make functions available to the console for testing purposes, they must be global variables.&lt;br /&gt;
&lt;br /&gt;
=== The Threshold Table and First Look at Metatables===&lt;br /&gt;
&lt;br /&gt;
Consider a scenario design situation that occurred in Over the Reich: a bomber is generating some bombs via a key press, and the number of bombs it should generate is dependant on its current remaining hitpoints.  The more hitpoints the bomber has, the more bombs it should generate.  What we want is to specify that if a bomber has between x and y hitpoints, it should produce 2 bombs.  That is, for a given type of bomber, we want to have, for example,&lt;br /&gt;
&lt;br /&gt;
hp &amp;gt;= 16 --&amp;gt; 4 bombs&lt;br /&gt;
16 &amp;gt; hp &amp;gt;= 12 --&amp;gt; 3 bombs&lt;br /&gt;
12 &amp;gt; hp &amp;gt;= 9 --&amp;gt; 2 bombs&lt;br /&gt;
9 &amp;gt; hp &amp;gt;= 4 --&amp;gt; 1 bomb&lt;br /&gt;
4 &amp;gt; hp &amp;gt;= 0 --&amp;gt; 0 bombs&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Lua tables do not naturally encode this kind of association by default.  However, Lua does have a feature called metatables, which allows us to change the behaviour of tables.  (This will be a much better way to make the specification than I ended up writing in Over the Reich.)&lt;br /&gt;
&lt;br /&gt;
A metatable is a table that we can &amp;quot;attach&amp;quot; to another table, and then the metatable changes the behaviour of that table.  We&#039;ll only look at metatables briefly here, but more information can be found [https://www.tutorialspoint.com/lua/lua_metatables.htm here].&lt;br /&gt;
&lt;br /&gt;
What we want is a data structure that can accept numerical &amp;quot;key values&amp;quot; that are between the key values explicitly specified, and return the appropriate value for those keys.  We will call this data structure a threshold table, since we are specifying threshold values as keys.  We can do this by assigning the following metatable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local mt = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we run &amp;lt;code&amp;gt; setmetatable(myTable,mt)&amp;lt;/code&amp;gt;, then whenever we ask for an index from myTable and that index doesn&#039;t currently exist in myTable, the function assigned to __index will run.  Now let us examine the function.&lt;br /&gt;
&lt;br /&gt;
If the type of the key is not a number, then we return whatever the table value is for that key.  We use the function rawget, because the standard &amp;lt;code&amp;gt;thresholdTable[key]&amp;lt;/code&amp;gt; will invoke this function again if the key doesn&#039;t exist, and so never return an answer (when we want it to return nil).&lt;br /&gt;
&lt;br /&gt;
If the key type is a number, then we look for the largest numerical index that is also less than or equal to the key value.  We return a default value of false if the key submitted is smaller than all numerical values.  False is chosen over nil, so that a maximum value can be set by setting the value of a numerical index to false.  Using the key [-math.huge] allows a return value to be set for all numbers (since all numbers are greater than -math.huge).&lt;br /&gt;
&lt;br /&gt;
Since we don&#039;t want scenario creators to have to re-create threshold tables every time they need them, we&#039;ll add this functionality to the General Library&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local thresholdTableMetatable = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 -- gen.makeThresholdTable(table or nil)--&amp;gt;thresholdTable&lt;br /&gt;
 function gen.makeThresholdTable(inputTable)&lt;br /&gt;
     inputTable = inputTable or {}&lt;br /&gt;
     return setmetatable(inputTable,thresholdTableMetatable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-06-ThresholdTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
===A Munition Generation Module===&lt;br /&gt;
&lt;br /&gt;
Now, let us write some re-usable code for a human player to generate units by pressing a key while an appropriate unit is active.  This sort of code could be used for ranged attacks (generating a &amp;quot;munition&amp;quot;) and also for recruiting mercenaries by paying gold.&lt;br /&gt;
&lt;br /&gt;
The first thing we will want to do is to decide how our code will be used by the end user.  This will, perhaps, change by the time we finish writing the code, but it will at least give us a starting point.&lt;br /&gt;
&lt;br /&gt;
spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&lt;br /&gt;
&lt;br /&gt;
Our goal is that when a player attempts to generate a unit using another unit, they will provide the unit spawning the new unit, and a table of information specifying if a unit (or units) can be spawned and anything else that must happen while spawning (like paying money, expending movement points, etc.).&lt;br /&gt;
&lt;br /&gt;
We have an option here.  We could have the scenario creator provide the specification table as a required file for our module, or the creator can provide it at the time spawnUnit is called.  I choose the latter for a couple of reasons.  The first is that it allows the player to have more than one specification table, either because more than one key can spawn a unit, or because the specification can change over time.  The other is reason is so that the creator can make the table in the events.lua file if desired (since our module can&#039;t require information from events.lua).&lt;br /&gt;
&lt;br /&gt;
Having decided that our generateUnit events are going to be specified by a table, we have to decide what the contents of that table should be.  It seems pretty reasonable to index the specificationTable with the index of the unit type of each unit that can generate using the information in the table.  If a unit type id number is missing, that unit doesn&#039;t generate a munition (or recruit a unit).&lt;br /&gt;
&lt;br /&gt;
The value for each unit type id in the specification table will be a table that specifies how and if that unit generates other units.&lt;br /&gt;
&lt;br /&gt;
 --specificationTable[unitType.id]={&lt;br /&gt;
 --&lt;br /&gt;
 -- goldCost = integer or nil&lt;br /&gt;
 --      amount of gold it costs to generate a unit&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minTreasury = integer or nil&lt;br /&gt;
 --      minimum amount of gold in treasury to generate a unit&lt;br /&gt;
 --      absent means refer to gold cost&lt;br /&gt;
 --      (tribe will generate and be set to 0 if treasury is less than goldCost)&lt;br /&gt;
 -- treasuryFailMessage = string or nil&lt;br /&gt;
 --      A message to be displayed if the unit fails to spawn a unit due to an &lt;br /&gt;
 --      insufficient treasury&lt;br /&gt;
 --      nil means no message&lt;br /&gt;
&lt;br /&gt;
 -- There are three ways to specify move costs, in full movement points,&lt;br /&gt;
 -- in &amp;quot;atomic&amp;quot; movement points, and as a fraction of total movement points for the&lt;br /&gt;
 -- unit type.  Use only one kind per unit type &lt;br /&gt;
 &lt;br /&gt;
 -- moveCost = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMove = integer or nil&lt;br /&gt;
 --      minimum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
 --      absent means any movement points for land/sea, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMove = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostAtomic = integer or nil&lt;br /&gt;
 --      movement points to be expended generating the unit&lt;br /&gt;
 --      refers to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveAtomic = integer or nil&lt;br /&gt;
 --      minumum remaining movement points to be allowed to generate a unit&lt;br /&gt;
 --      referes to the unit.moveSpent movement points&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- postGenMinMoveAtomic = integer or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- moveCostFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points expended generating the unit&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 --      absent means 0&lt;br /&gt;
 -- minMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      fraction of unit&#039;s total movement points that must remain to be allowed&lt;br /&gt;
 --      to generate a unit&lt;br /&gt;
 --      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 --      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
 -- postGenMinMoveFraction = number in [0,1] or nil&lt;br /&gt;
 --      a unit will be left with at least this many movement points after&lt;br /&gt;
 --      the generation function, round up to nearest &amp;quot;atomic&amp;quot; move point&lt;br /&gt;
 --      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
 -- roundFractionFull = bool or nil&lt;br /&gt;
 --      fractional movement cost and minimum are rounded up to full movement point&lt;br /&gt;
 --      instead of atomic movement point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- roundFractionFullDown = bool or nil&lt;br /&gt;
 --      fractional cost and minimum are rounded down to full move point&lt;br /&gt;
 --      nil/false means don&#039;t&lt;br /&gt;
 -- minMoveFailMessage = string or nil&lt;br /&gt;
 --      a message to be displayed if a unit is not generated due to insufficient&lt;br /&gt;
 --      movement points.&lt;br /&gt;
 --      nil means no message &lt;br /&gt;
&lt;br /&gt;
 -- allowedTerrainTypes = table of integers or nil&lt;br /&gt;
 --      a unit may only be generated if the tile it is standing on&lt;br /&gt;
 --      corresponds to one of numbers in the table&lt;br /&gt;
 --      nil means the unit can be generated on any terrain type&lt;br /&gt;
 -- terrainTypeFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to standing&lt;br /&gt;
 --      on the incorrect terrain &lt;br /&gt;
&lt;br /&gt;
 -- requiredTech = tech object or nil&lt;br /&gt;
 --      the generating civ must have this technology in order to generate&lt;br /&gt;
 --      the unit&lt;br /&gt;
 --      nil means no requirement&lt;br /&gt;
 -- techFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to not having&lt;br /&gt;
 --      the correct technology &lt;br /&gt;
&lt;br /&gt;
 -- payload = boolean or string&lt;br /&gt;
 --      if true, unit must have a home city in order to generate munitions&lt;br /&gt;
 --      and generating munitions sets the home city to NONE&lt;br /&gt;
 -- payloadFailMessage = string or nil&lt;br /&gt;
 --      message to be displayed if a unit is not generated due to the &lt;br /&gt;
 --      payload restriction&lt;br /&gt;
 -- payloadRestrictionCheck = nil or function(unit)--&amp;gt;boolean&lt;br /&gt;
 --      If function returns false, the home city is not valid for giving the&lt;br /&gt;
 --      unit a payload.  This will be checked when the unit is activated, when&lt;br /&gt;
 --      the unit is given a new home city with the &#039;h&#039; key and when the unit&lt;br /&gt;
 --      tries to generate a munition&lt;br /&gt;
 --      nil means no restriction&lt;br /&gt;
 -- payloadRestrictionMessage = nil or string&lt;br /&gt;
 --      message to show if a unit fails the payloadRestrictionCheck&lt;br /&gt;
&lt;br /&gt;
 -- canGenerateFunction = nil or function(unit)--&amp;gt;boolean &lt;br /&gt;
 --      This function applied to the generating unit must return true in order&lt;br /&gt;
 --      for a unit to be spawned.  All other conditions still apply.&lt;br /&gt;
 --      any failure message should be part of canGenerateFunction&lt;br /&gt;
 --      absent means no extra conditions &lt;br /&gt;
&lt;br /&gt;
 -- generateUnitFunction = nil or function(unit)--&amp;gt;table of unit&lt;br /&gt;
 --      This function creates the unit or units to be generated&lt;br /&gt;
 --      and returns a table containing those units&lt;br /&gt;
 --      Ignore any specifications prefixed with * if this is used&lt;br /&gt;
 --      nil means use other specifications &lt;br /&gt;
&lt;br /&gt;
 --*generatedUnitType = unitType&lt;br /&gt;
 --      The type of unit to be generated&lt;br /&gt;
 --      can&#039;t be nil unless generateUnitFunction is used instead &lt;br /&gt;
&lt;br /&gt;
 --*giveVeteran = bool or nil&lt;br /&gt;
 --      generated unit(s) given veteran status if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
 --      if true, overrides copyVeteranStatus&lt;br /&gt;
&lt;br /&gt;
 --*copyVeteranStatus = bool or nil&lt;br /&gt;
 --      generated unit(s) copy veteran status of generating unit if true&lt;br /&gt;
 --      nil or false means don&#039;t give vet status&lt;br /&gt;
&lt;br /&gt;
 --*setHomeCityFunction = nil or function(generatingUnit)--&amp;gt;cityObject&lt;br /&gt;
 --      determines what home city the spawned unit should have&lt;br /&gt;
 --      nil means a home city of NONE &lt;br /&gt;
&lt;br /&gt;
 --*numberToGenerate = nil or number or thresholdTable or function(generatingUnit)--&amp;gt;number&lt;br /&gt;
 --      if nil, generate 1 unit in all circumstances&lt;br /&gt;
 --      if integer, generate that many units (generate 0 if number less than 0)&lt;br /&gt;
 --      if number not integer, generate floor(number), and 1 more with&lt;br /&gt;
 --      probability number-floor(number)&lt;br /&gt;
 --      if thresholdTable, use remaining hp as the key, to get the number to create&lt;br /&gt;
 --      if function, get the number as the returned value of the function &lt;br /&gt;
&lt;br /&gt;
 -- activate = bool or nil&lt;br /&gt;
 --      Activates one of the generated units if true.  If generateUnitFunction was used,&lt;br /&gt;
 --      the unit at index 1 is activated, if index 1 has a value.  (if not, any unit in&lt;br /&gt;
 --      the list might be chosen)&lt;br /&gt;
&lt;br /&gt;
The very last entry brings forward a change that must be made to our unit generation specification.  Lua&#039;s activate unit command doesn&#039;t run the unit activation trigger, even though the active unit is changed.  Therefore, we must do that manually.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
becomes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit,specificationTable,unitActivationCode)--&amp;gt;table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Perhaps we will change it again later.&lt;br /&gt;
&lt;br /&gt;
I&#039;ve decided to try a different instructional technique for this section.  Instead of writing the code and then going through it section by section, I&#039;ve recorded a video of my coding and testing this module, and I attempt to explain some of the stuff that I do along the way.&lt;br /&gt;
&lt;br /&gt;
I&#039;m not sure of the value of the video.  If you find that there seems to be little useful content relative to the time it takes to watch, then feel free to skip it and continue the lesson.  I don&#039;t teach anything &amp;quot;new&amp;quot; in it, so you won&#039;t miss anything crucial.  However, it should be pretty close to how programming Lua can actually happen in the &amp;quot;real world.&amp;quot;  While I did give some thought to how to write the module before I started, I do attempt to solve problems in real time, and make mistakes that are not discovered for a while (including one where I try to explain how I solve a problem and then not actually do a crucial part).&lt;br /&gt;
&lt;br /&gt;
You can find the code [https://forums.civfanatics.com/threads/totpp-the-munitions-library.647910/ here].  Even if you decide not to watch the video, download the code and try testing some of the features based on the specification above.  If you find any bugs, submit a fix (or at least report the issue).&lt;br /&gt;
&lt;br /&gt;
The video can be found [https://youtu.be/XxPyNknGlAo here].&lt;br /&gt;
&lt;br /&gt;
===A Unit Attack Bonus for Complementary Units in Square===&lt;br /&gt;
&lt;br /&gt;
Something we might like to do is to give units an attack bonus if they attack from a square with some special unit, for example a &amp;quot;leader&amp;quot; unit.  The [[Napoléon I]] scenario, for example, gives an attack bonus to units if a commander unit, such as Napoleon, is in the square when the unit is activated (the unit can subsequently move and still retain the bonus as long as no other unit is selected).  We will now make a module providing the same functionality.&lt;br /&gt;
&lt;br /&gt;
We first have to have a basic idea of how this functionality should work.  When a unit is activated, the onActivateUnit event checks if the newly activated unit should get an attack bonus, based on the other units in the square.  If the unit deserves an attack bonus, the corresponding unitType.attack entry is changed, and all the attack value of all other units is reset to the default value.  If the activated unit also does not deserve an attack bonus, that value is also set to the default value.&lt;br /&gt;
&lt;br /&gt;
This now leads us to some more possibilities.  Should multiple bonus units lead to multiple bonuses or only apply the best one?  For example, suppose a legion gets a bonus if an archer is also in the same square.  Should two archers provide twice the bonus?  Perhaps two archers should provide a larger bonus than one, but not twice as much.  Perhaps a legion should also get a bonus if there is a catapult in the square, but that bonus should apply even if the maximum archer bonus is already achieved.  It seems like perhaps there should be a &amp;quot;ranged unit&amp;quot; bonus, an &amp;quot;artillery unit&amp;quot; bonus and maybe a &amp;quot;cavalry&amp;quot; bonus which should all impact the legion&#039;s attack value.  It&#039;s looking like we might end up demanding that a scenario creator make a big complicated table in order to use this functionality, even if they only have simple needs.&lt;br /&gt;
&lt;br /&gt;
What we can do to alleviate this is to write a &amp;quot;simple&amp;quot; version of the event that is easy to use (and program), and also write a more complicated version that gives the expanded capability.&lt;br /&gt;
&lt;br /&gt;
Specification Table for simpleAttackBonus&lt;br /&gt;
&lt;br /&gt;
--simpleAttackBonusTable[activeUnit.type.id] ={[bonusUnitType.id]=bonusNumber}&lt;br /&gt;
--simpleAttackBonusTable.type = string&lt;br /&gt;
--if simpleAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
-- add the bonusNumber to the base attack&lt;br /&gt;
--if simpleAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
-- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
-- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
--if simpleAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
-- add the fraction of the attack value to the attack,&lt;br /&gt;
-- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
-- if simpleAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
-- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
-- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
-- if simpleAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
-- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
-- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
--simpleAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
-- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
-- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
-- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
-- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
-- if fraction part is less than 0.5, and rounded up otherwise&lt;br /&gt;
&lt;br /&gt;
The relevant first draft of the code is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function simpleAttackBonus(activeUnit,simpleAttackBonusTable,defaultAttackTable)&lt;br /&gt;
     -- reset all unit attack values&lt;br /&gt;
     for unitTypeID,attackValue in pairs(defaultAttackTable) do&lt;br /&gt;
         civ.getUnitType(unitTypeID).attack = attackValue&lt;br /&gt;
     end&lt;br /&gt;
     local unitBonusTable = simpleAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
     if not unitBonusTable then&lt;br /&gt;
         -- unitBonusTable is nil (or false), so the active unit can&#039;t&lt;br /&gt;
         -- get a bonus&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
     -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
     for unit in activeUnit.location.units do&lt;br /&gt;
         if unitBonusTable[unit.type.id] and unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
             bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     if bestBonusSoFar == 0 then&lt;br /&gt;
         -- If no bonus unit is found, this will be true, so do nothing else&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- set the new attack and return&lt;br /&gt;
     if string.lower(simpleAttackBonusTable.type) == &amp;quot;addBonus&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = activeUnit.type.attack+bestBonusSoFar&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     local attackMultiplier = 1&lt;br /&gt;
     if type(simpleAttackBonusTable.type) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = (100+bestBonusSoFar)/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
         attackMultiplier = 1+bestBonusSoFar&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar&lt;br /&gt;
     else&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     end&lt;br /&gt;
     -- apply the bonus and round as appropriate&lt;br /&gt;
     if type(simpleAttackBonusTable.round) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;up&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.ceil(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;down&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     else&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now let us go over this section by section.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-07-AttackBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The first thing we do is to reset all the attack values of all the unit types.  That way, if a bonus existed for the last unit activated, that bonus no longer applies.  If a unit type is not in the defaultAttackTable, then we don&#039;t have the information to reset the attack value anyway, so we can safely ignore it by using the pairs function to iterate over the table.&lt;br /&gt;
&lt;br /&gt;
Now, we must find out if the newly activated unit deserves a bonus.  For that, we get the table associated with the active unit&#039;s type.  If the value is nil instead of a table, then the unit&#039;s type is not in the simpleAttackBonusTable, so there is no bonus to apply and the function returns.&lt;br /&gt;
&lt;br /&gt;
If the unit is eligible for bonuses, we then check the units in the square to see if any bonuses actually apply.  We&#039;ve seen this kind of code before.  If the unit in the stack can provide a bonus, and that bonus is better than the best bonus already found, the unit now provides the best bonus.  All bonus types that we can have are better if they are larger, and we are not comparing between bonus types, so a simple numerical comparison will do.  All bonuses are larger than 0 in our formulation, so 0 is a good starting value in the search.&lt;br /&gt;
&lt;br /&gt;
If the best bonus so far is still 0, there is no bonus, so the function can return.&lt;br /&gt;
&lt;br /&gt;
At this point, it occurs to me that when searching for the best bonus, we should exclude the active unit from the search.  That way, you can have a &amp;quot;strength in numbers&amp;quot; bonus, for example.  The relevant change to the code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    for unit in activeUnit.location.units do&lt;br /&gt;
        if unit ~= activeUnit and unitBonusTable[unit.type.id] and &lt;br /&gt;
			unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, consider&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-08-AttackBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we apply the bonus that we&#039;ve found.  We use string.lower on simpleAttackBonusTable.type so that we don&#039;t have to worry about capitalization.  That does, however, require a correction to &amp;quot;addBonus&amp;quot;, since a lower case string will never be equal to that.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;addbonus&amp;quot; is the only type of bonus that is directly added to the existing attack value.  All other bonus types are a form of multiplication.  Since the addition is straightforward and doesn&#039;t require any rounding, the activeUnit&#039;s type attack value can be changed immediately, and the function execution ended with return.&lt;br /&gt;
&lt;br /&gt;
When there is only one bonus being applied, all other types of bonus are different ways of expressing how to multiply the existing attack value to get a new one, so we simply convert to the appropriate multiplier, and provide an error message if the type of bonus is not one of the valid possibilities.&lt;br /&gt;
&lt;br /&gt;
Finally, we round the attack value to an appropriate integer (since unit attack values must be integers), change the attack value of the active unit&#039;s type, and return to end the function execution.&lt;br /&gt;
&lt;br /&gt;
Now, we integrate into events.lua by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus = require(&amp;quot;attackBonus&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The relevant integration code for events.lua is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local defaultAttackValueTable = {[unitAliases.legion.id]=4}&lt;br /&gt;
 local simpleAttackBonusTable ={}&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=3,[unitAliases.musketeer.id]=4}&lt;br /&gt;
 &lt;br /&gt;
 local function doOnActivation(unit,source)&lt;br /&gt;
     munitions.payloadRestrictionCheck(unit,munitionSpecificationTable)&lt;br /&gt;
 	attackBonus.simpleAttackBonus(unit,simpleAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can check that the bonus is being applied correctly by checking the Civlopedia entry for legion and looking at the attack value.  The following cases must be tested (remember that activating a unit from the city screen doesn&#039;t run the onActivation event, so activate from the map).&lt;br /&gt;
&lt;br /&gt;
Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
Legion activated with archer, but no musketeer (7 attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (8 attack)&lt;br /&gt;
Legion activated with archer and musketeer (8 attack)&lt;br /&gt;
Legion activated with 2 archer, no musketeer (7 attack)&lt;br /&gt;
Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
Activate some other unit (should have regular attack value).&lt;br /&gt;
I recommend making a stack for each of these cases and activating them one by one.&lt;br /&gt;
To facilitate the test, add the following line to doOnActivation&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.ui.text(tostring(unit.type.attack))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You will want to comment out this line after testing.&lt;br /&gt;
&lt;br /&gt;
Next, change simpleAttackBonusTable to do &amp;quot;addpercent&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=30,[unitAliases.musketeer.id]=70}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With no rounding set, standard rounding is used&lt;br /&gt;
Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
Legion activated with archer and musketeer (7 attack)&lt;br /&gt;
Legion activated with 2 archer, no musketeer (5 attack)&lt;br /&gt;
Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
These numbers test both rounding up and rounding down.&lt;br /&gt;
&lt;br /&gt;
Now, use&lt;br /&gt;
simpleAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
Legion activated with archer, but no musketeer (6 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next,&lt;br /&gt;
simpleAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (6 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
simpleAttackBonusTable.round=&amp;quot;standard&amp;quot;&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next, we test &amp;quot;addfraction&amp;quot;.  Since we&#039;ve tested all the rounding options, we don&#039;t have to do that again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=0.3,[unitAliases.musketeer.id]=0.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=130,[unitAliases.musketeer.id]=170}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiply&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Before we finish, we should test a legion bonus for the legion.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.legion.id]=2,[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Legion alone should have 4 attack.&lt;br /&gt;
A second legion on the square should provide 8 attack instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, let us try to formulate a more complicated bonus system.  One thing we mentioned is that we&#039;d like the ability to get bonuses from multiple units, and to be able to get bonuses from different &amp;quot;classes&amp;quot; of units (like &amp;quot;artillery,&amp;quot; &amp;quot;cavalry,&amp;quot; and &amp;quot;ranged attackers.&amp;quot;  Something else we might want to do is to allow different kinds of bonuses.  That is, maybe some units should provide a fixed +2 to any unit receiving the bonus, so that it is better at improving units with a low attack value, while other units should provide a percentage bonus (making them better at supporting units with an already high attack value).  It turns out that both of these ideas are not too difficult to implement individually, but that trying to implement them together makes it problematic to find the best bonus.&lt;br /&gt;
&lt;br /&gt;
Let us implement a bonus system with multiple categories but only one bonus type.  In our specification, we will first specify a data type called &amp;quot;bonusCategory.&amp;quot;  It is still just a table (though we could add a metatable if we wanted), but it will help us make our specification clearer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- A &amp;quot;bonusCategory&amp;quot; is a table&lt;br /&gt;
 -- bonusCategory = {[bonusUnitType.id]=bonusNumber, maxBonusUnits=integer or nil, nextBonusValue = fraction or nil}&lt;br /&gt;
 -- In a bonusCategory, the value for bonusUnitType.id tells what the base bonus for that unit type is,&lt;br /&gt;
 -- maxBonusUnits is the maximum number of units that can provide a bonus in this category,&lt;br /&gt;
 -- nextBonusValue tells how much to reduce the bonus for each subsequent unit,&lt;br /&gt;
 -- e.g. nextBonusValue = 0.7, and 5 units, which each have a bonusNumber=1&lt;br /&gt;
 -- The total bonus is 1(0.7)^0+.7+(.7)(.7)+(.7)^3+(.7)^4 = 1+.7+.49+.343+.2401=2.7731&lt;br /&gt;
 -- (which would be rounded as specified)&lt;br /&gt;
 -- nil means nextBonusValue=1&lt;br /&gt;
 --&lt;br /&gt;
 -- If a unit type is in two bonus categories for the same unit, there is no guarantee that the&lt;br /&gt;
 -- best bonus will be achieved&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, the bonus category is indexed by unitType id numbers for units that can give a bonus, and the corresponding bonus.  It also specifies the maximum number of units that can give a bonus, and a number that governs how to reduce a bonus for extra units.  That way, there can be diminishing returns for bonuses.&lt;br /&gt;
&lt;br /&gt;
Next, we look at the specification for the categoryAttackBonusTable&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 --categoryAttackBonusTable[activeUnit.type.id] =table of bonusCategory&lt;br /&gt;
 --categoryAttackBonusTable.type = string&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up all the percents, then compute the bonus&lt;br /&gt;
 -- i.e. 50% bonus and 50% bonus is 100% bonus, not 125%&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 50% bonus units become 50% + 25% &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up the fractions, then compute the bonus&lt;br /&gt;
 -- i.e. .5 bonus and .5 bonus is 1+.5+.5= 2x bonus, not 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 .5 bonus units become .5+.25 &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 150% and 150% yields 225% of original value&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 100, i.e. nextBonusValue=.5 2 150% bonuses become 150% and 125%&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 1.5 and 1.5 yields 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 1, i.e. nextBonusValue=.5 and two 1.5 bonuses become 1.5 and 1.25&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 --categoryAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise&lt;br /&gt;
 &lt;br /&gt;
 -- If the active unit can get a bonus, go through each category and compute the bonus for that category.&lt;br /&gt;
 -- Then, combine the bonuses for all categories to get the overall bonus, and round the result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With the bonusCategory defined, the value of the unit indices of categoryAttackBonusTable become easy to define.  Most of the specification is showing what exactly the different bonus categories mean, so the end user can use them properly.  It&#039;s not strictly necessary to offer so many choices to the end user on how to specify data, but it can be more convenient.&lt;br /&gt;
&lt;br /&gt;
Here is the actual code (before testing) to implement this more general version of attack bonuses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-- HELPER FUNCTION&lt;br /&gt;
-- findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable) --&amp;gt; number or false&lt;br /&gt;
-- usedUnitTable is indexed by the i.d. number of units, and if the value for a unit is true,&lt;br /&gt;
-- then it has already been used for a bonus (and, so, is not eligible)&lt;br /&gt;
-- The function returns the bonus (before nextBonusValue is applied) if there is one, and marks the &lt;br /&gt;
-- unit as used in the usedUnitTable&lt;br /&gt;
-- returns false if no unit qualifies&lt;br /&gt;
local function findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable)&lt;br /&gt;
    local bestBonusSoFar = 0&lt;br /&gt;
    local bestUnitSoFar = nil&lt;br /&gt;
    -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
    -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
    for unit in tile.units do&lt;br /&gt;
        if not usedUnitTable[unit.id] and bonusCategory[unit.type.id] &lt;br /&gt;
            and bonusCategory[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestUnitSoFar = unit&lt;br /&gt;
            bestBonusSoFar = bonusCategory[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if bestUnitSoFar then&lt;br /&gt;
        usedUnitTable[bestUnitSoFar.id] = true&lt;br /&gt;
        return bestBonusSoFar&lt;br /&gt;
    else&lt;br /&gt;
        return false&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- HELPER FUNCTION&lt;br /&gt;
-- computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
-- Computes the bonus that the active unit will receive from this category, taking into &lt;br /&gt;
-- account the type of bonus for the table&lt;br /&gt;
local function computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local bonusThusFar = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then &lt;br /&gt;
        bonusThusFar = 1&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        bonusThusFar = 100&lt;br /&gt;
    else&lt;br /&gt;
        bonusThusFar = 0&lt;br /&gt;
    end&lt;br /&gt;
    local bonusDiscount = 1&lt;br /&gt;
    for i=1,(bonusCategory.maxBonusUnits or 10000) do&lt;br /&gt;
        local currentBonus =findBestBonusInUnitStack(activeUnit.location,bonusCategory,usedUnitTable) &lt;br /&gt;
        if not currentBonus then&lt;br /&gt;
            -- no more valid bonuses for this category&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
        if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-1)*bonusDiscount+1)&lt;br /&gt;
        elseif bonusType ==&amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
        else&lt;br /&gt;
            bonusThusFar = bonusThusFar+currentBonus*bonusDiscount&lt;br /&gt;
        end&lt;br /&gt;
        bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
    end&lt;br /&gt;
    return bonusThusFar&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function categoryAttackBonus(activeUnit,categoryAttackBonusTable,defaultAttackTable)&lt;br /&gt;
    local bonusInfoTable = categoryAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
    if not bonusInfoTable then&lt;br /&gt;
        -- unit doesn&#039;t get a bonus&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
    -- keep track of bonuses already computed&lt;br /&gt;
    local bonusResultsTable = {}&lt;br /&gt;
    -- keep track of units that have already been &amp;quot;used&amp;quot; for a bonus&lt;br /&gt;
    local usedUnitTable = {[activeUnit.id]=true}&lt;br /&gt;
    for index,bonusCategory in pairs(bonusInfoTable) do&lt;br /&gt;
        bonusResultsTable[index]=computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    end&lt;br /&gt;
    -- compute the bonus&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local resultAttackBeforeRounding = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult/100&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack+bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+(bonusResult/100)&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    else&lt;br /&gt;
        error(&amp;quot;categoryAttackBonus: categoryAttackBonusTable.type is not a valid value.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    -- apply the bonus and round as appropriate&lt;br /&gt;
    local roundType = categoryAttackBonusTable.round&lt;br /&gt;
    if type(roundType) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;up&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.ceil(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;down&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    else&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two helper functions for computeCategoryBonus are only used once each in the code, so making them helper functions does not help us re-use code.  However, what it does do is to break down the function design process into smaller tasks, which are each more manageable to complete.  If you&#039;re trying to keep track of too many things in your program, try writing a few helper functions to handle individual tasks.  We&#039;ll look at the helper functions when we actually arrive at them in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-09-CategoryAtkBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If there is no entry in the categoryAttackBonusTable or the active unit&#039;s type, then the function returns without doing anything further.&lt;br /&gt;
&lt;br /&gt;
The bonusResultsTable keeps track of the total bonus from each category, so they can be added or multiplied together after all the category bonuses are applied.  The usedUnitsTable keeps track of units that are no longer eligible to contribute to a bonus (such as if they have already contributed), and we initialize it with the active unit, so that it doesn&#039;t provide a bonus to itself.&lt;br /&gt;
&lt;br /&gt;
The for loop computes the bonus for every category, and stores the value in the bonusResultsTable, for use later.Now, let us look at the helper functions.&lt;br /&gt;
&lt;br /&gt;
First up is findBestBonusInUnitStack&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-10-CategoryAtkBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This basically does what it says in the name.  For a bonusCategory, it finds the unit in the tile that provides the best bonus, and has not already provided a bonus elsewhere.  If there is no qualifying unit, false is returned.  If there is, that unit&#039;s bonus is returned, and the unit&#039;s id is entered into the usedUnitTable, so that unit can&#039;t provide another bonus for the active unit.  We&#039;ve searched for the best of something before, so there is little need to go over it again.&lt;br /&gt;
&lt;br /&gt;
Next is computeCategoryBonus&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-11-CategoryAtkBonus3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we&#039;re computing the bonus for the entire bonusCategory.  We need the bonus type in order to know what kind of math to do.  The math itself is not very interesting.  We also initialize the bonusDiscount, which keeps track of the fraction of the next unit&#039;s bonus that will actually be applied.&lt;br /&gt;
&lt;br /&gt;
Next, we enter a for loop that will run one time for each possible bonus that there can be in a bonus category.  If bonusCategory.maxBonusUnits is nil, then we set an arbitrary limit of 10000 units, which is very unlikely to happen in practice.&lt;br /&gt;
&lt;br /&gt;
At each iteration of the loop, the best available bonus in the stack is found.  If no unit was eligible to provide a bonus, then the current bonus is false, and the &amp;quot;break&amp;quot; command is issued.  Break immediately exits the current loop.  So, our program doesn&#039;t run 10000 loops if there is no maximum number of bonus units, it just breaks at an appropriate time.&lt;br /&gt;
&lt;br /&gt;
After the bonus is found, it is added to or multiplied with the bonus already found.  The bonus computed in this way will be the largest possible, since the bonus provided does not depend on the other units chosen (so we don&#039;t have a situation where &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; are both useless, but &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; chosen together are best).  Also, since the best bonus is chosen first, the smallest bonus discount applies to it, so the cost imposed by the discounting is smallest.&lt;br /&gt;
&lt;br /&gt;
Finally, we update the bonusDisount.  Here, I notice a problem in the code as written, since bonusCategory.nextBonusValue is allowed to be nil.  Replace&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
with &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*(bonusCategory.nextBonusValue or 1) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
so that if there is no nextBonusValue, a default of 1 is used, and the bonusDiscount stays at 1 (i.e. no discount is applied).&lt;br /&gt;
&lt;br /&gt;
We return to categoryAttackBonus to see&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-12-CategoryAtkBonus4.jpg]]&lt;br /&gt;
&lt;br /&gt;
From here, we combine the bonuses stored in bonusResultsTable, the exact way of doing so being dependant on the type of bonus involved.  The math itself isn&#039;t very interesting, and doesn&#039;t seem all that likely to come up in this exact form elsewhere.  If you need help with the mathematical details of some event you want to write, ask in the forums.  There&#039;s a good chance someone has the skills to help you solve your specific problem.&lt;br /&gt;
&lt;br /&gt;
For every type of bonus, the result is stored in resultAttackBeforeRounding, so that variable can be rounded up or down as specified by the rounding type.&lt;br /&gt;
&lt;br /&gt;
Here, I notice another error.  We should restrict the attack value for a unit to not exceed 98.  We can do that with a math.min(value, 98).&lt;br /&gt;
&lt;br /&gt;
Now, we need to test the various aspects of the attack bonus program, so we need an appropriate table&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addbonus&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=2,[unitAliases.chariot.id]=4,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=2,[unitAliases.musketeer.id]=4,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Also, comment out the old attack bonus line, and put in a new one&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus.categoryAttackBonus(unit,categoryAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addbonus&amp;quot;&lt;br /&gt;
Legion:4attack&lt;br /&gt;
Legion+chariot:8 attack&lt;br /&gt;
Legion+chariot+chariot: 10 attack&lt;br /&gt;
Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
Already, we find a problem.  Although there were no syntax errors to fix, I forgot to reset unit attack values.  So, very quickly, the legions keep gathering extra attack values when they are activated (since the base attack is not reset to 4).  Since this is happening anyway, I&#039;ll test the 98 attack value maximum.  That appears to work, at least in the case of no specified rounding.&lt;br /&gt;
&lt;br /&gt;
Cut and paste the appropriate lines from the simpleAttackBonus to the categoryAttackBonus, and save.&lt;br /&gt;
&lt;br /&gt;
With that bug fixed, everything works as expected.&lt;br /&gt;
&lt;br /&gt;
Next, we change the categoryAttackBonusTable to &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addpercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=50,[unitAliases.chariot.id]=100,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=50,[unitAliases.musketeer.id]=100,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addpercent&amp;quot;.  These are the same, since adding we&#039;re adding percentages of the same base value of 4.  So a value of 2 is the same as adding 50% of 4.&lt;br /&gt;
Legion:4attack&lt;br /&gt;
Legion+chariot:8 attack&lt;br /&gt;
Legion+chariot+chariot: 10 attack&lt;br /&gt;
Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
The results are the same.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addfraction&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=.50,[unitAliases.chariot.id]=1.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.50,[unitAliases.musketeer.id]=1.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion:4attack&lt;br /&gt;
Legion+chariot:8 attack&lt;br /&gt;
Legion+chariot+chariot: 10 attack&lt;br /&gt;
Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
We&#039;ll have to do some new calculations, now, since multiply and multiplyfraction give different results than the various adding formulations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiply&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=1.50,[unitAliases.chariot.id]=2.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=1.50,[unitAliases.musketeer.id]=2.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion:4attack&lt;br /&gt;
Legion+chariot:8 attack&lt;br /&gt;
Legion+chariot+chariot: 12 attack&lt;br /&gt;
Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Finally, we use multiplyPercent, and check for the same results&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=150,[unitAliases.musketeer.id]=200,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion:4attack&lt;br /&gt;
Legion+chariot:8 attack&lt;br /&gt;
Legion+chariot+chariot: 12 attack&lt;br /&gt;
Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Quickly, I find that if a bonus applies, that bonus makes the attack value of a legion 98.  I failed to multiply percents correctly in computeCategoryBonus.  The Line &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Is changed to &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+100)/100&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, Change archer bonus to 110 and musketeer bonus to 120 (so a unit will make a legion have 4.4 and 4.8 value before rounding), and test the rounding options.  You will find they all work.&lt;br /&gt;
&lt;br /&gt;
At the moment, we don&#039;t have a way to mix different types of bonuses.  As said earlier, we might want this so that some units can be better at giving bonuses to low attack units than to high attack units, while others give a percentage bonus to everything.  We could now write a bonus system that allows for multiple types of bonuses. However, the current bonus system allows for the bonus to change per unit.  This means that we can, for example, convert a +2 attack bonus to a plus 100% bonus for a unit with 2 attack, and a plus 50% bonus for a unit with 4 attack.  In the case of the multiplied bonuses, this will make the bonus more powerful if there is more than one.  That is, 2 attack, +2 twice is 6, but if +2 is changed to x2, then the multiplied bonus brings the attack up to 8.  However, this seems like it would be a relatively unlikely problem, and there are other things this code can&#039;t handle, so we&#039;ll let someone else make the code if they actually need it.&lt;br /&gt;
&lt;br /&gt;
So, what we&#039;ll do is write a function that will change all appropriate entries in the categoryAttackBonusTable to reflect a different value.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed(unitType,number,categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unit type to any unit to be equivalent&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, an issue with tables arises.  It is very likely that when someone defines their cateogryAttackBonusTable, they&#039;ll define it something like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.25,[unitAliases.musketeer.id]=.5}&lt;br /&gt;
 local bonusTableForInfantry = {rangeBonusCategory}&lt;br /&gt;
 local cABT = {type=&amp;quot;addfraction&amp;quot;}&lt;br /&gt;
 cABT[unitAliases.phalanx.id]=bonusTableForInfantry&lt;br /&gt;
 cABT[unitAliases.legion.id] = bonusTableForInfantry&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
However, this means that both &amp;lt;code&amp;gt; cABT[unitAliases.legion.id]  &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt; cABT[unitAliases.phalanx.id] &amp;lt;/code&amp;gt; actually refer to the same piece of memory, and changing cABT[unitAliases.legion.id][1][unitAliases.archer.id] will also change the value at cABT[unitAliases.phalanx.id][1][unitAliases.archer.id].  This is because of the way lua tables are designed.  This design can be useful, for example it allowed us to make changes to usedUnitsTable in the last function without having to copy the table, make changes to the copy of the table, and then replace the original table with that copy as a return value.  However, it also requires us to be careful when we make changes to entries in tables.  In this case, we&#039;ll simply copy the table and all its sub values into a new table.&lt;br /&gt;
&lt;br /&gt;
The code to do this is given by&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will explain this code in the next section, since it involves a programming technique which we haven&#039;t discussed before.&lt;br /&gt;
&lt;br /&gt;
For now, we analyze plusFixed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed({[unitType1.id]=fixedBonus,[unitType2.id]=fixedBonus},categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unitTypeI.id to a unit to be equivalent to&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power.  If the unit doesn&#039;t receive a bonus&lt;br /&gt;
 -- from the unitType, then it won&#039;t after applying plusFixed.&lt;br /&gt;
 -- The value of the existing bonus is ignored.&lt;br /&gt;
 &lt;br /&gt;
 local function plusFixed(fixedUnitBonusTable,categoryAttackBonusTable)&lt;br /&gt;
     local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
     for bonusReceivingUnitTypeID,bonusTable in pairs(categoryAttackBonusTable) do&lt;br /&gt;
         -- replace bonusTable with an equivalent table that is not referened&lt;br /&gt;
         -- anywhere else, so that changes to it can be made without impacting&lt;br /&gt;
         -- data elsewhere&lt;br /&gt;
         categoryAttackBonusTable[bonusReceivingUnitTypeID] = duplicateTable(bonusTable)&lt;br /&gt;
         -- make bonusTable refer to the &amp;quot;current&amp;quot; bonus table for the unit type&lt;br /&gt;
         bonusTable =categoryAttackBonusTable[bonusReceivingUnitTypeID] &lt;br /&gt;
         -- For each unit type in the fixedUnitBonusTable, check if any bonus category&lt;br /&gt;
         -- in the bonusTable corresponds to it.  If so, make the change&lt;br /&gt;
         for bonusGivingUnitTypeID,fixedBonusValue in pairs(fixedUnitBonusTable) do&lt;br /&gt;
             -- get the attack of the unit type &lt;br /&gt;
             local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
             -- in each bonus category, check if the giver&#039;s unit type id is there,&lt;br /&gt;
             -- if so, change to the correct attack&lt;br /&gt;
             for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
                 if bonusCategory[bonusGivingUnitTypeID] then&lt;br /&gt;
                 -- change the bonus appropriately&lt;br /&gt;
                     if bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue&lt;br /&gt;
                     elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*(fixedBonusValue+baseAttack)/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=(fixedBonusValue+baseAttack)/baseAttach&lt;br /&gt;
                     else&lt;br /&gt;
                         error(&amp;quot;pluxFixed: categoryAttackBonusTable.type does not have an acceptable value.&amp;quot;)&lt;br /&gt;
                     end&lt;br /&gt;
                 end&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-13-plusFixed1.jpg]]&lt;br /&gt;
&lt;br /&gt;
As before, we save the bonusType in lower case, since we&#039;ll be using it a lot later.  Next, we open a for loop, where the index is the id of the unit type receiving the bonus, and the value is the bonus table for that unit type.  Next, we duplicate the bonus table, so that we have a table we can change without impacting anything elsewhere, and we store the duplicated table in categoryAttackBonusTable in place of the original bonusTable for the current bonus receiving unit id.  Next, we assign this duplicated table to the variable bonusTable, so we can refer to it later in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-14-plusFixed2.jpg]]&lt;br /&gt;
&lt;br /&gt;
We now perform the following actions for each unitType.id and corresponding fixedBonusValue submitted in the fixedUnitBonusTable.&lt;br /&gt;
&lt;br /&gt;
First, get the attack of the bonus receiving unit, since we&#039;ll need that in order to customize the bonus.  Next, check each bonus category in the bonus table.  If the bonus category has the current unitTypeID as a key, then replace the existing value with a bonus equivalent to adding a fixed value to the receiving unit&#039;s attack.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all that must be done, so end all the loops.&lt;br /&gt;
&lt;br /&gt;
Now we test the function.&lt;br /&gt;
&lt;br /&gt;
Add unitAliases.phalanx = civ.getUnitType(3) to the appropriate file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 defaultAttackValueTable[unitAliases.phalanx.id]=1&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,&lt;br /&gt;
 								nextBonusValue=0.5,maxBonusUnits=1}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=125,[unitAliases.musketeer.id]=150,&lt;br /&gt;
 								nextBonusValue=0.75,maxBonusUnits=1}&lt;br /&gt;
 local standardBonus = {cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.phalanx.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 attackBonus.plusFixed({[unitAliases.chariot.id]=2,[unitAliases.musketeer.id]=2},&lt;br /&gt;
 						categoryAttackBonusTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The chariot and the musketeer individually should each add 2 to both a phalanx and a legion,&lt;br /&gt;
so the phalanx should have an attack of 3, and the legion should have an attack of 6, if one bonus&lt;br /&gt;
is applied.&lt;br /&gt;
&lt;br /&gt;
Since the bonus type is multiplypercent, together the phalanx would have an attack of 9, and the legion will also have an attack of 9.&lt;br /&gt;
&lt;br /&gt;
In testing, we quickly get this error&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
You should see this in lua console if this worked&lt;br /&gt;
...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: bad argument #1 to &#039;getUnitType&#039; (number expected, got string)&lt;br /&gt;
stack traceback:&lt;br /&gt;
	[C]: in function &#039;civ.getUnitType&#039;&lt;br /&gt;
	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At line 356, which is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This must mean that bonusReceivingUnitTypeID is not a number.  This is because we&#039;re looping over categoryAttackBonusTable, and that table has a couple of entries that are not integers (&amp;quot;type&amp;quot; and &amp;quot;round&amp;quot;).  Therefore, we have to insert code to deal with this eventuality.&lt;br /&gt;
&lt;br /&gt;
The simplest way is to put everything in the loop body into an if statement, so that it only runs when bonusGivingUnitTypeID is actually a number.  You should be able to do this without detailed instructions, so do so (hint: use type function).&lt;br /&gt;
&lt;br /&gt;
The next error is &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: bad argument #1 to &#039;pairs&#039; (table expected, got nil)&lt;br /&gt;
 stack traceback:&lt;br /&gt;
 	[C]: in function &#039;pairs&#039;&lt;br /&gt;
 	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
 	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 360 for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we have a nil value for bonusTable.  This turns out to be an error in duplicateTable.  When I duplicated the table, I forgot to return that table.  That is, both the if and else statement in that function need a return command, and I forgot to add &amp;lt;code&amp;gt; return duplicatedTable &amp;lt;/code&amp;gt; in the if portion.  Add this to the duplicate table function.&lt;br /&gt;
&lt;br /&gt;
After this, our predictions are true.  Testing the other types of bonus is left as an assignment.&lt;br /&gt;
&lt;br /&gt;
===Recursive Functions===&lt;br /&gt;
&lt;br /&gt;
Let us return to the duplicateTable function.  Recall that in the last section we added a line to it, so we&#039;ll restate it here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
 		return duplicatedTable&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-16-duplicateTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
The interesting thing about duplicateTable is that it invokes duplicateTable within its code.  When we copy the key-value pairs into the new table, we run duplicateTable on the value.  If the value is not a table, then we are in the else case, and the value is immediately returned to be inserted into the duplicated table.  If the value is a table, that table is duplicated before anything else is done.&lt;br /&gt;
&lt;br /&gt;
Let us look at a simple example of a recursive function, the factorial function N!.  In lesson 3, we discussed the factorial function in the context of loops.  Since N!=N*(N-1)*(N-2)*...*3*2*1, we can give another definition of N!:&lt;br /&gt;
N!=1 if N = 1&lt;br /&gt;
N!=N*(N-1)! if N &amp;gt; 1&lt;br /&gt;
Or, using the convention that 0!=1, we can state&lt;br /&gt;
N!=1 if N = 0&lt;br /&gt;
N!=N*(N-1)! if N &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
The case where N =1 or N=0 is called the &amp;quot;base case.&amp;quot;  If we keep substituting N! as N*(N-1)!, then we won&#039;t go on forever, because we will eventually reach a point where N=0, and N! can be substituted as 1 instead of N*(N-1)!.  As long as there is a base case, our program will eventually reach the base case(s), and begin &amp;quot;completing&amp;quot; evaluation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
function factorial(N)&lt;br /&gt;
if N&amp;gt;0 then&lt;br /&gt;
    return N*factorial(N-1)&lt;br /&gt;
else&lt;br /&gt;
    return 1&lt;br /&gt;
end&lt;br /&gt;
end&lt;br /&gt;
print(factorial(5))&lt;br /&gt;
print(factorial(6))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run this in code in the lua demo website, or using the TOTPP lua interpreter.&lt;br /&gt;
&lt;br /&gt;
Returning to our duplicateTable function, the base case is any time a table value is not itself a table.  When that happens, the recursion &amp;quot;chain&amp;quot; ends, and everything can evaluated.&lt;br /&gt;
&lt;br /&gt;
Although is shouldn&#039;t be a problem in this particular case, it should be noted that it is possible for there to not be a &amp;quot;base case&amp;quot; in the recursion style: if table, recur, if not return a value.  Consider the following table system&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
a={}&lt;br /&gt;
b={[1]=a}&lt;br /&gt;
a[1]=b&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In this case, the code would never end.&lt;br /&gt;
&lt;br /&gt;
It is possible that even if the code could &amp;quot;theoretically&amp;quot; execute to completion, you run out of memory before that.  This is called a &amp;quot;stack overflow,&amp;quot; and if it occurs, you will have to think of an alternate way to solve your problem.  It will probably be best to ask for help in that case (and it might be useful to provide others with an example of a problem that results in a stack overflow), but you might also look into &amp;quot;tail recursion&amp;quot;, including http://www.lua.org/pil/6.3.html .&lt;br /&gt;
&lt;br /&gt;
===Conclusion===&lt;br /&gt;
&lt;br /&gt;
With the skills covered in this chapter, you now have the tools to split a large events file into multiple files that are more manageable.  You also have the basics for how to write re-useable modules for your events, so that your work can be used by others.  Remember that if someone else uses your implementation of a feature, they will spend much less time coding and testing it, allowing them to either finish the scenario sooner, or to introduce some other feature.  So, it might very well pay to spend at least a little effort making your code into a reusable module.  Perhaps you have an idea for a cool scenario mechanic, but don&#039;t have a scenario for it (or don&#039;t want to take the time to make it).  If that&#039;s the case, just make the module and test it in a &amp;quot;toy&amp;quot; scenario (like Classic Rome) so that it can be used more or less &amp;quot;off the shelf&amp;quot; when someone needs it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5180</id>
		<title>Get Started With Lua Events Lesson 6: Splitting Code into Multiple Files</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=Get_Started_With_Lua_Events_Lesson_6:_Splitting_Code_into_Multiple_Files&amp;diff=5180"/>
		<updated>2019-07-26T14:28:18Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: /* The Threshold Table and First Look at Metatables */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Lua Resources]]&lt;br /&gt;
Back to [[Get Started With Lua Events by Prof. Garfield| Get Started With Lua Events]]&lt;br /&gt;
&lt;br /&gt;
This Lesson is under construction.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
In this lesson, we will take a look at how to split the code for a scenario&#039;s events into multiple files.  There are several reasons to consider doing this.&lt;br /&gt;
&lt;br /&gt;
The first reason is simply to organize your work.  If you have a series of complicated events, the events.lua file can become very large very quickly. Once your events.lua file has thousands of lines of code in it, it may not be very obvious where the best place is to put that next helper function, or where to implement the function that runs a complicated event.  Sometimes even finding the piece of code that has to be changed can be a bit of a hassle.  In Over the Reich, I sometimes search for the associated civ.scen line, and then search for the exact name of the function I need.  Occasionally, there may even be more searching to find what I actually have to change.  With multiple files, it becomes easier to find things.&lt;br /&gt;
&lt;br /&gt;
Another aspect of using multiple files is that you can make certain changes without worrying about breaking things elsewhere.  If myBigComplicatedFunction relies on aModestHelperFunction for a certain part of its functionality, and a change to myBigComplicatedFunction also requires a change to aModestHelperFunction, you have to make sure that nothing else in your code also uses aModestHelperFunction, or, if something else does depend on it, that aModestHelperFunction either still provides the original functionality, or that all other functions that use aModestHelperFunction are suitably modified.  If myBigComplicatedFunction is defined in its own lua module, then you don&#039;t have to worry about forgetting that aModestHelperFunction was used elsewhere, since it can&#039;t be accessed outside the module unless you specifically allow it to be.&lt;br /&gt;
&lt;br /&gt;
A second reason to split events code into multiple files is to facilitate collaboration.  If all of the events are in a single file, then only one person can make changes to the file at a time.  If one partner starts changing an event, but has to do something else before finishing, everyone waits on one person&#039;s delay.  However, if most aspects of the scenario are separated into individual files, everyone can work on his or her own piece of the puzzle without depriving others of the opportunity to work at that time.&lt;br /&gt;
&lt;br /&gt;
A third reason to split events into multiple modules is to facilitate reusing code.  If everything required to implement an event is in its own file (or files), it becomes much easier for other creators to use your functionality in their scenario.  Since everything they need is already in one place, they don&#039;t have to find every last helper function, or concern themselves with naming conflicts.&lt;br /&gt;
&lt;br /&gt;
===Two Simple Examples===&lt;br /&gt;
&lt;br /&gt;
Let us look at the top of the events.lua file.  You can get the version that I started lesson 6 with [[here]].&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-01-DefaultRequire.jpg]]&lt;br /&gt;
&lt;br /&gt;
We get code from other files by using the command &amp;lt;code&amp;gt;require&amp;lt;/code&amp;gt; along with a string specifying the file name (except for the .lua extension).  At the moment, we can only get code stored in the lua folder in the Test of Time directory.  This is inconvenient if we&#039;re trying to distribute a scenario, since installing a scenario would require moving certain files to the lua directory, and those file names might conflict.  Instead, we need to tell the Lua interpreter to search in the same folder that the events.lua folder is in.&lt;br /&gt;
&lt;br /&gt;
To do this, we need the following code:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local eventsPath = string.gsub(debug.getinfo(1).source, &amp;quot;@&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 local scenarioFolderPath = string.gsub(eventsPath, &amp;quot;events.lua&amp;quot;, &amp;quot;?.lua&amp;quot;)&lt;br /&gt;
 if string.find(package.path, scenarioFolderPath, 1, true) == nil then&lt;br /&gt;
    package.path = package.path .. &amp;quot;;&amp;quot; .. scenarioFolderPath&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can probably cut and paste this code before the require lines in your events.lua file and not worry about how it works.  However, I&#039;ll provide a brief explanation for reference.&lt;br /&gt;
&lt;br /&gt;
The first line stores the location of the of the current file as a string in eventsPath.&lt;br /&gt;
&lt;br /&gt;
The second line replaces events.lua in the eventsPath with ?.lua, which will tell the Lua interpreter to look for .lua files in the current directory (that is to say, the directory with the events.lua file).  &lt;br /&gt;
&lt;br /&gt;
The if statement adds scenarioFolderPath to the places for the Lua interpreter to search for code, if that directory is not already in the search path.  Since the search path is kept active by the Lua interpreter, it will not be necessary to repeat these lines of code in every file that performs a require action as long as you are running the file as part of events.  If you are writing some other kind of code, you will need to substitute &amp;quot;events.lua&amp;quot; with the name of the file with the code you are running.  Note that for some reason, events.lua is always provided in lower case.  However, for use in other situations, debug.getinfo(1).source uses the correct case for event files. I have only briefly tested this, so you may have to do some testing yourself if this situation comes up (or ask for help in the forums).&lt;br /&gt;
&lt;br /&gt;
Now that we&#039;ve told Lua where to look for our extra code, we can begin moving code to other files.  Think of require as telling Lua to run the entire contents of another file as a function.  We can then assign a value to whatever that file returns, which will usually be a table.  A couple of examples will clarify.&lt;br /&gt;
&lt;br /&gt;
For our first example, we will move our scenario&#039;s parameters to a separate file, and access it via require.  This may not seem worthwhile in this example, but tables like this can get large in a hurry.  At the time of writing, Over the Reich has over 100 lines of parameters (&amp;quot;specialNumbers&amp;quot;), and parameters are something that a designer might like to play with while collaborators make other implementations.  Also, parameters will have to be referenced by other parts of the code, and a file that is required by events.lua cannot, in turn, require events.lua in order to get information.  That means that we&#039;ll have to keep our parameters in a separate file anyway.&lt;br /&gt;
&lt;br /&gt;
Cut the parameters table definition and paste it into a new file, classicRomeParameters.lua.  For the last line, write&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return parameters&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, Near the top of events.lua, where the existing require lines are, add the eventsPath code from above and also the line&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local parameters = require(&amp;quot;classicRomeParameters&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
[[File:GetStartedWithLuaLesson6-02-RequireParameters.jpg]]&lt;br /&gt;
&lt;br /&gt;
Open the classicRome scenario and test out a couple of events to make sure everything is the same.&lt;br /&gt;
&lt;br /&gt;
We might find it convenient to put a few tables into the same file.  For this, we will simply return a table containing these tables, and give each table a name in the events.lua file.&lt;br /&gt;
&lt;br /&gt;
Create a file classicRomeAliases.lua and move all the &amp;quot;aliases&amp;quot; tables to that file.  Also move the getCityAt function.&lt;br /&gt;
&lt;br /&gt;
At the bottom of the file, put the following lines:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 unitAliases=unitAliases,&lt;br /&gt;
 tribeAliases=tribeAliases,&lt;br /&gt;
 tileAliases=tileAliases,&lt;br /&gt;
 cityAliases=cityAliases,&lt;br /&gt;
 textAliases=textAliases,&lt;br /&gt;
 terrainAliases=terrainAliases,&lt;br /&gt;
 improvementAliases=improvementAliases,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following lines to events.lua (in the require section)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local aliases = require(&amp;quot;classicRomeAliases&amp;quot;)&lt;br /&gt;
 local unitAliases,tribeAliases,tileAliases,cityAliases,textAliases,&lt;br /&gt;
 		terrainAliases,improvementAliases=aliases.unitAliases,aliases.tribeAliases,&lt;br /&gt;
 		aliases.tileAliases,aliases.cityAliases, aliases.textAliases,aliases.terrainAliases,&lt;br /&gt;
 		aliases.improvementAliases&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, our classicRomeAliases module is returning a table with our &amp;quot;alias&amp;quot; tables.  We then assign the entries in this returned table to local variables with the desired names.  Here, I use multiple variable assignment, which I don&#039;t believe I&#039;ve used before (even though Lua allows it), but these could just as simply have been assigned line by line.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-03-RequireAliases.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now, let us move the legion plundering code into its own file, which we&#039;ll call plunder.lua.  First, copy over the legionPlunder function, and paste it near the bottom of the new file.&lt;br /&gt;
&lt;br /&gt;
Now, let us go through the code of this function, and figure out what else we need in our plunder.lua module.&lt;br /&gt;
&lt;br /&gt;
The very first part of the function is a check against unitAliases.legion.  This means we need the unitAliases table, and so we copy the aliases require code to the top of plunder.lua.  We don&#039;t need the path information, since that will be added in events.lua.&lt;br /&gt;
&lt;br /&gt;
A few more lines down, we find that the function cityRadius is also used in legionPlunder.  Therefore, we move that over as well.  We also need the plunderValue function, so copy that over as well.&lt;br /&gt;
&lt;br /&gt;
Next, we check if cityRadius relies on anything, but it doesn&#039;t.&lt;br /&gt;
&lt;br /&gt;
Proceeding to plunderValue, we find that it relies on the parameters table, so require that as well.  The function plunderValue does not appear to depend on anything else, so we&#039;re done moving functionality.  If we missed something, the Lua interpreter will complain at some point anyway.&lt;br /&gt;
&lt;br /&gt;
Next, we require the plunder module in events.lua, with the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local plunder = require(&amp;quot;plunder&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, for each of the functions in plunder.lua, we check if it is used somewhere in events.lua.  We can do this by searching.  plunderValue isn&#039;t used anywhere, so we&#039;re done with that.  City radius is used.  At the bottom of plunder.lua, we begin our return table, and have&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 return {&lt;br /&gt;
 cityRadius=cityRadius,&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, in events.lua, we replace the ocurance of cityRadius with plunder.cityRadius.  Alternatively, we could have put &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local cityRadius=plunder.cityRadius&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
after the line requiring plunder.&lt;br /&gt;
&lt;br /&gt;
Similarly, for legionPlunder, we add &amp;lt;code&amp;gt;legionPlunder=legionPlunder&amp;lt;/code&amp;gt; to the table that plunder.lua returns, and pre-append plunder. to legionPlunder in the one location where it occurs.&lt;br /&gt;
&lt;br /&gt;
Now, we test the legion plunder function and the press 4 generate archers function to make sure everything works.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-04-RequirePlunder.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Working With a Library===&lt;br /&gt;
&lt;br /&gt;
In programming terms, a &amp;quot;library&amp;quot; is a collection of code that can provide some specified functionality to a programmer without that programmer having to modify the code in the library.  Thus far, you have been using the &amp;quot;civ&amp;quot; library to interact with the game, and there has been no need modify it in order to use it in our own events.  (Unfortunately, in the case of the civ library, we don&#039;t actually know how to modify it.)  This is in contrast to much of the code we have written thus far.  For example, the code we wrote last lesson to make Selucid elephants attack Egypt is highly specific.  You couldn&#039;t just cut and paste that code, change the argument of a single function, and get your own goto event.  It is still a good example for how to write a goto event, but a user would still have to actually write the event.&lt;br /&gt;
&lt;br /&gt;
If you plan to write some functionality for your scenario that others might find useful, it is worth spending a little extra effort to see if you can write that functionality in a form that will allow others to use it with minimal effort.  If you can, then a little extra work on your part might save someone else the trouble of re-inventing the wheel, and allow them to complete their project sooner, or to work on some new feature for you to enjoy.  Unfortunately, the Lua scenarios that have been completed at the time of writing haven&#039;t been that good at creating re-usable code, at least in part since we were all getting used to Lua.  This will hopefully be improved in the future.&lt;br /&gt;
&lt;br /&gt;
For now, we&#039;re going to look at a library which is called the General Library (unless someone comes up with a better name) and which can be found [https://forums.civfanatics.com/threads/totpp-the-general-library.647583/ here].  The purpose of this module is to provide relatively simple functionality that probably shouldn&#039;t be implemented every time it is needed.  This is useful for our purposes, since we can look at relatively self contained and simple functions for our first examples.  We&#039;ll create a library for generating munitions later.&lt;br /&gt;
&lt;br /&gt;
This library would be used by invoking the line &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local gen = require(&amp;quot;generalLibrary&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to make these functions available to the console for testing purposes, you would simply omit the local, thereby making gen a global variable.&lt;br /&gt;
&lt;br /&gt;
Let us now take a look at a function provided by the General Library &amp;lt;code&amp;gt; gen.hasIrrigation(tile)--&amp;gt;boolean&amp;lt;/code&amp;gt;.  The very first line references the helper function &amp;lt;code&amp;gt; toTile(tile or table)--&amp;gt;tile&amp;lt;/code&amp;gt;, so let us include that code, and look at it first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 -- toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- gen.toTile(tile or table)--&amp;gt;tile&lt;br /&gt;
 -- If given a tile object, returns the tile&lt;br /&gt;
 -- If given coordinates for a tile, returns the tile&lt;br /&gt;
 -- Causes error otherwise&lt;br /&gt;
 -- Helper Function (provided to this library as toTile and gen.toTile)&lt;br /&gt;
 local function toTile(input)&lt;br /&gt;
     if civ.isTile(input) then&lt;br /&gt;
         return input&lt;br /&gt;
     elseif type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         local xVal = input[1] or input[&amp;quot;x&amp;quot;]&lt;br /&gt;
         local yVal = input[2] or input[&amp;quot;y&amp;quot;]&lt;br /&gt;
         local zVal = input[3] or input[&amp;quot;z&amp;quot;] or 0&lt;br /&gt;
         if type(xVal)==&amp;quot;number&amp;quot; and type(yVal)==&amp;quot;number&amp;quot; and type(zVal)==&amp;quot;number&amp;quot; then&lt;br /&gt;
             if civ.getTile(xVal,yVal,zVal) then&lt;br /&gt;
                 return civ.getTile(xVal,yVal,zVal)&lt;br /&gt;
             else&lt;br /&gt;
                 error(&amp;quot;Table with values {&amp;quot;..tostring(xVal)..&amp;quot;,&amp;quot;..tostring(yVal)..&lt;br /&gt;
                         &amp;quot;,&amp;quot;..tostring(zVal)..&amp;quot;} does not correspond to a valid tile.&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
         else&lt;br /&gt;
             error(&amp;quot;Table did not correspond to tile coordinates&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         error(&amp;quot;Did not receive a tile object or table of coordinates.&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
 gen.toTile = toTile&lt;br /&gt;
 &lt;br /&gt;
 -- gen.hasIrrigation(tile)--&amp;gt;boolean&lt;br /&gt;
 -- returns true if tile has irrigation but no farm&lt;br /&gt;
 -- returns false otherwise&lt;br /&gt;
 function gen.hasIrrigation(tile)&lt;br /&gt;
     tile = toTile(tile)&lt;br /&gt;
     local improvements = tile.improvements&lt;br /&gt;
     -- irrigation, but no mining, so not farmland&lt;br /&gt;
     if improvements &amp;amp; 0x04 == 0x04 and improvements &amp;amp; 0x08 == 0 then&lt;br /&gt;
         return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-05-HasIrrigation.jpg]]&lt;br /&gt;
&lt;br /&gt;
Let us begin by looking at the function &amp;lt;code&amp;gt;toTile&amp;lt;/code&amp;gt;.  The purpose of this function is to allow other functions to accept tile coordinates in a table instead of an actual tile object.  The function tries to be reasonably permissive in the coordinates it will accept, allowing both integer indices and lowercase string indices, and by assuming that a missing z value corresponds to map 0.  The function also tries to give reasonably helpful errors.&lt;br /&gt;
&lt;br /&gt;
This brings up something that should be considered when making reusable code: what to do if you don&#039;t get values you were expecting.  One option is to throw an error and bring up the Lua console.  This is good for scenario creators, so they know something is wrong, but not so great for end users because the error stops the rest of the event from happening, should the mistake slip through playtesting.&lt;br /&gt;
&lt;br /&gt;
The other option is for the code to fail silently, and try to do what it can.  This is the way the old Test of Time macro system often fails.  If Civ II doesn&#039;t &amp;quot;understand&amp;quot; the event, it just doesn&#039;t happen, and doesn&#039;t bother the player with the error.  This means that the scenario will still mostly work, but it is harder to catch issues during playtesting.  Sometimes, this means doing something &amp;quot;sensible&amp;quot; if the input isn&#039;t of the expected type, and might make the code easier to write, since you don&#039;t have to handle inputs differently.&lt;br /&gt;
&lt;br /&gt;
A third option is to write your code such that both things can be done.  At the top of your code, you put in a variable named &amp;quot;debugMode&amp;quot; or something, and make all the functions throw errors when true, and fail silently when false.  Then you playtest with debugMode set to true, and release with debug mode set to false.  However, this means extra work in writing your code and you also have to test everything with debug mode off.&lt;br /&gt;
&lt;br /&gt;
For toTile, I went with the fail with error option, since that will allow every function that uses toTile to assume it is receiving proper data.  It also seems unlikely that people will be regularly trying to check tiles that don&#039;t exist or have tables with tiles and units and improvement objects all in one.  And if they do, &amp;quot;guarding&amp;quot; is fairly straightforward anyway (as we&#039;ve done in previous lessons).&lt;br /&gt;
&lt;br /&gt;
Although toTile is mainly meant to be a helper function for the General Library, it is also put into the gen table to be made available to end users, since it offers useful functionality.  Hence, &amp;lt;code&amp;gt; gen.toTile=toTile&amp;lt;/code&amp;gt;.  Note that we could have given toTile a different name in the gen table that this module will return, such as gen.tableToTile=toTile.  In fact, we could refer to the same function with multiple keys in the gen table, if we want to.&lt;br /&gt;
&lt;br /&gt;
Next, we will look at gen.hasIrrigation.&lt;br /&gt;
&lt;br /&gt;
The first thing to notice is that local is not being used to define this function.  That is because we&#039;re putting the function for gen.hasIrrigation directly into the gen table that this module will return.  We could define hasIrrigation as a local variable and then copy it into the gen table.  However, there is a decent chance that the General Library will have more than 200 functions by the time everything is complete, since it is meant to provide a lot of building block functionality and keep it in one place, and we will run into trouble if we assign 200 local variables in a single function (which a required lua file acts as).&lt;br /&gt;
&lt;br /&gt;
Perhaps the most striking thing is that we begin by changing the value of tile, the argument of the function.  It looks like we&#039;re making a global variable named tile, but we&#039;re not.  When you specify the names of the arguments for a function (in this case tile), you create local variables for that function, which can be given new values just as if you had explicitly used the local keyword.&lt;br /&gt;
&lt;br /&gt;
Beyond that, we extract the integer representing the tile improvements into a local variable (which upon later reflection isn&#039;t really necessary), and check that the irrigation bit is set to 1 and the mining bit is set to 0.  Refer to lesson 5 for why this works.  In fact, we could have simply returned the value of the if statement, rather than specifying return true and return false, although it is very slightly clearer what is going on in the expanded version of the code.&lt;br /&gt;
&lt;br /&gt;
Now, let us write a function to place irrigation on a square.  It seems pretty clear that we should do nothing if the tile has a city, but we also have to decide what to do if there is mining or farmland on the tile, since those interfere with placing irrigation.  We&#039;ll just remove them, on the basis that if we&#039;re trying to &amp;quot;place irrigation,&amp;quot; then we want irrigation to be there when we are finished.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 function gen.placeIrrigation(tile)&lt;br /&gt;
    tile = toTile(tile)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These lines open the function and convert a table of coordinates to a tile if necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 if tile.city then&lt;br /&gt;
    return&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the tile has a city, return so nothing else is done in the function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
     -- Set irrigation bit to 1&lt;br /&gt;
     tile.improvements = tile.improvements | 0x04&lt;br /&gt;
     -- Set mining bit to 0&lt;br /&gt;
     tile.improvements = tile.improvements &amp;amp; ~0x08&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the irrigation bit to 1 and the mining bit to 0.&lt;br /&gt;
&lt;br /&gt;
The functions in this library don&#039;t have to be complex, and in fact, most probably shouldn&#039;t be.  They just have to make life easier for the end user.  If you reach this lesson before the General Library is considered &amp;quot;complete,&amp;quot; your assignment now is to submit some work for it.  If you don&#039;t feel comfortable doing bitwise operations, you can test the work of others or submit functions that simplify other tasks.  However, there are also some helper functions in the library to facilitate changing bits, so you might also consider working on the unit type flags functions.  Remember, if you want to make functions available to the console for testing purposes, they must be global variables.&lt;br /&gt;
&lt;br /&gt;
=== The Threshold Table and First Look at Metatables===&lt;br /&gt;
&lt;br /&gt;
Consider a scenario design situation that occurred in Over the Reich: a bomber is generating some bombs via a key press, and the number of bombs it should generate is dependant on its current remaining hitpoints.  The more hitpoints the bomber has, the more bombs it should generate.  What we want is to specify that if a bomber has between x and y hitpoints, it should produce 2 bombs.  That is, for a given type of bomber, we want to have, for example,&lt;br /&gt;
&lt;br /&gt;
hp &amp;gt;= 16 --&amp;gt; 4 bombs&lt;br /&gt;
16 &amp;gt; hp &amp;gt;= 12 --&amp;gt; 3 bombs&lt;br /&gt;
12 &amp;gt; hp &amp;gt;= 9 --&amp;gt; 2 bombs&lt;br /&gt;
9 &amp;gt; hp &amp;gt;= 4 --&amp;gt; 1 bomb&lt;br /&gt;
4 &amp;gt; hp &amp;gt;= 0 --&amp;gt; 0 bombs&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Lua tables do not naturally encode this kind of association by default.  However, Lua does have a feature called metatables, which allows us to change the behaviour of tables.  (This will be a much better way to make the specification than I ended up writing in Over the Reich.)&lt;br /&gt;
&lt;br /&gt;
A metatable is a table that we can &amp;quot;attach&amp;quot; to another table, and then the metatable changes the behaviour of that table.  We&#039;ll only look at metatables briefly here, but more information can be found [https://www.tutorialspoint.com/lua/lua_metatables.htm here].&lt;br /&gt;
&lt;br /&gt;
What we want is a data structure that can accept numerical &amp;quot;key values&amp;quot; that are between the key values explicitly specified, and return the appropriate value for those keys.  We will call this data structure a threshold table, since we are specifying threshold values as keys.  We can do this by assigning the following metatable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local mt = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we run &amp;lt;code&amp;gt; setmetatable(myTable,mt)&amp;lt;/code&amp;gt;, then whenever we ask for an index from myTable and that index doesn&#039;t currently exist in myTable, the function assigned to __index will run.  Now let us examine the function.&lt;br /&gt;
&lt;br /&gt;
If the type of the key is not a number, then we return whatever the table value is for that key.  We use the function rawget, because the standard &amp;lt;code&amp;gt;thresholdTable[key]&amp;lt;/code&amp;gt; will invoke this function again if the key doesn&#039;t exist, and so never return an answer (when we want it to return nil).&lt;br /&gt;
&lt;br /&gt;
If the key type is a number, then we look for the largest numerical index that is also less than or equal to the key value.  We return a default value of false if the key submitted is smaller than all numerical values.  False is chosen over nil, so that a maximum value can be set by setting the value of a numerical index to false.  Using the key [-math.huge] allows a return value to be set for all numbers (since all numbers are greater than -math.huge).&lt;br /&gt;
&lt;br /&gt;
Since we don&#039;t want scenario creators to have to re-create threshold tables every time they need them, we&#039;ll add this functionality to the General Library&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local thresholdTableMetatable = { __index = function(thresholdTable,key)&lt;br /&gt;
                 if type(key) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
                     return rawget(thresholdTable,key)&lt;br /&gt;
                 else&lt;br /&gt;
                     local bestIndexSoFar = -math.huge&lt;br /&gt;
                     local bestValueSoFar = false&lt;br /&gt;
                     for index,value in pairs(thresholdTable) do&lt;br /&gt;
                         if type(index) == &amp;quot;number&amp;quot; and key &amp;gt;= index and index &amp;gt;= bestIndexSoFar then&lt;br /&gt;
                             bestIndexSoFar = index&lt;br /&gt;
                             bestValueSoFar = value&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return bestValueSoFar&lt;br /&gt;
                 end&lt;br /&gt;
             end,}&lt;br /&gt;
 -- gen.makeThresholdTable(table or nil)--&amp;gt;thresholdTable&lt;br /&gt;
 function gen.makeThresholdTable(inputTable)&lt;br /&gt;
     inputTable = inputTable or {}&lt;br /&gt;
     return setmetatable(inputTable,thresholdTableMetatable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-06-ThresholdTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
===A Munition Generation Module===&lt;br /&gt;
&lt;br /&gt;
Now, let us write some re-usable code for a human player to generate units by pressing a key while an appropriate unit is active.  This sort of code could be used for ranged attacks (generating a &amp;quot;munition&amp;quot;) and also for recruiting mercenaries by paying gold.&lt;br /&gt;
&lt;br /&gt;
The first thing we will want to do is to decide how our code will be used by the end user.  This will, perhaps, change by the time we finish writing the code, but it will at least give us a starting point.&lt;br /&gt;
&lt;br /&gt;
spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&lt;br /&gt;
&lt;br /&gt;
Our goal is that when a player attempts to generate a unit using another unit, they will provide the unit spawning the new unit, and a table of information specifying if a unit (or units) can be spawned and anything else that must happen while spawning (like paying money, expending movement points, etc.).&lt;br /&gt;
&lt;br /&gt;
We have an option here.  We could have the scenario creator provide the specification table as a required file for our module, or the creator can provide it at the time spawnUnit is called.  I choose the latter for a couple of reasons.  The first is that it allows the player to have more than one specification table, either because more than one key can spawn a unit, or because the specification can change over time.  The other is reason is so that the creator can make the table in the events.lua file if desired (since our module can&#039;t require information from events.lua).&lt;br /&gt;
&lt;br /&gt;
Having decided that our generateUnit events are going to be specified by a table, we have to decide what the contents of that table should be.  It seems pretty reasonable to index the specificationTable with the index of the unit type of each unit that can generate using the information in the table.  If a unit type id number is missing, that unit doesn&#039;t generate a munition (or recruit a unit).&lt;br /&gt;
&lt;br /&gt;
The value for each unit type id in the specification table will be a table that specifies how and if that unit generates other units.&lt;br /&gt;
&lt;br /&gt;
--specificationTable[unitType.id]={&lt;br /&gt;
--&lt;br /&gt;
-- goldCost = integer or nil&lt;br /&gt;
--      amount of gold it costs to generate a unit&lt;br /&gt;
--      absent means 0&lt;br /&gt;
-- minTreasury = integer or nil&lt;br /&gt;
--      minimum amount of gold in treasury to generate a unit&lt;br /&gt;
--      absent means refer to gold cost&lt;br /&gt;
--      (tribe will generate and be set to 0 if treasury is less than goldCost)&lt;br /&gt;
-- treasuryFailMessage = string or nil&lt;br /&gt;
--      A message to be displayed if the unit fails to spawn a unit due to an &lt;br /&gt;
--      insufficient treasury&lt;br /&gt;
--      nil means no message&lt;br /&gt;
&lt;br /&gt;
-- There are three ways to specify move costs, in full movement points,&lt;br /&gt;
-- in &amp;quot;atomic&amp;quot; movement points, and as a fraction of total movement points for the&lt;br /&gt;
-- unit type.  Use only one kind per unit type&lt;br /&gt;
&lt;br /&gt;
-- moveCost = integer or nil&lt;br /&gt;
--      movement points to be expended generating the unit&lt;br /&gt;
--      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
--      absent means 0&lt;br /&gt;
-- minMove = integer or nil&lt;br /&gt;
--      minimum remaining movement points to be allowed to generate a unit&lt;br /&gt;
--      &amp;quot;full&amp;quot; movement points&lt;br /&gt;
--      absent means any movement points for land/sea, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
-- postGenMinMove = integer or nil&lt;br /&gt;
--      a unit will be left with at least this many movement points after&lt;br /&gt;
--      the generation function&lt;br /&gt;
--      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
-- moveCostAtomic = integer or nil&lt;br /&gt;
--      movement points to be expended generating the unit&lt;br /&gt;
--      refers to the unit.moveSpent movement points&lt;br /&gt;
--      absent means 0&lt;br /&gt;
-- minMoveAtomic = integer or nil&lt;br /&gt;
--      minumum remaining movement points to be allowed to generate a unit&lt;br /&gt;
--      referes to the unit.moveSpent movement points&lt;br /&gt;
--      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
-- postGenMinMoveAtomic = integer or nil&lt;br /&gt;
--      a unit will be left with at least this many movement points after&lt;br /&gt;
--      the generation function&lt;br /&gt;
--      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
-- moveCostFraction = number in [0,1] or nil&lt;br /&gt;
--      fraction of unit&#039;s total movement points expended generating the unit&lt;br /&gt;
--      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
--      absent means 0&lt;br /&gt;
-- minMoveFraction = number in [0,1] or nil&lt;br /&gt;
--      fraction of unit&#039;s total movement points that must remain to be allowed&lt;br /&gt;
--      to generate a unit&lt;br /&gt;
--      absent means any movement points for land, 2 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
--      round up to nearest &amp;quot;atomic&amp;quot; movement point&lt;br /&gt;
-- postGenMinMoveFraction = number in [0,1] or nil&lt;br /&gt;
--      a unit will be left with at least this many movement points after&lt;br /&gt;
--      the generation function, round up to nearest &amp;quot;atomic&amp;quot; move point&lt;br /&gt;
--      absent means 0 for land/sea, 1 &amp;quot;atomic&amp;quot; for air units&lt;br /&gt;
-- roundFractionFull = bool or nil&lt;br /&gt;
--      fractional movement cost and minimum are rounded up to full movement point&lt;br /&gt;
--      instead of atomic movement point&lt;br /&gt;
--      nil/false means don&#039;t&lt;br /&gt;
-- roundFractionFullDown = bool or nil&lt;br /&gt;
--      fractional cost and minimum are rounded down to full move point&lt;br /&gt;
--      nil/false means don&#039;t&lt;br /&gt;
-- minMoveFailMessage = string or nil&lt;br /&gt;
--      a message to be displayed if a unit is not generated due to insufficient&lt;br /&gt;
--      movement points.&lt;br /&gt;
--      nil means no message&lt;br /&gt;
&lt;br /&gt;
-- allowedTerrainTypes = table of integers or nil&lt;br /&gt;
--      a unit may only be generated if the tile it is standing on&lt;br /&gt;
--      corresponds to one of numbers in the table&lt;br /&gt;
--      nil means the unit can be generated on any terrain type&lt;br /&gt;
-- terrainTypeFailMessage = string or nil&lt;br /&gt;
--      message to be displayed if a unit is not generated due to standing&lt;br /&gt;
--      on the incorrect terrain&lt;br /&gt;
&lt;br /&gt;
-- requiredTech = tech object or nil&lt;br /&gt;
--      the generating civ must have this technology in order to generate&lt;br /&gt;
--      the unit&lt;br /&gt;
--      nil means no requirement&lt;br /&gt;
-- techFailMessage = string or nil&lt;br /&gt;
--      message to be displayed if a unit is not generated due to not having&lt;br /&gt;
--      the correct technology&lt;br /&gt;
&lt;br /&gt;
-- payload = boolean or string&lt;br /&gt;
--      if true, unit must have a home city in order to generate munitions&lt;br /&gt;
--      and generating munitions sets the home city to NONE&lt;br /&gt;
-- payloadFailMessage = string or nil&lt;br /&gt;
--      message to be displayed if a unit is not generated due to the &lt;br /&gt;
--      payload restriction&lt;br /&gt;
-- payloadRestrictionCheck = nil or function(unit)--&amp;gt;boolean&lt;br /&gt;
--      If function returns false, the home city is not valid for giving the&lt;br /&gt;
--      unit a payload.  This will be checked when the unit is activated, when&lt;br /&gt;
--      the unit is given a new home city with the &#039;h&#039; key and when the unit&lt;br /&gt;
--      tries to generate a munition&lt;br /&gt;
--      nil means no restriction&lt;br /&gt;
-- payloadRestrictionMessage = nil or string&lt;br /&gt;
--      message to show if a unit fails the payloadRestrictionCheck&lt;br /&gt;
&lt;br /&gt;
-- canGenerateFunction = nil or function(unit)--&amp;gt;boolean &lt;br /&gt;
--      This function applied to the generating unit must return true in order&lt;br /&gt;
--      for a unit to be spawned.  All other conditions still apply.&lt;br /&gt;
--      any failure message should be part of canGenerateFunction&lt;br /&gt;
--      absent means no extra conditions&lt;br /&gt;
&lt;br /&gt;
-- generateUnitFunction = nil or function(unit)--&amp;gt;table of unit&lt;br /&gt;
--      This function creates the unit or units to be generated&lt;br /&gt;
--      and returns a table containing those units&lt;br /&gt;
--      Ignore any specifications prefixed with * if this is used&lt;br /&gt;
--      nil means use other specifications&lt;br /&gt;
&lt;br /&gt;
--*generatedUnitType = unitType&lt;br /&gt;
--      The type of unit to be generated&lt;br /&gt;
--      can&#039;t be nil unless generateUnitFunction is used instead&lt;br /&gt;
&lt;br /&gt;
--*giveVeteran = bool or nil&lt;br /&gt;
--      generated unit(s) given veteran status if true&lt;br /&gt;
--      nil or false means don&#039;t give vet status&lt;br /&gt;
--      if true, overrides copyVeteranStatus&lt;br /&gt;
&lt;br /&gt;
--*copyVeteranStatus = bool or nil&lt;br /&gt;
--      generated unit(s) copy veteran status of generating unit if true&lt;br /&gt;
--      nil or false means don&#039;t give vet status&lt;br /&gt;
&lt;br /&gt;
--*setHomeCityFunction = nil or function(generatingUnit)--&amp;gt;cityObject&lt;br /&gt;
--      determines what home city the spawned unit should have&lt;br /&gt;
--      nil means a home city of NONE&lt;br /&gt;
&lt;br /&gt;
--*numberToGenerate = nil or number or thresholdTable or function(generatingUnit)--&amp;gt;number&lt;br /&gt;
--      if nil, generate 1 unit in all circumstances&lt;br /&gt;
--      if integer, generate that many units (generate 0 if number less than 0)&lt;br /&gt;
--      if number not integer, generate floor(number), and 1 more with&lt;br /&gt;
--      probability number-floor(number)&lt;br /&gt;
--      if thresholdTable, use remaining hp as the key, to get the number to create&lt;br /&gt;
--      if function, get the number as the returned value of the function &lt;br /&gt;
&lt;br /&gt;
-- activate = bool or nil&lt;br /&gt;
--      Activates one of the generated units if true.  If generateUnitFunction was used,&lt;br /&gt;
--      the unit at index 1 is activated, if index 1 has a value.  (if not, any unit in&lt;br /&gt;
--      the list might be chosen)&lt;br /&gt;
&lt;br /&gt;
The very last entry brings forward a change that must be made to our unit generation specification.  Lua&#039;s activate unit command doesn&#039;t run the unit activation trigger, even though the active unit is changed.  Therefore, we must do that manually.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit, specificationTable)--&amp;gt; table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
becomes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;spawnUnit(generatingUnit,specificationTable,unitActivationCode)--&amp;gt;table of unitCreated&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Perhaps we will change it again later.&lt;br /&gt;
&lt;br /&gt;
I&#039;ve decided to try a different instructional technique for this section.  Instead of writing the code and then going through it section by section, I&#039;ve recorded a video of my coding and testing this module, and I attempt to explain some of the stuff that I do along the way.&lt;br /&gt;
&lt;br /&gt;
I&#039;m not sure of the value of the video.  If you find that there is little useful content relative to the time it takes to watch, then feel free to skip it and continue the lesson.  I don&#039;t teach anything &amp;quot;new&amp;quot; in it, so you won&#039;t miss anything crucial.  However, it should be pretty close to how programming Lua can actually happen in the &amp;quot;real world.&amp;quot;  While I did give some thought to how to write the module before I started, I do attempt to solve problems in real time, and make mistakes that are not discovered for a while (including one where I try to explain how I solve a problem and then not actually do a crucial part).&lt;br /&gt;
&lt;br /&gt;
You can find the code [[here]].  Even if you decide not to watch the video, download the code and try testing some of the features based on the specification above.&lt;br /&gt;
&lt;br /&gt;
The link to the video is&lt;br /&gt;
&lt;br /&gt;
https://youtu.be/XxPyNknGlAo&lt;br /&gt;
&lt;br /&gt;
===A Unit Attack Bonus for Complementary Units in Square===&lt;br /&gt;
&lt;br /&gt;
Something we might like to do is to give units an attack bonus if they attack from a square with some special unit, for example a &amp;quot;leader&amp;quot; unit.  The [[Napoléon I]] scenario, for example, gives an attack bonus to units if a commander unit, such as Napoleon, is in the square when the unit is activated (the unit can subsequently move and still retain the bonus as long as no other unit is selected).  We will now make a module providing the same functionality.&lt;br /&gt;
&lt;br /&gt;
We first have to have a basic idea of how this functionality should work.  When a unit is activated, the onActivateUnit event checks if the newly activated unit should get an attack bonus, based on the other units in the square.  If the unit deserves an attack bonus, the corresponding unitType.attack entry is changed, and all the attack value of all other units is reset to the default value.  If the activated unit also does not deserve an attack bonus, that value is also set to the default value.&lt;br /&gt;
&lt;br /&gt;
This now leads us to some more possibilities.  Should multiple bonus units lead to multiple bonuses or only apply the best one?  For example, suppose a legion gets a bonus if an archer is also in the same square.  Should two archers provide twice the bonus?  Perhaps two archers should provide a larger bonus than one, but not twice as much.  Perhaps a legion should also get a bonus if there is a catapult in the square, but that bonus should apply even if the maximum archer bonus is already achieved.  It seems like perhaps there should be a &amp;quot;ranged unit&amp;quot; bonus, an &amp;quot;artillery unit&amp;quot; bonus and maybe a &amp;quot;cavalry&amp;quot; bonus which should all impact the legion&#039;s attack value.  It&#039;s looking like we might end up demanding that a scenario creator make a big complicated table in order to use this functionality, even if they only have simple needs.&lt;br /&gt;
&lt;br /&gt;
What we can do to alleviate this is to write a &amp;quot;simple&amp;quot; version of the event that is easy to use (and program), and also write a more complicated version that gives the expanded capability.&lt;br /&gt;
&lt;br /&gt;
Specification Table for simpleAttackBonus&lt;br /&gt;
&lt;br /&gt;
--simpleAttackBonusTable[activeUnit.type.id] ={[bonusUnitType.id]=bonusNumber}&lt;br /&gt;
--simpleAttackBonusTable.type = string&lt;br /&gt;
--if simpleAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
-- add the bonusNumber to the base attack&lt;br /&gt;
--if simpleAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
-- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
-- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
--if simpleAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
-- add the fraction of the attack value to the attack,&lt;br /&gt;
-- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
-- if simpleAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
-- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
-- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
-- if simpleAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
-- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
-- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
--simpleAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
-- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
-- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
-- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
-- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
-- if fraction part is less than 0.5, and rounded up otherwise&lt;br /&gt;
&lt;br /&gt;
The relevant first draft of the code is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local function simpleAttackBonus(activeUnit,simpleAttackBonusTable,defaultAttackTable)&lt;br /&gt;
     -- reset all unit attack values&lt;br /&gt;
     for unitTypeID,attackValue in pairs(defaultAttackTable) do&lt;br /&gt;
         civ.getUnitType(unitTypeID).attack = attackValue&lt;br /&gt;
     end&lt;br /&gt;
     local unitBonusTable = simpleAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
     if not unitBonusTable then&lt;br /&gt;
         -- unitBonusTable is nil (or false), so the active unit can&#039;t&lt;br /&gt;
         -- get a bonus&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
     -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
     local bestBonusSoFar = 0&lt;br /&gt;
     for unit in activeUnit.location.units do&lt;br /&gt;
         if unitBonusTable[unit.type.id] and unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
             bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     if bestBonusSoFar == 0 then&lt;br /&gt;
         -- If no bonus unit is found, this will be true, so do nothing else&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     -- set the new attack and return&lt;br /&gt;
     if string.lower(simpleAttackBonusTable.type) == &amp;quot;addBonus&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = activeUnit.type.attack+bestBonusSoFar&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
     local attackMultiplier = 1&lt;br /&gt;
     if type(simpleAttackBonusTable.type) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = (100+bestBonusSoFar)/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
         attackMultiplier = 1+bestBonusSoFar&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar/100&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.type) == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
         attackMultiplier = bestBonusSoFar&lt;br /&gt;
     else&lt;br /&gt;
         error([[simpleAttackBonus: simpleAttackBonusTable.type should be a string with&lt;br /&gt;
                 one of the following values: &amp;quot;addbonus&amp;quot;, &amp;quot;addpercent&amp;quot;, &amp;quot;addfraction&amp;quot;, &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
                 or &amp;quot;multiply&amp;quot;.  Actual value is ]]..tostring(simpleAttackBonusTable.type))&lt;br /&gt;
     end&lt;br /&gt;
     -- apply the bonus and round as appropriate&lt;br /&gt;
     if type(simpleAttackBonusTable.round) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;up&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.ceil(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     elseif string.lower(simpleAttackBonusTable.round) == &amp;quot;down&amp;quot; then&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier)&lt;br /&gt;
         return&lt;br /&gt;
     else&lt;br /&gt;
         activeUnit.type.attack = math.floor(activeUnit.type.attack*attackMultiplier+0.5)&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now let us go over this section by section.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-07-AttackBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
The first thing we do is to reset all the attack values of all the unit types.  That way, if a bonus existed for the last unit activated, that bonus no longer applies.  If a unit type is not in the defaultAttackTable, then we don&#039;t have the information to reset the attack value anyway, so we can safely ignore it by using the pairs function to iterate over the table.&lt;br /&gt;
&lt;br /&gt;
Now, we must find out if the newly activated unit deserves a bonus.  For that, we get the table associated with the active unit&#039;s type.  If the value is nil instead of a table, then the unit&#039;s type is not in the simpleAttackBonusTable, so there is no bonus to apply and the function returns.&lt;br /&gt;
&lt;br /&gt;
If the unit is eligible for bonuses, we then check the units in the square to see if any bonuses actually apply.  We&#039;ve seen this kind of code before.  If the unit in the stack can provide a bonus, and that bonus is better than the best bonus already found, the unit now provides the best bonus.  All bonus types that we can have are better if they are larger, and we are not comparing between bonus types, so a simple numerical comparison will do.  All bonuses are larger than 0 in our formulation, so 0 is a good starting value in the search.&lt;br /&gt;
&lt;br /&gt;
If the best bonus so far is still 0, there is no bonus, so the function can return.&lt;br /&gt;
&lt;br /&gt;
At this point, it occurs to me that when searching for the best bonus, we should exclude the active unit from the search.  That way, you can have a &amp;quot;strength in numbers&amp;quot; bonus, for example.  The relevant change to the code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    for unit in activeUnit.location.units do&lt;br /&gt;
        if unit ~= activeUnit and unitBonusTable[unit.type.id] and &lt;br /&gt;
			unitBonusTable[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestBonusSoFar = unitBonusTable[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, consider&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-08-AttackBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we apply the bonus that we&#039;ve found.  We use string.lower on simpleAttackBonusTable.type so that we don&#039;t have to worry about capitalization.  That does, however, require a correction to &amp;quot;addBonus&amp;quot;, since a lower case string will never be equal to that.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;addbonus&amp;quot; is the only type of bonus that is directly added to the existing attack value.  All other bonus types are a form of multiplication.  Since the addition is straightforward and doesn&#039;t require any rounding, the activeUnit&#039;s type attack value can be changed immediately, and the function execution ended with return.&lt;br /&gt;
&lt;br /&gt;
When there is only one bonus being applied, all other types of bonus are different ways of expressing how to multiply the existing attack value to get a new one, so we simply convert to the appropriate multiplier, and provide an error message if the type of bonus is not one of the valid possibilities.&lt;br /&gt;
&lt;br /&gt;
Finally, we round the attack value to an appropriate integer (since unit attack values must be integers), change the attack value of the active unit&#039;s type, and return to end the function execution.&lt;br /&gt;
&lt;br /&gt;
Now, we integrate into events.lua by using &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus = require(&amp;quot;attackBonus&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The relevant integration code for events.lua is&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local defaultAttackValueTable = {[unitAliases.legion.id]=4}&lt;br /&gt;
 local simpleAttackBonusTable ={}&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addbonus&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=3,[unitAliases.musketeer.id]=4}&lt;br /&gt;
 &lt;br /&gt;
 local function doOnActivation(unit,source)&lt;br /&gt;
     munitions.payloadRestrictionCheck(unit,munitionSpecificationTable)&lt;br /&gt;
 	attackBonus.simpleAttackBonus(unit,simpleAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can check that the bonus is being applied correctly by checking the Civlopedia entry for legion and looking at the attack value.  The following cases must be tested (remember that activating a unit from the city screen doesn&#039;t run the onActivation event, so activate from the map).&lt;br /&gt;
&lt;br /&gt;
Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
Legion activated with archer, but no musketeer (7 attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (8 attack)&lt;br /&gt;
Legion activated with archer and musketeer (8 attack)&lt;br /&gt;
Legion activated with 2 archer, no musketeer (7 attack)&lt;br /&gt;
Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
Activate some other unit (should have regular attack value).&lt;br /&gt;
I recommend making a stack for each of these cases and activating them one by one.&lt;br /&gt;
To facilitate the test, add the following line to doOnActivation&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 civ.ui.text(tostring(unit.type.attack))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You will want to comment out this line after testing.&lt;br /&gt;
&lt;br /&gt;
Next, change simpleAttackBonusTable to do &amp;quot;addpercent&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=30,[unitAliases.musketeer.id]=70}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With no rounding set, standard rounding is used&lt;br /&gt;
Legion activated with neither archer nor musketeer (4attack)&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
Legion activated with archer and musketeer (7 attack)&lt;br /&gt;
Legion activated with 2 archer, no musketeer (5 attack)&lt;br /&gt;
Legion with no bonus, activated right after legion with bonus (4 attack)&lt;br /&gt;
Activate some other unit (should have regular attack value).&lt;br /&gt;
&lt;br /&gt;
These numbers test both rounding up and rounding down.&lt;br /&gt;
&lt;br /&gt;
Now, use&lt;br /&gt;
simpleAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
Legion activated with archer, but no musketeer (6 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next,&lt;br /&gt;
simpleAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (6 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
simpleAttackBonusTable.round=&amp;quot;standard&amp;quot;&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Next, we test &amp;quot;addfraction&amp;quot;.  Since we&#039;ve tested all the rounding options, we don&#039;t have to do that again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=0.3,[unitAliases.musketeer.id]=0.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=130,[unitAliases.musketeer.id]=170}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable.type = &amp;quot;multiply&amp;quot;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion activated with archer, but no musketeer (5 (5.2) attack)&lt;br /&gt;
Legion activated with musketeer, but no archer (7 (6.8) attack)&lt;br /&gt;
&lt;br /&gt;
Before we finish, we should test a legion bonus for the legion.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 simpleAttackBonusTable[unitAliases.legion.id] = {[unitAliases.legion.id]=2,[unitAliases.archers.id]=1.3,[unitAliases.musketeer.id]=1.7}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Legion alone should have 4 attack.&lt;br /&gt;
A second legion on the square should provide 8 attack instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, let us try to formulate a more complicated bonus system.  One thing we mentioned is that we&#039;d like the ability to get bonuses from multiple units, and to be able to get bonuses from different &amp;quot;classes&amp;quot; of units (like &amp;quot;artillery,&amp;quot; &amp;quot;cavalry,&amp;quot; and &amp;quot;ranged attackers.&amp;quot;  Something else we might want to do is to allow different kinds of bonuses.  That is, maybe some units should provide a fixed +2 to any unit receiving the bonus, so that it is better at improving units with a low attack value, while other units should provide a percentage bonus (making them better at supporting units with an already high attack value).  It turns out that both of these ideas are not too difficult to implement individually, but that trying to implement them together makes it problematic to find the best bonus.&lt;br /&gt;
&lt;br /&gt;
Let us implement a bonus system with multiple categories but only one bonus type.  In our specification, we will first specify a data type called &amp;quot;bonusCategory.&amp;quot;  It is still just a table (though we could add a metatable if we wanted), but it will help us make our specification clearer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- A &amp;quot;bonusCategory&amp;quot; is a table&lt;br /&gt;
 -- bonusCategory = {[bonusUnitType.id]=bonusNumber, maxBonusUnits=integer or nil, nextBonusValue = fraction or nil}&lt;br /&gt;
 -- In a bonusCategory, the value for bonusUnitType.id tells what the base bonus for that unit type is,&lt;br /&gt;
 -- maxBonusUnits is the maximum number of units that can provide a bonus in this category,&lt;br /&gt;
 -- nextBonusValue tells how much to reduce the bonus for each subsequent unit,&lt;br /&gt;
 -- e.g. nextBonusValue = 0.7, and 5 units, which each have a bonusNumber=1&lt;br /&gt;
 -- The total bonus is 1(0.7)^0+.7+(.7)(.7)+(.7)^3+(.7)^4 = 1+.7+.49+.343+.2401=2.7731&lt;br /&gt;
 -- (which would be rounded as specified)&lt;br /&gt;
 -- nil means nextBonusValue=1&lt;br /&gt;
 --&lt;br /&gt;
 -- If a unit type is in two bonus categories for the same unit, there is no guarantee that the&lt;br /&gt;
 -- best bonus will be achieved&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, the bonus category is indexed by unitType id numbers for units that can give a bonus, and the corresponding bonus.  It also specifies the maximum number of units that can give a bonus, and a number that governs how to reduce a bonus for extra units.  That way, there can be diminishing returns for bonuses.&lt;br /&gt;
&lt;br /&gt;
Next, we look at the specification for the categoryAttackBonusTable&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 --categoryAttackBonusTable[activeUnit.type.id] =table of bonusCategory&lt;br /&gt;
 --categoryAttackBonusTable.type = string&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
 -- add the bonusNumber to the base attack&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addpercent&amp;quot;&lt;br /&gt;
 -- add bonusNumber percent to the unit&#039;s attack&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 50, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up all the percents, then compute the bonus&lt;br /&gt;
 -- i.e. 50% bonus and 50% bonus is 100% bonus, not 125%&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 50% bonus units become 50% + 25% &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 --if categoryAttackBonusTable.type == &amp;quot;addfraction&amp;quot;&lt;br /&gt;
 -- add the fraction of the attack value to the attack,&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 0.5, new attack 9&lt;br /&gt;
 -- for multiple unit bonuses, add up the fractions, then compute the bonus&lt;br /&gt;
 -- i.e. .5 bonus and .5 bonus is 1+.5+.5= 2x bonus, not 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 12&lt;br /&gt;
 -- nextBonusValue applied directly to bonusNumber, i.e. nextBonusValue=.5 and 2 .5 bonus units become .5+.25 &lt;br /&gt;
 -- so attack 6 --&amp;gt; 10.5&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by the bonusNumber precent&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 150, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 150% and 150% yields 225% of original value&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 100, i.e. nextBonusValue=.5 2 150% bonuses become 150% and 125%&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 -- if categoryAttackBonusTable.type == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
 -- multiply the unit&#039;s attack by bonusNumber&lt;br /&gt;
 -- i.e. attack 6, bonusNumber 1.5, new attack 9&lt;br /&gt;
 -- bonuses are multiplied together, i.e. 1.5 and 1.5 yields 2.25x&lt;br /&gt;
 -- attack 6 --&amp;gt; attack 13.5&lt;br /&gt;
 -- nextBonusValue applied to bonusNumber in excess of 1, i.e. nextBonusValue=.5 and two 1.5 bonuses become 1.5 and 1.25&lt;br /&gt;
 -- so attack 6 --&amp;gt; 11.25&lt;br /&gt;
 --categoryAttackBonusTable.round = &amp;quot;up&amp;quot; or &amp;quot;down&amp;quot; or &amp;quot;standard&amp;quot; or nil&lt;br /&gt;
 -- nil means &amp;quot;standard&amp;quot;&lt;br /&gt;
 -- &amp;quot;up&amp;quot; means a fractional attack value after a bonus is rounded up&lt;br /&gt;
 -- &amp;quot;down&amp;quot; means a fractional attack value after a bonus is rounded down&lt;br /&gt;
 -- &amp;quot;standard&amp;quot; means a fractional attack value is rounded down&lt;br /&gt;
 -- if fraction part is less than 0.5, and rounded up otherwise&lt;br /&gt;
 &lt;br /&gt;
 -- If the active unit can get a bonus, go through each category and compute the bonus for that category.&lt;br /&gt;
 -- Then, combine the bonuses for all categories to get the overall bonus, and round the result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With the bonusCategory defined, the value of the unit indices of categoryAttackBonusTable become easy to define.  Most of the specification is showing what exactly the different bonus categories mean, so the end user can use them properly.  It&#039;s not strictly necessary to offer so many choices to the end user on how to specify data, but it can be more convenient.&lt;br /&gt;
&lt;br /&gt;
Here is the actual code (before testing) to implement this more general version of attack bonuses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-- HELPER FUNCTION&lt;br /&gt;
-- findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable) --&amp;gt; number or false&lt;br /&gt;
-- usedUnitTable is indexed by the i.d. number of units, and if the value for a unit is true,&lt;br /&gt;
-- then it has already been used for a bonus (and, so, is not eligible)&lt;br /&gt;
-- The function returns the bonus (before nextBonusValue is applied) if there is one, and marks the &lt;br /&gt;
-- unit as used in the usedUnitTable&lt;br /&gt;
-- returns false if no unit qualifies&lt;br /&gt;
local function findBestBonusInUnitStack(tile,bonusCategory,usedUnitTable)&lt;br /&gt;
    local bestBonusSoFar = 0&lt;br /&gt;
    local bestUnitSoFar = nil&lt;br /&gt;
    -- find the best bonus. For all bonus types, the bonus will be greater than 0, &lt;br /&gt;
    -- and for all bonus types, a larger number means a better bonus&lt;br /&gt;
    for unit in tile.units do&lt;br /&gt;
        if not usedUnitTable[unit.id] and bonusCategory[unit.type.id] &lt;br /&gt;
            and bonusCategory[unit.type.id] &amp;gt; bestBonusSoFar then&lt;br /&gt;
            bestUnitSoFar = unit&lt;br /&gt;
            bestBonusSoFar = bonusCategory[unit.type.id]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if bestUnitSoFar then&lt;br /&gt;
        usedUnitTable[bestUnitSoFar.id] = true&lt;br /&gt;
        return bestBonusSoFar&lt;br /&gt;
    else&lt;br /&gt;
        return false&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- HELPER FUNCTION&lt;br /&gt;
-- computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
-- Computes the bonus that the active unit will receive from this category, taking into &lt;br /&gt;
-- account the type of bonus for the table&lt;br /&gt;
local function computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local bonusThusFar = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then &lt;br /&gt;
        bonusThusFar = 1&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        bonusThusFar = 100&lt;br /&gt;
    else&lt;br /&gt;
        bonusThusFar = 0&lt;br /&gt;
    end&lt;br /&gt;
    local bonusDiscount = 1&lt;br /&gt;
    for i=1,(bonusCategory.maxBonusUnits or 10000) do&lt;br /&gt;
        local currentBonus =findBestBonusInUnitStack(activeUnit.location,bonusCategory,usedUnitTable) &lt;br /&gt;
        if not currentBonus then&lt;br /&gt;
            -- no more valid bonuses for this category&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
        if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-1)*bonusDiscount+1)&lt;br /&gt;
        elseif bonusType ==&amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
            bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
        else&lt;br /&gt;
            bonusThusFar = bonusThusFar+currentBonus*bonusDiscount&lt;br /&gt;
        end&lt;br /&gt;
        bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
    end&lt;br /&gt;
    return bonusThusFar&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function categoryAttackBonus(activeUnit,categoryAttackBonusTable,defaultAttackTable)&lt;br /&gt;
    local bonusInfoTable = categoryAttackBonusTable[activeUnit.type.id]&lt;br /&gt;
    if not bonusInfoTable then&lt;br /&gt;
        -- unit doesn&#039;t get a bonus&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
    -- keep track of bonuses already computed&lt;br /&gt;
    local bonusResultsTable = {}&lt;br /&gt;
    -- keep track of units that have already been &amp;quot;used&amp;quot; for a bonus&lt;br /&gt;
    local usedUnitTable = {[activeUnit.id]=true}&lt;br /&gt;
    for index,bonusCategory in pairs(bonusInfoTable) do&lt;br /&gt;
        bonusResultsTable[index]=computeCategoryBonus(activeUnit,categoryAttackBonusTable,bonusCategory,usedUnitTable)&lt;br /&gt;
    end&lt;br /&gt;
    -- compute the bonus&lt;br /&gt;
    local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
    local resultAttackBeforeRounding = nil&lt;br /&gt;
    if bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
        local bonus = 1&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus*bonusResult/100&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding = activeUnit.type.attack*bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack+bonus&lt;br /&gt;
    elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+bonusResult&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
        local bonus = 0&lt;br /&gt;
        for __,bonusResult in pairs(bonusResultsTable) do&lt;br /&gt;
            bonus = bonus+(bonusResult/100)&lt;br /&gt;
        end&lt;br /&gt;
        resultAttackBeforeRounding =activeUnit.type.attack*(1+bonus)&lt;br /&gt;
    else&lt;br /&gt;
        error(&amp;quot;categoryAttackBonus: categoryAttackBonusTable.type is not a valid value.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    -- apply the bonus and round as appropriate&lt;br /&gt;
    local roundType = categoryAttackBonusTable.round&lt;br /&gt;
    if type(roundType) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;up&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.ceil(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    elseif roundType == &amp;quot;down&amp;quot; then&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding)&lt;br /&gt;
        return&lt;br /&gt;
    else&lt;br /&gt;
        activeUnit.type.attack = math.floor(resultAttackBeforeRounding+0.5)&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two helper functions for computeCategoryBonus are only used once each in the code, so making them helper functions does not help us re-use code.  However, what it does do is to break down the function design process into smaller tasks, which are each more manageable to complete.  If you&#039;re trying to keep track of too many things in your program, try writing a few helper functions to handle individual tasks.  We&#039;ll look at the helper functions when we actually arrive at them in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-09-CategoryAtkBonus1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If there is no entry in the categoryAttackBonusTable or the active unit&#039;s type, then the function returns without doing anything further.&lt;br /&gt;
&lt;br /&gt;
The bonusResultsTable keeps track of the total bonus from each category, so they can be added or multiplied together after all the category bonuses are applied.  The usedUnitsTable keeps track of units that are no longer eligible to contribute to a bonus (such as if they have already contributed), and we initialize it with the active unit, so that it doesn&#039;t provide a bonus to itself.&lt;br /&gt;
&lt;br /&gt;
The for loop computes the bonus for every category, and stores the value in the bonusResultsTable, for use later.Now, let us look at the helper functions.&lt;br /&gt;
&lt;br /&gt;
First up is findBestBonusInUnitStack&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-10-CategoryAtkBonus2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This basically does what it says in the name.  For a bonusCategory, it finds the unit in the tile that provides the best bonus, and has not already provided a bonus elsewhere.  If there is no qualifying unit, false is returned.  If there is, that unit&#039;s bonus is returned, and the unit&#039;s id is entered into the usedUnitTable, so that unit can&#039;t provide another bonus for the active unit.  We&#039;ve searched for the best of something before, so there is little need to go over it again.&lt;br /&gt;
&lt;br /&gt;
Next is computeCategoryBonus&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-11-CategoryAtkBonus3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here, we&#039;re computing the bonus for the entire bonusCategory.  We need the bonus type in order to know what kind of math to do.  The math itself is not very interesting.  We also initialize the bonusDiscount, which keeps track of the fraction of the next unit&#039;s bonus that will actually be applied.&lt;br /&gt;
&lt;br /&gt;
Next, we enter a for loop that will run one time for each possible bonus that there can be in a bonus category.  If bonusCategory.maxBonusUnits is nil, then we set an arbitrary limit of 10000 units, which is very unlikely to happen in practice.&lt;br /&gt;
&lt;br /&gt;
At each iteration of the loop, the best available bonus in the stack is found.  If no unit was eligible to provide a bonus, then the current bonus is false, and the &amp;quot;break&amp;quot; command is issued.  Break immediately exits the current loop.  So, our program doesn&#039;t run 10000 loops if there is no maximum number of bonus units, it just breaks at an appropriate time.&lt;br /&gt;
&lt;br /&gt;
After the bonus is found, it is added to or multiplied with the bonus already found.  The bonus computed in this way will be the largest possible, since the bonus provided does not depend on the other units chosen (so we don&#039;t have a situation where &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; are both useless, but &amp;quot;catapult&amp;quot; and &amp;quot;rock&amp;quot; chosen together are best).  Also, since the best bonus is chosen first, the smallest bonus discount applies to it, so the cost imposed by the discounting is smallest.&lt;br /&gt;
&lt;br /&gt;
Finally, we update the bonusDisount.  Here, I notice a problem in the code as written, since bonusCategory.nextBonusValue is allowed to be nil.  Replace&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*bonusCategory.nextBonusValue&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
with &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusDiscount = bonusDiscount*(bonusCategory.nextBonusValue or 1) &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
so that if there is no nextBonusValue, a default of 1 is used, and the bonusDiscount stays at 1 (i.e. no discount is applied).&lt;br /&gt;
&lt;br /&gt;
We return to categoryAttackBonus to see&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-12-CategoryAtkBonus4.jpg]]&lt;br /&gt;
&lt;br /&gt;
From here, we combine the bonuses stored in bonusResultsTable, the exact way of doing so being dependant on the type of bonus involved.  The math itself isn&#039;t very interesting, and doesn&#039;t seem all that likely to come up in this exact form elsewhere.  If you need help with the mathematical details of some event you want to write, ask in the forums.  There&#039;s a good chance someone has the skills to help you solve your specific problem.&lt;br /&gt;
&lt;br /&gt;
For every type of bonus, the result is stored in resultAttackBeforeRounding, so that variable can be rounded up or down as specified by the rounding type.&lt;br /&gt;
&lt;br /&gt;
Here, I notice another error.  We should restrict the attack value for a unit to not exceed 98.  We can do that with a math.min(value, 98).&lt;br /&gt;
&lt;br /&gt;
Now, we need to test the various aspects of the attack bonus program, so we need an appropriate table&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addbonus&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=2,[unitAliases.chariot.id]=4,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=2,[unitAliases.musketeer.id]=4,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Also, comment out the old attack bonus line, and put in a new one&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 attackBonus.categoryAttackBonus(unit,categoryAttackBonusTable,defaultAttackValueTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addbonus&amp;quot;&lt;br /&gt;
Legion:4attack&lt;br /&gt;
Legion+chariot:8 attack&lt;br /&gt;
Legion+chariot+chariot: 10 attack&lt;br /&gt;
Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
Already, we find a problem.  Although there were no syntax errors to fix, I forgot to reset unit attack values.  So, very quickly, the legions keep gathering extra attack values when they are activated (since the base attack is not reset to 4).  Since this is happening anyway, I&#039;ll test the 98 attack value maximum.  That appears to work, at least in the case of no specified rounding.&lt;br /&gt;
&lt;br /&gt;
Cut and paste the appropriate lines from the simpleAttackBonus to the categoryAttackBonus, and save.&lt;br /&gt;
&lt;br /&gt;
With that bug fixed, everything works as expected.&lt;br /&gt;
&lt;br /&gt;
Next, we change the categoryAttackBonusTable to &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addpercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=50,[unitAliases.chariot.id]=100,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=50,[unitAliases.musketeer.id]=100,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expected Test Results when type is &amp;quot;addpercent&amp;quot;.  These are the same, since adding we&#039;re adding percentages of the same base value of 4.  So a value of 2 is the same as adding 50% of 4.&lt;br /&gt;
Legion:4attack&lt;br /&gt;
Legion+chariot:8 attack&lt;br /&gt;
Legion+chariot+chariot: 10 attack&lt;br /&gt;
Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
The results are the same.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;addfraction&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=.50,[unitAliases.chariot.id]=1.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.50,[unitAliases.musketeer.id]=1.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion:4attack&lt;br /&gt;
Legion+chariot:8 attack&lt;br /&gt;
Legion+chariot+chariot: 10 attack&lt;br /&gt;
Legion+chariot+chariot+chariot: 11 attack&lt;br /&gt;
Legion+chariot+chariot+chariot+chariot+horseman: 11 (if maxBonusUnits not applied,11.5+2/16 rounds to 12)&lt;br /&gt;
Legion+musketeer+archer: 4+4+1.5=9.5 round to 10, (if archer computed first then 4+2+3 = 9 instead)&lt;br /&gt;
Legion+musketeer+chariot+chariot+chariot: 15 attack&lt;br /&gt;
&lt;br /&gt;
We&#039;ll have to do some new calculations, now, since multiply and multiplyfraction give different results than the various adding formulations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiply&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=1.50,[unitAliases.chariot.id]=2.00,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=1.50,[unitAliases.musketeer.id]=2.00,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion:4attack&lt;br /&gt;
Legion+chariot:8 attack&lt;br /&gt;
Legion+chariot+chariot: 12 attack&lt;br /&gt;
Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Finally, we use multiplyPercent, and check for the same results&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,nextBonusValue=0.5,maxBonusUnits=3}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=150,[unitAliases.musketeer.id]=200,nextBonusValue=0.75,}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]={cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;down&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Legion:4attack&lt;br /&gt;
Legion+chariot:8 attack&lt;br /&gt;
Legion+chariot+chariot: 12 attack&lt;br /&gt;
Legion+chariot+chariot+chariot: 15 attack&lt;br /&gt;
Legion+chariot+chariot+chariot+chariot+horseman: 15 (if maxBonusUnits not applied,~17 )&lt;br /&gt;
Legion+musketeer+archer: 4*2*(1.375) = 11 , (if archer computed first then 4*1.5*1.75 =10.5 instead, so use round down)&lt;br /&gt;
Legion+musketeer+chariot+chariot+chariot: 30 attack (4*2*2*1.5*1.25)&lt;br /&gt;
&lt;br /&gt;
Quickly, I find that if a bonus applies, that bonus makes the attack value of a legion 98.  I failed to multiply percents correctly in computeCategoryBonus.  The Line &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+1)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Is changed to &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 bonusThusFar = bonusThusFar*((currentBonus-100)*bonusDiscount+100)/100&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, Change archer bonus to 110 and musketeer bonus to 120 (so a unit will make a legion have 4.4 and 4.8 value before rounding), and test the rounding options.  You will find they all work.&lt;br /&gt;
&lt;br /&gt;
At the moment, we don&#039;t have a way to mix different types of bonuses.  As said earlier, we might want this so that some units can be better at giving bonuses to low attack units than to high attack units, while others give a percentage bonus to everything.  We could now write a bonus system that allows for multiple types of bonuses. However, the current bonus system allows for the bonus to change per unit.  This means that we can, for example, convert a +2 attack bonus to a plus 100% bonus for a unit with 2 attack, and a plus 50% bonus for a unit with 4 attack.  In the case of the multiplied bonuses, this will make the bonus more powerful if there is more than one.  That is, 2 attack, +2 twice is 6, but if +2 is changed to x2, then the multiplied bonus brings the attack up to 8.  However, this seems like it would be a relatively unlikely problem, and there are other things this code can&#039;t handle, so we&#039;ll let someone else make the code if they actually need it.&lt;br /&gt;
&lt;br /&gt;
So, what we&#039;ll do is write a function that will change all appropriate entries in the categoryAttackBonusTable to reflect a different value.  Hence,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed(unitType,number,categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unit type to any unit to be equivalent&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, an issue with tables arises.  It is very likely that when someone defines their cateogryAttackBonusTable, they&#039;ll define it something like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=.25,[unitAliases.musketeer.id]=.5}&lt;br /&gt;
 local bonusTableForInfantry = {rangeBonusCategory}&lt;br /&gt;
 local cABT = {type=&amp;quot;addfraction&amp;quot;}&lt;br /&gt;
 cABT[unitAliases.phalanx.id]=bonusTableForInfantry&lt;br /&gt;
 cABT[unitAliases.legion.id] = bonusTableForInfantry&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
However, this means that both &amp;lt;code&amp;gt; cABT[unitAliases.legion.id]  &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt; cABT[unitAliases.phalanx.id] &amp;lt;/code&amp;gt; actually refer to the same piece of memory, and changing cABT[unitAliases.legion.id][1][unitAliases.archer.id] will also change the value at cABT[unitAliases.phalanx.id][1][unitAliases.archer.id].  This is because of the way lua tables are designed.  This design can be useful, for example it allowed us to make changes to usedUnitsTable in the last function without having to copy the table, make changes to the copy of the table, and then replace the original table with that copy as a return value.  However, it also requires us to be careful when we make changes to entries in tables.  In this case, we&#039;ll simply copy the table and all its sub values into a new table.&lt;br /&gt;
&lt;br /&gt;
The code to do this is given by&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will explain this code in the next section, since it involves a programming technique which we haven&#039;t discussed before.&lt;br /&gt;
&lt;br /&gt;
For now, we analyze plusFixed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- plusFixed({[unitType1.id]=fixedBonus,[unitType2.id]=fixedBonus},categoryAttackBonusTable) --&amp;gt; void&lt;br /&gt;
 -- changes the bonus given by unitTypeI.id to a unit to be equivalent to&lt;br /&gt;
 -- to adding number to that unit&#039;s attack power.  If the unit doesn&#039;t receive a bonus&lt;br /&gt;
 -- from the unitType, then it won&#039;t after applying plusFixed.&lt;br /&gt;
 -- The value of the existing bonus is ignored.&lt;br /&gt;
 &lt;br /&gt;
 local function plusFixed(fixedUnitBonusTable,categoryAttackBonusTable)&lt;br /&gt;
     local bonusType = string.lower(categoryAttackBonusTable.type)&lt;br /&gt;
     for bonusReceivingUnitTypeID,bonusTable in pairs(categoryAttackBonusTable) do&lt;br /&gt;
         -- replace bonusTable with an equivalent table that is not referened&lt;br /&gt;
         -- anywhere else, so that changes to it can be made without impacting&lt;br /&gt;
         -- data elsewhere&lt;br /&gt;
         categoryAttackBonusTable[bonusReceivingUnitTypeID] = duplicateTable(bonusTable)&lt;br /&gt;
         -- make bonusTable refer to the &amp;quot;current&amp;quot; bonus table for the unit type&lt;br /&gt;
         bonusTable =categoryAttackBonusTable[bonusReceivingUnitTypeID] &lt;br /&gt;
         -- For each unit type in the fixedUnitBonusTable, check if any bonus category&lt;br /&gt;
         -- in the bonusTable corresponds to it.  If so, make the change&lt;br /&gt;
         for bonusGivingUnitTypeID,fixedBonusValue in pairs(fixedUnitBonusTable) do&lt;br /&gt;
             -- get the attack of the unit type &lt;br /&gt;
             local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
             -- in each bonus category, check if the giver&#039;s unit type id is there,&lt;br /&gt;
             -- if so, change to the correct attack&lt;br /&gt;
             for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
                 if bonusCategory[bonusGivingUnitTypeID] then&lt;br /&gt;
                 -- change the bonus appropriately&lt;br /&gt;
                     if bonusType == &amp;quot;addbonus&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue&lt;br /&gt;
                     elseif bonusType == &amp;quot;addpercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;addfraction&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=fixedBonusValue/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiplypercent&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=100*(fixedBonusValue+baseAttack)/baseAttack&lt;br /&gt;
                     elseif bonusType == &amp;quot;multiply&amp;quot; then&lt;br /&gt;
                         bonusCategory[bonusGivingUnitTypeID]=(fixedBonusValue+baseAttack)/baseAttach&lt;br /&gt;
                     else&lt;br /&gt;
                         error(&amp;quot;pluxFixed: categoryAttackBonusTable.type does not have an acceptable value.&amp;quot;)&lt;br /&gt;
                     end&lt;br /&gt;
                 end&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-13-plusFixed1.jpg]]&lt;br /&gt;
&lt;br /&gt;
As before, we save the bonusType in lower case, since we&#039;ll be using it a lot later.  Next, we open a for loop, where the index is the id of the unit type receiving the bonus, and the value is the bonus table for that unit type.  Next, we duplicate the bonus table, so that we have a table we can change without impacting anything elsewhere, and we store the duplicated table in categoryAttackBonusTable in place of the original bonusTable for the current bonus receiving unit id.  Next, we assign this duplicated table to the variable bonusTable, so we can refer to it later in the code.&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-14-plusFixed2.jpg]]&lt;br /&gt;
&lt;br /&gt;
We now perform the following actions for each unitType.id and corresponding fixedBonusValue submitted in the fixedUnitBonusTable.&lt;br /&gt;
&lt;br /&gt;
First, get the attack of the bonus receiving unit, since we&#039;ll need that in order to customize the bonus.  Next, check each bonus category in the bonus table.  If the bonus category has the current unitTypeID as a key, then replace the existing value with a bonus equivalent to adding a fixed value to the receiving unit&#039;s attack.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all that must be done, so end all the loops.&lt;br /&gt;
&lt;br /&gt;
Now we test the function.&lt;br /&gt;
&lt;br /&gt;
Add unitAliases.phalanx = civ.getUnitType(3) to the appropriate file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 defaultAttackValueTable[unitAliases.phalanx.id]=1&lt;br /&gt;
 categoryAttackBonusTable = {}&lt;br /&gt;
 categoryAttackBonusTable.type=&amp;quot;multiplypercent&amp;quot;&lt;br /&gt;
 local cavalryBonusCategory = {[unitAliases.horsemen.id]=150,[unitAliases.chariot.id]=200,&lt;br /&gt;
 								nextBonusValue=0.5,maxBonusUnits=1}&lt;br /&gt;
 local rangeBonusCategory = {[unitAliases.archer.id]=125,[unitAliases.musketeer.id]=150,&lt;br /&gt;
 								nextBonusValue=0.75,maxBonusUnits=1}&lt;br /&gt;
 local standardBonus = {cavalryBonusCategory,rangeBonusCategory}&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.legion.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable[unitAliases.phalanx.id]=standardBonus&lt;br /&gt;
 categoryAttackBonusTable.round=&amp;quot;up&amp;quot;&lt;br /&gt;
 attackBonus.plusFixed({[unitAliases.chariot.id]=2,[unitAliases.musketeer.id]=2},&lt;br /&gt;
 						categoryAttackBonusTable)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The chariot and the musketeer individually should each add 2 to both a phalanx and a legion,&lt;br /&gt;
so the phalanx should have an attack of 3, and the legion should have an attack of 6, if one bonus&lt;br /&gt;
is applied.&lt;br /&gt;
&lt;br /&gt;
Since the bonus type is multiplypercent, together the phalanx would have an attack of 9, and the legion will also have an attack of 9.&lt;br /&gt;
&lt;br /&gt;
In testing, we quickly get this error&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
You should see this in lua console if this worked&lt;br /&gt;
...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: bad argument #1 to &#039;getUnitType&#039; (number expected, got string)&lt;br /&gt;
stack traceback:&lt;br /&gt;
	[C]: in function &#039;civ.getUnitType&#039;&lt;br /&gt;
	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:356: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At line 356, which is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 local baseAttack = civ.getUnitType(bonusReceivingUnitTypeID).attack&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This must mean that bonusReceivingUnitTypeID is not a number.  This is because we&#039;re looping over categoryAttackBonusTable, and that table has a couple of entries that are not integers (&amp;quot;type&amp;quot; and &amp;quot;round&amp;quot;).  Therefore, we have to insert code to deal with this eventuality.&lt;br /&gt;
&lt;br /&gt;
The simplest way is to put everything in the loop body into an if statement, so that it only runs when bonusGivingUnitTypeID is actually a number.  You should be able to do this without detailed instructions, so do so (hint: use type function).&lt;br /&gt;
&lt;br /&gt;
The next error is &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: bad argument #1 to &#039;pairs&#039; (table expected, got nil)&lt;br /&gt;
 stack traceback:&lt;br /&gt;
 	[C]: in function &#039;pairs&#039;&lt;br /&gt;
 	...rive_c\Test of Time\Scenario\ClassicRome\attackBonus.lua:360: in function &#039;attackBonus.plusFixed&#039;&lt;br /&gt;
 	...e15\drive_c\Test of Time\Scenario\ClassicRome\events.lua:218: in main chunk&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 360 for bonusCategoryIndex,bonusCategory in pairs(bonusTable) do&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we have a nil value for bonusTable.  This turns out to be an error in duplicateTable.  When I duplicated the table, I forgot to return that table.  That is, both the if and else statement in that function need a return command, and I forgot to add &amp;lt;code&amp;gt; return duplicatedTable &amp;lt;/code&amp;gt; in the if portion.  Add this to the duplicate table function.&lt;br /&gt;
&lt;br /&gt;
After this, our predictions are true.  Testing the other types of bonus is left as an assignment.&lt;br /&gt;
&lt;br /&gt;
===Recursive Functions===&lt;br /&gt;
&lt;br /&gt;
Let us return to the duplicateTable function.  Recall that in the last section we added a line to it, so we&#039;ll restate it here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 -- duplicateTable(table or value) --&amp;gt; table or value&lt;br /&gt;
 -- duplicates a table and all the other tables referenced in that table&lt;br /&gt;
 -- this way, a change can be made to any element of the table,&lt;br /&gt;
 -- and it won&#039;t impact data referenced anywhere else (unless this newly&lt;br /&gt;
 -- created table is subsequently referenced)&lt;br /&gt;
 -- if a non-table value is input, that value is returned&lt;br /&gt;
 --&lt;br /&gt;
 local function duplicateTable(input)&lt;br /&gt;
     if type(input) == &amp;quot;table&amp;quot; then&lt;br /&gt;
         -- the input value is a table, so create a new table&lt;br /&gt;
        local duplicatedTable={} &lt;br /&gt;
         -- and copy all the indexes and values into the new table, &lt;br /&gt;
         -- making sure to duplicate any tables that appear as values&lt;br /&gt;
         for index,value in pairs(input) do&lt;br /&gt;
             duplicatedTable[index]=duplicateTable(value)&lt;br /&gt;
         end&lt;br /&gt;
 		return duplicatedTable&lt;br /&gt;
     else&lt;br /&gt;
         -- the input value was not a table, so we return that value&lt;br /&gt;
         return input&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:GetStartedWithLuaLesson6-16-duplicateTable.jpg]]&lt;br /&gt;
&lt;br /&gt;
The interesting thing about duplicateTable is that it invokes duplicateTable within its code.  When we copy the key-value pairs into the new table, we run duplicateTable on the value.  If the value is not a table, then we are in the else case, and the value is immediately returned to be inserted into the duplicated table.  If the value is a table, that table is duplicated before anything else is done.&lt;br /&gt;
&lt;br /&gt;
Let us look at a simple example of a recursive function, the factorial function N!.  In lesson 3, we discussed the factorial function in the context of loops.  Since N!=N*(N-1)*(N-2)*...*3*2*1, we can give another definition of N!:&lt;br /&gt;
N!=1 if N = 1&lt;br /&gt;
N!=N*(N-1)! if N &amp;gt; 1&lt;br /&gt;
Or, using the convention that 0!=1, we can state&lt;br /&gt;
N!=1 if N = 0&lt;br /&gt;
N!=N*(N-1)! if N &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
The case where N =1 or N=0 is called the &amp;quot;base case.&amp;quot;  If we keep substituting N! as N*(N-1)!, then we won&#039;t go on forever, because we will eventually reach a point where N=0, and N! can be substituted as 1 instead of N*(N-1)!.  As long as there is a base case, our program will eventually reach the base case(s), and begin &amp;quot;completing&amp;quot; evaluation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
function factorial(N)&lt;br /&gt;
if N&amp;gt;0 then&lt;br /&gt;
    return N*factorial(N-1)&lt;br /&gt;
else&lt;br /&gt;
    return 1&lt;br /&gt;
end&lt;br /&gt;
end&lt;br /&gt;
print(factorial(5))&lt;br /&gt;
print(factorial(6))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run this in code in the lua demo website, or using the TOTPP lua interpreter.&lt;br /&gt;
&lt;br /&gt;
Returning to our duplicateTable function, the base case is any time a table value is not itself a table.  When that happens, the recursion &amp;quot;chain&amp;quot; ends, and everything can evaluated.&lt;br /&gt;
&lt;br /&gt;
Although is shouldn&#039;t be a problem in this particular case, it should be noted that it is possible for there to not be a &amp;quot;base case&amp;quot; in the recursion style: if table, recur, if not return a value.  Consider the following table system&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
a={}&lt;br /&gt;
b={[1]=a}&lt;br /&gt;
a[1]=b&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In this case, the code would never end.&lt;br /&gt;
&lt;br /&gt;
It is possible that even if the code could &amp;quot;theoretically&amp;quot; execute to completion, you run out of memory before that.  This is called a &amp;quot;stack overflow,&amp;quot; and if it occurs, you will have to think of an alternate way to solve your problem.  It will probably be best to ask for help in that case (and it might be useful to provide others with an example of a problem that results in a stack overflow), but you might also look into &amp;quot;tail recursion&amp;quot;, including http://www.lua.org/pil/6.3.html .&lt;br /&gt;
&lt;br /&gt;
===Conclusion===&lt;br /&gt;
&lt;br /&gt;
With the skills covered in this chapter, you now have the tools to split a large events file into multiple files that are more manageable.  You also have the basics for how to write re-useable modules for your events, so that your work can be used by others.  Remember that if someone else uses your implementation of a feature, they will spend much less time coding and testing it, allowing them to either finish the scenario sooner, or to introduce some other feature.  So, it might very well pay to spend at least a little effort making your code into a reusable module.  Perhaps you have an idea for a cool scenario mechanic, but don&#039;t have a scenario for it (or don&#039;t want to take the time to make it).  If that&#039;s the case, just make the module and test it in a &amp;quot;toy&amp;quot; scenario (like Classic Rome) so that it can be used more or less &amp;quot;off the shelf&amp;quot; when someone needs it.&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
	<entry>
		<id>https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson6-16-duplicateTable.jpg&amp;diff=5179</id>
		<title>File:GetStartedWithLuaLesson6-16-duplicateTable.jpg</title>
		<link rel="alternate" type="text/html" href="https://sleague.civfanatics.com/index.php?title=File:GetStartedWithLuaLesson6-16-duplicateTable.jpg&amp;diff=5179"/>
		<updated>2019-07-26T14:17:59Z</updated>

		<summary type="html">&lt;p&gt;Prof. Garfield: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prof. Garfield</name></author>
	</entry>
</feed>