Tuesday, 10 February 2015

Maybe I Should Have Studied CS

Well, I've hit a really awkward snag that I'm kludging my way through, but what I should have done to begin with is a mystery to me. It's difficult to even describe the problem I'm having.

Suppose I have two different upgrades you can buy, they various properties like a name and a cost and so forth. Each one is an object in the game. If upgrade A modifies how upgrade B works by modifying one or more of its properties, then it needs to be declared after object B in the code. If I declare A first then it looks for B.cost and returns an error - since B is undefined it has no properties.

But when I'm adding new things, I don't want to spend time figuring out what order they have to go in. What's more, I don't want to remove things from natural theme-related groupings to put them in logical order because that makes the code much harder to read and things much harder to find.

What I should be doing is not actually having any of these objects look at the others until run-time, but I think I've structured the whole thing in the wrong way to accomplish that. Essentially I'm left feeling that I need to define certain properties of each object as a function that runs to return the properties that I want them to be, then after defining all the objects, run those functions.

I don't like that idea much because it's really awkward and it is going to make the code look really strange, but I don't see a way around it right now. I can't even pass around a reference to B.cost until B is declared, I would have to pass around a function () {return B.cost}.

There is another way I can think of to do it, which is to have all of the functions that create these objects not create them, but instead add them to an array to be created, and to first run through the array and create all of the objects as empty objects before going through again to assign actual values to all of them. It doesn't matter if B.cost is undefined when I pass it in, as long as it is defined by the time the upgrade actually wants to do anything with it - which won't be until you buy the upgrade.

Anyway, for now I'm just kludging through by reordering things, but I think that's limiting me from doing certain things that I would be doing otherwise.


  1. Typically the way around this is for compiled languages like C++ is to declare all your objects at the top of the file (or in a separate header file that gets included at the top using compiler directives), then have all your actual implementation in a big block down at the bottom. The upside is that you can still group things logically within their section, the downside is that every object is split into two pieces. For more modularity you can put every object into its own file, which helps with that some.

    If the language you're using isn't compiled, you can usually just get away with deferring all actual work until the end of the whole file. Usually in languages like this you can define functions referencing things that don't exist as long as they exist by the time the line is actually executed.

    So it depends on the language, really.

  2. You should take the same approach in JS as well. Define an object with your cost variables, and have your upgrade objects use these variables. Then A, B, or whatever other code can modify the cost variables and the objects will see the changes.

    1. If I'm reading this right, then you are saying I'd be better off declaring game.cost and then looking up game.cost[name] than I would be declaring game.name and looking up game.name.cost. Store all the variables in one place.

      If that is what you are saying then I found a way to do it without changing too much code, which is pretty nice.