Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Bitwise operator-safe state values. #1

Merged
merged 2 commits into from Jun 11, 2011

Conversation

Projects
None yet
2 participants
Contributor

xdissent commented Jun 10, 2011

Hey Mike, here's my changes. I added the exception to warn users if they try to make more than 30 states and cleaned up some variables in the loops for efficiency. Plus, of course, the power-of-2 based state values. You should be able to hit "merge" (or similar) on this pull request and it will merge my changes into your master branch. Thanks again, and great work!

Greg

xdissent added some commits Jun 10, 2011

@xdissent xdissent Added bitwise operator compatible state values.
Fixed unscoped iterator variable.
424c8fa
@xdissent xdissent Added 30 symbol limit exception.
Optimized array length and index lookups in loops.
Replaced name test against empty string with boolean test (empty string evaluates to false).
21ab780
Owner

boneheadmed commented Jun 10, 2011

Very cool once again Greg. I'm a bit concerned about the max 30 states,
mainly because I'm up to 25 already in my current game. Is there a way
to expand this beyond 30 to say 60 or would that make it overly complex?

I could drop the singleton nature of the Symbols class, but I really
wanted to prevent someone from accidentally creating more than one
instance whereby the symbol names and numbers wouldn't match, leading to
hard to find debug problems.

Another idea may be to set an option during initializing the Symbols
class so that you could choose either bitwise or standard integers as
the representation. What do you think?

Mike

On 6/10/2011 3:15 PM, xdissent wrote:

Hey Mike, here's my changes. I added the exception to warn users if they try to make more than 30 states and cleaned up some variables in the loops for efficiency. Plus, of course, the power-of-2 based state values. You should be able to hit "merge" (or similar) on this pull request and it will merge my changes into your master branch. Thanks again, and great work!

Greg

Contributor

xdissent commented Jun 11, 2011

Yeah, unfortunately Javascript uses 64bit double precision floats to represent all numbers. We're lucky they're implemented the way they are or we might not even get the familiar 32bit integer style lower bits, which would mean no practical binary operations at all. With double floats, you can represent some very large integers - far larger than 2^30 (which is where my symbols implementation starts to choke). The problem is that the underlying bits don't increment in powers of 2 anymore, which means your bitwise operations to determine which state(s) you're in will break down at 2^31 as you define your 31st state. =/

Example: http://jsbin.com/iwoti6

Dropping the singleton requirement does sound like a good idea, but only in the context that you could apply a different set of symbols to different base classes. For example, I'd like to have some global game states (indicating the current level or loading state perhaps) and some entity states (running, shooting etc) that don't necessarily even make sense together and shouldn't be available on both the ig.Game and ig.Entity classes. That being said, there is also a desire to share states with subclasses, which could optionally add additional states (only available to that subclass or subclasses of it). Since the only source of potential confusion is when a subclass accidentally tries to compare its state to a state on the subclass, but referenced on the parent class:

new ig.Symbols("RUNNING JUMPING", [ig.Entity]); // Or whatever
new ig.Symbols("SHOOTING", [EntityEnemy]);

var e = ig.game.spawnEntity(ig.Entity, 0, 0);
e.state = ig.Entity.RUNNING;        // Fine
e.state = ig.Entity.SHOOTING;       // Error - only defined on subclass
e.state = EntityEnemy.SHOOTING;     // Error - not an instance of EntityEnemy

var ee = ig.game.spawnEntity(EntityEnemy, 0, 0);
ee.state = EntityEnemy.SHOOTING;    // Fine
ee.state = EntityEnemy.RUNNING;     // Also fine - inherited
ee.state = ig.Entity.RUNNING;       // Ok (and bit compatible) but confusing
ee.state = ig.Entity.SHOOTING;      // Error - undefined on ig.Entity

But that also brings up the question of where the states should be defined, because we're putting the onus on the class to know which states are available to it through the inheritance chain (and to add any it needs). It doesn't make sense to declare states in the init() because they'd be redeclared with every instantiation of the class.

I'm gonna marinate on some of these points for a while and see what I can come up with. I know we're probably over thinking everything at this point, but it also feels like we could be close to an invaluable tool for Impact games. We'll see which it is I guess ;-)

Owner

boneheadmed commented Jun 11, 2011

Thanks for the further explanation Greg. Believe me, I've overthought
this for a while, so I appreciate a good brain to help me make it
better. Let me give you some background (hope you have coffee):

The reason for the seemingly odd way of creating the symbols class, such
that you can add the same exact symbols to both ig.Entity and ig.Game
for example, is two-fold. Initially I tried to make symbols its own
singleton class represented by /ig.s/. But I ran into some problems. See
my initial attempt problem:
http://impactjs.com/forums/help/problem-trying-to-get-custom-class-to-work-within-weltmeister

So I found that if I instead pushed the symbols onto ig.Entity or
another Impact class, then I didn't have the problem in Weltmeister.
However doing so destroyed some of the power of symbols. If you're
familiar with Ruby, once you make mention of a symbol it is available
essentially globally to any other class. I toyed with therefore adding
the symbols to the base /ig/ class, but I thought there could
potentially be name conflict problems as Impact gets upgraded, so I
decided to make the symbols available to any impact class that the user
wanted. Therefore, the odd implementation.

The other issue is that I have a need to pass messages between different
entities. Therefore I always want the same symbol name to represent the
same number, otherwise it is a debugging nightmare.

The power of the symbol is that it everywhere means the exact same
thing, there is never any ambiguity where it may mean one thing in one
class and one in another. Therefore optimally it is essentially a
global variable. I thought also about making Symbols it's own object
outside of Impact, but I was concerned about potentially overwriting
other custom objects or jQuery, etc that people may be using. Also I
wanted it to feel like idiomatic Impact. Therefore it would by
represented by ig.Entity or ig.Game, etc.

I'll think about this some more too. I wonder if we code in such a way
that we can combine two binary variables and therefore get 60? I'm
guessing it is hard to get the bitwise operators to function. Another
possibility is a dual set of symbols, one standard and one binary so you
could use the standard as in
ig.Entity.FALLING

or binary

ig.Entity.b.RUNNING

with the b set representing symbols on which you can apply bitwise
operations?

@boneheadmed boneheadmed added a commit that referenced this pull request Jun 11, 2011

@boneheadmed boneheadmed Merge pull request #1 from xdissent/master
Bitwise operator-safe state values.
02767b2

@boneheadmed boneheadmed merged commit 02767b2 into boneheadmed:master Jun 11, 2011

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment