|
Author
|
|
Topic: MapSquare Class OO discussion |  |
|
Mark_Everson Clash of Civilizations Project Lead Canton, MI, USA b.02-15-99
|
 |
posted September 23, 2000 15:00
  |
 |
 |  |
The idea of this thread is to achieve concensus on an OO structure for the MapSquare class. F_Smith, can you post the variables for your existing class here also?Here is what I currently have in the MapSquare classes for the demo 4 + code. Because I was initially trying to be frugal with memory storage for each MapSquare there was a hierarchy of three types of MapSquare classes. The lowest is BaseMapSquare which can handle things like sea squares that don't require all the information that is required for land. Next highest is MapSquare which holds all the info necessary for a land square. The highest is PopSquare which is a MapSquare with population in it. Given what I've learned from F. Smith, it is probably foolish to have these three different levels of MapSquare. I will just put them one after the other, and the sum of all three is my guess the starting proposal for the new MapSquare class. The entire map is held in a class called TheMap which is simply a 2D array of BaseMapSquare. I strongly urge that we keep this structure intact, since substantial amounts of the existing code for AI, movement, and map graphics, relies on this 2d array being there. If you don't want to look at my abbreviated version, the complete Javadoc and source code are available in the thread Javadoc Documentation for current source / + current source code This stuff is not all self-explanatory. There's some things that relate to the AI, such as having different worlds (to test out strategies in a world that is divorced from the game world). If you are really having a hard time figuring out what something is, post a question and I'll try to answer it quickly. Also, where possible, I think we should keep the current variable names and structures unless there are big problems with them. Every change will potentially involve a lot of work. Please don't suggest a change unless you think the existing version is so bad that it will cause significant future problems. code:
/** BaseMapSquare is an individual square of the map and its characteristics. * BaseMapSquare provides routines used by all MapSquare classes, stores information about: * 1) Generic Terrain Types and Specific Value for This Square, * 2) Square Location, X and Y, * 3) Military TFs present..., * 4) Whether the Square Is Selected or Not, an Aid for the User Interface, * 5) Special resources are implemented at this level (eventually) to handle fishing..., * * BaseMapSquare fully represents a sea or lake Square. For a land square it is extended to * MapSquare if unpopulated, and PopSquare if populated. * * Copyright 1999, the Clash of Civilizations Development Group * * @author Mark Everson * @version 0.3, Date: January 12 2000 */ public class BaseMapSquare extends SerialCloneable implements Cloneable { // Which world is the square in? Defaults to 0, the main game world // Rather than have a whole new set of constructors for different worlds, when the World() // constructor is called it will paste in the correct value. private byte worldIndex = 0; /** Describing whether a square is coastal, inland, etc */ private byte positionType = 0; /** Describes land squares around a littoral water square; so far just use 4 bits for adjacent land to the North (1), East (2), South (4), and West (8); so a one-square lake = 15*/ private byte oceanType = 0; protected byte terrain = OFF_MAP; // one of the terrain types, e.g. MapSquare.WATER private byte siteType = 0;// index pointing to position in econSitesArray that holds site information // Right now there is only one siteType for each terrain type, but I'm setting it up more // generally for future use private byte mapTile = 0; // map Tile numbers - not used currently
protected int xLoc, yLoc; // absolute x and y coords of the square. private TF[] TFsHere; // the TFs know what civ they're from by TF.itsCiv private byte numTFsHere = 0; /** Is combat possible here this turn; used for assigning support forces to friendly TFs */ private boolean potentialCombat = false; /** Attacker for combat that will take place this turn, loaded in isTherePotentialCombatThisTurn()*/ private Civ attackerCiv; /** Defender for combat that will take place this turn, loaded in isTherePotentialCombatThisTurn() */ private Civ defenderCiv; private boolean selected; // for use in selecting squares on the map for various functions private boolean isTarget; // a second type of selection, currently not used ************************************************** /** MapSquare * PopSquare at bottom of file extends MapSquare to cover populated squares that * don't belong to a civ * An individual land square of the map and its characteristics * * Copyright 1999, the Clash of Civilizations Development Group * * @Author Unknown * @Version 0.3 Date January 12 2000 */ public class MapSquare extends BaseMapSquare implements Cloneable { /** 1 in a bit means there's a river, all rivers flow to center of Sq * N edge is 8x bit rotating clockwise (NESW) to * W edge is 1x bit - River N&E -> riverPos = 12; */ private byte riverPos = 0; /** [0] is N and it goes cw ([1] = NE etc...) * just because roadTo[x] is true doesn't mean there's a useable road * must check roadCondition[] value to determine existence and * quality */ private boolean[] roadTo; /** None = 0, is for planned or destroyed roads */ private byte[] roadCondition; /** MapSquare() constructor */ public MapSquare(){ // [0] is N and it goes cw ([1] = NE etc...) roadTo = new boolean[8] ; // None = 0, is for planned or destroyed roads // might have info, like the tiling used to display // the road in future implementations roadCondition = new byte[8] ; } Copy /** PopSquare // * PopSquare extends MapSquare to cover populated squares * * Copyright 1999, the Clash of Civilizations Development Group * * @Author Unknown * @Version 0.3 Date January 12 2000 */ public class PopSquare extends MapSquare implements Cloneable { /** the Province the square is associated with, if any */ private Province prov; /** city indicates whether the square is urban or not */ private boolean city = false; /** used in multi-square province (MSP) bookkeeping, has to * do with how developed this square is with respect to the average for the MSP * no [0] similar to sector numbers [1] is diff for Farm, [5] is for Merch... */ private float[] capDifference = null; /** Contains the population of the square population, 1 = 1000 people */ private float pop; /* The defensive military capability of the inhabitants of the square */ private float milPower = 0; /** Culture covers tech and society aspects of populated squares there can be up to three cultures per popSquare */ private Culture cultures[]; /** culturepct that don't belong to a civ, culturePct keeps track of percent * of population in each of three cultures if sum over culturePct less than 100 * the rest of the pop is a mixture of other cultures too small to keep track of */ private byte culturePct[]; /** nomad is the pop primarily nomadic or agricultural */ private boolean nomad = false; /** frontline is used if sq is part of a prov to determine if * this square is directly exposed to potential hostilities */ private boolean frontLine = false; /** number of foreign squares adjacent * Specifically, number of adjacent land squares not controlled directly by us */ private byte numForeignSqs = -1; ******************************************************************* And here is TheMap... /** * TheMap Holds a map (2D array of type BaseMapSquare) of the world for a particular World. * It functions mostly as just a container for map[][] after initialization which it handles. * Right now initialization is by reading in a world map from a save file format and performing * some modifications to the initial information. For now there is no way to replace a square * with a different type directly, you're stuck with the map as it is. * * Date: 10/4/1999, Copyright 1999, the Clash of Civilizations Development Group * * @author Mark Everson * @Version 0.3 Date January 12 2000 */ public class TheMap{ /** which world this is associated with */ private int worldNumber; /** the detailed map */ private BaseMapSquare[][] map = new BaseMapSquare[mapLengthX][mapLengthY]; // eventually earth map will be absorbed by this map /** makes an off-map square for various uses */ private static PopSquare zipMapSquare; /** position of upper left of map in earthMap, right now set so play occurs on Europe */ private static Point smallMap00_Position_OnWorldMap;// /** squares in map x dir */ private static final int mapLengthX = 70; // /** squares in map y dir */ private static final int mapLengthY = 150; /** Map of Earth size 320x200 from an old game project called Antiquity */ private static short[][] earthMap = new short[320][200]; private static short[][] earthMapRotated = new short[1000][700]; private InputStream in; /*FileInputStream*/
|
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 23, 2000 20:10
|
 |
 |  |
Excellent start, Mark:I'll work with this, think about it, then get back to you tonight. One thing off the top of my head, tho -- all the 'AI' copies of a mapsquare don't belong in the class. That should be done seperately. Each mapsquare only needs to know the info it'll need to do it's own methods. |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 24, 2000 00:23
|
 |
 |  |
Mark:Here's the 'MapSquare' class in the beast -- Now, this extends Canvas, which we may not want to do. But I think we will want it to have the code to draw itself, via whatever means necessary, so that we can easily redraw individual squares. The relevant data items are all listed at the top --
- GameData -- a pointer to the game world database.
- Name -- String name of the square (player defined).
- Terrain -- a pointer to a 'terrain' object.
- explored -- a boolean to indicate if the player has explored here yet.
- selected_square -- a pointer to the square that is 'selected'.
- controlling_civ -- a pointer to the 'civ' controlling it.
- controlling prov -- a pointer to the 'prov' controlling it.
- ethnic_groups -- a collection of pointers to all the ethnic_groups in the square.
- task_forces -- a collection of pointers to all the 'task force' objects (military version of an EG) in the square.
- zone integers -- several 'zone' values that likely should be handled as a single object. That part hasn't been designed yet.
- x_loc and y_loc -- x and y location of the mapsquare.
- observers -- a list of all GUI components that will need to be redrawn when the mapsquare data changes.
- menu -- the popup menu that will be displayed on right-clicking this square.
- pref_size -- for screen redraw, the optimal size to draw this square.
- turn_handler -- a pointer to the 'turnhandler' object that will be called once per turn.
There's getters and setters for all, which is how a mapsquare is built and used. The constructer requires a pointer to the gamedata database, and the x and y locatoin of the mapsquare. Then you setTerrain, addFoodZone, addEthnicGroup, that kind of thing. For use, there are all the necessary getters. There are methods for getting the total pop (it just adds up the pop from all the EGs contained within), terrain, controlling_civ, etc. Now the big question is this -- Clear your mind of any previous thoughts, any other models. Answer this question cold, with a 'beginners mind'.
- What other information is contained within a square location of land that would have an effect on gameplay?
What do I still need to add?
code:
import java.awt.*; import java.awt.event.*; import java.util.*;public class MapSquare extends Canvas { private GameData data; private String name = "Wild Countryside"; private Terrain terrain; private boolean explored; static private MapSquare selected_square; private boolean selected; private Civilization controlling_civ; private Province controlling_prov; private Vector ethnic_groups; private Vector task_forces; private int food_zones; private int raw_materials_zones; private int production_zones; private int services_zones; private int special_materials_zones; private int x_loc; private int y_loc; private Vector observers; private PopupMenu menu; private Dimension pref_size; private TurnHandler turn_handler; public MapSquare(GameData d, int x, int y) { data = d; initData(x, y); } private void initData(int x, int y) { explored = true; pref_size = new Dimension(50, 50); ethnic_groups = new Vector(); task_forces = new Vector(); observers = new Vector(); x_loc = x; y_loc = y; setTurnHandler(new MapSquareTurnHandler(this)); addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { select(); if(hasTaskForces()) { TaskForce t = (TaskForce)task_forces.elementAt(0); if(evt.getClickCount() == 2) { t.issueOrders(); setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); } else { setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } } } } ); updateView(); } public void updateView() { if(hasTaskForces()) { TaskForce tf = (TaskForce)task_forces.elementAt(0); addPopup(tf.getDetailPopup()); } else addPopup(getDetailPopup()); } public void addPopup(PopupMenu m) { menu = m; add(menu); } public void processMouseEvent(MouseEvent evt) { if((menu != null) && (evt.isPopupTrigger())) { if(hasTaskForces()) { Enumeration enum = getAllTaskForces(); TaskForce tf = (TaskForce)enum.nextElement(); addPopup(tf.getDetailPopup()); } else { addPopup(getDetailPopup()); } menu.show(this, evt.getX(), evt.getY()); } else super.processMouseEvent(evt); } public void setName(String n) { name = n; } public String getName() { return name; } public void setTurnHandler(TurnHandler t) { turn_handler = t; } public TurnHandler getTurnHandler() { return turn_handler; } public void addEthnicGroup(EthnicGroup g) { g.setLocation(this); ethnic_groups.addElement(g); repaint(); notifyObservers(g); } public void loadEGVector(Vector eg) { Enumeration enum = eg.elements(); while(enum.hasMoreElements()) { EthnicGroup g = (EthnicGroup)enum.nextElement(); addEthnicGroup(g); } } public EthnicGroup getEthnicGroup(String n) { Enumeration enum = ethnic_groups.elements(); while(enum.hasMoreElements()) { EthnicGroup grp = (EthnicGroup)enum.nextElement(); if(grp.getNationality().equals(n)) return grp; } return null; } public Enumeration getAllEthnicGroups() { return ethnic_groups.elements(); } public Demographics getDemographics() { Demographics d = new Demographics(); int uc = 0; int mc = 0; int lc = 0; int sl = 0; Enumeration enum = getAllEthnicGroups(); while(enum.hasMoreElements()) { EthnicGroup eg = (EthnicGroup)enum.nextElement(); Demographics eg_demo = eg.getDemographics(); uc += eg_demo.getUC(); mc += eg_demo.getMC(); lc += eg_demo.getLC(); sl += eg_demo.getSlaves(); } return d; } public void addTaskForce(TaskForce t) { task_forces.addElement(t); t.setLocation(this); // updateView(); } public void removeTaskForce(TaskForce t) { int index = task_forces.indexOf(t); task_forces.removeElementAt(index); updateView(); } public Enumeration getAllTaskForces() { return task_forces.elements(); } public boolean hasTaskForces() { return !task_forces.isEmpty(); } public int getPop() { int pop = 0; Enumeration enum = ethnic_groups.elements(); while(enum.hasMoreElements()) { EthnicGroup eg = (EthnicGroup)enum.nextElement(); pop += eg.getPopulation(); } return pop; } public void addFoodZones(int n) { food_zones += n; } public void setFoodZones(int n) { food_zones = n; } public void removeFoodZones(int n) { food_zones -= n; if(food_zones < 0) food_zones = 0; } public int getFoodZones() { return food_zones; } public int getSoilQuality() { return terrain.getSoilQuality(); } public void setLocation(int x, int y) { x_loc = x; y_loc = y; } public int getXLoc() { return x_loc; } public int getYLoc() { return y_loc; } public boolean isPopulated() { return !ethnic_groups.isEmpty(); } public void setControllingCiv(Civilization c) { controlling_civ = c; } public Civilization getControllingCiv() { return controlling_civ; } public void setControllingProv(Province p) { controlling_prov = p; } public Province getControllingProv() { return controlling_prov; } public boolean isControlled() { if(controlling_civ == null) return false; return true; } public void select() { if(selected_square != this) { if(selected_square != null) selected_square.unselect(); selected = true; selected_square = this; notifyObservers(this); } repaint(); } public void unselect() { selected = false; notifyObservers("unselected"); repaint(); } public void setTerrain(Terrain t) { terrain = t; terrain.initZones(this); setBackground(terrain.getColor()); } public String getTerrain() { return terrain.toString(); } public PopupMenu getDetailPopup() { PopupMenu menu = null; if(hasTaskForces()) { Enumeration enum = getAllTaskForces(); TaskForce tf = (TaskForce)enum.nextElement(); menu = tf.getDetailPopup(); } else { menu = new PopupMenu("Square"); menu.add(new MenuItem("Food")); menu.add(new MenuItem("Raw Materials")); menu.add(new MenuItem("Finished Goods")); menu.add(new MenuItem("Services")); menu.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { String cmd = evt.getActionCommand(); if(cmd.equals("Food")) { foodCommand(); } } } ); } return menu; } public void foodCommand() { new FoodDetailDialog(new Frame(), this); } public void paint(Graphics g) { update(g); } public void update(Graphics g) { Dimension d = getSize(); Dimension off_dimension = getSize();; Image off_image = createImage(d.width, d.height); if(off_image != null) { Graphics off_graphics = off_image.getGraphics(); int h = (int)d.height; int w = (int)d.width; if(explored) { if(selected) setBackground(Color.pink); else setBackground(terrain.getColor()); drawTerrain(off_graphics, h); if(hasTaskForces()) drawTaskForce(off_graphics, h, w); else if(isPopulated()) drawPopulation(off_graphics, h, w); if(isControlled()) drawCivMask(off_graphics, h, w); else if(data.isGridOn()) drawGrid(off_graphics, h, w); } g.drawImage(off_image, 0, 0, this); } } public void drawTaskForce(Graphics off_graphics, int h, int w) { off_graphics.setColor(Color.black); TaskForce t = (TaskForce)task_forces.elementAt(0); int n = t.getNumOfMen()/100; int x = 10; int y = 10; for(int i=0; i { if(x<(h-10)) { off_graphics.drawImage(t.getUnitSprite(), x, y, this); x+=10; } else { y+=10; x = 10; } } } public void drawTerrain(Graphics off_graphics, int scale) { Image i = terrain.drawTerrain(scale); if(i != null) off_graphics.drawImage(i, 0, 0, this); } private void drawPopulation(Graphics off_graphics, int h, int w) { off_graphics.setColor(Color.black); int[] x = { 20, 30, 25 }; int[] y = { 20, 20, 30 }; for(int i=0; i<3; i++) off_graphics.drawImage(new ImageBank().smallHouse(), x[i], y[i], this); } private void drawCivMask(Graphics off_graphics, int h, int w) { if(controlling_civ.getCapitol() == this) { Image i = terrain.image_bank.castle(controlling_civ.getColor()); off_graphics.drawImage(i, w-30, 5, this); } off_graphics.setColor(getControllingCiv().getColor()); for(int i=0; i<2; i++) off_graphics.drawRect(i, i, h-(i*2), w-(i*2)); } private void drawGrid(Graphics off_graphics, int h, int w) { off_graphics.setColor(Color.black); off_graphics.drawRect(0, 0, h-1, w-1); } public Dimension getPreferredSize() { return pref_size; } public Dimension getMinimumSize() { return pref_size; } public void addObserver(Observer o) { observers.addElement(o); } public void removeObserver(Observer o) { int index = observers.indexOf(o); if(index != -1) observers.removeElementAt(index); } public void notifyObservers(Object arg) { Enumeration enum = observers.elements(); while(enum.hasMoreElements()) { Observer o = (Observer)enum.nextElement(); o.update(null, arg); } } }
|
Mark_Everson Clash of Civilizations Project Lead Canton, MI, USA b.02-15-99
|
 |
posted September 24, 2000 13:24
  |
 |
 |  |
Hi F:First off, it's good to have this going. Let's see... I do strongly object to MapSquare extending Canvas. I think you know that you are badly mixing different parts of the MVC paradigm . And even I have this part right in the demo 4 code! You don't want to be taking steps backwards do you? Same comment goes for all the other GUI-type stuff you currently have in MapSquare. So I guess my proposal is you need a MapSquareView class or something and point to it from MapSquare. On to other things, first thoughts about what you have included already ... Personally I think it is silly to have every single object in the game have a pointer to GameData. You know more than me about these things, but it seems more rational to have a static method in GameData that can give the pointer to the game data instance associated with the player. But it's your code, so my feelings are not nearly as strong as about the MVC point. Just for the record, I think there should be more than one level of whether a square has been explored or not. In Clash one should be able to learn about squares without actually trudging a military unit through them. But that is just a detail here. Additional stuff that needs to be in there. Most of these are already covered above, so I will just use one word or so to indicate them. I am not clearing my mind for this, I am just referring to what is above so you don't miss it. Roads, railways, rivers, canals... or do you envision this in Terrain? There are a lot of things we need for AI support at the square level. These are things like my variable positionType that describes whether a square is coastal, inland, etc.. There are six or seven things like that in total in the stuff I described above. If you want to keep these out of the MapSquare object itself, that is perfectly understandable. But then we will need to add a unique object for each MapSquare that is an AI helper for MapSquare that each MapSquare will have a pointer to. You need a pointer for an economy object in each MapSquare. Right now in the demo 4 code this is called EconStub because it can either be a limited amount of information, or point to a full-fledged Economy object. There is a possibility that we will need some support in MapSquare for the ticks system of military movement. This is to ensure that two units that "swap squares" and move on the same tick can't teleport over each other when in reality they would meet. We can probably handle this when we talk about the military stuff. Possibly we need military infrastructure such as walls and fortifications. Do you think this should go with the square itself, or be accessed through an infrastructure object that belongs to the economy object of the MapSquare? I can't come up with anything truly new to put into this object. Then again I have been thinking about this for years, so it's probably not too surprising. I am assuming all the economic sites stuff both in terms of potential sites, and sites actually usable at current technology, will be contained in the terrain object. So we need to talk about that soon also. Oh, one other thing. People have mentioned that in terms of flexibility we may want to have different levels to the terrain like in CTP. So you may need X, Y, and Z info for each square to allow for this flexibility. |
Richard Bruns Prince NC, USA Nov 1999
|
 |
posted September 24, 2000 14:54
 |
 |
 |  |
I agree that we should have the ability to make multiple maps like underworld, surface, and sky. That provides a lot of flexibility.Is it feasable to include the ability to create the cube world I discussed earlier? It has six maps with certain rules for joining at the edges. For more description, see my original post. [This message has been edited by Richard Bruns (edited September 24, 2000).] |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 24, 2000 15:40
|
 |
 |  |
Mark:Actually, the 'M-V-C' architecture requires data objects to draw themselves. In fact, OO requires that objects do all their own work. It's the GUI components that will display the object that belongs in the 'View' code. We don't absolutely have to do this that way, but I'll show you an example of it in action and why the architecture is designed that way. It simplifies the code a lot. As far as using a 'global' GameData object -- it's consider very bad form to use Global variables. We can do it that way, but I'd rather not. I agree with you about the 'explored' boolean. There should be more booleans. 'Roads', 'Railways' and 'Canals' are 'infrastructure' objects, which I was thinking would be held in 'Terrain' -- altho that's what we're here to work thru. 'River' absolutely belongs in 'terrain'. In fact, the 'Terrain' object will also hold all that info you want for AI (and more, I think). An 'Economy' data object certainly belongs somewhere in all this. Altho I'm not sure of the object hierarchy. Haven't thought it thru. We'll have to do an analysis. For the military tick support, I'm not sure I understand what needs to be here. We should talk about that. Again, for walls and fortifications those will be 'infrastructure' objects like roads, etc, and I was initially thinking that they belong to the terrain. We'll go thru the 'terrain' object analysis next, so this won't have to wait long for discussion. You're absolutely correct, I should have a 'z_loc' for height above sea level. Will do. For multiple layers (sky, space and underground/underwater), I would want to use a different object and a seperate collection, instead of containing all the info in that square object.
Richard: I'll look at your post when I get a chance. If it's feasible, I'll make it happen. One of the rules of XP is that when asked to include functionality, the programmer must always say "yes, I can do that"! |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 24, 2000 15:53
|
 |
 |  |
Mark:A quick note -- for an excellent example of how the 'M-V-C' architecture works, check out the Swing components 'JTable', 'JList', 'JTree', etc. I'll go over 'JTable' real quick. You have the 'view' component, 'JTable'. It's only purpose is to contain a 'TableModel' object and display that object. Then you have the 'data' component -- 'TableModel' (you extend 'AbstractTableModel'). It contains all the code on how specifically it will be rendered -- the number of columns, the number of rows, the info on how those rows and columns will be rendered ('CellRenderer' objects). Does that explain it? The biggest bonus to using this 'M-V-C' approach is that the 'view' object never has to be altered. When the data in the 'data' object changes, the 'data' object redraws itself. |
Richard Bruns Prince NC, USA Nov 1999
|
 |
posted September 24, 2000 15:56
 |
 |
 |  |
Are you planning on considering Beör's proposal regarding "Habitat" objects? I really think that it could be good. The natural landscape would be kept in "Terrain" mapsquares, and all the populated stuff could be the "Habitat" mapsquares. Creating that distinction could give us lots of flexibility. quote:

One of the rules of XP is that when asked to include functionality, the programmer must always say "yes, I can do that"!
 |
[Darth Vader Voice] I have you now! [/Vader Voice]Could you add the functionality of Beör's proposal?  |
roquijad Clash of Civilizations Government Model Santiago Nov 1999
|
 |
posted September 24, 2000 18:26
 |
 |
 |  |
Hmmm... I didn't like much the Habitat idea. Can we discuss it some more before taking this coding step with Habitats? |
Richard Bruns Prince NC, USA Nov 1999
|
 |
posted September 24, 2000 18:44
 |
 |
 |  |
If we don't like it we can shut it off and revert to the standard way. It would only be an option. Even if it is not standard, it could be a scenario design tool.At least, that was my impression of the flexibility of OO. Is that correct, or am I confused again? |
Beör Warlord Copenhagen, Denmark Aug 2000
|
 |
posted September 25, 2000 07:40
 |
 |
 |  |
Only discussing map issues (immobile habitats), I think the habitat idea could be incorporated seemlessly. You would have exactly the same functionality, with the option of adding a little more at a later stage. I don't even think the programming would be very hard. It might take some decisions as to whether the habitat is really derived from a more basic infrastructure object being able to contain population, which again could be a derivative of the basic infrastructure object, only having a slot for the basic infrastructure action (object in, transform, object out)If on the other hand we are talking about extending the concept to include mobile habitats this would change the entire object model, particularly the military unit and related parts |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 25, 2000 11:31
|
 |
 |  |
Guys:If you want the game logic to work that way, that's an easy thing to include as an option. But if you want the game architecture to work that way, that's not an easy option. And as an architecture, this seems to be very complex for no added functionality -- in fact, it would remove functionality that is necessary for the game. The existing architecture can produce these results. |
Richard Bruns Prince NC, USA Nov 1999
|
 |
posted September 25, 2000 11:50
 |
 |
 |  |
I don't understand  I just think, as a game designer, that infrastructure should not be tied to a certain mapsquare. How does it couse problems to model tham as part of a "habitat" rather than part of the mapsquare? Note: I do not ask these questions to be mean or try to tell people wat to do. I ask questions because I want to learn about something. |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 25, 2000 12:23
|
 |
 |  |
I'll reply fully in the 'Basic OO design' Thread. |
Beör Warlord Copenhagen, Denmark Aug 2000
|
 |
posted September 25, 2000 19:13
 |
 |
 |  |
Not knowing Java makes it a little difficult to comment, but I'll give it a shot.1. Could someone please give a brief explanation of what's in game world database. 2. 'Extending canvas' - If I need to understand this please explain. 3. Same goes for MVC. 4. Why track both the controlling province and the controlling civ? I should think that having access to the province would yield the civ. 5. Are mapsquares still stored in a two-dimensional array as in demo4? 6. Are all military units taskforces here? 7. It seems that most of the interesting stuff (infrastructure) could go in the terrain object. However, I think it is likely that we will have infrastructure objects that are not part of task forces, but still resemble military units by being able to move (fishing fleets again). I would think it more intuitive to keep infrastructure of all sorts in the mapsquare object itself with EGs and military units (it has been argued that military units are infrastructure objects, which makes sense given the way they are produced via the infrastructure model). If you have military units in the mapsquare it would also make most sense to have their encampments and fortifications here. You might even have military units possessing/carying infrastructure. The terrain object would then only be concerned with the physical characteristics of the square itself. Of course the distinction between infrastructure and terrain is not a clear one: Roads, canals and rivers have features of both. Since roads and canals can be constructed I would probably place them in the mapsquare, and since I see no difference between a canal and a river (except that the latter cannot be constructed) I would probably opt for including rivers in the mapsquare as well. 8. I brought this up in another thread as well: Someone please explain the status of sites. What are they, infrastructure or terrain or something else. Mark mentioned somewhere that it was the intention to make it possible to construct sites, as if they were some kind of infrastructure. Will there be a maximum number of sites available at maximum tech level? Another possibility is to have 'tagged' sites. When you reach a particular tech level you could enable x food sites, which could then be exploited. I don't think we lack anything, but we should decide what goes where. If y'all think that the infrastructure vector should be placed in the terrain-object I have no objections (I think ;, and even if I had, it would probably not make a big difference )), so let's decide and move on to the terrain object. |
Beör Warlord Copenhagen, Denmark Aug 2000
|
 |
