Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Josh @ Dreamland

General ENIGMA / Re: Variable performance
« on: May 17, 2014, 08:41:27 am »
I'm glad we actually have a benchmarking tool. This can be fixed with a little reflection, and depending on the user's mood, a little memory. Throughout ENIGMA's past, I've hemmed and hawed about how to treat variables referenced in with blocks. The current behavior is to look them up in the same manner as ID-referenced variables. The other behavior was to scope them into everything, so they exist and are located in the same place in every object, and therefore are trivial to access.

A third behavior I have not attempted is using virtual tables to store the variable access methods. This would make arbitraryId.myvariable into getter(arbitraryId)->get_myvariable(). This moves the burden from a switch statement based on object index to a simple virtual call. We're probably already incurring a by-pointer function call, so this could only mean savings.

The simplest way to take care of the whole "var" fiasco is with some static analysis of the code. This cannot be done with the current compiler.

Note: the behavior you are seeing, ie, GM being faster at setting a single var index, is due to the fact that GM's variables are always a map. So nothing special is constructed when you need to assign to a var. It's not that assigning to a var is expensive—constructing one is. There might be a way to improve that by enforcing a single var implementation, and moving the contents of var4_lua.cpp into var4.cpp. This would remove the need to do the allocation tricks I've done, and expose all code to the optimizer. Another quick trick might be replacing std::map with a faster map type; you could try hash_map.

Please do a benchmark with variant instead of var.

General ENIGMA / Re: EDC Partially Fixed
« on: May 12, 2014, 09:47:06 pm »
We weren't hacked; someone just decided that a good item to display on failure is "ಠ_ಠ". This was RackSpace side, which was funny. That's the only reason it was worth remarking on.

The only issue with the EDC was in how we retrieve our API URLs from the Service Catalog we are given along with our auth token. The problem was that we were just taking the first service in the catalog. That *used* to be the only service listed, but now we're given a catalog of some 25 other services, and we wanted the 14th in the list, called "CloudFiles". So now I just filter for that string. RackSpace actually recommends just hard-coding the URLs, though, so we'll probably switch to that in the near future (or next time this breaks).

Programming Help / Re: function error
« on: May 11, 2014, 04:43:05 pm »
If that works for any reason, it's because it's getting parsed into something entirely different. But it shouldn't even compile...

Programming Help / Re: Question on variables and arrays (important)
« on: May 11, 2014, 09:34:59 am »
The local and global keywords in ENIGMA, when followed by a type, begin a C++-style declaration at the instance-local or global scope, respectively.

I am still deliberating on the sanity of this behavior when it comes to arrays. Presently, local int my_int[100]; declares in the instance a C++-style array of 100 integers. This means that indices [0] - [99] are valid, while indices outside that range will cause an immediate, unrelenting, undetectable segmentation fault, in the best case. In the worst case, you'll silently break your whole game by assigning out of bounds.

What should be done about this is modifying the way arrays are treated in debug mode. That is, use a hidden, fixed-size array class behind the scenes while in debug mode. This class would report undefined behavior through the show_error mechanism.

Now that I think about it, an elegant way of dealing with it might be to create a distinction between int a[100] and int[] a;, regardless of whether we allow (unlike most languages) specifying the size in the prefix [].

As for data structures, be aware that var is a sparse matrix. This means that you can use it efficiently as an array, or a 2D map. Assigning to myvar[100000, 200000] will not significantly increase your memory usage. That said, you probably don't want local var a[100];, as this creates an array of 100 sparse matrices. You could then say [snip=EDL]a[10][10000, 15000] = 20;[snip], but the first bound would have the same limitations and dangers as previously discussed with integer arrays. Plus, it just looks weird.

Programming Help / Re: Using C++ and GML in same project. Why?
« on: April 27, 2014, 10:36:21 pm »
There are a lot of benefits to a more authentic object-oriented paradigm. I'll write up some clear and useful documentation for them after they are actually implemented. Right now, our C++ feature set is pretty limited.

Programming Help / Re: function error
« on: April 27, 2014, 10:33:28 pm »
What I mean is that the memory allocated for the variable exists. It's true that these values can be uninitialized, at least for var/variant. In fact, we attempt to do so now, at the user's option. We could technically allow something like this:

Code: (C++) [Select]
bool variable_initialized(const variant& x) {
  return x.type != -1;

This would offer the same functionality, provided the option "treat uninitialized variables as value 0" was not set.I believe we disable that functionality in release mode, presently, but that's not to say we can't undo that. In general, though, I'm opposed to this; I prefer to be able to seamlessly convert var and variant to primitive types. Before that can happen, of course, I will still need to add checking for function calls that only take the var/variant reference. So theoretically, implementing those functions wouldn't harm too much, at that stage. But I still don't encourage the practice.

But to answer your original question, yes, if you are using the local variable a, it still exists, even if you never use it outside the step event. You are able to access it in other objects using object0.a, or whatever.

The use case you give is archaic at best. If you want other entities to assign that for you, which is arguably way too intimiate (but standard, poor practice in GM), then the solution is to set it to -1 in the create event and check that in the script or whatever. In other words, if (button_grid == -1) button_grid = ds_grid_create(0,0);. This is always safe, because the create event is always performed first. So you'll never accidentally overwrite something by setting it to -1 in create.

Programming Help / Re: Does ENIGMA support command-line args ?
« on: April 27, 2014, 10:22:10 pm »
That doesn't sound right. If it's compliant, parameter_count() should give 3, with parameter_string giving "GAME.EXE", "/cheat", and "/secrets" for 0, 1, and 2, respectively.

I see. I had GM's find_value and the typical meaning of "find value" confused. I never use Game Maker's data structures; they're kind of terrible.

By object_name.instance_id.variable, I assume you mean That's the same, though, as saying object_name.variable. Once you have forced . to find you an instance, it has a definite result whose id will only point to itself. So you could just as well say, but why would you.

When you say obj_unit.x, your call is theoretically ambiguous, because there are probably multiple instances of obj_unit. ENIGMA deals with this by returning the first instance of that object, which won't always be what you want. This is where an ID comes in, which is why you stash the return value of instance_create: an ID of a specific instance of obj_unit. Note that is the unambiguous ID of the current first instance of obj_unit. Which still isn't that helpful, because it'll remain the first instance (thus being accessible through only the object name) until it's destroyed, and then you don't want to be accessing it.

Correct, on both counts. Those IDs won't change (but may be destroyed), and all lists are global.

I did my best to explain this in Q1, but I'll clarify here. If you don't have the ID of a specific instance, then there's no way to access the exact instance you want, unless by chance there is only one instance of that particular object or you are always interested in the first. So if all you know is that you want some obj_unit, you don't really know a lot. However, there are methods to access *all* of the instances, as well as to narrow down some particular instance.

You seem to already be aware of the with statement. It lets you iterate over all instances of a given object, one at a time, changing the scope of the statement to each of their scopes as you go. This is the easiest way of accessing all instances.

What you want to access a specific instance with only an object index, normally you want something like the nearest instance or the instance that intersects some point. For those, you'd use instance_nearest and collision_point, respectively. These functions accept an object index and return an ID of some instance of that object.

You can keep lists of instances, as you are doing. But if you already have the ID of some instance, then looking that ID up in the list is probably not what you want to do. Instead of un = ds_list_find_value(t0_list,up); un.image_index = 1;, try just using up.image_index = 1;. In your code, un is the index of the instance in your list, which is local to your list, while up is how ENIGMA refers to the instance.

That said, you really only need the list of units if there are many lists of units that you want to iterate over. Otherwise, you can iterate over all of them using with, as you are already doing once to zero the image_index values, and you can just use up to access the current instance of interest.

General ENIGMA / Re: Please vote for ENIGMA's new license
« on: April 26, 2014, 06:44:04 pm »
I'm talking about this:

And I am not aware of a place to submit a license for review. If there is a process for that, I'm interested in seeing it. It's likely that your proposal is a great place to start (at least better than the typical LGPL exemption). But I still need to read that over.

Off-Topic / Re: Environment Variables are Windows Only
« on: April 26, 2014, 05:35:11 pm »
I don't see a problem with using an otherwise cross-platform toolkit to do platform-dependent coding. With preprocessor expressions, equivalents or alternatives can be given on platforms which do not support that feature.

It's a little unfair that Linux users have to pick between dconf, gconf, xfconf, kconf, and just writing the keys to a file in ~. But that's the downside of customizability, something that Linux distributions have always had, and Windows has generally not. At this point, the obvious choice is dconf or just writing the file.

General ENIGMA / Re: Please vote for ENIGMA's new license
« on: April 26, 2014, 05:11:31 pm »
That puts us back in legal muddy-water, because now our license isn't Open-Source approved, and may or may not actually hold water, legally. What constitutes similar/competing software, for example? It's possible we could pull from an existing legal definition of "competing," but only a lawyer would know that.

General ENIGMA / Re: Please vote for ENIGMA's new license
« on: April 26, 2014, 03:48:41 pm »
I will have to read over the wx license, but I suspect it suffers the same problem. The problem is that if you can release an arbitrary binary linked against ours, without source code, you can lock us out and sell an improved ENIGMA binary. While this does not encumber the use of our software directly, it gives this party direct and perpetual competitive advantage, leaving this team with little incentive to continue development, and locking everyone in on a proprietary version of ENIGMA due to addiction to the improvements.

This isn't a problem for wx due to its active developer base. Outdoing the wx devs with their own source code is a lot harder than outdoing us with ours.

That's what the local keyword does. It moves your declaration into the class scope. From the behavior you describe with the keyword in place, I'd say the code is working as intended, and the problem is more likely to lie in the code that works with those variables locally.

Developing ENIGMA / Re: Inheritance
« on: April 25, 2014, 07:59:38 pm »
To summarize our previous discussion for public record,
  • What you have is basically correct, but remember that checks which don't begin with {} are expressions and not code, and can just be inlined by the compiler. Super-checks are global and do not need rewritten.
  • Stacked events cannot call their parent's event dispatch method unless you guarantee that the child does not call any of the same events. You're better off just writing all the parent's event calls in with the child's, in those methods.
  • The big chain of ifs this case is fine. It's big if-else ladders we want to avoid, where the truth of any one implies the falsity of the others. These ifs are all independent and cannot be avoided. You should consider, though, that the code for myevent_alarm_0_subcheck and myevent_alarm_1_subcheck differs by very little, if not none at all, and can probably be consolidated into one method. This falls apart if the event does something screwy like construct variable names from the digit, which can frequently (but not always) be replaced with an array.