• We have updated our Community Code of Conduct. Please read through the new rules for the forum that are an integral part of Paradox Interactive’s User Agreement.

Pang Bingxun

Field Marshal
2 Badges
Nov 22, 2011
5.596
186
  • Arsenal of Democracy
  • 500k Club
As most of you probably know the current approach on the research AI has some serios flaws. It depends on which field a technology is in, but it does not depend on whether ministers grant a bonus on that field. It does not depend on available tech teams, but that is something can make a great difference to the time needed for a tech. Also historical date modifier influences greatly how much time is needed for research, but apparently AI does not take it into account. The later is not entirely true, it does depend on whether historical date penalty applies, but it does not depend on the degree of it. So whether historical date modifier is 0.99 or 0.29 does not matter to AI and it does also not depend on whether it is 1.01 or 2.0.

1.) I have proposed a new approach that addresses all of that, but it comes at the cost of losing backwards compatibility. Instead of importating something like this

Code:
technology = {
   endgoal    = {
     [...]
   }
   preference    = {
     [...]
   }
   ignore      = {
     [...]
   }
   armor      = 18
   infantry    = 63 # 21 x 3, super high priority
   industry    = 52
   aircraft    = 21
   naval      = 11 # 23 / 2, no navy early
   land_doctrines    = 26 # 13 x 2, no use of endgoal
   secret_weapons    = 6
   air_doctrines    = 38
   naval_doctrines = 7 # 21 / 3, no navy early
}

in 1.09 something like this

Code:
technology = {
   value = {
     1010 = 8000 # 200 x 40 # 1918 Inf
     1020 = 8000 # 200 x 40 # 1936 Inf
     1030 = 8000 # 200 x 40 # 1939 Inf
     1040 = 8000 # 200 x 40 # 1941 Inf
     1050 = 8000 # 200 x 40 # 1943 Inf
     1060 = 8000 # 200 x 40 # 1945 Inf
     10000 = 8000 # 200 x 40 # 1947 Inf
     10010 = 8000 # 200 x 40 # 1951 Inf

     1190 = 270 # 10 x 27 # 1918 Cav
     1200 = 280 # 10 x 28 # 1936 Cav
     1210 = 330 # 10 x 33 # 1937 Cav
     1220 = 350 # 10 x 35 # 1937 semimot Cav
     1300 = 440 # 10 x 44 # 1946 Cav

     1230 = 350 # 10 x 35 # 1938 Mot
     1240 = 350 # 10 x 35 # 1941 Mot
     1250 = 400 # 10 x 40 # 1944 Mot
     10080 = 400 # 10 x 40 # 1947 Mot
     10090 = 400 # 10 x 40 # 1951 Mot

     1070 = 440 # 10 x 44 # 1939 Par
     1080 = 450 # 10 x 45 # 1940 Par
     1090 = 450 # 10 x 45 # 1942 Par
     1100 = 450 # 10 x 45 # 1944 Par
     10020 = 450 # 10 x 45 # 1947 Par
     10030 = 450 # 10 x 45 # 1951 Par

     1260 = 370 # 10 x 37 # 1940 Mech
     1270 = 400 # 10 x 40 # 1942 Mech
     1280 = 430 # 10 x 43 # 1944 Mech
     1290 = 470 # 10 x 47 # 1945 Mech
     10100 = 470 # 10 x 47 # 1947 Mech
     10110 = 470 # 10 x 47 # 1951 Mech

     1150 = 920 # 20 x 46 # 1938 Mar
     1160 = 920 # 20 x 46 # 1940 Mar
     1170 = 980 # 20 x 49 # 1942 Mar
     1180 = 940 # 20 x 47 # 1944 Mar
     10060 = 940 # 20 x 47 # 1947 Mar
     10070 = 940 # 20 x 47 # 1951 Mar

     1340 = 3500 # 100 x 35 # 1937 Repairs
     1350 = 4000 # 100 x 40 # 1941 Repairs
     1360 = 4500 # 100 x 45 # 1943 Repairs
     1370 = 5500 # 100 x 55 # 1949 Repairs

     1110 = 450 # 10 x 45 # 1937 Mtn
     1120 = 440 # 10 x 44 # 1939 Mtn
     1130 = 450 # 10 x 45 # 1941 Mtn
     1140 = 450 # 10 x 45 # 1943 Mtn
     10040 = 450 # 10 x 45 # 1947 Mtn
     10050 = 450 # 10 x 45 # 1951 Mtn

     1310 = 5250 # 150 x 35 # 1936 Logistics
     1320 = 6000 # 150 x 40 # 1940 Logistics
     1330 = 6750 # 150 x 45 # 1942 Logistics
     10120 = 6750 # 150 x 45 # 1945 Logistics

     1380 = 800 # 20 x 40 # 1937 Railway Transportation
     1390 = 860 # 20 x 43 # 1941 Railway Transportation

     2010 = 420 # 10 x 42 # 1918 Arm
     2020 = 420 # 10 x 42 # 1936 Light Arm
     2030 = 480 # 10 x 48 # 1936 Arm
     2040 = 420 # 10 x 42 # 1938 Light Arm
     2050 = 480 # 10 x 48 # 1939 Light Arm
     2060 = 360 # 10 x 36 # 1943 Light Arm Brigade
     2070 = 540 # 10 x 54 # 1939 Arm
     2080 = 580 # 10 x 58 # 1941 Arm
     2090 = 600 # 10 x 60 # 1943 Arm
     2100 = 480 # 10 x 48 # 1938 Heavy Arm
     2110 = 540 # 10 x 54 # 1941 Heavy Arm
     2120 = 630 # 10 x 63 # 1943 Heavy Arm
     2130 = 610 # 10 x 61 # 1944 SH Arm
     2140 = 720 # 10 x 72 # 1945 Arm
     11000 = 600 # 10 x 60 # 1947 Arm
     11010 = 600 # 10 x 60 # 1951 Arm
     2550 = 500 # 10 x 50 # 1954 Arm

     2170 = 250 # 10 x 25 # 1938 TD
     2180 = 250 # 10 x 25 # 1940 TD
     2190 = 250 # 10 x 25 # 1941 TD
     2200 = 300 # 10 x 30 # 1943 TD
     2210 = 350 # 10 x 35 # 1946 TD
     11020 = 350 # 10 x 35 # 1950 TD

     2260 = 250 # 10 x 25 # 1941 SpRocketArt
     2270 = 300 # 10 x 30 # 1942 SpRocketArt
     2280 = 350 # 10 x 35 # 1944 SpRocketArt
     11050 = 350 # 10 x 35 # 1947 SpRocketArt
     11060 = 350 # 10 x 35 # 1951 SpRocketArt

     2450 = 2500 # 100 x 25 # 1918 Static AA
     2460 = 2500 # 100 x 25 # 1936 Static AA
     2470 = 3000 # 100 x 30 # 1938 Static AA
     2480 = 3500 # 100 x 35 # 1941 Static AA
     2490 = 4000 # 100 x 40 # 1943 Static AA
     2500 = 4500 # 100 x 45 # 1945 Static AA
     11080 = 4500 # 100 x 45 # 1948 Static AA

     2400 = 250 # 10 x 25 # 1936 AT
     2410 = 250 # 10 x 25 # 1938 AT
     2420 = 250 # 10 x 25 # 1940 AT
     2430 = 300 # 10 x 30 # 1943 AT
     2440 = 350 # 10 x 35 # 1946 AT
     11070 = 350 # 10 x 35 # 1951 AT

     2370 = 250 # 10 x 25 # 1940 Rocket Art
     2380 = 250 # 10 x 25 # 1941 Rocket Art
     2390 = 300 # 10 x 30 # 1943 Rocket Art

     2510 = 250 # 10 x 25 # 1938 AA Brigade
     2520 = 270 # 10 x 27 # 1941 AA Brigade
     2530 = 320 # 10 x 32 # 1943 AA Brigade
     2540 = 330 # 10 x 33 # 1946 AA Brigade
     11090 = 330 # 10 x 33 # 1950 AA Brigade
     2560 = 450 # 10 x 45 # 1955 AA Brigade

     2290 = 6000 # 200 x 30 # 1918 Light Art
     2300 = 6000 # 200 x 30 # 1918 Medium Art
     2310 = 6000 # 200 x 30 # 1918 Heavy Art
     2320 = 5000 # 200 x 25 # 1936 Art
     2330 = 3750 # 150 x 25 # 1938 Art
     2340 = 3750 # 150 x 25 # 1940 Art
     2350 = 4500 # 150 x 30 # 1943 Art
     2360 = 4950 # 150 x 33 # 1945 Art

     2220 = 250 # 10 x 25 # 1938 SpArt
     2230 = 260 # 10 x 26 # 1940 SpArt
     2240 = 300 # 10 x 30 # 1943 SpArt
     2250 = 350 # 10 x 35 # 1945 SpArt
     11030 = 350 # 10 x 35 # 1947 SpArt
     11040 = 350 # 10 x 35 # 1951 SpArt

     2150 = 250 # 10 x 25 # 1937 AC
     2160 = 250 # 10 x 25 # 1941 AC
     11110 = 280 # 10 x 28 # 1950 AC
     2570 = 400 # 10 x 40 # 1956 AC

     3070 = 420 # 10 x 42 # 1918 CL
     3080 = 420 # 10 x 42 # 1930 CL
     3090 = 420 # 10 x 42 # 1936 CL
     3100 = 420 # 10 x 42 # 1938 CL
     3110 = 420 # 10 x 42 # 1941 CL
     3120 = 420 # 10 x 42 # 1945 CL
     12010 = 420 # 10 x 42 # 1948 CL

     3010 = 420 # 10 x 42 # 1918 DD
     3020 = 420 # 10 x 42 # 1930 DD
     3030 = 420 # 10 x 42 # 1936 DD
     3040 = 420 # 10 x 42 # 1938 DD
     3050 = 420 # 10 x 42 # 1941 DD
     3060 = 420 # 10 x 42 # 1945 DD
     12000 = 420 # 10 x 42 # 1947 DD

     3190 = 480 # 10 x 48 # 1918 BC
     3200 = 480 # 10 x 48 # 1930 BC
     3210 = 480 # 10 x 48 # 1936 BC
     3220 = 480 # 10 x 48 # 1938 BC
     3230 = 480 # 10 x 48 # 1941 BC
     3240 = 480 # 10 x 48 # 1945 BC
     12030 = 480 # 10 x 48 # 1948 BC

     3400 = 420 # 10 x 42 # 1918 SS
     3410 = 420 # 10 x 42 # 1924 SS
     3420 = 420 # 10 x 42 # 1930 SS
     3430 = 420 # 10 x 42 # 1938 SS
     3440 = 420 # 10 x 42 # 1944 SS
     3450 = 420 # 10 x 42 # 1945 SS
     3470 = 420 # 10 x 42 # 1933 HSS
     3480 = 420 # 10 x 42 # 1942 HSS

     3130 = 420 # 10 x 42 # 1918 CA
     3140 = 420 # 10 x 42 # 1930 CA
     3150 = 420 # 10 x 42 # 1936 CA
     3160 = 420 # 10 x 42 # 1938 CA
     3170 = 420 # 10 x 42 # 1941 CA
     3180 = 420 # 10 x 42 # 1945 CA
     12020 = 420 # 10 x 42 # 1948 CA

     3250 = 540 # 10 x 54 # 1918 BB
     3260 = 540 # 10 x 54 # 1924 BB
     3270 = 540 # 10 x 54 # 1930 BB
     3280 = 540 # 10 x 54 # 1936 BB
     3290 = 540 # 10 x 54 # 1941 BB
     3300 = 540 # 10 x 54 # 1945 BB
     12040 = 540 # 10 x 54 # 1948 BB
     3310 = 540 # 10 x 54 # 1938 SH BB
     12050 = 540 # 10 x 54 # 1945 SH BB

     3320 = 540 # 10 x 54 # 1918 CV
     3330 = 540 # 10 x 54 # 1930 CV
     3340 = 540 # 10 x 54 # 1936 CV
     3350 = 540 # 10 x 54 # 1938 CV
     3360 = 540 # 10 x 54 # 1941 CV
     3370 = 540 # 10 x 54 # 1943 CV
     3380 = 540 # 10 x 54 # 1944 CV
     3390 = 540 # 10 x 54 # 1945 CV
     12060 = 540 # 10 x 54 # 1947 CV

     12100 = 420 # 10 x 42 # 1936 CVL
     12110 = 420 # 10 x 42 # 1939 CVL
     12120 = 420 # 10 x 42 # 1941 CVL
     12130 = 420 # 10 x 42 # 1943 CVL
     12140 = 420 # 10 x 42 # 1945 CVL
     12150 = 420 # 10 x 42 # 1948 CVL

     4120 = 600 # 10 x 60 # 1934 TAC
     4130 = 600 # 10 x 60 # 1936 TAC
     4140 = 600 # 10 x 60 # 1938 TAC
     4150 = 600 # 10 x 60 # 1940 TAC
     4160 = 600 # 10 x 60 # 1943 TAC
     15100 = 600 # 10 x 60 # 1945 TAC
     15110 = 600 # 10 x 60 # 1949 TAC

     15500 = 11600 # 200 x 58 # 1943 Turbojet engine

     4010 = 11600 # 200 x 58 # 1934 Int
     4020 = 11600 # 200 x 58 # 1936 Int
     4030 = 11600 # 200 x 58 # 1937 Int
     4060 = 11800 # 200 x 59 # 1940 Int
     4090 = 12000 # 200 x 60 # 1943 Int
     15000 = 12000 # 200 x 60 # 1944 Int
     15010 = 12000 # 200 x 60 # 1947 Int
     15020 = 12000 # 200 x 60 # 1950 Int
     4290 = 10000 # 200 x 50 # 1959 Int

     4170 = 600 # 10 x 60 # 1937 CAS
     4280 = 600 # 10 x 60 # 1940 CAS
     4180 = 600 # 10 x 60 # 1943 CAS
     15120 = 600 # 10 x 60 # 1945 CAS
     15130 = 600 # 10 x 60 # 1947 CAS

     4190 = 600 # 10 x 60 # 1938 NAV
     4200 = 600 # 10 x 60 # 1941 NAV
     4210 = 600 # 10 x 60 # 1943 NAV
     15140 = 600 # 10 x 60 # 1945 NAV
     15150 = 600 # 10 x 60 # 1949 NAV

     4050 = 580 # 10 x 58 # 1937 Esc
     4080 = 590 # 10 x 59 # 1940 Esc
     4110 = 600 # 10 x 60 # 1943 Esc
     15060 = 600 # 10 x 60 # 1944 Esc
     15070 = 600 # 10 x 60 # 1947 Esc
     15080 = 600 # 10 x 60 # 1951 Esc
     4300 = 500 # 10 x 50 # 1960 Esc

     4220 = 600 # 10 x 60 # 1937 Str
     4230 = 600 # 10 x 60 # 1940 Str
     4240 = 600 # 10 x 60 # 1943 Str
     15160 = 600 # 10 x 60 # 1945 Str
     15170 = 600 # 10 x 60 # 1949 Str

     4250 = 580 # 10 x 58 # 1936 Tra
     4260 = 580 # 10 x 58 # 1940 Tra
     4270 = 580 # 10 x 58 # 1942 Tra
     15180 = 580 # 10 x 58 # 1947 Tra
     15190 = 580 # 10 x 58 # 1951 Tra

     4040 = 580 # 10 x 58 # 1938 MRF
     4070 = 590 # 10 x 59 # 1940 MRF
     4100 = 600 # 10 x 60 # 1943 MRF
     15030 = 600 # 10 x 60 # 1944 MRF
     15040 = 600 # 10 x 60 # 1947 MRF
     15050 = 600 # 10 x 60 # 1950 MRF
     4310 = 500 # 10 x 50 # 1962 MRF

     5050 = 9400 # 200 x 47 # 1936 Machine Tools
     5060 = 10600 # 200 x 53 # 1937 Machine Tools
     5070 = 11800 # 200 x 59 # 1938 Machine Tools
     5080 = 9400 # 200 x 47 # 1936 Construction
     5090 = 7950 # 150 x 53 # 1937 Construction
     5100 = 8850 # 150 x 59 # 1938 Construction
     5110 = 8400 # 150 x 56 # 1939 Production Control
     5120 = 8400 # 150 x 56 # 1939 Production Planning
     5130 = 12800 # 200 x 64 # 1940 Assembly Line Experimentation
     5140 = 10800 # 150 x 72 # 1940 Aircraft Assembly Line
     5150 = 720 # 10 x 72 # 1940 Ship Assembly Line
     5160 = 720 # 10 x 72 # 1940 Vehicle Assembly Line
     5170 = 720 # 10 x 72 # 1942 Rocket Assembly Line
     5180 = 7200 # 100 x 72 # 1940 Small Arms Assembly Line

     5550 = 8100 # 150 x 54 # 1936 Rocket Test
     5560 = 7500 # 150 x 50 # 1939 Rocket Engine
     5570 = 7500 # 150 x 50 # 1939 Turbojet Engine
     5580 = 480 # 10 x 48 # 1940 Flying Bomb Dev
     5590 = 540 # 10 x 54 # 1941 Flying Rocket Dev

     5010 = 4400 # 100 x 44 # 1936 Modern Agriculture
     5020 = 5000 # 100 x 50 # 1936 Mechanized Agriculture
     5030 = 4600 # 100 x 46 # 1936 Agrichemistry
     5040 = 6200 # 100 x 62 # 1936 Agricultural Production
     13000 = 6200 # 100 x 62 # 1945 Advanced Agricultural Production
     13010 = 6200 # 100 x 62 # 1948 Modern Agricultural Production

     5410 = 2000 # 50 x 40 # 1937 BD Radar
     5420 = 2250 # 50 x 45 # 1940 ID Radar
     5430 = 2250 # 50 x 45 # 1942 AD Radar
     5440 = 2550 # 50 x 51 # 1942 BC Radar
     5450 = 2750 # 50 x 55 # 1943 IC Radar
     5460 = 3000 # 50 x 60 # 1944 AC Radar
     13030 = 3000 # 50 x 60 # 1944 MC Radar

     5310 = 8550 # 150 x 57 # 1936 Census Tabulating Machine
     5320 = 9000 # 150 x 60 # 1936 Computing Machine
     5330 = 9000 # 150 x 60 # 1938 Computing Machine
     5340 = 9000 # 150 x 60 # 1940 Computing Machine
     5350 = 4500 # 100 x 45 # 1937 Encryption
     5360 = 2500 # 50 x 50 # 1938 Decryption
     5370 = 4500 # 100 x 45 # 1939 Encryption
     5380 = 2500 # 50 x 50 # 1940 Decryption
     5390 = 4500 # 100 x 45 # 1941 Encryption
     5400 = 2500 # 50 x 50 # 1942 Decryption
     13060 = 4500 # 100 x 45 # 1947 information theory

     5190 = 4480 # 80 x 56 # 1936 Oil Plant
     5200 = 4480 # 80 x 56 # 1938 Oil Plant
     5210 = 5580 # 90 x 62 # 1940 Oil Plant
     5220 = 6400 # 100 x 64 # 1941 Oil Plant
     5230 = 8000 # 125 x 64 # 1942 Oil Plant
     5240 = 9600 # 150 x 64 # 1943 Oil Plant
     13020 = 640 # 10 x 64 # 1945 Oil Plant

     13040 = 12800 # 200 x 64 # 1945 Plastics
     13050 = 12800 # 200 x 64 # 1948 Advanced material sciences
     5250 = 8250 # 150 x 55 # 1948 Polymers
     5260 = 8250 # 150 x 55 # 1953 Polymers
     5270 = 8250 # 150 x 55 # 1958 Polymers
     5280 = 11000 # 200 x 55 # 1963 Polymers

     5290 = 390 # 10 x 39 # 1936 Rare Plant
     5300 = 400 # 10 x 40 # 1939 Rare Plant
     5600 = 450 # 10 x 45 # 1941 Rare Plant
     5610 = 450 # 10 x 45 # 1943 Rare Plant

     5470 = 600 # 10 x 60 # 1936 Faculty of Atomic Research
     5480 = 600 # 10 x 60 # 1936 Atomic Research Laboratories
     5490 = 600 # 10 x 60 # 1939 Faculty of Nuclear Research
     5500 = 720 # 10 x 72 # 1941 Isotope Separation Facility
     5510 = 720 # 10 x 72 # 1941 Nuclear Fuel Analysis
     5520 = 720 # 10 x 72 # 1941 Experimental Reactor
     5530 = 720 # 10 x 72 # 1943 Nuclear Reactor Operability
     5540 = 720 # 10 x 72 # 1944 Nuclear Power Production
     5620 = 720 # 10 x 72 # 1947 Nuclear Power Plant
     5630 = 720 # 10 x 72 # 1951 Nuclear Power Plant
     5640 = 720 # 10 x 72 # 1955 Nuclear Power Plant
     5650 = 720 # 10 x 72 # 1957 Nuclear Power Plant

     6010 = 12000 # 200 x 60 # 1930 Firepower Focus Doctrine
     6020 = 9000 # 150 x 60 # 1936 Superior Firepower Doctrine
     6040 = 12000 # 200 x 60 # 1937 Delay Doctrine
     6050 = 12000 # 200 x 60 # 1938 Mobile Defense Doctrine
     6060 = 12000 # 200 x 60 # 1939 Stand Off Doctrine
     6070 = 12000 # 200 x 60 # 1940 Integrated Support Doctrine
     6080 = 12000 # 200 x 60 # 1942 Regimental Combat Teams
     6090 = 12000 # 200 x 60 # 1943 Combined Arms Defense
     6100 = 12000 # 200 x 60 # 1943 Mechanized Offensive
     14050 = 10000 # 200 x 50 # 1946 Air Land Battle

     6030 = 11000 # 200 x 55 # 1936 Grand Battleplan Doctrine
     6120 = 11000 # 200 x 55 # 1936 Trench Warfare Doctrine
     6130 = 11000 # 200 x 55 # 1940 Preplanned Defense Doctrine
     6140 = 11000 # 200 x 55 # 1942 Central Planing Doctrine
     14070 = 10000 # 200 x 50 # 1946 Assault Concentration Doctrine
     6380 = 11800 # 200 x 59 # 1956 C3I theory (2 other copies!)
     6110 = 11000 # 200 x 55 # 1938 Mass Assault Doctrine
     6160 = 11000 # 200 x 55 # 1942 Infiltration Assault Doctrine
     6190 = 11000 # 200 x 55 # 1943 Infiltration in Depth
     6150 = 8250 # 150 x 55 # 1942 Attritional Containment Doctrine
     6180 = 11000 # 200 x 55 # 1944 Assault Breakthrough
     6170 = 8250 # 150 x 55 # 1942 Operational Stages Doctrine
     6200 = 11000 # 200 x 55 # 1944 Branch Interoperability

     6210 = 9000 # 150 x 60 # 1930 Mobility Focus Doctrine
     6220 = 12000 # 200 x 60 # 1937 Spearhead Doctrine
     6230 = 12000 # 200 x 60 # 1939 Delay Doctrine
     6240 = 12000 # 200 x 60 # 1940 Elastic Defense Doctrine
     6250 = 12000 # 200 x 60 # 1937 Schwerpunkt Doctrine
     6260 = 12000 # 200 x 60 # 1938 Blitzkrieg Doctrine
     6270 = 12000 # 200 x 60 # 1941 Kampfgruppe Doctrine
     6280 = 12000 # 200 x 60 # 1943 Firebrigade Doctrine
     6290 = 12000 # 200 x 60 # 1943 Spearhead HQs
     14090 = 470 # 10 x 47 # 1944 Volkssturm Doctrine
     14100 = 10400 # 200 x 52 # 1947 Modern Blitzkrieg

     6300 = 6000 # 100 x 60 # 1936 Human Wave Doctrine
     14080 = 500 # 10 x 50 # 1944 Guerilla Warfare Doctrine
     6310 = 12000 # 200 x 60 # 1937 Large Front Doctrine
     6330 = 12000 # 200 x 60 # 1940 Deep Operations Doctrine
     6320 = 12000 # 200 x 60 # 1941 Pocket Defense Doctrine
     6340 = 12000 # 200 x 60 # 1941 Defense in Depth
     6350 = 12000 # 200 x 60 # 1941 Large Formation SOP Doctrine
     6360 = 10000 # 200 x 50 # 1943 Breakthrough Priority Doctrine
     6370 = 10000 # 200 x 50 # 1943 Movement Speed Offensive Doctrine
     14060 = 10000 # 200 x 50 # 1946 Mechanized Wave

     14000 = 5000 # 100 x 50 # 1936 Hospital
     14010 = 5000 # 100 x 50 # 1938 Hospital
     14020 = 5000 # 100 x 50 # 1941 Hospital
     14030 = 5000 # 100 x 50 # 1945 Hospital
     14040 = 5000 # 100 x 50 # 1950 Hospital

     7170 = 590 # 10 x 59 # 1944 Nuclear Waste Bomb
     7180 = 630 # 10 x 63 # 1944 Semi-Fission Bomb
     7190 = 700 # 10 x 70 # 1945 Fission Bomb
     16010 = 700 # 10 x 70 # 1948 Miniaturized Fission Bomb
     16020 = 720 # 10 x 72 # 1951 Fusion Bomb

     7270 = 5300 # 100 x 53 # 1949 Surface-to-Air Missile (SAM)
     7260 = 530 # 10 x 53 # 1951 Air-to-Surface Missile (ASM)
     7200 = 630 # 10 x 63 # 1948 Capital Ship Nuclear Propulsion
     7210 = 630 # 10 x 63 # 1948 Screening Ship Nuclear Propulsion

     7140 = 8550 # 150 x 57 # 1941 Computers
     7150 = 9300 # 150 x 62 # 1943 Computers
     7160 = 3500 # 50 x 70 # 1945 Computers
     16000 = 3500 # 50 x 70 # 1948 Computers
     7250 = 5000 # 100 x 50 # 1944 Weather Forecast
     7290 = 5500 # 100 x 55 # 1946 Weather Forecast

     7240 = 690 # 10 x 69 # 1951 Air Cavalry
     16030 = 600 # 10 x 60 # 1951 Intercontinental Bomber
     7330 = 920 # 10 x 92 # 1937 Super-Heavy Railway Artillery

     7010 = 12400 # 200 x 62 # 1941 Rocket Interceptor
     7020 = 12800 # 200 x 64 # 1943 Rocket Interceptor

     7100 = 630 # 10 x 63 # 1941 Flying Bomb V1
     7110 = 630 # 10 x 63 # 1942 Flying Rocket V2
     7120 = 670 # 10 x 67 # 1944 Ballistic Missile
     7130 = 710 # 10 x 71 # 1951 ICBM
     7300 = 640 # 10 x 64 # 1956 Simple Satellite
     7310 = 670 # 10 x 67 # 1958 Basic Reconnaissance Satellite
     7320 = 700 # 10 x 70 # 1959 Reconnaissance Satellite Network

     7050 = 620 # 10 x 62 # 1945 Turbojet Carrier Air Group
     7280 = 570 # 10 x 57 # 1948 Turbojet Carrier Air Group

     8010 = 500 # 10 x 50 # 1936 Decisive Battle Doctrine
     8020 = 500 # 10 x 50 # 1937 Naval Firepower Doctrine
     8030 = 500 # 10 x 50 # 1937 Fleet Auxiliary Carrier Doctrine
     8040 = 500 # 10 x 50 # 1937 Fleet Auxiliary Submarine Doctrine
     8050 = 500 # 10 x 50 # 1937 Convoy Sailing Doctrine

     8070 = 500 # 10 x 50 # 1938 Fleet-in-Being Doctrine
     8120 = 500 # 10 x 50 # 1939 Battlefleet Concentration Doctrine
     8100 = 500 # 10 x 50 # 1939 Subsidiary Carrier Role Doctrine (2 other copies!)
     8130 = 500 # 10 x 50 # 1939 Hunter-Killer Group Doctrine (1 other copy!)
     8310 = 500 # 10 x 50 # 1939 Floating Fortress Doctrine (2 other copies!)
     8190 = 500 # 10 x 50 # 1940 Naval Attrition Doctrine
     8090 = 500 # 10 x 50 # 1939 Indirect Approach Doctrine (2 other copies!)
     8110 = 500 # 10 x 50 # 1939 Carrier Task Force Doctrine (1 other copy!)
     8160 = 500 # 10 x 50 # 1939 Trade Interdiction Submarine Doctrine (2 other copies!)
     8330 = 500 # 10 x 50 # 1944 Maritime Power Projection Doctrine
     8340 = 500 # 10 x 50 # 1944 Floating Airbase Doctrine
     8240 = 500 # 10 x 50 # 1943 Carrier Aviation Doctrine (1 other copy!)
     8200 = 500 # 10 x 50 # 1941 Commerce Defence Doctrine
     8250 = 500 # 10 x 50 # 1942 Escort Carrier Role Doctrine (1 other copy!)
     8140 = 500 # 10 x 50 # 1942 Aerial Convoy Defence Doctrine (1 other copy!)
     8260 = 500 # 10 x 50 # 1943 Integrated Convoy Defence Doctrine

     8060 = 500 # 10 x 50 # 1938 Base Strike Doctrine
     8180 = 500 # 10 x 50 # 1940 Indirect Strike Doctrine
     8230 = 500 # 10 x 50 # 1940 Deep Operations Doctrine
     8170 = 500 # 10 x 50 # 1939 Unrestricted Submarine Warfare Doctrine (1 other copy!)
     8320 = 500 # 10 x 50 # 1943 Massive Strike Doctrine
     8270 = 500 # 10 x 50 # 1944 Fleet Train Doctrine
     8350 = 500 # 10 x 50 # 1944 Carrier Warfare Doctrine
     18000 = 500 # 10 x 50 # 1947 Carrier group doctrine
     18010 = 500 # 10 x 50 # 1952 Amphibious Operations Doctrine

     8080 = 500 # 10 x 50 # 1938 Sealane Interdiction Doctrine
     8150 = 500 # 10 x 50 # 1939 Raider Patrol Doctrine
     8210 = 500 # 10 x 50 # 1940 Commerce Raider Doctrine
     8280 = 500 # 10 x 50 # 1940 Capital Ship Raider Group Doctrine
     8290 = 500 # 10 x 50 # 1940 Wolfpack Doctrine
     8300 = 500 # 10 x 50 # 1942 Advanced Submarine Operations Doctrine
     8220 = 500 # 10 x 50 # 1940 Decisive Interdiction Doctrine

     9010 = 5250 # 150 x 35 # 1933 Air Superiority Doctrine
     9020 = 5250 # 150 x 35 # 1936 Flying Circus Doctrine
     9030 = 5250 # 150 x 35 # 1936 Force Substitution Doctrine

     9040 = 250 # 10 x 25 # 1936 Battlefield Destruction Doctrine
     9050 = 250 # 10 x 25 # 1937 Dive Bombing Doctrine
     9060 = 250 # 10 x 25 # 1938 Direct Ground Support Doctrine
     9070 = 250 # 10 x 25 # 1938 Bomber Veteran Initiative
     9080 = 250 # 10 x 25 # 1939 Night Strikes Doctrine
     9270 = 300 # 10 x 30 # 1941 Combat Unit Destruction Doctrine
     9280 = 300 # 10 x 30 # 1941 Hunt & Destroy Groups Doctrine
     9290 = 300 # 10 x 30 # 1942 Low Echelon CAS Doctrine
     9300 = 300 # 10 x 30 # 1942 Bomber Ace Initiative

     9090 = 2000 # 80 x 25 # 1937 Operational Destruction Doctrine
     9100 = 1500 # 60 x 25 # 1938 Battlefield Interdiction Doctrine
     9110 = 1500 # 60 x 25 # 1938 Strafing Doctrine
     9120 = 1500 # 60 x 25 # 1938 Logistical Strike Doctrine
     9130 = 2500 # 100 x 25 # 1939 Night Strafing Doctrine
     9350 = 300 # 10 x 30 # 1941 Infrastructure Destruction Doctrine
     9360 = 300 # 10 x 30 # 1942 Infiltration Bombardment Doctrine
     9370 = 300 # 10 x 30 # 1942 Carousel Bombardment Doctrine
     9380 = 300 # 10 x 30 # 1943 Keypoint Bombardment Doctrine
     17010 = 300 # 10 x 30 # 1952 Theater Organization Doctrine

     9140 = 250 # 10 x 25 # 1937 Strategic Destruction Doctrine
     9150 = 250 # 10 x 25 # 1938 Escort Box System Doctrine
     9160 = 250 # 10 x 25 # 1939 Combat-Bombardment Groups Doctrine
     9170 = 250 # 10 x 25 # 1939 Dead Reckoning Bombardment Doctrine
     9180 = 250 # 10 x 25 # 1939 Night Bombardment Doctrine
     9430 = 300 # 10 x 30 # 1942 Mass Destruction Doctrine
     9440 = 300 # 10 x 30 # 1942 Escort Relay System Doctrine
     9450 = 300 # 10 x 30 # 1942 Carpet Bombing Doctrine
     9460 = 300 # 10 x 30 # 1943 Flying Armada Doctrine
     17000 = 300 # 10 x 30 # 1947 Integrated offensive doctrine

     9190 = 6000 # 200 x 30 # 1939 First Strike Doctrine
     9200 = 4500 # 150 x 30 # 1939 Dispersed Fighting Doctrine
     9210 = 4500 # 150 x 30 # 1939 Frontal Missions Doctrine
     9220 = 5400 # 180 x 30 # 1939 Fighter Veteran Initiative
     9310 = 6000 # 200 x 30 # 1942 Offensive Fighter Box doctrine
     9320 = 4500 # 150 x 30 # 1943 Fighter Baiting Doctrine
     9330 = 4500 # 150 x 30 # 1943 Dogfight Experiment Doctrine
     9340 = 5400 # 180 x 30 # 1943 Fighter Ace Initiative

     9230 = 6000 # 200 x 30 # 1939 Perimeter Defence Doctrine
     9240 = 4500 # 150 x 30 # 1939 Formation Fighting Doctrine
     9250 = 4500 # 150 x 30 # 1940 Home Defence Doctrine
     9260 = 4500 # 150 x 30 # 1940 Recon Skirmisher Doctrine
     9390 = 6000 # 200 x 30 # 1942 Defensive Fighter Box Doctrine
     9400 = 4500 # 150 x 30 # 1942 Multi-altitude Group Doctrine
     9410 = 4500 # 150 x 30 # 1943 Filter Room System Doctrine
     9420 = 4500 # 150 x 30 # 1943 Air Reserve Doctrine
   }
}

would be imported from the AI files. This actually is from the default ai file intended for 1.11, it is meant for a nation with 2 tech slots. This list contains all techs of vanilla AoD. All other ai files would only contain changes relative to the default file in order to avoid "maintenance hell" as Lennartos put it.

Whenever at the start of a day a free tech slot can be used for every available tech team for every researchable tech it is remembered which combinations scores best at

Code:
score = [value] x [historical date modifier] / [research time including ministers and ideas but excluding historical date modifier]

That combination will be used for actual research. Excluding the historical date modifier will simplify calculating the estimated research time. Using only the historical date modifier at the start of the research will make AI discriminate more strongly by the historical date modifier. Teaching AI to appreciate historical date modifier seems rather important.

One of the effects of this approach is that available tech teams and ministers will influence the research strategy of AI. Identical imported research sections of an AI file might result in very different research strategies as AI will optimize for its strenghts. I image an alliance of AIs exchanging blueprints could utilize it relativly well.

The values could also be divided by say 50 and be reused as trading values of blueprints. There is a slightly different approach that does not share this advantage but may require less effort from modders adapting their modifications to the new approach.

2.) Instead of importing the value(8000 for 1918 Inf) the value_dbed(200 for 1918 Inf) would be imported. The calculation of value would be done by the game by multiplying value_dbed with the effective difficulty(40 for 1918 Inf) of a tech. That is 2+max(difficulty, 3) for each component and twice that value if double_time=yes.

If no value_dbed had been defined in the ai file a default value of 100 could be used. That means that any tech not set to be essentially ignored might be researched. Personally i prefer a low value_dbed of 10 as most technologies will never be researched by most nations due to lack of research capabilities. But for vanilla AoD that would be done via the ai files anyway, therefore it is not relevant for vanilla AoD and what is more convenient for modders would seem to be the paramount concern.

3.) Another option is to keep the current approach despite its flaws and only make it slightly less flawed by taking into account all the techs of a research field. So if 25 naval techs have been researched, 2 are already being researched and the question if another one should be researched it will be calculated with 25+2+1=28 instead of 25 like now. This would help in the early years against absurd high priority for fields with no tech researched yet and later it will help to avoid researching very many techs of one field in parallel and thus exceeding the amount of suitable tech teams.


I clearly prefer the first approach, but switching to the second would probably be not too much of an hassle either. Keeping the current approach however seems like a bad idea. What is your take on it?

Edit: I have changed my entries to use value and value_dbed instead of priority and priority_modifier to reflect what 1.11 is intended to use.
 
Last edited:
  • 1
Reactions:
My general stance is that the AI should utilise as much information as it has and as much information as it can, within its time constraints, calculate in addition to that.

Informed decisions may not always be smart, but at least they are seldomly stupid.

Note that these are very preliminary thoughts:
The fitness function ought to take into account more parameters of the country itself.
Some items that should probably contribute:
  1. current distribution of unit types
  2. future distribution of unit types
  3. estimated project time
  4. (recursively) important successor technologies
1) and 3) can be calculated directly and need no softcode handle.

2) could be calculated from the ai/military block, iff "relative_build_scheme = yes".
As "relative_build_scheme = no" is very hard to actually work with and cannot at all react to unit losses, I would like to deprecate it in the future anyway.
Still, this is likely the primary benefactor of a softcode handle, which could then of course also be used to set priority arbitrarily.

4) would generally be desired for an AI trying to play optimally, but would also block certain AI patterns that might be desirable ("struggles long with a particular hurdle, then quickly progresses once overcome").
An on/off switch or even a weighting factor (which might be zero) are obvious softcode handles.

I am not actually convinced that the historical date modifier should play a notable role by itself, rather than implicitely through 3), but it might be worth it to easier keep research to historical paths of progress.
If it were to receive its own main term independent (and then ideally excluded) from 3), this does not seem worth a softcode handle, beyond of course the modifier itself.

Then there is the issue of handling technologies, which are not defined (or dominated) by their effect on units.
1) and 2) obviously could be extended to buildings, with the same considerations applying; it would then be necessary to define a conversion function to weight unit-1) and -2) vs. building-1) and -2).
This conversion function should likely involve another softcode handle in form of a factor that allows shifting focus between infrastructure vs. military.

A weight should also be provided for technologies activating a new unit type. 2) can probably be generalised to cover this without changes.

Finally, doctrine technologies might require a weighting term alternative to 1) and 2), unless a suitably generic relation between combat events and unit types could be found - I am currently clueless about how viable that is.
Again, a softcode handle in form of a factor seems desirable, that allows shifting focus between material and theoretic technologies.
- Note that likely the current upgrade backlog can provide a strong indicator here and should probably be used for that.
As to how this might pertain to an eventual file structure:
Code:
technology = {
  # endgoal = { [...] } # have not seen it used ever; can probably be deprecated
  preference = { # provides considerations for 2); should probably change the name

    # 4) alternative 1: simple
    <technology ID> = <weight>

    # 4) alternative 2: explicit switch
    <technology ID> = { <weight>, [no|yes] }
    <technology ID> = <weight> # default

    # 4) alternative 2: explicit weights
    <technology ID> = { <weight>, <weight of successors> }
    <technology ID> = <weight> # default

    [...]
  }
  ignore = { # too handy to remove; ideally technologies should not be
    [...]    # picked if not appropriate and this block would pertain to
  }          # technologies-which-would-normally-be-desirable-but-for-design-reasons-are-not

  # deprecated: will not research ships if does not have or plan to have ships
  # <area of research> = <weight>

  # 4) alternative 1: simple switch
  default_consider_successors = [no|yes]
  # 4) alternative 2: weighting factor
  default_successor_weight    = [0, 2] # [none, twice mine]

  # weighting factor for considerations between
  # building / province improvements vs. unit improvements
  factor_economic_vs_military = [0, 1] # 0: ignore unit improvements while building
                                       #    or province improvements are available
                                       # 1: the reverse

  # weighting factor for considerations between
  # upgrade-inducing vs. passively boosting improvements
  factor_material_vs_theory   = [0, 1] # 0: ignore doctrine improvements while
                                       #    upgrade improvements are available
                                       # 1: the reverse
}

I am not sure why you chose your score as you did. I am more partial to designing the fitness function in such a way that it is
Code:
f : T^n -> R := sum(Ti) for i in [0,n)
where Ti are themselves weak reasoners about some partial aspect, e.g. 1)-4).

If the parameters can be varied enough, a strongly ordering f should be appropriate. If it turns out, however, that most countries in given scenarios usually have a constant research order, ensuring that f only provides a weak ordering seems to be desirable.
- There is neither AI nor replayability in "same procedure as every time".

Mayhap a dedicated priority term could be introduced as a Tn to provide a means to disable research reasoning completely in favour of a purely defined research order.

The individual or some subsets of Ti might have to be normalised into a common co-domain.
 
Last edited:
I am not sure why you chose your score as you did.

The reasoning for that is rather simple. Optimizing for historic date modifier and proper tech teams is what determines the general degree of advancement within a given set of to be researched technologies. Blueprints, test sites and ministers are also relevant, but all that is relevant is included in the score function. With a proper input from softcoding it will deliver optimal results.

If a tech has a very high priority the general degree of advancement can be reduced in favour of having this particular tech a few months earlier. Most notably this is the case for tech that unlocks many other tech like 1940 assemably line experimentation. In that case the effect on the general degree of advancement is not by necessity negative.

