[TOT] New Supply Lines module for Lua events

Knighttime

Prince
Joined
Sep 20, 2002
Messages
380
More than a few scenario developers have probably wished there was a way to implement supply lines into a scenario, in an abstract way -- that is, without the micromanagement of moving dozens of supply train units across the map each turn. This concept is now possible and can be integrated into a TOT scenario using Lua events and TOTPP, and the attached module provides a working implementation.

This is a separate supplyLines.lua file that would be stored within a scenario directory and referenced from the scenario's main events.lua file. It allows the scenario designer to first customize the definition of a valid supply link -- that is, what criteria determine whether or not a supply line can pass through a given tile. Then you can customize the definition of a valid supply depot, from which supplies would originate to reach units in the field. The remainder of the code in the module contains the pathfinding logic that searches for a connection between the unit and depot that meets all of the criteria. Each time a unit is activated, the main events.lua file runs this module to immediately determine whether or not that unit is supplied.

As an aid to the designer, the module also contains a "review" feature that will highlight the shortest valid path connecting the active unit to the nearest valid supply depot. (If there are multiple paths of equal length, the first one found by the pathfinding logic is the one which will be highlighted.) If no such depot could be found, the highlighting can be used to reveal the area of the map from which the active unit *could* be supplied, if a depot was located there.

More details, including a working example, are available within the attachment. Here are a series of screen shots to illustrate the behavior:

SupplyLines1.jpg
In this first screen shot, the Warrior cannot be supplied from the city of Rome, because it is not a port city. (This example defined supply lines that are permitted to cross ocean tiles, but only to reach port cities -- they may not proceed further inland.) Therefore the closest depot is the city of Antium, so the supply line ignores Rome and connects Antium to the Warrior.

SupplyLines2.jpg
In this second screen shot, a barbarian Trireme has now blockaded the north side of the city of Antium, which was previously part of the supply line. However, the pathfinding logic determined that it is still possible for supplies from Antium to reach the Warrior, by a longer southern route.

SupplyLines3.jpg
In this third screen shot, another barbarian Trireme has now occupied a narrow channel that was previously part of the southern supply line to Antium. The pathfinding logic correctly identified that now Antium is no longer reachable at all, so the shortest valid supply line extends all the way to Cumae.

LuaConsole.jpg
The Lua console, which provides information to the scenario designer, reveals the actions taken by the module in the above examples. As you can see, Lua is pretty quick! The pathfinding logic analyzed 1731 tiles in order to find the supply line between the Warrior and Cumae, which was 65 tiles long, and it did so in less than 1/10 of a second. It should be possible to support supply lines of just about any length, even on large maps, with no discernible lag in performance. However, it's very easy to configure a maximum supply line length, which may be more realistic for scenarios anyway. This would limit the number of tiles the module would need to analyze, and would also ensure that performance remains acceptable even on extremely large maps.

If this feature would be useful in a scenario you are designing, you're welcome to incorporate it and customize it as you wish. I'll do my best to answer any qustions you may have as you do so. Please let me know if you have any feedback, including requests for new features.

As with all Lua features for TOT, a big round of applause for TheNamelessOne who created TOTPP and made it possible for Lua events to interact with the game, at a level far surpassing what was possible with the original macro language.

Happy Civing!
 

Attachments

Last edited:
Hi Knighttime,

This is a very interesting indeed and I’m certain many designers will want to implement this in their scenarios at one point or another. I did take the opportunity to take a preliminary look at the event file itself and, if you don’t mind, had few starting questions.

Looking at the code, it’s a little unclear to me. Can a supply source only be a city tile or could it also be a unit (say an HQ or Supply Depot)?

Could one limit the number of units a supply source could support, say either based on a hardcoded number or the size of a city for example?

It looks like the supply for each unit is determined at the moment of its activation (civ.scen.onActivateUnit). Does the out supply status apply for the remainder of the turn? Or can a unit move within that same turn to a tile that would put it back in supply? Personally I would prefer the former but since the event appears to be related to the onActivateunit I suspect it might be the latter.

In the events.lua file you made the effect of being out of supply to reduce the attack factor to zero. Could one also reduce its movement factor, for example to one or zero MP’s, or apply attrition to the unit or any combination of all three at the same time?

Does an enemy unit’s ZOC (i.e. the 8 tiles surrounding the unit) block a supply line or just the tile the unit physically occupies count?

I noticed in the supplyLines.lua that the code appears to apply only for land units. Could a similar kind of feature be designed for naval units? I’ve always found it somewhat unrealistic that once your naval units left a port that they could essentially remain at sea for the remainder of the scenario without ever needing to come back to port. Would it be possible, for example, to reduce the movement factor of a naval unit that was at sea by half if it didn’t begin the turn say stacked with a supply/tanker ship?
 
This is an awesome tool that I think is going to make a world of difference in new scenarios, and possibly refresh some older ones.

Knighttime had asked me about ZOC when developing this and I asked that he not include that at the time because I was looking at this from the perspective of trying to replicate Stalingrad, with the 6th Army desperately trying to keep a small corridor open for supplies and so I was trying to go for a total encirclement to cut off supplies.

With that said I at least got the impression from our conversation that ZOC would be possible.

One question I have is if it would be possible to perhaps use a terrain "improvement" like pollution, an airbase or fortress to show the supply chain (rather than a unit) which the player could then press a key to "see" briefly before it "disappears" (perhaps onActivate of the next unit). All this to help people understand what they need to do to break the siege or to effect one.
 
All good questions! I will start a list of possible enhancements for version 2.0. :)

Can a supply source only be a city tile or could it also be a unit (say an HQ or Supply Depot)?
Yes, it could certainly be a unit. Really it can be any object or attribute that is associated with a specific location on the map. The isValidSupplyDepot() function takes a tile and a tribe as parameters, and needs to contain logic to answer the question, "Can this tile serve as a supply depot for this tribe?" I could add another commented-out example in that function, showing how to test that location for the presence of a particular unit type.

However, remember that due to an apparent bug, if a unit is activated directly from the city screen, the onActivateUnit() trigger doesn't fire. If all cities are supply depots, and your suppliedUnitEffects() function is written to assume that units are supplied by default and to apply a penalty if they are not, this isn't really an issue. But if some/all cities are not supply depots, you could run into a situation where a unit activated in such a city wouldn't search for a supply line. So... just something to keep in mind as the designer, and weigh pros and cons.

The only other thing I'll add is that a key advantage of this module is that it allows you to abstract supply lines away from needing to move supply train units around on the map, thus reducing micromanagement. Using a unit as a depot is certainly possible, but if you take that idea too far, you may end up losing much of the benefit.

Could one limit the number of units a supply source could support, say either based on a hardcoded number or the size of a city for example?
How would you envision that the game would identify which units are supplied by that source, if the number of possibilities exceeded that limit? Simply order of unit activation on a given turn? That seems a little arbitrary and could force the player back into micromanagement, by very carefully activating units manually in a particular order. From a code perspective, this would require the use of the state table to track history, so it would add quite a bit of complexity. I'm not sure I see a clear path forward for this one yet.

It looks like the supply for each unit is determined at the moment of its activation (civ.scen.onActivateUnit). Does the out supply status apply for the remainder of the turn? Or can a unit move within that same turn to a tile that would put it back in supply? Personally I would prefer the former but since the event appears to be related to the onActivateunit I suspect it might be the latter.
Correct, it's the latter at this point: a unit which begins its turn "out of supply" does not necessarily have that status for its entire turn. A change in status could be achieved by moving the unit (so that it's in range of a supply depot) or by killing an enemy unit that was blocking a depot (thereby opening up a valid supply line) or even by adding/moving a supply depot (building a new city, moving a supply "storehouse" unit, building a new tile improvement such as an airbase, etc.).

Calculating the supplied status for each unit at the beginning of your turn, and having that status apply for the entire turn, would definitely be possible, but this would again require the use of the state table. Because units can be both killed and created during a turn, and unit IDs get reused by the game :(, the complexity goes up quickly. Would this be a huge benefit to you? If so I can add it to the list of version 2.0 ideas. Personally I prefer the current behavior, and it was definitely simpler to write, so that's why it works this way in version 1.0. :)

In the events.lua file you made the effect of being out of supply to reduce the attack factor to zero. Could one also reduce its movement factor, for example to one or zero MP’s, or apply attrition to the unit or any combination of all three at the same time?
Absolutely, all of those are possible. The example provided in events.lua was recommended by @JPetroski to illustrate the power of this feature, but it's just one example and not intended to limit you from introducing new or different effects.

Does an enemy unit’s ZOC (i.e. the 8 tiles surrounding the unit) block a supply line or just the tile the unit physically occupies count?
Knighttime had asked me about ZOC when developing this and I asked that he not include that at the time because I was looking at this from the perspective of trying to replicate Stalingrad, with the 6th Army desperately trying to keep a small corridor open for supplies and so I was trying to go for a total encirclement to cut off supplies.
With that said I at least got the impression from our conversation that ZOC would be possible.
This is definitely something I considered, but based on John's feedback it didn't seem like a critical feature, at least for version 1.0. This would add some complexity to the code, but my biggest concern is performance: this would mean that every tile the code analyzes, to see if it's a valid supply link, would require it to find up to 7 other tiles, and look for enemy units on them. That could be a pretty severe hit and might mean that there would need to be a much lower cap on the maximum supply line length, to avoid a noticeable lag each time a unit is activated. I haven't tried to write or test this yet, though, so it's all speculation at this point.

I noticed in the supplyLines.lua that the code appears to apply only for land units. Could a similar kind of feature be designed for naval units? I’ve always found it somewhat unrealistic that once your naval units left a port that they could essentially remain at sea for the remainder of the scenario without ever needing to come back to port.
Yes, a similar kind of feature would be possible, but it seems to me that you might want different rules for valid supply lines, or depots, than you would use for land units. So this might necessitate adding additional constants at the top of the file, splitting isValidSupplyDepot() into separate isValidLandUnitSupplyDepot() and isValidNavalUnitSupplyDepot() functions, possibly doing the same to isValidSupplyLink(), and then adjusting the core logic in hasSupplyLine() to branch based upon unit domain.
Would it be possible, for example, to reduce the movement factor of a naval unit that was at sea by half if it didn’t begin the turn say stacked with a supply/tanker ship?
This actually wouldn't require a supplyLines module at all, since the primary purpose of it is pathfinding -- detecting an open route between a unit and a depot located elsewhere. If all you want is to detect the presence of a supply unit on the same tile, for either land or naval units, this could be done directly within the onActivateUnit() section of your events.lua.

One question I have is if it would be possible to perhaps use a terrain "improvement" like pollution, an airbase or fortress to show the supply chain (rather than a unit) which the player could then press a key to "see" briefly before it "disappears" (perhaps onActivate of the next unit). All this to help people understand what they need to do to break the siege or to effect one.
Sure, that would be possible and not too difficult. I picked a unit because it seemed more likely that a scenario could spare one unit slot, than that the scenario would have no pollution/fortresses/airbases thus leaving one of those icons available. I could add some commented-out examples of how to implement those other options though.
 
I'm trying to envision how to use this for naval supply routes, specifically convoy routes going to Britain (or any other island in any scenario). In this case, it would be preferable for the city to be reliant on supplies more so than the unit. From Garfield's work on OTR, I know that it is possible to change the production of a city each turn (or probably each "other trigger") to 0 shields, or likely to reset its food supplies, etc.

If a designer were so inclined, rather than requiring the game to check for every possible route, could a route be predefined? Imagine a straight (or curved) line of coordinates in a table that a designer goes through the trouble of writing into a large table. If any such tile has an enemy unit on it, the city it supplies is effectively cut off.

Perhaps I would then draw several lines across the map that feed into Britain - if these are cut, then perhaps one city goes dark per line, or perhaps each city has a reduced production by some percentage depending on how many lines are cut.

I'm especially interested in this because Hinge of Fate will have multiple maps. The east coast of North America will be one map and Europe will be another. I imagine that a system like this would work across multiple maps, because it would simply be a matter of the game checking different coordinates on different maps in a table - I suspect that wouldn't cause major issues.

I think that this would be very useful for my scenario as well as @Prof. Garfield 's planned Imperialism remake. This would cut down on micromanagement in that a player wouldn't need to scour the entire ocean looking for supply ships to sink, or U-Boats to defend against. They'd have a set line to patrol, which I imagine would be fairly true to real life anyway (most sea lanes are well known and utilized). Importantly, I can get the AI to defend these sea lanes with unit creation and moveunit commands.

I know there is the issue with onActivate for the units but if the goal is to simply starve the cities by cutting them off (so they can't produce anything else and perhaps actually start starving) would this system work for a naval supply mechanism?
 
Hi Kighttime,

Thank you for the feedback. For now, I’m simply trying to understand what the feature is capable of doing and what are its potentials and limitations, so I’m not ready to request any enhancements or changes.

One of the future projects I’m envisioning working on is my companion to my Battle of France scenario, which is the Battle of Italy (from Sicily to the end of the war). I can definitely see supply playing an important role in that design.

Yes, it could certainly be a unit. Really it can be any object or attribute that is associated with a specific location on the map. The isValidSupplyDepot() function takes a tile and a tribe as parameters, and needs to contain logic to answer the question, "Can this tile serve as a supply depot for this tribe?" I could add another commented-out example in that function, showing how to test that location for the presence of a particular unit type.

In my vision, one of the advantages of using HQ or Supply type units, would be to limit the supply range, in order to represent the danger of armies running too far ahead of their supply sources.

However, remember that due to an apparent bug, if a unit is activated directly from the city screen, the onActivateUnit() trigger doesn't fire. If all cities are supply depots, and your suppliedUnitEffects() function is written to assume that units are supplied by default and to apply a penalty if they are not, this isn't really an issue. But if some/all cities are not supply depots, you could run into a situation where a unit activated in such a city wouldn't search for a supply line. So... just something to keep in mind as the designer, and weigh pros and cons.

Understood.

How would you envision that the game would identify which units are supplied by that source, if the number of possibilities exceeded that limit? Simply order of unit activation on a given turn? That seems a little arbitrary and could force the player back into micromanagement, by very carefully activating units manually in a particular order. From a code perspective, this would require the use of the state table to track history, so it would add quite a bit of complexity. I'm not sure I see a clear path forward for this one yet.

Understood. This allows me to understand the potential pitfalls to avoid.

Correct, it's the latter at this point: a unit which begins its turn "out of supply" does not necessarily have that status for its entire turn. A change in status could be achieved by moving the unit (so that it's in range of a supply depot) or by killing an enemy unit that was blocking a depot (thereby opening up a valid supply line) or even by adding/moving a supply depot (building a new city, moving a supply "storehouse" unit, building a new tile improvement such as an airbase, etc.).

Though I prefer the former, I think the fact that one of the effects you could apply is to reduce the MP of an unsupplied unit to zero, would resolve my personal dilemma. In this manner, the isolated unit would require a friendly unit to come to its aid to redress its supply situations and if you added attrition to the mix would make things even more interesting.

Absolutely, all of those are possible. The example provided in events.lua was recommended by @JPetroski to illustrate the power of this feature, but it's just one example and not intended to limit you from introducing new or different effects.

That sound great!

This is definitely something I considered, but based on John's feedback it didn't seem like a critical feature, at least for version 1.0. This would add some complexity to the code, but my biggest concern is performance: this would mean that every tile the code analyzes, to see if it's a valid supply link, would require it to find up to 7 other tiles, and look for enemy units on them. That could be a pretty severe hit and might mean that there would need to be a much lower cap on the maximum supply line length, to avoid a noticeable lag each time a unit is activated. I haven't tried to write or test this yet, though, so it's all speculation at this point.

As long as the conditions are clear, I think most designers could live with the simpler solution.

Yes, a similar kind of feature would be possible, but it seems to me that you might want different rules for valid supply lines, or depots, than you would use for land units. So this might necessitate adding additional constants at the top of the file, splitting isValidSupplyDepot() into separate isValidLandUnitSupplyDepot() and isValidNavalUnitSupplyDepot() functions, possibly doing the same to isValidSupplyLink(), and then adjusting the core logic in hasSupplyLine() to branch based upon unit domain.

I don’t see any harm in giving designers the extra flexibility.

This actually wouldn't require a supplyLines module at all, since the primary purpose of it is pathfinding -- detecting an open route between a unit and a depot located elsewhere. If all you want is to detect the presence of a supply unit on the same tile, for either land or naval units, this could be done directly within the onActivateUnit() section of your events.lua.

In this instance, I was thinking of my next version of my Total War scenario whereby naval task forces would be required to move around with tanker/supply ships to be able to move effectively at sea. If this can be accomplished with the onActivateUnit() function, all the better.


I'm nowhere near selecting my next major project (though its not the options that are missing) but it's good to know some of the new lua features that will be there when I'm ready to move forward.

Short term, I'm hoping to complete the changes to version 1.1 of Napoléon once I've received feedback from the players. After that, I would probably like to finalize my Battle of Alesia scenario. Since it is relatively short and simple in concept, it would be an ideal candidate for me to try to write the core of the lua for it (though I'm certain I would probably need help along the way).
 
Well my mind is blown! This is a hell of a development. The Train Militaire/Attrition in Napoleon worked perfectly for the particular historical situation in that scenario. Having to build them & then ensure they are in the right place at the right time. This will just add another dimension, especially in modern scenarios where foraging is not really a viable option for mechanized armies.

I'm so impressed. Thanks for all the effort you're putting in here Knighttime!
 
I'm trying to envision how to use this for naval supply routes, specifically convoy routes going to Britain (or any other island in any scenario). In this case, it would be preferable for the city to be reliant on supplies more so than the unit.
So, just to avoid any confusion, I think the term "naval supply" is best used to refer to supplies reaching naval units. What you're describing is a concept I would refer to as "city supply" -- with specific supply line criteria that (only? primarily?) involve the use of ocean tiles.

From Garfield's work on OTR, I know that it is possible to change the production of a city each turn (or probably each "other trigger") to 0 shields, or likely to reset its food supplies, etc.
Yes, it's possible to set the number of food stored in the food box, and/or the number of shields stored in the shield box. It is not possible, at present, to change what the city is building. It's also not possible to directly set the quantity of food or shields generated each turn, since that's derived from the tiles worked and then adjusted by city improvements and wonders.

If a designer were so inclined, rather than requiring the game to check for every possible route, could a route be predefined? Imagine a straight (or curved) line of coordinates in a table that a designer goes through the trouble of writing into a large table. If any such tile has an enemy unit on it, the city it supplies is effectively cut off.
Well... as I mentioned above, the key breakthrough with this module is pathfinding -- that is, finding a valid route through any portion of the map based on a set of criteria that need to be continually re-evaluated because they could change based on player actions. If you have a set of predefined coordinates in a table, and you want to know whether any of them are blocked by an enemy unit, I'd do that by looping through the table, not by using this supplyLines module:
Code:
local supplyLineOpen = true
for _, supplyTile in pairs(supplyLineTable) do
   for unit in supplyTile.units do
       if unit.tribe ~= thisTribe then
           supplyLineOpen = false
           break
       end
   end
   if supplyLineOpen == false then
       break
   end
end
Using the supplyLines module could potentially work, but it feels a little like using pliers to pound in a nail. :)

Perhaps I would then draw several lines across the map that feed into Britain - if these are cut, then perhaps one city goes dark per line, or perhaps each city has a reduced production by some percentage depending on how many lines are cut.
So depending on how these lines are laid out, whether or not they crisscross, and whether there are multiple branching paths through them, it might mean that the supplyLines module is more appropriate after all. If an enemy unit blocking a tile on a predefined supply line automatically invalidates that supply line, you probably don't need the module; but if that situation means that supplies could potentially reroute along a different path to still reach the destination successfully, that seems more like a situation where the module may come in handy.

I'm especially interested in this because Hinge of Fate will have multiple maps. The east coast of North America will be one map and Europe will be another. I imagine that a system like this would work across multiple maps, because it would simply be a matter of the game checking different coordinates on different maps in a table - I suspect that wouldn't cause major issues.
Actually, the core logic of the module relies very heavily on the concept of adjacent tiles on a single map. I think supply lines that stretch across different maps (especially where the "connection" has a different X,Y coordinate, not just a different Z coordinate) would mean that you could not use this supplyLines module -- at least, not without a substantial rewrite (version 2.0 at least).

I think that this would be very useful for my scenario as well as @Prof. Garfield 's planned Imperialism remake. This would cut down on micromanagement in that a player wouldn't need to scour the entire ocean looking for supply ships to sink, or U-Boats to defend against. They'd have a set line to patrol, which I imagine would be fairly true to real life anyway (most sea lanes are well known and utilized). Importantly, I can get the AI to defend these sea lanes with unit creation and moveunit commands.
I can see why this concept of sea lanes for supplying cities might be well-suited to some scenarios, but to be quite honest it seems different enough from the way supply lines are conceptualized for units in this module, that I think you would be better off building a different solution from scratch. Perhaps I should start work on a "seaLanes.lua" module? ;)