posted September 25, 2000 19:26
 |
 |
 |  |
Please disregard the queries pertaining to sites. I think we have that going in another thread.  |
Beör Warlord Copenhagen, Denmark Aug 2000
|
 |
posted September 26, 2000 09:29
 |
 |
 |  |
Why not make a new class zone, and have the five _zone integers replaced by a Zones (vector)? This would give flexibility if we later decided to add more zonetypes (I think Mark mentioned the possibility of this somewhere). BTW why did you call it zones instead of sites? The zones should in my opinion be in the terrain object, since now that I've studied the site_concept it is clearly equivalent to natural ressources.OTOH it might make sense to treat sites as if they were infrastructure. Given the proper tech new sites could be constructed/developed/discovered just like what happens with infrastructure objects. If handled this way I think sites should stay here in the mapsquareobj Another option is to move the _zone variables to a separate class ProdZones and point to it from here or the terrain object. Then changing the number of zonetypes would only mean changing code in this class and in the economy class (I think)
|
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 26, 2000 11:00
|
 |
 |  |
Beor:
- The 'GameData' class holds collections of all the game objects -- 'civilizations', 'gamemap', etc. Tonight from home I'll post the exact list of items.
- 'Extending' a class is how Java handles inheritance. The 'subclass' inherits all the variables and methods of the parent class. 'Canvas' is a class that provides drawing capability. So extending Canvas means that the subclass (in this case, the mapsquare) has the ability to draw itself automatically when added to a GUI object like a 'Frame'.
- 'M-V-C' is the 'Model-View-Controller' architecture. This is the standard approach to writing complex systems like this. The idea is that all code can be broken into 3 parts --
- The 'Data Model' -- classes/objects to hold all the game's data.
- The 'View' -- GUI objects to hold and display the data objects.
- The 'Controller' code -- game/business logic and program flow code. In our case, the 'turn handlers' and 'IO' module.
- That was a convenience. Mapsquare must have methods 'getControllingProv' and 'getControllingCiv' anyway, and as you pointed out we can either aquire it every time, or just store a pointer locally. That could go either way.
- The mapsquares in Demo 4 are stored in a 2d array. I'd prefer to use a collection, but that's up in the air. The code won't care -- it'll access mapsquares thru the method 'getMapSquare(int x, int y)'. But using a collection would also allow us to easily include a method 'getAllMapSquares', which we'll need for turn logic. There is a speed difference, but in testing it was negligible. But this can easily be switched back and forth in the code without affecting the rest.
- Yes, so far, the 'military units' object is currently called 'Task Force'.
- That is the way it is, with one added layer -- I've put a 'Terrain' between the two. To allow for a mapsquare with multiple 'terrains', later. So a 'mapsquare' "has a" 'terrain'. A 'terrain' has a 'task force'. And 'infrastructure' belongs to 'terrain'. An 'ocean' terrain holds the 'fishing fleet' infrastructure object, while the 'port' infrastructure object can be part of the 'shore' terrain object in the same square. That infrastructure object will have a mobility variable, and a carrying capacity. It can be immobile, as in a Military fort. 'Task Force' objects will hold pointers to the infrastructure they use (forts, tools, weapons, etc).
- Absolutely correct, 'Zone' or 'Site' info must be a vector within the 'Terrain' that holds them. And 'sites' are not a type of infrastructure, since they are by definition not improved.
Did I cover everything? |
Mark_Everson Clash of Civilizations Project Lead Canton, MI, USA b.02-15-99
|
 |
