[TOTPP] Prof. Garfield's Lua Code Thread

Prof. Garfield

Deity
Supporter
Joined
Mar 6, 2004
Messages
4,366
Location
Ontario
For my current method of code distribution, see this thread instead.

I've decided to change the way I 'distribute' the Lua code I've been working on. Until now, I've started a thread for each 'type' of module/library that I've made, with the intention of posting updates to each thread when necessary. The trouble is that I never really did this, even for the General Library, which would get extra code whenever I wrote something and thought that it was likely to be useful in other contexts. I also had issues synchronizing multiple copies of 'foundational' modules.

My new strategy is to upload to Github a couple folders from a Test of Time installation that I plan to use for code creation. The lua folder will contain modules that (if working properly) shouldn't need to be changed by the scenario designer (and are likely to be shared between projects). The files in the folders of LuaTestScenario would have to be changed by the scenario designer for the specific needs of the scenario.

This is the repository.

This will make things easier for me, and will make it easier for others to get the latest version of the code I've produced. If you want to double check that the code is recent, simply bump this thread and ask me to sync the code. The process should be quick and easy for me.

The downside is that you might find stuff that is incomplete or just experimenting and testing. Feel free to ask if you're not sure.

I'll use this as my main "Lua Library" support thread (stuff to do with the lessons should be asked in that thread), though I may move an extensive conversation to a dedicated thread. This includes bug reporting/fixing and questions about how to use the modules. You can also ask that I prioritize work if you are likely to have a use for it in the short to medium term.
 
Last edited:
Very useful, Proffessor. Thanks. I've been playing a little with LUA before coming back to the forum, and I love it. I am a programmer by trade (C,C++, python mainly) with a focus on realtime over Linux - so LUA is not part of my usual trade, I find the scripting very intuitive. A humble suggestion would be to have a list of "features" or "to do", so maybe some of us can contribute patches to your repo for you to review/accept :) I mean - if you have a list, and someone is bored, they can always go and implement the feature :)
 
Very useful, Proffessor. Thanks. I've been playing a little with LUA before coming back to the forum, and I love it. I am a programmer by trade (C,C++, python mainly) with a focus on realtime over Linux - so LUA is not part of my usual trade, I find the scripting very intuitive. A humble suggestion would be to have a list of "features" or "to do", so maybe some of us can contribute patches to your repo for you to review/accept :) I mean - if you have a list, and someone is bored, they can always go and implement the feature

Some help would be welcome. There's a huge list of functions in the General Library module that have to be implemented, but most are not really all that difficult, and I sort of left them as 'low hanging fruit' for someone learning (or, to be filled in as needed). Something a little more challenging would be to figure out and document all the unit/city attribute flags, and code functions to access them.

If you're looking for something to do now, how about a diplomacy module, for stuff like transferring units, making payments to others, etc. I could use it for A Soaring Spirit. JPetroski described the idea in another thread:

Now with that being said, if you do undertake to build a MP game, could I convince you to implement an in-game peer to peer diplomacy module that renders using cheat mode for treaties and transfers obsolete?

I would think you'd want bilateral and unilateral options. Bilateral would require offer and acceptance, unilateral would only require a player to decide to do it.

City transfer, unit transfer, tech transfer, money transfer, all from a menu system rather than cheat mode...

To enable SP games, unilateral might come with consequences (you buy a unit rather than one is gifted). In MP, perhaps players stack units on certain terrain that is a "mercenary field" and others can press a button, see a menu with the options and price, and have it transfer.

I'd love to make use of this for a Cold War scenario that is becoming my "pandemic build" at the moment and I think eliminating cheat mode in MP games (which is clunky at best) would be great.

There's a started module in the repo, but I only started it since I needed a couple 'diplomacy checks' in another module, and I figured a diplomacy module would be made at some point anyway. If you're interested, it could essentially be your project. Check out text.lua for some pre-made menu functions.

I think @techumseh was looking for a lead programmer for a Bismark scenario. That might be another option, though it would be a bigger commitment.
 
