Announcement

Collapse
No announcement yet.

The revised Diplomacy Model: Coding Discussion

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • LDiCesare
    replied
    That one should be fairly simple to do. It's more of a placeholder than anything right now though, as it just gives statuses which, I believe, don't change during the game.

    Leave a comment:


  • alms66
    replied
    Just a quick note:

    We need to change the diplo panel into a scrollable pane. In the Ancient Middle East scenario I'm working on (which has 26 civs), the panel extends so far south I wouldn't be able to use it were it active.

    Leave a comment:


  • vovan
    replied
    Yes, that's exactly what I meant when I said we could combine the two civs and use that as a key. Thanks, Laurent

    Leave a comment:


  • LDiCesare
    replied
    Originally posted by vovansim
    So, I suppose then you would recommend this approach?
    Yes
    See, I was also thinking it would be the best, but then of course, I wouldn't be able to use the HashMap provided with java, since there is only one key for each value. What we need is a combination of two keys for each value, since each diplomatic state involves two nations. So, I was wondering how would we combine two Civ classes into one, so that the result conforms to the following rules necessary to preserve the functionality:
    1. civA + civB produces the same output as civB + civA
    2. No two combinations produce the same result.
    Exactly. The same result means both hashcode and equals method are consistent.
    After we got the combination, we can use that as a key for the table and be done with it. But since I don't quite see how that would work - though if somebody came up with an idea of how to add civs, that'd be cool, - I suppose what I would need to do is just implement a hashtable on my own, that uses two keys for each value instead of one. It's not that complicated, but might be quite a bit less efficient than the java hashtable. Then again, I can try to inherit from the built-in hashtable, and try to tweak just the appropriate functions, but once again, I am not quite sure yet how that would work. Any way, suggestions on the implementation of that would be great.
    NO!! (abuse but I like that smiley)
    You just use HashMap with a clever key, it is as you described, it looks like that:
    You just have to take care with the equal (or is it equals?) method:
    public class Key
    {
    private Civilization civ1;
    private Civilization civ2;
    public Key(Civilization civA, Civilization civB)
    {
    civ1 = civA;
    civ2 = civB;
    }
    public int hashcode()
    {
    return civ1.hashcode() + civ2.hashcode();
    }
    public boolean equal(Object other)
    {
    if (other instanceof Key)
    {
    if (other == this)
    return true;
    if ((civ1 == other.civ1) && (civ2 == other.civ2))
    return true;
    if ((civ1 == other.civ2) && (civ2 == other.civ1))
    return true;
    }
    return false;
    }
    }
    Change Key by something meaningful, put it into a HashMap, don't bother what order civ1 and civ2 are fed to you and voila.
    It is MUCH simpler than recoding a HashMap.

    Leave a comment:


  • Mark_Everson
    replied
    I guess Laurent is right that for a sneak attack you will indeed be at peace, but have an internal AI knowledge that you are preparing for a sneak attack. That does seem the right way to work it. As for the implemenation details, I'm agnostic.

    Leave a comment:


  • vovan
    replied
    Originally posted by LDiCesare
    I must confess I really like hashtables (though in java, HashMap is the name, as HashTables are synchronized, which we don't need). Considering civs can be added dynamically during the game, and some disappear, I think it is the most flexible data structure in order to add/remove new entries. Plus it is fast, and actually won't take much more space than any other solution, maybe even less.
    So, I suppose then you would recommend this approach? See, I was also thinking it would be the best, but then of course, I wouldn't be able to use the HashMap provided with java, since there is only one key for each value. What we need is a combination of two keys for each value, since each diplomatic state involves two nations. So, I was wondering how would we combine two Civ classes into one, so that the result conforms to the following rules necessary to preserve the functionality:
    1. civA + civB produces the same output as civB + civA
    2. No two combinations produce the same result.

    After we got the combination, we can use that as a key for the table and be done with it. But since I don't quite see how that would work - though if somebody came up with an idea of how to add civs, that'd be cool, - I suppose what I would need to do is just implement a hashtable on my own, that uses two keys for each value instead of one. It's not that complicated, but might be quite a bit less efficient than the java hashtable. Then again, I can try to inherit from the built-in hashtable, and try to tweak just the appropriate functions, but once again, I am not quite sure yet how that would work. Any way, suggestions on the implementation of that would be great.

    Leave a comment:


  • vovan
    replied
    I agree with Laurent in that we need to decide what we are going to use the diplomatic state for. On the one hand, we can use it for almost purely diplomatic purposes, as he suggested, and as I had originally thought. That way, it is clear that the notion of diplomatic state is strictly two-way: if one nation is in war with another, it necessarily follows that the latter is in war with the former. Or, civA is in war with civB iff (if-and-only-if) civB is in war with civA.

    On the other hand, we could use the diplomatic status data mostly for the AI's use, as Mark suggests. That would work for the AI's advantage like this: some high-level AI class decides that it is time to kick the behind of a neighbor. It then uses the diplomatic status to essentially tell the low-level military AI to gather forces and move them towards the neighbor's borders. Then, when the class that issues unit orders calls some findEnemy() method, it will get the neighbor's civ in return, since it thinks that the state of affairs is now war. Of course, the neighbor has no clue about the coming attack, since he thinks that the state of affairs is peace. Then, once the aggressor's forces attack, the victim changes his diplomatic status to war also.

    I can see how this can be useful for the Ai to make sneak attacks and what not. But this raises one important concern: the problem comes in when there appears a human player. (Well, as a matter of fact, not necessarily a human player, but rather a third party.) This third nation is also making some plans for dominance, and is thinking of who to attack first. Now, they look at the state of affairs between the two earlier nations, and what do they see? One nation thinks they are in war, the other - that they are in peace. Well, if it's a player, he'll just say that the AI's gone nuts. But seriously, with such a situation, how do we determine what kind of information a third party gets?

    There might also be some other difficulties with such approach, so I think we shouldn't mix the concepts here, leave the AI alone for now, and assume that the diplomatic state between two nations is the same from both points of view.

    Leave a comment:


  • LDiCesare
    replied
    I think this one is best. The size of diplomatic state storage is such an infinitesimal fraction of program memory that it is really IMO a) irrelevant and b) premature optimization.
    Indeed the size of data is irrelevant BUT the other point made by vovan is much more important: you have to do the same thing twice. And that is EVIL.

    Now,
    I can also see cases where CivA may want to have a state of War with civ B, but doesn't want to tell B until the surprise attack is launched. In such a case Civ A would for one phase, have War with B while B might have peace with A.
    this is the important question. And, Mark, I disagree. You can prepare for war while being in peace. While your internal agenda says you are going to go to war, you probably want to be in peace with your opponent. So to me, the diplomatic state is bilateral, whereas the internal opinion and choices are not reciprocal. I am not sure the internal state of relation needs be checked.
    Now if not being bilateral had some use (other than for the ai, and I think the ai doesn't need it), what use zould it have for the player? I can't see any.

    And finally, yet another possible way would be to implement a hashtable, in which for every value - diplomatic state - there are two keys - the civs between which the state exists. That might be the most elegant solution, but I am not quite sure about it.
    I must confess I really like hashtables (though in java, HashMap is the name, as HashTables are synchronized, which we don't need). Considering civs can be added dynamically during the game, and some disappear, I think it is the most flexible data structure in order to add/remove new entries. Plus it is fast, and actually won't take much more space than any other solution, maybe even less.

    Leave a comment:


  • Mark_Everson
    replied
    Hi Vovan:

    Originally posted by vovansim
    Of course, we can have a certain structure as a property of each civilization, which would hold the data about diplomatic statuses with every other nation.
    I think this one is best. The size of diplomatic state storage is such an infinitesimal fraction of program memory that it is really IMO a) irrelevant and b) premature optimization.

    I can also see cases where CivA may want to have a state of War with civ B, but doesn't want to tell B until the surprise attack is launched. In such a case Civ A would for one phase, have War with B while B might have peace with A.

    Anyway that's my $0.02!

    Leave a comment:


  • vovan
    replied
    OK, so as I am moving closer to the point where I have to make the diplomacy model work with the existing code, I am wondering about one point.

    So, we have this concept of diplomatic relations. Or, rather the status of diplomatic relations. As in war, peace, and alliance. Now, that is all fine and dandy, but I am wondering, what would be an efficient way of storing that information? There are several ways I can think of, but I don't particularly like any of them.

    Of course, we can have a certain structure as a property of each civilization, which would hold the data about diplomatic statuses with every other nation. Although with this approach it might be a little faster to fetch the data, this is not good in terms of storing efficiency. For one thing, we are storing twice as much information as we actually should (after all, if civA is in war with civB, isn't the reverse also necessarily true? Therefore, why store that info twice - once in civA's attribute, and the second time in civB's attribute.). Secondly, when a state changes, when need to make sure to change it in two places instead of one.

    So, then we need to have a single object , and have it store the relations of all civs.

    Then the question arises: how is this repository going to store the data?

    Well, the easiest idea is to have a 2-D array, and have it stored something like this:

    Code:
    +------+------+------+------+-----+------+
    | ---- | civ1 | civ2 | civ3 | ... | civN |
    +------+------+------+------+-----+------+
    | civ1 | ---- | peace| war  | ... | peace|
    +------+------+------+------+-----+------+
    | civ2 | ---- | ---- | ally | ... | war  |
    +------+------+------+------+-----+------+
    | civ3 | ---- | ---- | ---- | ... | ally |
    +------+------+------+------+-----+------+
    | ...  | ---- | ---- | ---- | --- | peace|
    +------+------+------+------+-----+------+
    | civN | ---- | ---- | ---- | ... | ---- |
    +------+------+------+------+-----+------+
    Of course, with that set-up, only half of the matrix is used. The other half just wastes space. Concerning that, we can institute a fix like this:

    Code:
    +------+------+
    | civ2 | peace|
    +------+------+------+
    | civ3 | war  | ally |
    +------+------+------+------+
    | ...  | ...  | ...  | ...  |
    +------+------+------+------+-----+
    | civN | peace| peace| ally | ... |
    +------+------+------+------+-----+
    Since with Java, 2-D arrays don't have to be square, that is technically possible.

    And finally, yet another possible way would be to implement a hashtable, in which for every value - diplomatic state - there are two keys - the civs between which the state exists. That might be the most elegant solution, but I am not quite sure about it.

    So, if any of you coders out there have any ideas, feel free to share.
    Last edited by vovan; January 14, 2003, 23:32.

    Leave a comment:


  • vovan
    replied
    Originally posted by LDiCesare
    I just want to avoid having figures instead of objects when they are not needed. <snip> I also think the 0 figure is important in some cases and we may often check things in the code like (attitude > 0) which would be easier to read if it was (attitude.isFriendly()).
    Makes perfect sense. I will make it so

    Leave a comment:


  • LDiCesare
    replied
    The design seems OK. I just want to avoid having figures instead of objects when they are not needed. If they are indeed useful, just go ahead.
    Though you could code it thus:
    setAttitude(currentAttitude.nextBetterAttitude());

    This allows managing limit situations like avoiding an attitude of 10 reaching 12 and eventually 999.

    Of course, the nextBetterAttitude() method I suggest requires either a table somewhere based on figures or a sorted list of sorts.
    I also think the 0 figure is important in some cases and we may often check things in the code like (attitude > 0) which would be easier to read if it was (attitude.isFriendly()).

    Leave a comment:


  • vovan
    started a topic The revised Diplomacy Model: Coding Discussion

    The revised Diplomacy Model: Coding Discussion

    I think it would be better to have the coding discussions separate from the concept discussions, because that way the people, who just care about the ideas, and do not want to concern themselves with the specifics of code, do not have to sort through the technical posts.

    First of all, I would like to respond in more detail to Laurent:

    Originally posted by LDiCesare
    Having attitudes/status ranked between -10 and 10 is OK if we need figures, but objects might be more appropriate.
    OK, I have thought about it, and here is how I think it is going to work:
    There will be a certain abstract class DiplomaticStatus, which will contain constant definitions for the name of the diplomatic status and the weight, or strength, of it, and possibly a short description. It will also have definitions for accessors (getters, I think they are also called) for these fields. It will also have subclasses, which will actually have the constants initialized to specific values. That way, we have diplomatic statuses represented as objects, and yet preserve the wieghts. The structure will also be the same for attitudes.

    As a little side note: I think that weights are, in fact, important for such a model because that would make the coding of other things much simpler. For instance: let us say I am coding some method gaveGift(), which will handle the attitude of one nation towards another if the latter gave the former a big gift of whatever. In the code I really don't want to say something like:
    Code:
    if currentAttitude == DeepHatered
        setAttitude(Fury)
    else if currentAttitude == Fury
        setAttitude(Anger)
    
          ...
    
    else if currentAttitude == Philantropy
        setAttitude(BrotherlyLove)
    That is ugly, annoying, and if we choose to add / remove an attitude, I would have to edit the code. Note also, that since there will be more than one method that affects attitude, I would have to edit this stuff in each and every one of them. In addition to me being lazy, there is another reason for not doing things that way: you can easily miss stuff, when editing code like that. And that would lead to nasty bugs, that will be really hard to track. What I really want to say is:
    Code:
    setAttitude(currentAttitude.getStrength() + 2)
    That is more robust, less code, and I don't have to edit it any more if we choose to redefine the attitudes.

    That's how I see the attitudes and diplomatic status implemented. What do you think of such model, Laurent? (I would certainly appreciate comments from other people, too, if you are interested.)
    Last edited by vovan; January 11, 2003, 16:36.
Working...
X