skip to Main Content

I have created an array in my code that holds quite a lot of information. My question is probably more simple to answer, than read, but for some reason, after four hours of messing around, I just can’t target the right part of the array to extract the information. The first snippet is a truncated output from this array, fullTerritoriesInRange or enough of it for me to continue with my question:

[
    [
        [
            "7",
            "Vatican City"
        ],
        [
            [
                "Italy",
                [
                    {
                        "x": 1311.7569580078126,
                        "y": 156.45799255371095
                    }, //etc etc
                ],
                0.8130994663446266
            ],
            [
                "Corsica",
                [
                ],
                11.270796168914153
            ],
            [
                "Sardinia",
                [
                ],
                13.191931711691217
            ],
            [
                "Croatia",
                [
                ],
                18.581217785849135
            ],
            [
                "Slovenia",
                [
                ],
                22.755208655235703
            ],
            [
                "Bosnia And Herzegovina",
                [
                ],
                24.103141314701163
            ],
            [
                "France",
                [
                ],
                24.795528021316174
            ],
            [
                "Tunisia",
                [
                ],
                27.31657280841581
            ],
            [
                "Montenegro",
                [
                    
                ],
                28.780943036642854
            ],
            [
                "Switzerland",
                [
                    
                ],
                28.824686624652168
            ]
        ]
    ]
]

The array shows the name of a territory Vatican City, and all territories that are "in range" of it (Italy etc)

Then I am attempting to create a copy of this array, that basically is the same except, if the territory is "owned" by the player, it doesn’t include that territory in the new array attackableTerritoriesInRange, this is what I tried.

const attackableTerritoriesInRange = [];
        for (let j = 0; j < fullTerritoriesInRange.length; j++) {
            let isOwned = false; // Flag to track if any match is found

            for (let k = 0; k < fullTerritoriesInRange[j][1].length; k++) {
                const territoryNameToCheck = fullTerritoriesInRange[j][1][k][0];
                for (let l = 0; l < arrayOfLeadersAndCountries[i][2].length; l++) {
                    const ownedTerritoryName = arrayOfLeadersAndCountries[i][2][l].territoryName;
                    if (territoryNameToCheck === ownedTerritoryName) {
                        isOwned = true;
                        break; // No need to continue checking, one match is enough
                    }
                }
                if (isOwned) {
                    break;
                }
            }
            if (!isOwned) {
                attackableTerritoriesInRange.push(fullTerritoriesInRange[j][1]);
            }
            console.log("and the attackable territories are:");
            console.log(attackableTerritoriesInRange);
        }

Any references to [i] in the snippet are referring to the player whose possibly numerous territories are being checked at the moment, i.e. the whole snippet sits in the i loop. This loop is of a different array called arrayOfLeadersAndCountries that holds all the information for each AI player. This array is how we know if it is owned or not and below is an output of that array:

[
    [
        "Vatican City",
        {
            "name": "Champion Sasha IV",
            "leaderType": "aggressive",
            "traits": {
                "dominance": 0.9527169509560709,
                "economy": 0.3240949299375549,
                "territory_expansion": 0.9349304869977676,
                "style_of_war": 0.9428410503399216,
                "reconquista": 0.35144885924449245
            }
        },
        [
            {
                "uniqueId": "7",
                "dataName": "Vatican City",
                "territoryId": "0",
                "territoryName": "Vatican City",
                "territoryPopulation": 800,
                "productiveTerritoryPop": 285.32,
                "area": 3752.993217866781,
                "continent": "Europe",
                "armyForCurrentTerritory": 7,
                "assaultForCurrentTerritory": 0,
                "useableAssault": 0,
                "airForCurrentTerritory": 0,
                "useableAir": 0,
                "navalForCurrentTerritory": 0,
                "useableNaval": 0,
                "infantryForCurrentTerritory": 7,
                "goldForCurrentTerritory": 387.9310344827586,
                "oilForCurrentTerritory": 106.01078144024904,
                "oilCapacity": 106.01078144024904,
                "oilDemand": 0,
                "foodForCurrentTerritory": 0.08070000000000001,
                "foodCapacity": 807,
                "foodConsumption": 807,
                "consMatsForCurrentTerritory": 300,
                "consMatsCapacity": 300,
                "devIndex": 0.812,
                "continentModifier": 15,
                "farmsBuilt": 0,
                "oilWellsBuilt": 0,
                "forestsBuilt": 0,
                "fortsBuilt": 0,
                "defenseBonus": 10,
                "isDeactivated": false,
                "isCoastal": false,
                "isLandLockedBonus": 10,
                "mountainDefense": 2,
                "mountainDefenseBonus": 20,
                "owner": "Vatican City",
                "leader": {
                    "name": "Champion Sasha IV",
                    "leaderType": "aggressive",
                    "traits": {
                        "dominance": 0.9527169509560709,
                        "economy": 0.3240949299375549,
                        "territory_expansion": 0.9349304869977676,
                        "style_of_war": 0.9428410503399216,
                        "reconquista": 0.35144885924449245
                    }
                }
            }
        ]
    ],

arrayOfLeadersAndCountries[i][2] is an object with a property .territoryName, and if this string appears in the list being checked it means that the one being checked is a player owned territory, and should not be added.

So, pulling all this information together, if a reachable territory is owned by the player when checking each of the player’s territories, it should skip, otherwise it should push it to the attackableTerritoriesInRange array.

Due to the complexity in explaining this question, I have given an example of how the attackableTerritoriesInRange array should look:

In this scenario, the current player "i" has two territories, ‘Malta’ and ‘Gozo’.

fullTerritoriesInRange array:

[
  ['357', 'Malta'],
  [
    ['Gozo', <internalArray>, 0.2],
    ['Tunisia', <internalArray>, 0.3],
    ['Italy', <internalArray>, 0.34],
  ]
],
[
  ['358', 'Gozo'],
  [
    ['Malta', <internalArray>, 0.42],
    ['Tunisia', <internalArray>, 0.3],
    ['Italy', <internalArray>, 0.34],
  ]
]

attackableTerritoriesInRange array should look like this with the owned territories removed:

[
  ['357', 'Malta'],
  [
    ['Tunisia', <internalArray>, 0.3],
    ['Italy', <internalArray>, 0.34],
  ]
],
[
  ['358', 'Gozo'],
  [
    ['Tunisia', <internalArray>, 0.3],
    ['Italy', <internalArray>, 0.34],
  ]
]

I have really tried to explain this, and I know it seems convoluted but I need to get the information across and it is pretty complex, but the solution is probably easier than reading the question. Please try to help me by mentioning if my approach is wrong, or by correcting the code, as at the moment it is returning an empty array is the length of fullTerritoriesInRange[j][1] is more than 1, and if it is 1, it returns all the territories that were in the fullTerritoriesInRange array in the first place and more than once. Feel free to ask me anything I missed. I can supply all the javascript that creates any of the other arrays if they are needed, and I will happily provide the whole function if it is needed, to see more context.

This question refers to a globally available app that can be seen at:
https://leighhobson89.itch.io/dominationwc

The current version has the console.log, so you can see the issue if you prefer. To reproduce, load the game at the link (maybe f5 is necessary once due to an intermittent async error) then click any territory and click CONFIRM. When it finishes initialising, click the Green "Military" button twice and then look at the console output, you can see everything in this question there. Thanks for reading.

2

Answers


  1. Chosen as BEST ANSWER

    I have marked this answer as the solution, it didn't work exactly as it was, but it definitely got me on the right track to the point where only one or two lines needed changing, and based on only having the info I could provide in my question, it was super helpful. Also I got some good ideas about organising my data from this question.

    In the end I decided to change the scope of this array, and after the array was made without the owned territories, I would then reduce it into just a one dimensional list of territoryName strings that I can uniquely identify later on to get the actual data from the main data object array, and the fullTerritoriesInRange array. The important thing was to pull out the owned territories which has been accomplished. Thanks to all!

    let attackableTerritoriesInRange = [];
            for (let j = 0; j < fullTerritoriesInRange.length; j++) {
                let isOwned = false;
    
                for (let k = 0; k < fullTerritoriesInRange[j][1].length; k++) {
                    const territoryNameToCheck = fullTerritoriesInRange[j][1][k][0];
                    for (let l = 0; l < arrayOfLeadersAndCountries[i][2].length; l++) {
                        const ownedTerritoryName = arrayOfLeadersAndCountries[i][2][l].territoryName;
                        if (territoryNameToCheck === ownedTerritoryName) {
                            isOwned = true;
                            break;
                        }
                    }
                    if (!isOwned) {
                        attackableTerritoriesInRange.push(fullTerritoriesInRange[j][1][k]);
                    }
                    isOwned = false;
                }
            }
    
            attackableTerritoriesInRange = formatAttackableTerritoriesArray(attackableTerritoriesInRange);
            console.log("and the attackable territories are:");
            console.log(attackableTerritoriesInRange);
    

  2. I would recommend finding a better way to keep track of your data, based on the website, it seems like this will become a very large and complex project, and finding a better way to keep track of the data, while hard now will benefit you in the long run.

    But this code should fix your problem if I am understanding it correctly, it was hard to understand your question and the data, so this may not work as you want. If you could provide a more complete and better formatted set of data, I can improve this solution.

    In short what I did was, instead of pushing the whole subarray (i.e., fullTerritoriesInRange[j][1]), I push a new subarray that contains the territory name and its internal array. Also, you should only push territories that are not owned by the player, so I adjusted the placement of the if (!isOwned) condition.

    const attackableTerritoriesInRange = [];
    for (let j = 0; j < fullTerritoriesInRange.length; j++) {
        let isOwned = false;
    
        for (let k = 0; k < fullTerritoriesInRange[j][1].length; k++) {
            const territoryNameToCheck = fullTerritoriesInRange[j][1][k][0];
            for (let l = 0; l < arrayOfLeadersAndCountries[i][2].length; l++) {
                const ownedTerritoryName = arrayOfLeadersAndCountries[i][2][l].territoryName;
                if (territoryNameToCheck === ownedTerritoryName) {
                    isOwned = true;
                    break;
                }
            }
            if (isOwned) {
                break;
            }
        }
    
        if (!isOwned) {
            const territoryData = [fullTerritoriesInRange[j][0], fullTerritoriesInRange[j][1]];
            attackableTerritoriesInRange.push(territoryData);
        }
    }
    
    console.log("and the attackable territories are:");
    console.log(attackableTerritoriesInRange);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search