startshape realStart rule realStart { start { x 2 } } background { b -1 } rule start { terminal4 { r 12 } } rule start { terminal1 { r 12 } } rule start { terminal4 { r 12 } } rule start { terminal4 { r 12 } } rule start .05 { terminal2 { r 12 } } rule terminal4 { SQUARE { b 0.50 s .055 sat 0.40 hue 95 } SQUARE { b 1 s .055 a -.8 } train { x .06 } train { r 90 y .06 } train { r 180 x -.06 } train { r 270 y -.06 } } rule terminal2 2 { SQUARE { b 1 s .055 a -.85 } train { r 90 y .06 } train { r 270 y -.06 } } rule terminal2 1 { SQUARE { b 1 s .055 a -.8 } train { x .06 } train { r 90 y .06 } } rule terminal2 1 { SQUARE { b 1 s .055 a -.85 } train { x.06 } train { r 270 y -.06 } } rule terminal1 { CIRCLE { b 1 s .055 a -.9 } train { r 90 y .06 } } rule terminal1 { CIRCLE { b 1 s .055 a -.9 } train { r -90 y -.06 } } rule train 1 { CIRCLE { b 1 s .045 a -.9 } train { x .06 } } rule train 2 { terminal1 { } } rule train .02 { terminal2 { } } rule train .005 { terminal4 { } } rule train .03 { CIRCLE { b 1 s .03 a -.9 r -95 } }

Keith's Blog

A teen's .net musings

Future

Posted on February 9, 2011 at 9:29 PM

I am going to be redoing the blog posts from my last engine (dasblog, don’t try, not worth it) in the next few days/months/years/maybe never. I am having some difficulty extracting the information and media from the old format, but I think that it will not be long before I should be able to post them again. In the meantime, I will continue to post about 7Bomb and other related musings. Sorry for the long reprieve any readers they may be if any.

7Bomb Rocks!!!!

Posted on February 9, 2011 at 9:23 PM

7Bomb, the new game that I wrote for the windows phone 7 is doing unexpectedly well! As you can see on the new banner (or old banner with out broken search bar) we have over 1000 downloads and a 9 and counting reviews. I never expected to have anywhere near this amount of downloads, and am very excited to see where it will be going next. As a sneak preview of the next update, I am fixing the mine bug and adding more explosion animation. Please post with any ideas or requests that you have. The next update should be on the market by tomorrow, the 10th. Have fun!!!

Context Free World

Posted on June 4, 2010 at 5:44 PM

I have been dabbing in context free again and have created some new works that I would like to share. The first of a few that I will be posting on is a work on the world. I got the original idea from a project that a guy made called It's a Small World After All I thought it was unique and so I elaborated on it. I saw that it did a really good job of suggesting a world, so I decided to give it three new things and as an added challenge I forced myself not to look at his code at all and only replicate the result. The code I came up with was this:

startshape start

rule start {
	360 * { x 1 r 1 } {
		SQUARE { }
		building { y 1 }
	}
}

rule building 1.5 {
	SQUARE{}
	building{ y 1 }
}

rule building { 
	SQUARE{}
}

This didn’t quite turn out as I expected as shown here!

Fail World

Not only were the buildings pointing down but they were also too small so I then generated this new code to fit the required criteria.

startshape start

rule start {
	180 * { x 1 r -2 } {
		SQUARE { }
		building { y 1 }
	}
}

rule building 1.5 {
	SQUARE{}
	building{ y 1 }
}

rule building { 
	SQUARE{}
}

The fixed image was this:

Not so Fail World

Now the buildings were better and were facing up like they should and all was good in the world (pun intended) at least until meg came in! She came and said it was cool and that what it REALLY needed was some UFOs. I sighed and complied because I had nothing better to do and created some UFO code.

startshape ufo

rule ufo {
	CIRCLE{  }
	SQUARE{ b 1 y –.25 s 1 .5 }
	CIRCLE{ s 1.5 .5 }
}

Which then was used to make this Context-Free-Planet-Terrorizing-Machine.

UFO

Now the only trouble was getting it on top of the buildings with out it running into the top of them. This was quickly remedied by adding another building finisher that had a UFO 10 units above it.

startshape start

rule start {
	180 * { x 1 r -2 } {
		SQUARE { }
		building { y 1 }
	}
}

rule building 1.5 {
	SQUARE{}
	building{ y 1 }
}

