Arel.js, The Roguelike Library: Adopting a jQuery-like API

I've been doing some thinking. I know, it's dangerous--but this time I think I might be on to something. My current project, Arel.js, has so far been doing pretty much what every other Roguelike library does, at least as far as JavaScript goes. And there's nothing wrong with that, but I think it could be so much more, you know?

So I had this idea of giving Arel.js a jQuery-like API. It would introduce something called the VOM: the "view object model". Basically, it would be a layer for interacting with the display that borrows from the DOM (document object model). Instead of providing a document, though, the VOM provides a "view". A view of what? The map, of course! I thought about calling it the "map object model", but then I realized what the acronym would be. Nope. Let's not go there.

So we have the VOM, which holds the current state of the map (and perhaps can have multiple layers). And then we have Arel.js, which not only provides the VOM, but also provides ways to modify it as well; perhaps wrapped in '$' or '_' or some other short JS variable.

The implications of this all (where you say whoa)

Arel.js would expose functions which would allow you to do the following:

$("4 4").ch("@").style("foreground", "white");

All the methods would of course return themselves, allowing for chaining. There's an enormous amount of possibilities here. You could get into tile selectors, for example:

$("* 10").ch(".");

The above code would select all the tiles in the 10th row of the map and perform the same operation on all of them (the '*' is naturally a wildcard). It would eliminate the need for clumsy for loops every time you wanted to modify a chunk of tiles. Instead, you might be able to do something like this:

$("10 10, 20 20").ch("#");

...to select all the tiles within the rectangle defined by the points (10, 10) and (20, 20) and set their character to "#". This would make modifying the map incredibly easy and, if optimized correctly, incredibly fast.

But the VOM would be much more than a wrapper for painting characters to the screen: it would hold the entire state of the map. This allows for even further optimization, but also lets you do stuff like finding the current character at a specific tile, or even storing references to your own custom data structures directly on the VOM. So you'd first store a reference to your tile data structure on each tile in the VOM:

$("* *").forEach(function(x, y) {
  this.data(yourMapStructure[x][y]);
});

Then later on if you needed to get a reference to your data structure through the VOM you could do this:

$("5 5").data().somePropertyOnYourTileObject;

Pretty handy.

Finishing up

So with all my brainstorming so far, introducing a jQuery-like API into Arel.js seems like it would introduce an unprecedented level of cleanliness and flexibility. It would also increase development speed and code maintainability. If you've got any thoughts on this design pattern please let me know, so that I can take them into consideration moving forward with Arel's development.

7 Cool JavaScript Expressions You Should Never Use

I think we can all agree that JavaScript is a pretty cool language. And as with many things, some bits of JavaScript are cooler than others. However, the cool-ness of a piece of JavaScript code is by no means synonymous with its practicality. In fact, one might go so far as to say that the coolness of a JavaScript statement is an inverse measure of how often it should be used. That is, the cooler the code is, the less you should use it.

And if that's the case, then you should never, ever use anything you see in this article, because from here on out you will be exposed to some Seriously Cool Code.

1) Truncating numbers with bitwise operators

You can use bitwise operators to truncate numbers, like so:

num = ~~num;
num = num#
num = num|num;

Each of these is roughly equivalent to using parseInt or floor on a number, and will all yield the same result. They behave like Math.floor(num) would, assuming the number is positive. They always behave like parseInt(num, 10). Of the three, the last appears to be the fastest.

2) While loop with the iterator in the condition

// while loop with iterator as condition
var i = 5;
while(i--) {

}

This is a reverse for loop with what appears to be no conditional logic! Is it infinite? Nope. Since 0 is a falsy value, when i-- results in zero, the loop will execute a final time and quit. It's quick, easy, and the fastest loop currently known.

3) If statements without the if

someBoolean && (someStatement = 10);

Okay, what's going on here? We're taking advantage of the fact that when parsing conditional statements, the return value of the statement is evaluated. We also know that if the left hand statement of an && operator is evaluated as truthy, the right hand will be evaluated as well; otherwise, it won't be. So this code is essentially equivalent to this:

if(someBoolean) {
someStatement = 10;
}

4) Comma operator

var a = 1,
b = 2;

b = (a++, 10);

The little known comma operator can be a bit mysterious and tricky to understand, but once you know what it means, it can be rather useful. Note, however, that useful is not equivalent with maintainable or understandable, and both of those take precedence over "useful". Anyways, the comma operator performs all statements enumerated and returns the last statement's value.

That means, in the above code, "a" will end up equaling 2, and "b" will end up equaling 10; the two statements in the last line are evaluated, and the return value of the last one is passed on.

5) The double exclamation point!!

value = !!value;

Using a double exclamation point will instantly identify you as an over-excited internet poster under-familiar with the colloquial usage of English. (unless you're writing in JavaScript, in which case it's perfectly ok). The double exclamation point, or double bang, converts a truthy or falsy value to "true" or "false". In other words, it operates exactly like Boolean(value) would.

