taw's blog

The best kittens, technology, and video games blog in the world.

Monday, August 22, 2016

CSS is uniquely impossible to test

Cat by Adrian Midgley from flickr (CC-NC-ND)

Times change. Back when I started this blog ten years ago serious automated testing was something people have generally heard of, but very few actually did. It was very common for even big projects to have literally zero tests, or if they did they were token tests or at best some regression checks.

Then TDD's shaming campaign happened, and it was even more effective than shaming campaigns against smoking, and now not testing is the exception, and most fights are over what kind of testing is most appropriate.

It was mostly cultural change. Ruby or Java were pretty much just as testable 10 years ago as they are now, but underlying technology changed considerably as well. Just some of such changes:
  • Very low level languages like C/C++ where any bug just corrupts memory at random are extremely hard to test - they're far less popular than they used to be (and the ones that still exist usually have nonexistent or very shitty tests)
  • Languages like Perl which didn't even have working equality and had a lot of context dependence are much less popular - Perl was still possible to test, but it was a bit awkward
  • Headless browsers made it possible to reasonably test javascript
  • jQuery and greater compatibility between browsers made cross-browser javascript testing basically unnecessary
  • Web-based user interfaces are far easier to test than most native interfaces
  • Going all web made cross-OS testing unnecessary, and if you really need them VMs are far easier to setup than ever
  • Application logic in database paradigm mostly died out, and much easier to test application logic in application paradigm is clearly dominant now
  • Complex multithreading never got popular, and it's more common to have isolated services communicating over HTTP or other messaging
  • Cloud makes it much easier to replicate production setup in test environment for reliable system-level testing
  • All languages have a lot more testing libraries, so things like mocking network or filesystem communication which used to be massive pain to setup are now nearly trivial.
  • There are now ways to test with multiple browsers at once, even if it's still not quite as simple.
And yet, one technology from dark days before testing is still with us, and shows no sign of either going away or becoming testable. CSS.

Let's just cover a few things which would be difficult to automatically validate, and in theory they ought to be possible to automate, but there are no good ways to do that:
  • Site works with no major glitches on different browsers. Any major difference should be flagged, but what counts as "major" difference would probably need somewhat complex logic in testing library.
  • Site looks reasonable on different screen sizes. There will be differences, and testing library would need to contain a lot of logic to determine what's fine and what's not. Some examples would be maximum/minimum element sizes, no content missing unless specifically requested to be hidden, no content cut by overflow, no horizontal scrollbars etc.
  • All CSS rules in your application.css are actually used. It seems everybody's CSS accumulates leftovers after every refactoring, and with some browser hooks it ought to be possible to automatically flag them.
  • When you do CSS animations, start and end state show what they ought to. Even disregarding transitions. Some kind of assertions like "X is fully visible and not covered by any other element or overflow: hidden", "Y cannot be seen" would be great, but they're not easy to do now.
As far as I can tell there's been minimal progress in ten years. There are some attempts at CSS testing, but their tests are far too low level, don't address real needs, and as a result nearly nobody uses them.

I don't have any solutions. Hopefully over next few years it will get better or we'll replace CSS with something more testable.

Sunday, August 21, 2016

Test coverage in ruby

IMG_5547 by rautiocination from flickr (CC-NC)

In highly dynamic language like ruby it ought to be common sense to aim at 100% test coverage. Any line without coverage can contain any kind of typo or other silliness and crash in production.

Statically typed languages have a minor advantage here, as compile-time type check is sort of a test. Unfortunately it has such a massive false positive rate and incurs such a massive penalty to expressiveness as to make the whole idea of static typing worthless. In early days of computing people seriously expected rich static type systems to be mathematical proofs of various properties of languages, but that went nowhere. Anyway, enough history.

In ruby 100% test coverage - every part of the program being executed at least once by some kind of rudimentary test - really ought to be the minimum goal. Just running the code and verifying that it returns something vaguely reasonable without crashing really isn't that much to ask for.

Unfortunately it seems to be far too common for people to see 100% coverage as some highly ambitious goal, and be satisfied with "good enough" numbers like let's say 80%.

Let's have a talk about all that.

Rails autoloader

A lot of ruby code uses Rails, which uses code autoloading in development for a good reason, but unfortunately it also uses it during testing when it really seriously shouldn't, and someone please submit that as a bug report on an off-change it won't get EWONTFIXed.

This leads to a very nasty situation where simplecov reports that you have 100% test coverage, even though you completely forgot about a bunch of models and controllers. Not loaded means not included in coverage report at all, instead of being big red 0%.

Rails generators will automatically create empty test classes for you, so if you use generators you're going to be somewhat less affected by this problem, but most people end up creating a lot of files manually as well.

Anyway, if you use any kind of Rails project for which you want to get reasonable coverage report, you ought to put something like this in your spec/spec_helper.rb or equivalent, possibly guarded by if ENV["COVERAGE"].present? if you'd prefer to only generate coverage report when explicitly requested:

SimpleCov.at_exit do
  Rails.application.config.eager_load_paths |= Rails.application.config.autoload_paths
  Rails.application.eager_load!
  SimpleCov.result.format!
end

If you do that on existing project, you might be for a big surprise.

0 tests = 50% test coverage

Next time you think 80% coverage is good, try to run coverage report with all tests disabled. You'll probably get a figure around 50% coverage, from zero tests. Let's take a look at this example:

class HelloWorld
  def say_hello
    putts "Hello, world!"
  end
end

In meaningful sense it has only one line of code, third, which also happens to have nasty typo. As far as ruby and simplecov are concerned however, there are three lines, as that code is more or less just syntactic sugar for:

(HelloWorld = Class.new).instance_eval do
  define_method :say_hello do
    putts "Hello, world!"
  end
end

And lines 1-3 are all perfectly executable. Depending on how long your methods are, you'll get something close to 50% test coverage with no test- just from the way ruby works.

That means that "80% coverage" might very well be 60% of actual code, and that sounds a lot less appealing, doesn't it?

ruby -w

I tend to dislike linters, as they mostly tend to enforce authors' misguided ideas on what is proper way to code, and have extremely high false positive rate for finding genuine problems.

For some reason every one of them has some ideas which are not just pointless, they result in actually horrible code. For example rubocop will whine if you use consistent double quotes and will demand awful mix of single and double quotes; and then it will whine even more if you consistently use trailing comma in multiline Array/Hash literals, instead forcing you to write ugly code with even uglier git diffs and pointless merge conflicts. The project should die in a fire, and its authors should feel ashamed of ever publishing such pile of crap.

One simple alternative is to that is checking your program with ruby -w, which has fairly low rate of false positives (whining about system *%W[some --command] is the only one I keep running into a lot), but can still find most simple typos, misindentation, and such.

This kind of analysis is usually not counted as part of coverage report, but is useful supplement.

Error lines

Even in reasonably tested software it is very common to see code which raises exception not covered.

There are two cases which look the same syntactically:
  • errors because something bad happened
  • errors because something supposed to be impossible happened
For example z3 gem had this code in a private method:

  def check_sat_results(r)
    case r
    when 1
      :sat
    when 0
      :unknown
    when -1
      :unsat
    else
      raise Z3::Exception, "Wrong SAT result #{r}"
    end
  end

z3 library is supposed to return -1, 0, or 1, so the whole raise line is just debugging aid and it's rather pointless to test it - but on an off chance gem author messed it up or z3 quietly changed its API, it's better to have this kind of line than just return nil quietly.

On the other hand if the same code was in some user-exposed API, then we should probably be checking that exception happens when we pass unexpected value.

These two situations are semantically different, but syntactically equivalent, so coverage reporter can't tell the difference between the two.

This only gets worse because...

Coverage is by line

So it's very easy to rewrite such one lines of "not covered" into code which doesn't execute but appears green in coverage report. Like this:

  def check_sat_results(r)
    raise Z3::Exception, "Wrong SAT result #{r}" if r > 1 or r < -1
    case r
    when 1
      :sat
    when 0
      :unknown
    when -1
      :unsat
    end
  end

or this:

  def check_sat_results(r)
    {
      1 => :sat,
      0 => :unknown,
     -1 => :unsat,
    }[0] or raise Z3::Exception, "Wrong SAT result #{r}"
  end

Sometimes such code which doesn't get own line looks perfectly natural, other times it feels a bit convoluted.

Unfortunately there's no reason to expect that we'll consistently use this form for "can't happen" errors, but never for "legitimate" exceptions, so we'll have both false positives and false negatives here.

Scripts

Unix scripts, rake files, deploy scripts, and such are left untested so often they're usually not even included in coverage report. I wrote previously about some patterns for testing them, but even then they're not really the low hanging fruit of testing.

Even worse when you actually test your scripts in realistic way by actually executing them, simplecov requires quite a few hoops to jump before it will show code executed via such scripts as covered.

What is code anyway?

Your codebase might contain files which are sort of code, but not completely so, like .haml/.erb files. It's not generally included in coverage reports, even though view logic is as much part of program logic as anything else, and complex views are fairly common, even if people frown at them.

You can move complex logic out of views into models, controllers, and helpers, but even when all that's left is relatively straightforward it would be useful to know it was ran at least once during testing.

Automatically generated code

Metaprogramming is a big aspect of ruby, so it's fairly common for ruby programs to contain a lot of generated code.

It still deserves some kind of at least rudimentary testing, even if tests are generated as well.