I know there is the issue with onActivate for the units but if the goal is to simply starve the cities by cutting them off (so they can't produce anything else and perhaps actually start starving) would this system work for a naval supply mechanism?
I think land unit supply and naval unit supply are best triggered by onActivateUnit(), but city supply (which is what you're discussing) would probably belong in the onTurn() trigger. In summary, I think your vision is definitely possible, it's just pretty different from what this was written to do.

In my vision, one of the advantages of using HQ or Supply type units, would be to limit the supply range, in order to represent the danger of armies running too far ahead of their supply sources.
That makes sense. I think this supplyLines module would work well in connection with supply units as long as you want supply units to benefit other units within the surrounding area. If a supply unit should only provide supplies to units on its own tile, you don't need this module.

In this instance, I was thinking of my next version of my Total War scenario whereby naval task forces would be required to move around with tanker/supply ships to be able to move effectively at sea. If this can be accomplished with the onActivateUnit() function, all the better.
Yep -- again, the distinction is whether supply units have a supply radius reaching to multiple tiles, or if they only affect the single tile on which they're located.

Well my mind is blown! This is a hell of a development.
...
I'm so impressed. Thanks for all the effort you're putting in here Knighttime!
Thank you sir! :D It's great to hear that this seems like a useful feature.
 
Last edited:
"I'm trying to think of a way to implement encirclement and supply lines in a [...] scenario." [#171]
The issue was meanwhile raised a couple of times, e.g. by JPetroski, or Manuel Re [#206] -- and I feel with this supplyLines module we got the tool in order to tackle it in a very smart (i.e. for the player easy to handle) way. Nonetheless, I have the greatest respect for the conceptual and programming work in order to make the vision come true. Therefore: Thanks @Knighttime! I think you are also the right person to address my questions to. If considering encirclement and supply lines within the context of a turn based game we are basically facing two situations.

[First, encircled by an enemy] At the beginning of my turn I see my unit(s) have been cut off from a valid route -- calculated on a set of criteria, e.g. if only tiles with road improvement count and one is blocked by an enemy unit. At this stage, a penalty may already have been applied (reduced movement, increased damage) and with the help of the pathfinding I will now be able to detect an open route (or track the tile which is blocking) between my unit and a supply depot (city, unit, whatsoever). I guess that part / concept already works well and could basically be enhanced by some kind of logic, e.g. unit’s ZOC, add further criteria to “isValidLandUnitSupplyDepot()” etc., so far so good.

Moreover, if accepting a delaying effect (of at least one turn) between trigger (an enemy is blocking my valid supply route) and action (reduce the attack factor of my unit(s) to zero, reduce its movement factor, or apply attrition etc.) this module enables the scenario designer to appropriately represent encirclement.

But if one aims to go even a step further, i.e. apply trigger & action at the same time, would that be possible with Lua? Here is what I am envisioning:

[Second, encircle the enemy] I cut off the enemy’s valid supply route and during the same turn a penalty (for example an increased damage) is immediately applied to the enemy’s cut off unit(s) = the trapped force. In my view this is not only how the reality is at least for really big encircled armies (they recognize the shortage of food, ammunition, or fuel yet by a few days), but also would bring a highly dynamical element into the game. But I have no idea how to translate this into code, or if this is even possible at all. As John rightly asked “How does an attacking army somehow "know" that it has encircled an enemy army?” As you, Knighttime, mentioned “If you have a set of predefined coordinates in a table, and you want to know whether any of them are blocked by an enemy unit, I'd do that by looping through the table” But as you can see in this case there are no predefined coordinates in a table. The module has rather to ask the question the other way round: If my unit ‘onActivateUnit()’ cuts off a ‘isValidSupplyLink’, which supplied enemy unit(s) is (are) affected (return the unit IDs) and then apply immediately a penalty if there is no other ‘isValidSupplyLink’ to the cut off unit(s).

While thinking about this I got the idea that it will be almost impossible to implement -- taking a reasonable coding effort as a precondition -- and as said, the tool is already a very good starting point. Just curious how far / close we can possibly get to reality with Lua in Civ 2.

Having said this and regardless of the feasibility, could I ask for your help in adjusting your module to my scenario needs? :)
 
Last edited:
Hi @SorFox, thanks for writing, and I appreciate your feedback!

If considering encirclement and supply lines within the context of a turn based game we are basically facing two situations.

[First, encircled by an enemy] At the beginning of my turn I see my unit(s) have been cut off from a valid route...
You're correct that this is essentially what version 1.0 of the supplyLines module was written to do. Just a couple comments -- both of which may be clear to you already, it's just a little hard to tell from what you wrote:
  • The implementation is intended to apply equally to AI tribes/units as well as those belonging to the human player -- either can do the encircling, or suffer the effects of being encircled. Unfortunately, the the AI won't really understand what's happening and move strategically to create a good situation or fix a bad one. If that imbalance is a concern, it wouldn't be difficult to limit this to only penalizing the human player, but that takes away all your incentive (as the human player) to encircle your opponent -- and the AI would only ever encircle you accidentally, since it can't intentionally work towards that goal.
  • You said "a delaying effect (of at least one turn)" but realize that the effect could happen on the same game turn (that is, on the same game year or month/year) if the encircled player gets to move after the encircling player. But you're correct that if you manage to encircle the enemy, this provides no advantage to you while you're still playing that same turn -- the advantage kicks in the next time that enemy has the opportunity to move their units, which could be later that same game turn or early (before you) on the following game turn.

But if one aims to go even a step further, i.e. apply trigger & action at the same time, would that be possible with Lua? Here is what I am envisioning:

[Second, encircle the enemy] I cut off the enemy’s valid supply route and during the same turn a penalty (for example an increased damage) is immediately applied to the enemy’s cut off unit(s) = the trapped force...
Taking a step back: in considering possible negative effects of being encircled, it's important to distinguish between stats that can be modified at the unit level, vs. those which are only stored by Civ at the unit type level. For example, in considering offensive impacts, you can reduce movement points for each unit individually; but changing attack strength must be done for the unit type, which instantly affects all units of that type. This can still work, though, if attack strength is reset to the base value for every type upon every subsequent unit activation -- essentially reverting the change before it can affect more than the single unit that we intended. (Side note: this is how leader attack bonuses work in Napoléon, although in that scenario we're increasing attack strength rather than decreasing it.)

Similarly, in considering defensive impacts, you can reduce hit points for each unit individually; but reducing defense strength must be done for the unit type, which would instantly affect all units of that type. UNFORTUNATELY, unlike the similar offensive impact, we won't (necessarily) have an opportunity to revert this before it impacts a specific unit we did not intend! (You could theoretically encircle one enemy Rifleman but then attack a different one which was not encircled.) So it really seems to me like defensive impacts need to be limited to ones which can be applied directly to individual units. Your example of "increased damage" can work, as long as you mean "reduced hit points" rather than "increased likelihood to take damage".

If my unit ‘onActivateUnit()’ cuts off a ‘isValidSupplyLink’, which supplied enemy unit(s) is (are) affected (return the unit IDs) and then apply immediately a penalty if there is no other ‘isValidSupplyLink’ to the cut off unit(s).
Translated into code, this would mean: Every time I activate one of my units, run the supplyLines module for every enemy unit that could possibly be affected, and if it does not have a valid supply line, reduce its HP. Furthermore, to avoid applying this encirclement penalty over and over again to the same units, document in the "state" table which enemy units have already suffered the encirclement penalty this turn, and don't apply the penalty to any given unit more than once.

This is technically possible, but it probably isn't going to scale well. If MAX_SUPPLY_LINE_LENGTH is small, and/or if the enemy has a relatively small number of units, Lua may be able to handle all of the necessary calculations quickly enough that the human player doesn't really notice the delay. But as either of these numbers grows, it seems more and more likely that the game will momentarily pause while the event runs -- and this would happen every single time you activate a unit, which would basically render the game unplayable (or at least, not enjoyable).

Furthermore, if the event works the same way on the AI tribe's turn, their turn could take much longer than normal, and again it may look like the game has frozen while calculations take place. (The AI tends to activate units more frequently than the human player, which magnifies the issue.)

While thinking about this I got the idea that it will be almost impossible to implement -- taking a reasonable coding effort as a precondition -- and as said, the tool is already a very good starting point. Just curious how far / close we can possibly get to reality with Lua in Civ 2.
There might be another option, although the effect would be more limited. What if we didn't run this check whenever you activated one of your units, or on every other enemy unit, but instead ran it at the time you attacked an enemy unit, and ran it only on the one unit that was attacked? This would mean putting the call to the supplyLines module within civ.scen.onResolveCombat(), and then immediately reducing the defensive unit's HP by an additional amount (if it's unsupplied) alongside the first round of the battle. I haven't tested this approach, but it seems like it might be possible. This falls short of your stated goal in two ways, though: the penalty isn't applied immediately (at the time the encirclement happens), and it also doesn't affect an enemy unit at all unless it's attacked. You wouldn't even be able to confirm whether or not enemy units were encircled prior to an attack. But it would provide an advantage to you during your current turn, rather than deferring this to the enemy's next turn.

Having said this and regardless of the feasibility, could I ask for your help in adjusting your module to my scenario needs? :)
I'd be glad to help. Have you made any attempts on your own to implement this module? Feel free to send me a private message if you'd prefer to go back and forth about the details without using this public forum. (I expect we'll need to exchange scenario and Lua files back and forth, and it's perfectly understandable if you don't want to post your project work publicly until it's finished.)

It would be great to see a scenario released that makes use of this module, and I look forward to learning more about your project.
 
Thanks for your encouraging answer, Knighttime!

The implementation is intended to apply equally to AI [...] as those belonging to the human player. If that imbalance is a concern, it wouldn't be difficult to limit this to only penalizing the human player
I am absolutely with you, not to take away the incentive trying to encircle the AI as a human player. It is fine just as it is implemented.

So it really seems to me like defensive impacts need to be limited to ones which can be applied directly to individual units. Your example of "increased damage" can work, as long as you mean "reduced hit points" rather than "increased likelihood to take damage".
Yes again, I am aware of the different implications if talking either of unit, or unit type level -- and I was only talking about the “hit points” not the “defence factor” of a unit.
Btw: It's a pretty smart solution you find in Napoléon in order to handle the issue by reverting back the change of the leader attack bonuses.

This is technically possible, but it probably isn't going to scale well [...] render the game unplayable (or at least, not enjoyable).
Good point. I expected it, but as you described the steps what calculations will be done when, it’s even more obvious that’s not going to be the right approach.

There might be another option, [...] instead ran it at the time you attacked an enemy unit, and ran it only on the one unit that was attacked?
That sounds like a great idea -- furthermore, I don’t see it as a big shortfall! If I understand that correctly, therewith the desired immediate advantage (bonus for the force able to create encirclement) could be enacted for the case which matters the most, in the combat situation. Also the general penalty for the trapped force will still be applied, only with a time delay as discussed above, i.e. if the encircled player gets to move after the encircling player.

You wouldn't even be able to confirm whether or not enemy units were encircled prior to an attack.
Indeed, this points to a big issue. I think it would enhance playability if one could get something like a visual confirmation for a successful encirclement. I mean, on the other hand basically you will have already a good idea -- as a player -- what to do in order to encircle an enemy force. Assuming you know about the triggers and have a rough overview of the battle field situation, I can live with no hint of encirclement prior to an attack. But for example you still can oversee a little road which keeps counting as ‘isValidSupplyLink’ to the enemy, so a visual confirmation while attacking would be helpful. I am thinking of something like a red frame for the tile where the unit is attacked, something you already implemented for the module for “Units.bmp”. Maybe by adding a code line before reducing the defensive unit's HP -- alongside the first round of civ.scen.onResolveCombat(), but by using the pollution slot of “Terrain1.bmp”, or even better the “Goody Huts” slot? But you will know better...

I expect we'll need to exchange scenario and Lua files back and forth, and it's perfectly understandable if you don't want to post your project work publicly until it's finished.
Precisely! ;)

I'd be glad to help. [...] feel free to send me a private message [...] I look forward to learning more about your project.
Thanks mate, I am really happy to hear and will send you details, which would only crowd this thread, and files by PM.
 
Last edited:
I'm revisiting this thread a bit... Just curious if it would be possible to demand a link between three points:

Unit, city 1 and city 2?

I'd like to use cities as the supply link but also want cities (like Leningrad and Stalingrad) to be besieged by an encirclement, which isn't going to work very well with a single dependency. If, on the other hand, a unit must be able to trace a path to "x" cities, then one could account for a siege.

Sorry if this was already explained as possible-- I read this thread with a few rugrats giggling and could easily have been distracted :)
 
