1
\$\begingroup\$

Am facing a bit of a problem regarding the structure of a CSV file that will be used to generate levels in a match3 game, my in-engine data structure is the following:

  LevelGoal(LevelGoalType type, int colorIndex, int target)

so that is a single goal in a level, and a level is composed of multiple goals, and the number of goals in a single level is not fixed, so some levels can have 3 goals, and other can have 4 (see image below). Am wondering if there is a "common way" to setup the CSV file so it supports this feature, currently the only solution i could think of is to actually include the LevelIndex in the CSV and use that to create the data in game, but maybe there is a better "standarized" way since people have been making Match3 games for ages.

Thanks!

enter image description here

Edit:

another solution am thinking of is to have all the goals no matter what, but if the target is 0 then the game won't show that that goal: enter image description here

EDIT2:

I marked @DMGregory answer as the solution because it ended up being the closest one to what the client and my puzzle-expert friend told me, check the image below to see the final version of the table, it turns out that the main priority for game designers is to have 1 row per level, ideally the "GoalType" could've been a string and we can add rules to the spreadsheet so that the string can never have a typo, their initial suggestion was exactly what @DMGregory suggested, but after talking with the designer we chose this solution instead, plus parsing wise, it's easier for me to have one column per "object", with that said, they also told me that this kind of workflow is only used in prototypes, if the game get the greenlight then the devs will end up creating a Level editor, and will probably never deal with CSV again and save it all as JSON (or binary if your boss is insane) enter image description here

Thank you all!

\$\endgroup\$
12
  • 1
    \$\begingroup\$ Have you considered using something other than a CVS file that would allow you to more cleanly specify an array of values for some specific key, like JSON? \$\endgroup\$
    – user35344
    Dec 8, 2021 at 15:07
  • \$\begingroup\$ @Tyyppi_77 that was my first thought too, unfortunately the client's game designer only want to work with CSV \$\endgroup\$ Dec 8, 2021 at 15:23
  • 1
    \$\begingroup\$ Does the final save file spec have any requirements beyond CSV? \$\endgroup\$
    – Pikalek
    Dec 8, 2021 at 15:41
  • 2
    \$\begingroup\$ I don't see any obvious problem with the way your data is currently set up. Is there something specific about it that you find unsuitable or unpleasant to work with? \$\endgroup\$
    – DMGregory
    Dec 8, 2021 at 15:41
  • \$\begingroup\$ Keep in mind that just because a CSV can represent a rectangular rows x columns type table, that doesn't mean that it limited to only representing tabular &/or rectangular data. \$\endgroup\$
    – Pikalek
    Dec 8, 2021 at 15:43

2 Answers 2

1
\$\begingroup\$

If you don't like multiple rows per level, you could structure your data like this...

Level Goal 1 Type Goal 1 Colour Goal 1 Target Goal 2 Type Goal 2 Colour Goal 2 Target Goal 3...
1 0 1 10 0 2 6 0
2 0 1 5 0 2 8 1
3 0 3 7

Note that your rows don't all need the same number of cells. A parser can then read triplets of cells to form each goal, until it hits the end of the line and moves on to the next level, something like this:

(Though you'd likely want to include more error checking and helpful debug messages than what I've shown here)

var rows = csv.text.Split("\n");
foreach (var row in rows) {
    var cells = row.Split(",");
    int level = int.Parse(cells[0]);

    var goals = new List<Goal>();


    for (int i = 1; i < cells.Length; i+=3) {
        Goal goal = default;
        goal.type = goalTypes[int.Parse(cells[i])];
        goal.colour = colours[int.Parse(cells[i+1])];
        goal.target = int.Parse(cells[i+2]);
        goals.Add(goal);
    }

    levelGoals[level] = goals;
}

The downside of this is that now similar data about your goals is spread across many columns. So if you were authoring this data in a spreadsheet tool like Excel or Google Sheets, and you wanted to answer questions like "How well balanced are our goals across the different colours?" you'd have to aggregate data from multiple columns to do that.

If that's a use case you care about, then I'd suggest your existing data format is actually superior to this one, even with its redundancy.

You could slightly reduce the redundancy by omitting the level number when it's the same as the row above, though it doesn't save any significant amount, and I'd argue the types of balancing calculations you might want to do are easier if the data is there, redundant or no.

\$\endgroup\$
1
  • \$\begingroup\$ This seems to be the best option "programmatically", but not sure if the clients are gonna like it haha, I have a friend who's been making puzzles games for the past 10 years (worked at King), I'll ask him and see what he thinks tomorrow, am also starting to have a big feeling that they may use a CSV for each level lol (but i really hope not) \$\endgroup\$ Dec 8, 2021 at 17:46
0
\$\begingroup\$

The CSV format does not support hierarchical data very well. When your data format requires more complexity than a simple table, then you might want to switch to a more advanced markup language which supports nested objects and arrays. Like JSON, for example.

levels: [
    { index: 1,
      goals: [
          { type: 0, color: 1, target: 10 },
          { type: 0, color: 3, target: 7 }
      ]
    },
    { index: 2,
      goals: [
          { type: 0, color: 1, target: 8 },
          { type: 1, color: 2, target: 9 },
          { type: 1, color: 3, target: 10 },
          { type: 0, color: 4, target: 10 }
      ]
    }
]

You might now wonder "How the heck am I supposed to parse that?". Don't worry, there are plenty of libraries available for parsing JSON and converting it to internal object representations. There is very likely also one available for your programming language of choice.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Given that OP seems to have a hard constraint to use CSV here due to their client, "unfortunately the client's game designer only want to work with CSV", is there a method you'd recommend that would help them fulfill that constraint? \$\endgroup\$
    – DMGregory
    Dec 8, 2021 at 17:26
  • \$\begingroup\$ thanks for the help but JSON is not an option for now \$\endgroup\$ Dec 8, 2021 at 17:46
  • 1
    \$\begingroup\$ @alaslipknot JSON needn't be the final format. A web search brings up lots of options for converting JSON to & from CSV. \$\endgroup\$
    – Pikalek
    Dec 8, 2021 at 18:36
  • 1
    \$\begingroup\$ @pikalek what would that solve though ? if the client is still going to deal with CSV, how is adding a JSON converter gonna help me ? the issue is not with code, it's with configuring the CSV \$\endgroup\$ Dec 8, 2021 at 18:50
  • 1
    \$\begingroup\$ @alaslipknot It helps because the configuration is managed by the converter - you're potentially automating the work. In some cases, a layer of indirection is useful. If using JSON is just as much work for you as using CSV, then admittedly, a conversion doesn't save you anything. \$\endgroup\$
    – Pikalek
    Dec 8, 2021 at 19:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .