Jump to content

CulturedCait

Community Members
  • Posts

    18
  • Joined

  • Last visited

Everything posted by CulturedCait

  1. That was good suggestion. I placed as much "warns" as possible and discovered that in my OnInitGame trigger: Trigger.prototype.TestLearningStart = function() { warn("Init"); //zapytajmy czy jest plik startowy inicjalizujacy nasz algorytm wstepnymi entities itp let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); cmpGuiInterface.PushNotification({ "type": "load-json", "players": [0], "name": "testlearning-last", "param": "init" }); warn("Init finish"); //this.TestLearningStartFromScratch(); } PushNotification sends the request without errors, but OnCommand never receives it. It is was clear that my custom message "load-json", which loads JSON file, is simply not being push further. This is my load-json msg: "load-json": function(notification, player) { warn("Received load-json"); let name = notification.name || "testlearning"; let data = null; if (Engine.FileExists("simulation/" + name + ".json")) data = Engine.ReadJSONFile("simulation/" + name + ".json"); Engine.PostNetworkCommand({ "type": "dialog-answer", "dialog": "json", "answer": { "param": notification.param, "data": data, }, }); warn("finished load-json"); }, And this is how I run the game with loading mod with customized "messages.js": $ pyrogenesis -mod="public" -mod="train" -autostart-victory="endless" -autostart="skirmishes/test_sparta" -autostart-disable-replay -quickstart -autostart-nonvisual Mod "train" contains just one single file with modified "messages.js". Since warning "Received load-json" never appears, we can be sure this message never hits in headless mode. So the only explanation is that under -autostart-nonvisual, custom "messages.js" coming from my mod is either ignored or, which is more likely, overlapped with different set of "messages.js" designated for -autostart-nonvisual. Since I need custom messages to communicate with some GUI APIs, I can't get rid of this pattern... I think it is not worth investigating further. I'm satisfied with my current solution as it is and although headless mode certainly could be nice improvement it is not that important for these type of calculations. Thank you again for your help.
  2. Nope. I'm not sure if I can attach full logs here in public. They include sensitive data like API keys. I can send you both logs in PM if needed. In -autostart-nonvisual "NonVisualTrigger.js" is loaded additionally as opposed to regular run. I don't think its the culprit, but who knows.
  3. Well, as I mentioned earlier my output is not appearing at all. I have plenty of warns. Script also reads/writes JSON files and does save game. None of this is executed if -autostart-nonvisual is on. Just "Turn (...)..." appears instead. Looks like it is impossible to use headless mode just to run map with scripts. Probably -autostart-nonvisual is not just turning off graphics and sound, but rather special mode designated to work with -rl-interface only.
  4. That explains a lot. Hmm.. Weird idea, but is it possible that in nonvisual mode "OnInitGame" is not invoked?? This is my entry point: { let learnTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); learnTrigger.RegisterTrigger("OnDeserialized", "TestLearningLoad", { "enabled": true }); learnTrigger.RegisterTrigger("OnInitGame", "TestLearningStart", { "enabled": true }); learnTrigger.RegisterTrigger("OnPlayerCommand", "TestLearningCommand", { "enabled": true }); ////learnTrigger.DoAfterDelay(1000, "TestLearningSpeed", { "enabled": true }); } In single run my script ends in about 20 minutes,then Engine.Exit is issued to close the game. If it works much faster in -nonvisual mode, then we should expect it to finish in less than 20 minutes. What I did was to test it again with -autostart-nonvisual and just waited. Although it didn't produce save games and JSON files, we could explain this is somehow forbidden in this mode. But considering it has still not finished after 30 minutes, maybe the whole thing is just that the script is not triggering in -nonvisual mode??
  5. Nope, this is not the issue. Script works correctly. It was just redundancy but didn't affect anything. I removed "TestLearningCommand" so you could see it had nothing to do with this matter. Problem is that --autostart-nonvisual does *something*, but certainly not what user selected with "-autostart". Here are some proofs: --autostart-nonvisual causes high CPU usage and uses all cores. While regular game uses only one thread (~6-7%). My script should generate "debug.json" after start, and about each minute performs the save game. With --autostart-nonvisual nothing happens. Even if we assumed --autostart-nonvisual suppressed all warnings, but still performed map and scripts, I should expect to JSON files and savegame to be created. --autostart-nonvisual uses only ~250Mb of memory. My script after start uses ~1G and after 15min consumes around 5G. It's combat between ~300units performed each 5sec. Screen below pertains --autostart-nonvisual: Certainly pyrogenesis performs some heavy computations on all cores. And selected map is not being run. While this screen below is without -autostart-nonvisual. One core used, JSON files produced, output produced, and all works as intended: I checked on windows and it's same story. The only difference is that if you use --autostart-nonvisual, "Turn (....)" output is not being produced at all, program exits immediately spawning another process. Rest is the same. Spawned process *does something* on all cores, but not running the map that it was asked.
  6. I see. I'll try to run same command on windows build to see if it works there. That should hopefully give me the answer if the problem is my version of the game or something else.
  7. While quick searching the repository I encountered this: https://gitea.wildfiregames.com/0ad/0ad/src/commit/b77ee3c5dcde432787b0bdf0386fbf766e19f25f/source/ps/Replay.cpp#L279 It's part of the "Replay" method and looks precisely as part of the output I got. Is it possible that --autostart-nonvisual is designed only for replays and you simply can't start the match from scratch when this parameter is present?
  8. Yes, I checked other maps. Same result. Always executes "Turn 0 (200).." script etc ignoring the map. Doesn't matter if mods are used or not. If I remove --autostart-nonvisual everything is OK and maps are loaded normally. Maybe my version of the game is the issue? ~/.local/share/0ad/mods/user/simulation$ pyrogenesis -autostart="skirmishes/tarim_basin_2p" -quickstart --autostart-nonvisual TIMER| InitVfs: 160.709 us FILES| Main log written to '/home/przemek/.config/0ad/logs/mainlog.html' FILES| Interesting log written to '/home/przemek/.config/0ad/logs/interestinglog.html' TIMER| CONFIG_Init: 2.53454 ms FILES| Replay written to '/home/przemek/.local/share/0ad/replays/0.27.1/2026-01-06_0007' GAME STARTED, ALL INIT COMPLETE Turn 0 (200)... Turn 1 (200)... Turn 2 (200)... Turn 3 (200)... Turn 4 (200)... Turn 5 (200)... Turn 6 (200)... Turn 7 (200)... Turn 8 (200)... Turn 9 (200)... Turn 10 (200)... ~/.local/share/0ad/mods/user/simulation$ pyrogenesis -autostart="scenarios/polynesia" -quickstart --autostart-nonvisual TIMER| InitVfs: 194.705 us FILES| Main log written to '/home/przemek/.config/0ad/logs/mainlog.html' FILES| Interesting log written to '/home/przemek/.config/0ad/logs/interestinglog.html' TIMER| CONFIG_Init: 3.4274 ms FILES| Replay written to '/home/przemek/.local/share/0ad/replays/0.27.1/2026-01-06_0008' GAME STARTED, ALL INIT COMPLETE Turn 0 (200)... Turn 1 (200)... Turn 2 (200)... Turn 3 (200)... Turn 4 (200)...
  9. OK, I've completed environment setup. I managed to expose SetEngineRate, WriteJSONFile and incorporate other useful APIs to JS triggers according to your suggestions. To make it work creating a very tiny mod was necessary. However -autostart-nonvisual seems not to work as intended. According to readme: -autostart-nonvisual disable any graphics and sounds Apparently it ignores all other settings and runs the game with hardcoded options like if it was tailored to --rl-interface only. This is the command I run the game. It includes my custom map with all algorithms, and mod name with exposed functions. pyrogenesis -mod="public" -mod="train" -autostart-victory="endless" -autostart="skirmishes/test_sparta" -autostart-disable-replay -quickstart Typically map starts automatically, then training is performed, and after one generation script closes the game due to high memory usage. Then bash script runs it again indefinitely to iterate etc. Expected output in my case after pyrogenesis start is something like: (....) TIMER| session/setup.xml: 82.173 us TIMER| session/sprites.xml: 381.305 us TIMER| session/styles.xml: 72.086 us TIMER| session/session.xml: 31.4006 ms GAME STARTED, ALL INIT COMPLETE WARNING: Beginning from JSON file WARNING: Trigger.js: Trigger "TestLearningCommand" has been registered before. Aborting... WARNING: Load WARNING: currentIteration: 9 WARNING: entitiesToDo: 0 WARNING: entitiesDone: 250 WARNING: crossover chance: 50% WARNING: mutation chance: 40% WARNING: 512 (....) However if I just add "-autostart-nonvisual", then map isn't being loaded, and some other scripts or computations are being performed instead (look after "GAME STARTED, ALL INIT COMPLETE): bash:~/.local/share/0ad/mods/user/simulation$ pyrogenesis -mod="public" -mod="train" -autostart-victory="endless" -autostart="skirmishes/test_sparta" -autostart-disable-replay -quickstart -autostart-nonvisual TIMER| InitVfs: 197.269 us FILES| Main log written to '/home/przemek/.config/0ad/logs/mainlog.html' FILES| Interesting log written to '/home/przemek/.config/0ad/logs/interestinglog.html' TIMER| CONFIG_Init: 1.27741 ms WARNING: Init GAME STARTED, ALL INIT COMPLETE Turn 0 (200)... Turn 1 (200)... Turn 2 (200)... Turn 3 (200)... Turn 4 (200)... Turn 5 (200)... Turn 6 (200)... (...) This may be a bug if (=>readme) is accurate. Is it possible to disable screen and sound in a different way? Thank you!
  10. OK! Thank you guys. I'll investigate and let you know if I encounter any obstacles. Cheers.
  11. I checked the python repo and it picked my interest. Particularly headless option you mentioned would be very useful. I have question regarding this cmd: pyrogenesis --rl-interface=0.0.0.0:6000 --autostart-nonvisual --mod=rl-scenarios --mod=public Is there any api documentation regarding how to communicate with this interface? I.e. what should you send to this port to execute some part of the game (assuming I understand this interface correctly, sorry I didn't have much time to examine python scripts in detail..). In my case what I needed would be to actually load given map remotely, and save this map after period of time.
  12. Nope. Very interesting. This would be precisely what I'm looking for. Thank you.
  13. Well, I wanted to avoid creating a mod. Actually I just wanted to make scripted map in plain "vanilla" 0 A.D. SetSimRate, as helpful as it would be for automating few things, is not that critical in the end. I can always invoke the command from the console. Thank you. Ok. This is very long story, but to the details what I'm working on... I'll try to explain. I've always wanted to know which types of units and formations are best in a given case. Also, how my formation should look like considering shape and direction vector of the enemy during tactical clash (in second stage of the project my idea would be also to find precise polynomials that should represent formation lines that should be used). On the one hand these are pointless questions (what we're dealing with are differential equations... that's why some say that strategy is rather an art than something you can calculate). But for a long time it's been bugging me and I had some ideas how to crack this problem with genetic algorithms. Or at least to try finding approximate or partial answers in some cases. Since I found some time during the Christmas I developed very tiny genetic algorithm framework in JS that operates only on 0 AD triggers in asynchronous way. Since the objective function in my problem is the result of single combat, and GA requires to perform many of such clashes for single generation, this is "the lengthy calculation" I was talking about. GA has to wait for each of such "entities" (i.e. clash of two armies) results to pick parameter candidates for next generation. That's why I was interested in SetSimRate to speed up the process a little. As you can see there are many asynchronous calculations (actually thousands...) that need to be processed sequentially. Speeding up simulation helps much. I know what you say. You could always grab units statistics, calculations etc from the code and write a program in faster environment to achieve similar results. But I wanted to utilize exact 0 A.D. engine as it is. There would be many mistakes in this process if I did otherwise. Maybe it would be easier, and you wouldn't have to resort to some quirks, but since scripting support in 0 A.D. is very comprehensive it is possible to achieve all I described above. GA's are very slow by definition so technology doesn't matter that much. The algorithm itself is the bottleneck. This is of course very lengthy project. Absolutely nothing to brag about, more like a hobby actually Hope this now sheds little light where my question came from. Now, to simulate how SetSimRate helps, just try to invoke something simple that spawns itself each 100ms in a sequence using DoAfterDelay. You can assume this "100ms" is aforementioned sequenced lengthy atomic operation that you don't know the result yet. You'll be notified of the result later when it finishes, and you'll utilize the result later to spawn next iteration "somehow". testTrigger.DoAfterDelay(100, .....) You'll see the difference if you speed up simulation to x20. This "100" would become ~5 in real life time. Maybe not really 5, but much faster.
  14. Hi phosit, I checked PushNotification and it seems to be limited to several possible message types. Which of course makes sense from the usage perspective... Does it mean the only way to achieve what I wanted would be to mod messages.js by adding new message type that registers function executing SetSimRate? Did I get your idea right? Thanks.
  15. Hi Vantha, thanks for detailed explanation. All is clear now. What I wanted to achieve is to programmatically speed up the game in the beginning to the value of~ x20 (just temporarily) to override default Map Setup setting. Reason is to perform some JS asynchronous calculations much faster eliminating internal tick bottleneck. Then go back to the default speed value few moments after. What you described as a workaround sounds very promising! Can you please explain little more how to communicate between different contexts to register SetSimRate? Thank you!
  16. Hi guys! I'm working on a new script and I was wondering if there is a way to execute Engine.SetSimRate / Engine.GetSimRate from JS trigger script? It works if executed directly from the console, but using these functions inside JS produces following error: ERROR: Error in timer on entity 1, IID103, function DoAction: TypeError: Engine.SetSimRate is not a function This is my test trigger: Trigger.prototype.TestDelay = () => { Engine.SetSimRate(20); } const trg = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); trg.DoAfterDelay(5000,"TestDelay", {enabled: true}); I'm on release-a27.1 6a576. Do you have an idea how to change simulation speed from within javascript? Is it even possible using trigger mechanics? Thank you.
  17. Hello! Imagine a perfectly symmetrical world... Where harmony is the most important virtue... Can you survive this seemingly endless war? Can you dominate the world? Welcome to the Endless Arena! Features: Automatic adjustment of allies/enemies depending on their military power Fair support for weaker players High difficulty due to equilibrium oriented design & scripting Unique gameplay leading to test new ideas. The key to victory is use your cunning and maintain balance. You'll have to use stratagems and art of wars rather than sheer military power. Notes: recommended 64bit version of 0 A.D. Alternatively you can lower population limit in game setup if out of memory occurs during large battles. Version : 1.5.5 Map Created : 10/27/2024 Last Edited : 1/14/2025 Map type : skirmish Players# : 8 Size : Giant Tested @ 0 A.D. Alpha 26 Changes: v1.5.5 [1/14/2025]: replaced turkeys with chickens, changed map preview to fit 0AD convention Mod io homepage (always latest version): https://mod.io/g/0ad/m/map-endless-arena Direct ZIP download: Endless Arena v 1.5.5 or *.pyromod format in attachment My idea was to create a map, where the gameplay on the one hand could be extended as much as possible, and on the other hand it remained fair and symmetrical for everyone. To achieve these goals map uses set of algorithms to calculate power of each player and use this information to impose balance between them. Calculating Power As a short introduction, you need to remember few things. Typically power of a state is the sum of its kinetic power (known as military) and potential power (widely known as economy and R&D). Economy and R&D is treated as a potential power only because it may be forged to build military power later in the future. Otherwise it could be completely irrelevant. In fact many scholars often ignore economic power, because it is typically being used for purposes other than building military forces. It becomes useless in predicting or explaining various events from the large scale perspective. History proves this may be good approach. Many states ignore economy as a mean to create their own military power (either involuntary or coerced by other powers), leaving real future of a state in the hands of other greater powers. Whatever the reason, most of the economic power is usually wasted. Same applies also to 0AD to some extent. Since it is difficult to tell how much economic power would be turned to strength in the future, and how useful technology investments would become for military uses, Endless Arena uses only military might as power indicator. This is not perfectly accurate, and later addressed in "Divine Intervention". But in the end it is military might that determines the future of a kingdom. Unlikely to in-game military score, only current military power is being used as a factor. In dynamical systems, historical achievements does not determine future at all if they possess Markov property. And most chaotic systems we observe in life, seem to have this property. 0 A.D included. What matter is power "here and now" (factor "A" in below equation) and how well it is being used. History may tell us only about how well power is typically applied by a given state (strategic culture, quality of commanders, leaders). In Endless Arena this is represented by factor "B". So the formula used to calculate power of a kingdom in Endless Arena is following: Power = A * log(B) Where: A - Current military power potential B - How well military power is being applied Current military power Current military power is being calculated based on all of your current population, its cost and health. We can easily assume the more expensive the unit, the more powerful it is. If your soldier is heavily wounded (25% of health), we can also assume they're tired and 4 times less capable of fighting comparing to freshly recruited one. Of course there are many other factors, like forge technologies, that should be applied to this to be more accurate. However, during tests this heuristics appeared sufficient. Other players development progress was usually similar, hence easily ignored - especially in the late game experience. So to recap, to determine power potential Endless Arena uses: current demography, their cost and their well being. How well military is being used There exists simple indicator that helps to determine how well you're managing your military: Kill/Death ratio (KDR) and this coef is being used for "B". During tests it appeared to be important to use logarithmic function with this coefficient, as it operates much better toward equilibrium. We can fell it - there is not much difference between someone who manages to have 100 KDR comparing to 20 KDR. It doesn't really mean they are 5x better than the other. They're both skilled generals. And the difference may be related to luck, weaker enemies or geographic properties. Typically geographic landscape and players proximity should also be taken into consideration. The reason is, that "power" (soldiers) shifts and flows according to certain geographic properties. In this regard in some places power would always equal to zero no matter how good it looks in raw numbers. Even if state is equipped with elite soldiers and high demography (consider oceans or mountains as an example, where people and their goods simply cannot be present). On the other hand there are some places of extreme importance. Consider mountain passages or straits, where soldiers would have to always be displaced in order to reach, gain or defend "something". Therefore I decided to create symmetric map with equal distance to each other player, equal number of resources etc. This way we could mitigate geography factor in our equation. Technical details Endless Arena map calculates power and alliances each 5 minutes. During the assessment process, algorithm calculates all possible alliances combinations and permutations, and chooses best according to the simple rule: the more similar in power the alliances are, the closer to equilibrium such alliance set is. Mathematically, the smaller standard deviation between the power of each Teams (alliances), the better set of alliances. After the process of deciding who belongs to what alliance, each player change their teams automatically. Typically weaker players are paired with better one, best players are usually lone wolfs facing bigger threats alone etc. Map tries to keep balance at each stage. Divine Intervention Previously there have been described some issues with economy value used to calculate power. On the one hand you can't use 100% of economy value to calculate power as most of it is wasted from the power perspective (same applies to military power, however in military we can easily determine how useful it is examining units health). On the other hand, however, some of the economy is being used to train your soldiers, research military technologies helping you with your military power etc. This definitely should be used to calculate might. How to find a good solution to this? Given the level of entanglement in game mechanics and possible outcomes, there seems to be no answer to this problem. Hence my approach is a little different. I'm not using economy potential to calculate power at all. But, during assessment process, each player is estimated how much military power it lacks to the best player. Let's assume Player 3 in terms of military is best player (100%), and Player 1 is at 84%. Player 1 lacks 16% of power to the best player. Endless Arena assumes that Player 1 must be lacking some military resources to achieve Player 3 level. These missing 16% are calculated to manpower that would be needed to get to 100%, and then converted to regular resources amount (food, wood, ore & stone) needed to recruit these missing soldiers. Next, these resources would be distributed to the Player 1 as a divine help during the next 5 minutes in form of tranches (one small tranche each 10 seconds). These additional resources should be used to build missing military capabilities. But if the Player already have "missing resources", no help would be given at all! Game assumes, that if a player already have enough resources to build military, but for whatever reason they are not building it, it's their business. Volenti non fit iniuria. Lets consider few examples how it works. Example 1. Sometimes you could face the situation to inadvertently become target of the whole world. Just imagine the situation, especially in the beginning of the game, when you're the fastest developing player (as a human comparing to AI) and in the numbers become stronger than sum of 3 other players. You're not as good as all 7 others, but still considering raw numbers they'll be coerced to form a strong alliance against you! Initially you could even repel some waves of the enemies, but in the end this will even worsen your situation as officially your power increases thanks to high kill to death ratio in the next assessment (you're also skilled tactician). After few initial victories you probably won't have enough time and resources to heal all your soldiers... And even if you do, your enemies have operational depth (in spite of facing huge losses at the front!). This depth helps them to continue their development, while you're occupied with warfare. Weak alliance you'll be part of, probably won't be much of a help due to problems with coordination. They would even expect help from your side, since you're powerful! You'll find yourself quickly in a big pressure, typically rolling back most of your hard earned progress! Yeah, it's true that after such a defeat, with next estimate you would be part of a strong alliance, but what about your destroyed economy and kingdom? Not an easy thing to start from scratch, when everyone else is at City Phase. Thanks to divine intervention, you'll receive big help as a severely weakened player in comparison to other, more powerful. First you violated equilibrium with your outstanding development, then another equilibrium is violated to help you and eventually balance will be restored. Just like with tight rubber band that tries to find natural position after being released. Example 2. Similarly, just imagine you won few battles with AI due to your tactical skills. At some point they refuse to develop and build military.. This is typical problem in most regular 0 A.D. maps. Mostly due to destroyed economy. Result of one or two great battles determines future forever. Game is ruined, as you totally dominate world. To address such issues with balance, AI will be bestowed upon with lot's of resources (but not more than it is needed to attain your military level) that'll help them to repel your vile actions. Again: the point of the game is to keep balance as much as possible, so everyone could exist and live as long as possible. Known Issues There are few known issues: When diplomacy changes, we can witness short lags. And since there are many alliance changes (depending on situation there may be even >20 changes each 5 minutes) you may expect short lags in game each 5 minutes. I don't know how to mitigate the issue and whether it's related with AI or internal game engine, so the only solution to this was to add ~2 second delay between diplomacy switch. During tests in Windows, there were sometimes problems with memory (Out of Memory exception). Solution to this is to use 64bit version of 0 A.D. Optionally you could limit the number of population in game settings to control memory usage. Map wasn't tested in online play. Currently it's unknown whether script works correctly in on-line game. Hope you'll like this map! I'm appreciating all feedback. Thank you! map-endless-arena.pyromod
×
×
  • Create New...