posted September 26, 2000 11:58
  |
 |
 |  |
Hi All:F_Smith, please keep the 2d array nature of the map square container . As you point out that and a generic continer aren't fundamentally different. But much of the existing AI code assumes a 2d array, and it would be easier to get it going quickly if that assumption were held at least in the intermediate term. The implementation of a method 'getAllMapSquares' is Absolutely trivial, something like 5 lines, and should Not be used as a reason to decide to go one way or the other! |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 26, 2000 12:42
|
 |
 |  |
Mark:If you're talking about looping thru all the mapsquares in the code, then we really should use the 'getAllMapSquares' and loop thru whatever collection we decide to have 'getAllMapSquares' return. It is considered a big faux pas to require the code outside the Map to have to know how the map is stored. All you should return is an 'enumeration' or 'iterator' of all the mapsquares, so that looping thru this collection isn't any different from any other collection. This will make it much easier on the programmers, and eliminate a big potential point of code failure. We really should not have the code do a -- code:
for(int x=0; x "less than" mapwidth; x++) for(int y=0; y "less than" mapheight; y++) doXToMapSquare(mapsquare[x][y]);
That's completely unscalable. That should be done with a collection, derived from the GameData 'getAllMapSquares()' method. As I said, which should return either an 'enumeration' (Java 1.x) or an 'iterator' (Java 2). Java 2 makes it easy to get an iterator from a multidimensional array, so it won't be a big deal if yo want to store it that way, but I don't see the point. And using an actual collection allows us later to scale the map for non-square 'mapsquares', Risk-style. P.S. -- It wouldn't let me use the 'less than' sign, above, so I just wrote it. [This message has been edited by F_Smith (edited September 26, 2000).] |
Mark_Everson Clash of Civilizations Project Lead Canton, MI, USA b.02-15-99
|
 |
posted September 26, 2000 12:56
  |
 |
 |  |
F_Smith:No, its not for that... Its for looping over neighbors and next-nearest neighbors of squares etc. And again, this is only a medium-term issue. At some point in the future it will all be rewritten to be more flexible. But it could make a month's difference in getting a crude military AI going if I need to start from scratch not using the 2d stuff. |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 26, 2000 13:14
|
 |
 |  |
Mark:We'll actually need methods in the GameData class to do that -- something like 'getAdjacentMapSquares(MapSquare msq)'. It will have to return a collection. This is actually a perfect example of why we must code this way. As you said, changing the existing map implementation will currently require code changes all over the place. Well, all that code absolutely will have to be rewritten, I'm afraid, and it's best to do it right away. Saving time up front by not changing it will almost always cost us more time later. I doubt it will take too long. You can just replace those routines with this simple one -- code:
Iterator it = data.getAdjacentMapSquares(mapsquare_x);while(it.hasNext()) { MapSquare msq = (MapSquare)it.next(); doWhatever(msq); }
It should be a simple matter of copy/paste. And that way, all collection code everywhere is the same. And then we can play with a hundred different ways to store the map, without ever having to change the code outside GameData.
[This message has been edited by F_Smith (edited September 26, 2000).] |
Mark_Everson Clash of Civilizations Project Lead Canton, MI, USA b.02-15-99
|
 |
posted September 26, 2000 15:36
  |
 |
 |  |
ok, sold  |
Beör Warlord Copenhagen, Denmark Aug 2000
|
 |
posted September 26, 2000 17:36
 |
 |
 |  |
F_SmithI thought Terrain was an object that described various default terrain types (dessert, farmland, prairie etc). I see now that it is in fact the result of a division of the mapsquare into two layers - funny, where did I hear that before? Multiple Terrains - multiple Habitats. No wonder you thought the Habitat thing was superfluous - you have almost exactly the same structures in your code, they're just divided between the Terrain-object, the EG-object and the TaskForce-object you proposed in the other thread. This way it is obviuos that infrastructure and sites should be in the Terrain object. But why not taskforces and EGs then? Why are they in the mapsquare - I should think that the terrain would be interposed between the mapsquare and these objects as well. This may be details, but I would really like to know your reasoning. BTW I do find the name Terrain a bit confusing (probably a civ2-damage), could we call it something else (no, not habitat ), Surface perhaps. Maybe not so good if we want more than one 'Surface', but how about Location or Landscape. Or Locus (plural Loci) for latin freaks like me? If we were modelling different species of animals I would suggest Ecological Niche or the H-word. This would make it clearer that we are in fact talking of the top of two layers or one of many possible locations in the top layer.. Would there be a point in making a class that holds default terrain types like I mentioned? The class would hold something like: Graphics, default site numbers, movement costs, defense multipliers, and methods for improving the terrain. They would be an option when designing the map. All values could be overridden in every square, and specials would have to be added manually, randomly, by some algoritm or by a combination of the three. When you are talking about adding a z-loc, this is not a way of making multiple layers, is it? Then I suggest that you name it differently from the x_loc and y_loc. Something like Altitude. We can make off-map squares in a jiffy, right? More on sites in the other thread , let's keep that thereBasic OO Design...
[This message has been edited by Beör (edited September 26, 2000).] |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 26, 2000 17:54
|
 |
 |  |