I actually did the diplomacy utility, civ2dip (top entry here: https://www.civfanatics.com/civ2/downloads/utility/), so doing the diplomacy thing may be a throwback to the past. In the utility I did, what I end up doing was to patch the save games themselves, as I reserved the same game format.

I will try to look into that, or if tech has a shopping list for Bismarck, I can look into that....
 
Well, if you're considering help with the diplomacy module, I figure I'd better state what I intend to use it for in the Cold War 1947 - 1991.

* I'm basically trying to create a few situations via a menu.

1. Have a system where the Soviet and American (or perhaps others) players can initiate proxy wars to cause trouble for each other and the European colonies. The way I was figuring this would be done would be to have each control a second civ (Pro-East and Pro-West) and on pressing a key (such as backspace), calling up a menu which states, "Where should we fund rebels/freedom fighters?" This would look to a table, where I'd be able to define things like "Angola" or "Egypt" or "Cuba". Each option would cost money, the amount also defined in the table. If the Soviets picked "Cuba" then certain Pro-East units would show up on tiles in Cuba and money would be deducted from the player's treasury. There'd be no need for the Soviet player to have the units to transfer - there are "local" units that would pop up.

This would enable civs to cause trouble for each other without directly going to war. In a MP game, the Soviets would probably also control the Pro-East and the Americans Pro-West, but in a SP game, you'd simply be funding the AI. I found that First Strike's proxy war system was clunky and reliant on house rules, so proxy wars didn't usually happen. Also, it was difficult for some civs to project power and get proxy wars raging. With this system, you simply have the Pro-East and Pro-West constantly at war with each other and proxy wars would be much more fluid. This also would transfer fine to single player games.

2. Basically create an arms industry. In my scenario, I have a unit called an "Arms dealer" (that can hold air units like a carrier, which is why I am using a unit for this). I plan on having a few tiles in Russia with such units, one labelled "Sell to China," another "Sell to India," a third being "Sell to Pro-East." The player would place any units on these tiles that they want to make available for sale, and the next player would press a key to bring up a menu that shows the units and their price (which I'd define in a table). This is a bilateral exchange.

Anyway, that was my thought for #2, trying to keep things simple. I'm sure the two of you could come up with more elegant solutions. It might be possible/better (though probably more work) to have a system where Player A cycles through a menu to "offer" something to player B, which then "stores" via a state, and then after production, Player B gets a prompt where they choose to "accept" the offer or deny it.

If I'm making sense?
 
I can give it a try. Can you send me the scenario files so I can see it working on the real thing? I'd say that I'll start with (1) and let you know how it goes.
 
Unfortunately the scenario is a WIP at this point - you might try taking First Strike to see if you can get it running?
 
The files for A Soaring Spirit are now in my repository. All I'm looking for there is some basic ability to make peace/alliance, give away money, or units and cities at the location of the cursor. Stuff that you might want to do in any multi-player scenario, and which usually requires cheat mode to accomplish. Some customization might be nice, such as only being able to give techs that the recipient has the prerequisites for, maybe only certain types of units can be given away, perhaps cities (or certain cities) can't be given away. Giving away would be easier to implement than trades, and all you need is a house rule that agreements that can be fulfilled immediately must actually be fulfilled. That would be good enough for a lot of use cases.
 
Just a note: I'm working on JPetroski scenario, but as soon as possible I'll start the diplo thing.
 
I think I did already what JP asked for me, I'll start this diplomacy thing in the background.
 
Moved this here, since it doesn't have much to do with the Cold War scenario.

I do not think there is a better approach. Yes, shift and ctrl will be added like that, but I was thinking also of doing

withCtrl(x) return x + key.ctrl_offset
withShift(x) return x + key.shift_offset

So someone can write

if(key == withCtrl(keyboard.x))

That may be a more intuitive.

That makes sense. The other thing I can think of that would make sense would be to programmatically produce some nested tables (or, possibly use metatables), so that someone could write, say,

keyboard.ctrl.b

and get the desired result.
 
Moved this here, since it doesn't have much to do with the Cold War scenario.



That makes sense. The other thing I can think of that would make sense would be to programmatically produce some nested tables (or, possibly use metatables), so that someone could write, say,

keyboard.ctrl.b

and get the desired result.

Grrr, of course, that makes a lot of sense. How stupid is my suggestion in comparison :) I've sent you a pull request in github with the keyboard.ctrl, keyboard.shift, keyboard.ctrl.shift and keyboard.shift.ctrl tables, generated programmatically. I've tested it a bit and it seems to work.
 
Grrr, of course, that makes a lot of sense. How stupid is my suggestion in comparison :) I've sent you a pull request in github with the keyboard.ctrl, keyboard.shift, keyboard.ctrl.shift and keyboard.shift.ctrl tables, generated programmatically. I've tested it a bit and it seems to work.

Thanks. I'll figure out how to do the pull in Github tomorrow (I have to work in a couple hours, and this Civ stuff is all I've ever done with Git and Github, since I've found sharing code on the forums to be cumbersome at best).

Don't feel bad. I have some very stupid ideas immortalized in Over the Reich. The way that a 0-1 'dice roll' is converted to 'damage' is not intuitive and a bit more thought on my part would have saved JPetroski a lot of confusion and a decent amount of work.
 
So, I have done the diplomacy thing you requested. Can you please kindly review if you like the look of it?

1-withUnits.jpg


You can give out money, technology, units (at the position of the cursor) and the city over the cursor. After selecting what to give out, you are presented with a dialog to select the civilization

3-toWhom.jpg


For money, you select the amount (you can configure a list of amounts, and only those smaller or equal than the treasury)

4-money.jpg


For technology, you can select which technology to give out
6-tech.jpg


You can give also units, here we give out a bunch of units outside Heraclea

8-units.jpg


9-units.jpg


You can also give out a city, as long as it has not a palace. Here we give out Neapolis
11-city.jpg


12-city.jpg
 

Attachments

  • 2-withCity.jpg
    2-withCity.jpg
    834.3 KB · Views: 245
I'm sending you a pull request in github to check if you like the new ideas. This is the list of configuration options for the dialog - it can be expanded with more if needed

-- * main_dialog_text -> Text to display in main dialog text
-- * civ_selection_text -> Text to display when selecting destination civ
-- * gift_money_text -> Text to display in main dialog text
-- * gift_money_confiramtion -> Text to display when money is gifted
-- * gift_money_amounts -> A table with the available amounts and the text associated to them
-- * same_civ_player -> Text when a player attemps to gift something to his/herself.
-- * gift_units_text -> Text to be shown to ask for confirmation
-- * gift_units_confirmation -> Dialog to show after confirmation
-- * gift_units_locations -> A list of locations to put the gift. It will start with the first one,
-- and use all of them until one is valid
-- * gitft_units_error -> A error message to be displayed in case no suitable location is found
-- (only happens when gift_units_location is provided)
-- * gift_city_text -> Text to be shown to ask for confirmation
-- * gift_city_confirmation -> Dialog to show after confirmation
-- * gift_city_destroy units -> Whether all units needs to be destroyed after the city is given out

Also, in all strings to be displayed you can use the following keywords and they will be replaced

-- * $receiver -> Tribe name of who is receiving the gift
-- * $money -> The amount of money given out
-- * $tile -> Tile where it happens
-- * $city -> Name of the city
 

Attachments

  • upload_2020-4-17_1-49-50.png
    upload_2020-4-17_1-49-50.png
    2.5 MB · Views: 253
Pull request sent your way! Please remember that this is for review. You can reject it if you see something you do not like :)
 
Do the units just change ownership but stay in the same spot? If so, how about a way to transfer between two points that share a common feature (for example: terrain type or certain improvement like a port)?

Great work here btw--this will be awesome to use in MP games.
 
Do the units just change ownership but stay in the same spot? If so, how about a way to transfer between two points that share a common feature (for example: terrain type or certain improvement like a port)?

Great work here btw--this will be awesome to use in MP games.

It's configurable. If you do not configure anything, all units gifted are keep in place. Otherwise, you can define, per receiving civ, a list of locations to receive the units, and the units will be sent to the first valid location (which may be different for different units in the same location)

Specifically, the configuration param is

-- * gift_units_locations -> A list of locations to put the gift. It will start with the first one,

Another thing is that the units keep their home city, still in the gifting civ. We may want to make this configurable, too.

This for me is a first version. I am happy to do as many changes as needed.

Thanks a ton for your kind words!
 
This is looking very good. Thank you very much.

I've accepted the pull request. Since nothing is actually using this code at the moment, any improvements/fixes can simply be merged in later. I'd rather have my code up to date.

It might be a couple days before I can take a close look at the code. Here are my thoughts based on what you've posted:

1. It would probably be useful to display a list of the units that will be given away (at least the first 3 or 4), to reduce the likelihood that the player gives away the wrong tile of units by accident.

2. For giving money away, it would be helpful if the player could choose the total via a set of menus, then confirm the gift. I'm thinking some code using tail recursion would be easiest. Something like (not proper code)

Code:
chooseNumber(numberSoFar)
numberSoFar = numberSoFar or 0
-- menu to add/subtract/multiply existing amount
 if add 100
return chooseNumber(numberSoFar+100)
if subtract 10 then
return chooseNumber(numberSoFar-10)
if multiply by 10 then
return chooseNumber(10*numberSoFar)
if correct amount then
return numberSoFar

If this isn't clear, I'll do it myself in a few days.

3. It would be very helpful to be able to specify the settings for the module in a separate file, and use a function to provide the table to the diplomacy module. I have an example of that with the canBuild module. This isn't so crucial for the end user, but it means I only need to have the 'core' module in one place, rather than synchronizing modules in every test scenario that I have (this has already been an issue for me, since I made the same mistake for the legacy event engine).

4. This is some minor consistency stuff between code. Don't bother changing if it is a lot of work.
4a. Consider %MONEY instead of $money. Reason: %STRING0, %STRING1, etc is used in the game's text files, and I followed that convention for text.substitute.
4b. TNO used the convention of camelCase, which I think everyone's been following, rather than underscores. Not really a huge issue, but it might spare some confusion.
 
This is looking very good. Thank you very much.

I've accepted the pull request. Since nothing is actually using this code at the moment, any improvements/fixes can simply be merged in later. I'd rather have my code up to date.

It might be a couple days before I can take a close look at the code. Here are my thoughts based on what you've posted:

I'll do the changes you comment. Do you prefer to continue with pull requests or would it be better if I get read/write permissions to your repo? That way I can do things directly there.

1. It would probably be useful to display a list of the units that will be given away (at least the first 3 or 4), to reduce the likelihood that the player gives away the wrong tile of units by accident.

I will do something like that. Understood

2. For giving money away, it would be helpful if the player could choose the total via a set of menus, then confirm the gift. I'm thinking some code using tail recursion would be easiest. Something like (not proper code)

Code:
chooseNumber(numberSoFar)
numberSoFar = numberSoFar or 0
-- menu to add/subtract/multiply existing amount
 if add 100
return chooseNumber(numberSoFar+100)
if subtract 10 then
return chooseNumber(numberSoFar-10)
if multiply by 10 then
return chooseNumber(10*numberSoFar)
if correct amount then
return numberSoFar

If this isn't clear, I'll do it myself in a few days.

I'll fix that too

3. It would be very helpful to be able to specify the settings for the module in a separate file, and use a function to provide the table to the diplomacy module. I have an example of that with the canBuild module. This isn't so crucial for the end user, but it means I only need to have the 'core' module in one place, rather than synchronizing modules in every test scenario that I have (this has already been an issue for me, since I made the same mistake for the legacy event engine).

I can do that, for sure, no problem. One question, though, why don't you use symbolic links? I use that to ensure that I edit the same copy all the time. They are supported in windows since Vista (for NFTS partitions). You should have them as you use WINE, isn't it?

(My personal setup is Windows, for working reasons, but I do all this in Linux with emacs under the lovely WLS - Windows Linux Subsytem, that allow you to run Ubuntu inside Linux)

4. This is some minor consistency stuff between code. Don't bother changing if it is a lot of work.
4a. Consider %MONEY instead of $money. Reason: %STRING0, %STRING1, etc is used in the game's text files, and I followed that convention for text.substitute.
4b. TNO used the convention of camelCase, which I think everyone's been following, rather than underscores. Not really a huge issue, but it might spare some confusion.

Both things will be done. They are easy.
 
Top Bottom