Your idea seems to be to reduce the relevance of direct softcoding, to split it up into many subaspects, so that the softcoder will have less effective control. I definitively prefer an approach where the softcoder can easily anticipate the effect of the softcoded input. By reducing the value of a tech into one scalar this is the case. I hate to be at the mercy of a computer who thinks it is smarter than me.
 
But is ease of aquisition really so dominant over actual usefulness that the latter can be omitted?
Furthermore is the softcoder really supposed to calculate the benefits - subject to change - of every possible technology vs. every other viable one for a given timespan?

Can the softcoder deal with e.g. unit losses through desastrous naval battles or even encirclements?
- With the current handles not really.

Should the softcode deal with them?
- Why, if there is already someone good at the required math and having to handle all the required data in realtime precision anyway.
Those who are best suited to the task shall have it.

Concise:
  • The softcoder cannot interject at the time a research slot opens: all their input has to happen beforehand - like a legal law, it must be guiding but be interpreted in context every time it is applied.
  • The existence of a unique precomputable optimal research path is a flaw in the research system. The closer we come to fix this flaw, the greater a flaw research scripting depending on a precomputable optimal path becomes. We'd be coding ourselves in a corner here.
  • Conversely, a system that always selects the same one out of several optimal research paths is flawed, as it makes the optimal path chosen non-optimal by allowing the precomputation of optimal counter-paths. Of course no AI will do so, but players are free to. This hurts replayability unless they house-rule themselves to ignore the obvious advantage.
I hate to be at the mercy of a computer who thinks it is smarter than me.
Should it not really, really be the other way around?

The softcoder is much like a stern parent, who tells their child the rules it shall comply with, before leaving the house and it to its own devices.
- But unlike a child, the AI will of course never break a rule, no matter how sensible it would be. If you tell it not to go outside and the house catches fire, it will dutyfully burn to death with a sense of accomplishment.

There is no country-sharing between player and AI currently, nor is there in-place editing of softcode.
(Well, it does work by saving, quitting, changing and reloading, but it would seem to be more faithful to rather call that killing the old AI and replacing it with a new one; it is not a change but a replacement.)
Under these circumstances, all a softcoder can give to the AI is a plan flawed-by-necessity. I would rather have the plan be flawed-through-incompleteness than flawed-through-inapplicability.

Of course, I cannot claim to have a cure-all. But a systemic simulation can be improved upon on the systemic level, whereas a mere specification of results is at the mercy of external means to obtain said results - means unsynchronised with the actual game and therefore necessarily threatened by obsolescence.

- It would be perfectly possible to define an override for those who really want to shut off the AI and have absolute control. I am very much unconvinced that it would be a smart idea. Control is alluring regardless of result. People with less time, dedication and intricate understanding of the game than you will feel no less attracted by the prospect - and screw it up. The same people could be productive, enriching modders in the time they wasted on their sub-par technology lists, if not lured into the trap. It would not even be their fault to begin with: as was recently criticised, the documentation of the game's in-depth mechanics is spotty, obsolete in large parts and ambiguous. That's not going to change any time soon. People have to acquire the kind of insight you and I take for granted by scientific observation of a black box model considerably more complicated than a video recorder (for which, in a case I remember, it took almost two years to figure out all the accepted IR signals).

... And then there is also the overhead added to a couple of basic tasks definitely not limited to
  • changing a technology's prerequisites
  • [adding|removing] effects for a single unit type from a technology
  • defining a new division and adding effects for it to several technologies (not yet, but projected to be possible)
Why should there be overhead for the modder, if these things might as well have automatic effects on technology selection?

Currently, it is pretty much necessary to provide elaborate technology weighting for the AI to make sensible decisions. I consider this status quo itself flawed as per my argumentation, but as the softcode dealing with that (as well as can be done) is already in place, I also consider it not too pressing to change. The flaw (and it is the very same one) becomes unforgiving though, when it does start to require expansive softcode changes. Even when there is someone available to do them.
The two tasks I concentrate on the most while coding is to prune dead code and to make used code more concise and thence easier to read (I do not shorten expressions that would become harder to read) - it reduces compile times and improves the overview of the project as a whole, and that aids not just myself but also anyone who might come after me. I often rewrite code without changing its functionality, just because it is messy and drawn out. Might always be run over by a tram the next day, and the easier it is to learn the ropes the higher the chance for someone to do so. The setup you propose looks like a large step in the opposite direction to me.
Your idea seems to be to reduce the relevance of direct softcoding, to split it up into many subaspects, so that the softcoder will have less effective control. I definitively prefer an approach where the softcoder can easily anticipate the effect of the softcoded input.
While, at large, I wish to expand the scope of softcoding, I also wish to direct softcoding capabilities to where they have the most profound - not the most raw - impact. Softcode handles should feed values to the AI which have a defined semantical context. "Concentrate more on doctrines than on upgrades" has context. "Technology A is extra important" has not.

Conversely, "concentrate more on doctrines than on upgrades" is largely stable against environmental changes - the technologies picked will differ as appropriate, but the ratio will be maintained as defined. "Technology A is extra important" may change from an objectively great advice into an objectively bad one by as little as changes to a preceeding AI file. The defined behaviour is then not upheld, precisely because no change occurs in the technologies picked: The AI now decides poorly when it should have decided well - an unwanted change.
As AI switches may generally form an undirected graph, this event is rather hard to predict.

Softcode handles should communicate intent.

I am pretty sure that in general handles with direct and obvious effects are overrides - and they override reason too. "Always go head first" will of course translate into "always go head first through the wall" just as well as into "always go head first through a curtain". The latter is sensible, the former is not. An absolute rule is at most as useful as none.

... And of course the softcoder may spend their time far better on important tasks than on the minutiae of technology ordering - especially if, as desired, many possible paths are actually of equal estimated (if not emerging) quality.
 
Last edited:
But is ease of aquisition really so dominant over actual usefulness that the latter can be omitted?

That will depend on the actual ease of the aquistion and the degree of betterness of the alternative. The assessment of both escapes me. As for the approach i suggested i very well understand the consequences, using it in the early phases of 1.11 is very reasonable and on this research the remaining balancing will be based on.

Can the softcoder deal with e.g. unit losses through desastrous naval battles or even encirclements?
- With the current handles not really.

It is possible to change research AI via events similar to events changing the building schemes. But in most cases changing them in any major way does not seem to be advisable. Research requires to plan ahead a few years, its dependence on short term events should be limited.

Should the softcode deal with them?
- Why, if there is already someone good at the required math and having to handle all the required data in realtime precision anyway.

That is a big if. For the foreseeable future of vanilla AoD, namely 1.11 and 1.12, i fail to image how an approach different from mine would benefit AI. For something much farer away from current vanilla AoD, be it Core or a much different official version, that may be different.

Conversely, a system that always selects the same one out of several optimal research paths is flawed, as it makes the optimal path chosen non-optimal by allowing the precomputation of optimal counter-paths.

I wonder how foundated this assumption of small to no variations within the approach i proposed is. The way i see it there will always be a great number of researchable techs whose score will be very close to each other, that will mostly be due to optimizing for historic date modifier. Ideally no tech of year n+1 is researched before the techs of year n are done, more presisely starting the first tech of year n+1 should happen as late as reasonable possible. Ideally up to 10 techs of year n finish about the the same so that up 10 techs of year n+1 start about the same time.

Now, what happens if there are many techs of very similar score? Gaining or losing tech slots a few weeks earlier or later will have some effect, changing ministers will have some effect, gaining blueprints some month earlier or later will have some effect. All that will effect the utilization of tech teams. Currently unused tech teams however will greatly effect score. Thus i anticipate a great deal of variation.

The two tasks I concentrate on the most while coding is to prune dead code and to make used code more concise and thence easier to read (I do not shorten expressions that would become harder to read) - it reduces compile times and improves the overview of the project as a whole, and that aids not just myself but also anyone who might come after me. I often rewrite code without changing its functionality, just because it is messy and drawn out. Might always be run over by a tram the next day, and the easier it is to learn the ropes the higher the chance for someone to do so. The setup you propose looks like a large step in the opposite direction to me.

That would seem to be a matter of where one starts. Compared to the status quo my proposal is a lot simpler. Instead of 3 tables and 9 weighting factors only 1 table would be importated. The afghanistan file was reduced from 2165 lines to 1039 lines. That way everything is easily interpreted from reading the ai file.
 
Ideally no tech of year n+1 is researched before the techs of year n are done, more presisely starting the first tech of year n+1 should happen as late as reasonable possible.
Wait, is that optimal? I have not played vanilla in ages, but I am fairly sure that it was not optimal in HoI:A and in CORE it certainly is not optimal for almost all countries (only case where it is are low-development, large IC countries such as unified China... as a matter of fact, I think CHI is the one single country where this were optimal in CORE)!
The afghanistan file was reduced from 2165 lines to 1039 lines.
I had a quick look at the file I bundled into 1.10 and it does look woefully overspecified. ... Well, actually most of the lines are comments.
  • 1662 lines in total
  • 9 lines of tech group priorities - We are in consensus about their fate.
  • 1034 lines of comments - There is more comment than code here, seriously!? They are not even useful when using an editor with search-in-files functionality.
  • 417 lines of technology IDs - Many of these in the ignore block are redundant though: 5/9 groups are set to zero and techs from those will not be picked.
  • 211 lines of syntax and empty lines - As the empty lines are a formatting help, their number would dwindle with the number of comments and redundant technology IDs.
This abundance of code is no indicator for a limitation of the game. It was a conscious decision of a softcoder to bloat the code like this.

A decision I would have never made, but mayhap that's just me. We have a lot of files in CORE as well, where commented out code is supposed to provide context for easier manipulation. Most of it is now horribly obsolete due to lack of maintenance and that will never change, as the manpower for such cosmetic tasks is absent, while the free availability of powerful editors reduces the usefulness of such designs towards the questionable. When I come across them in a file I am working with, I delete them after cursory examination - and it improves readability considerably, appreciably. There is such a thing as too much.

This leaves us at a conservative estimate of
  • 9 (as long as they exist, they are necessary)
  • + 417 * 2/3 (assuming equal distribution of meaningful code between the three sub blocks)
  • + 417 * (9 - 5) / (3 * 9) (assuming equal distribution of ignored techs between the tech groups)
  • + 200 (rounding down the number of syntactical lines to the full hundred)
a total of 585 lines.

We could probably shave off more, considering that the sheer number of priority techs looks fishy to me - apart from being redundant with the endgoals - but I would have to investigate more about the vanilla setup than I can currently affort time for. This has been a purely technology-agnostic review so far and already almost 65% of the lines are gone. There are 1077 lines worth of comments and empty lines available until breaking even.
 
Last edited:
Wait, is that optimal?

It is optimal in terms of the general degree of advancement within a given set of to be researched technologies.

I have not played vanilla in ages, but I am fairly sure that it was not optimal in HoI:A and in CORE it certainly is not optimal for almost all countries

The relevant difference between Armageddon and AoD would be that AoD introduced a historical date modifier for past historic date. For Armageddon the same logic would apply while historic date modifier does apply, but the point probably is that it often does not apply.

If CORE also uses historical date modifier past historical date, than the same logic like in vanilla AoD would seem to apply. One important difference might be that the total of technologies sensible to be researched might be greater compared to research capability. In that case the degree in which the historical date modifier influences optimal research is lower, but still significant.

1034 lines of comments - There is more comment than code here, seriously!?

Well, i prefer to have those tables to be complete. That way for changing the code one only needs to uncomment entries or put them into comments. Incomplete entries like before 1.09 i consider a bad example of softcoding. All that of course is within the logic of a fairly stable tech tree like in vanilla AoD. If the rules of a game are often changed it makes it harder to adapt AI to it. If however the rules are stable like at chess, than AI can do some amazing things.

We could probably shave off more, considering that the sheer number of priority techs looks fishy to me - apart from being redundant with the endgoals - but I would have to investigate more about the vanilla setup than I can currently affort time for.

This is not quite redundant. The combination of endgoal and preference grants techs a much higher priority than only one of them. That way i tried to get the best out of the given system that i could.

417 lines of technology IDs - Many of these in the ignore block are redundant though: 5/9 groups are set to zero and techs from those will not be picked.

Also that is not entirely superfluous. The weighting factors of the 9 groups are meant to equal the amount of unignored techs until year 1945 in that group. The better solution would have been to abandon the weighting factors, but that was not available.

This abundance of code is no indicator for a limitation of the game. It was a conscious decision of a softcoder to bloat the code like this.

Surely it was, but that this decision would bloat it much more than needed was the result of the limitations of the game. Good game design minimizes the amount of sensible bloating.

If only 1 instead of 3 sub blocks were to be used it is much more elegant. The endgoal block becomes irrelevant by giving each tech a priority and the ignore block becomes obsolete by allowing priority to be zero. Only techs with positive priority should be considered for research.
 
Things that are obvious are usually only obvious after doing the math. So let us do some math. Assume that there are 2 techs and prior to rounding each component takes 39.5 days to complete if historical date modifer was 1. That is 200 days per tech due to rounding. One tech is of year 1937, the other of year 1938. Research starts in 1936.

In scenario A the tech are researched in the proper order:
Tech1 Component 1 takes 60 days to complete at historical date modefier 0.640 to 0.699.
Tech1 Component 2 takes 55 days to complete at historical date modefier 0.700 to 0.754.
Tech1 Component 3 takes 51 days to complete at historical date modefier 0.755 to 0.805.
Tech1 Component 4 takes 48 days to complete at historical date modefier 0.806 to 0.853.
Tech1 Component 5 takes 46 days to complete at historical date modefier 0.854 to 0.899.

Tech2 Component 1 takes 69 days to complete at historical date modefier 0.540 to 0.608.
Tech2 Component 2 takes 62 days to complete at historical date modefier 0.609 to 0.670.
Tech2 Component 3 takes 57 days to complete at historical date modefier 0.671 to 0.727.
Tech2 Component 4 takes 53 days to complete at historical date modefier 0.728 to 0.780.
Tech2 Component 5 takes 50 days to complete at historical date modefier 0.781 to 0.830.

That totals 551 days for 2 techs. In scenario B the 1938 tech is researched first:

Tech2 Component 1 takes 117 days to complete at historical date modefier 0.280 to 0.396.
Tech2 Component 2 takes 90 days to complete at historical date modefier 0.397 to 0.486.
Tech2 Component 3 takes 76 days to complete at historical date modefier 0.487 to 0.562.
Tech2 Component 4 takes 67 days to complete at historical date modefier 0.563 to 0.629.
Tech2 Component 5 takes 60 days to complete at historical date modefier 0.630 to 0.689.

Tech1 Component 1 takes 37 days to complete at historical date modefier 1.050 to 1.086.
Tech1 Component 2 takes 36 days to complete at historical date modefier 1.087 to 1.122.
Tech1 Component 3 takes 35 days to complete at historical date modefier 1.123 to 1.157.
Tech1 Component 4 takes 34 days to complete at historical date modefier 1.158 to 1.191.
Tech1 Component 5 takes 33 days to complete at historical date modefier 1.192 to 1.224.

That totals 585 days or 6.2% more. I must admit i estimated something far worse. It still makes sense to order techs by historic year, but the argument is not very strong and it gets weaker when starting less ahead of time.
 
I'll try to scavenge some time for a more expansive answer tomorrow. Two short notes:

A) We're getting closer. Consensus on the (syntax of the) priority block. I think I can agree on the ignore block as well: Priority 0 may as well be used as a special value disabling research regardless of implementation otherwise; it would then seem better to keep all listed technologies in a single block.

B) You seem to be optimising an ivory tower scientist. My assumption is that at times one particular single technology is more useful to acquire next than several others, even if the sum of the latter's research time equaled that of the former.
A (too) simple example: Country X has a lot of submarines and submarine techs are cheap - it is now sensible to research submarine technologies. X also has an equal number of tanks but available tank techs are expensive. Due to cheaper submarine techs it is sensible to prefer submarine techs over tank techs.
X then loses many submarines within a short timeframe and now has more tanks than submarines. The relative merit of submarine techs vs. tank techs is now no longer as clear cut, as more tanks benefit from one tech than submarines. The ratio of submarine research time to tank research time now has to be normalised on the ratio of submarines to tanks to express a meaningful fitness.
 
In that specific case the direction of the change in ideal priority may be the other way around. If many subs have been lost, than a technology enabling to build better subs becomes more valueable as more subs are going to be produced to replace losses. Other cases may be subject to similar intricacies.

B) You seem to be optimising an ivory tower scientist. My assumption is that at times one particular single technology is more useful to acquire next than several others, even if the sum of the latter's research time equaled that of the former.

That should be a deliberate change relative to an optimal research scheme. It is a deliberate sacrificing of general progressiveness in favour of a particular tech, a gamble if you will. That can make sense, certainly 1937 tools and 1938 tools do deserve high credit while resources and ic are short. Also interceptors and infantry deserve high credit for most countries including germany albeit ideally it does not build infantry, but it should grant blueprints to its allies.

What seldomly makes sense is to increase value so much that less adequate tech teams are used. Unexpected to me it even makes sense to tolerate worse historical date modifier if that optimizes for better teams. Still i doubt that it would make sense to change the score function as historical year does still supply a good mechanism to determine the order of techs, especially as tolerating bad historic date modifier means that a scarce tech team might be blocked from working at other projects.

What is your stance on the score function itself? The value used as input for it can

A) be directly imported from the ai file,
B) be calculated by multiplying an imported value_dbed with the effective difficulty or
C) as you seem to suggest be calculated in an even more automated manner.

Which one is used is not at the core of my suggestion. The idea is that value only becomes decisive in those cases that with same historic year would use the same team. In those cases a more finetuned order needs to be established.

It may make sense to calculate priority like this:

value = [effective difficulty] x value_dbed x ((1 - c) + c x [automated fitness function])

Automated fitness function and c would be in the range between 0 and 1. For vanilla i might use a low value between c=0 and c=0.3. In vanilla the imported value_dbed would be dominant, at least until i trust the automated fitness function will do better than i could.

Mods however could use c=1 and leave priority modifier undefined so that the default value of 100 would be used for it.
 
Last edited:
Change certainly but hardly progress.

Let's see if I can order my thoughts, in flux as they may be...

Syntax

While originally I wanted to avoid it, I grow more partial to defining special symbols for special intent.

E.g. it would be good to have a value to discard a priority of a single technology. 0 comes to mind as an obvious choice: It is the neutral element of addition and intuitively binds to absense of a value: "Priority of zero" equals "no priority".

Yet, there should also be a way to hard-disable a certain technology. For any system, whereof the priority is a mere part, it is non-trivial to ascertain the lower bounds - if they exist - of low-but-valid priority. This, however, should not be a task for anyone to actually do. A magic number is the adequate solution, but said magic number has to be outside the interval of ordinary values, so again the lower bound has to be calculated to be sure, and it has to be a hard bound.
- Again, 0 comes to mind as the neutral element of addition.

This is a conflict between usability cases - both, different cases are unrelated to the formulaic calculation. Allowing for one of the cases (I prefer the latter) e.g. the string "no" as a value would solve this.

Once such a use case were established, it would thenceforth be customary to allow such non-numeric tokens for "extraordinary" behaviour in numeric fields. I am not yet sure whether this is an elegant solution to go for, as e.g. these tokens would obviously compete with the established use of extra non-numeric fields within the same block, such as military/relative_build_scheme ; yet the latter cannot apply to this issue well, as they always change the meaning of whole blocks, not individual entries.

... As you can see, this is a line of thought mostly orthogonal to our discussion. I would like to figure it out for the sake of implementation details, and to help formulate a general strategy for extending soft code interfaces.

Semantics

We started this discussion with orthogonal motivations: You want values with absolute meaning "this is bad/good to pick", I want values pertaining to a certain question the AI has to and probably cannot answer "from beyond your understanding, this is an additional weight to your decision".

We both want a single numeric value.

Now, depending on what it is meant to signify our requirements on that value differ: I want it to never dominate the whole term. You want it to always dominate it. Both calls for different architecture of the term.

E.g. for your purpose, and as per your initial proposal, the value should be a factor on the highest level of contributors. That way, the natural range of values would be in N, with 0 disabling the technology so weighted naturally.

For my purpose, having the value be a summand is better. Dominance has to be normalised away, but that might be necessary for other internally calculated contributors just as well, so this is a small nuisance. As per my initial proposal, contributors might be chained into a convenient sum.

... Now, it was rather late that it occured to me that a purely mathematical solution might just not be what is called for. Formulas are notoriously bad at representing algorithms, and mayhap this is more of an algorithmic and less of a formulaic problem than I initially thought. For a start: we may easily have both implementations and a switch such as the aforementioned military/relative_build_scheme . It would not be sensible to try mixing the same meanings within the same block, whereas the syntax of the block is unchanging between the variants.

Of course, this is somewhat lacking in the elegancy department. Redundant work, and as I noted, a strong, persisting lure to bait the unsuspecting modder onto the perilous path to try and find the definite optimal order for each and every technology by themselves, notwithstanding that changes in far flung places may invalidate the quality of any precalculated order as they occur.

You correctly pointed out that I cannot just conjure up a superior AI out of thin air (well, actually that is mostly what happens, but it takes a lot of time I do not have). I have noted myself that even in cases where a definitely optimal order were calculated by the AI for the sake of historical accuracy there has to be a way to force it away.

