By day a mild-mannered software engineer - by night a caffeine fueled coding machine. This includes my log of development activities and observations regarding Pacific Islands Campaign - Guam.
Wednesday, December 18, 2013
First Life Recap - April 2012 - December 2013
I see that I have not posted in a long time here.
There are some reasons for that. To sum up, I've been too busy with First Life (IRL) to worry about Second Life (blogging, etc.).
What happened? In no particular order:
My wife gave birth to our son.
We sold our house.
Moved across town to an apartment.
We had Lennar build a new house; moved in.
A re-org at the office moved my development group into the main IT department.
I was reclassified from a Software Engineering Supervisor to a Senior Solutions Designer (aka architect).
I took on additional responsibilities at work - participating in a process/guidance team. My contributions so far have been in the areas of unit testing and app logging.
Helped my son deal with pyloric spasming.
I got a CPAP machine.
Completed a feasibility study for a new personal business project involving web-based community services. This involved proof of concept code using Authorize.Net APIs.
Started work on a laundry timer Windows Phone app.
Resumed work on the PIC-Guam prototype.
Wrote and released a "How to Create Apps" Windows Phone app located here.
I decided back in Q3 of this year that I would work 3-5 hours a week every week on personal projects. I split that time evenly between PIC-Guam and other projects.
I put in about 100 hours since May 2013 on PIC-Guam prototyping. I did the following.
Added automated unit tests to fix issues with range calculations.
Completed the level 1 Fire Combat AI.
Completed the level 1 Movement AI, including optimizations so the AI runs fast.
Completed an initial design for the level 2 AI.
Randomized casualty allocation.
Added suppression effects.
Added assaults to the game system.
Some small fit and finish fixes.
Some internal refactoring where necessary.
The game runs all the way through the Orote scenario with the US run by AI.
Next steps are to add assaults to the level 1 AI, and then to tailor a variant of the AI code for defense for the Japanese side.
The overall plan remains to complete the proof of concept app and then talk to Chris about completing the game for all scenarios and putting it on the Grognard Sims store. And then the next game and the next and the next!
I'm working on the AI code for PIC-Guam. In the last few months I have been able to spend a few hours optimizing the fire combat AI. I was able to get it to work reasonably well by replacing or changing a lot of LINQ statements from my "hello world" version from last year. This included movement code based on locating the phasing side's unit for maximum combat effect.
It did not scale.
I got three Japanese units to execute defensive fire, movement, and offensive fire on successive turns until the eight US units were eliminated. This worked rather well, but I needed to try the US side, as this approach would work in the offense but not the defense. I added code to run the US or the Japanese side (or both) in the AI depending on a selection.
This blew up in a combinatorial explosion resulting in OutOfMemoryExceptions. Every time. Optimizing the code was not going to solve the problem. The algorithm sucks: for a given set of attackers with range of target units it is O(Attackers ** Targets).
I decided to separate the movement AI from the combat AI. I will move the HQ units relative to the local FEBAs and other friendly HQs. Based on this, I will move the units to stay uniformly distributed to the FEBA in their respective HQs' sectors. Artillery will probably congregate near HQ units. As the lowest echelon HQ units need to be within 6 hexes of the FEBA in order for subordinate units to be in supply, this means most (US) artillery units will range the FEBA.
I did a proof of concept this afternoon. I hard coded a FEBA and let the allocation code run a movement. This worked fine for the US. I then proceeded to try combat. Which exploded.
I fixed the explosion by adding code to bias the AI in favor of attacks against adjacent units. This reduced the number of potential fire allocations by a factor of 50. For the eight US units against 3 Japanese units, it runs in almost no time: .167 seconds for 1024 fire allocations.
I may have to revisit the performance as I scale to the full Orote scenario, and again as I scale to the full ORBATs.
Total time this weekend was 8.5 hours.
Next step is to add code to determine a local FEBA. I can review the Eylau AI for useful techniques, and I can manipulate the test database to try different scenarios. It's also a good time to complete the Orote scenario ORBAT.
I am continuing to work on the prototype for the AI and UI for PC PIC-Guam. This weekend I wrote the evaluation function for the Fire Combat AI, hooked the AI up to the game system, and got the Japanese to conduct a Defensive Fire. I'm filling in around the edges now. The UI is not displaying color overlays to indicate the target hexes of the AI's fire combats. I also have some additional testing to do to make sure the game phases out of AI fire phases OK. After that I need to make sure the AI moves execute, and then I will change the game to have the AI run the US side.
I've done about 8 hours in the last few weeks. Not as much as I wanted, but not too bad. I implemented a fire combat AI prototype based on brute force as I mentioned in my previous post. I took all the shortcuts I could, primarily basing it on LINQ. This worked, but was very slow. For three firing units and 7 potential target units, the code produced 392 fire allocations in 446 seconds!
I then proceeded to optimize this code. In the first pass I improved the logic. The code had been doing repeated searches for hexes and enemies in range at the leaf nodes of the processing. By pre-calculating these before running through the permutations, I reduced the time to around 10 seconds.
This was a decent improvement, but not nearly enough to scale for the introductory scenario, let alone the full campaign.
I then profiled the code and saw that it was spending all its time in LINQ-driven code to determine the hexes within a given range/radius. I rewrote this, replacing the LINQ with code based on directional transforms. This reduced the time for the same problem to 0.035 seconds.
Doing some work on the prototype for PIC-Guam today. I did an hour yesterday; trying to build some momentum. I am implementing a prototype AI.
Today I had to refactor some code pertaining to movement footprint generation in order to reuse it in the AI.
My first approach to this AI is brute force. I am traversing the phasing unit list, generating all possible attacks permitted by the movement footprint. For each possible attack (firing unit in hex X versus target unit Y) for a unit, create a new allocation (list of such attacks) containing that attack and recursively call the allocation method for the next unit. As an allocation is completed (by adding an attack for the last unit in the list), concentrate the attacks in the allocation so that all units attacking the same enemy unit participate in the same FireCombat. Then evaluate the allocation by summing average fire combat results for each attack. The top N allocations are kept, and the actual allocation is randomly selected from among the top N allocations. During movement phases, the selected allocation also determines unit movement: each unit is moved to the
This will produce a very large combinatorial explosion, especially for the full order of battle. The questions are whether it will work in the first place for the small Orote scenario, how slowly it will run, and whether the results are any good.
I can reduce the processing and memory requirements of this brute force AI in several ways. I can pre-calculate the movement footprints and attack footprints for each of the phasing units. I can sort those movement/attack footprints by descending size and reorder the unit list accordingly, minimizing the number of nodes in the notional graph of partial allocations. I can also prune the movement footprints by accounting for overstacked hexes and removing allocations from consideration that exceed a threshold. I think I can also remove allocations that result in very few attacks (for the US side). For the Japanese side I may have to increase the difficulty by min-maxing to select the most casualties inflicted versus the least casualties incurred within a subsequent phase or two. Also, the Japanese side will need to constrain their movement in order to fully occupy the current generated FEBA line.
I'll eventually have to add some additional code to split out a certain number of Japanese engineers to create fallback defensive works. I'll need to control movement of AAA units with separate code as well in order to reduce the effects of US air.
It's been almost a year without blogging. Let me sum up.
I changed jobs from Senior Developer to Architect and have been holding down a Development Supervisor's position since February. I participated in a due diligence for an acquisition. I performed technical reviews on two chapters of an upcoming MS Press title. I scrubbed the rules and playtested several titles for Grognard Simulations: DRK - 3Pz, PIC-Iwo Jima, Hafid Ridge, Operation Gazelle, and Telnitz. I volunteered a couple of times for Habitat for Humanity builds.
I also managed to log around 40 hours (in a year :( ) of work on PC PIC-Guam.
In the meantime my daughter has gone from barely crawling to running and talking. She's high maintenance but worth it.
The maps are beautifully executed and easy to read. The counters are good: the die cuts are crisp and well registered, and the counters punch easily with no separation. All the charts are well laid out and easy to use. There were a few minor typos in the rules book but, as I said, this was a preliminary copy. I pointed out all the issues I could find to Chris, and I'm certain the production copies have the necessary corrections.
I setup the Japanese counters on Saipan. This is a useful and necessary step for the Japanese player. Necessary, because you can't play the game without first setting up the counters. Useful, because it gives the player an idea of what can and can't be done.
The "center of gravity" of the Japanese units on the island is in the geographic center of the island, and near the northern beaches. The rules prohibit free setup of units except for three companies of naval troops, and only three fortifications may be placed on beach hexes, though a total of 18 fortifications may be placed on the entire island.
Based on these limits, I would recommend a strategy similar to the de facto historical one. Similar, but not quite the same. Historically the Japanese fell back to the north and defended stubbornly. I recommend the same approach, but suggest it be done systematically. Place the three naval companies and the three permitted fort counters on the northernmost beach hexes. This is a forlorn hope as the odds are against those units surviving the amphibious assault phase, and the southern surviving unit will almost certainly be annihilated during the remainder of the turn. Still, these units will buy time. All units north of the lines of fortification counters head south, except perhaps for some engineering companies as described below. These units will be needed in the south early on anyway, so move all that are not needed to prepare fall back positions.
Carpet the hexes from 3717 southeast to 3219, forming a line across the island. Do the same thing from 3817 to 3320. Place the last three forts on 3420, 3521, and 3620. Have all units south of that line fall back towards that line. Sacrifice a few units if needed to slow down the US advance. Have any engineering units in fortification hexes upgrade those fortifications the first turn. (Remember 3420, 3521, and 3620?) Engineering units will continue to pave the north half of the island with forts. Once arriving at the first east-west line of fortifications the US units should have to struggle against fortifications all the way to Marpi point.
Once the Japanese have consolidated to the north, always fight in the best terrain and under forts. Attrition is the key. Always keep six steps of units in each hex on the FEBA to ensure the hex will not be overrun. As long as you can feed units into the line, the US cannot advance. Try to channel the US units into clear hexes where possible to maximize casualties.
Don't place artillery in clear hexes in order to avoid counterbattery fire.
Consider falling back occasionally in order to provide subsequent opportunities for Defensive First Fire. Also fall back to shorten lines as casualties mount and to skip over clear terrain that does not favor the defense.
Always cause casualties. The odds are extremely against the Japanese player achieving the time limit victory conditions. Most likely, the US will be knocking on the door right around the timing in the historical schedule. The best the Japanese side can hope for is to cause enough US casualties to reduce the victory level, and perhaps cause enough caution in the US player to have a better chance of delaying past the historical outcome.
The final bit of advice I can give the Japanese player is to use Banzai attacks frequently and prudently. There is no US Defensive First Fire at night, so you can safely mass and shift units. The 3x attack factors multiple and the +3 die roll modifier for Banzai attacks allow you to attack stronger units or stacks with weaker units and still cause casualties. Consider having an engineer platoon with artillery support Banzai charge a lone infantry company in clear terrain. The odds will be about 1-2, and the net DR should be +4. This gives a 2/3 chance of eliminating a company with a platoon.
Next I will compare company counts, average attack/defense factors, and total steps for the Japanese and US forces. I will also setup the units on Tinian and write up some notes on that part of the battle. It may be some time before I complete this...check out my "command central" for working on these notes, especially the background.
I'm working on the fire combat model for the PIC-Guam prototype. I added a FireCombat class to contain the information about the combat. I added a Turn class with lists of FireCombats for the US and Japanese fire phases, and added a list of Turns to the Game class. Then I got down to work. I added a bunch of code to support combat results table (CRT) processing. FireCombatResolution, OddsRatio and FireDieRollModifier are all enums. I also added FireCombatCRT and FireModifier classes, and nonserializable static lists of same to the main FireCombat class. Finally, I added a constructor to FireCombat and a couple of methods to setup the lists of FireCombatCRTs and FireModifiers.