Beor:You have a very good point about EGs possibly being in the terrain object. I'll explain what I was thinking, and why I didn't do that, but I'm not sure I'm right. 'Terrain' objects are not really 'layers', they're actually areas of 'terrain'. A mapsquare can have more than one because a square can have more than one type of terrain in it. For example, a mapsquare can have one 'terrain' object of type 'forest' and one terrain object of type 'lake'. This is not going to be in the basic game, as I understand it, it's just there for later. My assumption about EGs was that the people will not be tied to the terrain, but move about freely across all terrains. I only encapsulated things in the 'terrain' object that were specifically related to one terrain/place. So 'infrastructure', 'resources', that kind of thing. I like 'terrain', to be honest. I think it describes exactly what it is. It will hold all those properties -- it's own 'graphics', movement cost, defense modifiers, etc. I do agree, 'z_loc' should be altitude. Consider it changed. 'Off-map' squares? We can make them easily, sure. Why do we need them again? [This message has been edited by F_Smith (edited September 26, 2000).] |
Toubabo_Koomi Clash of Civilizations Disease & Natural Disasters Models
Oct 1999
|
 |
posted September 26, 2000 20:44
 |
 |
 |  |
It seems that the map code is being rewritten completely here so I'd like to make a suggestion that I had made previously, but it was rejected:have a "donought" shapped world ala, CTP we can easily skip the realism issue of traveling over the poles, as they did. I just find it makes more sense to be able to travel east-west and north-south, rather than only east-west. If this is totally undoable do to AI problems or translating current code, it's cool, it's just a suggestion. |
Lord God Jinnai Prince Arnold, Mo 63010 Sep 1999
|
 |
posted September 26, 2000 21:30
  |
 |
 |  |
That's the way it is with all of them and i really HATE that approach. Anyway i think some of the people doing Openciv3 were trying for a way similar to my suggestion i posted earlier, but i dunno and i also dunno if any of the coders here would be able to convert it either, but plz, lets go beyond the donut shape which is used in all the civ games. |
Richard Bruns Prince NC, USA Nov 1999
|
 |
posted September 26, 2000 21:57
 |
 |
 |  |
Is it possible to add the cube option? Six normal flat maps connected at the edges would make the world look and act right. Distortion would be minimized and accurate polar movement would be possible. And the AI should be fine since we are not really changing much. The AI would just see this:_O OXOO _O and it would be undistorted so the flat map AI should do just fine for determining the best path to a place on the other side of the world. |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 26, 2000 22:26
|
 |
 |  |
Any map layout that identifies mapsquares with an x and y coordinate will work.If ya'll are just thinking ahead, great. But that stuff has to wait for later. We'll just be working with a square map, for the very first alpha prototype. |
Beör Warlord Copenhagen, Denmark Aug 2000
|
 |
posted September 27, 2000 10:35
 |
 |
 |  |
Do you know the feeling: Click 'Submit reply', and get the feeling that something you said weren't accurate or that something was missing. I had that feeling last night re the position of taskforces and maybe EGs.And of course F_Smith put his finger on it, before I had a chance to redeem myself: I knew he would. While having TFs and EGs in the terrain when there was just one terrain made sense, having more than one terrain changes things. If TFs were kept in terrains then the player or the AI would have to decide where to put a TF when it was created or moved into the square. Imagine a square with two terrains: A city and the surrounding plains. It is like them old board games where you had to decide whether the 5th cavalry brigade was inside or outside the fortress of Ulm. If they were outside you placed them on top of a fortification counter, If they were inside you placed them beneath the counter. AND I ALWAYS HATED THAT! I even remember games where you had to consider whether to keep the units by the banks of a river or move them further inland. While it made for realistic gameplay with sieges and specialised bridgehead combat, it was not very playable to say the least, And the same thing goes for EGs: We really don't want to micromanage where in the hex they are at any given point in time. So lets keep TFs and EGs in the mapsquare. But that brings me back to infrastructure and rivers. Do we really want factory to be present in one terrain but not in another. And rivers: If there are rivers in both terrains flowing NE, what does that mean? Or we could have one terrain linked to the neighbouring sqaure by a road while the other is not. Since many infrastructure objects will interact with either EGs or TFs, they should probably be where they are - in the mapsquare. If we decide at one point to include more than one terrain in a square, I think that EGs or TFs should be allowed to choose the terrain effects that are most beneficial to them in a given situation. After all one turn in the default scenario equals one year - so it is reasonable to assume that they will have the time to do what's best for them. Thought: It would however be nice to have sieges. Defenders behind the city walls, attackers in the surrounding terrain. Maybe we could have the player/AI choose if he wants to enter the city, when a square with city-terrain is attacked? Have a fieldbattle or face a siege? |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 27, 2000 10:46
|
 |
 |  |
Beor:Excellent questions, but you're kinda getting way ahead of us. Someday those decisions will have to be made, for sure. But not for months, I think. I personally really like an infrastructure having to pick a terrain. That means no boats on dry land. No Mines in a lake. A logging camp belongs in a forest. Altho I wouldn't want to push beyond two, or perhaps 3 different types of terrain in a single mapsquare. But we have that ability, if someone wants to make up rules to cover it. Later . . . |
Richard Bruns Prince NC, USA Nov 1999
|
 |
posted September 27, 2000 11:30
 |
 |
 |  |
The rules already exist to deal with multiple terrains per mapsquare. The Ecology model assumes that each square could have some percentage of forest or wetlands, so a square could be hills with 50% forest cover and 50% scrubland.So in general, the geography would be one terrain type and the vegetation would be one or two terrain types on top of that. |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 27, 2000 12:55
|
 |
 |  |
Richard:You have a great point there -- that's an excellent object analysis. 'Terrain' objects could hold 'geography' objects. And 'geography' objects could hold 'vegetation' objects. I like this very much, if you think it's a level of detail that will get used. The flexibility is astounding, for 3 objects. The combinations are almost mind-boggling. And it has a bonus -- think of how crops would be handled! So easily. Just a 'vegetation' object. It can be removed when harvested, each crop type can potentially have it's own properties . . . good work, Richard. Is this too detailed? If no one objects, I'm going to use it. |
Beör Warlord Copenhagen, Denmark Aug 2000
|
 |
posted September 27, 2000 16:41
 |
 |
 |  |