Last edited:
I'm revisiting this thread a bit... Just curious if it would be possible to demand a link between three points:

Unit, city 1 and city 2?

I'd like to use cities as the supply link but also want cities (like Leningrad and Stalingrad) to be besieged by an encirclement, which isn't going to work very well with a single dependency. If, on the other hand, a unit must be able to trace a path to "x" cities, then one could account for a siege.
I was working on a version 2.0 of this module awhile back, but never quite finalized it or released it -- kind of fell off my radar, actually. I should probably come back to that if there's interest in the module.

Here's how I envisioned tackling the situation you described. Instead of requiring that a unit be supplied by more than one depot, my idea was to do the calculation of "Build the set of valid supply depots" as Stage 1, and then the calculation of "Can the unit reach a depot in that set" as Stage 2. In your example, Stage 1 would require that Leningrad itself have a connection to a different city in order to serve as a depot. If it's encircled and this isn't true, then all of the units within that encirclement would fail the check in Stage 2 and therefore be unsupplied.

The version 2.0 that I was building is really very flexible, but what I was finding is that (surprise, surprise) with the flexibility came substantially more complexity. It's hard to know where to draw the line so that it's feature-rich, without the complexity itself becoming a barrier to adoption.

Let me know if you have further questions or comments! Hopefully I can find time to resume work on this and release the new version soon.
 
The version 2.0 that I was building is really very flexible, but what I was finding is that (surprise, surprise) with the flexibility came substantially more complexity. It's hard to know where to draw the line so that it's feature-rich, without the complexity itself becoming a barrier to adoption.

The 'how many features?' question is a difficult one. My suggestion is to provide some basic features in an easy to use way, and also let the user provide their own functions if they want. For example, in my munitions library, I have a number of possible requirements for making a munition, but I also let the designer supply their own function (if they want) that returns false if the unit can't generate the munition and true if it can (provided the other conditions are also met).
 
Back
Top Bottom