diff --git a/CHANGELOG.md b/CHANGELOG.md index 28af64447..f04abbee9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,42 +3,43 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -## [Unreleased] +## [3.1.0] - 2022-01-05 ### Added - Support for warcraft 3 1.32.10 patch changes. (Pixyy) ### Changed +- To reduce spam from your allied AIs they now only sometimes report what they are countering instead of every single time its re-evaluated, unless debug mode is on. +- At game start as there is nothing to counter yet the message to allies about what to counter will not be included. - Improved Chinese language translations and various issues fixed. (Pixyy) - Removed some explicit Chinese chat translations. - Goblin Shredders now count as more wood cutting workers. (Pixyy) - Creep building detection range slightly increased. (Pixyy) -- Tweaks to brewmaster and alchemist skill picks. (Pixyy) +- Tweaks to Brewmaster and Alchemist skill picks. (Pixyy) - More resources (just over double) are now needed before the multi peasant fast builds can be used to avoid resource starvation. (Pixyy) - Balance pass to all racial hero selection, skill selection and strategy selection. Mostly minor but most noticeable changes include (Pixyy) - Night Elf increased use of warden and keeper. - Reduced use of mirror image skill. - Reduced the appearance rate of Goblin Tinker - Strategy tweaks and optimizations (Pixyy) - - Improvements to human, orc, undead and night elf strategy compositions. - - Fixed undead harassment group numbering. - - Hero priorities for building and resurrecting increased. + - Improvements to human, orc, undead and night elf strategy compositions to make the pre-built strategies more effective when used. + - Removed non-useful units from harass attacks and fixed undead harassment group numbering. + - Hero priorities for building and resurrecting increased to ensure there are being built first. - Tweaks to item buying priorities, town portals are more important, other items less so or no longer built. - - Improvements to base defense logic. + - Improvements to base defense logic with more towers being built when spare funds available. - Tweaks to the dynamic strategies to balance the counter units and correct some cases of invalid counter units being built. ### Fixed -- Tweaked ranged units to only avoid melee units only if damaged to 70% instead of 90% and reduced distance to trigger slightly to improve AI performance. (Pixyy) +- Tweaked ranged units to avoid melee units only if damaged to 70% instead of 90% and reduced distance to trigger slightly. (Pixyy) - Fixed an issue where healing totems are not cast correctly. (Pixyy) - Reduced number of mines needed before heading into high upkeep to help prevent dead time where AMAI doesn't appear to build anything. (Pixyy) - Front base distance range slightly increased again to help fix night elf troops getting stuck in base. (Pixyy) -- Improved handling of the bug that the AI ​​hero card does not operate at home. (Pixyy) -This bug still occasionally occurs, but has reduced the freezing time. Heroes will rejoin the battle when their health is mostly healthy. +- Improved handling of the bug that the AI ​​hero will get stuck healing at home. They will now return to the battle when mostly healthy. (Pixyy) - Heroes a little more likely to teleport to rescue a town regardless of the profiles aggression and smaller threat levels. (Pixyy) - Militia max expansion range has been reduced as militia did not always last long enough to be useful. (Pixyy) -- Ambush no longer used for hero units as its too easy to pick them off. (Pixyy) -- Fixed an issue where no tier bonus was applying to the fail safe upgrade system. -- Fixed an issue where human upgrades magic sentry and flare could not be researched. (Pixyy) +- Ambush no longer used for hero units as its too easy to abuse and pick them off. (Pixyy) +- Fixed an issue where no tier bonus was applying to the dynamic upgrade system. +- Fixed an issue where human upgrades magic sentry and flare could not be researched by the AI. (Pixyy) ## [3.0.1] - 2021-01-30 diff --git a/README.md b/README.md index f8be5f3a7..806f83d99 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ As was originally hosted on http://www.wc3campaigns.net/forumdisplay.php?f=601 | -----------|--------------------------------|---------------| | 2.5.4 | Min 1.24+ | Classic edition from 2008 | | 2.6.1 | Min 1.24+ | Better Support for 1.30+ | -| 3.0 | Min 1.32.10+ | Full Support for the 1.30+ era | +| 3.0 | Min 1.32+ | Full Support for the 1.30+ era | +| 3.1 | Min 1.32.10+ | | * There are reports that v1.29 of Warcraft 3 prevents AMAI from chatting. This is just an issue with this version and you can downgrade or upgrade. @@ -22,8 +23,8 @@ AMAI release comes with the standard AI scripts pre-built for you. It is suggested to create a subfolder in your "maps" folder like "maps\AMAI" and copy the maps you intend to use AMAI with there. For Warcraft 1.30 onwards you need to use http://www.zezula.net/en/casc/main.html to extract a copy of official maps. -- Run *InstallTFTtoMap* from a windows commandline or powershell, to install AMAI to maps e.g `InstallTFTToMap.bat "C:\mymap.w3m"` -- Alternatively for complex installs if you have `perl` installed you can run `InstallTFTtoDir.pl "C:\Documents\Warcraft III\Maps\AMAI"` to install AMAI to all maps in a directory and subdirectories. +- From a windows commandline or powershell type `InstallTFTToMap.bat "C:\mymap.w3m"` and press enter to install AMAI to maps +- Alternatively for complex installs if you have `perl` installed from a commandline you can type `perl InstallTFTtoDir.pl "C:\Documents\Warcraft III\Maps\AMAI"` and press enter to install AMAI to all maps in a directory and subdirectories. - After installing AMAI on your map just start Warcraft3: RoC or TFT and play the map against and/or with computers to make use of AMAI. ## Notes @@ -41,19 +42,19 @@ Tested with strawbery perl 5.30 and Tk 804.034 *You may need to run as an administrator if you have issues with maps not displaying any teams. ## TFT Build -- Use *makeTFT.bat* to create the standard scripts for the AI. -- Run *InstallTFTToMap.bat "C:\mymap.w3m"* to install the AI scripts to Warcraft 3 maps. +- Run/double click *makeTFT.bat* to create the standard scripts for the AI. +- From a command prompt type *InstallTFTToMap.bat "C:\mymap.w3m"* and press enter to install the AI scripts to Warcraft 3 maps. - Run up a custom game and select the map to play. ## VS AI Build - This special version will make *odd* teams run with AMAI and *even* teams run with the standard blizzard AI. -- Use *makeVAITFT.bat* to create the AMAI vs AI scripts. -- Run *InstallTFTToMap.bat "C:\mymap.w3m"* to install the AI scripts to Warcraft 3 maps. +- Run/double click *makeVAITFT.bat* to create the AMAI vs AI scripts. +- From a command prompt type *InstallTFTToMap.bat "C:\mymap.w3m"* and press enter to install the AI scripts to Warcraft 3 maps. ## ROC Build - This version is intended to be played in the original ROC (Reigns of Chaos) version of the game. This version is currently not supported in 1.30+. -- Use *makeROC.bat* to create the ROC scripts. -- Run *InstallROCtoMap.bat "C:\mymap.w3m"* to install the AI scripts to Warcraft 3 maps. +- Run/double click *makeROC.bat* to create the ROC scripts. +- From a command prompt type *InstallROCtoMap.bat "C:\mymap.w3m"* and press enter to install the AI scripts to Warcraft 3 maps. # Features - **Personality Profiles**: Each AI opponent has a set profile which modifies how it reacts or plays the game. Some can be real chickens and never dare to attack you while others will rush you down. diff --git a/common.eai b/common.eai index fa795d3a4..9a5fdb749 100644 --- a/common.eai +++ b/common.eai @@ -988,22 +988,23 @@ globals gamecache udg_debug_cache = null string udg_current_category = null timer udg_debug_timer = CreateTimer() - boolean job_debug = false // Job system reports will be displayed (used for finding thread crashes) - integer debug_player = 0 + boolean job_debug = false // Job system reports will be displayed (used for finding thread crashes) + integer debug_player = 0 //============================================================== // (AMAI) Dynamic Strategy variables //============================================================== integer chosen_counter = -1 - integer chosen_counter_unit = 0 - string array strengthtext - #INCLUDETABLE <$VER$\Strengths.txt> - integer array dyanti_%1 - integer totalanti_%1 = 0 - integer array dychance_%1 - integer totalchance_%1 = 0 - #ENDINCLUDE - + integer chosen_counter_unit = 0 + boolean no_counter = true + string array strengthtext + #INCLUDETABLE <$VER$\Strengths.txt> + integer array dyanti_%1 + integer totalanti_%1 = 0 + integer array dychance_%1 + integer totalchance_%1 = 0 + #ENDINCLUDE + endglobals @@ -2893,8 +2894,8 @@ function GetCurrentStrategyReport takes nothing returns string endfunction function GetCurrentDynamicReport takes nothing returns string - if strengthtext[chosen_counter] != null then - return " " + chat_dynamic_counter + strengthtext[chosen_counter] + if strengthtext[chosen_counter] != null and no_counter == false then + return " " + chat_dynamic_counter + strengthtext[chosen_counter] endif return "" endfunction @@ -8584,64 +8585,66 @@ function DetermineCounterForce takes nothing returns integer set num_strengths = 0 set j = 0 #INCLUDETABLE <$VER$\Strengths.txt> - set tstrength[num_strengths] = R2I(RMax(enemy_%1 - ally_%2 - ally_%3,0)*100) - set strength = strength + tstrength[num_strengths] - set strengthtext[num_strengths] = "%1" - set num_strengths = num_strengths + 1 + set tstrength[num_strengths] = R2I(RMax(enemy_%1 - ally_%2 - ally_%3,0)*100) + set strength = strength + tstrength[num_strengths] + set strengthtext[num_strengths] = "%1" + set num_strengths = num_strengths + 1 #ENDINCLUDE - // Normalise strength - //loop - // exitwhen j >= num_strengths - // set tstrength[j] = R2I((tstrength[j]*100)/strength) - // set total_strength = total_strength + tstrength[j] - // set j = j + 1 - //endloop - loop - exitwhen j >= num_strengths - if tstrength[j] > tstrength[maxstr] then - set thirdstr = secondstr - set secondstr = maxstr - set maxstr = j - elseif secondstr == -1 or tstrength[j] > tstrength[secondstr] then - set thirdstr = secondstr - set secondstr = j - elseif thirdstr == -1 or tstrength[j] > tstrength[thirdstr] then - set thirdstr = j - endif - set j = j + 1 - endloop - if chosen_counter >= 0 then - if tstrength[chosen_counter] > 0 then - set tstrength[chosen_counter] = tstrength[chosen_counter] + R2I(strat_persistence/200) // Bonus to current counter - set strength = strength + R2I(strat_persistence/200) - endif - endif - call Trace("Highest Enemy Unit Strength is:" + strengthtext[maxstr] + " with total:" + Int2Str(tstrength[maxstr])) - set j = 0 - // Remove bad strats to not affect calculations with really low amounts of strength - loop - exitwhen j >= num_strengths - if tstrength[j] < 3 then - set tstrength[j] = 0 - endif - set total_strength = total_strength + tstrength[j] - set j = j+1 - endloop - - // No strength so just use a random option - if total_strength == 0 then - set j = GetRandomInt(0, num_strengths) - else - set j = 0 - set random =GetRandomInt(1, total_strength) - set strength = 0 - loop - set strength = strength + tstrength[j] - exitwhen random <= strength or j >= num_strengths - set j = j + 1 // Will be the the chosen strength to build units against - endloop - endif + // Normalise strength + //loop + // exitwhen j >= num_strengths + // set tstrength[j] = R2I((tstrength[j]*100)/strength) + // set total_strength = total_strength + tstrength[j] + // set j = j + 1 + //endloop + loop + exitwhen j >= num_strengths + if tstrength[j] > tstrength[maxstr] then + set thirdstr = secondstr + set secondstr = maxstr + set maxstr = j + elseif secondstr == -1 or tstrength[j] > tstrength[secondstr] then + set thirdstr = secondstr + set secondstr = j + elseif thirdstr == -1 or tstrength[j] > tstrength[thirdstr] then + set thirdstr = j + endif + set j = j + 1 + endloop + if chosen_counter >= 0 then + if tstrength[chosen_counter] > 0 then + set tstrength[chosen_counter] = tstrength[chosen_counter] + R2I(strat_persistence/200) // Bonus to current counter + set strength = strength + R2I(strat_persistence/200) + endif + endif + call Trace("Highest Enemy Unit Strength is:" + strengthtext[maxstr] + " with total:" + Int2Str(tstrength[maxstr])) + set j = 0 + // Remove bad strats to not affect calculations with really low amounts of strength + loop + exitwhen j >= num_strengths + if tstrength[j] < 3 then + set tstrength[j] = 0 + endif + set total_strength = total_strength + tstrength[j] + set j = j+1 + endloop + + // No strength so just use a random option + if total_strength == 0 then + set no_counter = true + set j = GetRandomInt(0, num_strengths) + else + set no_counter = false + set j = 0 + set random =GetRandomInt(1, total_strength) + set strength = 0 + loop + set strength = strength + tstrength[j] + exitwhen random <= strength or j >= num_strengths + set j = j + 1 // Will be the the chosen strength to build units against + endloop + endif return j endfunction diff --git a/races.eai b/races.eai index 2035e2db1..fa6deb5cb 100644 --- a/races.eai +++ b/races.eai @@ -724,68 +724,70 @@ function build_sequence_all takes nothing returns nothing call Trace("Starting Build Sequence Loop") loop exitwhen player_defeated - - if recalculate_heros then - call AMAI_PickMeleeHero() - call set_skills() - set recalculate_heros = false - endif - - //call Trace("BUILD SEQUENCE: Running Loop") + + if recalculate_heros then + call AMAI_PickMeleeHero() + call set_skills() + set recalculate_heros = false + endif + + //call Trace("BUILD SEQUENCE: Running Loop") call peon_assignment_all() - //call Trace("BUILD SEQUENCE: peon_assignment") + //call Trace("BUILD SEQUENCE: peon_assignment") if x > 2 then set x = 0 - //call Trace("BUILD SEQUENCE: StrategyChanger") + //call Trace("BUILD SEQUENCE: StrategyChanger") call StrategyChanger() endif - if counter_timer > 0 then - set chosen_counter = DetermineCounterForce() - set reportStrategy = true - set last_counter = chosen_counter - set set_counter = true - set counter_timer = R2I(I2R(-strat_minimum_time[strategy] * (4 - Min(3, tier)))/(3*sleep_multiplier*Max(difficulty - 1, 1))/2) - endif + if counter_timer > 0 then + set chosen_counter = DetermineCounterForce() + if debugging or GetRandomInt(1,5) == 1 then // Only randomly report counter changes to allies not every single time unless debug mode is on + set reportStrategy = true + endif + set last_counter = chosen_counter + set set_counter = true + set counter_timer = R2I(I2R(-strat_minimum_time[strategy] * (4 - Min(3, tier)))/(3*sleep_multiplier*Max(difficulty - 1, 1))/2) + endif - if last_strategy != strategy then + if last_strategy != strategy then set last_strategy = strategy - set reportStrategy = true + set reportStrategy = true call SetRaceAggression() if strategy <= 49 then set x = R2I(I2R(-strat_minimum_time[strategy] * (4 - Min(3, tier)))/(3*sleep_multiplier*Max(difficulty - 1, 1))) endif - //call Trace("BUILD SEQUENCE: InitBuildarray") + //call Trace("BUILD SEQUENCE: InitBuildarray") call InitBuildArrayAM() - //call Trace("BUILD SEQUENCE: init_strategy") + //call Trace("BUILD SEQUENCE: init_strategy") call init_strategy() - endif - - if reportStrategy then - set reportStrategy = false - call DisplayToAlliesImportant( GetCurrentStrategyReport() + GetCurrentDynamicReport()) - call DisplayToObserversImportant( GetCurrentStrategyReport() + GetCurrentDynamicReport()) - endif - + endif + + if reportStrategy then + set reportStrategy = false + call DisplayToAlliesImportant( GetCurrentStrategyReport() + GetCurrentDynamicReport()) + call DisplayToObserversImportant( GetCurrentStrategyReport() + GetCurrentDynamicReport()) + endif + set new_tier = GetTier() if tier != new_tier then set tier = new_tier - //call Trace("BUILD SEQUENCE: initbuildarray2") + //call Trace("BUILD SEQUENCE: initbuildarray2") call InitBuildArrayAM() endif - //call Trace("BUILD SEQUENCE: build_sequence") - call Sleep(0.05) - call build_sequence() - if set_counter == true then - call DynamicStrategySelector() - set set_counter = false - endif + //call Trace("BUILD SEQUENCE: build_sequence") + call Sleep(0.05) + call build_sequence() + if set_counter == true then + call DynamicStrategySelector() + set set_counter = false + endif call Sleep(3 * sleep_multiplier) - //call Trace("BUILD SEQUENCE: peon_assignment 2") + //call Trace("BUILD SEQUENCE: peon_assignment 2") call peon_assignment_all() call Sleep(3 * sleep_multiplier) set x = x + 1 - set counter_timer = counter_timer + 1 + set counter_timer = counter_timer + 1 endloop endfunction