|AI & Tools|
These are the main features of the Communitas AI and Tools for Civ V: BNW.
You can also look at the pre-BNW feature page to see what the project will do once we finish adapting it to the expansion: Civup
We started this expansion pack because we believe Civilization is a fantastic game, and want to perfect it while remaining as close to the core experience as possible.
Cat makes the AI "smarter not harder." It improves the intelligence of the AI, while reducing the bonuses of the AI. Cat also adds many tools essential for modders. The other parts of the Communitas Expansion Pack (Ceg and Cin) use these tools.
- Details: Goals
"Good For" Analysis
I created an AI to automatically figure out the purpose of each building, unit, and tech. It shows its conclusions on tooltips.
This helps people new to mod, or people trying to analyze tech balance. We can glance at Pottery and immediately see it's good for religion, growth, and so on. There's no need to look at every number of every unit and building to figure out what it's good for. Pottery also leads to things good for science and culture, which the AI recognizes, and puts on the ratings of this tech.
This combines the strengths of AIs and humans. AIs can quickly analyze lots of numbers, while humans are better at choosing priorities.
In the past, humans had to laborously set the "good for" values for everything. The new AI reduces bugs and saves huge amounts of time and effort for human game designers. The computer players also ask this AI what each unit/building/tech is good for. This makes AI players smarter.
The tools below help people interested in modifying the game. You only need to read about these tools if you intend to create mods or improve this project.
This automatically writes tooltips for buildings, units, and promotions, reducing bugs and workload for human designers. It includes the basic attributes of units on their tooltip, like the move-after-attack capability of Horsemen.
I redesigned the yield functions so they are easier to use. For example, a single function player:GetYieldStored returns stored gold, science, culture, or so on. This is vastly simpler than the disorganized collection of functions required in the past.
CAT adds many new functions for the city, player, plot, and unit objects. You can find these in /Cat/Tools/ClassMethods. The project also adds many miscellaneous utility functions in /Tools/Core/MT_Utils.lua.
The first block of events can check players, units, cities, etc at the start or end of each turn. These loop through each category just once per turn to improve efficiency, and removes the need for multiple loops in multiple files.
For example, the ClearCamps function below runs at the end of the active player's turn. If an error occurs in the function, it will not interrupt other events in the project, because of the use of SafeCall.
function ClearCamps() -- do stuff end LuaEvents.ActivePlayerTurnEnd_Turn.Add(function() return SafeCall(ClearCamps) end)
Here are the available events:
LuaEvents.ActivePlayerTurnStart_Turn() LuaEvents.ActivePlayerTurnStart_Player(player) LuaEvents.ActivePlayerTurnStart_Unit(unit) LuaEvents.ActivePlayerTurnStart_City(city, owner) LuaEvents.ActivePlayerTurnStart_Plot(plot) LuaEvents.ActivePlayerTurn_Turn() LuaEvents.ActivePlayerTurn_Player(player) LuaEvents.ActivePlayerTurn_Unit(unit) LuaEvents.ActivePlayerTurn_City(city, owner) LuaEvents.ActivePlayerTurn_Plot(plot) LuaEvents.NewCity(hexPos, playerID, cityID, cultureType, eraType, continent, populationSize, size, fowState) LuaEvents.NewUnit(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible) LuaEvents.NewImprovement(hexX, hexY, cultureArtID, continentArtID, playerID, engineImprovementTypeDoNotUse, improvementID, engineResourceTypeDoNotUse, resourceID, eraID, improvementState) LuaEvents.NewTech(player, techID, changeID) LuaEvents.PlotChanged(hexX, hexY) LuaEvents.PlotAcquired(plot, newOwnerID) LuaEvents.NewPolicy(policyID, isPolicy) LuaEvents.CityOccupied(city, player, isForced) LuaEvents.CityPuppeted(city, player, isForced) LuaEvents.CityLiberated(city, player, isForced) LuaEvents.PromotionEarned(unit, promotionType) LuaEvents.UnitUpgraded(unit) LuaEvents.BuildingConstructed(player, city, buildingID) LuaEvents.BuildingDestroyed(player, city, buildingID) LuaEvents.CheckPlotBuildingsStatus(plot)
Tool: Error Handler
This lua message logger based on Java’s log4j provides dramatically easier debugging. While working on a mod it's often useful to print information to the console when fixing bugs. This utility is a powerful extension of the standard print function.
- Based on the industry standard log4j testing framework.
- Your mod won't spam the lua console when other modders need to use it.
- Automatically converts invalid variables to strings (nil outputs as "nil"), eliminating the need to tostring(...) variables that might not be initialized.
- Testers of your mod can easily enable specific levels of debug output without any programming knowledge, providing you valuable feedback.
- Built-in support for string.format codes to customize your debug output:
logger:Info("GiveMilitaristicRewards %15s rateMod=%.2f turnRate=%i", player:GetName(), rateMod, turnRate) output: myModName: INFO: GiveMilitaristicRewards Augustus 1.21 6 myModName: INFO: GiveMilitaristicRewards Nebuchadnezzar 1.76 3 myModName: INFO: GiveMilitaristicRewards Elizabeth 1.53 4
How to Use
Say you want to display someVariable, then check if it equals a test value:
include("MT_LuaLogger.lua") local log = Events.LuaLogger:New() log:SetLevel("DEBUG") function SomeFunction(someVariable) log:Debug("someVariable = %s", someVariable) if not someVariable then log:Warn("someVariable is nil!") end if someVariable ~= 42 then log:Info("someVariable is not the answer to life.") end end
This will display in the Live Tuner console and lua.log:
myModName: DEBUG: someVariable = 10 myModName: INFO: someVariable is not the answer to life.
When you're ready to release your mod, you can change setLevel("DEBUG") to setLevel("WARN") and nothing will display but important warning messages. I usually set files to the WARN level when not debugging.
These are the output levels from most to least important. If the logger level is set to "ERROR", only fatal and error messages will display. At the "TRACE" level, all messages will display. These messages appear in the Tuner console.
Critical errors where the mod cannot continue execution. Sending a Fatal message to the logger prints the message, terminates execution of the active Lua thread, and prints a trace of function calls which led to the error.
Example: A function expects an integer for one of its parameters but receives a nil value.
Other errors or unexpected conditions, but the mod can continue processing.
Example: A map script attempted to place 10 resources, but could only find locations for 9 resources.
'Almost' errors or undesirable situations, but not necessarily "wrong".
Example: A utility library for save-data warns users of the library that the map cache cannot be shared between mods.
Interesting events like starting a function.
Example: A map script prints results of natural wonder placement.
Detailed information on the flow through the system.
Example: A function prints the quantity of each terrain type around a unit before performing actions based on the surrounding terrain.
Step-by-step execution path of instructions, since the ModBuddy compiler can't do that for Lua.
Example: For every building, a function prints the yield type and quantity of every policy each player has which improves those buildings.
The page below shows all changes made to the project after July 12th 2013. (See civmodding.wordpress.com for earlier versions.) These are listed in chronological order for people who already have the mod to see what changes in updates.
- Details: Cat - History