1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

I want to help this mod

Discussion in 'Civ4 - Caveman 2 Cosmos' started by strategyonly, Aug 8, 2016.

  1. Toffer90

    Toffer90 C2C Modder

    Joined:
    Oct 16, 2011
    Messages:
    6,938
    Location:
    Norway
    Did an edit while you wrote your post, and I know it isn't a big thing in the code in question here, it was more meant as a general advice that makes most sense if used inside a loop that does its thing thousands of times in a row.
     
  2. Thunderbrd

    Thunderbrd C2C War Dog

    Joined:
    Jan 2, 2010
    Messages:
    27,691
    Gender:
    Male
    Location:
    Las Vegas
    Yeah, exactly... very good to know though.

    Also interesting about the compiler. Makes sense, I mean most of the code in C++ is just an easier way for us to read it and when compiled it is converted to the simplest possible processing flow that speaks directly to the processor that represents what you've programmed. This is why C++ is so much faster than python - python must be converted to processing language during the running of the code, so it's like you're compiling on demand during the program run. That's what I came to understand anyhow.
     
  3. Toffer90

    Toffer90 C2C Modder

    Joined:
    Oct 16, 2011
    Messages:
    6,938
    Location:
    Norway
    Python is actually interpreted by c (or was it c++) code, so there is no compiling actually happening at runtime, but there is a c code that reads python lines and interprets them and then call different generic c code functions to do what is written in the python code. That is pretty much why python is in some ways considered a pseudo programming language, as the language itself is often just another way to tell a different language what the job is.

    It's in reality a bit more complicated than that, but that is the simple understanding of it.
     
    Last edited: May 27, 2019
  4. MattCA

    MattCA Warlord

    Joined:
    Jan 25, 2019
    Messages:
    295
    Gender:
    Male
    I bet that change would be good in 100 different places. Anywhere there is "if (!NPC)" inside a player loop should be a good place to check.
    You could also move the unused NPCs to the end, after the bard/neand/animal player #s and lower MAX_CIV_PLAYERS to exclude the unused ones.

    I did a bit more digging into the civilization units/building.
    Each civilization type (not player - so it takes memory if civ is used or not) has 1 array of unit classes and 1 of building classes and there is a building/unit type set for each class . If there is nothing in the CivilizationInfo XML for a class, then the default found in UnitClassInfo is used.

    I'll start on somthing to remember eras.
     
  5. Thunderbrd

    Thunderbrd C2C War Dog

    Joined:
    Jan 2, 2010
    Messages:
    27,691
    Gender:
    Male
    Location:
    Las Vegas
    Be careful with this sort of thinking. There are some hardcoded tripwires on this kind of thing somewhere and I'm pretty sure some are in the EXE. I had much trouble with this when adding more NPCs. Pretty sure you cause a problem when you don't use Barbs as the last player possible. And I know there's a lot of places in the code that call for it like this but I don't think all of it is within the boundaries of what we see.
     
  6. MattCA

    MattCA Warlord

    Joined:
    Jan 25, 2019
    Messages:
    295
    Gender:
    Male
    Here's a piece of CvTeam::updateTechShare that I find odd.
    Code:
        iBestShare = MAX_INT;
    
        for (iI = 0; iI < MAX_TEAMS; iI++)
        {
            if (isTechShare(iI))
            {
                iBestShare = std::min(iBestShare, (iI + 1));
            }
        }
    
        if (iBestShare != MAX_INT)
    
    and another similar bit
    Code:
    // K-Mod
    int CvTeam::getTypicalUnitValue(UnitAITypes eUnitAI) const
    {
        int iMax = 0;
        for (int iI = 0; iI < MAX_PLAYERS; ++iI)
        {
            if (GET_PLAYER((PlayerTypes)iI).getTeam() == getID())
            {
                iMax = std::max(iMax, GET_PLAYER((PlayerTypes)iI).getTypicalUnitValue(eUnitAI));
            }
        }
        return iMax;
    }
    
     
  7. Thunderbrd

    Thunderbrd C2C War Dog

    Joined:
    Jan 2, 2010
    Messages:
    27,691
    Gender:
    Male
    Location:
    Las Vegas
    Not sure where they are from nor what they are for. Much of the K-Mod stuff was imported by Alberts2 and I have found some of it wasn't quite as compatible with C2C as intended in some few cases. No faulting anyone here. It was usually a good idea. I'm not sure what these are for. Perhaps it would help to explain why you find them odd.
     
  8. Toffer90

    Toffer90 C2C Modder

    Joined:
    Oct 16, 2011
    Messages:
    6,938
    Location:
    Norway
    The strange thing with the first one is that this:
    ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
    iBestShare = MAX_INT;

    for (iI = 0; iI < MAX_TEAMS; iI++)
    {
    if (isTechShare(iI))
    {
    iBestShare = std::min(iBestShare, (iI + 1));​
    }​
    }
    ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
    is the same as this:
    ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
    iBestShare = MAX_INT;

    for (iI = 0; iI < MAX_TEAMS; iI++)
    {
    if (isTechShare(iI))
    {
    iBestShare = iI + 1;
    break;​
    }​
    }
    ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
    I don't understand the purpose of the code, but something is probably amiss with it when it can be simplified like that.

    I don't see anything strange with the second one.
     
    Last edited: May 31, 2019
  9. MattCA

    MattCA Warlord

    Joined:
    Jan 25, 2019
    Messages:
    295
    Gender:
    Male
    the forum sucks for reading code.
    maybe im reading this stuff wrong but for the first

    iBestShare = MAX_INT;
    iBestShare = std::min(iBestShare, (iI + 1));
    if (iBestShare != MAX_INT)

    I was lookin at the middle line. its given a minimum of MAX_INT right? For some reason this is startin to confuse me, but iBestshare will always be force to MAX_INT?
    no big deal if im right anyways, just fails the if.
     
  10. Thunderbrd

    Thunderbrd C2C War Dog

    Joined:
    Jan 2, 2010
    Messages:
    27,691
    Gender:
    Male
    Location:
    Las Vegas
    It's not the same. If iI somehow runs away, such as in a case where the for loop is bugged, then iBestShare would end up equal to MAX_INT. Admittedly there's really no honest logical reason for such a hedge - if you have the problem, you'll have an issue anyhow when il exceeds MAX_INT. There really is admittedly no good reason for the pinch here. Even if C++ processes the pinch better than you thought, it's still added processing that's entirely unnecessary.

    If we're looking at the second statement for a mathematical quirk, it seems to check out to me. It gets the highest typical unit value from the typical unit values of all players on the team.
     
  11. Thunderbrd

    Thunderbrd C2C War Dog

    Joined:
    Jan 2, 2010
    Messages:
    27,691
    Gender:
    Male
    Location:
    Las Vegas
    No... min means get the lowest of both numbers. max means get the highest of these two numbers. Took me a bit to wrap my head around it but I'm pretty confident in my understanding of it after a lot of practice with it now.

    Thus, if iI+1 == something lower than the Maximum Integer value, then iBestShare will become that amount. If in the next pass iI+1 is lower (which it won't be) than the previous iI+1, then it will take on that value. It's always going to return the first true result it finds so why it doesn't just break at that point, I don't know. Another oversight. Unless isTechShare(iI) is capable of changing the value of iI after it's processed and returning a different amount. That may be the case if it's really clever here. I've never seen that sort of trick in our code employed before but whoever did this was apparently not thinking everything through quite right so I doubt such a clever approach to a value loop would be in play here.
     
  12. MattCA

    MattCA Warlord

    Joined:
    Jan 25, 2019
    Messages:
    295
    Gender:
    Male
    ah, I thought it ment if the second number goes above the first the make the second number equal to the first. I guess I was way off on that 1
     
  13. MattCA

    MattCA Warlord

    Joined:
    Jan 25, 2019
    Messages:
    295
    Gender:
    Male
    and for that current ear thing ull nee something on init() for the new member and all there is for the EraTypes enums is NO_ERA. I guess there's the function getStartEra() or I could use a 0, first era is 0 right? or getInfoTypeForString() but id rather 1 more enum like START_ERA or INITIAL_ERA.
     
  14. Thunderbrd

    Thunderbrd C2C War Dog

    Joined:
    Jan 2, 2010
    Messages:
    27,691
    Gender:
    Male
    Location:
    Las Vegas
    If you're looking for the current era number: (int)GC.getGame().getCurrentEra()

    Try to avoid getInfoTypeForString() wherever possible - it's very very slow and there's usually a better way unless you're basically caching the result of it and then calling it multiple times later.

    get StartEra() may not always be 0 if you didn't start the game in the Prehistoric. But you CAN use 0 to mean the gamestarting era, sure.

    I'm not sure what all this is referring to when you say, for THAT current era thing... but maybe this commentary helps?
     
  15. MattCA

    MattCA Warlord

    Joined:
    Jan 25, 2019
    Messages:
    295
    Gender:
    Male
    I cant find thread but toffer said it might be good idea to save value of current era instead of doin the loop through players. So GC.getGame().getCurrentEra() will return m_eCurrentEra. Ill need to initialize m_eCurrentEra which ill probably do on reset(). was just wondering what to use to give it it's first value. Ill use 0 for now
     
  16. Thunderbrd

    Thunderbrd C2C War Dog

    Joined:
    Jan 2, 2010
    Messages:
    27,691
    Gender:
    Male
    Location:
    Las Vegas
    Oh right I see.
     
  17. MattCA

    MattCA Warlord

    Joined:
    Jan 25, 2019
    Messages:
    295
    Gender:
    Male
    Code:
     int iEra = GET_PLAYER(getOwnerINLINE()).getCurrentEra();
    
    (iEra - GC.getGame().getStartEra() / 2)
    
    If iEra happens to be 0 can this cause a divide by 0?
     
  18. Thunderbrd

    Thunderbrd C2C War Dog

    Joined:
    Jan 2, 2010
    Messages:
    27,691
    Gender:
    Male
    Location:
    Las Vegas
    No. You are always dividing by 2. You can divide a 0, you just can't divide BY 0.
     
  19. Anq

    Anq Prince

    Joined:
    Apr 14, 2019
    Messages:
    351
    Gender:
    Male
    Location:
    Anser (geese) HQ
    I need some time to develop all possible memory savings based on this. Once I finish it, we can measure how much this approach benefits us. It's 434.5MB-> 435.5MB (1 test) after I converted 2 of those arrays, but we'll see.
    (Please ignore my last suggestion to reformat the XMLs -- it's too radical and provides no real benefit.)

    EDIT: It's better to use vectors instead.
     
    Last edited: Jun 20, 2019
    KaTiON_PT likes this.
  20. MattCA

    MattCA Warlord

    Joined:
    Jan 25, 2019
    Messages:
    295
    Gender:
    Male
    I think you said something like this a couple months ago. I've had this new global define laying around for a while. It allows someone to set a starting era for the water animal spawns.
    I've got another that does the spawning part of Raxo's No Limits mod.

    I havn't tested, also still needs the Xml.
     

    Attached Files:

Share This Page