Count all kinds of tests together for coverage report

Test coverage scale doesn't go from "no tests" to "great tests", it goes from "no tests" to "probably good enough tests", and it can't distinguish between "probably good enough" (at 100% or close to it) and tests which are actually great.

There's a temptation to check unit test coverage - counting only code tested directly, not "covered" accidentally by some high level integration tests.

That's a clever idea, but small number of high level integration tests can provide a lot of value for relatively little effort, and a lot of code probably doesn't deserves much more testing than that.

Excessive number of low-level tests would not only be slow to write, but they'd need constant updates every times something gets refactored.

It's a red flag if code you expect to run on production doesn't get run even once during your tests, but you should leave yourself flexibility on what kind of testing is most appropriate.

Merging coverage reports from multiple runs

This is currently far more complex than it has any reason to be. Let's say your program has a bunch of scripts, and you want to run them as scripts, and still include in coverage report.

The easiest way to deal with it I found is injecting a small bit of code into them. So in your test you'd run your scripts as IO.popen("ruby -r./spec/coverage_helper #{executable_path}").read and spec/coverage_helper.rb would setup per-script coverage report:

if ENV["COVERAGE"]
  require "simplecov"
  SimpleCov.command_name "#{File.basename($0)}"
  SimpleCov.start do
    add_filter "/spec/"
  end
  SimpleCov.at_exit do
    # Remove verbosity
    $stderr = open("/dev/null", "w")
  end
end

Those partial coverage reports are then automatically added together when you finish.

Thursday, August 18, 2016

Map mode for Hearts of Iron 4 resistance and suppression system

If HoI4 developers insist on keeping the current resistance and suppression system, and I think they shouldn't, the bare minimum they need to do is making its map mode functional.

Unfortunately there's no way to make them do so, and no way to mod map modes in-game (one of the biggest gaps in modability - like where are truce map modes?). So as the next best thing I grabbed my old map generation scripts (which I originally used for generating timelapse gifs for my EU4 campaigns) and adapted them to display suppression information for HOI4.

Here's alt-tab map mode for that, the way it ought to work.

Colors and numbers indicate how many 1cav divisions you need to suppress states, with correctly applied rounding etc. All colors for 15+ cavs are the same, as it felt unnecessary to have whole scale for just a handful of provinces.

See my previous post for explanations of why 1cav is best strategy and math behind it all.

Gentlest:


Gentle (default):

Harsh:

Harshest:

This is pretty much what I'd like to see in game when you select resistance map mode. Not forcing math on tooltip - just show by colors and numbers how many units are needed to keep a state in good order.

Monday, August 15, 2016

Analysis and critique of Hearts of Iron 4 resistance and suppression system

Charlotte by Gattou - Lucie Provencher from flickr (CC-SA)

I wanted to write an analysis and critique of Hearts of Iron 4 resistance system, but that can't be done without a lot of math - more than can fit into reddit comment.

tl;dr is: spam divisions with 1 cavalry battalion and nothing else; or just turn resistance off.

The goal is to suppress the whole world

In all calculations we'll try different strategies to suppress the whole map at once. Of course you'll deal with less than that, but it just scales things down proportionally without affecting optimal strategy to significant degree.

We're also going to assume no partisan bonuses or penalties.

Resistance is based on number of victory points in state vs total suppression of all divisions present in state. It doesn't matter where you put those divisions within particular state, and divisions in other states don't affect resistance.

Occupied states with your cores (like in let's say China-PRC war) and states not completely occupied don't generate any resistance, but we're going to ignore those effects.

Since we're going to suppress the whole world, any resistance growth due to resistance in neighbouring states is just temporary and can be ignored.

Resistance generation

As baseline every 1 victory point in state requires 1 suppression point to prevent divisions present, but we have a choice of occupation policies:
  • harshest - 1 suppression needed / 1 vp
  • harsh - 0.8 suppression needed / 1 vp
  • gentle - 0.6 suppression needed / 1 vp - this is default setting
  • gentlest - 0.4 suppression needed / 1vp 
Important caveat is that this is rounded down, on state level. So state with total of 1 vp, at harsh policy, will require 0.8 suppression, rounded down to 0. So anything below harshest saves you from having to police low vp states completely.

List of states by victory point totals

For reference, notice how vast majority of states with nonzero vp have just a small number:
  • 1: Abruzzo, Abu Dhabi, Aden, Akmolinsk, Aleppo, Alföld, Alpes, Anhui, Antalya, Antofagasta, Aragon, Arequipa, Arkansas, Armenia, Attu Island, Bahia, Baku, Bialystok, Bihar, Bursa, Cebu, Central islands, Chelyabinsk, Coahuila, Corsica, Crete, Crisana, Dalmatia, Dodecanese, East Bengal, Eritrea, Fiji, French Guiana, Gansu, Ghana, Gilbert Islands, Goa, Granada, Guam, Gujarat, Hainan, Henan, Herat, Hyderabad, Iceland, Isfahan, Istria, Izmit, Jalisco, Jordan, Kalimantan, Kazan, Kentucky, Kenya, Kerman, Khabarovsk, Khorasan, Khuzestan, Konya, Krasnoyarsk, Kuwait, Languedoc, Lappland, Leon, Lodz, Lucknow, Macau, Macedonia, Madurai, Maranhao, Mecklenburg, Mendoza, Mesopotamia, Midway Island, Mississippi, Moldova, Montana, Moravia, Mosul, Mozambique, Munster, Murcia, Mysore, Nauru, Nebraska, New Caledonia, Nigeria, Nord-Norge, Norrland, North Borneo, North Dakota, North Korea, Northern Malay, Oklahoma, Olonets, Oregon, Palau, Perm, Polesie, Pommern, Puerto Rico, Rhodesia, Rzhev, Saipan, Salla, Scottish Highlands, Siaulai, Sierra Leone, Småland, South Carolina, South Dakota, South Sakhalin, Southern Slovakia, Sverdlovsk, Tamaulipas, Tanganyika, Tartu, Tasmania, Tikhvin, Tonkin, Transylvania, Trondelag, Tucuman, Ufa, Utah, Veracruz, Vestlandet, Voroshilovgrad, Wake Island, West Papua, Wilno, Yakutsk, Zaporozhe, Zulia
  • 2: Alabama, Angola, Hejaz, Kirin, Luzon, Mandalay, Palestine, South Island, Sumatra, Zhejiang
  • 3: Alberta, Alma-Ata, Arizona, Astrakhan, Auvergne, Azerbaijan, Azores, Benghasi, Bhutan, Ceylon, Costa Rica, Croatia, Damascus, El Salvador, Emilia Romagna, Gabon, Galicia, Guangxi, Guatemala, Guizhou, Honduras, Hong Kong, Indochina, Iowa, Irkutsk, Jiangxi, Jutland, Karjala, Kuibyshev, Liberia, Mindanao, Navarre, Nepal, Nicaragua, North Carolina, Nova Scotia, Novosibirsk, Oman, Omsk, Pohjanmaa, Pskov, Rio Grande Sul, Sardinia, Shanxi, Sind, Slovenia, Somaliland, South Chahar, Sulawesi, Tannu Tuva, Tashkent, Tennessee, Trabzon, Tula, Urumqi, Western Australia, Yemen
  • 4: Adana, Alaska, Fars, Fujian, Khartoum, Leopoldville, Liaotung, Marshall Islands, Natal, Papua, Shaanxi, Solomon Islands, South Korea
  • 5: Albania, Arkhangelsk, Bismarck, Bosnia, Bourgogne, Brabant, Burgas, Burma, Cairo, Central Macedonia, Colorado, Derna, East Anglia, Florida, Gloucestershire, Grozny, Guangzhou, Haiti, Harju, Hubei, Indiana, Iwo Jima, Izmir, Kabul, Kaunas, Kursk, La Paz, Lebanon, Leinster, Lima, Limousin, Loire, Luxemburg, Lwow, Malta, Manitoba, Midi Pyrenees, Minnesota, Miranda, Murmansk, Nejd, New Jersey, North Transylvania, Northern Ireland, Northern Territory, Novgorod, Panama, Panama Canal, Paraguay, Plovdiv, Poitou, Poznan, Saratov, Senegal, Spanish Africa, Thüringen, Tibet, Transdanubia, Tuscany, Tyrol, Uruguay, Valencia, Vitebsk, Voronezh, Wales, Weser-Ems, West Bengal, Westfalen, Wisconsin, Württemberg, Yaroslavl
  • 6: Baghdad, Caroline Islands, Castille, Cuba, Dominican Republic, Ecuador, Krasnodar, La Libertad, Mongolia, Queensland, Savoy, Scania, Taiwan, Vidzeme
  • 7: Andalusia, Ethiopia
  • 8: Georgia, Java, Rio Grande, Shandong
  • 10: Algiers, Ankara, Bombay, Bryansk, Cape, Casablanca, Champagne, Cornwall, Cundinamarca, Danzig, Eastern Switzerland, Franken, Georgia, Gibraltar, Gomel, Gorki, Hokuriku, Kalinin, Kharkov, Krakow, Lorraine, Louisiana, Mexico City, Moselland, Nanning, Niederschlesien, Northern England, Odessa, Okinawa, Orel, Ostpreussen, Porto, Rhone, Sachsen, Santiago, Shikoku, Stalino, Tehran, Transvaal, Tripoli, Upper Austria, Veneto, Virginia, Western Slovakia
  • 11: Alexandria, Dnipropetrovsk, Lothian, Pampas, Provence, Tunisia, Västergötland, Washington
  • 12: Siam, Singapore
  • 13: Qinghai, Yunnan
  • 14: Sao Paulo
  • 15: British Columbia, Calabria, Catalonia, Delhi, Hannover, Hawaii, Hunan, Koshinetsu, Lanark, Lombardy, North Island, Ohio, Ostlandet, Piedmont, Rhineland, Rostov, Serbia, Smolensk, Sofia, Switzerland, Vladivostok, Wallonie
  • 16: Manila, Rio de Janerio
  • 17: Uusimaa
  • 20: Alsace, Aquitaine, Campania, Crimea, Hessen, Hokkaido, Istanbul, Michigan, Minsk, Northern Hungary, Svealand, Thessaly, Tohoku, Warszawa
  • 21: Beijing, Missouri, Texas
  • 22: New England
  • 23: Saint Lawrence
  • 25: Bohemia, Centre, Kiev, Normandy, Schleswig-Holstein, Sichuan, Sjaelland, Victoria, West Midlands, Yorkshire
  • 26: Brittany
  • 28: Muntenia, Tokai
  • 30: Chugoku, Illinois, Leningrad, Lisbon, Madrid, Oberbayern, Pas de Calais, Shanghai, Sicily, Southern Ontario, Stalingrad
  • 33: New York
  • 35: Lancashire, Lower Austria, Pennsylvania, Sussex
  • 40: Kansai
  • 45: Latium, Maryland
  • 50: Greater London Area, Ile de France, Kanto, Moscow
  • 51: New South Wales
  • 55: Brandenburg, Kyushu
  • 65: Holland, Vlaanderen
  • 71: California

Division design

Using your regular army for suppression is a very poor idea as classic 7inf2art has abysmally low 7 suppression points for huge manpower and production cost. You pretty much need dedicated suppression divisions.

The only relevant units are:
  • cavalry - 1000 manpower and 120 infantry equipment for 2 suppression
  • military police - 500 manpower, 40 infantry, and 10 support equipment for suppression bonus between +20% and +50% depending on technology.
I'm going to assume they'll be using weapons 1, but it doesn't change calculations much. In such case both cost exactly 60 production (0.5 production per infantry equipment and 4 production per support equipment).

Suppression is rounded down per division, so if you have 5 divisions of 1cav+MP with 40% bonus (at level 3) in a state, their 5x 2.8 is actually just 10 not 14 (even though template dialog displays fractional part, implying otherwise). Fortunately this complication disappears at max level MP, as 2+50% is 3, and it's not affected by rounding.

The first thing to notice is that unless you include military police, there's absolutely no reason to ever produce cavalry divisions with multiple battalions. 10cav division has exactly the same suppression and cost as 10 1cav divisions - except with big divisions most of that suppression will be wasted as you can't place just the right amount of cavalry in each state, and excess suppression is completely wasted.

The second thing to notice is that military police is only worth it if you have a lot of cavalry in your divisions.

So the only designs to consider are:
  • 1cav
  • Ncav + military police, for somewhat big N

Suppressing the world with 1cav

The first strategy to try is to spam 1cav only.
  • On harshest - 2036 divisions, 2036k men, 112k production
  • On harsh - 1429 divisions, 1429k men, 86k production
  • On gentle - 1146 divisions, 1146k men, 69k production
  • On gentlest - 740 divisions, 740k men, 44k production
Number of divisions required is very high, but manpower cost is surprisingly reasonable, and production cost is absolutely trivial - even without trying anything cute like opening special basic equipment production line just for your cavalry.

In further discussion I'll ignore production, and only focus on saving manpower.

How bad in Ncav spam actually?

We already know that Ncav spam for any N>1 is strictly worse than 1cav spam, but let's see how much worse?

On harshest:
  • 1cav - 2036 divisions, 2036k men
  • 2cav - 1174 divisions, 2348k men
  • 3cav - 851 divisions, 2553k men
  • 4cav - 741 divisions, 2964k men
  • 5cav - 634 divisions, 3170k men
  • 6cav - 605 divisions, 3630k men
  • 7cav - 579 divisions, 4053k men
  • 8cav - 541 divisions, 4328k men
  • 9cav - 527 divisions, 4743k men
  • 10cav - 510 divisions, 5100k men
On harsh:
  • 1cav - 1429 divisions, 1429k men
  • 2cav - 756 divisions, 1512k men
  • 3cav - 611 divisions, 1833k men
  • 4cav - 487 divisions, 1948k men
  • 5cav - 453 divisions, 2265k men
  • 6cav - 407 divisions, 2442k men
  • 7cav - 393 divisions, 2751k men
  • 8cav - 373 divisions, 2984k men
  • 9cav - 367 divisions, 3303k men
  • 10cav - 350 divisions, 3500k men
On gentle:
  • 1cav - 1146 divisions, 1146k men
  • 2cav - 664 divisions, 1328k men
  • 3cav - 487 divisions, 1461k men
  • 4cav - 447 divisions, 1788k men
  • 5cav - 398 divisions, 1990k men
  • 6cav - 373 divisions, 2238k men
  • 7cav - 366 divisions, 2562k men
  • 8cav - 348 divisions, 2784k men
  • 9cav - 335 divisions, 3015k men
  • 10cav - 332 divisions, 3320k men
On gentlest:
  • 1cav - 740 divisions, 740k men
  • 2cav - 474 divisions, 948k men
  • 3cav - 396 divisions, 1188k men
  • 4cav - 362 divisions, 1448k men
  • 5cav - 340 divisions, 1700k men
  • 6cav - 325 divisions, 1950k men
  • 7cav - 317 divisions, 2219k men
  • 8cav - 316 divisions, 2528k men
  • 9cav - 314 divisions, 2826k men
  • 10cav - 309 divisions, 3090k men
And similar story on intermediate levels. 2cav to 5cav is not totally crazy if you want to save yourself from some micromanagement, especially if you want to oppress everybody more, but going for huge divisions is just bad.

It's not difficult to understand why - most states that need suppression need just a few points of suppression, so you'll be wasting a lot of it.

How bad is Ncav+MP spam?

Because of rounding down on division level, with low levels of MP technology, MP bonus is even lower than it's supposed to be. For example 2cav+MP with 1936 tech gives 4.8 suppression, rounded down to 4, no better than 2cav alone.

But let's assume best case for MPs, 1945 technology (even though most campaigns are over or basically so by that point), as 50% suppression bonus never results in any rounding issues.

And it's still bad. Optimal strategy by level is:
  • harshest: 2cav+mp - 851 divisions, 2127k men (vs 2036k for 1cav)
  • harsh: 2cav+mp - 611 divisions, 1527k men (vs 1429k for 1cav)
  • gentle: 1cav+mp - 756 divisions, 1134k men (vs 1146k for 1cav)
  • gentlest: 1cav+mp - 600 divisions, 900k men (vs 740k for 1cav)
So considering just the absolutely best case for max technology level MPs is that on gentle they save you approximately 1% manpower (and cost of 32% more production, but it's not like that matters much), on other levels and on lower tech they're strictly worse.

Suppressing with two division types

Big divisions with MP offer good suppression to manpower ratio. The main reason they end up being horrible is that suppression is calculated on state level, so they end up wasting a lot of suppression in wrong places.

What if we mixed a few division types? I decided to try Ncav+MP and 1cav mix, with semi-greedy algorithm. This actually results in better results than pure 1cav:

Optimal on harshest:
  • 2036x 1cav - 2036k men
  • 743x 1cav and 224x 4cav+mp - 1751k men
Optimal on harsh:
  • 1429x 1cav - 1429k men
  • 613x 1cav and 137x 4cav+mp - 1229k men
Optimal on gentle:
  • 1146x 1cav - 1146k men
  • 525x 1cav and 137x 3cav+mp - 1004k men
Optimal on gentlest:
  • 740x 1cav - 740k men
  • 335x 1cav and 135x 2cav+mp - 672k men
You can even squeeze some savings on low MP technology, but they will be much smaller and apply to fewer states.

The strategy is to put big divisions in high vp states, then top it up with as many 1cavs as needed - and in small states use just 1cavs.

You could try even more types - for example California on harshest treatment could be suppressed by one monstrous division of 24cav+MP (24.5k men) instead of 5x 5cav+MP (27.5k men), but that template would be too big for literally every single other state.

This is horrible design and developer should feel ashamed

Now that we established the numbers and various possible strategies, let's talk about the most important issue here. This is absolutely atrocious game design! It's 100% meaningless micromanagement with zero strategic depth.

To add insult to injury it has awful interface as the only way to get the right number of units to the right state is to:
  • ignore alert on top of the screen, as it points at wrong states anyway
  • switch to resistance map mode
  • mouseover a state because relevant information is only on the tooltip
  • decode numbers on the tooltip and do the math how many divisions that actually means in your head
  • put your finger on the screen to point at the right state, as there won't be any indication which one that was after this point
  • switch to regular map mode
  • select right number of divisions
  • press strategic redeployment button and actually send them there (or make 1-province fallback line)
  • repeat that for every state, over and over
And as if that wasn't bad enough - nobody told AI that it needs to do that, so all its lands are always wrecked by 100% resistance!

This is horrible! A checkbox on occupation policy screen subtracting appropriate number of manpower and infantry equipment from your pool would have just as much strategic depth for 1% of meaningless and miserable clicking.

If devs absolutely insist on police units appearing on the map, the absolute minimum would be to group states into something like air regions or whole occupied countries, and count any resistance and suppression on that level. And then fix the damn UI so when you are in suppression mode big number of suppression needed appears directly on the map (not in tooltip) and you can move units without switching mode.

Workaround

If you're not trying to chase "achievements", just turn the whole miserable thing off by dropping file like this:

NDefines.NCountry.RESISTANCE_STRENGTH_FROM_VP = 0

into common/defines/no_resistance.lua

Warning - this makes game significantly harder, as AI Germany will be able to use French, Belgian, and Polish factories to build its equipment instead of having them all wrecked in a few months of occupation while its units all sit in "wrong" states.

Saturday, August 13, 2016

Let's Play Hearts of Iron 4 as Nationalist China

I finally got fibre internet recently, so I thought I'd give this twitch thing a try.

Of course if I'm streaming / recording something there's no reason not to upload it to youtube as well.

Here's the playlist.

And here's the first episode:



Further episodes will come out once per day.

This is my first experience with Twitch, so there are some minor technical issues like microphone being placed less than optimally for first episodes etc. It should be fairly OK regardless.

As uploading things to youtube is massive pain I did the long overdue thing and fought my way through Google APIs to write script to automatically publish videos on youtube - it does all the things I need - setting title, description, tags, playlist, thumbnail picture, and publication date.

Isn't this sort of amazing that youtube doesn't have anything like it?

Monday, August 08, 2016

HOI4 Hungary World Conquest AAR

Post 1 - Originally published on Google+ on 2016-07-27 11:27:36 UTC


Hungary game:
• mods to give a lot of countries focus trees: Netherlands, Sweden, Finland, Yugoslavia, Iran, China - notably not us, but it could be fun clusterfuck with ten factions
• most gameplay affecting mods (fewer majors, extra support companies, no resistance, no xp for army changes, no guarantees on neutrals) reversed - I'm not sure if they make game better or not
• still keeping extra straits, accurate ledger, final score fixes (I don't think that does anything in game), and some graphics mods

So the first problem is that we ought to have cores or at least claims for all of 1914 Kingdom of Hungary, and we only have ones for small bits of Slovakia. Hungary had claims on Northern Transylvania and Vojvodina in 1.0, but Swedish bastards removed them!

The second problem is that we're kingdom ruled by regent admiral Horthy, and yet we don't have any fleet, or even any sea access.

The third problem is unremoved kebab and unremoved kebab guarantor UK.

The fourth is that somehow game thinks historically non-aligned Hungary is somehow fascist. Actually, that's more an opportunity than a problem.

So let's start by reactivating our only existing claims on Czechoslovakia, and then as soon as possible on Romania.

Conclusions from war with Czechoslovakia:
• my army (6inf, no supports, got art support mid-war, but it with maybe 20% of artillery pieces specified) can't fight even to close a pocket
• Czechs forgot to put anyone in Prague

I tried to squeeze in Yugoslavia after Romania, but declaring war on Romania made tension go to 30% and started guarantee spam, so I had to abandon that one. Before I'd say "well, at least 2 more guarantees and I can do whatever I want", but after campaign where they made 12 total... Vojvodina true Hungarian clay! And by the way if Hungary had claims it had in 1.0, that would actually keep tension below guarantee spam level.

War with Romanians was fairly similar, all micro, fun with shitty armies on both sides, undefended capital.

Well, now I don't have any way to attack anyone - anybody I fabricate on will be instantly guaranteed by the Allies, and spamming a lot of simultaneous fabrications is not as reliable as I once thought it would be.

I can always just wait and see how things go from here.
 #hoi4

We got one sea, but straits are blocked.


Long countries are easy to cut, and they built defensive mountains are on wrong side.


Czechs had about twice my army size (theirs are 9inf, mine are 6inf), so I had to trap them to make it more even.


Always leave one unit in your capital, or this happens. I couldn't clear even one pocket in less than a month, that's why 4 pockets are left behind the lines.


Post 2 - Originally published on Google+ on 2016-07-27 12:59:18 UTC


I gave it a try, and started a bunch of simultaneous fabrications, trying to sneak in Austria before UK guarantee spam. And of course fucking UK guaranteed Yugoslavia, Belgium, Finland, and Austria. And France with barely 0.2 mana/day decided to spend 25 of it on Yugoslavia as well.

Of course that guarantee was only good against me, it did nothing to stop the Anschluss. And those damn guarantees don't even lower world tension to any significant degree, contrary to what they're supposed to.

Germans were at least kind enough to give me Vojvodina by national focus, because obviously UK and French guarantee for Yugoslavia is only binding against big scary Hungary, not good uncle Hitler.

And then it turned out, after Yugoslavia was already half the size, it figured out it doesn't want to surrender the rest and the German-Allies war started. Meanwhile Greece became German puppet, and Bulgaria grew from 3 to 5 states, so was a much more tempting target.

At least Poland founded its own faction, so I had a cute plan that I'd fabricate on Poland and Bulgaria, then DoW Bulgaria, and only fight Miedzymorze this way. Of course UK guaranteed Bulgaria, as if it didn't have own fucking war with Germany already.

And Soviets in a ridiculous programming bug got claims on Eastern Poland and all Baltic states from Molotov-Ribbentrop Pact without even reaching their "claims on Poland/Baltics" buttons, or without Germany even having decency to go "Danzig or War".

Soviets got their CB 4 months before me - and they were able to cheese removing Great Purge penalties early, without a real war. I barely managed to get Krakow for 10 victory points, but fuck that shit. We're fabricating on Moscow now!

They only have 4x as many divisions, what could possibly go wrong?

 #hoi4

So much for my Miedzymorze plan. There's only one way to go, and that way is to Moscow!


New focus trees in action. Biggest change is that China is actually too strong for Japan now, but things might happen in Scandinavia too.


For fuck's sake, these Soviet claims are a fucking bug.


Post 3 - Originally published on Google+ on 2016-07-28 03:47:23 UTC


I wrote a script that takes HOI4 save file (must be set to text mode in settings), and generates these "ledger" pages.

Here are some examples from my latest Hungary campaign (as just before I DoW Soviets I was really curious how we compare):
Hungary - http://pastebin.com/GidLMNdC
Soviet Union - http://pastebin.com/AUNC7rfH
Germany - http://pastebin.com/AeVmibmZ
 #hoi4

Post 4 - Originally published on Google+ on 2016-07-28 12:51:32 UTC


Here's some quotes from 1.1 patch notes: "Tweaked guarantee desire [...] Should keep Allies from going guarantee crazy". They apparently tweaked in fucking wrong way, as guarantee spam is much worse than I remember it from 1.0.

And all the guarantee spam targets little Hungary, which is just trying to reunify lands which belonged to Kingdom of Hungary for nearly a thousand years, and yet which somehow doesn't have cores or claims on any of them. Soviets trying to conquer Poland? Who gives a shit.

At least I hoped Poland would hold the line for a while so I could sneak into Warsaw, get half the warscore, and maybe divide it in half with the Soviets, but no such luck. So now I have to attack them mid-war, or they'll get 90% of Poland and Lithuania, leaving with without anything. I'm not going to call Germany unless things are going really poorly, they're just my insurance policy.

OOB, Hungary vs Soviets (in parentheses numbers including occupied Polish ICs):
• army - 87 divisions (841k men) vs 293 divisions (2480k men)
• artillery - 12005 vs 8980
• tanks - 26 (unused) vs 5115
• air force - 81 planes vs 2439 planes
• navy - 0 ships vs 79 ships
• military factories owned - 45 (+1) vs 63 (+11)
• civilian factories owned - 41 (+3) vs 63 (+13)
• dockyards owned - 2 (+0) vs 6 (+0)
• warscore against Poland - 108 vs 579

So as you can see, it's not all that bad. But it will get worse once Soviets annex Poland. Our army's philosophy is "never enough firepower". Soviet army is 3x bigger, but more diverse with light tanks, motorized, planes, ships and so on.

Anyway, time to strike - first goal is to take Warsaw to get the warscore in Polish war, and if possible actually keep Poland alive longer.

And of course that failed miserably, Poland surrendered to the Soviets, and instead of peace conference, they got it all, ignoring my warscore. Fuck! And since I was trying to get as much clay as fast as possible instead of pocketing, my losses were pretty severe, only 3 times less than Soviet's, which is no way to fight such war.

Well, second goal - destroy Soviet ability to wage war by grabbing as much of their industrial base as possible. That sort of starts working, balance in number of divisions is now worse at 89 vs 305, but I'm finally ahead of them in miltary factories.

Unfortunately I was unable to capture any significant amount of Soviet troops in Poland, they mostly managed to withdraw East. So I'll need to just shorten the frontlines in some defensible line before I plan anything more.

 #hoi4







Post 5 - Originally published on Google+ on 2016-07-28 15:26:39 UTC


I got hit by a truly ridiculous bug - in the middle of the war big chunk of Eastern Poland flipped to Soviets - it wasn't actually too bad, I just had to move some of my frontline troops back to retake it.

I finally managed to pocket 32 divisions in Eastern Poland, as well as a bunch of smaller pockets - unfortunately they managed to evacuate their Danzig divisions by sea.

I decided to pause and rebalance the frontlines, as just pushing the Soviets had poor K:D ratio, but the fucking AI managed to withdraw all troops from a few tiles in Crimea I had this way, and Soviets got it back. I hate it so much.

So far the war has been going very slowly. I managed to pocket Lithuania, and push a bit, but that's not blitzkrieg, that's WW1 style trench warfare. Too bad they don't have 10% NU like they used to back then.

OOB:
• army - 138 divisions (1179k men) vs 237 divisions (2004k men)
• losses - 413k vs 1.56m
• artillery - 11941 (half new type) vs 8037 (all old type)
• tanks - 26 (unused) vs 2392
• air force - 81 (unused) vs 2446 planes
• navy - 0 vs 81 ships
• military factories controlled - 77 vs 67
• civilian factories controlled - 74 vs 65
• dockyards controlled - 3 vs 5

In other words, Soviets is smaller by 55% of tanks, 10% of their artillery, and their 20% of their men. Their not doing too great, but they're far from broken.

Right now my best idea is to cut armies they have in Crimea - that's about 50-60 divisions. Such losses would be very difficult for them to replace, even if that would stretch my frontlines uncomfortably.

Meanwhile Germans are wrecking Western Europe.

 #hoi4

Germans are doing really well including puppet Greece (but no Danzig or Sudetenlands). I'm going to focus on encircling Crimea and maybe pocketing Caucasus. Or I could pause and regroup for a while, I have small equipment deficit (less than a month).


WTF? Even by standards of buggy focus buttons that's ridiculous.


It was only temporary inconvenience.


First big pocket, but Soviets replaced all those troops just fine.


Second big pocket. This time Soviets had much harder time replacing their losses.


Post 6 - Originally published on Google+ on 2016-07-29 00:33:38 UTC


After operation "pocket Crimea" the Soviets were reduced from 237 to just 200 divisions - only twice as much as me.

Unfortunately it was my manpower that was hurting not theirs, so I went up to "All Adults Serve", which is quite painful. Not quite as painful as it says on the tooltip, as penalties to production and construction speed are applied to base not multiplicatively, so for example -30% factory output is really 170% to 140% (-18%), and -30% construction speed is from 150% to 120% (-20%), or something like that.

On the other hand, my geopolitical situation was really good - Soviet Union was on its way out, even if it would take a while, I had great followup of going after China next, Germany couldn't attack me because I was in their faction, Allies couldn't attack me because they had no CB and I didn't join German wars (they called me every now and then, but I ignored that).

So the next step was to take Caucasus - and keep pushing on whole frontline whenever good opportunity arises, but not too aggressively as I was still suffering from equipment shortages.

It doesn't seem like that much clay on the map, but small Western part of the Soviet Union is most of their industry and victory points are, so those casual pushes often get nice cities like Minsk and Kharkov without much opposition.

I decided to expand the war a bit and fabricated on Latvia and Estonia, but UK guaranteed Estonia. Seriously? Do they have any idea how screwed they are? At least as fascist it only takes me 25 days to fabricate while at war with a major, so UK didn't get enough mana to guarantee Latvia as well. It wasn't exactly "Around Maginot", but it got me some nice clay, and it let me take a shortcut to Leningrad.

Meanwhile Caucasus front crush whoever was there, and took Stalingrad.

OOB:
• army - 145 divisions (1300k men) vs 136 divisions (1146k men)
• losses - 606k vs 3.11m
• artillery - 14666 vs 5725
• tanks - 26 (unused) vs 1103
• planes - 81 (unused) vs 2459
• military factories - 99 vs 53
• civilian factories - 95 vs 49
• dockyards - 7 vs 1
• progress towards victory - I have 49% vp, I need 70%

3/4 of men Soviets ever recruited are no longer fighting. Then again 1/3 of mine aren't either, but I'm not sure if that counts before or after field hospitals.

By the way you know what would be useful - some indication where the hell enemy air planes are coming from. Soviets kept bombing Western Poland, which made no sense whatsoever, but their nearest airport was really far away.

 #hoi4





Post 7 - Originally published on Google+ on 2016-07-29 02:51:59 UTC


I was really curious where the hell bombers Soviets are sending to Poland are coming from - and apparently they're from Moscow and Tula (one state south from Moscow). Well, so much for my strategy of prioritizing taking airfields so they can't use their air force.

Soviets were still a good deal away from capitulation, but their army was weaker than mine, even in just numbers. I could finally do panzer push column with plain infantry.

I could have rushed Moscow, but for now I used that to make huge pockets. Then again, I could do both - after closing all the pockets from Moscow to the West Soviets were reduced to 67 divisions, but still wouldn't capitulate.

That's actually fine, as I'd really like Turkey and Iran (who conquered Afghanistan, as it has custom national focuses with some CBs) to both join Comintern before it all ends.

Fortunately I didn't need to occupy all of them - I think even one tile works, but just to be sure I got a few victory points.

So now Hungary is strong. And we captured a lot of planes - we're up to 1893 (that's not all Soviets got, but most). Apparently ships all get scuttled. Oh well.

I finally researched my ways up to 1941 medium sparts and 1940 heavy fighters, and I started building them, but they won't be ready for war in China in any significant numbers.

Next step is obviously taking China, who's doing surprisingly well and even took over Tibet, and I'm going to get various Middle Eastern minors while I'm at war with them.

A quick peak at Chinas shows they have together 1806k men under arms, 2291 planes, and not a single tank or artillery piece, so in any war they'll get shredded to pieces.

Japan has 594k men and decent amount of proper hardware. So far Chinas lost 2.54m men and Japan lost 1.23m.

The good news is that Japan is not part of the Axis, so I could take Manchuria and Korea for myself, but they might join as soon as war starts.

 #hoi4

Towed artillery is a fine tank.


Once enemy army is broken, massive pockets are easy to make.


The great Red Army, almost all gone, but before we finish it off, a short Southern detour is needed.


Just push enough to make them part of peace conference. I even got capital of Iran. A bit surprised neither of them is a great power - I'm playing without great power fix, but the list is very sensible, without even Raj.


That's how far I needed to go.


It's actually not that much clay, it's just bad map projection.


Post 8 - Originally published on Google+ on 2016-07-29 05:06:59 UTC


I declared war on China three months later, but I wasn't actually interested in getting Manchuria, as I wasn't even sure if I'd get it or the Japanese would.

Instead I used that to get 80% fabrication speed bonus, which seems to be the only way around guarantee spam.

OOB is that I have artillery and they don't, and that's all anybody needs to know. Chinese attacked my forces on Manchurian borders, but they had 12:1 K:D ratio. I was seriously worried that China will lose so much equipment (manpower it can replace) that Japan will be able to wreck them and take most of China for itself.

Japan joined the Axis, probably because Axis member was also at war with China, which is not totally crazy logic - so I definitely did not want to push with my Manchurian troops, and give that captured clay to Japan.

Instead I got Iraq, Saudi Arabia, Yemen, and Oman with one army.

Two more armies went after Comintern (Mongolia, Tannu Tuva), and Sinkiang which chose to join Comintern somehow. As Tannu Tuva was the only major being faction leader, all capitulated as soon as I took capital of Tannu Tuva.

Both of these armies later went after Nepal and Bhutan and got into China from my side. Tibet was conquered by China a while before (as was Afghanistan by Iran).

Then I pushed from the West, no rush, just getting it done. The main risk being that Japan, who inexplicably has massive warscore, would actually get most of it. I think if you take a victory point, it's still counted as yours for warscore reasons even if you lose it later.

The big question I was wondering about was who to fight next - the Allies (or basically any minor, as everyone seems to be guaranteed by them by now) or the Axis.

I couldn't realistically finish off either as I have literally 0 ships, and no paratrooper technology. What I could do is maybe paradrop Japan - but then here's German OOB:

• 343 divisions (2898k men)
• 15017 artillery
• 11518 light tanks
• 704 medium tanks
• 405 heavy tanks
• 2259 planes
• 17 ships (I see the Royal Navy was not lazy)
• 149 military factories
• 154 civilian factories
• 40 dockyards

And on top of that there's also Italy (578k men), Japan (681k men), and Greece (119k men) to deal with.

Then it would be even harder to invade UK than Japan, and USA would probably join the Allies.

Fortunately I no longer need to wonder, as USA is fabricating CB on me, and they'll surely join the Allies as soon as they declare war.

Actually disregard that, "United States is justifying war against us" tooltip is fake, and they're really using their anti-German button. As long as I don't accept the call, they can't actually do anything.
 #hoi4

Pushing from side where I get it, not from side where Japan would. I got them a few tiles to make frontline shorter. Chinese losses against me made Japan do a bit better in Korea and their landing area than they were doing before, but I think I can get most of it before Japan breaks out.


War plan. Manchuria arrow is fake, Japan would get all of that not me. There are downsides to being in a faction.


You had one job... Province abandoned by battle planner being a fort only makes it more ridiculous.


Factions. USA will get CB on Germany (tooltip saying it's on me lies), and will presumably join the Allies soon enough. Sweden in allies due to its focus buttons from the mod.


Post 9 - Originally published on Google+ on 2016-07-29 07:04:19 UTC


I completely forgot Netherlands got their focus buttons too. They went fascist, but they're still in the Allies.

I randomly noticed that in lands under occupation by my faction members, resistance is 100% and every single factory is sabotaged pretty much as a rule. After a few campaigns without resistance, that's something new. That's presumably going to make Germany far weaker than it seems, so maybe I should backstab them soon?

USA joined the Allies and declared war on Germany. Spain joined the Axis.

China didn't really resist - artillery vs no artillery makes numbers fairly irrelevant, as Zulus have found a while ago.

Unfortunately Japan got far more than it deserved - in addition to 3 very rich states China gave them after Marco Polo Bridge incident.

Now I have 2 options:
• attack Allies (and somehow sneak invade UK and USA and who knows who else will turn major) with no ships and no paratroopers
• backstab the Axis

Axis backstabbing feels a lot more appealing. In about six months I could have about 250 divisions of 7mnt2mspart (disregarding all cavalry on MP duty). Hopefully 125 can hold the line in Europe, as I'd like about 24 to take Suez Canal, and 100 against Japan.

Germany unfortunately has a lot of tanks, so my msparts will have trouble dealing with them, and I don't want to use antitank support - I have art, rocket art, hospital, maintenance, logistics. I guess I could cut maintenance as I can produce huge amounts of military equipment, but it feels like a huge waste.

I could start building some tank divisions as well in addition to my regulars. Then again, it's not like I'm made out of manpower, Japan got most of China so I can't even 2% of that, so my armored divisions will probably be rather limited.

I have 330 factories vs 349 the rest of the Axis has, which is about even, considering I'm on "All adults serve" and they are on less strict laws, but then again I probably have better technology than most of them. And for now they're fighting a war, and I'm not - last serious war I had was first half of war against the Soviets, after that even my war time was rather one sided and with limited losses.

I can't currently import much rubber, as Gibraltar is closed for fighting, even though Suez canal is open, and I have ports on all oceans. Then again, the Axis is pretty low on rubber as well, and Germany seems to be very low on planes - I guess AI sometimes fights even in patch 1.1.

 #hoi4

Japan took far more than it deserved.


100% resistance, 16/16 factories damaged. Pretty much everything Germany holds looks at least half as bad as this.


So it has come to this.


All that "Japan" clay was taken by me - Japan couldn't even keep their invasion of Korea alive. I wonder if I'd get it all if I left the faction earlier. Probably, so I guess staying that long was a mistake.


Post 10 - Originally published on Google+ on 2016-07-29 21:16:12 UTC


I took my time. I'm not entirely sure if it benefits me, as everyone has more manpower, so the longer I wait the more troops they could equip.

AIs happily throw troops at each other, so casualties are high, but all majors have huge core populations, so I don't think any of them can plausibly run out.

Waiting also meant a small risk of Axis or Allies getting too strong. Neither side could realistically win, as AI can't naval invade UK, Japan, or especially USA, but if let's say USA spammed naval invasions of Spain and Italy until one sticks, I could end up with very little warscore left for myself.

I had one more trick. AI decides if it wants to put troops on your border or not depending on CBs. If you fabricate on AI, it will use that time to reposition troops on your border. Even 30 day fabrication is enough for them to get some troops and stall me.

On the other hand - if I fabricate on Spain or Italy, Germany and Japan won't take it as a threat, but they'll auto-accept call to arms, so I'll be able to get a lot of clay - and most importantly shorten the frontline - before major fighting starts. At least that's the idea.

Anyway, I extended my ledger to also support factions, and Allies are really strong on paper.

OOB, Hungary vs Axis vs Allies:
• army - 250 divisions (2360k men) vs 660 (5165k) vs 639 (5806k)
• artillery - 82188 vs 41621 vs 47192
• tanks - 1519 (no manpower to use) vs 22783 vs X
• ships - 0 (no manpower to bother with it) vs 350 vs 763
• planes - 5809 (no manpower to use) vs 6511 vs 24035
• controlled IC - 606 vs 930 vs 909

I also tried to get total casualties to the ledger, but they're only saved for active wars, not any past ones.

I'll probably strike mid 1943, there's not much benefit from waiting - it's not like I'm going to get much more manpower. The plan is to:

• not getting overrun in Europe
• shortening the border as much as possible to counter German numerical superiority - especially East Prussia should fall fast
• pushing border in Middle East up to Suez Canal
• pushing Japanese to the Sea

 #hoi4

I already conquered it once, I can conquer it second time


The border is very awkward, getting straight line from Berlin to Venice would be much easier to defend


Post 11 - Originally published on Google+ on 2016-07-29 23:43:42 UTC


I decided to arbitrarily set day of attack on Italy for May 1st, and predictably the rest of the Axis joined immediately.

One thing I did not consider were all exiled Italian divisions in my territory, which grabbed random tiles all over the place - apparently AI doesn't know how to strategically redeploy exiled divisions.

The plan in China and Middle East went about as well as could be expected - locally overwhelming forces just moved in with minimal resistance.

Much more interesting was situation in Europe. The plan was to pocket Silesia if possible, take East Prussia to prevent Germans from landing anyone there, take part of Serbia on north side of Danube, and push West from Western Hungary toward Vienna, to reach good defensive positions between Danube and its tributaries (Drau, Save, and Inn according to Wikipedia).

To increase chances of Silesia pocket succeeding I pushed with a few divisions west of it to pin any potential German reinforcements. Dresden and Leipsig were two tiles away from my borders, so I thought why not. And actually Berlin was only 5 tiles away from the border, so that fell within 8 days into the war.

And Allies succeeded at capturing Netherlands and Hamburg / Bremen area. So by May 11th Germany was 60% toward capitulation.

One awkward problem was that Bulgaria flipped fascist, joined Axis, and attacked me one week into the war, and of course our border was completely undefended, but by that time Silenias pocket closed, freeing some troops.

Amazingly Germany capitulated within a month, before I got even close to finishing off China. Unfortunately Allies got far too much of it. Well, I guess I'll just keep moving forward in Europe. Italy, Vichy France, Spain, Bulgaria, and Greece are still in the Allies.

 #hoi4

I expect the rest of the Axis to get overran as soon as I can reorganize my frontlines.


Small pinning attacks towards Dresden/Leipzig were done just to prevent Germans from saving Silesian pocket. I thought I'd need to do whole front defense and I wanted to shorten frontlines fast to make my defense easier - before I could send troops from China to do proper fighting in Europe.


Random Italian exiles


Their sense of timing is amazing. They were protected by UK guarantee, so they were pretty safe before that.


Germany completely overran. I'm not even sure why it was so one-sided. I was worried that not using anti-tanks and planes might be a mistake, but turns out it's just fine.


Faction map. I wish Japan/Siam took over French Vietnam, then I'd be able to reach the bastards.


No idea how to invade. I still have 0 ships, I only just started building some light cruisers, but it will take at least a year before I have anything. I have a lot of fighters, but no paratrooper tech, so that way would take a year as well.


Post 12 - Originally published on Google+ on 2016-07-30 01:10:48 UTC


Axis lost about half of everything after German capitulation, and then half of the rest in next two months as Axis members started falling one after the other.

I tried to get Switzerland in the war too, but somehow they got guaranteed by France and Sweden right away.

It turned out I had some unused discount on paratrooper tech from national focus, so I could get them in 50 days. Why not, I'll just retrain some cavalry and I'll get Japan in reasonable timeframe. It's a bit cheesy to go:

• recruit cavalry
• change them to paratroopers
• paradrop, capture port so supplies can flow
• change them to heavy infantry
• convoys with supplies with somehow sneak in and bring everything with no risk
• take Japan with overwhelming firepower

Hopefully once this war is over some countries like fascist Netherlands will leave the Allies so I don't need to go to war with the whole world at once. I'll have to eventually, as this is one-tag game, but it's easier to do it in batches.

I went scrapping the barrel, I might unscrap that after the war, which is somewhat cheesy but I didn't make the rules.

And first two light cruisers are just about to be finished.

 #hoi4



Post 13 - Originally published on Google+ on 2016-07-30 02:52:35 UTC


I did the cheesy thing of paradropping, then changing template I've seen marco antonio do.

That made Japan even easier than it usually is. Now I have two choices:
• go to war with the Allies - that will take forever, as I have only a few ships, and US will be quite hard to conquer. Then again, I might try Kamchatka to Alaska way and hope it's undefended.
• go to war with some non-faction country like fascist Netherlands (who left Allies as soon as war was over) or neutral Portugal. There's still decent change they'd join the Allies immediately.

OOB, Hungary vs Allies:

• army - 390 divisions (3634k men) vs 892 divisions (6818k men)
• navy - 7 ships vs 609 ships (even counting just light cruisers they still have 65)
• artillery - 122,262 vs 61,113
• tanks - 9786 vs 22255
• ic - 1210 (1194 working, 16 damaged) vs 1219 (1162 working, 57 damaged)
• air force - 10940 planes vs 38088 planes

Most of my planes, artillery, tanks etc. are never going to be used, as they're old models or captured light tanks etc. I let stockpile accumulate as honestly there's not that much to do with IC as this point.

They definitely have more trouble with damaged IC, but it's not a huge deal. France has 120 IC, but 29 of that is damaged, for other countries it's not a huge deal.

I don't expect the war be anything less than Allies getting completely overran in Europe and Asia, followed by some kind of paradrop to UK and Indonesia.

I got rid of scrapping the barrel and went down to limited exports.

With captured dockyards I can build 50 light cruisers a year - so in less than a year I should have strong enough fleet to be able to escort invasions in one place, even if not enough to challenge Allies to a decisive battle.

The most tedious part will be dealing with resistance, as patch 1.1 didn't fix that at all, but at least I have manpower for it.

 #hoi4

It's not exactly exploit, as it requires a port, take them a few weeks to get those guns, and cost them experience, but still feels a bit silly.


Less bordergore than usual.


Post 14 - Originally published on Google+ on 2016-07-30 16:46:34 UTC


I went back to savegame from start of war with the Axis to try to figure out why Germany was so weak.

Short story is that they had 133 divisions trying to force their way to Sweden, which was defended by 73 Swedish and 33 allied divisions. Amazingly that was only slightly out of supply as those areas have very good infrastructure, and many of these divisions were actually expeditionary corps which tend to be somewhat smaller. Also AI seems to have figured out 7inf2art, a lot of countries use it by mid-game.

And so Germans burned through all their equipment, had massive shortages of everything (like 200-300 days shortages, with more being burned every day), and while they could replace manpower losses, most of their divisions went to green experience level. Of course it didn't help that all the IC Germany took was mostly useless due to sabotage, and Germany wasn't very focused with ICs it had, building three kinds of tanks, multiply types of planes and so on.

Which brings us to the question - how the hell Sweden had that many divisions?

Moving back to present time, I looked at the Allies before the war - most have close to no forces as they were just released in peace deal recently, or lost a lot during failed naval invasions AI loves to spam.

By number of troops:
• Allies total - 7344k
• US - 3420k (this might be a difficult invasion)
• Sweden - 1587k (WTF?)
• Raj - 1140k
• UK - 551k
• Australia - 275k
• the rest doesn't matter

Wait, what the hell Sweden? What kind of ridiculously overpowered national focus tree they've got? And apparently they don't - they got a total of +1% recruitable pop from their tree, which is more than usual +0% for democracies, but I got +7% from generic tree as fascist. Sweden was in fact at 25% base from scrapping the barrel, but it simply kept their whole army guarding the straits, building it up with only modest losses while Germans were killing themselves in droves trying to cross.

The only thing Swedish focus tree did was made them choose to join the Allies instead of staying neutral as they tend to do, and even generic tree has some chance of abandoning neutrality.

Here you have it - Germany lost the war to join effort of Sweden and Hungary, with everything else being a sideshow. At least it's hard to accuse the game of railroading historical choices.

The plan is simple:
• fabricate on newly released Italy and Germany
• they inevitably get guarantee spammed by the Allies
• keep buying stuff from Portugal (tungsten) and Netherlands (rubber), leaving me with modest oil (long term, as there are no major sources except in US; I'll capture some here and there, but not enough to cover shortages) and steel (for a short while, until I take Alsace and Sweden) shortages after the war starts - I have far too much chromium and aluminum, and they're of relatively little use; it's not even that I don't have oil or steel, I just have obscene amount of military production
• fight the Allies, freshly released ones like France and Belgium are nearly defenseless; Raj will be a bit of a fight, but shouldn't be too bad
• take over various minors like Estonia, Finland, Switzerland, and whatever is that bordergone in the Balkans
• I had very bad experience with Sweden straits in my previous campaigns, and no navy (some paratroopers, but against this kind of defense it's probably not the best idea), so definitely invade via Finland, not via straits
• capture get Suez and Gibraltar to prevent any shenanigans
• after hopefully short campaign Allies will be reduced to various islands and deep Africa; not sure how to deal with the islands and for that matter with the US, but that can wait

 #hoi4

Loaded save of "How Germany lost the war". Just look at everybody else those divisions could have been fighting.


War plan in Europe and Africa. Oh and somehow there are two Spains.


War plan Asia. You can also see amazing AI skill at balancing the frontlines is  it just loves putting 1 division per tile, then everything else on ends (like that Raj 18-division tile on Raj/France/Hungary border). I had to split a few such clumps manually as they were eating too much local supply.


Post 15 - Originally published on Google+ on 2016-07-30 19:46:27 UTC


Here's a short explanation of HOI4 tag system:

• every country starts with tag like SPA, FRA, GER etc.
• when country flips ideology, it keeps its tag - there's no silliness like EU3's special "RFR" tag for "Revolutionary France".
• when civil war erupts, it creates dynamic tag, like D01, D02 etc., with original_tag saved
• country's name and flag are based on combination of original tag and ideology
• so FRA/fascist will be "Vichy France", but D02(original FRA)/fascist will also be "Vichy France"
• I don't think there's any way to do tag switching like in EU3/EU4 style BRA into PRU into GER into HRE
• after D01 (Nationalist Spain) wins the civil war, it doesn't become SPA - even if it's released as democratic and joins the Allies; that means original tag is still releasable
• so you can have two Spains very easily
• this could be fixed in a straightforward patch
• there's also some shenanigans with East/West Germany tags, merging two Communist Chinas, and probably some others I missed.

Day of attack was February 7th 1944. I had initial shortages of oil, tungsten (Portugal decided to change its export laws), and steel.

Initial phase of the war went about as well as could be expected - I didn't attack Raj as I couldn't be bothered to micro everything simultaneously.

I tried to sneak across Swedish straits as they had just 2 divisions defending them, but they reinforced, so I stopped it. Briefly it was empty again, so I tried to sneak in again, but they reinforced a few hours too fast. Oh well, not a big deal.

I tried a different way of managing resistance - all police is put into one army, and 1-province long fallback lines are created in various resisting provinces. This seems marginally easier than manually telling my cavalry to strategically redeploy themselves.

In a bit over a month, first stage is complete:
• France, Belgium, Luxembourg, Germany, Italy, Denmark, Yugoslavia, Switzerland all taken
• Suez Canal, Gibraltar, Hong Kong, Syria, Palestine, Egypt, Tunisia all taken
• Raj cut at Dacca
• armies progressing a bit in West Raj, French Vietnam, and Finland

Next stage will be Estonia, Scandinavia, Raj, Mayalsia, and a bit more of African coast.

So far casualties count is 19k to 602k, and armies are now 3630k to 8070k.

 #hoi4

Was worth a try, but they reinforced it too fast.


It's going quite well without major surprises.


Post 16 - Originally published on Google+ on 2016-07-31 01:42:10 UTC


Troops I sent to Africa turned out to be of some use, as Allies packed it full with troops. Both West Africa and East Africa armies got very good pockets.

In North Scandinavia supply is really miserable, but it's slowly getting there.

Raj capitulated - and it had some really big and really miserable supply. It's not just infrastructure levels, it's how many states make up one supply region - which in turns lowers everyone's supply as you control only small part of incoming edge tiles.

Malaysia at least was nice in terms of both supply and pocketing. It's just one pocket away from being all mine.

The only downside is that Canada took over Galicia, which is technically mine, but neither Portugal nor Republican Spain will let me pass there by land.

For that matter Portugal seems to be sending volunteers to 8 of my enemies. I might need to do something about that.

So far casualties count is 104k to 2806k, and armies are now 3895k to 6672k.

I now have huge surplus of all resources except for the shortage of oil - and light cruisers (now version 4) have priority. My fleet is up to 51 ships, 1 of which accidentally spawned in Marseille, but it managed to get away in spite of enemy trying to attack it 3 times.

The plan is:
• finish off all Americans, Brits, and who knows who else in the Raj - then capture nearby islands; Australia is now a major, so I'll need to deal with it too, so might as well do it soon
• keep pushing in Scandinavia as much as supplies allow - this needs to be followed by invasion of the UK
• get some clay in Africa because why not
 #hoi4

Cleaning up resistance after Raj surrendered.


And they say there's nothing of value in Africa


Advancing runs into supply problems.


Why bother with tanks if infantry is so good at pocketing?


East African pocket


Canada stronk


And that how Raj fell. Those narrow advance lines tend to run into supply problems anywhere I try them, here it was particularly bad.


After nearly 5 months of fighting, it's still quite far from victory. The upside is that by the time I want to invade someone, my fleet will be ready.


Post 17 - Originally published on Google+ on 2016-07-31 05:10:34 UTC


It somehow took me very long time to figure out that supply in Scandinavia was so bad simply because infrastructure was damaged, and there wasn't really any deeper reason for it - as soon as it got repaired, I could do whatever I wanted there. Still, I preferred to move cautiously, so Sweden is only just on the verge of capitulation, and Norway is still quite far from collapsing.

I started island hopping - first Ceylon, North Borneo, and Philippines, then two invasions of Papua (I didn't even notice there was a strait between the two), then two invasions of Australia - in Darwin and Townsville.

Africa was waiting for improved infrastructure as well, front moving a bit, but not too far.

All this is really slow, but body count is extremely biased 137k vs 4285k, and armies are now 3888k vs 5758k.

My fleet is big enough that I can send half of it to UK just fine. Then again, I should probably take New Zealand while I'm there just in case it becomes a major too. And I'd prefer to use my whole fleet, just in case US accidentally figured out how to spam light cruisers too.

 #hoi4

Island hopping. I won't bother with Hawaii or Alaska, I'll get US from Atlantic side, but Australia is a major power somehow.


I seriously dislike how AI naval invasions with multiple targets always do 1:7 not 4:4. It's still safer than single landing.


One column follows coast to Malmo, second follows coast to Oslo. It takes time, but it's not like my fleet is big enough to cover two big invasion routes.


It seems that I somehow lost 1 division in Africa, no idea when or where. 47 divisions spread from one end of Africa to the other are not exactly much for daring maneuvers. I just column march pocket (for easy kills) or whole front push (for better supply) or forget about Africa for a while because it's the least important frontline.


Post 18 - Originally published on Google+ on 2016-07-31 20:25:48 UTC



I'm starting to question 7mnt 2mspart build - even with logistics companies it's taking a ton of supplies. 6mnt 2art 1mtank has roughly comparable stats (some better, some worse) but uses 1.00 supply instead of 1.23 (with my set of supports etc.), at cost of a 15% more IC.

I've been using infantry column orders as something that my army can competently execute and it takes no micro and tends to result in extremely skewed K:D ratio.

I finished off Sweden, Norway, Australia, and New Zealand - then I invaded Iceland, Greenland, and Scotland. UK is a lot better defended than in 1936 invasions, but I don't think it's going to survive long.

I expect UK to capitulate by the end of the year, but at this rate invasion of Canada will probably take place in 1946, and WC might have to wait until 1948 or so.

At least I'll have nuke tech in February 1946. I've built a bunch of nuclear reactors, so nukes will start coming probably March-April 1946.

Then again, game crashed once already, so it could end up like my Germany campaign on 1.0.

So far casualties count is 164k to 5108k, and armies are now 3891k to 5906k.

 #hoi4

Much more opposition than in 1936


Finally


Not sure if that was good idea. All victory points are in the South-East, and it's just two level-1 ports that brought almost no supplies. I should probably have landed in Canberra/Sydney/Melbourne area.


Sweden landed some troops, which was surprising as straits were blocked, but I don't usually bother clearing up random islands. I misclicked and had both fleets here not just one, so I did two invasions.


Infantry column tactic (drop off one unit per tile as you advance) on both sides. If you have initiative and a shitton of soft attack, it's best way to get whatever you want (huge pockets, key victory points) with very little micro.
Sometimes I tell everybody not in the attack to form frontline, sometimes I don't, it work about equally well either way.

The downside is that if one of divisions involved in the column loses organization, you'll


UK landings


Hungary stronk


Post 19 - Originally published on Google+ on 2016-08-01 04:43:59 UTC


I deployed all obsolete aircraft to some faraway air fields - this cost me manpower, but at least makes interface usable.

I split my navy into 4, trying to clean up whatever was left of Allied navies in Europe, and they were constantly fighting, but I have no idea if they were getting someone, or just getting into endless loop of spotting sub which then ran away.

I deployed some paratroopers just to clean up random islands to deny those subs any ports, but a lot of them paradropped with losses - in spite of nobody being on these island, not one shit, no AA, nothing. I don't even know how it works any more.

Their ship count decreased from 643 in August to 477 in December, so I guess I was doing something right.

By the end of the year I got South Africa, UK, Ireland, and even managed to invade Newfoundland. The only Allied countries which did not capitulate yet were Canada and US (both obviously majors), and there were some Allied forces in Africa, and presumably a bunch on random islands I never bothered to capture.

Newfoundland, Greenland, and Iceland were building infrastructure (and it was also queued in Kamchatka, but pretty low in priority list) in preparation for receiving some armies, but navies were pretty busy.

So far casualties count is 168k to 5645k and armies are now 4176k to 6231k. I'm obviously not killing them fast enough, as they've been training new troops faster than I destroy them.

 #hoi4



Post 20 - Originally published on Google+ on 2016-08-01 06:40:17 UTC


It was risky, but then what else could I do (except go through Alaska or South America). I invaded Quebec from Newfoundland. I thought I'd switch mountaineers for marines in those few divisions, but somehow I forgot to research marines ever. Oops.

Well, I prepared invasion in deep nowhere, with plan to build a port there before bastard figure out what happened and in the mean time I started dropping nuclear bombs.

6 bombs reduced Canadian national unity from 90% to 22%, which was good enough to actually take them without conquering every last bit of wasteland.

Unfortunately they managed to send armies to meet my invasion, and I could barely hold my ground while ports and infrastructure were slowly building up.

Even more unfortunately due to really retarded way supplies work in the game, that wouldn't help, they were flowing backwards from no-infrastructure Quebec (as I had two ports there, but didn't fully control) to high-infrastructure Labrador (which had only one port, but I fully controlled so I could fix its infrastructure). Usually supply system bugs are tolerable, this one was really nasty, as I could have easily started moving forward if it was fixed. Instead I had to build 3 ports in Labrador...

Fortunately second invasion at Halifax worked out better. Unfortunately they suffered massively in process, so I waited for second port to be built in Halifax, from better side, before sending reinforcement.

After that it went smoothly - I captured airport in New England, dropped 4 bombs on US from there, dropping their national unity from 55% to 20%.

Finally, after year of heavy fighting, by end of 1946 I managed to connect by two invasions, and wreck both USA and Canada quite well, getting them to brink of capitulation.

Unfortunately meanwhile Brazil joined the Allies as another major, so it's going to take a while longer. I have 35 bombs and produce them in huge numbers, but it's not like Brazil would just capitulate because I drop a few there.

So far casualties count is 314k to 7019k. Armies are 4160k to 6151k.

And Allies only have 433 ships left to my 209.
 #hoi4

















Post 21 - Originally published on Google+ on 2016-08-01 07:46:54 UTC


Canada capitulated before Christmas 1946, and US before end of January 1947, with no more nukes necessary.

Unfortunately Mexico joined in addition to Brazil, so I had two majors to defeat. Allies army was reduced to just 1975k at this point - 833k of that USA divisions that somehow escaped surrender.

I really didn't want to bother with another naval invasion nonsense, so I declared war on everyone between Mexico and Brazil, and dropped a bunch of bombs on Mexico City, so Mexico capitulated mid March.

Unfortunately from that point on I started doubting my idea of invading my land - it was narrow low infrastructure passage, and everybody was throwing all they've got at stopping me there.

After a few pockets sufficiently reduced enemy numbers I told African field marshal to just finish them off.

Casualties climbed to 370k to 8913k, but Allies armies still have 1823k men - mostly due to new members.

Of course Colombia and Venezuela are majors now, because why not.


I think it should all be over by 1948 or 1949.
 #hoi4







Post 22 - Originally published on Google+ on 2016-08-03 03:30:54 UTC


I assumed the war will end with capitulation of the US, and I'll have a good chunk of the world to conquer afterwards - but instead I'm goint to Brazil anyway. It was also helpful initially to stay at peace with Portugal and Netherlands, so I can trade with them, but it's no longer relevant. So instead fabricate on everyone.

Going through Central America was extremely painful - and they've thrown like 20k planes or so over it, but then I've noticed that they've been trying to stick 19183 airplanes in airport with 800 capacity, so I can actually outshoot the bastards. Well, it would have been a lot faster if I knew it earlier.

Somehow that stacking penalty didn't seem to bother AI, and we both lost similar numbers of planes.

By the end of the year, only Brazil was still fighting - and a few South American minors were yet to be forced into the war.

Even with me automating most of the fighting, casualties are 437k to 10,379k, and armies are 4172k to only 799k.
 #hoi4

Getting through Central America was really slow. I had a backup plan of some extra naval landings, but ended up not using it because I accidentally deleted it when I was cleaning up orders on Cuba's landing. Cuba was delayed because of their focus button delaying fabrications. All of them joined us after Colombia was taken.


If there's a way to have good K:D ratio is the air, I don't know it. 2146 heavy fighters take 86k men to operate, so I hope they don't suffer 100% losses when planes are lost, or that would be very painful. Probably not as I lost only 67k men in last half year, and that's with AI-automated frontlines.


Everything except South America is taken or random island belonging to a country which already surrendered.


Post 23 - Originally published on Google+ on 2016-08-03 18:50:28 UTC


My advance was stopped by horrible supplies in Amazon, so I detached an army to deal with West Coast minors - with some help from nukes, as they were fairly obnoxious.

Of course everyone was a major. No big deal, I just kept going until I got Brazil to capitulate. And Repubican Spain with zero victory points and only a few random islands became a major too.

Not a huge deal as 1-division naval invasions take only 3 days to prepare.

And so on August 21, 1948, Triannon got completely revised.
 #hoi4

There will be no border conflicts if there are no borders.


At some point the game will add a way to damage own infrastructure, as that seems to be the most effective strategy against me.


Propaganda confetti!


Everybody is major. Republican Spain joined the list too a bit later.


Final resistance.


Wait, how is that not over yet? Republican Spain, leader of the Allies...


Post 24 - Originally published on Google+ on 2016-08-04 04:01:14 UTC


One small surprise I had in my Hungary campaign was that my 7mnt 2mspart's armor was getting pierced in South America by regular infantry. I thought maybe they were using support antitanks, which would be surprising, but turns out not so.

It was big wtf, but it turns out infantry piercing goes like:
• basic eq - 1
• weapons 1 - 4
• weapons 2 - 5
• weapons 3 - 10
• bonus from infantry antitank techs - 200%
• (all those techs are very high on AI priority list)
• so AI divisions had piercing in low 20s, just as my divisions had armor

6mnt 2art 1mtank will never have this problem, as it always has armor >30.
Neither would one with modern spart - something I could switch to by that time, but I somehow couldn't be bothered.
Or presumably if I got medium spart variant up to level 5 armor, it would be at almost 30.
 #hoi4