rule building { 
	SQUARE{}
}

rule building {
	SQUARE{}
	ufo{ y 10 }
}

rule ufo {
	CIRCLE{  }
	SQUARE{ b 1 y -.25 s 1 .5}
	CIRCLE{ s 1.5 .5 }
}

This created a slightly different problem for the inhabitants of small-vill.

UFO Apocolypse

The poor inhabitants were now being over run by a UFO apocalypse. I triumphantly marched over to my slave driver of a sister and showed her the new calamity that she had ordered upon my poor creation. And of coarse she was not pleased. Sigh now she wanted there only to be one or two of the UFOs so that all of my people didn’t die at once but took a while first. So now I added a lower value to the randomness of the UFO invasion.

startshape start

rule start {
	180 * { x 1 r -2 } {
		SQUARE { }
		building { y 1 }
	}
}

rule building 1.5 {
	SQUARE{}
	building{ y 1 }
}

rule building { 
	SQUARE{}
}

rule building .03 {
	SQUARE{}
	ufo{ y 10 }
}

rule ufo {
	CIRCLE{  }
	SQUARE{ b 1 y -.25 s 1 .5}
	CIRCLE{ s 1.5 .5 }
}

The new world now only had a few enemies from the sky.

UFO Apocolypse 2

When showed the new picture my all knowing sister nodded, an said that it was good. She then ordered my new born planet into a sudden onslaught of color because “ it was to boring with out it. “ So I decided to do two things to add a little bit of color to the small little world. First I would make the sky be a nice blue and second I would add some green to the center. The first job was easy and done with a simple background directive, but the second was a little harder. I wanted the color to be around the whole planet and I wanted it to be a gradual shading into the center not a harsh one. So I decided to make every section of the planet send of a tendril of color into the center which would gradually shade from bright green into a brownish color. The only problem with just changing that was that I needed to make the erasing squares under each of the UFOs become the same color. So I did and came up with this: 

startshape start

background{ hue 200 sat 1 }

rule start {
	180 * { x 1 r -2 } {
		SQUARE { }
		building { y 1 }
		tendril{ y -1 h 107.31 sat 0.8962 b 1.0000 }
	}
}

rule building 1.5 {
	SQUARE{}
	building{ y 1 }
}

rule building { 
	SQUARE{}
}

rule building .03 {
	SQUARE{}
	ufo{ y 10 }
}

rule ufo {
	CIRCLE{  }
	SQUARE{ b 1 y -.25 s 1 .5 hue 200 sat 1 }
	CIRCLE{ s 1.5 .5 }
}

rule tendril {
	26 * { a -0.06 hue -2  y -1.1 b -0.02` z 1} {SQUARE{}}
}

This produced a colorful new habitat for my imaginary subjects.

Colorful planet

All this was shown to the royal majesty and wonder of wonders she was still not happy. So now she wanted a planet that was more green than this one. I protested saying that this was as green as it could get but she said “Not that kind of green, silly! You need less buildings and more trees.” I slowly sulked back to my corner and came up with a clever little tree design.

startshape tree

rule tree {
	SQUARE{s .05 .1 h 33.69 sat 1.0000 b 0.7017 }
	TRIANGLE{y .05 s .5 .25 h 117.90 sat 1.0000 b 0.7017 }
	TRIANGLE{ y .15 s .4 .25 h 117.90 sat 1.0000 b 0.7017 }
	TRIANGLE{ y .25 s .3 .25 h 117.90 sat 1.0000 b 0.7017 }
}

tree

 

THIS was then placed on top of the new terrain type.  The only problem is that the project that I had before was created with only one terrain in mind and the terrain really needs to be in sections that are more then completely random. I decided that the sections would be 5 squares long and would be random after that. So I came up with this new code to create the circle.

startshape start

background{ hue 200 sat 1 }

rule start {
	36 * {x 5 r -10} {
		terrainSection {r 5 }
	}
}

rule terrainSection {
	5 * {r -2 x 1}	{
		SQUARE{}
		building{ y 1 }
		tendril{ y -1 h 107.31 sat 0.8962 b 1.0000 }
	}
}

rule terrainSection {
	5 * {r -2 x 1}	{
		SQUARE{}
		tree{ y 1 s 7 z 100000}
		tendril{ y -1 h 107.31 sat 0.8962 b 1.0000 }
	}
}

rule building 1.5 {
	SQUARE{}
	building{ y 1 }
}

rule building { 
	SQUARE{}
}

rule building .03 {
	SQUARE{}
	ufo{ y 10 }
}

rule ufo {
	CIRCLE{  }
	SQUARE{ b 1 y -.25 s 1 .5 hue 200 sat 1 }
	CIRCLE{ s 1.5 .5 }
}

rule tendril {
	26 * { a -0.06 hue -2  y -1.1 b -0.02` z 1} {SQUARE{}}
}

rule tree {
	SQUARE{s .05 .1 h 33.69 sat 1.0000 b 0.7017 }
	TRIANGLE{y .05 s .5 .25 h 117.90 sat 1.0000 b 0.7017 }
	TRIANGLE{ y .15 s .4 .25 h 117.90 sat 1.0000 b 0.7017 }
	TRIANGLE{ y .25 s .3 .25 h 117.90 sat 1.0000 b 0.7017 }
}

rule tree { }

As you can see, I added the tree code that I had come up with along with the new world creation code. The way it works is I make the new circle with a larger x and r value in order to give room for each piece of terrain. Then I make a new rule that decides which terrain to use and then creates it. The last thing that I had to do was add a blank tree rule so that the forest would look semi random. The resulting picture is this:

planet with forest

I then showed this to my sis and of coarse, once again she wanted more. She said that trees do not grow on the same stuff that buildings grow on and that if they were real trees they needed dirt not artificial stuff. So I then added coloring to the crust of my planet where it had not been colonized. At this point I had spent quite a bit of time creating this piece and I showed the fruits of my labor to my dad. He looked at it with a critical eye and said that the thing that it really needed was a new terrain that included water. So I set about to implement the new requests. All I needed to do the water was to create a new terrain method that had blue squares instead of the original ones.

startshape start

background{ hue 200 sat 1 }

rule start {
	36 * {x 5 r -10} {
		terrainSection {r 5 }
	}
}

rule terrainSection {
	5 * {r -2 x 1}	{
		SQUARE{}
		building{ y 1 }
		tendril{ y -1 h 107.31 sat 0.8962 b 1.0000 }
	}
}

rule terrainSection {
	5 * {r -2 x 1}	{
		SQUARE{ h 29.74 sat 1.0000 b 0.5580 }
		tree{ y 1 s 7 z 100000}
		tendril{ y -1 h 107.31 sat 0.8962 b 1 }
	}
}

rule terrainSection {
	5* {r -2 x 1} {
		SQUARE{ h 238.63 sat 1.0000 b 0.6133 y -.5 z 100000 }
		tendril{ y -1 h 107.31 sat 0.8962 b 1 }
	}
}

rule building 1.5 {
	SQUARE{}
	building{ y 1 }
}

rule building { 
	SQUARE{}
}

rule building .03 {
	SQUARE{}
	ufo{ y 10 }
}

rule ufo {
	CIRCLE{  }
	SQUARE{ b 1 y -.25 s 1 .5 hue 200 sat 1 }
	CIRCLE{ s 1.5 .5 }
}

rule tendril {
	26 * { a -0.06 hue -2  y -1.1 b -0.02` z 1} {SQUARE{}}
}

rule tree {
	SQUARE{s .05 .1 h 33.69 sat 1.0000 b 0.7017 }
	TRIANGLE{y .05 s .5 .25 h 117.90 sat 1.0000 b 0.7017 }
	TRIANGLE{ y .15 s .4 .25 h 117.90 sat 1.0000 b 0.7017 }
	TRIANGLE{ y .25 s .3 .25 h 117.90 sat 1.0000 b 0.7017 }
}

rule tree { }

Here I created the colors for the new terrain and I decided to make the more natural terrains become a little more round or natural looking, so I decided to make their draw be in circles instead of squares. I also doubled the frequency of the circles so that it wouldn’t be as bumpy. The resulting code was now:

startshape start

background{ hue 200 sat 1 }

rule start {
	36 * {x 5 r -10} {
		terrainSection {r 5 }
	}
}

rule terrainSection {
	5 * {r -2 x 1}	{
		SQUARE{}
		building{ y 1 }
		tendril{ y -1 h 107.31 sat 0.8962 b 1.0000 }
	}
}

rule terrainSection {
	5 * {r -2 x 1}	{
		CIRCLE{ h 29.74 sat 1.0000 b 0.5580 }
		CIRCLE{ h 29.74 sat 1.0000 b 0.5580 x .5 }
		tree{ y 1 s 7 z 100000}
		tendril{ y -1 h 107.31 sat 0.8962 b 1 }
	}
}

rule terrainSection {
	5* {r -2 x 1} {
		CIRCLE{ h 238.63 sat 1.0000 b 0.6133 y -.5 z 100000 }
		CIRCLE{ h 238.63 sat 1.0000 b 0.6133 y -.5 z 100000 x .5 }
		tendril{ y -1 h 107.31 sat 0.8962 b 1 }
	}
}

rule building 1.5 {
	SQUARE{}
	building{ y 1 }
}

rule building { 
	SQUARE{}
}

rule building .03 {
	SQUARE{}
	ufo{ y 10 }
}

rule ufo {
	CIRCLE{  }
	SQUARE{ b 1 y -.25 s 1 .5 hue 200 sat 1 }
	CIRCLE{ s 1.5 .5 }
}

rule tendril {
	26 * { a -0.06 hue -2  y -1.1 b -0.02` z 1} {SQUARE{}}
}

rule tree {
	SQUARE{s .05 .1 h 33.69 sat 1.0000 b 0.7017 }
	TRIANGLE{y .05 s .5 .25 h 117.90 sat 1.0000 b 0.7017 }
	TRIANGLE{ y .15 s .4 .25 h 117.90 sat 1.0000 b 0.7017 }
	TRIANGLE{ y .25 s .3 .25 h 117.90 sat 1.0000 b 0.7017 }
}

rule tree { }

The new picture was now this:

World with water

by now my creation was becoming pretty interesting and I now realized a few things that had happened on accident but seemed to turn out well. First is the fact that the UFOs only appear over the buildings which I didn’t do on purpose but did make sense. Also is the fact that the land with trees wasn’t moved forward to be in front like the water and so it was always behind everything and met nicely at the junction between land and building or land and water. I was trying to come up with some new features for my quickly developing planet and decided to make clouds up in the sky. I had no clue on how to make this new thing and so decided to “borrow” someone else's. I looked and looked and came across a somewhat cartoonish cloud that appeared to fit nicely with the rest of my design. I was trying to understand how it worked but the author of this horrifically created code was not nice enough to give names to his methods that made any sense what so ever. If so I will not show the code here but the picture that was created was this:

cloud 

Now all I had to do was replace the UFOs with the clouds. Once I had clouds I realized that the clouds need an atmosphere and so I added some Circles that change in color from blue fading into black.

startshape planet

background {b -1 }

rule planet {
	sky { z -1000000000000 y -28 x 2}
	world{ }
}

rule world{
	36 * {r -10 x 5} {
		terrainSection {r 5 }
	}
}

rule terrainSection {
	5 * {r -2 x 1}	{
		SQUARE{}
		building{ y 1 }
		tendral{ y -1 h 107.31 sat 0.8962 b 1.0000 }
		cloud{ y 10 s 5 }
	}
}

rule terrainSection {
	5 * {r -2 x 1 } {
		CIRCLE{h 29.74 sat 1.0000 b 0.5580}
		CIRCLE{h 29.74 sat 1.0000 b 0.5580 x .5}
		tree{ y 1 s 7 z 100000}
		tendral{ y -1 h 107.31 sat 0.8962 b 1.0000 }
		cloud{ y 10 s 5 }
	}
}

rule terrainSection {
	5 * {r -2 x 1 } {
		CIRCLE{h 238.63 sat 1.0000 b 0.6133 y -.5 z 100000}
		CIRCLE{h 238.63 sat 1.0000 b 0.6133 y -.5 z 100000 x .5}
		tendral{ y -1 h 107.31 sat 0.8962 b 1.0000 }
		cloud{ y 10 s 5 }
	}
}

rule building 1.5 {
	SQUARE{}
	building{ y 1 }
}

rule building { 
	SQUARE{}
}

rule tendral {
	26 * { a -0.06 hue -2  y -1.1 b -0.02` z 1} {SQUARE{}}
}

rule tree {
	SQUARE{s .05 .1 h 33.69 sat 1.0000 b 0.7017 }
	TRIANGLE{y .05 s .5 .25 h 117.90 sat 1.0000 b 0.7017 }
	TRIANGLE{ y .15 s .4 .25 h 117.90 sat 1.0000 b 0.7017 }
	TRIANGLE{ y .25 s .3 .25 h 117.90 sat 1.0000 b 0.7017 }
}

rule tree { }

rule sky {
	100 * { s .99 b .05 a .1 z 10000  } { CIRCLE{ size 125 hue 200 b 0 sat 1 } }
}

rule cloud {
	formeB{y 1 s .75 z 60}
	inNUAGE{z 30}
	inNUAGE{flip 90}
}

rule cloud 10 {}

rule inNUAGE 3{
	formeB{y .9}
	inNUAGE{x .5 s .8 z -15}
}

rule inNUAGE 3{
	formeB{y .9}
	inNUAGE{x .5 s .6 z -15}
}

rule formeB 15{
	formeA{}
	formeB{s .9 r 73 z -1}
}

rule formeB 15{
	formeA{} 
	formeB{s .9 r 53 z -1}
}

rule formeB {
	formeA{}
	formeB{s .9 r 127 z 15}
}

rule formeA 3{
	CIRCLE {hue 195 sat .3 x -.75}
	INformeA{x -.72 s .99}
}

rule formeA 6{
	CIRCLE {hue 195 sat .3 x -.6}
	INformeA{x -.57 s .99}
}

rule formeA {
	CIRCLE {hue 195 sat .3 x -.3}
	INformeA{x -.27 s .99}
}

rule INformeA 3{
	INformeA{s .99}
}

rule INformeA 3{
	INformeA{x .01}
}

rule INformeA {
	CIRCLE{b 1}
}

As you can see the code is a little different  but mostly is the same. The resulting picture is this:

World4

JSAdventure

Posted on May 11, 2010 at 4:50 PM

Copy this code into an html file and then run it and you will get the saving on your computer. All this does is make it so that you get the saved cookies on your computer instead of the site which makes it so that they don’t get saved to this domain but yours which for some reason seems to work better.

<html>
<head>
    <title>Text Adventure</title>
</head>
<body onunload="save()">
    <p id="p0.3">
        You do not have javascript enabled currently. Please enable javascript to play my
        game.</p>
    <script type="text/javascript">
        "use strict";
        var versionNumber = 0.3;
        var paragraphElementID = "p" + versionNumber;
        var currentRoom;
        var rooms = {};
        var inventory = {};
        var output = "";
        var header = "<b>JSAdventure version " + versionNumber + "</b> <br/> <br/>";
        var setUp = false;
        var jsonizer = {};

        // implementation of JSON.stringify borrowed from http://www.sitepoint.com/blogs/2009/08/19/javascript-json-serialization/
        jsonizer.stringify = function (obj)
        {
            var type = typeof (obj);
            if (type !== "object" || obj === null)
            {
                // simple data type
                if (type === "string")
                {
                    obj = '"' + obj + '"';
                }
                return String(obj);
            }
            else
            {
                // recurse array or object
                var nameOfElement;
                var v;
                var json = [];
                var isArray = (obj && obj.constructor === Array);
                for (nameOfElement in obj)
                {
                    if (obj.hasOwnProperty(nameOfElement))
                    {
                        v = obj[nameOfElement];
                        type = typeof (v);

                        if (type === "string")
                        {
                            v = '"' + v + '"';
                        }
                        else if (type === "object" && v !== null)
                        {
                            v = jsonizer.stringify(v);
                        }

                        json.push((isArray ? "" : '"' + nameOfElement + '":') + String(v));
                    }
                }
                return (isArray ? "[" : "{") + String(json) + (isArray ? "]" : "}");
            }
        };

        // implementation JSON.parse borrowed from http://www.sitepoint.com/blogs/2009/08/19/javascript-json-serialization/
        jsonizer.parse = function (str)
        {
            if (str === "")
            {
                str = '""';
            }
            var func = new Function("var p =" + str + ";" +
    "return p;");
            return func();
        };

        function CreateCookie(name, value, days)
        {
            var expires = "";
            if (days)
            {
                var date = new Date();
                date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
                expires = "; expires=" + date.toGMTString();
            }
            value = value.replace(/\;/g, "#");
            document.cookie = name + "=" + value + expires + "; path=/";
        }

        function ReadCookie(name)
        {
            var nameEQ = name + "=";
            var ca = document.cookie.split(';');
            for (var i = 0; i < ca.length; i = i + 1)
            {
                var c = ca[i];
                while (c.charAt(0) === ' ')
                {
                    c = c.substring(1, c.length);
                }
                if (c.indexOf(nameEQ) === 0)
                {
                    var string = c.substring(nameEQ.length, c.length);
                    string = string.replace(/#/g, ";");
                    return string;
                }
            }
            return null;
        }

        function AddToOutPut(text)
        {
            output += text;
        }

        function AddLinkToOutput(text, functionName, functionParams)
        {
            AddToOutPut("<b onclick=\"" + functionName + "(" + functionParams + ")\">" + text + "</b>");
        }

        function AddToCurrentText(text)
        {
            document.getElementById(paragraphElementID).innerHTML += "<br/" + text;
        }

        function WriteStoredLine()
        {
            document.getElementById(paragraphElementID).innerHTML = header + output;
            output = "";
        }

        function WriteDiscription()
        {
            AddToOutPut("You are in " + currentRoom.name + "<br/><br/>");
            AddToOutPut(currentRoom.discription + "<br/><br/>");
            for (var direction in currentRoom.exits)
            {
                if (currentRoom.exits.hasOwnProperty(direction))
                {
                    AddLinkToOutput(direction + " ", "Go", "'" + direction + "'");
                    if (currentRoom.exits[direction].key)
                    {
                        AddToOutPut("there is a locked exit.<br/>");
                    }
                    else
                    {
                        AddToOutPut("there is an exit.<br/>");
                    }
                }
            }
            for (var x in currentRoom.items)
            {
                if (currentRoom.items.hasOwnProperty(x))
                {
                    AddToOutPut("There is a ");
                    AddLinkToOutput(x, "GetOrDrop", "'" + x + "'");
                    AddToOutPut(" in the room.<br/>");
                }
            }
            AddToOutPut("<br/>");
            for (var itemName in inventory)
            {
                AddToOutPut("You have a ");
                AddLinkToOutput(itemName, "GetOrDrop", "'" + itemName + "'");
                AddToOutPut(" in your inventory.<br/>");
                if (inventory[itemName].listOfUses)
                {
                    AddToOutPut("With it you can:<br/>");
                    for (var useName in inventory[itemName].listOfUses)
                    {
                        if (inventory[itemName].listOfUses.hasOwnProperty(useName))
                        {
                            AddToOutPut("&nbsp&nbsp&nbsp&nbsp&nbsp");
                            AddLinkToOutput(useName, "Use", "'" + itemName + "','" + useName + "'");
                        }
                    }
                }
            }
            WriteStoredLine();
        }

        function Room(name, discription)
        {
            this.name = name;
            this.discription = discription;
            this.actors = {};
            this.items = {};
            this.exits = {};
            this.visits = 0;
            this.events = [];
            rooms[name] = this;
        }

        function Exit(direction, room, targetRoom, key)
        {
            this.direction = direction;
            room.exits[direction] = this;
            this.targetRoom = targetRoom;
            this.key = key;
        }

        function Item(name, container, carryable, listOfUses)
        {
            this.name = name;
            if (container)
            {
                container.items[name] = this;
            }
            else
            {
                inventory[name] = this;
            }
            this.carryable = carryable;
            this.listOfUses = listOfUses;
        }

        function Event(room, action, timesInRoom)
        {
            rooms[room].events.push(this);
            this.action = action;
            this.timesInRoom = timesInRoom;
        }

        function GetOrDrop(item)
        {
            var found = false;
            for (var name in currentRoom.items)
            {
                if (name === item)
                {
                    if (currentRoom.items[name].carryable === true)
                    {
                        inventory[name] = currentRoom.items[name];
                        delete currentRoom.items[name];
                        WriteDiscription();
                        found = true;
                    }
                    else
                    {
                        AddToCurrentText("You can't carry that! It's too big!");
                    }
                }
            }
            if (!found)
            {
                for (var itemName in inventory)
                {
                    if (itemName === item)
                    {
                        currentRoom.items[itemName] = inventory[itemName];
                        delete inventory[itemName];
                        WriteDiscription();
                    }
                }
            }
        }

        function Go(direction)
        {
            for (var i in currentRoom.exits)
            {
                if (currentRoom.exits[i].direction === direction)
                {
                    var door = currentRoom.exits[i];
                    if (!door.key)
                    {
                        if (rooms[door.targetRoom] === currentRoom)
                        {
                            AddToOutPut("You go through the exit and somehow come right back to the room you were just in... Weird...<br/><br/>");
                        }
                        currentRoom = rooms[door.targetRoom];
                        currentRoom.visits += 1;
                        WriteDiscription();
                    }
                    else
                    {
                        for (var x in inventory)
                        {
                            if (x == door.key.name)
                            {
                                door.key = null;
                                currentRoom = rooms[door.targetRoom];
                                currentRoom.visits += 1;
                                WriteDiscription();
                                AddToCurrentText("You unlocked the door with your " + x + " and step through.");
                                break;
                            }
                        }
                        if (door.key)
                        {
                            AddToCurrentText("You can't go that way because it's locked with a " + door.key.name);
                        }
                    }
                    break;
                }
            }
        }

        function Use(nameofitem, nameofuse)
        {
            for (var i in inventory)
            {
                if (i === nameofitem)
                {
                    var tool = inventory[i];
                    for (var z in tool.listOfUses)
                    {
                        if (z === nameofuse)
                        {
                            var func = new Function(tool.listOfUses[z]);
                            func();
                        }
                    }
                }
            }
        }

        function save()
        {
            if (setUp === true)
            {
                var inventoryJSON = jsonizer.stringify(inventory);
                var roomsJSON = jsonizer.stringify(rooms);
                CreateCookie("roomsJSON" + versionNumber, roomsJSON, 50);
                CreateCookie("inventoryJSON" + versionNumber, inventoryJSON, 50);
                CreateCookie("currentRoomName" + versionNumber, currentRoom.name, 50);
                CreateCookie("currentText" + versionNumber, document.getElementById(paragraphElementID).innerHTML, 50);
                CreateCookie("saved" + versionNumber, "saved", 50);
            }
        }

        if (ReadCookie("saved" + versionNumber))
        {
            rooms = jsonizer.parse(ReadCookie("roomsJSON" + versionNumber));
            inventory = jsonizer.parse(ReadCookie("inventoryJSON" + versionNumber));
            currentRoom = rooms[ReadCookie("currentRoomName" + versionNumber)];
            var text = ReadCookie("currentText" + versionNumber);
            text = text.replace(/$/g, "");
            document.getElementById(paragraphElementID).innerHTML = text;
            setUp = true;
        }
        else
        {
            var room1 = new Room("Room1", "A plain room... what else?");
            var room2 = new Room("Room2", "Another plain room... sigh...");
            var room3 = new Room("Room3", "Yet a third plain room... I'll give you a guess what the next one is!");
            var room4 = new Room("Room4", "Yep! Another plain one.");
            var room5 = new Room("Room5", "This is a secret room!!!!");
            var room6 = new Room("Room6", "Congrats! you just got past the first puzzle.");

            currentRoom = room1;
            currentRoom.visits += 1;

            var bouncyBall = new Item("small bouncy ball", room1, true, null);
            var bolder = new Item("large rock", room3, false, null);
            var key = new Item("key", room3, true, null);
            var bombuses = {};
            bombuses["blow up rock"] = "" +
                "for (var i in currentRoom.items)" +
                "{" +
                    "if (currentRoom.items[i].name == 'large rock')" +
                    "{" +
                        "delete currentRoom.items[i];" +
                        "for (var x in inventory) " +
                        "{" +
                            "if (inventory[x].name == 'bomb') " +
                            "{" +
                                "delete inventory[x];" +
                            "}" +
                        "}" +
                        "for(var room in rooms)" +
                        "{" +
                            "if(room == 'Room3')" +
                            "{" +
                                "new Exit('Down', rooms[room], 'Room6', null);" +
                            "}" +
                            "else if(room == 'Room6')" +
                            "{" +
                                "new Exit('Up', rooms[room], 'Room3', null);" +
                            "}" +
                        "}" +
                        "WriteDiscription();" +
                        "AddToOutPut('<br/>You use your bomb to blow up the rock<br/> and it leaves a small opening you can crawl through.');" +
                        "AddToCurrentText(output);" +
                        "output = '';" +
                        "return;" +
                    "}" +
                "}" +
                "AddToCurrentText('<br/>There is nothing to blow up in here...');";
            var bomb = new Item("bomb", room5, true, bombuses);

            var room1exit1 = new Exit("South", room1, "Room2", null);
            var room2exit1 = new Exit("North", room2, "Room1", null);
            var room2exit2 = new Exit("East", room2, "Room3", null);
            var room3exit1 = new Exit("West", room3, "Room2", null);
            var room3exit2 = new Exit("South", room3, "Room4", null);
            var room4exit1 = new Exit("North", room4, "Room3", null);
            var room4exit2 = new Exit("South", room4, "Room5", key);
            var room5exit = new Exit("North", room5, "Room4", null);

            WriteDiscription();
            setUp = true;
        }
    </script>
</body>
</html>

JSAdventure Item Uses and Saving

Posted on May 11, 2010 at 1:30 PM

In this version I have added two major features. First is the ability to create uses for the items. For instance I made a boulder in the previous version that was not carryable. Now with the bomb in the new locked room you can blow up the boulder and reveal an exit leading down to a new room. This was all possible through JavaScript's eval. I take the string which is defined in creation of the item and call eval on it which will parse the string and execute it as though it were just plain JavaScript. I have found this somewhat useful and effective only because it allows my program to be easily extended, though there are some things that you will need to think about before using it every where. First is the fact that all eval code should only be taken from your own program and nowhere else. This is because if you were to gather it from some other source it might be liable to tampering and could cause data loss or some other hap hazard effect. The only places I have found that this was useful was in this case and in json which I have used in this update as well. Here is the code for the uses.

function Use(nameofitem, nameofuse)
{
    for (var i in inventory)
    {
        if (i === nameofitem)
        {
            var tool = inventory[i];
            for (var z in tool.listOfUses)
            {
                if (z === nameofuse)
                {
                    var func = new Function(tool.listOfUses[z]);
                    func();
                }
            }
        }
    }
}

As you can see I try not to have actual references to any of the objects and so I keep the names instead. And using the objects in JavaScript (or associative arrays, they are one in the same) I can access the item or exit or whatever that I need just from the name of the object and it’s container. Then once I have the item I iterate through the objects list of uses to find the one I want and then I execute it. It’s as simple as that, but now if I wanted I could create an admin console or something in c# to generate whatever I’d like and just convert it to json to be used as the map or objects that I can create.

The last thing that I added into this version was the use of cookies for saving state. I searched and searched all over the internet for a good serializer when I realized that it was all right under my nose! json when trying to serialize straight to and from JavaScript on the same client is amazing and it was quite straight forward too. I just take some code to serialize ( borrowed from here ) into json and then just call eval to bring it back.

jsonizer.stringify = function (obj)
{
    var type = typeof (obj);
    if (type !== "object" || obj === null)
    {
        // simple data type
        if (type === "string")
        {
            obj = '"' + obj + '"';
        }
        return String(obj);
    }
    else
    {
        // recurse array or object
        var nameOfElement;
        var v;
        var json = [];
        var isArray = (obj && obj.constructor === Array);
        for (nameOfElement in obj)
        {
            if (obj.hasOwnProperty(nameOfElement))
            {
                v = obj[nameOfElement];
                type = typeof (v);
                if (type === "string")
                {
                    v = '"' + v + '"';
                }
                else if (type === "object" && v !== null)
                {
                    v = jsonizer.stringify(v);
                }
                json.push((isArray ? "" : '"' + nameOfElement + '":') + String(v));
            }
        }
        return (isArray ? "[" : "{") + String(json) + (isArray ? "]" : "}");
    }
};

The code is a little complicated ( I still don’t exactly know all that v does, but I the basic idea is to iterate over all of the properties of the object (or associative array which allows us to for loop over them) and either return a hard coded value, or rinse and repeat on the new object. Then what you get back is all of the literals of the object that you wanted serialized. Then when I want any of it back I just eval the string and I get back the object with all of it’s literals and everything still intact.

Ok, so I lied about that being the very last thing but this one is minor. I was looking for a good source analysis program for JavaScript and stumbled over jslint. At first the site looks like some small side project that somebody just works on in their spare time, but don’t be fooled, it can pack a powerful punch! The premise is that you take your crappy JavaScript code and put it all into jslint and it will yell at you telling you that it’s crappy. It actually found over 1000 problems with my code and I fixed every single one. Now I'm not going to say that my program is perfect ( you have to realize that I started coding in JavaScript last week ) but it sure is a lot better than it was.

So if anyone cares… Here it is!

You do not have javascript enabled, please enable it and try again.