Timing

The main issue I am already aware of - I have a feeling that there may be others I have not yet identified as such - is certainly, that a means to discard much of the internal logic in favour of an easily controlled simple equation producing an easily predetermined sequence, would currently be superior to the implementation at hand - which does little else, really, but in a unnecessarily convoluted way not allowing for the desired control - so its availability would create pressure to use it over the built-in variant. But if indeed most people - of the few there are - adopted the manual control approach, who would then switch back to the built-in method once it reached theoretical - but inherently less observable - superiority?

Switching to a human-dominated calculation would certainly require to review all the technology entries of all the countries. You have shown willingness to do so, others will eventually as well. But then, to ever switch back will of course mean to again review the whole batch of them, and the working assumption that all technologies with explicit priority will automatically have higher priority than all without would ascertain that virtually no entry could match in that second switch. Yet, as the syntax is the same, as soon as one person drops their conversion work and does not leave detailed documentation about which values they had processed and which not, the only valid way for anyone to pick it up and complete it is to discard everything and start over; ... that is actually not too bad, as the working assumption of the built-in method would of course be that most technology do not require nor gain an explicit priority. - But this means that the best way to switch would entail to discard all the implicit knowledge won while crafting the prior entries; would it then not be very tempting to just remain with what works, even if it required vastly more maintenance? Such developments are hardly unheard of in the software world.

In the face of all that, we have the status quo with a system that works, if badly, and may be gradually improved towards my goal in time, largely (I hope; not 100% sure on that) without necessary softcode changes (other than switching format around the actual entries and later removing entries, scaling remaining entries, operations viable to be applied via automated tool). No matter what we draw up eventually, work on the system can only be done gradually due to time constraints. This contrasts starkly, and not in a flattering way with a tool "as good as you yourself can make it". Thence I myself would rather put up with the status quo and improve known weaknesses piece by piece, as they are identified (and admittedly: as I feel like it). A rather big problem here, and with pretty much all improvements on the original, is sadly that before actual improvement can happen, a quite extensive cleanup effort on the code has to be made, which does not necessarily change user experience at all. Indeed, the absolute largest part of my coding efforts so far have - intentionally - had 0% visibility to the outside.

... But I guess I am just whining at this point. No matter how it goes, it would be comfortable for me not to tackle the implementation until after 1.11. I have quite a few irons in the fire already.

Misc

What is your stance on the score function itself? The priority used as input for it can

A) be directly imported from the ai file,
B) be calculated by multiplying an imported priority modifier with the effective difficulty or
C) as you seem to suggest be calculated in an even more automated manner.

Which one is used is not at the core of my suggestion. The idea is that priority only becomes decisive in those cases that with same historic year would use the same team. In those cases a more finetuned order needs to be established.
I think this is missing something. E.g. in some cases, it might be that a good team is free for current or overdue techs, which a country should want to research - but the next free slot should still go to another team on another technology, usually because the effect is more pressing (activation of a new unit type, non-absolute focus on a certain arm of the military).

Currently this is approximated via the weights on technology group, but we both want to get rid of those. So, this too is a responsibility of priority.
Code:
priority = [effective difficulty] x [priority modifier] x ((1 - c) + c x [automated fitness function])
That has a couple of issues. For one, we need the modifier (I referred to it as "value" earlier) on both sides, just like the difficulty. Weighted parts of the function would always be evaluated, even if c were 0 or 1. As noted before in "Semantics", I also do not think it is sensible to mix the different approaches, so values (0, 1) should be invalid anyway. At that point a good old if/else can do this just fine, at the benefit of branch predition (assuming that the balance of countries using either method is sufficiently different from 0.5).

An additional parameter c, especially when it is used for weighting on top of another parameter, also makes it significantly harder to predict the effect of a change - parameter hierarchies are generally a somewhat bad idea, I'd say.
 
I think this is missing something. E.g. in some cases, it might be that a good team is free for current or overdue techs, which a country should want to research - but the next free slot should still go to another team on another technology, usually because the effect is more pressing (activation of a new unit type, non-absolute focus on a certain arm of the military).

Currently this is approximated via the weights on technology group, but we both want to get rid of those. So, this too is a responsibility of priority.

To some degree it is. More pressing techs have a higher value_dbed. But the general idea is still to strongly favour those techs, whose relative research time is low due to matching teams and historical date modifier. The score function is intended to dominate over value_dbed.

That has a couple of issues. For one, we need the modifier (I referred to it as "value" earlier) on both sides, just like the difficulty. Weighted parts of the function would always be evaluated, even if c were 0 or 1. As noted before in "Semantics", I also do not think it is sensible to mix the different approaches, so values (0, 1) should be invalid anyway. At that point a good old if/else can do this just fine, at the benefit of branch predition (assuming that the balance of countries using either method is sufficiently different from 0.5).

An additional parameter c, especially when it is used for weighting on top of another parameter, also makes it significantly harder to predict the effect of a change - parameter hierarchies are generally a somewhat bad idea, I'd say.

A hard on/off switch will do. In fact for 1.11 it would be completely sufficient to only allow "use_automated_fitness_function = no" and not care about the automated fitness function for quite some time. But to include a severely better research AI seems an important improvement for 1.11 vanilla. It seems wrong to make 2 consecutive patches that while changing many things within the engine add almost nothing to Vanilla. From what i can tell the needed hardcoded changes for the new research AI are not too time consuming. It is better to let the development of 1.11 take a few additional weeks(?), than to publish it without substantial improvements.
 
Last edited:
Well, 1.11 is not done by quite a large margin. Neither of my minimal goals:
  • free Area+Region+Continent definition
  • improved AI fleet handling
  • SDL2 graphics rendering
are close to finished.

Especially the latter should be seen as quite a large contribution to vanilla, I dare say: What good is a setup, if players cannot even run the game!

As I am mostly occupied with my Master's thesis right now, I shy from doing large scale modifications at the moment. The benefit, at least somewhat tangible, I would like to think, are many small changes which, hopefully, are objective improvements. Bug fixes are of course objectively good. Minor improvements, even if small nothings for themselves, eventually stack up to the shape of great progress.

... But we seem to be pretty done with the details. I would have liked some more input from third parties, but it cannot be helped.
Let me summarise the new syntax, just to be sure:
Code:
technology = {
  <tag to switch the fitness function> = [no|yes]
  preference = {
    <tech ID> = [<signed integral>|no]
  }
}
With the following effects of entry "T = P":
  • "T = no" will make the AI only research T if all available techs are marked "no" as well (like ignore block does now, but slightly more permissible).
    • In this case, the choice among affected technologies will happen as if "P = 0" for all of them.
  • "T = 0" will be the neutral preference shared with all not-listed techs.
    • T will then be treated as if it had never been listed in the first place, including with "T = no".
  • For the purpose of this simple scheme, only natural numbers will be considered for P (but I want negative P for later).
I would like to find a fitting name for the switch tag, but that has time until 1.11 enters beta - it can be changed by search&replace without effort.

That leaves the fitness function. I do not think I want to use this mode myself, so if your draft is what you wish for, you may get it.

The priorities you show as example are of orders 10^[2, 4].
The historical date modifiers are of orders 10^[-3, -4] (sampling current vanilla and CORE setups).

What range should the research time be in? Note that internally, it is a date, a multi-value object. I have to convert it to some single value (time in days, mayhap).

Note that for different difficulties, different priorities may or may not be dominated away. Using this looks like a nightmare come true to me, but if you really, really want to, you shall have it.
"Let every man seek [hell] in his own fashion", and all that.
 
Last edited:
Do you really want to reuse "preference"? That term is already in usage.

  • "T = no" will make the AI only research T if all available techs are marked "no" as well (like ignore block does now, but slightly more permissible).
    • In this case, the choice among affected technologies will happen as if "P = 0" for all of them.

A hard ignore function may be better, some techs have negative effects like guerilla warfare doctrine for organisation of infantry. A soft ignore function is best done by value_dbed = 10. It essentialy means to only research it if all other techs suffers from the worst historical date modifier possible.

I would like to find a fitting name for the switch tag, but that has time until 1.11 enters beta - it can be changed by search&replace without effort.

How about "smart_ai = [no|yes]"?

The priorities you show as example are of orders 10^[2, 4].

That is for the case for priority as one of the inputs for the score function. My initial suggestion was to import value directly from AI files, but probably it is more convenient for softcoding to import value_dbed and calculate value by the gameengine. Which of those 2 methods will be used was the main question i hoped to answer with this thread.

value_dbed would be in the order 10^[1,2], value_dbed = 100 the fallback value indicating a neutral element.

The historical date modifiers are of orders 10^[-3, -4] (sampling current vanilla and CORE setups).

This seems to be wrong. For Vanilla it is limited to the interval [0.1, 2].

What range should the research time be in?

Excluding historical date modifier the maximum for vanilla would be tech 7330(Railroad Artillery). The effective difficulty is 92, with skill 1 team without matching expertise and no other modifiers(tech etc.) smaller than 1 the maximum research time would be slightly below 1710 days.The minimum research time of one tech component is slightly below 2 days, this is with blueprints and level 10 test size. So for Vanilla the range would be limited to [5,1800] days. I suppose it is best to ignore that in "reality" research times include rounding days up for each component.

In principle both team skill and difficulties of tech components can be increased by multible orders. The game does work for skill = 10000. That seems all very extreme, in practise the order 10^[0,4] days for research time will suffice.

Note that for different difficulties, different priorities may or may not be dominated away. Using this looks like a nightmare come true to me, but if you really, really want to, you shall have it.
"Let every man seek [hell] in his own fashion", and all that.

That is one reason why the calculation of

value = [effective difficulty] x value_dbed

may best be left to the game engine. But for me both variants are fine.
 
Last edited:
Do you really want to reuse "preference"? That term is already in usage.
For now. Could also be called "priority", but the difference is not convincing. That it is already in use only means less work for me.
  • "T = no" will make the AI only research T if all available techs are marked "no" as well (like ignore block does now, but slightly more permissible).
A hard ignore function may be better, some techs have negative effects like guerilla warfare doctrine for organisation of infantry. A soft ignore function is best done by priority modifier = 10. It essentialy means to only reserach it if all other techs suffers from the worst historical date modifier possible.
I do not think it is a problem, as long as most technologies are not "no". In the special case of Guerilla Warfare, if Modern Blitzkrieg is not "no", it will be guaranteed to get picked first and then Guerilla Warfare is disabled.

It might be that a need for a hard ignore does exist. I would like to wait for it to actually arise though. My motivation here has been that e.g. in CORE some countries are locked out from most of the tech tree and may eventually run out of technologies to research. Technologies they should never normally research, e.g. naval ones then become fair play, but of course it would require a switch file with a rather unwieldy and demanding to maintain trigger event.

Instead providing a layer below everything else, a "lowest priority possible" seems to fix that issue fine, at the same time it would seem that clearly negative technologies should not exist in the first place (but edge cases can of course be constructed; currently I am inclined to believe that they would be too complicated to be worthwile to the softcoder for reasons other than not being able to hard-ignore them for certain countries).
I would like to find a fitting name for the switch tag [...]
How about "smart_ai = [no|yes]"?
I was thinking about something a bit more telling about just what it does. Mayhap "consider_effects" or "guess_impact" or something along these lines.

The historical date modifiers are of orders 10^[-3, -4] (sampling current vanilla and CORE setups).
This seems to be wrong. For Vanilla it is limited to the interval [0.1, 2].
Ach, I see. Read the per-day values instead of the bounds.

10^[0, -4] then. That is a pretty wide range.
[...] That is one reason why the calculation of
Code:
priority = [effective difficulty] x [priority modifier]
may best be left to the game engine. But for me both variants are fine.
I was assuming it to be, truth be told. What else is a big calculator good for, if not to calculate.

Alright, then substitute "priority" with "priority modifier" in my design; actually I should have called it "preference", like the block implies, from the beginning.
Hrrch, going to edit that. (addendum: done)

I think for convenience the neutral value for preference should be 0. Of course, that only means we have to do
Code:
priority = <effective difficulty> x (100 + preference)
and the effect will be the same.
 
I do not think it is a problem, as long as most technologies are not "no". In the special case of Guerilla Warfare, if Modern Blitzkrieg is not "no", it will be guaranteed to get picked first and then Guerilla Warfare is disabled.

That might be the case for Volkssturm doctrine, it is not the case for guerilla warfare doctrine in the soviet doctrine tree. Also ignoring the Heavy Subs techs is a common workaround to prevent AI from building the high visibily heavy Subs instead of smaller subs with lower visibility. Anything that differs from the logic higher model = better unit is a problem as AI always upgrades production lines when finishing a unit. Acutually this problem does not exists for subs as an unused model blocks upgrading from SS1945 to heavy Sub 1933.

10^[0, -4] then. That is a pretty wide range.

Are you sure CORE uses such extreme values? Any historical date modifier below 0.1 would not make much a difference any way. As for the score function

[research time including ministers and ideas but excluding historical date modifier]/[historical date modifier]

will be in the range [2.5,20000]. Priority will be in the range [250,20000], but lower or high values could of course be entered. But usually score will be something like 10000/200=50.

I think for convenience the neutral value for preference should be 0. Of course, that only means we have to do
Code:
priority = <effective difficulty> x (100 + preference)
and the effect will be the same.

That seems very inconvenient. Are we talking about the same thing? Using 0 to overwrite any other values for a tech and use the standard value instead is fine with me. But this standard value should be 100. Else for all preference values the softcoder would have to calculate preference = priority modifier - 100 and the readability of the ai file suffers a lot. Now that i think about it 0 as neutral element does not make any sense at all. If all it does is to use the standard value of 100 instead one might aswell use 100 as standard value directly. In terms of human readibility 0 makes much more sense for ignoring a tech.
 
That might be the case for Volkssturm doctrine, it is not the case for guerilla warfare doctrine in the soviet doctrine tree. Also ignoring the Heavy Subs techs is a common workaround to prevent AI from building the high visibily heavy Subs instead of smaller subs with lower visibility. Anything that differs from the logic higher model = better unit is a problem as AI always upgrades production lines when finishing a unit. Acutually this problem does not exists for subs as an unused model blocks upgrading from SS1945 to heavy Sub 1933.
Ah, mixed up techs. You are right. Guerilla Warfare is actually a good example of a technology I always regarded as "wrong", insofar that I would never research it as any country, period.

But I am not the most dynamic player, so it may have its legitimate uses after all?
Are you sure CORE uses such extreme values? Any historical date modifier below 0.1 would not make much a difference any way. As for the score function
Code:
[research time including ministers and ideas but excluding historical date modifier] / [historical date modifier]
will be in the range [2.5, 20000]. Priority will be in the range [250, 20000], but lower or high values could of course be entered. But usually score will be something like 10000 / 200 = 50.
Vanilla, actually, does as well, if I am not mistaken:

A slot may become available at any day. On the second day of year X the historical date modifier of a year X technology will be
Code:
PRE  = -0.001 # Pre-Historical Date Mod
POST =  0.001 # After-Historical Date Mod
PRE_MIN  = -0.1 # _RV_PRE_HISTORICAL_PENALTY_LIMIT_
POST_MAX =  2.0 # _RV_AFTER_HISTORICAL_PENALTY_LIMIT_

<historical date modifier> = max(PRE_MIN, PRE x 0) + min(POST_MAX, POST x 1)
                           = 0.001
                           = 10^-3
After ten days, it would be 10^-2, after one hundred days 10^-1, etc. until it reaches the maximum after two thousand days.

Of course, it would be easy to shift the modifier to a different order, e.g. if we assume the 200 in your example as maximum, moving it up by a factor of 10^2 would fit. If we assume the 200 to be an average value, we may as well move it up by 10^3 (POST_MAX = 2000, POST = 1) and use that.

For the purpose of actual progress, the current value is added to 1.f and multiplied onto the daily gain. But of course the fitness function could do any scaling as convenient.

... Incidentally, looking at the misc.txt file and the code right now, is it not funny how "Pre-Historical Date Mod" and "_RV_PRE_HISTORICAL_PENALTY_LIMIT_" are differently signed?
- I think something is wrong here. Might have made a mistake last time I touched that code, or mayhap the mistake was there all along - will investigate.
That seems very inconvenient. Are we talking about the same thing? Using 0 to overwrite any other values for a tech and use the standard value instead is fine with me. But this standard value should be 100. Else for all preference values the softcoder would have to calculate preference = priority modifier - 100 and the readability of the ai file suffers a lot. Now that i think about it 0 as neutral element does not make any sense at all. If all it does is to use the standard value of 100 instead one might aswell use 100 as standard value directly. In terms of human readibility 0 makes much more sense for ignoring a tech.
I actually do think we may not.

<preference> is the value I expect in the softcode, in block technology/preference, on the right side of an entry:
Code:
technology = {
  preference = {
    <team ID> = <preference>
  }
}
<priority> is the value I expect to order technologies by, to pick the one with highest (arbitrarily between ties).
(Not yet sure whether any actual ordering would take place; as all the modifiers are either - almost always - constant or strictly monotonous, it might be sensible. In the end, no matter how, the technology with highest priority will get the slot.)

As such, it would seem pretty idiomatic to me to assume that 0 equals nothing, that is: no entry; and restores the behaviour of no entry existing.
Any priority assigned would be "more than nothing" and therefore greater the neutral element. 0 as the smallest natural number seems to fit rather well.
It continues to work amiably when extending to whole numbers. Anything below is "less than normal", anything above "more than normal". Again, 0 would restore "just do your thing, add nothing to it".

It seems to be pretty idiomatic in natural language too: "there is zero sense in this" is a valid variant of "there is no sense in this", if of slightly different tone.

Internally, of course there might be a better value for "nothing", but that is an implementation detail: It depends on and would change with the implementation, whereas defining "nothing" as zero creates an invariant.
(Of course we could just as well define it as 100 instead; but then why not choose 1000, or say, Pi? None of these values is inherently special in the realm of basic math, who would on their own suspect either over the others as neutral element?)
 
Last edited:
Ah, mixed up techs. You are right. Guerilla Warfare is actually a good example of a technology I always regarded as "wrong", insofar that I would never research it as any country, period.

But I am not the most dynamic player, so it may have its legitimate uses after all?

It does have its uses. Battle events become more likely. Unless organisation of infantry is deemed paramount researching it makes sense. But for AI organisation of infantry should be deemed paramount.

Vanilla, actually, does as well, if I am not mistaken:

You are. On day one of proper year historical date modifier is 1. 900 days before it is its 0.1, while 1000 days after start of proper year it will be 2.

Code:
PRE_MIN  = -0.1 # _RV_PRE_HISTORICAL_PENALTY_LIMIT_

This one should be 0.1 in misc.txt. The rest seems fine in the sense they are identical to what 1.09 used and worked alright.

<priority> is the value I expect to order technologies by, to pick the one with highest (arbitrarily between ties).

By my termina this would be score. score is calculated from value. value is calculated from value_dbed. Ideally value_dbed is what is imported as preference.

(Of course we could just as well define it as 100 instead; but then why not choose 1000, or say, Pi? None of these values is inherently special in the realm of basic math, who would on their own suspect either over the others as neutral element?)

We could use 1 = 100% as the neutral element of multiplication. value_dbed is proportional to value, the value of a tech if you will. Using 100 instead of 100% is just convience.

Moving things from simple proportionality to linearity complicates things unnecessarily.

0 as the smallest natural number seems to fit rather well.

There are many mathematicans that donnot include zero into natural numbers. But this is really going offtopic.
 
Last edited:
Mmh... I backtracked and found that the historical modifier still works as it did in 1.07. For known unfortunate reasons I cannot lookup whether 1.08 changed anything about it.
Found, where we disagree on its range as well: I have not considered the constant +1 part of it, but you have. For this purpose, the latter seems sensible.

Also recalled what that asymmetry in misc.txt is about: The limits concern the value after adding the constant, the modifiers themselves (of course) do not.
... Will change this so the limit is actually a limit to the modifer, I think, to provide symmetry and not require the modder to know about this implementation detail.

The fitness function of course has to consider implementation details, but it is one itself, so that is fine. Going to just call the same code in both cases, as already happens for the projected date of completion.

By my termina this would be score. score is calculated from priority. Priority is calculated from priority modifier. Ideally that priority modifier is what is imported as preference.
Mmh, I seem to have missed how score is calculated from priority. Thought the latter was just a rename of the former, as the formula's shape remained constant, but the former replaced the latter. Could you post the whole chain from modifier to score?
We could use 1 = 100% as the neutral element of multiplication. Priority modifier is proportional to priority, the value of a tech if you will. Using 100 instead of 100% is just convience.

Moving things from simple proportionality to linearity complicates things unnecessarily.
Ah, I see. Yes, 1 is fine as well. Do you foresee the desire to specify preferences in the interval (0, 1)?
This would then free 0 to have the meaning I proposed for "no", and "no" to be the hard ignore you wish for.

Now, I still think it is more natural - simpler, learned earlier - to count in increments rather than in multiples, but I am fine with doing it this way.
There definitely exists precedent, e.g. in garrison priorities.