Shannon V. OKeets -> RE: When? (12/2/2010 10:42:47 PM)
|
December 1, 2010 Status Report for Matrix Games’ MWIF Forum Accomplishments of November 2010 Project Management I monitored all the threads in the MWIF World in Flames forum daily. Programmer Dreams I had a dream this past month which you may find amusing. Since the dream is all about programming MWIF, you can take it as my subconscious’ report for the year-to-date. Skip to the section on Hardware and Software if this holds zero interest for you. As background, I used to play golf 3 days a week before starting work on MWIF, but over the past 4 years I have only played twice. I had a 6 handicap so I usually shot in the 70's. Because I played on public golf courses, it was very important to not dawdle and always keep up with the group playing in front of us. This short story is as accurate a remembrance of my dream as I can recall. The dream started with me arriving at the golf course early in the morning, and being in the first foursome to tee off that day. I didn’t know anyone else in my group, but that was common even when I was playing 3 days a week. The other guys hit their drives and then I was on the tee. I knew I would be rusty and that was confirmed when I hit a couple of drives off into the trees on the left. After giving myself two Mulligans (pretending my first two swings never happened), I decided to go with my 7 iron off the tee - the club with which I am most comfortable and therefore the most reliable. I hit a very good 7 iron shot down the middle of the fairway. Once the other guys had hit their second shots, I needed to choose a club for my second shot. The hole was a short par 4 and I had a good chance of reaching the green, although the fairway was very narrow with trees lining both sides. But I wasn’t sure of the distance to the green so I went looking for a yardage marker. That took a while since I had never played the course before and the other guys couldn’t locate a yardage marker either. I finally found a sprinkler head with 200 yards printed on it and by pacing off the distance from there to my ball I figured I had 190 yards to the hole. That’s usually a 4 iron for me, but being rusty I decided on a 3 iron. However, when I looked in my bag there were all these extra clubs. It seemed I had put in both my old and new sets of irons, so I had two of everything. Even worse, one of the other guys in my foursome had put most of his clubs in my bag, so I was carrying about 30 clubs instead of 14. I asked the other guy what he thought he was doing, and he said that since I had such a nice new bag with extra room, I could carry his clubs, since his golf bag was old and worn. I argued with him for a while but eventually took out my new 3 iron and walked ahead of my ball to see exactly in which direction I wanted to hit it. The green was slightly off to the right so I planned for my shot to go down the right side of the fairway. Of course when I went back to my ball, I couldn’t find it. My father showed up then. He was playing in the following foursome and we let his group “play through” since we couldn’t find my golf ball (my father always thought I did things too slowly). Then a foursome of ladies came up and they helped us look for my ball. They belonged to the Sweet Adelines (women’s barbershop quartets) and at some point they were singing. One of them asked if I was playing a Napoleon golf ball and I said, maybe (my ball had NAP printed on it). But what she had found was a rather small cardboard box and when I opened it, inside was a shoe with the brand name Napoleon on it. I then decided to look for the yardage marker again, but couldn’t find that either. Mumbling and grumbling, I decided to just hit another golf ball about where I guessed my original one had been. As I settled over the ball, calming my nerves and breathing, and running through in my head my litany of things to remember about making a good golf shot, a large RV roared onto the fairway pulling a trailer. The RV came in from the right, crossed the fairway about 50 yards in front of us, and crashed into the trees on the left. It then proceeded to tilt towards us and rolled over twice, with the trailer becoming unhitched and rolling off to the right. A man and his wife got out of the RV with 3 kids and they were all scrambling around the two vehicles. I yelled at the guy that he was completely blocking the fairway but he just ignored me. Then a big backhoe with forklift prongs showed up and started lifting up a large fallen tree to clear the fairway. But somehow the tree got tangled up in overhead power cables which fell on top of the two vehicles, shooting sparks everywhere. After a while all of that got cleared up but before I could hit my second shot the police showed up. They said the area was a crime scene and we wouldn’t be able to play golf on that fairway today. Not being stopped that easily, I went through the woods on the left until I came to a small clearing that looked out over a nice green valley - which was part of the first hole’s fairway. The green was on the far side of the valley and elevated. I was at the same elevation as the green and had a clear shot across the little valley. It was an odd shaped green, with a small portion on the right front which angled off to the larger portion in the back left. The whole left side of the green was protected by a string of sand traps, with another sand trap behind the green on the right side. I had a clear shot across the valley to the pin, which was in the right front. Going back to my bag for a 4 iron, I found that instead of removing his clubs from my bag, the other guy had put in a whole lot more - there were now like 50 clubs in the bag. To hide what he had done, he had turned all the clubs upside down so only their grips were visible. It took me a long time to take out all of his clubs so I could find my own. Again I settled over the ball, calming my nerves and breathing, and running through in my head my litany of things to remember about making a good golf shot. At which point a troop of boy scouts charged into the valley and began setting up camp. There were 30 to 40 of them and I yelled at them that they had to move since I was going to hit my shot right over their heads. They grudgingly left but were immediately followed by a dozen college fraternity guys who were more difficult to get to leave. As the frat guys left, I got the distinct impression that they would be back later, to play college pranks on me. My second shot was good and landed on the green but it was to the left and on the back side. I would have a long putt for a theoretical birdie, but most likely would make par. All of this had taken 2 hours. Given that a group is scheduled to tee off every 6 minutes, and that some groups are six-somes instead of foursomes, there were now about 100 guys backed up waiting to play the first hole. Even worse, everyone else who would play that day would also have a 2 hour delay, all due to my troubles on the first hole. Speaking of which, I still needed to finish the first hole and there were 17 more to play. The day was still bright and sunny. I then woke up and since it was 5:00 am I decided to work on the code for MWIF. Explanation In case you haven’t figured it out, here is some of the symbolism. Hitting golf shots = writing code. Finding the ball and figuring out the distance = defining the rules/program specifications. Golf clubs = software routines/modules. The other golfer in my group who keeps putting his clubs in my bag is Chris, who wrote the CWIF code. The RV = the upgrade to Delphi 2010 to support Win7, and the trailer = the Theme Engine upgrade. The cops = my conclusion that the Delphi 2010 debugger was unusable. The boy scouts = the beta testers finding bugs and things in the player interface that need improvement. The college guys = the WIF FE rules grognards. The golfers experiencing an intolerable delay = the players who want to buy a finished MWIF. You might want to read through the dream again and interpret some of the other images and events. Hardware and Software I have one problem with Theme Engine for Win7: it is taking too long to switch between major powers. For example, when choosing an action for each major power on the Allied side, the Choose Action form appears 5 times, once for each major power. When the deciding major power changes, the form refreshes to show the background colors et al for the new major power’s theme. That takes about 4 seconds, when it should be instantaneous. That’s too long given the number of times the deciding major power changes during a turn. I’ve got some ideas about why this happens and a couple of possible solutions. I converted the Unit menu from standard Windows style to Theme Engine, but I still need to perform that task for the Main menu. Beta Testing I released versions 6.00.02 (20 fixes), 6.00.03 (2 fixes), 6.00.04 (21 fixes), 6.00.05 (12 fixes), and 7.00.00 (9 fixes), to the beta testers last month. This totals 5 new versions and 64 fixes, which is way under over my previous 4 month average for fixes (112). I changed the numbering to 7.00.00 because I added 3 new phases to the sequence of play - more on that below. The drop off in the number of bugs fixed was caused by my rewriting/restructuring ~6000 lines of code in addition to creating 3 new phases. I cleaned up all known bugs related to partisans, air rebase, expending oil points, and US entry options. I tend to fix bugs in groups like this so I can work on a single section of code - it always takes a few minutes to refresh my memory about how things work for a rule. For rebasing carrier air units that are aboard carriers, I needed rule clarifications from the rules grognards and (eventually) Harry Rowland. Version 6.00.03 only fixed 2 items because I had removed a bunch of code that should have been left in place. I needed to quickly upload a new version with the old code restored to keep the beta testers productive. This error on my part was due to the failure of my normal practice of inserting comments so I will understand what the code is doing 1 year in the future. My newly revised practice is to insert comments so I will understand what the code is doing 5 years in the future. The comments I had made in 2006 were so vague that I had misunderstood them. I rewrote all the code for determining and finding valid rebase hexes. There were two bug reports which prompted me to do this: the search time was taking too long (minutes for a single air unit), and some valid hexes were being missed when triple the range was possible. The CWIF algorithm avoided the first problem by using Assembler code to speed up execution (I had replaced all Assembler code with Pascal code to achieve compatibility with operating system upgrades). The second bug was simply because the CWIF algorithm was wrong. I also revised the code to support clarifications from Harry on where carrier air units can rebase given where they start. The new algorithm is far superior in that it preforms two searches simultaneously (testing against double the range when flying over enemy hexes and triple the range if enemy hexes can be avoided). It also maintains a list of hexes already examined and a list of sea areas already explored. The latter list is only for carrier air units that started on land and could rebase to a carrier at sea. Both of these lists are stored as arrays so a fast check can be made for whether a hex has already been evaluated. The CWIF algorithm made repeated searches through long lists - which is why it took so long when the range of the air units was large (e.g., > 12). I tested a naval air with a range of 22 using the new algorithm and the response time was less than a second. For most air units the response time is instantaneous. Another test I made for using triple/double range was from southern England to Gibraltar for an air unit with a range of 10. It was able to find the all-sea (no enemy) loop around an Axis controlled Iberia traversing 28 hexes. By the way, the formula for counting the number of possible rebase hexes is 3X(X +1) + 1, where X is the range. So a unit with a printed range of 22 flying at triple its range is 3*66(66 + 1) + 1 = 13267 possible hexes, or about 1/5th of the global map. The search is much harder than simply checking each hex as a viable destination, since hexes controlled by neutral countries have to be avoided in finding a path to each hex. Fatal errors during program execution now appear to be solely related to my recent changes to the code, so I fix them quickly. Saved Games Saving and restoring games remains stable. I did fix one strange bug with creating AutoSave directories that one of the new beta testers encountered. Map and Units Rob continues to send me updates of the naval unit writeups. I renamed the Teheran militia unit so it matches the city name on the map. Scenarios and Optional Rules Nothing new here. MWIF Game Engine and CWIF Conversion The three new phases to the sequence of play I added are: Production Planning Final, Search and Seizure, and Scrap Destroyed Units. The new sequence of play is: . . • Preliminary Production Planning • Stay At Sea A • Stay At Sea D • Return To Base A • Return To Base D • Use Oil • Final Reorganization • Break Down • Final Production Planning (new) • Search and Seizure (new) • Scrap Destroyed Units • Naval Repair • Production . . The Search and Seizure (S&S) phase was fairly complicated to code because there are a lot of conditions that need to be satisfied before a player can execute a search and seizure. Other annoying elements are that a resource could pass through two or more sea areas that were S&Sed, but obviously the resource would only be ‘lost’ once. More difficult to code was when a non-oil resource, an oil resource, and a build point are going through a sea area and of the 3 convoys being used, only one can be S&Sed. I arbitrarily decided that the lowest value item (non-oil resource) would be lost first to S&S. I placed the highest value on build points. This could be handled using random numbers but that seemed like more effort than the rule deserved. If you are interested, a couple of the Pascal routines for search and seizure are appended to the end of this report. I added the Scrap Destroyed Units phase because the beta testers have been complaining for over a year about having to make a decision about scrapping every time a unit gets destroyed. That digression could occur in a couple of dozen places in the sequence of play and it was a distraction from what was immediately occurring (e.g., during an air-to-air combat). By simply placing all destroyed units in a big pile and letting the players decide which to scrap once at the end of the turn, the speed of play improves significantly. There are still two more subphases that need to be add to Land Combat Resolution. Patrice, and others, pointed out that the decision on destroying units must be made by the defender before the attacker chooses whether to convert shattered results into retreats. And disorganizing attacking units needs to occur after the advance after combat. Currently all those decisions/events occur in one subphase and are not done in the order dictated by the WIF rules. I’ll try to get that fixed new month - at which time I will have the full sequence of play finalized and coded. I rewrote all the code for moving units from the moving stack to a hex on the map. The CWIF code had been driving me crazy for years and I was having a very difficult time debugging land and naval moves (yeah, I know, the land moves should be easy to code). However, the CWIF code was a very long series of if statements. I restructured it using a case statement based on the current phase & subphase of the game. I did the same for Undoing unit moves. Together those routines had been roughly 3500 lines of code. As an example of why the naval moves are so hard to code, consider a CW naval transport and the Queens located in London. During the naval movement phase the transport loads a division in the port and then both ships move into the North Sea. The transport stops in the North Sea and pick up a second division from Portsmouth. Then the Queens enters Plymouth, where it picks up an infantry HQ, goes out to the Bay of Biscay, enters Bordeaux where it drops off the infantry HQ and picks up an elite infantry corps, reenters the Bay of Biscay and thence into Cape St. Vincent. Ok, now the player wants to Undo all those moves, so it is up to the program to have maintained a record of what got loaded & unloaded where. Throw in the possibility that the Germans attempted an unsuccessful interception in the North Sea and only some of the moves can be undone. There are also rules regarding foreign troop commitments for the BEF in France, so if the HQ and infantry corps are switched, some of those moves by the Queens might be illegal. There is also the possibility that it is late in the war and some of the units are US or Free French, so compatibility between the units has to be considered. This is just for naval movement. There are more rules that apply during the return to base phases and yet more if the naval units are rebasing because they were overrun. Very complex stuff to code. Player Interface I changed about a dozen places in the code where a Yes/No question was asked and the player had to answer without having access to information (e.g., the map). Most of the time, these decisions are easy to make, but there are cases where the player might want to review some stuff before deciding (e.g., denying the USSR claim on the Finnish Borderlands). The changes I made enable him to now do so for the more complex situations. Basically, the detailed and global maps and all the informational forms are now available. I created a new form for Search and Seizure. That whole phase is brand new and needs alpha testing by me before the beta testers take a crack at it. It’s hard to test since there have to be very precise conditions in place before search and seizure can be executed by a major power. I revamped the Victory form so more room is available for showing the victory points. At times there are little messages included to explain the victory points, and more room was needed. As often happens, because I was forced to make changes, I ended up with a better looking form in the end - I’ll try to remember to post the revised one in the next couple of days. I rewrote all the code for generating text messages as the cursor scrolls over the map with a unit (or units) in hand. These messages inform the player whether the unit(s) can move to the hex under the cursor and if not, why not. The beta testers had complained about some of the messages being wrong, or at best confusing. But the code was equally confusing - being 2500 lines in a series of if statements. I restructured it using a case statement based on the current phase & subphase of the game. In reality, my motivation for fixing these messages was that I was having trouble debugging naval moves and the erroneous messages were really not helping. Internet - NetPlay Nothing new. PBEM Nothing new. Artificial Intelligence (AI) Nothing new. Player’s Manual Nothing new. I need to go through the section on the sequence of play and bring it up-to-date so it includes the 3 new phases mentioned above. I also have to add a screen shot and text for the new Search and Seizure form. Tutorials, Training Videos, and Context Sensitive Help Nothing new. Historical Video, Music, and Sound Effects Nothing new. Marketing Andy Johnson (who did the work to develop the MWIF fan site from nothing) has found a new administrator for the fan site. As I write this we are still getting Paul established as a beta tester. Communications Nothing new. ===========================
// ****************************************************************************
function UFilterSearchAndSeizure(const U: TUnit): Boolean;
// ****************************************************************************
// • you must have an SCS, CV, or SUB in the sea area;
// ****************************************************************************
begin
Result := (MajPower(U) = UFMajorCountry) and
(U.UnitType in [utCarrier, utLightCarrier, utBattleship, utCruiser,
utLightCruiser, utAuxiliaryCruiser, utASWEscort,
utASWCarrier, utSubmarine]);
end;
// ****************************************************************************
function UFilterSearchAndSeizurePrevention(const U: TUnit): Boolean;
// ****************************************************************************
// • there must not be an SCS, CV, or aircraft unit with an air-to-sea factor,
// controlled by a major power with which you are at war in the sea area (nor
// a US unit that can escort there because of US entry options 11, 20, 29,
// 38, or 50 ~ see RAC 13.3.2).
// ****************************************************************************
var
Surface: Boolean;
NavAir: Boolean;
begin
Surface := (U.UnitType in [utCarrier, utLightCarrier, utBattleship, utCruiser,
utLightCruiser, utAuxiliaryCruiser, utASWEscort,
utASWCarrier]);
NavAir := (U.UnitType in AirUnitSet) and
(TAirUnit(U).AirSea > 0) and
(U.TransportedBy = nil);
Result := (UFMajorCountry.Relations[U.Country] = crWar) and
(Surface or NavAir);
if Result then Exit;
// ****************************************************************************
// Check for US entry option exceptions.
// ****************************************************************************
Result := (UFMajorCountry.Relations[U.Country] <> crWar) and
(UFMajorCountry.Side = sdAxis) and
(UFConvoyMajPow = UnitedStates) and
(MajPower(U) = UnitedStates) and
(Surface or
(NavAir and
USEntry.OptionChosen(useAirEscort))) and
// ****************************************************************************
// If unrestricted naval warfare has been declared, then all US combat units in
// any section box in all sea areas prevent search and seizure.
// ****************************************************************************
(USEntry.OptionChosen(useUnrestricted) or
((U.Section = 0) and
// ****************************************************************************
// If Arm Merchantmen has been declared, then US combat units in the zero
// section box of any sea area prevent search and seizure.
// ****************************************************************************
(USEntry.OptionChosen(useArmMerchantmen) or
(USEntry.OptionChosen(useNorthAtlanticEscorts) and
(UFSeaArea in [EastCoast, NorthAtlantic, CaribbeanSea])) or
(USEntry.OptionChosen(useEastCoastEscorts) and
(UFSeaArea in [EastCoast, CaribbeanSea])))));
end;
|
|
|
|