6) Define value if undefined

value = value || "hello world";

This function is quite simple. It defines a value if it appears to be undefined. That is, if the value already evaluates to a falsy value (which by some strange twist of fate, "undefined" does), it's replaced by whatever comes after the OR operator. Note: the following is a much safer, but slightly longer, way of ensuring the same thing:

value = (typeof value !== "undefined") ? value : "hello world";

The above code checks to see if "value" is literally exactly equal to undefined, and will not fail if "value" does not exist anywhere in the code and is unrecognized in addition to being undefined. However, it is a mouthful. Or lineful, dare I add.

7) The void operator

undefined = void 0;

There is an operator called void. It evaluates whatever expression is passed to it and then returns a true, unadulterated value of undefined. This is useful in cases where you suspect that undefined may in fact have been defined at some point (and yes, that is legal in JavaScript). You can also compare directly against void 0 if you don't want to overwrite whatever definition undefined has.

That's all, folks!

I think that's a sufficient amount of coolness in JavaScript for now, I don't want to freeze anybody out. And, having read this article, keep in mind that you should never, ever use any of the code I've demonstrated for you above.

But, since I know you'll ignore me, at least just remember to comment your super-cool JavaScript code. If not for yourself, at least for the sake of the next developer that comes along, who, being naturally less cool than you, will be unable to understand it.

And please, if you have any more cool, comment-worthy JavaScript, be sure to leave it below in the comments or shoot me an email--I'd love to see it.

Arel.js: A JavaScript Roguelike Library

What is Arel.js?

Arel.js is a lightweight JavaScript Roguelike development library designed to be both extremely performant and incredibly flexible.

Why am I writing it?

After completing a few roguelikes in JavaScript--and starting many more--I've come to the conclusion that I really should be relying on a library or toolkit to handle all the basic interaction between the game and the player. The input and the output. For JavaScript, this layer is the browser.

I believe that there are already a few such resources available, such as ROT.js, for example. I briefly considered using ROT; it seems to be pretty popular and the documentation is excellent. However, I really wanted to work with something that I myself had created and was intimately familiar with. To that end I thought about writing a wrapper for ROT.js, so that it would be my code on top.

However, I knew I'd run into problems and while writing a wrapper for ROT would be workable, it wouldn't be as satisfying as writing my own library. Then I realized that I in fact already have a sizable codebase built up, functions I find myself reusing between projects quite frequently. Why couldn't I write a wrapper for those instead?

To that end, I have begun work on a lightweight library of my own. It's not really anything to look at right now, as it consists mainly of input and output handling. But it's not going to stop there--I plan on implementing all sorts of goodies, like field of view, pathfinding, dungeon generation, and more. It also has extremely thorough documentation provided by YUIDoc.

When will it be usable?

Arel is available now: just download it from Github and include the source files in your project, if you'd like. Of course, it doesn't do much at present, and its development is only a hobby at the moment. However, I do plan on continuing to work on it into the foreseeable future.

If you have any questions or suggestions that you'd like to make, please leave a comment below. I'll get back to you as soon as I can.

Impera: 7DRL Success!

"Your allies have betrayed you; your mighty arch-enemy, the Demon Mage Impera, has stripped you of your powers and cast you into his arena. But your once-mighty Magicks are not all lost; you have retained the ability to create walls of pure mental energy. Fight your way through the arena to challenge Impera himself and gain your revenge."

I'm happy to announce that my entry for the 7dRL challenge this year, Impera, is a resounding success. I set my sights low at the beginning of the week, and by the end of the week had implemented everything I wanted to and more. I also had plenty of time to polish and bug fix. You can click here to play Impera; otherwise, read on.

The game is based around the idea of arena battles (eight total), with each level presenting a new type of monster. There are eight types of monsters, and each monster has its own behaviors that you'll need to learn how to counter. In addition to the eight monster types, the eighth and final level of the game features Impera, the Demon Mage. He's the archetype of the evil baddy found in most fantasy stories and games.

The main strategy of the game involves placing walls, which you use to cut off enemy attacks or trap monsters. Once you place a wall it's there forever, and if you get surrounded by walls and/or corpses, you die. Thus, you'll find yourself having to move around the map a lot in order to avoid getting walled in and buried alive. On the other hand, you can take advantage of these permanent walls to bury (most) enemies alive.

I didn't have as much time to balance and optimize the game as I wanted, so hopefully it's not too easy/hard. It's also technically possible to complete the game without placing a single wall, although I haven't managed to do so yet. As a matter of fact, I haven't managed to beat the game at all. All you need is a relatively modern browser, although your computer might be struggling by the time you reach the end of the game. Hopefully that's not too much of an issue. 

Oh, and please don't look at the source code without a hazmat suit on; I wouldn't want to be responsible for any deaths due to dangerously terrible code. It's over two thousand lines, probably one of my biggest projects yet, and I've pretty much thrown code architecture out of the window.