Re geography and vegetationI guess this is somewhat equivalent to the SMAC system where the terrain in a square is determined by a 3x3 matrix: Terrain (flat, rolling, rocky) and rainfall pattern (arid, moist, rainy) yielding 9 different combinations. We would however have a multitude of different combinations. One important thing to consider is that this demands very careful attention to details when we decide what effects combinations of geography and vegetation would have during play FE on combat, production and movement. What will be the combined effects on combat of rolling hills and scrub, mountains and forrest, flatlands and tundra etc. With the multitude of combinations we would probably have to design a system where the results of geography and vegetation were considered separately, the combined effect being the sum, the product or some other function of the two factors. If handled incorrectly, this could yield freak situations. It would also be necessary to prohibit certain combinations (FE mountains and mangrove). But OOOOH, what beautiful graphics we could make. Again we would probably have two layers, one for geography, one for vegetation - I'm not sure this is easy, but it can be done. I'm a little worried that the player would be confused by the multitude of different 'square-looks': In SMAC there are nine, and it took some getting used to. How we should handle mixing of different vegetation types in the same square graphically is even more tricky. Are you sure players would like to handle this sort of complexity: 'Should I place my legion in the flat marshes or in the forrested hills or behind the city walls?' And if faced with this choice whenever entering a square this will quickly become rather tedious ). It might work, but I definitely think this possibility strengthens the argument for placing of TFs in the mapsquare, not in the terrain. Then at least the choice between different locations within the mapsquare could be made by AI based on what would be most advantageous to the player. So I guess that what I'm saying is: In general I like the idea, but if too much of this functionality will require the attention if the player, I think we're urinating against the wind. If however it's kept at the AI and model level to achieve greater realism I see nothing wrong with it. F_Smith if we adopt this three-tiered object-hierarchy would you consider changing 'Terrain' into 'Location'? A location has a geography has a vegetation? Re infrastructure and terrain If we decide to model it one way or the other will it be difficult to recode in case it's needed? If no, let's drop the subject for now and proceed anyway you want If yes, we need to discuss it a little more: I see what you mean F_Smith. There has only been so many ships on top of mountains (mental picture: Noah's Ark on Ararat). And city walls around soft meadows isn't exactly realistic. Are we dealing with two different kinds of infrastructure here? Terrainbound and mapsquarebound (roads, canals, rivers, maybe more). Re off-map squares I was thinking in terms of having a mining-facility in an abstractly represented moon-square an such.
|
Mark_Everson Clash of Civilizations Project Lead Canton, MI, USA b.02-15-99
|
 |
posted September 27, 2000 17:59
  |
 |
 |  |
I'd say its ok if things like forrested hills or half forest, half plains are fine in the Object Model. However as Beör says we need to discuss all these things from a gameplay etc point of view before we consider locking them in as standard. These kind of decisions have fairly large leverage on learning curve and gamplay issues.As for the military stuff, the notion has been to allow TFs to be in fortresses or outside them depending on the TF orders. I think the AI can handle that level of differentiation within a square. So the object model will need to be able to have TFs contained within at least a few infra types, and the general square itself. As for position with respect to rivers, I think that may be getting a bit much. But we should discuss the details in the Mil thread. |
Richard Bruns Prince NC, USA Nov 1999
|
 |
posted September 27, 2000 21:17
 |
 |
 |  |
F_Smith: quote:

Richard: You have a great point there -- that's an excellent object analysis.
 |
 I don't understand this. When I diligantly try to learn and do OO analysis, I fail miserably, make you mad, and create a big disturbance. But when I am scrupulously trying to avoid any mention of coding, you say that I am producing wonderful test cases and OO analysis. I feel like I'm in the twilight zone. Beor: quote:

With the multitude of combinations we would probably have to design a system where the results of geography and vegetation were considered separately, the combined effect being the sum, the product or some other function of the two factors.
 |
Already planned. quote:

But OOOOH, what beautiful graphics we could make. Again we would probably have two layers, one for geography, one for vegetation - I'm not sure this is easy, but it can be done.
 |
This very thing is being discussed in the Map Graphics Thread.You could be right about the complexity. But the defense determination should be something as simple as +X% for hills, +X% for forest, add them up. |
Richard Bruns Prince NC, USA Nov 1999
|
 |
posted September 27, 2000 21:39
 |
 |
 |  |
BTW, F_Smith, that is a great idea for crops. It is an elegant way to do things. Now, the system for harvesting crops can be the same as the one for chopping trees. I'll post that and other relevant stuff in the ecology model. |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 28, 2000 11:51
|
 |
 |  |
Beor:You're exactly right, I hadn't thought of that. SMAC does use a similar approach. Bet that game was done via OOA, too. Layering as many objects as necessary is easy. In the beast, those stupid little stick figures were all layered graphics -- each little man, or little house, was an individual graphic with a 'transparent' background. I can take any picture and replace a color (or more than one color) with transparency. So we can go nuts -- assuming someone with actual artistic skill can make the pictures. I, obviously, will not be much help in the 'art' department. Unless you've got a call for stickfigures . . . Absolutely players will have to decide the 'disposition' of their troops -- order them to stay in the fortress and take a siege, or sally forth and give battle on the 'terrain'. This is one of the fun parts, to me. It would be difficult to go back and add this functionality later. If we might ever want it, we should architect the data structure this way now. Oh, and 'off-map' squares will be a simple thing. This game datastructure can even be used to make a game that happens on several planets (assuming enough processor power). Maybe that can be the online game? Let the servers handle all those worlds? Dunno.
Richard: I'm sorry if it seems confusing sometimes. But using the "is a/has a" method, can you see why this is an OO analysis? Terrain "has a" geography, geography "has a" vegetation. I think you understand this better than you may realize. |
F_Smith Prince Austin, Tx 78728 May 99
|
 |
posted September 28, 2000 12:06
|
 |
 |  |
Hmmm . . .Posting that description to Richard, I have to say I think I might agree with Beor, perhaps the objects names should then be location, terrain and vegetation -- A 'Location' has 'terrain'. 'Terrain' has 'vegetation'. That sounds better to me. I think I'll do that. |
Richard Bruns Prince NC, USA Nov 1999
|
 |
posted September 28, 2000 13:34
 |
 |
 |  |
Could we model cities and towns the same way we do vegetation? In the view of the ecology model, they are basically the same thing.I vote to eliminate the word "terrain." It is a concept that is no longer relevant IMO. So:
A Location has geography, water availibiity, and climate. Geography has vegetation, crops, and human settlements. Human settlements have infrastruture and population.
It could be a problem that infrastructure affects water availability and crops. Can things lower in the hierarchy have thet kind of effect on things at the top?Should we be discussing this in the Ecology model thread? | |