Dear Globulation 2 gurus, Okay, I have revised my proposal for a state machine for the building life cycle. There were some single-letter names that I have expanded into self-describing words. I have made the notation more C++-like. I have added more explanations. I have also fixed a bug where the older version of this proposal didn't actually solve the building-site-abuse problem; it does solve this problem now.
The technical details follow below. Comments are welcome! Is this a good idea or does it suck? Joe ---------------------------------------------------------------------- Here is a suggested state machine for the building life cycle. This proposal solves a number of problems with the previous system: 1. Clearing is automatically requested for new buildings and upgrades that will make larger buildings, saving the user from the pain of setting clearing areas and flags before starting construction. 2. The user can request direct construction to any desired level without stopping at the intervening levels. 3. This proposal solves the bug where upgrading is silently canceled when resources grow on the larger area needed before all the globules are out of the building and out of the larger area. 4. Abuse of construction sites is impossible, because the building does not occupy any space until the first resources are supplied. 5. Visually distracting forbidden/guard/clearing areas are removed from the areas occupied by buildings. 6. This proposal has a clean, precise semantics which is likely to lead to fewer bugs (e.g., it would probably have helped avoid the repair crash bug in glob2 version 0.8.22, because the desiredLevel and currentLevel values are tracked separately). 7. In the new system, all of the different levels of a kind of building are now considered to have the same type, whereas in the previous system, they are all different types. This will make it easier to develop new features. 8. There is no need to repair before upgrading (is there now?), as the needed amount of resources will be calculated correctly. 9. Attempts to build on unsuitable territory (which can happen when requesting a building site on undiscovered territory) are properly cleaned up once the unsuitability is discovered. (In the previous system sometimes a forbidden area is left behind.) This proposal has benefited from comments by Eli Dupree, Leo, Kai, and Xylix. The proposed new system is as follows. Each building B has several adjustable values associated with it: its type (B.buildingType), its state (B.constructionState), two levels (B.currentLevel and B.desiredLevel), and its number of requested workers (B.requestedWorkers). During ordinary use, B.currentLevel == B.desiredLevel. It is only during the construction/upgrade/repair process that B.currentLevel can differ from B.desiredLevel. Each building also has two sets of resources: its construction resources (all the resources used so far to build and upgrade it), and its supply resources (the resources gathered for ordinary use of the building). While in any state, as hitpoints are lost due to damage, the construction resources of the building are reduced appropriately. There is a table Work such that Work(T,S,L) gives the number of workers to use for a building of type T in state S at level L. (For the state USE (see more on this state below), Work(T,USE,L) should only be non-zero for buildings that need workers to supply them during ordinary use.) There is a table Area such that Area(T,L) gives the space used by a building of type T at level L. It must be the case that Area(T,0) is the empty area for every building type T (i.e., zero-level buildings occupy no space). (Although I am writing “Work” and “Area” as though they were functions, precisely how they is implemented is outside the scope of this proposal.) Let currentArea(B) == Area(B.buildingType,B.currentLevel). Let desiredArea(B) == Area(B.buildingType,B.desiredLevel). A new building B starts with B.constructionState = CLEARING, with B.currentLevel = 0 (meaning the building does not yet exist), with no resources (construction or supply), and with a target level B.desiredLevel ≥ 1. The possible values of B.constructionState are CLEARING, SHOOING, GROUNDBREAKING, CONSTRUCTION, USE, and EMPTYING. The behavior in each different state is defined as follows: CLEARING (surveying the land and clearing resources): The purpose of this state is to clear the land so construction can begin. While in this state, the building occupies the area given by currentArea(B). (If B.currentLevel == 0, this must be no area at all, and workers/warriors can walk on it and resources can grow on it. In this case, it is probably desirable to show a ghost of the size desiredLevel version so the user can see what they have requested and have something to click on to see and adjust the status.) Upon entry into this state, clearing cells are placed and all forbidden or guard cells are removed on the area given by desiredArea(B). Upon exit from this state, all forbidden/guard/clearing cells are removed on the area given by desiredArea(B). While in this state, the building site acts like a clearing flag, summoning a number of workers given by B.requestedWorkers, which is set to Work(B.buildingType, CLEARING, B.desiredLevel) upon entry into this state. If all the resources are cleared and all the area is discovered and is grass with no other buildings on it, then the building switches to B.constructionState = SHOOING. If construction is canceled, or unclearable resources (e.g., stone) or unsuitable land (sand/water) are found on the area (perhaps a new building was requested on unknown territory), or a conflicting building is found (perhaps an enemy is also building here), then the building switches to B.constructionState = USE, with the value of B.desiredLevel changing to be the same as B.currentLevel (i.e., the building reverts to the old level, or disappears if the old level is zero). SHOOING (shooing the workers and warriors): The purpose of this state is to get globules out of the way so construction can begin. While in this state, the building occupies the area given by currentArea(B). (See comment for state CLEARING regarding the B.currentLevel == 0 case.) Upon entry into this state, forbidden and clearing cells are placed and all guard cells are removed on the area given by desiredArea(B). Upon exit from this state, all forbidden/guard/clearing cells are removed on the area given by desiredArea(B). If all the workers and warriors exit the area, the building switches to B.constructionState = CONSTRUCTION. If any resources grow on the area, the building switches to B.constructionState = CLEARING. If construction is canceled, the building switches to B.constructionState = USE, with the value of B.desiredLevel changing to be the same as B.currentLevel (i.e., the building reverts to the old level, or disappears if the old level is zero). GROUNDBREAKING (applying the first resources to an enlarged area): The purpose of this state is the same as the purpose of the subsequent CONSTRUCTION: to get resources and use them for building. The important difference between this state and CONSTRUCTION is the area used by the building, which remains the old area until the first resources are applied (thereby solving the building-site-abuse problem). While in this state, the building occupies the area given by currentArea(B). (See comment for state CLEARING regarding the B.currentLevel == 0 case.) Upon entry into this state, forbidden and clearing cells are placed and all guard cells are removed on the area given by desiredArea(B). Upon exit from this state, all forbidden/guard/clearing cells are removed on the area given by desiredArea(B). While in this state, the building summons workers to bring it resources to increase its construction resources to the level required for a building of type B.buildingType and level B.desiredLevel. The number of workers summoned is given by B.requestedWorkers, which is set to Work(B.buildingType, GROUNDBREAKING, B.desiredLevel) upon entry into this state. If the building has any more construction resources than needed for a building of type B.buildingType and level B.currentLevel (and this may already be the case upon entry to this state if earlier canceled upgrading is being resumed), then the building switches to B.constructionState = CONSTRUCTION. If construction is canceled, the building switches to B.constructionState = USE, with the value of B.desiredLevel changing to be the same as B.currentLevel (i.e., the building reverts to the old level, or disappears if the old level is zero). CONSTRUCTION (building): The purpose of this state is to get resources and use them for building. While in this state, the building occupies the area given by desiredArea(B). While in this state, the building summons workers to bring it resources to increase its construction resources to the level required for a building of type B.buildingType and level B.desiredLevel. The number of workers summoned is given by B.requestedWorkers, which is set to Work(B.buildingType, CONSTRUCTION, B.desiredLevel) upon entry into this state. If all the needed resources arrive, the building switches to B.constructionState = USE, with the value of B.currentLevel changing to be the same as B.desiredLevel (i.e., the new level has been achieved). If construction is canceled, the building switches to B.constructionState = USE, with the value of B.desiredLevel changing to be the same as B.currentLevel (i.e., the building reverts to the old level, or disappears if the old level is zero). (If construction is canceled, the construction resources accumulated are remembered, so one can restart an upgrade or repair later and continue from where one left off.) USE (use): This is the state for normal use. Upon entry to this state, B.desiredLevel and B.currentLevel must have the same value. Upon entry to this state, if B.desiredLevel == B.currentLevel == 0, then the building disappears. (This happens if you cancel construction on a new building before ever entering state USE. In this case you lose any resources gathered so far.) While in this state, the building occupies the area given by desiredArea(B) == currentArea(B). While in this state, the building summons to supply it the number of workers given by B.requestedWorkers, which is set to Work(B.buildingType, USE, B.currentLevel) upon entry into this state. If repair is requested, the building switches to B.constructionState = EMPTYING (and B.desiredLevel remains the same as B.currentLevel). If upgrade to level L > B.desiredLevel is requested, the building switches to B.constructionState = EMPTYING with B.desiredLevel = L. EMPTYING (emptying): The purpose of this state is to wait for globules inside the building to finish their feeding/healing/training so that construction can begin. While in this state, the building occupies the area given by currentArea(B). Upon entry into this state, clearing cells are placed and all forbidden or guard cells are removed on the area given by desiredArea(B). Upon exit from this state, all forbidden/guard/clearing cells are removed on the area given by desiredArea(B). In this state, the building waits for any globules inside to exit and does not accept any new guests. If the globules all exit, the building switches to B.constructionState = CLEARING. If construction is canceled, the building switches to B.constructionState = USE, with the value of B.desiredLevel changing to be the same as B.currentLevel (i.e., the building reverts to the old level). (How the values in the table Work are determined is outside of the scope of this proposal and is a completely separate issue. I suggest the user interface should allow setting all of them separately. It should be possible to solve problems like the fact that you currently can not set the number of workers for a construction site of a new building until the globules leave the construction location. Or the fact that you can't set the number of workers while waiting for globules to exit the building.) _______________________________________________ glob2-devel mailing list [email protected] http://lists.nongnu.org/mailman/listinfo/glob2-devel
