The code below implements a “Roguelike” game in JavaScript. To see it in action, copy it into an .html file and open that file in a web browser that runs JavaScript. Or, to play an online version, visit http://thiscouldbebetter.neocities.org/roguelike.html.
If you want to run it locally, you’ll need to download a copy of the NetHack-Tiles-Vanilla.png image to the same directory, and since WordPress seems to be doing some weird automatic formatting on it, you’ll proabably need to get it directly from the URL https://thiscouldbebetter.files.wordpress.com/2013/07/nethack-tiles-vanilla.png Also, if you’re not running the game through a web server you might need to disable some of your browser’s security settings to avoid errors. Specifically, if you’re using Google’s Chrome browser, you might try using the –disable-web-security command-line option.
It’s not nearly finished yet. You can’t equip things and you can’t throw things. Most of the tools and magic items don’t do anything, and the ones that do don’t do the right thing. Monsters don’t spawn, except for one lonely ant per level. There’s no real goal, and if you go deep enough the dungeon eventually just peters (or actually errors) out. Eventually the plan is to build a full NetHack clone, or at least something very similar, but who knows how realistic that is.
UPDATE 2013-11-02 – I actually “posted” this privately three or four months ago, but I figure I might as well make it public, since it’s clear that I’m not very likely to finish it in the near future anyway.
UPDATE 2014-07-02 – I have updated the code somewhat, notably by changing all the stuff that used to be rendered with various discrete DOM elements to just draw images to a canvas instead. I changed the way the status controls work too, and I haven’t brought all of them back up to code yet.
UPDATE 2016-06-15 – Been a while. I have updated the code so that the entities store just the names of their definitions rather than the whole object, and use that to look up the actual entity definition only when needed. Also, I should note that, if you’re testing this in Google’s Chrome browser against an tileset image stored locally, you’ll need to start the browser with the “–allow-file-access-from-file” command-line flag.
<html> <body> <script type="text/javascript"> // application function Simulation() {} { Simulation.prototype.main = function() { var imageTilesPath = "nethack-tiles-vanilla.png"; var itemTypeImage = MediaLoaderItemType.Instances.Image; var mediaLoader = new MediaLoader ( this, // objectContainingCallback, this.main2, // callbackToRunWhenLoadingComplete, [ new MediaLoaderItem("Tiles", itemTypeImage, imageTilesPath), new MediaLoaderItem("TilesTransparent", itemTypeImage, imageTilesPath), ] ); mediaLoader.loadItemsAll(); } Simulation.prototype.main2 = function(mediaLoader) { var imageTiles = Image.buildFromSystemImage ( "Tiles", mediaLoader.items["Tiles"].htmlElement, new Coords(640, 432) // sizeInPixels ); imageTiles.onload = null; var imageTilesTransparent = Image.buildFromSystemImage ( "TilesTransparent", mediaLoader.items["TilesTransparent"].htmlElement, new Coords(640, 432) // sizeInPixels ); imageTilesTransparent.onload = null; var sizeOfImageTilesInTiles = new Coords(40, 27); var imagesForTiles = ImageHelper.sliceImageIntoTiles ( imageTiles, sizeOfImageTilesInTiles ); var imagesForTilesTransparent = ImageHelper.sliceImageIntoTiles ( imageTilesTransparent, sizeOfImageTilesInTiles ); Camera.initializeStatic(); var universeDefn = DemoData.buildUniverseDefn(imagesForTiles, imagesForTilesTransparent); var venues = universeDefn.buildVenues ( universeDefn, universeDefn.venueDefns, universeDefn.entityDefnGroups, [] ); var universe0 = new Universe ( "Universe0", universeDefn, venues, null // entityForPlayer ); Globals.Instance.initialize ( DemoData.buildFont(), 100, //realWorldMillisecondsPerTick, new Coords(800, 800), //viewSizeInPixels, universe0 ); } } // extensions Array.prototype.addLookups = function(keyName) { for (var i = 0; i < this.length; i++) { var item = this[i]; this[item[keyName]] = item; } } Array.prototype.getPropertyWithNameFromEachItem = function(propertyName) { var returnValues = []; for (var i = 0; i < this.length; i++) { var item = this[i]; returnValues.push(item[propertyName]); } return returnValues; } // classes function Action(name, ticksToHold, perform, argumentForPerform) { this.name = name; this.ticksToHold = ticksToHold; this.perform = perform; this.argumentForPerform = argumentForPerform; } function Activity(defnName, target) { this.defnName = defnName; this.target = target; } { // instance methods Activity.prototype.defn = function() { return Globals.Instance.universe.defn.activityDefns[this.defnName]; } Activity.prototype.initialize = function(actor) { this.defn().initialize(actor, this); } Activity.prototype.perform = function(actor) { this.defn().perform(actor, this); } } function ActivityDefn(name, initialize, perform) { this.name = name; this.initialize = initialize; this.perform = perform; } function ActorData() { // do nothing? } { ActorData.prototype.activity_Get = function() { return this._activity; } ActorData.prototype.activity_Set = function(actor, value) { this._activity = value; this._activity.initialize(actor); } } function ActorDefn(activityDefnNameInitial) { this.activityDefnNameInitial = activityDefnNameInitial; } function AnimationDefn(name, animationDefnNameNext, frames) { this.name = name; this.animationDefnNameNext = animationDefnNameNext; this.frames = frames; } { AnimationDefn.buildManyFromImageSets = function(imageSetsForFrames) { var returnValues = []; var numberOfImageSets = imageSetsForFrames.length; for (var i = 0; i < numberOfImageSets; i++) { var imageSet = imageSetsForFrames[i]; var animationDefn = new AnimationDefn ( "" + i, "" + i, AnimationFrame.buildManyFromImages(imageSet) ); returnValues.push(animationDefn); } return returnValues; } } function AnimationDefnSet(name, animationDefns) { this.name = name; this.animationDefns = animationDefns; this.animationDefns.addLookups("name"); } { AnimationDefnSet.buildFromImage = function(image) { var imageAsImageSets = [ [ image ] ]; var returnValue = new AnimationDefnSet ( image.name, AnimationDefn.buildManyFromImageSets ( imageAsImageSets ) ); return returnValue; } AnimationDefnSet.buildFromImageForHeadings = function(image, numberOfHeadings) { var imageAsImageSet = []; imageAsImageSet.push(image); var imageAsImageSets = []; for (var i = 0; i < numberOfHeadings; i++) { imageAsImageSets.push(imageAsImageSet); } var returnValue = new AnimationDefnSet ( image.id, AnimationDefn.buildManyFromImageSets ( imageAsImageSets ) ); return returnValue; } // instance methods AnimationDefnSet.prototype.toRun = function() { return new AnimationRun(this); } } function AnimationFrame(visual, ticksToHold) { this.visual = visual; this.ticksToHold = ticksToHold; } { AnimationFrame.buildManyFromImages = function(imagesForFrames) { var returnValues = []; var numberOfImages = imagesForFrames.length; for (var i = 0; i < numberOfImages; i++) { var imageForFrame = imagesForFrames[i]; var frame = new AnimationFrame ( imageForFrame, 1 // ticksToHold ); returnValues.push(frame); } return returnValues; } } function AnimationRun(animationDefnSet) { this.animationDefnSet = animationDefnSet; var animationDefns= this.animationDefnSet.animationDefns; this.animationDefnNameCurrent = animationDefns[0].name; this.frameIndexCurrent = 0; this.ticksOnFrameCurrent = 0; this.visualForFrameCurrent = this.frameCurrent().visual.cloneAsVisual(); } { AnimationRun.prototype.advance = function() { var frameCurrent = this.frameCurrent(); this.ticksOnFrameCurrent++; if (this.ticksOnFrameCurrent >= frameCurrent.ticksToHold) { this.ticksOnFrameCurrent = 0; this.frameIndexCurrent++; var animationDefnCurrent = this.animationDefnCurrent(); if (this.frameIndexCurrent >= animationDefnCurrent.frames.length) { this.animationDefnNameCurrent_Set ( animationDefnCurrent.animationDefnNameNext ); this.frameIndexCurrent = 0; } } } AnimationRun.prototype.animationDefnCurrent = function() { return this.animationDefnSet.animationDefns[this.animationDefnNameCurrent]; } AnimationRun.prototype.animationDefnNameCurrent_Set = function(value) { if (this.animationDefnNameCurrent != value) { this.animationDefnNameCurrent = value; this.frameIndexCurrent = 0; } } AnimationRun.prototype.clone = function() { return new AnimationRun(this.animationDefnSet); } AnimationRun.prototype.cloneAsVisual = function() { return this.clone(); } AnimationRun.prototype.frameCurrent = function() { return this.animationDefnCurrent().frames[this.frameIndexCurrent]; } AnimationRun.prototype.drawToGraphicsAtPos = function(graphics, drawPos) { this.visualForFrameCurrent.drawToGraphicsAtPos(graphics, drawPos); } AnimationRun.prototype.updateForVenue = function(entity) { this.advance(); } } function ArrayHelper() { // do nothing } { ArrayHelper.concatenateArrays = function(arraysToConcatenate) { var returnArray = []; for (var i = 0; i < arraysToConcatenate.length; i++) { var arrayToConcatenate = arraysToConcatenate[i]; for (var j = 0; j < arrayToConcatenate.length; j++) { returnArray.push(arrayToConcatenate[j]); } } return returnArray; } } function Attack(name, dieRollDamage) { this.name = name; this.dieRollDamage = dieRollDamage; } function Attribute(name, value) { this.name = name; this.value = value; } function AttributeGroup(name, attributes) { this.name = name; this.attributes = attributes; this.attributes.addLookups("name"); } function Bounds(pos, size) { this.pos = pos; this.size = size; this.max = new Coords(); this.center = new Coords(); this.recalculateMaxAndCenter(); } { // static methods Bounds.doBoundsOverlap = function(bounds0, bounds1) { var boundsSet = [bounds0, bounds1]; var doAllDimensionsOverlapSoFar = true; for (var d = 0; d < Coords.NumberOfDimensions; d++) { var doesDimensionOverlap = Bounds.doBoundsOverlapInDimension ( bounds0, bounds1, d ); if (doesDimensionOverlap == false) { doAllDimensionsOverlapSoFar = false; break; } } return doAllDimensionsOverlapSoFar; } Bounds.doBoundsOverlapInDimension = function(bounds0, bounds1, dimensionIndex) { var returnValue = ( bounds0.pos.dimension(dimensionIndex) < bounds1.max.dimension(dimensionIndex) && bounds0.max.dimension(dimensionIndex) > bounds1.pos.dimension(dimensionIndex) ); return returnValue; } Bounds.doBoundsInSetsOverlap = function(boundsSet0, boundsSet1) { var returnValue = false; var numberOfBoundsInSet0 = ( boundsSet0 == null ? 0 : boundsSet0.length ); var numberOfBoundsInSet1 = ( boundsSet1 == null ? 0 : boundsSet1.length ); for (var i = 0; i < numberOfBoundsInSet0; i++) { var boundsFromSet0 = boundsSet0[i]; for (var j = 0; j < numberOfBoundsInSet1; j++) { var boundsFromSet1 = boundsSet1[j]; var doBoundsOverlap = this.doBoundsOverlap ( boundsFromSet0, boundsFromSet1 ); if (doBoundsOverlap == true) { returnValue = true; break; } } } return returnValue; } // instance methods Bounds.prototype.recalculateMaxAndCenter = function() { this.max.overwriteWith(this.pos).add(this.size); this.center.overwriteWith(this.size).divideScalar(2).add(this.pos); } } function Camera(name, viewSizeInPixels) { this.name = name; this.viewSizeInPixels = viewSizeInPixels; this.viewSizeInPixelsHalf = this.viewSizeInPixels.clone().divideScalar(2); this.entity = new Entity ( this.name + "_CameraEntity", Camera.EntityDefn.name, new Coords(0, 0) ); } { // constants Camera.initializeStatic = function() { Camera.ViewSizeStandard = new Coords(480, 480); Camera.EntityDefn = new EntityDefn ( "CameraEntity", [ "Camera" ], // categoryNames null // properties ); } } function Category ( name, construct, collide, initializeEntityForVenue, updateEntityForVenue, finalizeEntityForVenue ) { this.name = name; this.construct = construct; this.collide = collide; this.initializeEntityForVenue = initializeEntityForVenue; this.updateEntityForVenue = updateEntityForVenue; this.finalizeEntityForVenue = finalizeEntityForVenue; } function CollidableData(defn) { this.defn = defn; this.mapCellOccupied = null; } function CollidableDefn(blocksMovement, blocksView) { this.blocksMovement = blocksMovement; this.blocksView = blocksView; } { function CollidableDefn_Instances() { if (CollidableDefn.Instances != null) { return CollidableDefn.Instances; } CollidableDefn.Instances = this; this.Blocking = new CollidableDefn(true, true); this.Concealing = new CollidableDefn(false, true); this.Clear = new CollidableDefn(false, false); } new CollidableDefn_Instances(); } function Collision(entities) { this.entities = entities; } function CollisionHelper() {} { CollisionHelper.prototype.collideEntities = function(collision, entity0, entity1) { var entity0DefnCategoryNames = entity0.defn().categoryNames; var categories = Globals.Instance.universe.defn.categories; for (var c = 0; c < entity0DefnCategoryNames.length; c++) { var categoryName = entity0DefnCategoryNames[c]; var category = categories[categoryName]; // hack if (category != null) { var methodForCollision = category.collide; if (methodForCollision != null) { methodForCollision(entity0, entity1); } } } } CollisionHelper.prototype.doEntitiesCollide = function(entity0, entity1) { var returnValue = entity0.loc.posInCells.equals ( entity1.loc.posInCells ); return returnValue; } CollisionHelper.prototype.findCollisionsBetweenEntitiesInSets = function ( entitySet0, entitySet1 ) { var returnValues = []; var numberOfEntitiesInSet0 = entitySet0 == null ? 0 : entitySet0.length; var numberOfEntitiesInSet1 = entitySet1 == null ? 0 : entitySet1.length; for (var i = 0; i < numberOfEntitiesInSet0; i++) { var entityFromSet0 = entitySet0[i]; for (var j = 0; j < numberOfEntitiesInSet1; j++) { var entityFromSet1 = entitySet1[j]; if (this.doEntitiesCollide(entityFromSet0, entityFromSet1) == true) { var collision = new Collision ( [entityFromSet0, entityFromSet1] ); returnValues.push(collision); } } } return returnValues; } } function Color(name, symbol, systemColor) { this.name = name; this.symbol = symbol; this.systemColor = systemColor; } { // static methods Color.getBySymbol = function(symbolToGet) { var returnValue = Color.Instances._All[symbolToGet]; return returnValue; } // instances function Color_Instances() { if (Color.Instances != null) { return Color.Instances; } Color.Instances = this; this.Transparent = new Color("Transparent", ".", "rgba(0, 0, 0, 0)"); this.Black = new Color("Black", "k", "#000000"); this.Blue = new Color("Blue", "b", "#0000ff"); this.BlueDark = new Color("BlueDark", "B", "#000080"); this.Brown = new Color("Brown", "n", "#804000"); this.Cyan = new Color("Cyan", "c", "#00ffff"); this.Gray = new Color("Gray", "a", "#808080"); this.GrayDark = new Color("GrayDark", "A", "#404040"); this.Green = new Color("Green", "g", "#00ff00"); this.GreenDark = new Color("GreenDark","G", "#008000"); this.Orange = new Color("Orange", "o", "#ff8000"); this.Purple = new Color("Purple", "p", "#ff00ff"); this.Red = new Color("Red", "r", "#ff0000"); this.Tan = new Color("Tan", "t", "#aaaa40"); this.White = new Color("White", "w", "#ffffff"); this.Yellow = new Color("Yellow", "y", "#ffff00"); this._All = new Array ( this.Transparent, this.Black, this.Blue, this.BlueDark, this.Brown, this.Cyan, this.Gray, this.GrayDark, this.Green, this.GreenDark, this.Orange, this.Purple, this.Red, this.Tan, this.White, this.Yellow ); for (var i = 0; i < this._All.length; i++) { var color = this._All[i]; this._All[color.symbol] = color; } } new Color_Instances(); } function Constants() {} { Constants.Tau = Math.PI * 2; } function Constraint(defn, entityConstrained) { this.defn = defn; this.entityConstrained = entityConstrained; } function ConstraintDefn(name, methodToRun) { this.name = name; this.methodToRun = methodToRun; } { function ConstraintDefn_Instances() { if (ConstraintDefn.Instances != null) { return; } this.Follow = new ConstraintDefn ( "Follow", function (constraint) { var entityConstrained = constraint.entityConstrained; // hack var entityToFollow = entityConstrained.loc.venue().entitiesByCategoryName [ "Player" ][0]; entityConstrained.loc.posInCells.overwriteWith ( entityToFollow.loc.posInCells ); } ); ConstraintDefn.Instances = this; } new ConstraintDefn_Instances(); } function ContainerData() { this.items = []; } { ContainerData.prototype.dropItem = function(actor, itemToDrop) { var itemsHeld = this.items; this.removeItem(actor, itemToDrop); itemToDrop.loc.overwriteWith(actor.loc); itemToDrop.loc.venue().entitiesToSpawn.push(itemToDrop); } ContainerData.prototype.removeItem = function(actor, itemToDrop) { var itemsHeld = this.items; var actionSelectNext = Globals.Instance.universe.defn.actions["Item_SelectNext"]; actionSelectNext.perform(actor); var indexOfItemToDrop = itemsHeld.indexOf(itemToDrop); itemsHeld.splice(indexOfItemToDrop, 1); if (itemsHeld.length == 0) { this.itemSelected = null; } this.controlUpdate(actor); } ContainerData.prototype.pickUpItem = function(actor, itemToPickUp) { this.items.push(itemToPickUp); itemToPickUp.loc.venue().entitiesToRemove.push(itemToPickUp); if (this.itemSelected == null) { this.itemSelected = itemToPickUp; } this.controlUpdate(actor); } // control ContainerData.prototype.controlUpdate = function(entity, pos) { if (this.control == null) { this.control = new ControlContainer ( "containerContainerData", pos, new Coords(200, 100), // size [ new ControlLabel("labelItems", new Coords(10, 10), "Items"), new ControlList ( "listItems", new Coords(10, 20), // pos new Coords(180, 70), // size "defn().itemDefn.appearance", // bindingPath this.items ) ] ); } return this.control; } } function Control() { // static class } { Control.getValueFromObjectAtBindingPath = function(object, bindingPath) { if (bindingPath != null) { var bindingAncestry = bindingPath.split("."); for (var i = 0; i < bindingAncestry.length; i++) { var bindingPath = bindingAncestry[i]; if (bindingPath.endsWith("()") == true) { bindingPath = bindingPath.substr ( 0, bindingPath.indexOf("()") ); var methodToCall = object[bindingPath]; object = methodToCall.call(object); } else { object = object[bindingPath]; } } } return object; } Control.posAbsoluteOfControl = function(control) { var returnValue = new Coords(0, 0); while (control != null) { returnValue.add(control.pos); control = control.parent; } return returnValue; } } function ControlContainer(name, pos, size, children) { this.name = name; this.pos = pos; this.size = size; this.children = children; for (var i = 0; i < this.children.length; i++) { var child = this.children[i]; child.parent = this; this.children[child.name] = child; } } { ControlContainer.prototype.drawToGraphics = function(graphics) { var drawPos = Control.posAbsoluteOfControl(this); graphics.fillStyle = "rgba(0, 0, 0, 0)"; graphics.strokeStyle = "Gray"; graphics.fillRect(drawPos.x, drawPos.y, this.size.x, this.size.y); graphics.strokeRect(drawPos.x, drawPos.y, this.size.x, this.size.y); for (var i = 0; i < this.children.length; i++) { var child = this.children[i]; child.drawToGraphics(graphics); } } } function ControlLabel(name, pos, textFormat, dataContexts, bindingPaths) { this.name = name; this.pos = pos; this.textFormat = textFormat; this.dataContexts = dataContexts; this.bindingPaths = bindingPaths; } { ControlLabel.prototype.drawToGraphics = function(graphics) { var drawPos = Control.posAbsoluteOfControl(this); var text = this.textFormat; if (this.dataContexts != null) { var textParts = text.split("^"); text = ""; for (var i = 0; i < this.dataContexts.length; i++) { var dataContext = this.dataContexts[i]; var bindingPath = this.bindingPaths[i]; var boundValue = Control.getValueFromObjectAtBindingPath ( dataContext, bindingPath ); text += textParts[i]; text += boundValue; } if (textParts.length > this.dataContexts.length) { text += textParts[this.dataContexts.length]; } } graphics.fillStyle = "Gray"; graphics.fillText ( text, drawPos.x, drawPos.y ); } } function ControlList(name, pos, size, bindingPath, listables) { this.name = name; this.pos = pos; this.size = size; this.bindingPath = bindingPath; this.listables = listables; } { ControlList.prototype.drawToGraphics = function(graphics) { var drawPos = Control.posAbsoluteOfControl(this); graphics.fillStyle = "rgba(0, 0, 0, 0)"; graphics.strokeStyle = "Gray"; graphics.fillRect(drawPos.x, drawPos.y, this.size.x, this.size.y); graphics.strokeRect(drawPos.x, drawPos.y, this.size.x, this.size.y); graphics.fillStyle = "Gray"; for (var i = 0; i < this.listables.length; i++) { var listable = this.listables[i]; drawPos.y += 10; // hack var itemText = Control.getValueFromObjectAtBindingPath ( listable, this.bindingPath ); graphics.fillText ( itemText, drawPos.x, drawPos.y ) } } } function Coords(x, y) { this.x = x; this.y = y; } // instances function Coords_Instances() { if (Coords.Instances != null) { return Coords.Instances; } Coords.Instances = this; this.Ones = new Coords(1, 1); this.Twos = new Coords(2, 2); this.Zeroes = new Coords(0, 0); this.DirectionE = new Coords(1, 0); this.DirectionN = new Coords(0, -1); this.DirectionNE = new Coords(1, -1); this.DirectionNW = new Coords(-1, -1); this.DirectionS = new Coords(0, 1); this.DirectionSE = new Coords(1, 1); this.DirectionSW = new Coords(-1, 1); this.DirectionW = new Coords(-1, 0); this._DirectionsByHeading = [ this.DirectionE, this.DirectionSE, this.DirectionS, this.DirectionSW, this.DirectionW, this.DirectionNW, this.DirectionN, this.DirectionNE, ]; this.Temp = new Coords(0, 0); } new Coords_Instances(); { // constants Coords.NumberOfDimensions = 2; // instance methods Coords.prototype.absolute = function() { this.x = Math.abs(this.x); this.y = Math.abs(this.y); return this; } Coords.prototype.add = function(other) { this.x += other.x; this.y += other.y; return this; } Coords.prototype.clear = function() { this.x = 0; this.y = 0; return this; } Coords.prototype.clone = function() { var returnValue = new Coords(this.x, this.y); return returnValue; } Coords.prototype.dimension = function(dimensionIndex) { var returnValue; if (dimensionIndex == 0) { returnValue = this.x; } else { returnValue = this.y; } return returnValue; } Coords.prototype.dimension_Set = function(dimensionIndex, valueToSet) { if (dimensionIndex == 0) { this.x = valueToSet; } else { this.y = valueToSet; } return this; } Coords.prototype.dimensionIndexOfLargest = function(indexOfDimensionThatLosesTies) { return this.dimensionIndexOfSmallestOrLargest ( indexOfDimensionThatLosesTies, -1 ); } Coords.prototype.dimensionIndexOfSmallest = function(indexOfDimensionThatLosesTies) { return this.dimensionIndexOfSmallestOrLargest ( indexOfDimensionThatLosesTies, 1 ); } Coords.prototype.dimensionIndexOfSmallestOrLargest = function ( indexOfDimensionThatLosesTies, multiplier ) { var returnValue; var value = ( Math.abs(this.x) - Math.abs(this.y) ) * multiplier; if (value > 0) { returnValue = 1; } else if (value < 0) { returnValue = 0; } else if (indexOfDimensionThatLosesTies != null) { returnValue = indexOfDimensionThatLosesTies; } return returnValue; } Coords.prototype.directions = function() { if (this.x > 0) { this.x = 1; } else if (this.x < 0) { this.x = -1; } if (this.y > 0) { this.y = 1; } else if (this.y < 0) { this.y = -1; } return this; } Coords.prototype.divide = function(other) { this.x /= other.x; this.y /= other.y; return this; } Coords.prototype.divideScalar = function(scalar) { this.x /= scalar; this.y /= scalar; return this; } Coords.prototype.equals = function(other) { return (this.x == other.x && this.y == other.y); } Coords.prototype.floor = function() { this.x = Math.floor(this.x); this.y = Math.floor(this.y); return this; } Coords.prototype.invert = function(scalar) { this.x = 0 - this.x; this.y = 0 - this.y; return this; } Coords.prototype.isWithinRange = function(range) { var returnValue = ( this.x >= 0 && this.x <= range.x && this.y >= 0 && this.y <= range.y ); return returnValue; } Coords.prototype.magnitude = function() { var returnValue = Math.sqrt(this.x * this.x + this.y * this.y); return returnValue; } Coords.prototype.multiply = function(other) { this.x *= other.x; this.y *= other.y; return this; } Coords.prototype.multiplyScalar = function(scalar) { this.x *= scalar; this.y *= scalar; return this; } Coords.prototype.normalize = function() { var returnValue; var magnitude = this.magnitude(); if (magnitude == 0) { returnValue = this; } { returnValue = this.divideScalar(magnitude); } return returnValue; } Coords.prototype.overwriteWith = function(other) { this.x = other.x; this.y = other.y; return this; } Coords.prototype.overwriteWithDimensions = function(x, y) { this.x = x; this.y = y; return this; } Coords.prototype.random = function() { var randomizer = Globals.Instance.randomizer; this.x = Math.floor(this.x * randomizer.getNextRandom()); this.y = Math.floor(this.y * randomizer.getNextRandom()); return this; } Coords.prototype.round = function() { this.x = Math.round(this.x); this.y = Math.round(this.y); return this; } Coords.prototype.subtract = function(other) { this.x -= other.x; this.y -= other.y; return this; } Coords.prototype.sumOfXAndY = function() { return this.x + this.y; } Coords.prototype.toString = function() { return "(" + this.x + "," + this.y + ")"; } Coords.prototype.trimToRange = function(rangeToTrimTo) { if (this.x < 0) { this.x = 0; } else if (this.x > rangeToTrimTo.x) { this.x = rangeToTrimTo.x; } if (this.y < 0) { this.y = 0; } else if (this.y > rangeToTrimTo.y) { this.y = rangeToTrimTo.y; } return this; } } function DeviceData(numberOfCharges) { this.numberOfCharges = numberOfCharges; } { DeviceData.prototype.use = function(userEntity, deviceEntity, targetEntity) { if (this.numberOfCharges > 0) { this.numberOfCharges--; deviceEntity.defn().deviceDefn.use ( userEntity, deviceEntity, targetEntity ); } if (this.numberOfCharges <= 0) { var deviceDefn = deviceEntity.defn().deviceDefn; if (deviceDefn.consumedWhenAllChargesUsed == true) { userEntity.containerData.removeItem ( userEntity, deviceEntity ); } else { Font.spawnMessageFloater ( deviceEntity.defn().name, Message.getTextForName("NothingHappens"), userEntity.loc ); } } } } function DeviceDefn(chargesMax, consumedWhenAllChargesUsed, effectsToApply) { this.chargesMax = chargesMax; this.consumedWhenAllChargesUsed = consumedWhenAllChargesUsed; this.effectsToApply = effectsToApply; } { DeviceDefn.prototype.use = function(userEntity, deviceEntity, targetEntity) { for (var i = 0; i < this.effectsToApply.length; i++) { var effect = this.effectsToApply[i]; effect.applyToEntity(deviceEntity, targetEntity); } } } function DiceRoll(expression) { this.expression = expression; } { // static methods DiceRoll.roll = function(expression) { var diceRoll = DiceRoll.Instance; diceRoll.overwriteWithExpression(expression) var returnValue = diceRoll.roll(); return returnValue; } // instances DiceRoll.Instance = new DiceRoll("1"); // instance methods DiceRoll.prototype.overwriteWithExpression = function(expression) { this.expression = expression; return this; } DiceRoll.prototype.roll = function() { var expression = this.expression; var totalSoFar = 0; var terms = ( expression.indexOf("+") < 0 ? [expression] : expression.split("+") ); for (var t = 0; t < terms.length; t++) { var term = terms[t]; if (term.indexOf("d") < 0) { var valueConstant = parseInt(term); totalSoFar += valueConstant; } else { var tokens = term.split("d"); var numberOfDice = parseInt(tokens[0]); var sidesPerDie = parseInt(tokens[1]); for (var i = 0; i < numberOfDice; i++) { var valueRolledOnDie = 1 + Math.floor ( Globals.Instance.randomizer.getNextRandom() * sidesPerDie ); totalSoFar += valueRolledOnDie; } } } return totalSoFar; } } function DisplayHelper() {} { DisplayHelper.prototype.clear = function() { this.graphics.fillStyle = "Black"; this.graphics.fillRect ( 0, 0, this.viewSizeInPixels.x, this.viewSizeInPixels.y ); } DisplayHelper.prototype.drawControl = function(controlToDraw) { controlToDraw.drawToGraphics(this.graphics); } DisplayHelper.prototype.drawMap = function(map) { var cellPos = new Coords(0, 0); var drawPos = new Coords(0, 0); for (var y = 0; y < map.sizeInCells.y; y++) { cellPos.y = y; for (var x = 0; x < map.sizeInCells.x; x++) { cellPos.x = x; var cell = map.cellAtPos(cellPos); var cellTerrain = cell.terrain; var terrainImage = cellTerrain.image; drawPos.overwriteWith ( cellPos ).multiply ( map.cellSizeInPixels ); this.graphics.drawImage ( terrainImage.systemImage, drawPos.x, drawPos.y ); var entitiesInCell = cell.entitiesPresent; for (var i = 0; i < entitiesInCell.length; i++) { var entity = entitiesInCell[i]; var visual = entity.drawableData.visual; visual.drawToGraphicsAtPos ( this.graphics, drawPos ); } } } } DisplayHelper.prototype.drawVenue = function(venue) { var map = venue.map; this.drawMap(map); } DisplayHelper.prototype.initialize = function(viewSizeInPixels) { this.viewSizeInPixels = viewSizeInPixels; this.canvas = document.createElement("canvas"); this.canvas.width = this.viewSizeInPixels.x; this.canvas.height = this.viewSizeInPixels.y; this.graphics = this.canvas.getContext("2d"); document.body.appendChild(this.canvas); } } function DrawableData(isVisible) { this.isVisible = isVisible; } function DrawableDefn(visual, sizeInPixels, zIndex) { this.visual = visual; this.sizeInPixels = sizeInPixels; this.zIndex = zIndex; if (this.sizeInPixels == null) { this.sizeInPixels = Coords.Instances.Zeroes; } if (this.zIndex == null) { this.zIndex = 0; } this.sizeInPixelsHalf = this.sizeInPixels.clone().divideScalar(2); } function DynamicData(defn) { this.vel = defn.vel; this.accel = defn.accel; } function DynamicDefn(vel, accel) { this.vel = vel; this.accel = accel; } function Effect(defn) { this.defn = defn; } { Effect.prototype.applyToEntity = function(actingEntity, targetEntity) { this.defn.apply(actingEntity, targetEntity); } Effect.prototype.clone = function() { return new Effect(this.defn); } } function EffectDefn(name, apply) { this.name = name; this.apply = apply; } function EffectableData() { this.effects = []; } function Entity(name, defnName, pos, propertyValues) { this.name = name; this.defnName = defnName; this.loc = new Location ( null, // venueName pos ); if (propertyValues != null) { for (var i = 0; i < propertyValues.length; i++) { var propertyValue = propertyValues[i]; var propertyName = propertyValue.constructor.name; propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); this[propertyName] = propertyValue; } } } { Entity.EntityText = "Entity"; Entity.fromDefn = function(name, defn, pos, propertyValues) { var returnValue = new Entity(name, null, pos, propertyValues); returnValue._defn = defn; return returnValue; } Entity.prototype.defn = function() { var returnValue; if (this._defn == null) { returnValue = Globals.Instance.universe.defn.entityDefns[this.defnName]; } else { returnValue = this._defn; } return returnValue; } } function EntityDefn ( name, categoryNames, propertyValues ) { this.name = name; this.categoryNames = categoryNames; if (propertyValues != null) { for (var i = 0; i < propertyValues.length; i++) { var propertyValue = propertyValues[i]; var propertyName = propertyValue.constructor.name; propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); this[propertyName] = propertyValue; } } EntityDefnGroup.prototype.toXmlElement = function() { return new XmlElement ( this.constructor.name, // attributeNameValuePairs [ [ "name", this.name ], ], // children [ // todo ] ); } } function EntityDefnGroup(name, relativeFrequency, entityDefns) { this.name = name; this.relativeFrequency = relativeFrequency; this.entityDefns = entityDefns; } { EntityDefnGroup.prototype.toXmlElement = function() { return new XmlElement ( this.constructor.name, // attributeNameValuePairs [ [ "name", this.name ], [ "relativeFrequency", this.relativeFrequency ], ], // children [ new XmlElement("EntityDefns", [], XmlElement.buildManyFromXmlizables(this.entityDefns)), ] ); } } function EphemeralData(defn) { this.ticksToLive = defn.ticksToLive; } function EphemeralDefn(ticksToLive) { this.ticksToLive = ticksToLive; } function EquipmentSocket(defn, itemEquipped) { this.defn = defn; this.itemEquipped = itemEquipped; } { // control EquipmentSocket.prototype.controlUpdate = function(entity) { if (this.control == null) { this.control = new ControlContainer ( "containerEquipmentSocket", new Coords(0, 0), // pos new Coords(100, 100), // size [ new ControlLabel("labelName", new Coords(10, 10), this.defn.name), ] ); } return this.control; } } function EquipmentSocketSet(equipmentSocketDefnSet) { this.equipmentSocketDefnSet = equipmentSocketDefnSet; this.sockets = []; var socketDefns = equipmentSocketDefnSet.socketDefns; for (var i = 0; i < socketDefns.length; i++) { var socketDefn = socketDefns[i]; var socket = new EquipmentSocket(socketDefn, null); this.sockets.push(socket); } } function EquipmentSocketDefn(name, namesOfCategoriesAllowed) { this.name = name; this.namesOfCategoriesAllowed = namesOfCategoriesAllowed; } function EquipmentSocketDefnSet(name, socketDefns) { this.name = name; this.socketDefns = socketDefns; } function EquippableData(equippableDefn) { this.equipmentSocketSet = new EquipmentSocketSet ( equippableDefn.equipmentSocketDefnSet ); } { // control EquippableData.prototype.controlUpdate = function(entity) { if (this.control == null) { this.control = new ControlContainer ( "containerEquippableData", new Coords(0, 0), // pos new Coords(100, 100), // size [ new ControlLabel("labelEquipment", new Coords(10, 10), "Equipment:"), ] ); } return this.control; } } function EquippableDefn(equipmentSocketDefnSet) { this.equipmentSocketDefnSet = equipmentSocketDefnSet; } function FieldOfView() { // do nothing } { FieldOfView.prototype.setVenueAndRangeAndViewerPos = function ( venue, distanceFromEyeMax, eyePos ) { this.venue = venue; this.distanceFromEyeMax = distanceFromEyeMax; this.eyePos = eyePos; } FieldOfView.prototype.calculateCellPositionsVisible = function() { var numberOfCellPositionsMax = 4 * this.distanceFromEyeMax * this.distanceFromEyeMax; if ( this.cellPositionsVisible == null || this.cellPositionsVisible.length < numberOfCellPositionsMax ) { this.cellPositionsVisible = []; for (var i = 0; i < numberOfCellPositionsMax; i++) { this.cellPositionsVisible.push(new Coords(0, 0)); } } var tau = Constants.Tau; var eyePosCentered = this.eyePos.clone().add(new Coords(.5, .5)); var angleRangeSetNotYetBlocked = new RangeSet ([ new Range(0, 1) ]); var displacementFromEyeToCell = new Coords(0, 0); var directionsForSides = [ new Coords(-1, 1), new Coords(-1, -1), new Coords(1, -1), new Coords(1, 1), ]; var cornerAddendsForSides = [ new Coords(0, 0), new Coords(0, -1), new Coords(1, 0), new Coords(0, 1), ]; var cellPos = new Coords(0, 0); var cellPosRelative = new Coords(0, 0); var vertexPositionsRelative = [ new Coords(0, 0), new Coords(0, 0) ]; this.cellPositionsVisible[0] = this.eyePos.clone(); this.numberOfCellsVisible = 1; var map = this.venue.map; for (var r = 1; r <= this.distanceFromEyeMax; r++) { cellPosRelative.overwriteWithDimensions(r, 0); vertexPositionsRelative[0].overwriteWith(new Coords(r - .5, -.5)); vertexPositionsRelative[1].overwriteWith(new Coords(r - .5, .5)); for (var s = 0; s < directionsForSides.length; s++) { var direction = directionsForSides[s]; vertexPositionsRelative[1].add(cornerAddendsForSides[s]); for (var d = 0; d < r; d++) { cellPos.overwriteWith(this.eyePos).add(cellPosRelative); if (cellPos.isWithinRange(map.sizeInCellsMinusOnes) == true) { var cellSpan = new Range ( NumberHelper.atan3(vertexPositionsRelative[0]), NumberHelper.atan3(vertexPositionsRelative[1]) ); var cellSpanAsSet = new RangeSet( [ cellSpan ] ); cellSpanAsSet.splitRangesThatSpanPeriod(1); if (cellSpanAsSet.overlaps(angleRangeSetNotYetBlocked) == true) { var cellPosVisible = this.cellPositionsVisible [ this.numberOfCellsVisible ]; cellPosVisible.overwriteWith ( cellPos ); this.numberOfCellsVisible++; var cellAtPos = map.cellAtPos(cellPos); if (cellAtPos.terrain.blocksVision == true) { angleRangeSetNotYetBlocked.subtract ( cellSpanAsSet ); } else { var entitiesPresent = this.venue.map.cellAtPos ( cellPos ).entitiesPresent; for (var b = 0; b < entitiesPresent.length; b++) { var entityPresent = entitiesPresent[b]; if (entityPresent.defn().collidableDefn.blocksView == true) { angleRangeSetNotYetBlocked.subtract(cellSpanAsSet); } } } } } cellPosRelative.add(direction); vertexPositionsRelative[0].overwriteWith(vertexPositionsRelative[1]); vertexPositionsRelative[1].add(direction); } } } } } function Font(charactersAvailable, characterSize, characterImages) { this.charactersAvailable = charactersAvailable; this.characterSize = characterSize; this.characterImages = characterImages; } { Font.prototype.buildEntityDefnForText = function ( visualForIcon, text, isFloater ) { text = text.toUpperCase(); var visualsForCharacters = []; visualsForCharacters.push(visualForIcon); for (var i = 0; i < text.length; i++) { var character = text[i]; var characterIndex = this.charactersAvailable.indexOf ( character ); if (characterIndex >= 0) { var characterImage = this.characterImages [ characterIndex ]; var visualForCharacter = new VisualOffset ( characterImage, new Coords(i * this.characterSize.x, 0) ); visualsForCharacters.push ( visualForCharacter ); } } var entityDefnCategoryNames = [ "Drawable", ]; var entityDefnProperties = [ new DrawableDefn ( new VisualSet(text, visualsForCharacters), null, // sizeInPixels 2 // zIndex ), ] var ticksToLive = (isFloater == true ? 16 : null); if (ticksToLive != null) { entityDefnCategoryNames.push("Ephemeral"); entityDefnProperties.push(new EphemeralDefn(ticksToLive)); } var velocity = (isFloater == true ? new Coords(0, -.4) : null); if (velocity != null) { entityDefnCategoryNames.push("Dynamic"); entityDefnProperties.push ( new DynamicDefn(velocity, Coords.Instances.Zeroes) ); } var entityDefn = new EntityDefn ( "Message_" + text, entityDefnCategoryNames, entityDefnProperties ); return entityDefn; } Font.spawnMessage = function ( messageIconName, messageText, loc, isFloater ) { var universe = Globals.Instance.universe; var entityDefns = universe.defn.entityDefns; var messageIcon = ( messageIconName == null ? null : entityDefns[messageIconName].drawableDefn.visual ); var entityMessage = Entity.fromDefn ( messageText, Globals.Instance.font.buildEntityDefnForText ( messageIcon, messageText.toUpperCase(), isFloater ), loc.posInCells.clone() ); //entityMessage.drawableData.isVisible = true; universe.venueCurrent.entitiesToSpawn.push(entityMessage); } Font.spawnMessageFixed = function ( messageText, loc ) { Font.spawnMessage(null, messageText, loc, false); } Font.spawnMessageFloater = function ( messageIconName, messageText, loc ) { Font.spawnMessage(messageIconName, messageText, loc, true); } } function Globals() { this.htmlElementLibrary = new HTMLElementLibrary(); this.randomizer = new RandomizerLCG ( 1103515245, // multiplier 12345, // addend Math.pow(2.0, 31), // modulus 0.12345 // firstRandom ); this.sightHelper = new SightHelper(); } { Globals.prototype.initialize = function ( font, realWorldMillisecondsPerTick, viewSizeInPixels, universe ) { this.collisionHelper = new CollisionHelper(); this.font = font; this.inputHelper = new InputHelper(); this.inputHelper.initialize(); this.realWorldMillisecondsPerTick = realWorldMillisecondsPerTick; this.displayHelper = new DisplayHelper(); this.displayHelper.initialize(viewSizeInPixels); this.universe = universe; this.timer = setInterval ( Globals.Instance.processTick.bind(this), this.realWorldMillisecondsPerTick ); } Globals.prototype.processTick = function() { this.inputHelper.updateForTick(); this.universe.update(); } } { Globals.Instance = new Globals(); } function Heading() {} { // constants Heading.numberOfHeadings = 8; // static methods Heading.fromCoords = function(coordsToConvert) { var returnValue = Math.floor ( Math.atan2 ( coordsToConvert.y, coordsToConvert.x ) * Heading.numberOfHeadings / (2 * Math.PI) ); if (returnValue < 0) { returnValue += Heading.numberOfHeadings; } return returnValue; } } function HTMLElementLibrary() { this.idNext = 0; this.elements = []; } { HTMLElementLibrary.Instance = new HTMLElementLibrary(); HTMLElementLibrary.prototype.createElement = function(tagName) { var returnValue = document.createElement(tagName); returnValue.id = "_" + this.idNext; this.idNext++; this.elements[returnValue.id] = returnValue; return returnValue; } HTMLElementLibrary.prototype.getElementByID = function(idToGet) { return this.elements[idToGet]; } } function HTMLHelper() {} { HTMLHelper.Newline = "<br />"; HTMLHelper.HandleHideOrShowControlEvent = function(event) { HTMLHelper.HideOrShowControl(event.target); } HTMLHelper.HideOrShowControl = function(controlToHideOrShow) { var htmlElementToHideOrShow = controlToHideOrShow.elementToHideOrShow; if (controlToHideOrShow.isExpanded == false) { controlToHideOrShow.isExpanded = true; controlToHideOrShow.innerHTML = "-"; htmlElementToHideOrShow.style.display = ""; } else { controlToHideOrShow.isExpanded = false; htmlElementToHideOrShow.style.display = "none"; controlToHideOrShow.innerHTML = "+"; } } } function Image() {} { // static methods Image.buildFromFilePath = function(name, filePath) { var returnValue = new Image(); returnValue.name = name; returnValue.filePath = filePath; returnValue.systemImage = document.createElement("img"); returnValue.systemImage.src = filePath; return returnValue; } Image.buildFromSystemImage = function(name, systemImage, sizeInPixels) { var returnValue = new Image(); returnValue.name = name; returnValue.htmlElementID = systemImage.id; returnValue.filePath = systemImage.src; returnValue.sizeInPixels = sizeInPixels; returnValue.systemImage = systemImage; return returnValue; } // instance methods Image.prototype.clone = function() { var returnValue = new Image(); returnValue.name = name; returnValue.filePath = this.filePath; returnValue.sizeInPixels = this.sizeInPixels.clone(); returnValue.systemImage = this.systemImage; return returnValue; } Image.prototype.cloneAsVisual = function() { return this.clone(); } Image.prototype.drawToGraphicsAtPos = function(graphics, drawPos) { graphics.drawImage ( this.systemImage, drawPos.x, drawPos.y ); } Image.prototype.updateForVenue = function() { // do nothing } } function ImageHelper() {} { // static methods ImageHelper.buildImageFromStrings = function(name, stringsForPixels) { return ImageHelper.buildImageFromStringsScaled ( name, Coords.Instances.Ones, stringsForPixels ); } ImageHelper.buildImagesFromStringArrays = function(name, stringArraysForImagePixels) { var returnValue = []; for (var i = 0; i < stringArraysForImagePixels.length; i++) { var stringsForImagePixels = stringArraysForImagePixels[i]; var image = ImageHelper.buildImageFromStrings(name + i, stringsForImagePixels); returnValue.push(image); } return returnValue; } ImageHelper.buildImageFromStringsScaled = function(name, scaleFactor, stringsForPixels) { var sizeInPixels = new Coords ( stringsForPixels[0].length, stringsForPixels.length ); var htmlElementLibrary = Globals.Instance.htmlElementLibrary; var canvas = document.createElement("canvas"); canvas.width = sizeInPixels.x * scaleFactor.x; canvas.height = sizeInPixels.y * scaleFactor.y; var graphics = canvas.getContext("2d"); var pixelPos = new Coords(0, 0); var colorForPixel; for (var y = 0; y < sizeInPixels.y; y++) { var stringForPixelRow = stringsForPixels[y]; pixelPos.y = y * scaleFactor.y; for (var x = 0; x < sizeInPixels.x; x++) { var charForPixel = stringForPixelRow[x]; pixelPos.x = x * scaleFactor.x; colorForPixel = Color.getBySymbol(charForPixel); graphics.fillStyle = colorForPixel.systemColor; graphics.fillRect ( pixelPos.x, pixelPos.y, scaleFactor.x, scaleFactor.y ); } } var imageFromCanvasURL = canvas.toDataURL("image/png"); var htmlImageFromCanvas = htmlElementLibrary.createElement("img"); htmlImageFromCanvas.width = canvas.width; htmlImageFromCanvas.height = canvas.height; htmlImageFromCanvas.src = imageFromCanvasURL; var returnValue = Image.buildFromSystemImage ( name, htmlImageFromCanvas, sizeInPixels ); return returnValue; } ImageHelper.copyRegionFromImage = function(imageToCopyFrom, regionPos, regionSize) { var canvas = document.createElement("canvas"); canvas.id = "region_" + regionPos.x + "_" + regionPos.y; canvas.width = regionSize.x; canvas.height = regionSize.y; canvas.style.position = "absolute"; var graphics = canvas.getContext("2d"); graphics.drawImage ( imageToCopyFrom.htmlElement, regionPos.x, regionPos.y, // source pos regionSize.x, regionSize.y, // source size 0, 0, // destination pos regionSize.x, regionSize.y // destination size ); var imageFromCanvasURL = canvas.toDataURL("image/png"); var htmlImageFromCanvas = document.createElement("img"); htmlImageFromCanvas.width = canvas.width; htmlImageFromCanvas.height = canvas.height; htmlImageFromCanvas.style.position = "absolute"; htmlImageFromCanvas.src = imageFromCanvasURL; var returnValue = Image.buildFromSystemImage ( imageToCopyFrom.name, htmlImageFromCanvas, regionSize ); return returnValue; } ImageHelper.sliceImageIntoTiles = function(imageToSlice, sizeInTiles) { var returnImages = []; var htmlElementLibrary = Globals.Instance.htmlElementLibrary; var systemImageToSlice = htmlElementLibrary.getElementByID ( imageToSlice.htmlElementID ); var imageToSliceSize = imageToSlice.sizeInPixels; var tileSize = imageToSliceSize.clone().divide(sizeInTiles); var tilePos = new Coords(0, 0); var sourcePos = new Coords(0, 0); for (var y = 0; y < sizeInTiles.y; y++) { tilePos.y = y; var returnImageRow = []; for (var x = 0; x < sizeInTiles.x; x++) { tilePos.x = x; var canvas = document.createElement("canvas"); canvas.id = "tile_" + x + "_" + y; canvas.width = tileSize.x; canvas.height = tileSize.y; canvas.style.position = "absolute"; var graphics = canvas.getContext("2d"); sourcePos.overwriteWith(tilePos).multiply(tileSize); graphics.drawImage ( systemImageToSlice, sourcePos.x, sourcePos.y, // source pos tileSize.x, tileSize.y, // source size 0, 0, // destination pos tileSize.x, tileSize.y // destination size ); // browser dependent? var imageFromCanvasURL = canvas.toDataURL("image/png"); var htmlImageFromCanvas = htmlElementLibrary.createElement("img"); htmlImageFromCanvas.width = canvas.width; htmlImageFromCanvas.height = canvas.height; htmlImageFromCanvas.style.position = "absolute"; htmlImageFromCanvas.src = imageFromCanvasURL; imageFromCanvas = Image.buildFromSystemImage ( imageToSlice.name + tilePos.toString(), htmlImageFromCanvas, tileSize ); returnImageRow.push(imageFromCanvas); } returnImages.push(returnImageRow); } return returnImages; } } function InputBinding(key, actionName) { this.key = key; this.actionName = actionName; } { InputBinding.prototype.action = function() { return Globals.Instance.universe.defn.actions[this.actionName]; } } function InputHelper() { this.mousePos = new Coords(0, 0); this.bindings = []; this.keyCodeToBindingLookup = []; this.actionsBeingPerformed = []; } { // instance methods InputHelper.prototype.initialize = function() { document.body.onkeydown = this.processKeyDownEvent.bind(this); document.body.onkeyup = this.processKeyUpEvent.bind(this); document.body.onmousedown = this.processMouseDownEvent.bind(this); } InputHelper.prototype.bindingsRegister = function(bindingsToRegister) { this.bindings = new Array(); this.keyCodeToBindingLookup = new Array(); var numberOfBindings = bindingsToRegister.length; for (var b = 0; b < numberOfBindings; b++) { var binding = bindingsToRegister[b]; this.bindings.push(binding); this.keyCodeToBindingLookup[binding.key.systemKeyCode] = binding; } } InputHelper.prototype.updateForTick = function() { var inputHelper = Globals.Instance.inputHelper; var actionsBeingPerformed = inputHelper.actionsBeingPerformed; var actionsToEnd = []; for (var i = 0; i < actionsBeingPerformed.length; i++) { var actionBeingPerformed = actionsBeingPerformed[i]; actionBeingPerformed.ticksSoFar++; } } // event handlers InputHelper.prototype.processKeyDownEvent = function(event) { var keycode = "_" + event.which; var binding = this.keyCodeToBindingLookup[keycode]; if (binding != null) { var action = binding.action(); var actionsBeingPerformed = this.actionsBeingPerformed; if (actionsBeingPerformed[action.name] == null) { action.ticksSoFar = 0; actionsBeingPerformed[action.name] = action; actionsBeingPerformed.push(action); } } } InputHelper.prototype.processKeyUpEvent = function(event) { var binding = this.keyCodeToBindingLookup["_" + event.which]; if (binding != null) { var action = binding.action(); var actionsBeingPerformed = this.actionsBeingPerformed; if (actionsBeingPerformed[action.name] != null) { delete actionsBeingPerformed[action.name]; var indexToDeleteAt = actionsBeingPerformed.indexOf ( action ); actionsBeingPerformed.splice(indexToDeleteAt, 1); } } } InputHelper.prototype.processMouseDownEvent = function(event) { this.mousePos.overwriteWithDimensions(event.x, event.y); var keycode = "Mouse"; var binding = this.keyCodeToBindingLookup[keycode]; if (binding != null) { var action = binding.action(); var actionsBeingPerformed = this.actionsBeingPerformed; if (actionsBeingPerformed[action.name] == null) { action.ticksSoFar = 0; actionsBeingPerformed[action.name] = action; actionsBeingPerformed.push(action); } } } } function InputKey(name, systemKeyCode) { this.name = name; this.systemKeyCode = systemKeyCode; } { function InputKey_Instances() { if (InputKey.Instances != null) { return; } InputKey.Instances = this; this._All = [ new InputKey("A", "_65"), new InputKey("B", "_66"), new InputKey("C", "_67"), new InputKey("D", "_68"), new InputKey("E", "_69"), new InputKey("F", "_70"), new InputKey("G", "_71"), new InputKey("H", "_72"), new InputKey("I", "_73"), new InputKey("J", "_74"), new InputKey("K", "_75"), new InputKey("K", "_76"), new InputKey("M", "_77"), new InputKey("N", "_78"), new InputKey("O", "_79"), new InputKey("P", "_80"), new InputKey("Q", "_81"), new InputKey("R", "_82"), new InputKey("S", "_83"), new InputKey("T", "_84"), new InputKey("U", "_85"), new InputKey("V", "_86"), new InputKey("W", "_87"), new InputKey("X", "_88"), new InputKey("Y", "_89"), new InputKey("Z", "_90"), new InputKey("BracketClose", "_221"), new InputKey("BracketOpen", "_219"), new InputKey("Period", "_190"), ]; this.systemKeyCodeToKeyLookup = []; for (var i = 0; i < this._All.length; i++) { var key = this._All[i]; this[key.name] = key; this.systemKeyCodeToKeyLookup[key.systemKeyCode] = key; } } new InputKey_Instances(); } function ItemData() { // todo } {} function ItemDefn(appearance, mass, stackSizeMax, relativeFrequency, initialize, use) { this.appearance = appearance; this.mass = mass; this.stackSizeMax = stackSizeMax; this.relativeFrequency = relativeFrequency; this.initialize = initialize; this.use = use; if (this.initialize == null) { this.initialize = ItemDefn.InitializeDoNothing; } if (this.use == null) { this.use = ItemDefn.UseDoNothing; } } { ItemDefn.InitializeDevice = function(entity, item) { alert("[UseDevice]"); } ItemDefn.InitializeDoNothing = function() { // do nothing } ItemDefn.UseDevice = function(userEntity, deviceEntity, targetEntity) { deviceEntity.deviceData.use(userEntity, deviceEntity, targetEntity); } ItemDefn.UseDoNothing = function() { // do nothing } ItemDefn.UseEquip = function(entity, item) { var itemCategoryNames = item.defn().categoryNames; var equippableData = entity.equippableData; var socketSet = equippableData.equipmentSocketSet; var sockets = socketSet.sockets; for (var d = 0; d < itemCategoryNames.length; d++) { var itemCategoryName = itemCategoryNames[d]; for (var i = 0; i < sockets.length; i++) { var socket = sockets[i]; var namesOfCategoriesAllowed = socket.defn.namesOfCategoriesAllowed; for (var c = 0; c < namesOfCategoriesAllowed.length; c++) { var nameOfCategoryAllowed = namesOfCategoriesAllowed[c]; if (itemCategoryName == nameOfCategoryAllowed) { socket.itemEquipped = item; entity.moverData.controlUpdate(entity); return; } } } } } } function KillableData(defn) { this.defn = defn; this.integrity = this.defn.integrityMax; } { KillableData.prototype.integrityAdd = function(amountToAdd) { this.integrity = NumberHelper.trimValueToRangeMax ( this.integrity + amountToAdd, 0, this.defn.integrityMax ); } } function KillableDefn(integrityMax) { this.integrityMax = integrityMax; } function Location(venueName, posInCells) { this.venueName = venueName; this.posInCells = posInCells; this.heading = 0; } { Location.prototype.overwriteWith = function(other) { this.venueName = other.venueName; this.posInCells = other.posInCells.clone(); this.heading = other.heading; } Location.prototype.venue = function() { return Globals.Instance.universe.venues[this.venueName]; } } function Map(name, terrains, cellSizeInPixels, cellsAsStrings) { this.name = name; this.terrains = terrains; this.cellSizeInPixels = cellSizeInPixels; this.sizeInCells = new Coords ( cellsAsStrings[0].length, cellsAsStrings.length ); this.sizeInCellsMinusOnes = this.sizeInCells.clone().subtract ( new Coords(1, 1) ); this.sizeInPixels = this.sizeInCells.clone().multiply(this.cellSizeInPixels); this.cellIndicesModified = []; this.cells = []; var cellPos = new Coords(0, 0); for (var y = 0; y < this.sizeInCells.y; y++) { cellPos.y = y; for (var x = 0; x < this.sizeInCells.x; x++) { cellPos.x = x; var cellAsChar = cellsAsStrings[cellPos.y][cellPos.x]; var cellTerrain = this.terrains[cellAsChar]; var cell = new MapCell(cellTerrain); this.cells.push(cell); } } } { // static methods Map.buildBlank = function(name, terrains, cellSizeInPixels, sizeInCells) { var cellsAsStrings = []; var terrainBlank = terrains[0]; // hack for (var y = 0; y < sizeInCells.y; y++) { var cellRowAsString = ""; for (var x = 0; x < sizeInCells.x; x++) { cellRowAsString += terrainBlank.codeChar; } cellsAsStrings.push(cellRowAsString); } var returnValue = new Map ( name, terrains, cellSizeInPixels, cellsAsStrings ); return returnValue; } // instance methods Map.prototype.buildCellPosFromIndex = function(cellIndex) { return new Coords ( cellIndex % this.sizeInCells.x, Math.floor(cellIndex / this.sizeInCells.x) ); } Map.prototype.cellAtPos = function(cellPos) { var returnValue = null; if (cellPos.isWithinRange(this.sizeInCellsMinusOnes) == true) { var cellIndex = this.indexOfCellAtPos(cellPos); returnValue = this.cells[cellIndex]; } return returnValue; } Map.prototype.cellAtPos_Set = function(cellPos, cellToSet) { var cellIndex = this.indexOfCellAtPos(cellPos); this.cells[cellIndex] = cellToSet; this.cellIndicesModified.push(cellIndex); } Map.prototype.clone = function() { var cellsAsStrings = []; var cellPos = new Coords(0, 0); for (var y = 0; y < map.sizeInCells.y; y++) { cellPos.y = y; var cellRowAsString = ""; for (var x = 0; x < map.sizeInCells.x; x++) { cellPos.x = x; var cell = this.cellAtPos(cellPos); var cellTerrain = this.terrains[cellAsChar]; var terrainChar = terrain.codeChar; cellRowAsString += terrainChar; } cellsAsStrings.push(cellRowAsString); } return new Map ( this.name, this.terrains, this.cellSizeInPixels, cellsAsStrings ); } Map.prototype.copyNCellsAtPositionsToOther = function ( numberOfCellsToCopy, cellPositionsToCopy, other ) { for (var i = 0; i < numberOfCellsToCopy; i++) { var cellPos = cellPositionsToCopy[i]; var cell = this.cellAtPos(cellPos); if (cell != null) { other.cellAtPos_Set(cellPos, cell); } } } Map.prototype.indexOfCellAtPos = function(cellPos) { return cellPos.y * this.sizeInCells.x + cellPos.x } } function MapCell(terrain) { this.terrain = terrain; this.entitiesPresent = []; } function MapTerrain(name, codeChar, costToTraverse, blocksVision, color, image) { this.name = name; this.codeChar = codeChar; this.costToTraverse = costToTraverse; this.blocksVision = blocksVision; this.color = color; this.image = image; } function MediaLoader ( objectContainingCallback, callbackToRunWhenLoadingComplete, items ) { this.objectContainingCallback = objectContainingCallback; this.callbackToRunWhenLoadingComplete = callbackToRunWhenLoadingComplete; this.items = items; this.items.addLookups("name"); } { MediaLoader.prototype.itemLoaded = function(event) { this.numberOfItemsLoadedSoFar++; if (this.numberOfItemsLoadedSoFar >= this.items.length) { this.callbackToRunWhenLoadingComplete.call ( this.objectContainingCallback, this ); } } MediaLoader.prototype.loadItemsAll = function() { this.numberOfItemsLoadedSoFar = 0; for (var i = 0; i < this.items.length; i++) { var item = this.items[i]; item.load(this, item); } } } function MediaLoaderItem(name, itemType, path) { this.name = name; this.itemType = itemType; this.path = path; } { MediaLoaderItem.prototype.load = function(mediaLoader) { this.itemType.load(mediaLoader, this); } } function MediaLoaderItemType(name, load) { this.name = name; this.load = load; } { function MediaLoaderItemType_Instances() { this.Image = new MediaLoaderItemType ( "Image", function(mediaLoader, mediaLoaderItem) { var htmlElementLibrary = Globals.Instance.htmlElementLibrary; var htmlElement = htmlElementLibrary.createElement("img"); mediaLoaderItem.htmlElement = htmlElement; htmlElement.mediaLoaderItem = mediaLoaderItem; htmlElement.onload = mediaLoader.itemLoaded.bind(mediaLoader); htmlElement.setAttribute("crossOrigin", "anonymous"); htmlElement.src = mediaLoaderItem.path; } ); } MediaLoaderItemType.Instances = new MediaLoaderItemType_Instances(); } function Message(name, textsForLanguages) { this.name = name; this.textsForLanguages = textsForLanguages; } { Message.getTextForName = function(messageName) { return Message.Instances._All[messageName].textsForLanguages[0]; } // instances function Message_Instances() { this._All = [ new Message("NothingHappens", [ "Nothing happens." ]) ]; this._All.addLookups("name"); } Message.Instances = new Message_Instances(); } function MoverData(moverDefn) { this.movesThisTurn = moverDefn.movesPerTurn; this.demographics = moverDefn.demographics; this.locus = new MoverData_Locus(); this.traits = moverDefn.traits; this.skills = moverDefn.skills; this.spells = moverDefn.spells; this.vitals = new MoverData_Vitals(moverDefn.vitals); this.attributes = moverDefn.attributes; } { // controls MoverData.prototype.controlUpdate = function(entity) { if (this.control == null) { this.control = new ControlContainer ( "containerMoverData", new Coords(0, 0), // pos new Coords(220, 240), // size [ new ControlLabel("labelName", new Coords(10, 16), "Name: " + entity.name), this.demographics.controlUpdate(entity, new Coords(10, 32)), this.traits.controlUpdate(entity, new Coords(10, 48)), this.vitals.controlUpdate(entity, new Coords(10, 64)), this.locus.controlUpdate(entity, new Coords(10, 80)), this.skills.controlUpdate(entity, new Coords(10, 96)), this.spells.controlUpdate(entity, new Coords(10, 112)), entity.containerData.controlUpdate(entity, new Coords(10, 128)), ] ); } return this.control; } } function MoverData_Demographics(species, role, rank) { this.species = species; this.role = role; this.rank = rank; } { // controls MoverData_Demographics.prototype.controlUpdate = function(entity, pos) { if (this.control == null) { this.control = new ControlContainer ( "containerMoverData_Demographics", pos, new Coords(200, 16), // size [ new ControlLabel ( "labelDemographics", new Coords(10, 10), "Level " + this.rank + " " + this.species + " " + this.role ), ] ); } return this.control; } } function MoverData_Locus() { } { // controls MoverData_Locus.prototype.controlUpdate = function(entity, pos) { if (this.control == null) { this.control = new ControlContainer ( "containerMoverData_Locus", pos, new Coords(200, 16), // size [ new ControlLabel ( "labelLocus", new Coords(10, 10), "Floor: ^ Turn: ^", [ entity.loc.venue().depth, Globals.Instance.universe ], [ null, "turnsSoFar" ] ), ] ); } return this.control; } } function MoverData_Skills(skillDefns) { this.skills = []; for (var i = 0; i < skillDefns.length; i++) { var skillDefn = skillDefns[i]; var skill = new Skill(skillDefn, 0); this.skills.push(skill); } } { MoverData_Skills.prototype.controlUpdate = function(entity, pos) { if (this.control == null) { this.control = new ControlContainer ( "containerMoverData_Skills", pos, new Coords(200, 16), // size [ new ControlLabel("labelSkills", new Coords(10, 10), "Skills"), ] ); } return this.control; } } function MoverData_Spells(spells) { this.spells = spells; } { MoverData_Spells.prototype.controlUpdate = function(entity, pos) { if (this.control == null) { this.control = new ControlContainer ( "containerMoverData_Spells", pos, new Coords(200, 16), // size [ new ControlLabel("labelSpells", new Coords(10, 10), "Spells"), ] ); } return this.control; } } function MoverData_Traits(traits) { this.traits = traits; } { MoverData_Traits.prototype.controlUpdate = function(entity, pos) { if (this.control == null) { var textForTraits = ""; for (var i = 0; i < this.traits.length; i++) { var trait = this.traits[i]; textForTraits += trait.defn.abbreviation + ": " + trait.rank + " "; } this.control = new ControlContainer ( "containerMoverData_Traits", pos, new Coords(200, 16), // size [ new ControlLabel("labelTraits", new Coords(10, 10), textForTraits), ] ); } return this.control; } } function MoverData_Vitals(defn) { this.defn = defn; this.energy = defn.energyMax; this.satiety = defn.satietyMax; } { MoverData_Vitals.prototype.addSatietyToMover = function(amountToAdd, moverEntity) { this.satiety += amountToAdd; if (this.satiety <= 0) { moverEntity.killableData.integrity = 0; } else if (this.satiety >= moverEntity.defn().moverDefn.vitals.satietyMax) { // todo } this.controlUpdate(moverEntity); } // controls MoverData_Vitals.prototype.controlUpdate = function(entity, pos) { if (this.control == null && pos != null) // hack { this.control = new ControlContainer ( "containerMoverData_Vitals", pos, new Coords(200, 16), // size [ new ControlLabel ( "labelHealth", new Coords(10, 10), "Life:^/^", [ entity.killableData, entity.killableData.defn ], [ "integrity", "integrityMax" ] ), new ControlLabel ( "labelEnergy", new Coords(60, 10), " Power:" + this.energy + "/" + this.defn.energyMax ), new ControlLabel ( "labelSatiety", new Coords(120, 10), " Sat: " + this.satiety + "/" + this.defn.satietyMax ), ] ); } return this.control; } } function MoverDefn ( difficulty, movesPerTurn, demographics, traits, skills, spells, vitals, entityDefnCorpse, attributeGroups ) { this.difficulty = difficulty; this.movesPerTurn = movesPerTurn; this.demographics = demographics; this.traits = traits; this.skills = skills; this.spells = spells; this.vitals = vitals; this.entityDefnCorpse = entityDefnCorpse; this.attributeGroups = attributeGroups; this.attributeGroups.addLookups("name"); } function MoverDefn_Vitals(energyMax, satietyMax) { this.energyMax = energyMax; this.satietyMax = satietyMax; } function MoverGenerator() { // do nothing } { MoverGenerator.EntityDefn = new EntityDefn ( "MoverGenerator", [ "Actor" ], // categoryNames // properties [ new ActorDefn("Generate Movers"), ] ); } function NumberHelper() {} { NumberHelper.atan3 = function(coordsToFind) { var returnValue = Math.atan2(coordsToFind.y, coordsToFind.x); if (returnValue < 0) { returnValue += Constants.Tau; } returnValue /= Constants.Tau; return returnValue; } NumberHelper.trimValueToRangeMax = function(valueToTrim, rangeMin, rangeMax) { if (valueToTrim > rangeMax) { valueToTrim = rangeMax; } return valueToTrim; } NumberHelper.wrapValueToRangeMax = function(valueToWrap, rangeMax) { while (valueToWrap < 0) { valueToWrap += rangeMax; } while (valueToWrap >= rangeMax) { valueToWrap -= rangeMax; } return valueToWrap; } } function Path(map, startPos, goalPos) { this.map = map; this.startPos = startPos; this.goalPos = goalPos; } { Path.prototype.calculate = function() { var map = this.map; var startPos = this.startPos.clone(); var goalPos = this.goalPos.clone(); var openList = []; var openLookup = []; var closedLookup = []; var tempPos = Coords.Instances.Temp; var startNode = new PathNode ( startPos, 0, tempPos.overwriteWith ( goalPos ).subtract ( startPos ).absolute().sumOfXAndY(), null ); openList.push(startNode); var startIndex = "_" + ( startNode.cellPos.y * map.sizeInCells.x + startNode.cellPos.x ); openLookup[startIndex] = startNode; while (openList.length > 0) { var current = openList[0]; if (current.cellPos.equals(goalPos) == true) { this.nodes = new Array(); while (current != null) { this.nodes.splice(0, 0, current); current = current.prev; } break; } openList.splice(0, 1); var currentIndex = "_" + ( current.cellPos.y * map.sizeInCells.x + current.cellPos.x ); delete openLookup[currentIndex]; closedLookup[currentIndex] = current; var neighbors = this.getNeighborsForNode(map, current, goalPos); for (var n = 0; n < neighbors.length; n++) { var neighbor = neighbors[n]; var neighborPos = neighbor.cellPos; var neighborIndex = "_" + ( neighborPos.y * map.sizeInCells.x + neighborPos.x ); if (closedLookup[neighborIndex] == null && openLookup[neighborIndex] == null) { var i; for (i = 0; i < openList.length; i++) { var nodeFromOpenList = openList[i]; if (neighbor.costFromStart < nodeFromOpenList.costFromStart) { break; } } openList.splice(i, 0, neighbor); openLookup[neighborIndex] = neighbor; } } } } Path.prototype.getNeighborsForNode = function(map, node, goalPos) { var returnValues = []; var originalPos = node.cellPos; var neighborPos = originalPos.clone(); var neighborPositions = []; var mapSizeInCellsMinusOnes = map.sizeInCellsMinusOnes; var directions = Coords.Instances._DirectionsByHeading; for (var i = 0; i < directions.length; i++) { var direction = directions[i]; neighborPos.overwriteWith(originalPos).add(direction); if (neighborPos.isWithinRange(mapSizeInCellsMinusOnes) == true) { neighborPositions.push(neighborPos.clone()); } } var tempPos = Coords.Instances.Temp; for (var i = 0; i < neighborPositions.length; i++) { var neighborPos = neighborPositions[i]; var costToTraverse = map.cellAtPos ( neighborPos ).terrain.costToTraverse; costToTraverse *= tempPos.overwriteWith ( neighborPos ).subtract ( originalPos ).magnitude(); var neighborNode = new PathNode ( neighborPos, node.costFromStart + costToTraverse, costToTraverse + tempPos.overwriteWith ( goalPos ).subtract ( neighborPos ).absolute().sumOfXAndY(), node ); returnValues.push(neighborNode); } return returnValues; } } function PathNode(cellPos, costFromStart, costToGoalEstimated, prev) { this.cellPos = cellPos; this.costFromStart = costFromStart; this.costToGoalEstimated = costToGoalEstimated; this.prev = prev; } function PlayerData() { this.venueKnownLookup = []; } function PortalData(destinationVenueName, destinationEntityName) { this.destinationVenueName = destinationVenueName; this.destinationEntityName = destinationEntityName; } function RandomizerLCG(multiplier, addend, modulus, firstRandom) { // "LCG" = "Linear Congruential Generator" this.multiplier = multiplier; this.addend = addend; this.modulus = modulus; this.currentRandom = firstRandom; } { RandomizerLCG.prototype.getNextRandom = function() { this.currentRandom = ( ( this.multiplier * (this.currentRandom * this.modulus) + this.addend ) % this.modulus ) / this.modulus; return this.currentRandom; } } function Range(min, max) { this.min = min; this.max = max; } { Range.prototype.clone = function() { return new Range(this.min, this.max); } Range.prototype.overlaps = function(other) { var returnValue = ( this.min < other.max && this.max > other.min ); return returnValue; } Range.prototype.random = function() { return this.min + (this.max - this.min) * Globals.Instance.randomizer.getNextRandom(); } } function RangeSet(ranges) { this.ranges = ranges; } { RangeSet.prototype.overlaps = function(other) { var returnValue = false; for (var i = 0; i < this.ranges.length; i++) { var rangeThis = this.ranges[i]; for (var j = 0; j < other.ranges.length; j++) { var rangeOther = other.ranges[j]; if (rangeThis.overlaps(rangeOther) == true) { returnValue = true; i = this.ranges.length; break; } } } return returnValue; } RangeSet.prototype.splitRangesThatSpanPeriod = function(period) { for (var i = 0; i < this.ranges.length; i++) { var range = this.ranges[i]; if (range.min > range.max) { var rangePart0 = new Range(0, range.max); var rangePart1 = new Range(range.min, period); this.ranges.splice(i, 1, rangePart0, rangePart1); i++; } } } RangeSet.prototype.subtract = function(other) { for (var i = 0; i < this.ranges.length; i++) { var rangeThis = this.ranges[i]; for (var j = 0; j < other.ranges.length; j++) { var rangeOther = other.ranges[j]; if (rangeThis.overlaps(rangeOther) == true) { if (rangeOther.min > rangeThis.min) { if (rangeOther.max < rangeThis.max) { var rangeNew = new Range ( rangeOther.max, rangeThis.max ); this.ranges.splice ( i + 1, 0, rangeNew ); i++; } if (rangeThis.min < rangeOther.min) { rangeThis.max = rangeOther.min; } else { this.ranges.splice(i, 1); i--; } } else if (rangeOther.max < rangeThis.max) { rangeThis.min = rangeOther.max; } else { this.ranges.splice(i, 1); i--; } } } } } } function Role(name, ranks, skills) { this.name = name; this.ranks = ranks; this.skills = skills; } function Role_Rank(skillPoints, attributes) { this.skillPoints = skillPoints; this.attributes = attributes; } function Role_Skill(defn, rankMax) { this.defn = defn; this.rankMax = rankMax; } function RoomData(pos, size) { this.bounds = new Bounds(pos, size); this.roomsConnected = []; } function SightHelper() { this.fieldOfView = new FieldOfView(); } { SightHelper.prototype.updateVenueFromCompleteForViewerPosAndRange = function ( venueKnown, venueComplete, viewerPos, sightRange ) { var fieldOfView = this.fieldOfView; fieldOfView.setVenueAndRangeAndViewerPos ( venueComplete, sightRange, viewerPos ); fieldOfView.calculateCellPositionsVisible(); venueComplete.map.copyNCellsAtPositionsToOther ( fieldOfView.numberOfCellsVisible, fieldOfView.cellPositionsVisible, mapKnown ); } } function Skill(defn, rank) { this.defn = defn; this.rank = rank; } function SkillDefn(name) { this.name = name; } function SpellDefn(name) { this.name = name; } function StringHelper() {} function StringHelper_Static() { StringHelper.toStringNullable = function(objectToConvertToString) { if (objectToConvertToString == null) { objectToConvertToString = "null"; } return objectToConvertToString.toString(); } } StringHelper_Static(); function Trait(defn, rank) { this.defn = defn; this.rank = rank; } function TraitDefn(name) { this.name = name; this.abbreviation = this.name.substr(0, 3); } function Universe(name, defn, venues, entityForPlayer) { this.name = name; this.defn = defn; this.venues = venues; this.entityForPlayer = entityForPlayer; this.venues.addLookups("name"); if (this.entityForPlayer == null) { var venue0 = this.venues[0]; var portal0 = venue0.entitiesToSpawn[0]; // hack this.entityForPlayer = new Entity ( "Player", this.defn.entityDefns["Player"].name, portal0.loc.posInCells.clone() ); this.entityForPlayer.loc.venueName = venue0.name; venue0.entitiesToSpawn.splice(0, 0, this.entityForPlayer); } this.venueNext = this.venues[this.entityForPlayer.loc.venueName]; this.turnsSoFar = 0; } { Universe.prototype.update = function() { if (this.venueNext != null) { this.venueNext.initialize(); Globals.Instance.inputHelper.bindingsRegister ( this.venueNext.defn.inputBindings ); this.venueCurrent = this.venueNext; this.venueNext = null; } this.venueCurrent.update(); } // xml Universe.prototype.toXmlElement = function() { return new XmlElement ( this.constructor.name, // attributeNameValuePairs [ [ "name", this.name ], ], // children [ this.defn.toXmlElement() ] ); } } function UniverseDefn ( name, actions, activityDefns, categories, entityDefnGroups, venueDefns, venueStructure, buildVenues ) { this.name = name; this.actions = actions; this.activityDefns = activityDefns; this.categories = categories; this.entityDefnGroups = entityDefnGroups; this.venueDefns = venueDefns; this.venueStructure = venueStructure; this.buildVenues = buildVenues; var entityDefnSets = this.entityDefnGroups.getPropertyWithNameFromEachItem ( "entityDefns" ); this.entityDefns = ArrayHelper.concatenateArrays ( entityDefnSets ); this.actions.addLookups("name"); this.activityDefns.addLookups("name"); this.venueDefns.addLookups("name"); this.entityDefnGroups.addLookups("name"); this.entityDefns.addLookups("name"); } { // xml UniverseDefn.prototype.toXmlElement = function() { return new XmlElement ( this.constructor.name, // attributeNameValuePairs [ [ "name", this.name ], ], // children [ new XmlElement("VenueDefns", [], XmlElement.buildManyFromXmlizables(this.venueDefns)), new XmlElement("EntityDefnGroups", [], XmlElement.buildManyFromXmlizables(this.entityDefnGroups)), ] ); } } function UniverseDefnVenueStructure(branchRoot) { this.branchRoot = branchRoot; } function UniverseDefnVenueStructureBranch ( name, venueDefnName, startsAfterSibling, startOffsetRangeWithinParent, depthRangeInVenues, children ) { this.name = name; this.venueDefnName = venueDefnName; this.startsAfterSibling = startsAfterSibling; this.startOffsetRangeWithinParent = startOffsetRangeWithinParent; this.depthRangeInVenues = depthRangeInVenues; this.children = children; this.venues = []; for (var i = 0; i < this.children.length; i++) { this.children[i].parent = this; } } { UniverseDefnVenueStructureBranch.prototype.buildVenuesAndAddToList = function ( universeDefn, venuesSoFar, venueDepth ) { var venueDefns = universeDefn.venueDefns; var entityDefns = universeDefn.entityDefns; var venueDefn = venueDefns[this.venueDefnName]; var numberOfVenuesInBranch = Math.floor(this.depthRangeInVenues.random()); var indexOfFirstVenueInBranch = venuesSoFar.length; for (var i = 0; i < numberOfVenuesInBranch; i++) { venueDepth++; var venue = venueDefn.venueGenerate ( universeDefn, // universeDefn venueDefn, venuesSoFar.length, // venueIndex venueDepth ); this.venues.push(venue); venuesSoFar.push(venue); } var venueFirstInBranch = venuesSoFar[indexOfFirstVenueInBranch]; if (this.parent != null && this.parent.venues.length > 0) { var venueIndexToBranchFrom = Math.floor(this.startOffsetRangeWithinParent.random()); var venueToBranchFrom = this.parent.venues[venueIndexToBranchFrom]; var entityPortalToParentBranch = new Entity ( "StairsUp", universeDefn.entityDefns["StairsUp"].name, venueFirstInBranch.map.sizeInCells.clone().subtract ( Coords.Instances.Ones ).random(), // propertyValues [ new PortalData ( venueToBranchFrom.name, "StairsDown" // portalName ), ] ); venue.entitiesToSpawn.push(entityPortalToParentBranch); } for (var i = 0; i < this.children.length; i++) { var child = this.children[i]; child.buildVenuesAndAddToList(universeDefn, venuesSoFar, 0); } return venuesSoFar; } } function Venue(name, depth, defn, sizeInPixels, map, entities) { this.name = name; this.depth = depth; this.defn = defn; this.sizeInPixels = sizeInPixels; this.map = map; this.entities = []; this.sizeInPixelsHalf = this.sizeInPixels.clone().divideScalar(2); this.entitiesByCategoryName = []; for (var c = 0; c < this.defn.categoriesKnown.length; c++) { var categoryName = this.defn.categoriesKnown[c].name; this.entitiesByCategoryName.push(categoryName); this.entitiesByCategoryName[categoryName] = []; } this.entitiesToSpawn = []; this.entitiesToRemove = []; for (var i = 0; i < entities.length; i++) { var entity = entities[i]; entity.loc.venueName = this.name; this.entitiesToSpawn.push(entity); } this.camera = new Camera ( "Camera", Camera.ViewSizeStandard ); this.camera.entity.loc.venueName = this.name; this.entitiesToSpawn.push(this.camera.entity); } { // instance methods Venue.prototype.entitiesInCategoryPresentAtCellPos = function(categoryName, cellPosToCheck) { var returnEntities = []; var entitiesInCategory = this.entitiesByCategoryName[categoryName]; if (entitiesInCategory != null) { for (var i = 0; i < entitiesInCategory.length; i++) { var entity = entitiesInCategory[i]; if (entity.loc.posInCells.equals(cellPosToCheck) == true) { returnEntities.splice(0, 0, entity); } } } return returnEntities; } Venue.prototype.entitySpawn = function(entityToSpawn) { entityToSpawn.loc.venueName = this.name; this.entities.push(entityToSpawn); this.entities[entityToSpawn.name] = entityToSpawn; var categoriesAll = Globals.Instance.universe.defn.categories; var entityCategoryNames = entityToSpawn.defn().categoryNames; for (var c = 0; c < entityCategoryNames.length; c++) { var entityCategoryName = entityCategoryNames[c]; var entityCategory = categoriesAll[entityCategoryName]; var entityListForCategory = this.entitiesByCategoryName[entityCategoryName]; if (entityListForCategory != null) { entityListForCategory.push(entityToSpawn); if (entityCategory.initializeEntityForVenue != null) { entityCategory.initializeEntityForVenue(entityToSpawn, this); } } } } Venue.prototype.initialize = function() { var categoriesKnown = this.defn.categoriesKnown; for (var b = 0; b < this.entities.length; b++) { var entity = this.entities[b]; var entityCategoryNames = entity.defn().categoryNames; for (var c = 0; c < entityCategoryNames.length; c++) { var entityCategoryName = entityCategoryNames[c]; var entityCategory = categoriesKnown[entityCategoryName]; if (entityCategory.initializeEntityForVenue != null) { entityCategory.initializeEntityForVenue(entity, this); } } } } Venue.prototype.update = function() { this.update_EntitiesToSpawn(); var player = Globals.Instance.universe.entityForPlayer; var venueKnown = player.playerData.venueKnownLookup[this.name]; if (venueKnown != null) { Globals.Instance.displayHelper.drawVenue(venueKnown); Globals.Instance.displayHelper.drawControl ( venueKnown.controlUpdate() ); } var numberOfCategories = this.entitiesByCategoryName.length; var categoriesAll = Globals.Instance.universe.defn.categories; for (var c = 0; c < numberOfCategories; c++) { var categoryName = this.entitiesByCategoryName[c]; var category = categoriesAll[categoryName]; if (category.updateEntityForVenue != null) { var entitiesInCategory = this.entitiesByCategoryName[categoryName]; var numberOfEntitiesInCategory = entitiesInCategory.length; for (var b = 0; b < numberOfEntitiesInCategory; b++) { var entity = entitiesInCategory[b]; category.updateEntityForVenue(entity, this); } } } this.update_Collidables(); this.update_EntitiesToRemove(); } Venue.prototype.update_EntitiesToRemove = function() { var categoriesAll = Globals.Instance.universe.defn.categories; for (var i = 0; i < this.entitiesToRemove.length; i++) { var entityToRemove = this.entitiesToRemove[i]; if (entityToRemove.collidableData != null) { var entitiesInCell = entityToRemove.collidableData.mapCellOccupied.entitiesPresent; entitiesInCell.splice ( entitiesInCell.indexOf(entityToRemove), 1 ); } this.entities.splice(this.entities.indexOf(entityToRemove), 1); delete this.entities[entityToRemove.name]; var entityCategoryNames = entityToRemove.defn().categoryNames; for (var c = 0; c < entityCategoryNames.length; c++) { var entityCategoryName = entityCategoryNames[c]; var entityCategory = categoriesAll[entityCategoryName]; var entitiesForCategory = this.entitiesByCategoryName[entityCategoryName]; entitiesForCategory.splice ( entitiesForCategory.indexOf(entityToRemove), 1 ); } } this.entitiesToRemove.length = 0; } Venue.prototype.update_EntitiesToSpawn = function() { for (var i = 0; i < this.entitiesToSpawn.length; i++) { var entityToSpawn = this.entitiesToSpawn[i]; this.entitySpawn(entityToSpawn); } this.entitiesToSpawn.length = 0; } Venue.prototype.update_Collidables = function() { var categories = Globals.Instance.universe.defn.categories; var emplacements = this.entitiesByCategoryName[categories.Emplacement.name]; var enemies = this.entitiesByCategoryName[categories.Enemy.name]; var items = this.entitiesByCategoryName[categories.Item.name]; var players = this.entitiesByCategoryName[categories.Player.name] var portals = this.entitiesByCategoryName[categories.Portal.name]; var projectiles = this.entitiesByCategoryName[categories.Projectile.name]; var collisionHelper = Globals.Instance.collisionHelper; var collisionSets = [ collisionHelper.findCollisionsBetweenEntitiesInSets ( players, emplacements ), collisionHelper.findCollisionsBetweenEntitiesInSets ( players, enemies ), collisionHelper.findCollisionsBetweenEntitiesInSets ( players, items ), collisionHelper.findCollisionsBetweenEntitiesInSets ( players, portals ), collisionHelper.findCollisionsBetweenEntitiesInSets ( enemies, projectiles ), ]; for (var s = 0; s < collisionSets.length; s++) { var collisions = collisionSets[s]; var numberOfCollisions = collisions.length; for (var c = 0; c < numberOfCollisions; c++) { var collision = collisions[c]; var numberOfEntities = collision.entities.length; for (var b0 = 0; b0 < numberOfEntities; b0++) { var entityThis = collision.entities[b0]; for (var b1 = b0 + 1; b1 < numberOfEntities; b1++) { var entityOther = collision.entities[b1]; collisionHelper.collideEntities ( collision, entityThis, entityOther ); collisionHelper.collideEntities ( collision, entityOther, entityThis ); } } } } } // controls Venue.prototype.controlUpdate = function() { if (this.control == null) { var entityForPlayer = Globals.Instance.universe.entityForPlayer; this.control = new ControlContainer ( "containerVenue", new Coords(10, 10), // pos new Coords(220, 240), // size // children [ entityForPlayer.moverData.controlUpdate(entityForPlayer), ] ); } return this.control; } } function VenueDefn(name, categoriesKnown, terrains, inputBindings, venueGenerate) { this.name = name; this.categoriesKnown = categoriesKnown; this.terrains = terrains; this.inputBindings = inputBindings; this.venueGenerate = venueGenerate; } { // xml VenueDefn.prototype.toXmlElement = function() { return new XmlElement ( this.constructor.name, // attributeNameValuePairs [ [ "name", this.name ], ], // children [ // todo ] ); } } function VisualOffset(visual, offset) { this.visual = visual; this.offset = offset; } { VisualOffset.prototype.drawToGraphicsAtPos = function(graphics, drawPos) { this.visual.drawToGraphicsAtPos ( graphics, drawPos.clone().add(this.offset) ); } } function VisualSet(name, visuals) { this.name = name; this.visuals = visuals; } { VisualSet.prototype.cloneAsVisual = function() { return this; // todo } VisualSet.prototype.drawToGraphicsAtPos = function(graphics, drawPos) { for (var i = 0; i < this.visuals.length; i++) { var visual = this.visuals[i]; visual.drawToGraphicsAtPos(graphics, drawPos); } } VisualSet.prototype.updateForVenue = function(entity, venue) { // do nothing } } function XmlElement(tagName, attributeNameValuePairs, children) { this.tagName = tagName; this.attributeNameValuePairs = attributeNameValuePairs; this.children = children; } { XmlElement.buildManyFromXmlizables = function(xmlizablesToBuildFrom) { var returnValues = []; for (var i = 0; i < xmlizablesToBuildFrom.length; i++) { var xmlizable = xmlizablesToBuildFrom[i]; var xmlElement = xmlizable.toXmlElement(); returnValues.push(xmlElement); } return returnValues; } XmlElement.prototype.toString = function() { var returnValue = "<" + this.tagName; for (var i = 0; i < this.attributeNameValuePairs.length; i++) { var attributeNameValuePair = this.attributeNameValuePairs[i]; returnValue += " " + attributeNameValuePair[0] + "='" + attributeNameValuePair[1] + "'"; } if (this.children.length == 0) { returnValue += "/>"; } else { returnValue += ">"; for (var i = 0; i < this.children.length; i++) { var child = this.children[i]; returnValue += child.toString(); } returnValue += "</" + this.tagName +">"; } return returnValue; } } // data // hack function AnimationDefnSetFake(image) { this.image = image; } { AnimationDefnSetFake.buildFromImage = function(image) { return new AnimationDefnSetFake(image); } AnimationDefnSetFake.prototype.toRun = function() { return this.image; } } function DemoData() { // do nothing } { DemoData.buildActions = function() { // Action.perform() declarations var actionEmplacement_Use_Perform = function(actor, action) { var loc = actor.loc; var venue = loc.venue(); var posInCells = actor.loc.posInCells; var usablesPresentInCell = venue.entitiesInCategoryPresentAtCellPos ( "Portal", posInCells ); if (usablesPresentInCell.length == 0) { return; } var usableToUse = usablesPresentInCell[0]; var costToUse = 1; if (actor.moverData.movesThisTurn < costToUse) { return; } actor.moverData.movesThisTurn -= costToUse; var portal = usableToUse; var portalData = portal.portalData; var destinationVenueName = portalData.destinationVenueName; var destinationEntityName = portalData.destinationEntityName; var universe = Globals.Instance.universe; var destinationVenue = universe.venues[destinationVenueName]; if (destinationVenue != null) { destinationVenue.initialize(); destinationVenue.update(); var entities = destinationVenue.entities; var destinationEntity = entities[destinationEntityName]; if (destinationEntity != null) { actor.loc.venue().entitiesToRemove.push(actor); destinationVenue.entitiesToSpawn.push(actor); actor.loc.posInCells.overwriteWith ( destinationEntity.loc.posInCells ); Globals.Instance.universe.venueNext = destinationVenue; actor.moverData.controlUpdate(actor); } } } var actionItem_DropSelected_Perform = function(actor, action) { var loc = actor.loc; var venue = loc.venue(); var posInCells = loc.posInCells; var itemsPresentInCell = venue.entitiesInCategoryPresentAtCellPos ( "Item", posInCells ); var containerData = actor.containerData; var itemToDrop = containerData.itemSelected; var costToDrop = 1; if (itemToDrop != null && actor.moverData.movesThisTurn >= costToDrop) { actor.moverData.movesThisTurn -= costToDrop; actor.containerData.dropItem(actor, itemToDrop); } } var actionItem_PickUp_Perform = function(actor, action) { var loc = actor.loc; var venue = loc.venue(); var posInCells = actor.loc.posInCells; var entitiesPresentAtCellPos = venue.map.cellAtPos(posInCells).entitiesPresent; for (var i = 0; i < entitiesPresentAtCellPos.length; i++) { var entityPresent = entitiesPresentAtCellPos[i]; if (entityPresent.defn().categoryNames.indexOf("Item") >= 0) { var itemToPickUp = entityPresent; var costToPickUp = 1; if (actor.moverData.movesThisTurn >= costToPickUp) { actor.moverData.movesThisTurn -= costToPickUp; actor.containerData.pickUpItem(actor, itemToPickUp); } } } } var actionItem_SelectAtOffset_Perform = function(actor, action) { var containerData = actor.containerData; var itemsHeld = containerData.items; if (itemsHeld.length == 0) { return; } var itemSelected = containerData.itemSelected; var indexOfItemSelected; if (itemSelected == null) { indexOfItemSelected = 0; } else { var indexOfItemSelected = itemsHeld.indexOf ( itemSelected ); var indexOffset = this.argumentForPerform; indexOfItemSelected += indexOffset; indexOfItemSelected = NumberHelper.wrapValueToRangeMax ( indexOfItemSelected, itemsHeld.length ); } containerData.itemSelected = itemsHeld[indexOfItemSelected]; actor.moverData.controlUpdate(actor); } var actionItem_TargetSelected_Perform = function(actor, action) { var containerData = actor.containerData; containerData.itemTargeted = containerData.itemSelected; actor.moverData.controlUpdate(actor); } var actionItem_UseSelected_Perform = function(actor, action) { var itemToUse = actor.containerData.itemSelected; if (itemToUse != null) { var movesToUse = 1; // todo if (actor.moverData.movesThisTurn >= movesToUse) { actor.moverData.movesThisTurn -= movesToUse; itemToUse.defn.itemDefn.use(actor, itemToUse, actor); } } } var actionMove_Perform = function(actor, action) { var directionToMove = action.argumentForPerform; if (directionToMove.magnitude() == 0) { return; } var actorLoc = actor.loc; var venue = actorLoc.venue(); var posInCellsDestination = actorLoc.posInCells.clone().add ( directionToMove ); var cellDestination = venue.map.cellAtPos(posInCellsDestination); var entitiesInCellDestination = cellDestination.entitiesPresent; var isDestinationAccessible = true; for (var b = 0; b < entitiesInCellDestination.length; b++) { var entityInCell = entitiesInCellDestination[b]; if (entityInCell.collidableData.defn.blocksMovement == true) { isDestinationAccessible = false; } if (entityInCell.defn().categoryNames.indexOf("Mover") >= 0) { isDestinationAccessible = false; var costToAttack = 1; // todo actor.moverData.movesThisTurn -= costToAttack; // todo - Calculate damage. var damageInflicted = DiceRoll.roll("1d6"); var entityDefns = Globals.Instance.universe.defn.entityDefns; var defnsOfEntitiesToSpawn = []; Font.spawnMessageFloater ( "Dagger", "-" + damageInflicted, actorLoc ); if (damageInflicted > 0) { entityInCell.killableData.integrityAdd ( 0 - damageInflicted ); if (entityInCell.killableData.integrity <= 0) { defnsOfEntitiesToSpawn.push ( entityInCell.defn().moverDefn.entityDefnCorpse ); } else { defnsOfEntitiesToSpawn.push ( entityDefns["Blood"] ); } } for (var i = 0; i < defnsOfEntitiesToSpawn.length; i++) { var defnOfEntityToSpawn = defnsOfEntitiesToSpawn[i]; var entityToSpawn = new Entity ( defnOfEntityToSpawn.name + "_Spawned", defnOfEntityToSpawn.name, posInCellsDestination ); venue.entitiesToSpawn.push ( entityToSpawn ); } } } if (isDestinationAccessible == true) { var costToTraverse = cellDestination.terrain.costToTraverse; if (costToTraverse <= actor.moverData.movesThisTurn) { actor.moverData.movesThisTurn -= costToTraverse; var cellDeparted = actor.collidableData.mapCellOccupied; var entitiesInCellDeparted = cellDeparted.entitiesPresent; entitiesInCellDeparted.splice ( entitiesInCellDeparted.indexOf(actor), 1 ); entitiesInCellDestination.push(actor); actor.collidableData.mapCellOccupied = cellDestination; actor.loc.posInCells.overwriteWith ( posInCellsDestination ); } } } var actionWait_Perform = function(actor, action) { actor.moverData.movesThisTurn = 0; } // directions var directions = new Coords_Instances()._DirectionsByHeading; // actions var actionEmplacement_Use = new Action ( "Use Emplacement", 1, actionEmplacement_Use_Perform ); var actionItem_DropSelected = new Action ( "Drop Selected Item", 1, actionItem_DropSelected_Perform ); var actionItem_PickUp = new Action ( "Pick Up Item", 1, actionItem_PickUp_Perform ); var actionItem_SelectNext = new Action ( "Select Next Item", null, actionItem_SelectAtOffset_Perform, 1 ); var actionItem_SelectPrev = new Action ( "Select Previous Item", null, actionItem_SelectAtOffset_Perform, -1 ); var actionItem_TargetSelected= new Action ( "Target Selected Item", 1, actionItem_TargetSelected_Perform ); var actionItem_UseSelected = new Action ( "Use Selected Item", 1, actionItem_UseSelected_Perform ); var actionMoveE = new Action ( "Move East", null, actionMove_Perform, directions[0] ); var actionMoveSE = new Action ( "Move Southeast", null, actionMove_Perform, directions[1] ); var actionMoveS = new Action ( "Move South", null, actionMove_Perform, directions[2] ); var actionMoveSW = new Action ( "Move Southwest", null, actionMove_Perform, directions[3] ); var actionMoveW = new Action ( "Move West", null, actionMove_Perform, directions[4] ); var actionMoveNW = new Action ( "Move Northwest", null, actionMove_Perform, directions[5] ); var actionMoveN = new Action ( "Move North", null, actionMove_Perform, directions[6] ); var actionMoveNE = new Action ( "Move Northeast", null, actionMove_Perform, directions[7] ); var actionWait = new Action("Wait", null, actionWait_Perform); var returnValues = [ actionEmplacement_Use, actionItem_DropSelected, actionItem_PickUp, actionItem_SelectNext, actionItem_SelectPrev, actionItem_TargetSelected, actionItem_UseSelected, actionMoveE, actionMoveSE, actionMoveS, actionMoveSW, actionMoveW, actionMoveNW, actionMoveN, actionMoveNE, actionWait, ]; // hack returnValues._MovesByHeading = [ actionMoveE, actionMoveSE, actionMoveS, actionMoveSW, actionMoveW, actionMoveNW, actionMoveN, actionMoveNE, ]; returnValues.addLookups("name"); return returnValues; } DemoData.buildActivityDefns = function() { var activityDefnDoNothing = new ActivityDefn ( "Do Nothing", // initialize function(actor, activity) { // do nothing }, // perform function(actor, activity) { // do nothing } ); var activityDefnGenerateMovers = new ActivityDefn ( "Generate Movers", // initialize function(actor, activity) { // do nothing }, // perform function(actor, activity) { var actorLoc = actor.loc; var venue = actorLoc.venue(); var agentsInVenue = venue.entitiesByCategoryName["Mover"]; var numberOfAgentsDesired = 5; if (agentsInVenue.length < numberOfAgentsDesired) { var chanceOfSpawnPerTurn = 1; // hack - actually per tick if (Math.random() < chanceOfSpawnPerTurn) { var difficultyMax = 1; // hack var universe = Globals.Instance.universe; var entityDefnsForAgents = universe.defn.entityDefnGroups["Agents"].entityDefns; var entityDefnForAgentToSpawn = null; var entityDefnIndex = Math.floor(Math.random() * entityDefnsForAgents.length); while (entityDefnForAgentToSpawn == null) { var entityDefn = entityDefnsForAgents[entityDefnIndex]; var moverDefn = entityDefn.moverDefn; if (moverDefn.difficulty <= difficultyMax) { entityDefnForAgentToSpawn = entityDefn; } entityDefnIndex++; if (entityDefnIndex >= entityDefnsForAgents.length) { entityDefnIndex = 0; } } var posToSpawnAt = venue.map.sizeInCells.clone().random(); var entityForAgent = new Entity ( entityDefnForAgentToSpawn.name + "0", entityDefnForAgentToSpawn.name, posToSpawnAt ); venue.entitiesToSpawn.push(entityForAgent); } } } ); var activityDefnMoveRandomly = new ActivityDefn ( "Move Randomly", // initialize function(actor, activity) { // do nothing }, // perform function(actor, activity) { // hack var actionsMoves = Globals.Instance.universe.defn.actions._MovesByHeading; var numberOfDirectionsAvailable = actionsMoves.length; var directionIndexRandom = Math.floor ( numberOfDirectionsAvailable * Globals.Instance.randomizer.getNextRandom() // Math.random() ); var actionMoveInRandomDirection = actionsMoves[directionIndexRandom]; actor.actorData.actions.push(actionMoveInRandomDirection); } ); var activityDefnMoveTowardPlayer = new ActivityDefn ( "Move Toward Player", // initialize function(actor, activity) { // do nothing }, // perform function(actor, activity) { if (actor.moverData.movesThisTurn <= 0) { return; } var actorLoc = actor.loc; var venue = actorLoc.venue(); var players = venue.entitiesByCategoryName["Player"]; if (players != null && players.length > 0) { var player = players[0]; var path = new Path ( venue.map, actorLoc.posInCells, player.loc.posInCells ); path.calculate(); if (path.nodes.length < 2) { return; } var pathNode1 = path.nodes[1]; var directionsToPathNode1 = pathNode1.cellPos.clone().subtract ( actor.loc.posInCells ).directions(); var heading = Heading.fromCoords(directionsToPathNode1); // hack var actionsMoves = Globals.Instance.universe.defn.actions._MovesByHeading; var actionMoveInDirection = actionsMoves[heading]; actor.actorData.actions.push ( actionMoveInDirection ); } } ); var activityDefnUserInputAccept = new ActivityDefn ( "Accept User Input", // initialize function(actor, activity) {}, // perform function(actor, activity) { var inputHelper = Globals.Instance.inputHelper; var actionsFromInput = inputHelper.actionsBeingPerformed; var actionsFromActor = actor.actorData.actions; for (var a = 0; a < actionsFromInput.length; a++) { var action = actionsFromInput[a]; var ticksToHold = ( action.ticksToHold == null ? action.ticksSoFar // hold forever : action.ticksToHold ); if (action.ticksSoFar <= ticksToHold) { actionsFromActor.push(action); } } } ); var returnValues = [ activityDefnDoNothing, activityDefnGenerateMovers, activityDefnMoveRandomly, activityDefnMoveTowardPlayer, activityDefnUserInputAccept, ]; returnValues.addLookups("name"); return returnValues; } DemoData.buildCategories = function() { var Actor = new Category ( "Actor", // construct null, null, // collide // initialize function(entity, venue) { var actorData = new ActorData(); entity.actorData = actorData; actorData.actions = []; var activity = new Activity ( entity.defn().actorDefn.activityDefnNameInitial, null ); actorData.activity_Set(entity, activity); }, // update function(entity, venue) { entity.actorData.activity_Get().perform(entity); var entityActions = entity.actorData.actions; for (var a = 0; a < entityActions.length; a++) { var action = entityActions[a]; action.perform(entity, action); } entityActions.length = 0; } ); var Camera = new Category("Camera", null, null, null, null); var Collidable = new Category ( "Collidable", // construct null, // collide function(entity) { // todo }, // initialize function(entity, venue) { var collidableData = new CollidableData ( entity.defn().collidableDefn ); var map = venue.map; var mapCellOccupied = map.cellAtPos(entity.loc.posInCells); mapCellOccupied.entitiesPresent.push(entity); collidableData.mapCellOccupied = mapCellOccupied; entity.collidableData = collidableData; }, // update function(entity, venue) { // todo }, // finalize function(entity, venue) { var collidableData = entity.collidableData; var entitiesPresentInCellOccupied = collidableData.mapCellOccupied; entitiesPresentInCellOccupied.splice ( entitiesPresentInCellOccupied.indexOf(entity), 1 ); } ); var Container = new Category ( "Container", // construct null, null, // collide // initialize function(entity, venue) { entity.containerData = new ContainerData(); }, null, // update null // finalize ); var Device = new Category ( "Device", // construct null, // collide // initialize function(entity, venue) { entity.deviceData = new DeviceData ( entity.defn().deviceDefn.chargesMax ); }, null, // update null // finalize ); var Drawable = new Category ( "Drawable", null, // construct null, // collide // initialize function(entity, venue) { entity.drawableData = new DrawableData ( true // isVisible ); var drawableData = entity.drawableData; var drawableDefn = entity.defn().drawableDefn; drawableData.visual = drawableDefn.visual.cloneAsVisual(); }, // update function(entity, venue) { entity.drawableData.visual.updateForVenue ( entity, venue ); }, null // finalize ); var Dynamic = new Category ( "Dynamic", null, // construct null, // collide null, // initialize // update function(entity, venue) { entity.dynamicData = new DynamicData(entity.defn().dynamicDefn); var dynamicData = entity.dynamicData; entity.loc.posInCells.add(dynamicData.vel); } ); var Effectable = new Category ( "Effectable", null, // construct null, // collide // initialize function(entity) { entity.effectData = new EffectData(); }, // update function(entity, venue) { // todo } ); var Emplacement = new Category("Emplacement", null, null, null, null); var Enemy = new Category("Enemy", null, null, null, null); var Ephemeral = new Category ( "Ephemeral", null, // construct null, // collide // initialize function(entity, venue) { entity.ephemeralData = new EphemeralData ( entity.defn().ephemeralDefn ); }, // update function(entity, venue) { var ephemeralData = entity.ephemeralData; ephemeralData.ticksToLive--; if (ephemeralData.ticksToLive <= 0) { venue.entitiesToRemove.push(entity); } } ); var Equippable = new Category ( "Equippable", null, // construct null, // collide // initialize function(entity) { entity.equippableData = new EquippableData ( entity.defn().equippableDefn ); }, null // update ); var Item = new Category ( "Item", null, // construct null, // collide // initialize function(entity) { entity.itemData = new ItemData(); }, null ); var Killable = new Category ( "Killable", null, // construct null, // collide // initialize function(entity, venue) { entity.killableData = new KillableData ( entity.defn().killableDefn ); }, // update function(entity, venue) { var killableData = entity.killableData; if (killableData.ticksToLive != null) { killableData.ticksToLive--; if (killableData.ticksToLive <= 0) { venue.entitiesToRemove.push(entity); } } if (killableData.integrity <= 0) { venue.entitiesToRemove.push(entity); } } ); var Mover = new Category ( "Mover", null, // construct null, // collide // initialize function(entity) { entity.moverData = new MoverData(entity.defn().moverDefn); }, // update function(entity, venue) { var entityLoc = entity.loc; entityLoc.posInCells.trimToRange ( venue.map.sizeInCellsMinusOnes ); } ); var Player = new Category ( "Player", null, // construct // collide function(entityThis, entityOther) { // todo }, // initialize function(entity, venue) { entity.playerData = new PlayerData(); entity.moverData.movesThisTurn = 0; var venueKnownLookup = entity.playerData.venueKnownLookup; var venueKnown = venueKnownLookup[venue.name]; if (venueKnown == null) { var mapComplete = venue.map; mapKnown = Map.buildBlank ( mapComplete.name + "_Known", mapComplete.terrains, mapComplete.cellSizeInPixels, mapComplete.sizeInCells ); venueKnown = new Venue ( venue.name + "_Known", venue.depth, venue.defn, venue.sizeInPixels, mapKnown, [] // entities ); venueKnownLookup[venue.name] = venueKnown; var categoryName = "Drawable"; var entitiesNotYetVisible = venue.entitiesByCategoryName[categoryName]; for (var i = 0; i < entitiesNotYetVisible.length; i++) { var entity = entitiesNotYetVisible[i]; entity.drawableData.isVisible = false; } Globals.Instance.sightHelper.updateVenueFromCompleteForViewerPosAndRange ( venueKnown, venue, entity.loc.posInCells, 8 //sightRange ); } }, // update function(entity, venue) { if (entity.moverData.movesThisTurn <= 0) { var vitals = entity.moverData.vitals.addSatietyToMover(-1, entity); var categoryName = "Mover"; var moversToRecharge = venue.entitiesByCategoryName[categoryName]; for (var i = 0; i < moversToRecharge.length; i++) { var mover = moversToRecharge[i]; mover.moverData.movesThisTurn = mover.defn().moverDefn.movesPerTurn; } Globals.Instance.universe.turnsSoFar++; var venueKnown = entity.playerData.venueKnownLookup[venue.name]; Globals.Instance.sightHelper.updateVenueFromCompleteForViewerPosAndRange ( venueKnown, venue, // venueComplete entity.loc.posInCells, 8 //sightRange ); entity.moverData.controlUpdate(entity); } } ); var Portal = new Category("Portal", null, null, null, null); var Projectile = new Category ( "Projectile", null, // construct // collide function(entityThis, entityOther) { var entityOtherCategoryNames = entityOther.defn().categoryNames; if (entityOtherCategoryNames.indexOf("Enemy") >= 0) { entityOther.killableData.integrity = 0; } }, null, null // update ); var returnValues = [ Actor, Camera, Collidable, Container, Device, Drawable, Dynamic, Effectable, Emplacement, Enemy, Ephemeral, Equippable, Item, Killable, Mover, Player, Portal, Projectile, new Category("Headwear"), new Category("Neckwear"), new Category("Shirt"), new Category("EntityArmor"), new Category("Cloak"), new Category("Glove"), new Category("Footwear"), new Category("Shield"), new Category("Armor"), new Category("Food"), new Category("Potion"), new Category("Ring"), new Category("Scroll"), new Category("Spellbook"), new Category("Tool"), new Category("Wand"), new Category("Weapon"), new Category("Ammunition"), ]; returnValues.addLookups("name"); return returnValues; } DemoData.buildEntityDefnGroups = function(images, activityDefns, categories) { // entityDefns var emplacements = DemoData.buildEntityDefnGroups_Emplacements(images, categories); var items = DemoData.buildEntityDefnGroups_Items(images, categories); var movers = DemoData.buildEntityDefnGroups_Movers(images, activityDefns, categories); var cameras = new EntityDefnGroup("Cameras", 0, [ Camera.EntityDefn ]); var returnValues = ArrayHelper.concatenateArrays ([ [ cameras ], [ emplacements ], items, [ movers ], ]); return returnValues; } DemoData.buildEntityDefnGroups_Emplacements = function(images, categories) { //var categories = Category.Instances; var animation = AnimationDefnSetFake.buildFromImage; var emplacements = [ "Collidable", "Drawable", "Emplacement", ]; var sizeInPixels = images["Floor"].sizeInPixels; var entityDefns = [ new EntityDefn ( "Blood", ArrayHelper.concatenateArrays ([ emplacements, [ "Ephemeral" ], ]), [ CollidableDefn.Instances.Clear, new DrawableDefn(animation(images["Blood"]).toRun(), sizeInPixels), new EphemeralDefn(30), ] ), new EntityDefn ( "Door", emplacements, [ CollidableDefn.Instances.Concealing, new DrawableDefn(animation(images["Door"]).toRun(), sizeInPixels) , ] ), new EntityDefn ( "Gravestone", emplacements, [ CollidableDefn.Instances.Clear, new DrawableDefn(animation(images["Gravestone"]).toRun(), sizeInPixels) ] ), new EntityDefn ( "StairsDown", [ "Collidable", "Drawable", "Emplacement", "Portal", ], [ CollidableDefn.Instances.Clear, new DrawableDefn(animation(images["StairsDown"]).toRun(), sizeInPixels), ] ), new EntityDefn ( "StairsUp", [ "Collidable", "Drawable", "Emplacement", "Portal", ], [ CollidableDefn.Instances.Clear, new DrawableDefn(animation(images["StairsUp"]).toRun(), sizeInPixels), ] ), ]; var returnValue = new EntityDefnGroup ( "Emplacements", 1, // relativeFrequency entityDefns ); return returnValue; } DemoData.buildEntityDefnGroups_Items = function(images, categories) { // convenience variables var animation = AnimationDefnSetFake.buildFromImage; var categoriesCommon = [ "Collidable", "Drawable", "Item", ]; var sizeInPixels = images["Floor"].sizeInPixels; var itemPropertiesNoStack = new ItemDefn ( "[Appearance]", 1, // mass 1, // stackSizeMax 1, // relativeFrequency null, // initialize null // use ); var itemPropertiesStandard = new ItemDefn ( "[Appearance]", 1, // mass 999, // stackSizeMax 1, // relativeFrequency null, // initialize null // use ); var effectDefnDoNothing = new EffectDefn ( "Do Nothing", function(targetEntity) { // do nothing } ); var effectDoNothing = new Effect(effectDefnDoNothing); var entityDefnSets = []; var methodsToRun = [ DemoData.buildEntityDefns_Items_Containers, DemoData.buildEntityDefns_Items_Food, DemoData.buildEntityDefns_Items_Potions, DemoData.buildEntityDefns_Items_Rings, DemoData.buildEntityDefns_Items_Scrolls, DemoData.buildEntityDefns_Items_Spellbooks, DemoData.buildEntityDefns_Items_Wands, DemoData.buildEntityDefns_Items_Weapons, DemoData.buildEntityDefns_Items_Armor, DemoData.buildEntityDefns_Items_Tools, DemoData.buildEntityDefns_Items_Stones, ]; var itemDefnGroups = []; for (var i = 0; i < methodsToRun.length; i++) { var itemDefnGroup = methodsToRun[i] ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, [] // entityDefnSets ); itemDefnGroups.push(itemDefnGroup); entityDefnSets.push(itemDefnGroup.entityDefns); } return itemDefnGroups; } DemoData.buildEntityDefns_Items_Containers = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { entityDefnSets.push ([ new EntityDefn ( "Chest", [ "Collidable", "Container", "Drawable", "Item", ], [ itemPropertiesNoStack, new DrawableDefn(animation(images["Chest"]).toRun(), sizeInPixels), ] ), ]); var returnValue = new EntityDefnGroup("Containers", 1, entityDefnSets[0]); return returnValue; } DemoData.buildEntityDefns_Items_Food = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { // items - foods var namesOfFoods = [ "Eucalyptus Leaf", "Apple", "Orange", "Pear", "Melon", "Banana", "Carrot", "Sprig of Wolfsbane", "Garlic Clove", "Slime Mold", "Royal Jelly", "Cream Pie", "Candy Bar", "Fortune Cookie", "Pancake", "Lembas Wafer", "Cram Ration", "Food Ration", "K Ration", "C Ration", "Tin", ]; var effectNourish = new Effect ( new EffectDefn ( "Nourish", function(targetEntity) { targetEntity.moverData.vitals.addSatietyToMover(1000, targetEntity); targetEntity.moverData.controlUpdate(targetEntity); } ) ); var entityDefnSetFoods = []; for (var i = 0; i < namesOfFoods.length; i++) { var name = namesOfFoods[i]; var entityDefn = new EntityDefn ( name, ArrayHelper.concatenateArrays ([ categoriesCommon, [ "Device", "Food", ] ]), [ CollidableDefn.Instances.Clear, new DeviceDefn ( 1, // chargesMax true, // consumedWhenAllChargesUsed // effectsToApply [ effectNourish ] ), new DrawableDefn(animation(images[name]).toRun(), sizeInPixels), new ItemDefn ( name, 1, // mass 1, // stackSizeMax, 1, // relativeFrequency ItemDefn.InitializeDevice, ItemDefn.UseDevice ) ] ); entityDefnSetFoods.push(entityDefn); } entityDefnSets.push(entityDefnSetFoods); return new EntityDefnGroup("Food", 1, entityDefnSets[0]); } DemoData.buildEntityDefns_Items_Potions = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { // items - magic - potions var ED = EffectDefn; var effectMessageNotImplemented = new EffectDefn ( "Display Not Implemented Message", function(actingEntity, targetEntity) { Font.spawnMessageFloater ( actingEntity.defn().name, "NOT IMPLEMENTED - " + actingEntity.defn().name, targetEntity.loc ); targetEntity.controlUpdate(); } ); var namesAndEffectDefnsOfPotions = [ [ "Acid" , new ED( null, function(ab, tb) { tb.moverData.integrityAdd(-30); tb.moverData.controlUpdate(tb); } ) ], [ "Blindness" , effectMessageNotImplemented ], [ "Booze" , effectMessageNotImplemented ], [ "Enlightenment" , effectMessageNotImplemented ], [ "Confusion" , effectMessageNotImplemented ], [ "Fruit Juice" , new ED( null, function(ab, tb) { tb.moverData.vitals.addSatietyToMover(100, targetEntity); tb.moverData.controlUpdate(targetEntity); } ) ], [ "Gain Ability" , new ED( null, function(ab, tb) { tb.moverData.traits.strength += 1; tb.moverData.controlUpdate(tb); } ) ], [ "Gain Energy" , new ED( null, function(ab, tb) { tb.moverData.vitals.energy += 100; tb.moverData.controlUpdate(tb); } ) ], [ "Gain Level" , new ED( null, function(ab, tb) { tb.moverData.demographics.level += 1; tb.moverData.controlUpdate(tb); } ) ], [ "Healing" , new ED( null, function(ab, tb) { tb.killableData.integrityAdd(10); tb.moverData.controlUpdate(tb); } ) ], [ "Healing Extra" , new ED( null, function(ab, tb) { tb.killableData.integrityAdd(30); tb.moverData.controlUpdate(tb); } ) ], [ "Healing Full" , new ED( null, function(ab, tb) { tb.killableData.integrityAdd(1000); tb.moverData.controlUpdate(tb); } ) ], [ "Invisibility" , effectMessageNotImplemented ], [ "Levitation" , effectMessageNotImplemented ], [ "Monster Detection" , effectMessageNotImplemented ], [ "Paralysis" , effectMessageNotImplemented ], [ "Object Detection" , effectMessageNotImplemented ], [ "Oil" , effectMessageNotImplemented ], [ "Polymorph" , effectMessageNotImplemented ], [ "Restore Ability" , effectMessageNotImplemented ], [ "See Invisible" , effectMessageNotImplemented ], [ "Sickness" , new ED( null, function(ab, tb) { tb.killableData.integrityAdd(-20); tb.moverData.controlUpdate(tb); } ) ], [ "Sleeping" , effectMessageNotImplemented ], [ "Speed" , effectMessageNotImplemented ], [ "Water" , effectMessageNotImplemented ], ]; var appearances = [ "Ruby","Pink","Orange","Yellow", "Emerald","Dark Green","Sky Blue","Cyan", "Brilliant Blue","Magenta","Purple-Red","Puce", "Milky","Swirly","Bubbly","Smoky", "Cloudy","Effervescent","Black","Golden", "Brown","Fizzy","Dark","White", "Murky", "Clear", ]; var entityDefnSetPotions = []; for (var i = 0; i < namesAndEffectDefnsOfPotions.length; i++) { var appearanceIndex = Math.floor ( Globals.Instance.randomizer.getNextRandom() * appearances.length ); var appearance = appearances[appearanceIndex] + " Potion"; appearances.splice(appearanceIndex, 1); var potionData = namesAndEffectDefnsOfPotions[i]; var name = potionData[0]; var effectDefn = potionData[1]; effectDefn.name = name; var entityDefn = new EntityDefn ( "Potion of " + name, ArrayHelper.concatenateArrays ([ categoriesCommon, [ "Potion", "Device", ] ]), [ CollidableDefn.Instances.Clear, new DeviceDefn ( 1, // chargesMax true, // consumedWhenAllChargesUsed // effectsToApply [ new Effect(effectDefn) ] ), //new DrawableDefn(animation(images[appearance]).toRun(), sizeInPixels) new DrawableDefn(images[appearance], sizeInPixels), new ItemDefn ( appearance, 1, // mass 1, // stackSizeMax, 1, // relativeFrequency ItemDefn.InitializeDevice, ItemDefn.UseDevice ) ] ); entityDefnSetPotions.push(entityDefn); } entityDefnSets.push(entityDefnSetPotions); return new EntityDefnGroup("Potions", 1, entityDefnSets[0]); } DemoData.buildEntityDefns_Items_Rings = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { // items - magic - rings var namesOfRings = [ "Adornment", // 0 "Aggravate Monster", "Conflict", "Free Action", "Gain Constitution", "Gain Strength", // 5 "Hunger", "Increase Accuracy", "Increase Damage", "Invisibility", "Levitation", // 10 "Polymorph", "Polymorph Control", "Protection", "Protection from Shape Changers", "Regeneration", // 15 "Resist Cold", "Resist Shock", "Resist Fire", "Resist Posion", "Searching", // 20 "See Invisible", "Slow Digestion", "Stealth", "Sustain Ability", "Teleport", // 25 "Teleport Control", "Warning", // 27 ]; appearances = [ "Pearl","Iron","Twisted","Steel", "Wire","Engagement","Shiny","Bronze", "Brass","Copper","Silver","Gold", "Wooden","Granite","Opal","Clay", "Coral","Black Onyx","Moonstone","Tiger Eye", "Jade","Agate","Topaz","Sapphire", "Ruby","Diamond","Ivory","Emerald", ]; var entityDefnSetRings = []; for (var i = 0; i < namesOfRings.length; i++) { var appearanceIndex = Math.floor ( Globals.Instance.randomizer.getNextRandom() * appearances.length ); var appearance = appearances[appearanceIndex] + " Ring"; appearances.splice(appearanceIndex, 1); entityDefnSetRings.push ( new EntityDefn ( "Ring of " + namesOfRings[i], ArrayHelper.concatenateArrays ([ categoriesCommon, [ "Ring" ], ]), [ CollidableDefn.Instances.Clear, new DrawableDefn(animation(images[appearance]).toRun(), sizeInPixels), new ItemDefn ( appearance, 1, // mass 1, // stackSizeMax 1, // relativeFrequency ItemDefn.InitializeDoNothing, ItemDefn.UseEquip ), ] ) ); } entityDefnSets.push(entityDefnSetRings); return new EntityDefnGroup("Rings", 1, entityDefnSets[0]); } DemoData.buildEntityDefns_Items_Scrolls = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { // items - magic - scrolls var namesOfScrolls = [ "Amnesia", // 0 "Blank", "Charging", "Confuse Monster", "Create Monster", "Destroy Armor", // 5 "Detect Food", "Detect Gold", "Earth", "Enchant Armor", "Enchant Weapon", // 10 "Fire", "Genocide", "Identify", "Light", "Mapping", // 15 "Punishment", "Remove Curse", "Scare Monster", "Stinking Cloud", "Taming", // 20 "Teleport", // 21 ]; appearances = [ "Andova Begarin", "Daiyen Fooels", "Duam Xnaht", "Eblib Yloh", "Elam Ebow", "Foobie Bletch", "Garven Deh", "Hackem Muche", "Juyed Awk Yacc", "Kernod Wel", "Kirje", "Lep Gex Ven Zea", "NR 9", "Pratyavayah", "Prirutsenie", "Read Me", "Temov", "Tharr", "Ve Forbryderne", "Velox Neb", "Venzar Borgavve", "Verr Yed Horre", "Xixaxa Xoxaxa Xuxaxa", "Yum Yum", "Zelgo Mer", ]; var entityDefnSetScrolls = []; for (var i = 0; i < namesOfScrolls.length; i++) { var appearanceIndex = Math.floor ( Globals.Instance.randomizer.getNextRandom() * appearances.length ); var appearance = "Scroll Titled '" + appearances[appearanceIndex] + "'"; appearances.splice(appearanceIndex, 1); var entityDefn = new EntityDefn ( "Scroll of " + namesOfScrolls[i], ArrayHelper.concatenateArrays ([ categoriesCommon, [ "Device", "Scroll", ], ]), [ CollidableDefn.Instances.Clear, new DeviceDefn ( 1, // chargesMax true, // consumedWhenAllChargesUsed // effectsToApply [ effectDoNothing ] ), new DrawableDefn(animation(images[appearance]).toRun(), sizeInPixels), new ItemDefn ( appearance, 1, // mass 1, // stackSizeMax 1, // relativeFrequency ItemDefn.InitializeDevice, ItemDefn.UseDevice ), ] ); entityDefnSetScrolls.push(entityDefn); } entityDefnSets.push(entityDefnSetScrolls); var returnValue = new EntityDefnGroup("Scrolls", 1, entityDefnSetScrolls); return returnValue; } DemoData.buildEntityDefns_Items_Spellbooks = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { var namesOfSpellbooks = [ // attack "Force Bolt", // 0 "Drain Life", "Magic Missile", "Cone of Cold", "Fireball", "Finger of Death", // 5 // clerical "Protection", "Create Monster", "Remove Curse", "Create Familiar", "Turn Undead", // 10 // divination "Detect Monsters", "Light", "Detect Food", "Clairvoyance", "Detect Unseen", // 15 "Identify", "Detect Treasure", "Magic Mapping", // enchantment "Sleep", "Confuse Monster", // 20 "Slow Monster", "Cause Fear", "Charm Monster", // escape "Jumping", "Haste", // 25 "Invisibility", "Levitation", "Teleport Away", // healing "Healing", "Cure Blindness", // 30 "Cure Sickness", "Extra Healing", "Stone to Flesh", "Restore Ability", // matter "Knock", // 35 "Wizard Lock", "Dig", "Polymorph", "Cancellation", // 39 ]; var appearances = [ "Parchment","Vellum","Ragged","Dogeared", "Mottled","Stained","Cloth","Leather", "White","Pink","Red","Orange", "Yellow","Velvet","Light Green","Dark Green", "Turquoise","Cyan","Light Blue","Dark Blue", "Indigo","Magenta","Purple","Violet", "Tan","Plaid","Light Brown","Dark Brown", "Gray","Wrinkled","Dusty","Bronze", "Copper","Silver","Gold","Glittering", "Shining","Dull","Thin","Thick", ]; var entityDefnSetSpellbooks = []; for (var i = 0; i < namesOfSpellbooks.length; i++) { var nameOfSpellbook = namesOfSpellbooks[i]; var appearanceIndex = Math.floor ( Globals.Instance.randomizer.getNextRandom() * appearances.length ); var appearance = appearances[appearanceIndex] + " Spellbook"; appearances.splice(appearanceIndex, 1); var effectLearnSpell = new Effect ( new EffectDefn ( "Learn Spell: " + nameOfSpellbook, function(targetEntity) { var spellToAdd = new SpellDefn("[Spell]"); var spellsKnown = targetEntity.moverData.spells.spells; var isSpellAlreadyKnown = false; for (var i = 0; i < spellsKnown.length; i++) { if (spellsKnown[i].name == spellToAdd.name) { isSpellAlreadyKnown = true; break; } } if (isSpellAlreadyKnown == false) { spellsKnown.push(spellToAdd); } } ) ); var entityDefn = new EntityDefn ( "Spellbook of " + nameOfSpellbook, ArrayHelper.concatenateArrays ([ categoriesCommon, [ "Device", "Spellbook", ], ]), [ CollidableDefn.Instances.Clear, new DeviceDefn(10, true, [ effectLearnSpell ]), new DrawableDefn(animation(images[appearance]).toRun(), sizeInPixels), new ItemDefn ( appearance, 1, // mass 1, // stackSizeMax 1, // relativeFrequency ItemDefn.InitializeDevice, ItemDefn.UseDevice ) ] ); entityDefnSetSpellbooks.push(entityDefn); } entityDefnSets.push(entityDefnSetSpellbooks); var returnValue = new EntityDefnGroup("Spellbooks", 1, entityDefnSets[0]); return returnValue; } DemoData.buildEntityDefns_Items_Wands = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { var effectMessage = new Effect ( new EffectDefn ( "Display a Message", function(actingEntity, targetEntity) { Font.spawnMessageFloater ( actingEntity.defn().name, "NOT IMPLEMENTED - " + actingEntity.defn().name, targetEntity.loc ); targetEntity.controlUpdate(); } ) ); var effectProjectileSpawn = new Effect ( new EffectDefn ( "Spawn Projectile", function(actingEntity, targetEntity) { var universe = Globals.Instance.universe; var loc = targetEntity.loc; var venue = loc.venue(); var entityForProjectile = new Entity ( "Projectile0", universe.defn.entityDefns["Rock"].name, loc.posInCells.clone() ); venue.entitiesToSpawn.push(entityForProjectile); targetEntity.controlUpdate(); } ) ); var effectTeleport = new Effect ( new EffectDefn ( "Teleport", function(actingEntity, targetEntity) { var loc = targetEntity.loc; var teleportPos = null; while (teleportPos == null) { var map = loc.venue().map; teleportPos = map.sizeInCells.clone().random(); var cellToTeleportTo = map.cellAtPos(teleportPos); if (cellToTeleportTo.terrain.costToTraverse > 1) { teleportPos = null; } } loc.posInCells.overwriteWith(teleportPos); targetEntity.controlUpdate(); targetEntity.moverData.controlUpdate(targetEntity); } ) ); var wandDatas = [ [ "Cancelling", effectMessage ], // 0 [ "Cold", effectProjectileSpawn ], [ "Create Monster", effectMessage ], [ "Death", effectProjectileSpawn ], [ "Digging", effectTeleport ], [ "Enlightenment", effectMessage ], // 5 [ "Fire", effectProjectileSpawn ], [ "Light", effectMessage ], [ "Lightning", effectProjectileSpawn ], [ "Locking", effectMessage ], [ "Make Invisible", effectMessage ], // 10 [ "Magic Missile", effectProjectileSpawn ], [ "Nothing", effectMessage ], [ "Opening", effectMessage ], [ "Polymorph", effectMessage ], [ "Probing", effectMessage ], // 15 [ "Secret Door Detection", effectMessage ], [ "Sleep", effectMessage ], [ "Slow Monster", effectMessage ], [ "Speed Monster", effectMessage ], [ "Striking", effectProjectileSpawn ], // 20 [ "Teleport", effectTeleport ], [ "Turn Undead", effectMessage ], [ "Wishing", effectMessage ], // 23 ]; appearances = [ "Glass","Balsa","Crystal","Maple", "Pine","Oak","Ebony","Marble", "Tin","Brass","Copper","Silver", "Platinum","Iridium","Zinc","Aluminum", "Uranium","Iron","Steel","Hexagonal", "Short","Runed","Long","Curved", "Forked","Spiked","Jeweled", ]; var entityDefnSetWands = []; for (var i = 0; i < wandDatas.length; i++) { var wandData = wandDatas[i]; var name = wandData[0]; var effect = wandData[1]; var appearanceIndex = Math.floor ( Globals.Instance.randomizer.getNextRandom(), appearances.length ); var appearance = appearances[appearanceIndex] + " Wand"; appearances.splice(appearanceIndex, 1); entityDefnSetWands.push ( new EntityDefn ( "Wand of " + name, ArrayHelper.concatenateArrays ([ categoriesCommon, [ "Device", "Wand", ], ]), [ CollidableDefn.Instances.Clear, new DeviceDefn ( 10, // chargesMax false, // consumedWhenAllChargesUsed // effectsToApply [ effect ] ), new DrawableDefn(animation(images[appearance]).toRun(), sizeInPixels), new ItemDefn ( appearance, 1, // mass 1, // stackSizeMax 1, // relativeFrequency ItemDefn.InitializeDevice, ItemDefn.UseDevice ), ] ) ); } entityDefnSets.push(entityDefnSetWands); return new EntityDefnGroup("Wands", 1, entityDefnSets[0]); } DemoData.buildEntityDefns_Items_MagicTools = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { // todo } DemoData.buildEntityDefns_Items_Weapons = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { var namesAndAppearancesOfWeapons = [ [ "Arrow", "Arrow" ], [ "Battle Axe", "Battle Axe" ], [ "Bow", "Bow" ], [ "Bow2", "Bow2" ], [ "Bow3", "Bow3" ], [ "Bow4", "Bow4" ], [ "Sling", "Sling" ], [ "Crossbow", "Crossbow" ], [ "Crossbow Bolt", "Crossbow Bolt" ], [ "Dagger", "Dagger" ], [ "Elven Dagger", "Runed Dagger" ], [ "Hand Axe", "Hand Axe" ], [ "Knife", "Knife" ], [ "Orcish Dagger", "Crude Dagger" ], [ "Polearm1", "Polearm1" ], [ "Silver Arrow", "Silver Arrow" ], [ "Sword", "Sword" ], ]; var entityDefnSetWeapons = []; for (var i = 0; i < namesAndAppearancesOfWeapons.length; i++) { var nameAndAppearance = namesAndAppearancesOfWeapons[i]; var name = nameAndAppearance[0]; var appearance = nameAndAppearance[1]; var entityDefn = new EntityDefn ( name, ArrayHelper.concatenateArrays ([ categoriesCommon, [ "Weapon" ] ]), [ CollidableDefn.Instances.Clear, new DrawableDefn(animation(images[name]).toRun(), sizeInPixels), new ItemDefn ( appearance, 1, // mass 1, // stackSizeMax 1, // relativeFrequency null, // initialize ItemDefn.UseEquip// use ), ] ); entityDefnSetWeapons.push(entityDefn); }; entityDefnSets["Group_Weapons"] = entityDefnSetWeapons; entityDefnSets.push(entityDefnSetWeapons); return new EntityDefnGroup("Weapons", 1, entityDefnSets[0]); } DemoData.buildEntityDefns_Items_Armor = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { var headwear = categories["Headwear"]; var entityArmor = categories["EntityArmor"]; var shirt = categories["Shirt"]; var cloak = categories["Cloak"]; var footwear = categories["Footwear"]; var shield = categories["Shield"]; var namesAndCategoriesOfArmor = [ [ "Elven Leather Helmet",headwear ], [ "Orcish Helmet", headwear ], [ "Dwarvish Helmet", headwear ], [ "Black Hat", headwear ], [ "Cornuthaum", headwear ], [ "Dunce Cap", headwear ], [ "Cooking Pot", headwear ], [ "Plumed Helmet", headwear ], [ "Etched Helmet", headwear ], [ "Crested Helmet", headwear ], [ "Visored Helmet", headwear ], [ "Plate Mail", entityArmor ], [ "Crystal Plate Mail", entityArmor ], [ "Bronze Plate Mail", entityArmor ], [ "Armor1", entityArmor ], [ "Armor2", entityArmor ], [ "Elven Mithril Shirt", entityArmor], [ "Dwarven Mithril Shirt", entityArmor], [ "Armor3", entityArmor ], [ "Orcish Chain Mail", entityArmor ], [ "Armor4", entityArmor ], [ "Studded Leather Armor", entityArmor ], [ "Armor5", entityArmor ], [ "Armor6", entityArmor ], [ "Leather Armor", entityArmor ], [ "Leather Jacket", entityArmor ], [ "Hawaiian Shirt", shirt], [ "Tee Shirt", shirt], [ "Mummy Wrapping", cloak ], [ "Elven Cloak", cloak ], [ "Leather Cloak", cloak ], [ "Hooded Cloak", cloak ], [ "Oilskin Cloak", cloak ], [ "Robe", cloak ], [ "Apron", cloak ], [ "Leather Cloak 2", cloak ], [ "Tattered Cloak", cloak ], [ "Opera Cloak", cloak ], [ "Ornamental Cope", cloak ], [ "Piece of Cloth", cloak ], [ "Low Boots", footwear ], [ "Dwarven Boots", footwear ], [ "High Boots", footwear ], [ "Combat Boots", footwear ], [ "Jungle Boots", footwear ], [ "Elven Boots", footwear ], [ "Mud Boots", footwear ], [ "Buckled Boots", footwear ], [ "Riding Boots", footwear ], [ "Snow Boots", footwear ], [ "Polished Shield", shield ], [ "Small Round Shield", shield ], ]; var entityDefnSetArmor = []; for (var i = 0; i < namesAndCategoriesOfArmor.length; i++) { var nameAndCategory = namesAndCategoriesOfArmor[i]; var name = nameAndCategory[0]; var appearance = name; // hack var category = nameAndCategory[1]; var entityDefn = new EntityDefn ( name, ArrayHelper.concatenateArrays ([ categoriesCommon, [ "Armor", category.name ] ]), [ CollidableDefn.Instances.Clear, new DrawableDefn(animation(images[name]).toRun(), sizeInPixels), new ItemDefn ( appearance, 1, // mass 1, // stackSizeMax 1, // relativeFrequency null, // initialize ItemDefn.UseEquip // use ) ] ); entityDefnSetArmor.push(entityDefn); }; entityDefnSets.push(entityDefnSetArmor); entityDefnSets["Group_Armor"] = entityDefnSetArmor; return new EntityDefnGroup("Armor", 1, entityDefnSets[0]); } DemoData.buildEntityDefns_Items_Tools = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { var entityDefnSet = []; var namesAndAppearances = [ [ "Key", ], [ "Lockpick"], [ "Credit Card" ], [ "Candle" ], [ "Candle2" ], [ "Lantern" ], [ "Oil Lamp" ], [ "Magic Lamp" ], [ "Expensive Camera" ], [ "Mirror" ], [ "Crystal Orb" ], [ "Eyeglasses" ], [ "Blindfold" ], [ "Towel" ], [ "Saddle" ], [ "Leash" ], [ "Stethoscope" ], [ "Tinning Kit" ], [ "Tin Opener" ], [ "Can of Grease" ], [ "Figurine" ], [ "Magic Marker" ], [ "Unarmed Land Mine" ], [ "Unarmed Bear Trap" ], [ "Tin Whistle" ], [ "Magic Whistle" ], [ "Flute" ], [ "Flute2" ], [ "Tooled Horn" ], [ "Horn of Cold" ], [ "Horn of Plenty" ], [ "Horn4" ], [ "Harp" ], [ "Harp2" ], [ "Bell" ], [ "Trumpet" ], [ "Drum" ], [ "Earthquake Drum" ], [ "Pickaxe" ], [ "Grappling Hook" ], [ "Unicorn Horn" ], [ "Candelabra" ], [ "Bell of Opening" ], ]; for (var i = 0; i < namesAndAppearances.length; i++) { var nameAndAppearance = namesAndAppearances[i]; var name = nameAndAppearance[0]; var appearance = nameAndAppearance[0]; // hack var entityDefn = new EntityDefn ( name, ArrayHelper.concatenateArrays ([ categoriesCommon, [ "Tool" ] ]), [ CollidableDefn.Instances.Clear, new DrawableDefn(animation(images[name]).toRun(), sizeInPixels), new ItemDefn ( appearance, 1, // mass 1, // stackSizeMax 1, // relativeFrequency null, // initialize ItemDefn.UseEquip // use ), ] ); entityDefnSet.push(entityDefn); }; return new EntityDefnGroup("Tools", 1, entityDefnSet); } DemoData.buildEntityDefns_Items_Stones = function ( images, animation, categories, categoriesCommon, sizeInPixels, itemPropertiesNoStack, itemPropertiesStandard, effectDoNothing, entityDefnSets ) { var namesOfStones = [ // precious stones "Dilithium Crystal", // 0 "Diamond", "Ruby", "Jacinth", "Sapphire", "Black Opal", // 5 "Emerald", "Turqoise", "Citrine", "Aquamarine", "Piece of Amber", // 10 "Topaz", "Piece of Jet", "Opal", "Chrysoberyl", "Garnet", // 15 "Amethyst", "Jasper", "Piece of Fluorite", "Piece of Jade", "Piece of Obsidian", // 20 "Agate", // glass "White Glass", "Blue Glass", "Red Glass", "Yellowish Brown Glass", // 25 "Orange Glass", "Yellow Glass", "Black Glass", "Green Glass", "Violet Glass", // 30 // gray stones "Luckstone", "Loadstone", "Touchstone", "Flint", // rock "Rock", // 35 ]; var appearancesOfStones = [ "White Gem","White Gem","Red Gem","Orange Gem", "Blue Gem","Black Gem","Green Gem","Green Gem", "Yellow Gem","Green Gem","Brownish Gem","Brownish Gem", "Black Gem","White Gem","Yellow Gem","Red Gem", "Violet Gem","Red Gem","Violet Gem","Black Gem", "Orange Gem","Green Gem","White Gem", "Blue Gem", "Red Gem","Brownish Gem","Orange Gem", "Yellow Gem", "Black Gem","Green Gem","Violet Gem","Gray Stone", "Gray Stone","Gray Stone","Gray Stone","Rock", ]; var entityDefnSetStones = []; for (var i = 0; i < namesOfStones.length; i++) { var appearance = appearancesOfStones[i]; entityDefnSetStones.push ( new EntityDefn ( namesOfStones[i], categoriesCommon, [ CollidableDefn.Instances.Clear, new DrawableDefn(animation(images[appearance]).toRun(), sizeInPixels), new ItemDefn ( appearance, 1, // mass 1, // stackSizeMax 1, // relativeFrequency ItemDefn.InitializeDoNothing, ItemDefn.UseDoNothing ), ] ) ); } entityDefnSets.push(entityDefnSetStones); entityDefnSets["Group_Stones"] = entityDefnSetStones; var entityDefnSetValuables = []; entityDefnSetValuables.push ( new EntityDefn ( "Coins", categoriesCommon, ArrayHelper.concatenateArrays ([ itemPropertiesStandard, new DrawableDefn(animation(images["Coins"]).toRun(), sizeInPixels), ]) ) ); entityDefnSets["Group_Valuables"] = entityDefnSetValuables; entityDefnSets.push(entityDefnSetValuables); return new EntityDefnGroup("Stones", 1, entityDefnSets[0]); return new EntityDefnGroup("Valuables", 1, entityDefnSets[1]); } DemoData.buildEntityDefns_Items_EquipmentSocketDefnSet = function(categories) { var biped = new EquipmentSocketDefnSet ( "Biped", [ new EquipmentSocketDefn("Head", [ categories.Headwear.name ]), new EquipmentSocketDefn("Neck", [ categories.Neckwear.name ]), new EquipmentSocketDefn("Shirt", [ categories.Shirt.name ]), new EquipmentSocketDefn("Entity", [ categories.EntityArmor.name ]), new EquipmentSocketDefn("Cloak", [ categories.Cloak.name ]), new EquipmentSocketDefn("Hands", [ categories.Glove.name ] ), new EquipmentSocketDefn("Feet", [ categories.Footwear.name ] ), new EquipmentSocketDefn("Left Finger", [ categories.Ring.name ] ), new EquipmentSocketDefn("Right Finger", [ categories.Ring.name ] ), new EquipmentSocketDefn("Wielding", [ categories.Weapon.name ] ), new EquipmentSocketDefn("Ammunition", [ categories.Ammunition.name ] ), ] ); return biped; } DemoData.buildEntityDefnGroups_Movers = function(images, activityDefns, categories) { var returnValues = []; // convenience variables var animation = AnimationDefnSet.buildFromImage; var sizeInPixels = images["Floor"].sizeInPixels; var skillDefns = DemoData.buildSkillDefns(); var spellDefns = DemoData.buildSpellDefns(); var traitDefns = DemoData.buildTraitDefns(); // player var equipmentSocketDefnSetBiped = DemoData.buildEntityDefns_Items_EquipmentSocketDefnSet ( categories ); var entityDefnCorpse = new EntityDefn ( "Corpse", [ "Collidable", "Drawable", "Item", ], [ CollidableDefn.Instances.Clear, new DrawableDefn(animation(images["Corpse"]).toRun(), sizeInPixels), new ItemDefn ( "Corpse", 1, // mass 1, // stackSizeMax, 1, // relativeFrequency ItemDefn.InitializeDevice, ItemDefn.UseDevice ), ] ); returnValues.push(entityDefnCorpse); returnValues[entityDefnCorpse.name] = entityDefnCorpse; var moverDefnPlayer = new MoverDefn ( 999, // difficulty 1, // movesPerTurn new MoverData_Demographics("Human", "Rogue", 1), new MoverData_Traits ([ new Trait(traitDefns["Strength"], 10), new Trait(traitDefns["Dexterity"], 10), new Trait(traitDefns["Willpower"], 10), new Trait(traitDefns["Constitution"], 10), new Trait(traitDefns["Charisma"], 10), ]), new MoverData_Skills(skillDefns), new MoverData_Spells(spellDefns), new MoverDefn_Vitals(20, 1000), entityDefnCorpse, [] // attributeGroups ); var visualForPlayerBase = images["Rogue"]; var animationDefnSetPlayer = new AnimationDefnSet ( "AnimationDefnSetPlayer", [ new AnimationDefn ( "AnimationDefnPlayer", "AnimationDefnPlayer", // animationDefnNameNext [ new AnimationFrame ( visualForPlayerBase, 100 // ticksToHold ), new AnimationFrame ( images["Wizard"], 100 // ticksToHold ), ] ) ] ); var animationDefnSetReticle = new AnimationDefnSet ( "AnimationDefnSetReticle", [ new AnimationDefn ( "AnimationDefnReticle", "AnimationDefnReticle", // animationDefnNameNext [ new AnimationFrame ( images["Reticle0"], 10 // ticksToHold ), new AnimationFrame ( images["Reticle1"], 10 // ticksToHold ), ] ) ] ); var visualForPlayer = new VisualSet ( "Player", [ animationDefnSetPlayer.toRun(), animationDefnSetReticle.toRun(), ] ); var drawableDefnPlayer = new DrawableDefn ( visualForPlayer, sizeInPixels, 1 // zIndex ); var entityDefnPlayer = new EntityDefn ( "Player", [ "Actor", "Collidable", // formerly moved to end? "Container", "Drawable", "Equippable", "Killable", "Mover", "Player", ], // properties [ new ActorDefn(activityDefns["Accept User Input"].name), CollidableDefn.Instances.Blocking, new EquippableDefn(equipmentSocketDefnSetBiped), new KillableDefn(16, null), moverDefnPlayer, drawableDefnPlayer, ] ); returnValues.push(entityDefnPlayer); returnValues["Player"] = entityDefnPlayer; // agents var categories = [ "Actor", "Collidable", "Container", "Drawable", "Enemy", "Equippable", "Killable", "Mover", ]; var agentDatas = DemoData.buildAgentDatas(); for (var i = 0; i < agentDatas.length; i++) { var agentData = agentDatas[i]; var agentName = agentData[0]; var difficulty = agentData[1]; var entityDefnForAgent = new EntityDefn ( agentName, categories, // properties [ new ActorDefn(activityDefns["Move Toward Player"].name), CollidableDefn.Instances.Blocking, new EquippableDefn(equipmentSocketDefnSetBiped), new KillableDefn(5, null), new MoverDefn ( difficulty, 1, // movesPerTurn new MoverData_Demographics(null, null), new MoverData_Skills([]), new MoverData_Spells([]), new MoverData_Traits(10, 10, 10, 10, 10), new MoverDefn_Vitals(20, 1000), entityDefnCorpse, // attributeGroups [ // todo ] ), new DrawableDefn ( animation(images[agentName]).toRun(), sizeInPixels, 1 // zIndex ), ] ); returnValues.push(entityDefnForAgent); returnValues[agentName] = entityDefnForAgent; } var returnValue = new EntityDefnGroup ( "Agents", 0, // relativeFrequency returnValues ); return returnValue; } DemoData.buildAgentDatas = function() { // resistances var acid = "acid"; var aggravate = "aggravate"; var cold = "cold"; var disintegrate = disintegrate; var fire = "fire"; var petrify = "petrify"; var poison = "poison"; var shock = "shock"; var sleep = "sleep"; var stun = "stun"; var telepathy = "telepathy"; // sizes var tiny = 0; var small = 1; var medium = 2; var large = 3; var huge = 4; // corpse drop frequency at http://www.steelypips.org/nethack/343/mon2-343.html var agentDatas = [ // name, difficulty, numberAppearing, attacks, baseLevel, baseExperience, // speed, base ac, base mr, alignment, frequency, genocidable, // weight, nutrition, size, resistances, resistancesConveyed // insects [ "Giant Ant", 4, "1d3", [ "Bite:1d4" ], 2, 20, 18, 3, 0, 0, 3, true, 10, 10, tiny, null, .33, null ], [ "Killer Bee", 5, "2d6", [ "Sting:1d3" ], 1, 31, 18, -1, 0, 0, 2, true, 1, 5, tiny, [ poison ], .33, [ poison, 1 ] ], [ "Soldier Ant", 6, "1d3", [ "Bite:2d4", "Sting:3d4" ], 3, 37, 18, 3, 0, 0, 2, true, 20, 5, tiny, [ poison ], .33, [ poison, 1 ] ], [ "Fire Ant", 6, "1d3", [ "Bite:2d4", "Sting:2d4" ], 3, 34, 18, 3, 10, 0, 1, true, 30, 10, tiny, [ fire ], .25, [ fire, 1 ] ], [ "Giant Beetle", 6, "1", [ "Bite:3d6" ], 5, 56, 6, 4, 0, 0, 3, true, 10, 10, large, [ poison ], 1, [ poison, 1 ], ], [ "Queen Bee", 12, "1", [ "Sting:1d8" ], 9, 225, 24, -4, 0, 0, 0, true, 1, 5, tiny, [ poison ], .25, [ poison, 1 ] ], // blobs [ "Acid Blob", 2, "1", [ "Acid:1d8" ], 1, 9, 3, 8, 0, 0, 2, true, 30, 10, tiny, [sleep, poison, acid, petrify], .33, null ], [ "Quivering Blob", 6, "1", [ "Touch:1d8" ], 5, 59, 1, 8, 0, 0, 2, true, 200, 100, small, [sleep, poison], .50, [ poison, 1 ] ], [ "Gelatinous Cube", 8, "1", [ "Touch:2d4","Paralyze:1d4"],6, 76, 6, 8, 0, 0, 2, true, 600, 150, large, [ fire, cold, shock, sleep, poison, acid, petrify], 1, [ fire, 1, cold, 1, shock, 1, sleep, 1 ] ], // cockatrices [ "Chickatrice", 7, "1d3", [ "Bite:1d2" ], 4, 136, 4, 8, 30, 0, 1, true, 10, 10, tiny, [ poison, petrify ], .25, [ poison, 1 ] ], [ "Cockatrice", 7, "1", [ "Bite:1d3" ], 5, 149, 6, 6, 30, 0, 5, true, 30, 30, small, [ poison, petrify ], .50, [ poison, 1 ] ], [ "Pyrolisk", 8, "1", [ "Gaze:2d6" ], 6, 82, 6, 6, 30, 0, 1, true, 30, 30, small, [ fire, poison ], .33, [ fire, 1, poison, 1 ] ], // canines [ "Jackal", 1, "1d3", [ "Bite:1d2" ], 0, 1, 12, 7, 0, 0, 3, true, 300, 250, small, null, .50, null ], [ "Fox", 1, "1", [ "Bite:1d3" ], 0, 4, 15, 7, 0, 0, 1, true, 300, 250, small, null, .33, null ], [ "Coyote", 2, "1d3", [ "Bite:1d4" ], 1, 8, 12, 7, 0, 0, 1, true, 300, 250, small, null, .33, null ], [ "Werejackal" ], [ "Little Dog", 3, "1", [ "Bite:1d6" ], 3, 2, 20, 18, 6, 0, 1, true, 150, 150, small, null, .33, null ], [ "Dog", 5, "1", [ "Bite:1d6" ], 4, 4, 44, 16, 0, 0, 1, true, 400, 200, medium, null, .33, [ aggravate, 1 ] ], [ "Large Dog", 7, "1", [ "Bite:2d4" ], 6, 76, 15, 4, 0, 0, 1, true, 800, 250, medium, null, .33, null ], [ "Dingo", 5, "1", [ "Bite:1d5" ], 4, 44, 16, 5, 0, 0, 1, true, 400, 200, medium, null, .33, null ], [ "Wolf", 6, "1d3", [ "Bite:2d4" ], 6, 56, 12, 4, 0, 0, 2, true, 500, 250, medium, null, .50, null ], [ "Werewolf" ], [ "Warg", 8, "1d3", [ "Bite:2d6" ], 7, 92, 12, 4, 0, -5, 2, true, 850, 350, medium, null, .50, null ], [ "Winter Wolf Cub", 7, "1d3", [ "Bite:1d8", "Breath:1d8" ], 5, 64, 12, 4, 0, -5, 2, true, 250, 200, small, [ cold ], .50, [ cold, .33 ] ], [ "Winter Wolf", 9, "1", [ "Bite:2d6", "Breath:2d6" ], 7, 102, 12, 4, 20, 0, 1, true, 700, 300, large, [ cold ], 1, [ cold, .47 ] ], [ "Hell Hound Pup", 9, "1d3", [ "Bite:2d6", "Breath:2d6" ], 9, 102, 12, 4, 20, -5, 1, true, 200, 200, small, [ fire ], .33, [ fire, .47 ] ], [ "Hell Hound", 14, "1", [ "Bite:3d6", "Breath:3d6"], 12, 290, 14, 2, 20, 0, 1, true, 600, 300, medium, [ fire ], .33, [ fire, .80 ] ], [ "Cerberus" ], // eyes and spheres [ "Gas Spore", 2, "1", [ "Explode:4d6" ], 2, 1, 12, 3, 10, 0, 1, true, 10, 10, small, null, 0, null ], [ "Floating Eye", 3, "1", [ ], 2, 17, 1, 9, 10, 0, 5, true, 10, 10, small, null, .50, [ telepathy, 1] ], [ "Flaming Sphere", 3, "1", [ "Explode:4d6" ], 6, 91, 13, 4, 0, 0, 2, true, 10, 10, small, [ cold ], 0, null ], [ "Freezing Sphere", 3, "1", [ "Explode:4d6" ], 6, 91, 13, 4, 0, 0, 2, true, 10, 10, small, [ fire ], 0, null ], [ "Shocking Sphere", 3, "1", [ "Explode:4d6" ], 6, 91, 13, 4, 0, 0, 2, true, 10, 10, small, [ shock ], 0, null ], [ "Beholder" ], // felines [ "Kitten", 3, "1", [ "Bite:1d6" ], 2, 20, 18, 6, 0, 0, 1, true, 150, 150, small, null, .33, null ], [ "Housecat", 5, "1", [ "Bite:1d6" ], 4, 44, 16, 5, 0, 0, 1, true, 200, 200, small, null, .33, null ], [ "Jaguar", 6, "1", [ "Claw:1d4", "Bite:1d8" ], 4, 44, 15, 6, 0, 0, 2, true, 600, 300, large, null, 1, null ], [ "Lynx", 7, "1", [ "Claw:1d4", "Bite:1d10" ], 5, 59, 15, 6, 0, 0, 1, true, 600, 300, large, null, .33, null ], [ "Panther", 7, "1", [ "Claw:1d6", "Bite:1d10" ], 5, 59, 15, 6, 0, 0, 1, true, 600, 300, large, null, 1, null ], [ "Large Cat", 7, "1", [ "Bite:2d4" ], 6, 76, 15, 4, 0, 0, 1, true, 250, 250, small, null, .33, null ], [ "Tiger", 8, "1", [ "Claw:2d4", "Bite:1d10" ], 6, 73, 12, 6, 0, 0, 2, true, 600, 300, large, null, 1, null ], // gremlins and gargoyles [ "Gremlin" ], // .50 [ "Gargoyle" ], // .50 [ "Winged Gargoyle" ], // .33 // humanoids [ "Hobbit", 2, "1", [ "Weapon:1d6" ], 1, 13, 9, 10, 0, 6, 2, true, 500, 200, small, null, .50, null ], [ "Dwarf", 4, "1", [ "Weapon:1d8" ], 2, 22, 6, 10, 10, 4, 3, true, 900, 300, medium, null, .50, null ], [ "Bugbear" ], // 1.00 [ "Dwarf Lord" ], // .50 [ "Dwarf King" ], // .33 [ "Mind Flayer" ], // .33 [ "Master Mind Flayer" ], // .33 // minor demons [ "Manes", 3, "2d6", [ "Claw:2x1d3", "Bite:1d4"], 1, 8, 3, 7, 0, -7, 1, true, 100, 100, small, [ sleep, poison ], 0, null ], [ "Homunculus" ], // .33 [ "Imp" ], // .25 [ "Lemure" ], // 0 [ "Quasit" ], // .50 [ "Tengu" ], // .50 // jellies [ "Blue Jelly" ], // .50 [ "Spotted Jelly" ], // .33 [ "Ochre Jelly" ], // .50 // kobolds [ "Kobold", 1, "1", [ "Weapon:1d4" ], 0, 6, 6, 10, 0, -2, 1, true, 400, 100, small, [ poison ], null ], [ "Large Kobold" ], [ "Kobold Lord" ], [ "Kobold Shaman" ], // leprechauns [ "Leprechaun" ], // mimics [ "Small Mimic", 8, "1", [ "Claw:3d4" ], 7, 92, 3, 7, 0, 0, 2, true, 300, 200, medium, [ acid ], null ], [ "Large Mimic", 9, "1", [ "Claw:3d4" ], 8, 113, 3, 7, 10, 0, 1, true, 600, 400, large, [ acid ], null ], [ "Giant Mimic", 8, "1", [ "Claw:2x3d4" ], 9, 186, 3, 7, 20, 0, 1, true, 800, 500, large, [ acid ], null ], // nymphs [ "Wood Nymph", 5, "1", [], 3, 28, 12, 9, 20, 0, 2, true, 600, 300, medium, null, null ], [ "Water Nymph", 5, "1", [], 3, 28, 12, 9, 20, 0, 2, true, 600, 300, medium, null, null ], [ "Mountain Nymph", 5, "1", [], 3, 28, 12, 9, 20, 0, 2, true, 600, 300, medium, null, null ], // orcs [ "Goblin", 1, "1", [ "Weapon:1d4" ], 0, 6, 9, 10, 0, -3, 2, true, 400, 100, small, null, null ], [ "Hobgoblin", 3, "1", [ "Weapon:1d6" ], 1, 13, 9, 10, 0, -4, 2, true, 1000, 200, medium, null, null ], [ "Orc", 3, "2d6", [ "Weapon:1d8" ], 1, 13, 9, 10, 0, -3, 0, true, 850, 150, medium, null, null ], [ "Hill Orc", 4, "2d6", [ "Weapon:1d6" ], 2, 22, 9, 10, 0, -4, 2, true, 1000, 200, medium, null, null ], [ "Mordor Orc" ], [ "Uruk-hai" ], [ "Orc Shaman" ], [ "Orc Captain" ], // piercer [ "Rock Piercer", 4, "1", [ "Bite:2d6" ], 3, 28, 1, 3, 0, 0, 4, true, 200, 200, small, null, null ], [ "Iron Piercer", 6, "1", [ "Bite:3d6" ], 5, 63, 1, 0, 0, 0, 2, true, 400, 300, medium, null, null ], [ "Glass Piercer", 9, "1", [ "Bite:4d6" ], 7, 106, 1, 0, 0, 0, 4, true, 400, 300, medium, [ acid ], null ], // quadrupeds [ "Rothe", 4, "1", [ "Claw:1d3", "Bite:1d8" ], 2, 17, 9, 7, 0, 0, 4, true, 400, 100, large, null, null ], [ "Mumak" ], [ "Leocrotta" ], [ "Wumpus" ], [ "Titanothere" ], [ "Baluchitherium" ], [ "Mastodon" ], // rodents [ "Sewer Rat", 1, "1d3", [ "Bite:1d3" ], 0, 1, 12, 7, 0, 0, 1, true, 20, 12, tiny, null, null ], [ "Giant Rat", 2, "1d3", [ "Bite:1d3" ], 1, 8, 10, 7, 0, 0, 2, true, 30, 30, tiny, null, null ], [ "Rabid Rat", 4, "1", [ "Bite:2d4" ], 2, 17, 12, 6, 0, 0, 1, true, 30, 5, tiny, [ poison ], null ], [ "Wererat" ], [ "Rock Mole" ], [ "Woodchuck" ], // spiders and centipedes [ "Cave Spider", 3, "1d3", [ "Bite:1d2" ], 1, 8, 12, 3, 0, 0, 2, true, 50, 50, tiny, [ poison ], [ poison, .07 ] ], [ "Centipede" ], [ "Giant Spider" ], [ "Scorpion" ], // trappers, lurkers above [ "Lurker Above" ], [ "Trapper" ], // horses and unicorns [ "White Unicorn" ], [ "Gray Unicorn" ], [ "Black Unicorn" ], [ "Pony" ], [ "Horse" ], [ "Warhorse" ], // vortices [ "Fog Cloud", 4, "1", [ "Suffocate:1d6" ], 3, 38, 1, 0, 0, 0, 2, true, 0, 0, huge, [ sleep, poison, petrify ], null ], [ "Dust Vortex" ], [ "Ice Vortex" ], [ "Energy Vortex" ], [ "Steam Vortex" ], [ "Fire Vortex" ], // worms [ "Baby Long Worm" ], [ "Baby Purple Worm" ], [ "Long Worm" ], [ "Purple Worm" ], // fantastical insects [ "Grid Bug", 1, "1d3", [ "Bite:0d0"], 0, 1, 12, 9, 0, 0, 3, true, 15, 10, tiny, [ shock, poison ], null ], [ "Xan" ], // lights [ "Yellow Light", 5, "1", [ ], 3, 44, 15, 0, 0, 0, 4, true, 0, 0, small, [ fire, cold, shock, disintegrate, sleep, poison, acid, petrify ], null ], [ "Black Light" ], // zruties [ "Zruty" ], // angelic beings [ "Couatl" ], [ "Aleax" ], [ "Angel" ], [ "Ki-rin" ], [ "Archon" ], // bats and birds [ "Bat", 2, "1", [ "Bite:1d4" ], 0, 6, 22, 8, 0, 0, 1, true, 20, 20, tiny, null, [ ] ], [ "Giant Bat", 3, "1", [ "Bite:1d6" ], 2, 22, 22, 7, 0, 0, 2, true, 30, 30, small, null, [ ] ], [ "Raven" ], [ "Vampire Bat" ], // centaurs [ "Plains Centaur" ], [ "Forest Centaur" ], [ "Mountain Centaur" ], // dragons [ "Baby Gray Dragon" ], [ "Baby Silver Dragon" ], [ "Baby Silver Dragon 2" ], [ "Baby Red Dragon" ], [ "Baby White Dragon" ], [ "Baby Orange Dragon" ], [ "Baby Black Dragon" ], [ "Baby Blue Dragon" ], [ "Baby Green Dragon" ], [ "Baby Yellow Dragon" ], [ "Gray Dragon" ], [ "Silver Dragon" ], [ "Silver Dragon 2" ], [ "Red Dragon" ], [ "White Dragon" ], [ "Orange Dragon" ], [ "Black Dragon" ], [ "Blue Dragon" ], [ "Green Dragon" ], [ "Yellow Dragon" ], // elementals and stalkers [ "Stalker" ], [ "Air Elemental" ], [ "Fire Elemental" ], [ "Earth Elemental" ], [ "Water Elemental" ], // fungi and molds [ "Lichen", 1, "1", [ "Touch:0d0" ], 0, 4, 1, 9, 0, 0, 4, true, 20, 200, small, null, null ], [ "Brown Mold" ], [ "Yellow Mold" ], [ "Green Mold" ], [ "Red Mold" ], [ "Shrieker" ], [ "Violet Fungus" ], // gnomes [ "Gnome", 3, "1", [ "Weapon:1d6" ], 1, 13, 6, 10, 4, 0, 1, true, 650, 100, small, null, null ], [ "Gnome Lord", 4, "1", [ "Weapon:1d8" ], 3, 33, 8, 10, 4, 0, 2, true, 700, 120, small, null, null ], [ "Gnomish Wizard", 5, "1", [ ], 3, 38, 10, 4, 10, 0, 1, true, 700, 120, small, null, null ], [ "Gnome King", 6, "1", [ "Weapon:1d6" ], 5, 61, 10, 10, 20, 0, 1, true, 750, 150, small, null, null ], // large humanoids [ "Giant" ], [ "Stone Giant" ], [ "Hill Giant" ], [ "Fire Giant" ], [ "Frost Giant" ], [ "Storm Giant" ], [ "Ettin" ], [ "Titan" ], [ "Minotaur" ], // jabberwock [ "Jabberwock" ], [ "Jabberwock 2?" ], // keystone kops [ "Keystone Kop" ], [ "Kop Sergeant" ], [ "Kop Lieutenant" ], [ "Kop Kaptain" ], // liches [ "Lich" ], [ "Demilich" ], [ "Master Lich" ], [ "Arch-Lich" ], // mummies [ "Kobold Mummy", 4, "1", [ "Claw:1d4" ], 3, 28, 8, 6, 20, -2, 1, true, 400, 50, small, [ cold, sleep, poison ], null ], [ "Gnome Mummy", 5, "1", [ "Claw:1d6" ], 4, 41, 10, 6, 20, -3, 1, true, 650, 50, small, [ cold, sleep, poison ], null ], [ "Orc Mummy", 6, "1", [ "Claw:1d6" ], 5, 56, 10, 5, 20, -4, 1, true, 850, 75, medium, [ cold, sleep, poison ], null ], [ "Dwarf Mummy", 6, "1", [ "Claw:1d6" ], 5, 56, 10, 5, 20, -4, 1, true, 900, 150, medium, [ cold, sleep, poison ], null ], [ "Elf Mummy", 7, "1", [ "Claw:2d4" ], 6, 73, 12, 4, 30, -5, 1, true, 800, 150, medium, [ cold, sleep, poison ], null ], [ "Elf Mummy", 7, "1", [ "Claw:2x2d4" ], 6, 73, 12, 4, 30, -5, 1, true, 1450, 200, medium, [ cold, sleep, poison ], null ], [ "Ettin Mummy", 8, "1", [ "Claw:2x2d6" ], 7, 92, 12, 4, 30, -6, 1, true, 1700, 250, huge, [ cold, sleep, poison ], null ], [ "Giant Mummy", 10, "1", [ "Claw:2x3d4" ], 8, 116, 14, 3, 30, -7, 1, true, 2050, 375, huge, [ cold, sleep, poison ], null ], // nagas [ "Red Naga Spawn", 4, "1", [ "Bite:1d4" ], 3, 28, 10, 6, 0, 0, 0, true, 500, 100, large, [ fire, poison ], [ fire, .1, poison, .1] ], [ "Black Naga Spawn", 4, "1", [ "Bite:1d4" ], 3, 28, 10, 6, 0, 0, 0, true, 500, 100, large, [ acid, poison, petrify ], [ poison, .2] ], [ "Golden Naga Spawn", 4, "1", [ "Bite:1d4" ], 3, 28, 10, 6, 0, 0, 0, true, 500, 100, large, [ poison ], [ poison, .2] ], [ "Golden Naga Spawn", 4, "1", [ "Bite:1d4" ], 3, 28, 10, 6, 0, 0, 0, true, 500, 100, large, [ poison ], [ poison, .2] ], [ "Red Naga", 8, "1", [ "Bite:2d4", "Breath:2d6"], 6, 82, 12, 4, 0, -4, 1, true, 2600, 400, huge, [ fire, poison ], [ fire, .2, poison, .2 ] ], [ "Black Naga", 10, "1", [ "Bite:2d6"], 8, 132, 14, 2, 10, 4, 1, true, 2600, 400, huge, [ poison, acid, petrify ], [ poison, .2 ]], [ "Golden Naga", 13, "1", [ "Bite:2d6", "Magic:4d6"], 10, 239, 14, 2, 70, 5, 1, true, 2600, 400, huge, [ poison ], [ poison, .2 ]], [ "Guardian Naga", 16, "1", [ "Bite:1d6", "Spit:1d6", "Hug:2d4"],12, 295, 14, 2, 70, 7, 1, true, 2600, 400, huge, [ poison ], [ poison, .2 ]], // ogres [ "Ogre" ], [ "Ogre Lord" ], [ "Ogre King" ], // puddings and amoeboids [ "Gray Ooze", 4, "1", [ "Bite:2d8" ], 3, 28, 1, 8, 0, 0, 2, true, 500, 250, medium, [ fire, cold, poison, acid, petrify ], [ poison, .07, cold, .07, fire, .07 ] ], [ "Brown Pudding" ], [ "Black Pudding" ], [ "Green Slime" ], // quantum mechanic [ "Quantum Mechanic" ], // rust monster and disenchanter [ "Rust Monster" ], [ "Disenchanter" ], // snakes [ "Garter Snake", 3, "1", [ "Bite:1d2" ], 1, 8, 8, 8, 0, 0, 1, true, 50, 60, tiny, null, null ], [ "Snake" ], [ "Water Moccasin" ], [ "Pit Viper" ], [ "Python" ], [ "Cobra" ], // trolls [ "Troll" ], [ "Ice Troll" ], [ "Rock Troll" ], [ "Water Troll" ], [ "Olog-Hai" ], // umber hulk [ "Umber Hulk" ], // vampires [ "Vampire" ], [ "Vampire Lord" ], [ "Vampire 2?" ], [ "Vlad the Impaler" ], // wraiths [ "Barrow Wight" ], [ "Wraith" ], [ "Nazgul" ], // xorn [ "Xorn" ], // apelike creatures [ "Monkey" ], [ "Ape" ], [ "Owlbear" ], [ "Yeti" ], [ "Carnivorous Ape" ], [ "Sasquatch" ], // zombies [ "Kobold Zombie" ], [ "Gnome Zombie" ], [ "Orc Zombie" ], [ "Dwarf Zombie" ], [ "Elf Zombie" ], [ "Human Zombie" ], [ "Ettin Zombie" ], [ "Giant Zombie" ], [ "Ghoul" ], [ "Skeleton" ], // golems [ "Straw Golem", 4, "1", [ "Claw:2x1d2" ], 3, 28, 12, 10, 0, 0, 1, false, 400, 0, large, [ sleep, poison ], null ], [ "Paper Golem" ], [ "Rope Golem" ], [ "Gold Golem" ], [ "Leather Golem" ], [ "Wood Golem" ], [ "Flesh Golem" ], [ "Clay Golem" ], [ "Stone Golem" ], [ "Glass Golem" ], [ "Iron Golem" ], // humans and elves [ "Human" ], [ "Wererat" ], [ "Werejackal" ], [ "Werewolf" ], [ "Elf" ], [ "Woodland-Elf" ], [ "Green-Elf" ], [ "Grey-Elf" ], [ "Elf-Lord" ], [ "Elvenking" ], [ "Doppelganger" ], [ "Nurse" ], [ "Shopkeeper" ], [ "Guard" ], [ "Prisoner" ], [ "Oracle" ], [ "Aligned Priest" ], [ "High Priest" ], [ "Soldier" ], [ "Sergeant" ], [ "Lieutenant" ], [ "Captain" ], [ "Watchman" ], [ "Watch Captain" ], [ "Medusa" ], [ "Wizard of Yendor" ], [ "Croesus" ], // ghosts and shades [ "Ghost" ], [ "Shade" ], // major demons [ "Water Demon" ], [ "Horned Devil" ], [ "Succubus" ], [ "Incubus" ], [ "Medusa" ], [ "Erinys" ], [ "Barbed Devil" ], [ "Marilith" ], [ "Vrock" ], [ "Hezrou" ], [ "Bone Devil" ], [ "Ice Devil" ], [ "Nalfeshnee" ], [ "Pit Fiend" ], [ "Balrog" ], [ "Jubilex" ], [ "Yeenoghu" ], [ "Orcus" ], [ "Geryon" ], [ "Dispater" ], [ "Baalzebub" ], [ "Asmodeus" ], [ "Demogorgon" ], [ "Death" ], [ "Pestilence" ], [ "Famine" ], [ "Mail Demon" ], [ "Djinni" ], [ "Sandestin" ], // sea monsters [ "Jellyfish" ], [ "Piranha" ], [ "Shark" ], [ "Giant Eel" ], [ "Electric Eel" ], [ "Kraken" ], // lizards [ "Newt", 1, "1", [ "Bite:1d2" ], 0, 1, 6, 8, 0, 0, 5, true, 10, 20, tiny, null, null ], [ "Gecko", 2, "1", [ "Bite:1d3" ], 1, 8, 6, 8, 0, 0, 5, true, 10, 20, tiny, null, null ], [ "Iguana", 3, "1", [ "Bite:1d4" ], 2, 17, 6, 7, 0, 0, 5, true, 30, 30, tiny, null, null ], [ "Baby Crocodile" ], [ "Lizard" ], [ "Chameleon" ], [ "Crocodile" ], [ "Salamander" ], [ "Long Worm Entity" ], // player monsters [ "Archeologist" ], [ "Barbarian" ], [ "Caveman" ], [ "Cavewoman" ], [ "Healer" ], [ "Knight" ], [ "Monk" ], [ "Priest" ], [ "Priestess" ], [ "Ranger" ], [ "Rogue" ], [ "Samurai" ], [ "Tourist" ], [ "Valkyrie" ], [ "Wizard" ], // quest leaders [ "Unknown Quest Leader 1?" ], [ "Lord Carnarvon" ], [ "Pelias" ], [ "Shaman Karnov" ], [ "Unknown Quest Leader 2?" ], [ "Hippocrates" ], [ "King Arthur" ], [ "Grand Master" ], [ "Arch Priest" ], [ "Orion" ], [ "Master of Thieves" ], [ "Lord Sato" ], [ "Twoflower" ], [ "Norn" ], [ "Neferet the Green" ], // quest nemeses [ "Minion of Huhetotl" ], [ "Thoth Amon" ], [ "Chromatic Dragon" ], [ "Unknown Quest Nemesis 1?" ], [ "Cyclops" ], [ "Ixoth" ], [ "Master Kaen" ], [ "Nalzok" ], [ "Scorpius" ], [ "Master Assassin" ], [ "Ashikaga Takauji" ], [ "Lord Surtur" ], [ "The Dark One" ], // quest guardians [ "Student" ], [ "Chieftan" ], [ "Neanderthal" ], [ "Unknown Quest Guardian 1?" ], [ "Attendant" ], [ "Page" ], [ "Abbot" ], [ "Acolyte" ], [ "Hunter" ], [ "Thug" ], [ "Ninja" ], [ "Roshi" ], [ "Guide" ], [ "Warrior" ], [ "Apprentice" ], ]; return agentDatas; } DemoData.buildRoles = function() { var skillDefns = DemoData.buildSkillDefns(); var returnValues = [ new Role ( "Wizard", // ranks [ new Role_Rank("Evoker", 0, null), ], // skills [ new Role_Skill(skillDefns["Attack Spells"], 4), new Role_Skill(skillDefns["Dagger"], 4), new Role_Skill(skillDefns["Quarterstaff"], 4), ] ), ]; return returnValues; } DemoData.buildSkillDefns = function() { var returnValues = [ new SkillDefn("Attack Spells"), new SkillDefn("Dagger"), new SkillDefn("Quarterstaff"), ]; returnValues.addLookups("name"); return returnValues; } DemoData.buildSpellDefns = function() { var returnValues = [ // todo ]; returnValues.addLookups("name"); return returnValues; } DemoData.buildTraitDefns = function() { var returnValues = [ new TraitDefn("Strength"), new TraitDefn("Dexterity"), new TraitDefn("Willpower"), new TraitDefn("Constitution"), new TraitDefn("Charisma"), ]; returnValues.addLookups("name"); return returnValues; } DemoData.buildMapTerrainsMines = function(imagesForTiles) { return DemoData.buildMapTerrainsDungeon(imagesForTiles); } DemoData.buildMapTerrainsDungeon = function(imagesForTiles) { this.Floor = new MapTerrain("Floor", ".", 1, false, "#00aa00", imagesForTiles["Floor"]); this.Stone = new MapTerrain("Stone", "x", 1000000, true, "#000000", imagesForTiles["Stone"]); this.WallCornerNorth = new MapTerrain("WallCornerNorth", "+", 1000000, true, "#0000aa", imagesForTiles["WallDungeonCornerNorth"]); this.WallCornerSouth = new MapTerrain("WallCornerSouth", "*", 1000000, true, "#0000aa", imagesForTiles["WallDungeonCornerSouth"]); this.WallEastWest = new MapTerrain("WallEastWest", "-", 1000000, true, "#0000aa", imagesForTiles["WallDungeonEastWest"]); this.WallNorthSouth = new MapTerrain("WallNorthSouth", "|", 1000000, true, "#0000aa", imagesForTiles["WallDungeonNorthSouth"]); var terrains = [ this.Stone, this.Floor, this.WallCornerNorth, this.WallCornerSouth, this.WallEastWest, this.WallNorthSouth, ]; terrains.addLookups("name"); terrains.addLookups("codeChar"); return terrains; } DemoData.buildMapTerrainsHades = function(imagesForTiles) { return DemoData.buildMapTerrainsDungeon(imagesForTiles); } DemoData.buildMapTerrainsLabyrinth = function(imagesForTiles) { return DemoData.buildMapTerrainsDungeon(imagesForTiles); } DemoData.buildMapTerrainsPuzzle = function(imagesForTiles) { return DemoData.buildMapTerrainsDungeon(imagesForTiles); } DemoData.buildMapTerrainsThrowback = function(imagesForTiles) { return DemoData.buildMapTerrainsDungeon(imagesForTiles); } DemoData.buildUniverseDefn = function(imagesForTiles, imagesForTilesTransparent) { var imagesOpaque = DemoData.buildImageLookup(imagesForTiles); var imagesTransparent = DemoData.buildImageLookup(imagesForTilesTransparent); var actions = DemoData.buildActions(); var activityDefns = DemoData.buildActivityDefns(); var categories = DemoData.buildCategories(); var entityDefnGroups = DemoData.buildEntityDefnGroups(imagesOpaque, activityDefns, categories); var venueDefns = DemoData.buildVenueDefns(imagesOpaque, actions, categories); var Branch = UniverseDefnVenueStructureBranch; var branchesMain = [ /* new Branch ( "Tutorial", "Tutorial", false, new Range(0, 0), new Range(1, 1), [] ), */ new Branch ( "DungeonShallow", "Dungeon", true, new Range(0, 0), new Range(5, 6), [ new Branch ( "MinesShallow", "Mines", false, new Range(1, 4), new Range(2, 4), [] ), new Branch ( "MinesTown", "MinesTown", true, new Range(0, 0), new Range(1, 1), [] ), new Branch ( "MinesDeep", "Mines", true, new Range(0, 0), new Range(2, 4), [] ), new Branch ( "MinesBottom", "MinesBottom", true, new Range(0, 0), new Range(1, 1), [] ), ] ), new Branch ( "Oracle", "Oracle", true, new Range(0, 0), new Range(1, 1), [] ), new Branch ( "DungeonDeep", "Dungeon", true, new Range(0, 0), new Range(5, 6), [ new Branch ( "Puzzle", "Puzzle", false, new Range(1, 4), new Range(2, 4), [] ), ] ), new Branch ( "Labyrinth", "Labyrinth", true, new Range(0, 0), new Range(3, 5), [] ), new Branch ( "Island", "Island", true, new Range(0, 0), new Range(1, 1), [] ), new Branch ( "Fortress", "Fortress", true, new Range(0, 0), new Range(1, 1), [] ), new Branch ( "Limbo", "Limbo", true, new Range(0, 0), new Range(1, 1), [] ), new Branch ( "Hades", "Hades", true, new Range(0, 0), new Range(10, 20), [] ), new Branch ( "Depths", "Dungeon", // todo true, new Range(0, 0), new Range(10, 20), [] ), ]; var venueStructure = new UniverseDefnVenueStructure ( new Branch ( "Root", "Dungeon", // hack false, new Range(0, 0), new Range(0, 0), branchesMain ) ) var returnValue = new UniverseDefn ( "UniverseDefn0", actions, activityDefns, categories, entityDefnGroups, venueDefns, venueStructure, // buildVenues function() { var returnValues = this.venueStructure.branchRoot.buildVenuesAndAddToList ( this, [], 0 ) return returnValues; } ); return returnValue; } DemoData.buildVenueDefns = function(images, actions, categories) { var inputBindings = [ new InputBinding(InputKey.Instances.A, actions["Move West"].name), new InputBinding(InputKey.Instances.C, actions["Move Southeast"].name), new InputBinding(InputKey.Instances.D, actions["Move East"].name), new InputBinding(InputKey.Instances.E, actions["Move Northeast"].name), new InputBinding(InputKey.Instances.F, actions["Use Selected Item"].name), new InputBinding(InputKey.Instances.G, actions["Pick Up Item"].name), new InputBinding(InputKey.Instances.Q, actions["Move Northwest"].name), new InputBinding(InputKey.Instances.R, actions["Drop Selected Item"].name), new InputBinding(InputKey.Instances.T, actions["Target Selected Item"].name), new InputBinding(InputKey.Instances.U, actions["Use Emplacement"].name), new InputBinding(InputKey.Instances.W, actions["Move North"].name), new InputBinding(InputKey.Instances.X, actions["Move South"].name), new InputBinding(InputKey.Instances.Z, actions["Move Southwest"].name), new InputBinding(InputKey.Instances.BracketClose, actions["Select Next Item"].name), new InputBinding(InputKey.Instances.BracketOpen, actions["Select Previous Item"].name), new InputBinding(InputKey.Instances.Period, actions["Wait"].name), ]; var mapTerrainsDungeon = DemoData.buildMapTerrainsDungeon(images); var returnValues = [ new VenueDefn ( "Dungeon", categories, mapTerrainsDungeon, inputBindings, DemoData.venueGenerateDungeon ), new VenueDefn ( "Fortress", categories, mapTerrainsDungeon, inputBindings, DemoData.venueGenerateFortress ), new VenueDefn ( "Hades", categories, DemoData.buildMapTerrainsHades(images), inputBindings, DemoData.venueGenerateHades ), new VenueDefn ( "Mines", categories, DemoData.buildMapTerrainsMines(images), inputBindings, DemoData.venueGenerateMines ), new VenueDefn ( "MinesTown", categories, DemoData.buildMapTerrainsMines(images), inputBindings, DemoData.venueGenerateMines ), new VenueDefn ( "MinesBottom", categories, DemoData.buildMapTerrainsMines(images), inputBindings, DemoData.venueGenerateMines ), new VenueDefn ( "Island", categories, mapTerrainsDungeon, inputBindings, DemoData.venueGenerateIsland ), new VenueDefn ( "Labyrinth", categories, DemoData.buildMapTerrainsLabyrinth(images), inputBindings, DemoData.venueGenerateLabyrinth ), new VenueDefn ( "Limbo", categories, mapTerrainsDungeon, inputBindings, DemoData.venueGenerateLimbo ), new VenueDefn ( "Oracle", categories, mapTerrainsDungeon, inputBindings, DemoData.venueGenerateLimbo ), new VenueDefn ( "Puzzle", categories, DemoData.buildMapTerrainsPuzzle(images), inputBindings, DemoData.venueGeneratePuzzle ), new VenueDefn ( "SingleChamber", categories, mapTerrainsDungeon, inputBindings, DemoData.venueGenerateSingleChamber ), new VenueDefn ( "Throwback", categories, DemoData.buildMapTerrainsThrowback(images), inputBindings, DemoData.venueGenerateThrowback ), new VenueDefn ( "Tutorial", categories, mapTerrainsDungeon, inputBindings, DemoData.venueGenerateTutorial ), ]; return returnValues; } DemoData.venueGenerateDungeon = function(universeDefn, venueDefn, venueIndex, venueDepth) { var entityDefnGroups = universeDefn.entityDefnGroups; var entityDefns = universeDefn.entityDefns; entityDefns.addLookups("name"); var mapSizeInCells = new Coords(64, 64); var mapCellsAsStrings = []; var cellPos = new Coords(0, 0); var terrains = venueDefn.terrains; terrainCodeChar = terrains.Stone.codeChar; for (var y = 0; y < mapSizeInCells.y; y++) { var mapCellRowAsString = ""; for (var x = 0; x < mapSizeInCells.x; x++) { mapCellRowAsString += terrainCodeChar; } mapCellsAsStrings.push(mapCellRowAsString); } var numberOfRooms = 12; var roomSizeMin = new Coords(4, 4); var roomSizeMax = new Coords(13, 13); var roomSizeRange = roomSizeMax.clone().subtract(roomSizeMin); terrainCodeChar = terrains.Floor.codeChar; var roomBoundsSetSoFar = []; while (roomBoundsSetSoFar.length < numberOfRooms) { var doesRoomOverlapAnother = true; while (doesRoomOverlapAnother == true) { var roomSize = roomSizeRange.clone().random().add ( roomSizeMin ); var roomSizePlusOnes = roomSize.clone().add ( Coords.Instances.Ones ); var roomPosRange = mapSizeInCells.clone().subtract ( roomSize ).subtract ( Coords.Instances.Twos ); var roomPos = roomPosRange.clone().random().add ( Coords.Instances.Ones ); doesRoomOverlapAnother = Bounds.doBoundsInSetsOverlap ( [ new Bounds(roomPos, roomSizePlusOnes) ], roomBoundsSetSoFar ); } var roomBounds = new Bounds(roomPos, roomSize); roomBoundsSetSoFar.push(roomBounds); } var rooms = []; for (var r = 0; r < numberOfRooms; r++) { var roomBounds = roomBoundsSetSoFar[r]; var room = new RoomData(roomBounds.pos, roomBounds.size); rooms.push(room); } for (var r = 0; r < numberOfRooms; r++) { var room = rooms[r]; var roomPos = room.bounds.pos; var roomSize = room.bounds.size; var roomMax = roomPos.clone().add(room.bounds.size); for (var y = roomPos.y; y < roomMax.y; y++) { var mapCellRowAsString = mapCellsAsStrings[y]; for (var x = roomPos.x; x < roomMax.x; x++) { if (x == roomPos.x || x == roomMax.x - 1) { if (y == roomPos.y) { terrainCodeChar = terrains.WallCornerNorth.codeChar; } else if (y == roomMax.y - 1) { terrainCodeChar = terrains.WallCornerSouth.codeChar; } else { terrainCodeChar = terrains.WallNorthSouth.codeChar; } } else if (y == roomPos.y || y == roomMax.y - 1) { terrainCodeChar = terrains.WallEastWest.codeChar; } else { terrainCodeChar = terrains.Floor.codeChar; } mapCellRowAsString = mapCellRowAsString.substring(0, x) + terrainCodeChar + mapCellRowAsString.substring(x + 1); } mapCellsAsStrings[y] = mapCellRowAsString; } } var roomsConnected = [ rooms[0] ]; var roomsToConnect = []; for (var r = 1; r < numberOfRooms; r++) { roomsToConnect.push(rooms[r]); } var doorwayPositions = []; while (roomsToConnect.length > 0) { var nearestRoomsSoFar = null; var distanceBetweenNearestRoomsSoFar = null; for (var r = 0; r < roomsConnected.length; r++) { var roomConnected = roomsConnected[r]; var roomConnectedCenter = roomConnected.bounds.center; for (var s = 0; s < roomsToConnect.length; s++) { var roomToConnect = roomsToConnect[s]; var roomToConnectCenter = roomToConnect.bounds.center; var distance = roomToConnectCenter.clone().subtract ( roomConnectedCenter ).absolute().sumOfXAndY(); if ( nearestRoomsSoFar == null || distance < distanceBetweenNearestRoomsSoFar ) { nearestRoomsSoFar = [ roomConnected, roomToConnect, ]; distanceBetweenNearestRoomsSoFar = distance; } } } var roomConnected = nearestRoomsSoFar[0]; var roomToConnect = nearestRoomsSoFar[1]; var roomConnectedBounds = roomConnected.bounds; var roomToConnectBounds = roomToConnect.bounds; var fromPos = roomConnectedBounds.pos.clone().add ( roomConnectedBounds.size.clone().subtract ( Coords.Instances.Twos ).random() ).add ( Coords.Instances.Ones ); var toPos = roomToConnectBounds.pos.clone().add ( roomToConnectBounds.size.clone().subtract ( Coords.Instances.Twos ).random() ).add ( Coords.Instances.Ones ); var displacementToRoomToConnect = toPos.clone().subtract ( fromPos ); var directionToRoomToConnect = displacementToRoomToConnect.clone(); var dimensionIndexToClear = directionToRoomToConnect.dimensionIndexOfSmallest(0); if (Bounds.doBoundsOverlapInDimension(roomConnectedBounds, roomToConnectBounds, 0) == true) { dimensionIndexToClear = 0; } else if (Bounds.doBoundsOverlapInDimension(roomConnectedBounds, roomToConnectBounds, 1) == true) { dimensionIndexToClear = 1; } directionToRoomToConnect.dimension_Set ( dimensionIndexToClear, 0 // valueToSet ).directions(); if (directionToRoomToConnect.x > 0) { fromPos.x = roomConnectedBounds.max.x; toPos.x = roomToConnectBounds.pos.x - 1; } else if (directionToRoomToConnect.x < 0) { fromPos.x = roomConnectedBounds.pos.x - 1; toPos.x = roomToConnectBounds.max.x; } else if (directionToRoomToConnect.y > 0) { fromPos.y = roomConnectedBounds.max.y; toPos.y = roomToConnectBounds.pos.y - 1; } else if (directionToRoomToConnect.y < 0) { fromPos.y = roomConnectedBounds.pos.y - 1; toPos.y = roomToConnectBounds.max.y; } doorwayPositions.push(fromPos.clone().subtract(directionToRoomToConnect)); doorwayPositions.push(toPos.clone().add(directionToRoomToConnect)); var cellPos = fromPos.clone(); terrainCodeChar = terrains.Floor.codeChar; var mapCellRowAsString = mapCellsAsStrings[cellPos.y]; var terrainCodeCharsForWalls = terrains.WallEastWest.codeChar + terrains.WallNorthSouth.codeChar; while (displacementToRoomToConnect.equals(Coords.Instances.Zeroes) == false) { var mapCellRowAsString = mapCellsAsStrings[cellPos.y]; var terrainCodeCharExisting = mapCellRowAsString[cellPos.x]; mapCellRowAsString = mapCellRowAsString.substring(0, cellPos.x) + terrainCodeChar + mapCellRowAsString.substring(cellPos.x + 1); mapCellsAsStrings[cellPos.y] = mapCellRowAsString; displacementToRoomToConnect.overwriteWith ( toPos ).subtract ( cellPos ); directionToRoomToConnect.overwriteWith ( displacementToRoomToConnect ).dimension_Set ( directionToRoomToConnect.dimensionIndexOfSmallest(0), 0 // valueToSet ).directions(); cellPos.add(directionToRoomToConnect); } roomsToConnect.splice(roomsToConnect.indexOf(roomToConnect), 1); roomsConnected.push(roomToConnect); } for (var i = 0; i < doorwayPositions.length; i++) { var cellPos = doorwayPositions[i]; var mapCellRowAsString = mapCellsAsStrings[cellPos.y]; mapCellRowAsString = mapCellRowAsString.substring(0, cellPos.x) + terrainCodeChar + mapCellRowAsString.substring(cellPos.x + 1); mapCellsAsStrings[cellPos.y] = mapCellRowAsString; } var entities = [ // stairs new Entity ( "StairsUp", entityDefns["StairsUp"].name, rooms[0].bounds.center.clone().floor(), // propertyValues [ new PortalData ( "Venue" + (venueIndex - 1), "StairsDown" ), ] ), new Entity ( "StairsDown", entityDefns["StairsDown"].name, rooms[1].bounds.center.clone().floor(), // propertyValues [ new PortalData ( "Venue" + (venueIndex + 1), "StairsUp" ), ] ), // movers // new Entity("Enemy 0", entityDefns["Giant Ant"], rooms[1].bounds.center.clone().floor()), Entity.fromDefn ( "Mover Generator", MoverGenerator.EntityDefn, null // pos ), ]; for (var i = 0; i < doorwayPositions.length; i++) { var entityForDoor = new Entity ( "Door" + i, entityDefns["Door"].name, doorwayPositions[i] ); entities.push(entityForDoor); } var chancesForItemPerRoom = 2; var probabilityOfItemPerChance = 1; var entityDefnGroupsForItems = [ entityDefnGroups["Armor"], entityDefnGroups["Food"], entityDefnGroups["Potions"], entityDefnGroups["Scrolls"], entityDefnGroups["Spellbooks"], entityDefnGroups["Stones"], entityDefnGroups["Tools"], entityDefnGroups["Wands"], entityDefnGroups["Weapons"], ]; var sumOfFrequenciesForAllGroups = 0; for (var g = 0; g < entityDefnGroupsForItems.length; g++) { var entityDefnGroup = entityDefnGroupsForItems[g]; sumOfFrequenciesForAllGroups += entityDefnGroup.relativeFrequency; } for (var r = 0; r < numberOfRooms; r++) { var room = rooms[r]; for (var c = 0; c < chancesForItemPerRoom; c++) { var randomValue = Globals.Instance.randomizer.getNextRandom(); if (randomValue <= probabilityOfItemPerChance) { randomValue = Globals.Instance.randomizer.getNextRandom() * sumOfFrequenciesForAllGroups; var sumOfFrequenciesForGroupsSoFar = 0; var entityDefnGroupIndex = 0; for (var g = 0; g < entityDefnGroupsForItems.length; g++) { var entityDefnGroup = entityDefnGroupsForItems[g]; sumOfFrequenciesForGroupsSoFar += entityDefnGroup.relativeFrequency; if (sumOfFrequenciesForGroupsSoFar >= randomValue) { entityDefnGroupIndex = g; break; } } var entityDefnGroup = entityDefnGroupsForItems[entityDefnGroupIndex]; var entityDefns = entityDefnGroup.entityDefns; var entityDefnIndex = Math.floor ( Globals.Instance.randomizer.getNextRandom() * entityDefns.length ); var entityDefnForItem = entityDefns [ entityDefnIndex ]; var pos = room.bounds.size.clone().subtract ( Coords.Instances.Twos ).random().add ( room.bounds.pos ).add ( Coords.Instances.Ones ) var entityForItem = new Entity ( entityDefnForItem.name, entityDefnForItem.name, pos ); entities.push(entityForItem); } } } var map = new Map ( "Venue" + venueIndex + "Map", venueDefn.terrains, new Coords(16, 16), // hack - cellSizeInPixels mapCellsAsStrings ); var returnValue = new Venue ( "Venue" + venueIndex, venueDepth, venueDefn, new Coords(480, 480), // sizeInPixels map, entities ); return returnValue; } DemoData.venueGenerateFortress = function(universe, venueDefn, venueIndex, venueDepth) { return DemoData.venueGenerateDungeon(universe, venueDefn, venueIndex, venueDepth); } DemoData.venueGenerateHades = function(universe, venueDefn, entityDefns, venueIndex, venueDepth) { return DemoData.venueGenerateDungeon(universe, venueDefn, venueIndex, venueDepth); } DemoData.venueGenerateIsland = function(universe, venueDefn, venueIndex, venueDepth) { return DemoData.venueGenerateDungeon(universe, venueDefn, venueIndex, venueDepth); } DemoData.venueGenerateMines = function(universe, venueDefn, venueIndex, venueDepth) { return DemoData.venueGenerateDungeon(universe, venueDefn, venueIndex, venueDepth); } DemoData.venueGenerateOracle = function(universe, venueDefn, venueIndex, venueDepth) { return DemoData.venueGenerateDungeon(universe, venueDefn, venueIndex, venueDepth); } DemoData.venueGenerateLabyrinth = function(universe, venueDefn, venueIndex, venueDepth) { return DemoData.venueGenerateDungeon(universe, venueDefn, venueIndex, venueDepth); } DemoData.venueGenerateLimbo = function(universe, venueDefn, venueIndex, venueDepth) { return DemoData.venueGenerateDungeon(universe, venueDefn, venueIndex, venueDepth); } DemoData.venueGeneratePuzzle = function(universe, venueDefn, venueIndex, venueDepth) { return DemoData.venueGenerateDungeon(universe, venueDefn, venueIndex, venueDepth); } DemoData.venueGenerateSingleChamber = function(universe, venueDefn, venueIndex, venueDepth) { return DemoData.venueGenerateDungeon(universe, venueDefn, venueIndex, venueDepth); } DemoData.venueGenerateThrowback = function(universe, venueDefn, venueIndex, venueDepth) { return DemoData.venueGenerateDungeon(universe, venueDefn, venueIndex, venueDepth); } DemoData.venueGenerateTutorial = function(universeDefn, venueDefn, venueIndex, venueDepth) { var sizeInCells = new Coords(16, 16); var stringForTopAndBottomRows = "x"; var stringForOtherRows = "x"; for (var x = 1; x < sizeInCells.x - 1; x++) { stringForTopAndBottomRows += "x"; stringForOtherRows += "."; } stringForTopAndBottomRows += "x"; stringForOtherRows += "x"; var mapCellsAsStrings = []; mapCellsAsStrings.push(stringForTopAndBottomRows); for (var y = 1; y < sizeInCells.y - 1; y++) { mapCellsAsStrings.push(stringForOtherRows); } mapCellsAsStrings.push(stringForTopAndBottomRows); var map = new Map ( "Venue" + venueIndex + "Map", venueDefn.terrains, new Coords(16, 16), // hack - cellSizeInPixels mapCellsAsStrings ); var entityDefns = universeDefn.entityDefns; var entities = [ // stairs new Entity ( "StairsDown", entityDefns["StairsDown"].name, sizeInCells.clone().subtract(Coords.Instances.Ones), // propertyValues [ new PortalData ( "Venue" + (venueIndex + 1), "StairsUp" ), ] ), ]; var returnValue = new Venue ( "Venue" + venueIndex, venueDepth, venueDefn, new Coords(480, 480), // sizeInPixels map, entities ); var locationForMessages = new Location(returnValue.name, new Coords(0, 0)); //Font.spawnMessageFixed("Tutorial", locationForMessages); return returnValue; } DemoData.buildImageLookup = function(imagesForTiles) { var returnValue = []; var tileNamesAndPositions = [ // terrains [ "Floor", new Coords(8, 21) ], [ "Stone", new Coords(29, 20) ], [ "WallCaveCornerNorth", new Coords(15, 25) ], [ "WallCaveCornerSouth", new Coords(17, 25) ], [ "WallCaveEastWest", new Coords(14, 25) ], [ "WallCaveNorthSouth", new Coords(13, 25) ], [ "WallDungeonCornerNorth", new Coords(32, 20) ], [ "WallDungeonCornerSouth", new Coords(34, 20) ], [ "WallDungeonEastWest", new Coords(31, 20) ], [ "WallDungeonNorthSouth", new Coords(30, 20) ], [ "WallHadesCornerNorth", new Coords(26, 25) ], [ "WallHadesCornerSouth", new Coords(28, 25) ], [ "WallHadesEastWest", new Coords(25, 25) ], [ "WallHadesNorthSouth", new Coords(24, 25) ], [ "WallPuzzleCornerNorth", new Coords(8, 26) ], [ "WallPuzzleCornerSouth", new Coords(10, 26) ], [ "WallPuzzleEastWest", new Coords(7, 26) ], [ "WallPuzzleNorthSouth", new Coords(6, 26) ], // emplacements [ "Blood", new Coords(3, 4) ], [ "Door", new Coords(4, 21) ], [ "Gravestone", new Coords(16, 21) ], [ "StairsUp", new Coords(11, 21) ], [ "StairsDown", new Coords(12, 21) ], // items - unsorted [ "Chest", new Coords(34, 9) ], [ "Coins", new Coords(29, 19) ], [ "Corpse", new Coords(36, 15) ], // items - foods [ "Eucalyptus Leaf", new Coords(3, 16) ], [ "Apple", new Coords(4, 16) ], [ "Orange", new Coords(5, 16) ], [ "Pear", new Coords(6, 16) ], [ "Melon", new Coords(7, 16) ], [ "Banana", new Coords(8, 16) ], [ "Carrot", new Coords(9, 16) ], [ "Sprig of Wolfsbane", new Coords(10, 16) ], [ "Garlic Clove", new Coords(11, 16) ], [ "Slime Mold", new Coords(12, 16) ], [ "Royal Jelly", new Coords(13, 16) ], [ "Cream Pie", new Coords(14, 16) ], [ "Candy Bar", new Coords(15, 16) ], [ "Fortune Cookie", new Coords(16, 16) ], [ "Pancake", new Coords(17, 16) ], [ "Lembas Wafer", new Coords(18, 16) ], [ "Cram Ration", new Coords(19, 16) ], [ "Food Ration", new Coords(20, 16) ], [ "K Ration", new Coords(21, 16) ], [ "C Ration", new Coords(22, 16) ], [ "Tin", new Coords(23, 16) ], // items - potions [ "Ruby Potion", new Coords(24, 16) ], [ "Pink Potion", new Coords(25, 16) ], [ "Orange Potion", new Coords(26, 16) ], [ "Yellow Potion", new Coords(27, 16) ], [ "Emerald Potion", new Coords(28, 16) ], [ "Dark Green Potion", new Coords(29, 16) ], [ "Sky Blue Potion", new Coords(30, 16) ], [ "Cyan Potion", new Coords(31, 16) ], [ "Brilliant Blue Potion", new Coords(32, 16) ], [ "Magenta Potion", new Coords(33, 16) ], [ "Purple-Red Potion", new Coords(34, 16) ], [ "Puce Potion", new Coords(35, 16) ], [ "Milky Potion", new Coords(36, 16) ], [ "Swirly Potion", new Coords(37, 16) ], [ "Bubbly Potion", new Coords(38, 16) ], [ "Smoky Potion", new Coords(39, 16) ], [ "Cloudy Potion", new Coords(39, 16) ], [ "Effervescent Potion", new Coords(0, 17) ], [ "Black Potion", new Coords(1, 17) ], [ "Golden Potion", new Coords(2, 17) ], [ "Brown Potion", new Coords(3, 17) ], [ "Fizzy Potion", new Coords(4, 17) ], [ "Dark Potion", new Coords(5, 17) ], [ "White Potion", new Coords(6, 17) ], [ "Murky Potion", new Coords(7, 17) ], [ "Clear Potion", new Coords(8, 17) ], // items - armor - helmets [ "Elven Leather Helmet", new Coords(25, 11) ], [ "Orcish Helmet", new Coords(26, 11) ], [ "Dwarvish Helmet", new Coords(27, 11) ], [ "Black Hat", new Coords(28, 11) ], [ "Cornuthaum", new Coords(29, 11) ], [ "Dunce Cap", new Coords(30, 11) ], [ "Cooking Pot", new Coords(31, 11) ], [ "Plumed Helmet", new Coords(32, 11) ], [ "Etched Helmet", new Coords(33, 11) ], [ "Crested Helmet", new Coords(34, 11) ], [ "Visored Helmet", new Coords(35, 11) ], // items - armor - entity armor [ "Gray Dragonscale Mail", new Coords(36, 11) ], [ "Silver Dragonscale Mail", new Coords(37, 11) ], [ "Rainbow Dragonscale Mail", new Coords(38, 11) ], [ "Red Dragonscale Mail", new Coords(39, 11) ], [ "White Dragonscale Mail", new Coords(0, 12) ], [ "Orange Dragonscale Mail", new Coords(1, 12) ], [ "Black Dragonscale Mail", new Coords(2, 12) ], [ "Blue Dragonscale Mail", new Coords(3, 12) ], [ "Green Dragonscale Mail", new Coords(4, 12) ], [ "Yellow Dragonscale Mail", new Coords(5, 12) ], [ "Gray Dragon Scales", new Coords(6, 12) ], [ "Silver Dragon Scales", new Coords(7, 12) ], [ "Rainbow Dragon Scales", new Coords(8, 12) ], [ "Red Dragon Scales", new Coords(9, 12) ], [ "White Dragon Scales", new Coords(10, 12) ], [ "Orange Dragon Scales", new Coords(11, 12) ], [ "Black Dragon Scales", new Coords(12, 12) ], [ "Blue Dragon Scales", new Coords(13, 12) ], [ "Green Dragon Scales", new Coords(14, 12) ], [ "Yellow Dragon Scales", new Coords(15, 12) ], [ "Plate Mail", new Coords(16, 12) ], [ "Crystal Plate Mail", new Coords(17, 12) ], [ "Bronze Plate Mail", new Coords(18, 12) ], [ "Armor1", new Coords(19, 12) ], [ "Armor2", new Coords(20, 12) ], [ "Elven Mithril Shirt", new Coords(21, 12) ], [ "Dwarven Mithril Shirt", new Coords(22, 12) ], [ "Armor3", new Coords(23, 12) ], [ "Orcish Chain Mail", new Coords(24, 12) ], [ "Armor4", new Coords(25, 12) ], [ "Studded Leather Armor", new Coords(26, 12) ], [ "Armor5", new Coords(27, 12) ], [ "Armor6", new Coords(28, 12) ], [ "Leather Armor", new Coords(29, 12) ], [ "Leather Jacket", new Coords(30, 12) ], [ "Hawaiian Shirt", new Coords(31, 12) ], [ "Tee Shirt", new Coords(32, 12) ], [ "Mummy Wrapping", new Coords(33, 12) ], [ "Elven Cloak", new Coords(34, 12) ], [ "Leather Cloak", new Coords(35, 12) ], [ "Hooded Cloak", new Coords(36, 12) ], [ "Oilskin Cloak", new Coords(37, 12) ], [ "Robe", new Coords(38, 12) ], [ "Apron", new Coords(39, 12) ], [ "Leather Cloak 2", new Coords(0, 13) ], [ "Tattered Cloak", new Coords(1, 13) ], [ "Opera Cloak", new Coords(2, 13) ], [ "Ornamental Cope", new Coords(3, 13) ], [ "Piece of Cloth", new Coords(4, 13) ], // items - armor - shields [ "ShieldSmall", new Coords(5, 13) ], [ "ShieldGreen", new Coords(6, 13) ], [ "ShieldWhiteHanded", new Coords(7, 13) ], [ "ShieldRedEyed", new Coords(8, 13) ], [ "ShieldLarge", new Coords(9, 13) ], [ "Small Round Shield", new Coords(10, 13) ], [ "Polished Shield", new Coords(11, 13) ], // items - armor - gloves [ "Padded Gloves", new Coords(12, 13) ], [ "Old Gloves", new Coords(13, 13) ], [ "Riding Gloves", new Coords(14, 13) ], [ "Snow Gloves", new Coords(15, 13) ], // items - armor - boots [ "Low Boots", new Coords(16, 13) ], [ "Dwarven Boots", new Coords(17, 13) ], [ "High Boots", new Coords(18, 13) ], [ "Combat Boots", new Coords(19, 13) ], [ "Jungle Boots", new Coords(20, 13) ], [ "Elven Boots", new Coords(21, 13) ], [ "Mud Boots", new Coords(22, 13) ], [ "Buckled Boots", new Coords(23, 13) ], [ "Riding Boots", new Coords(24, 13) ], [ "Snow Boots", new Coords(25, 13) ], // items - rings [ "Wooden Ring", new Coords(26, 13) ], [ "Granite Ring", new Coords(27, 13) ], [ "Moonstone Ring", new Coords(28, 13) ], [ "Clay Ring", new Coords(29, 13) ], [ "Shiny Ring", new Coords(30, 13) ], [ "Black Onyx Ring", new Coords(31, 13) ], [ "Opal Ring", new Coords(32, 13) ], [ "Tiger Eye Ring", new Coords(33, 13) ], [ "Emerald Ring", new Coords(34, 13) ], [ "Engagement Ring", new Coords(36, 13) ], [ "Bronze Ring", new Coords(37, 13) ], [ "Sapphire Ring", new Coords(38, 13) ], [ "Ruby Ring", new Coords(39, 13) ], [ "Diamond Ring", new Coords(0, 14) ], [ "Pearl Ring", new Coords(1, 14) ], [ "Iron Ring", new Coords(2, 14) ], [ "Brass Ring", new Coords(3, 14) ], [ "Copper Ring", new Coords(4, 14) ], [ "Twisted Ring", new Coords(5, 14) ], [ "Steel Ring", new Coords(6, 14) ], [ "Agate Ring", new Coords(7, 14) ], [ "Silver Ring", new Coords(8, 14) ], [ "Gold Ring", new Coords(9, 14) ], [ "Topaz Ring", new Coords(10, 14) ], [ "Ivory Ring", new Coords(11, 14) ], [ "Wire Ring", new Coords(12, 14) ], [ "Jade Ring", new Coords(13, 14) ], [ "Coral Ring", new Coords(14, 14) ], // items - scrolls [ "Scroll Titled 'Andova Begarin'", new Coords(10, 17) ], [ "Scroll Titled 'Daiyen Fooels'", new Coords(11, 17) ], [ "Scroll Titled 'Duam Xnaht'", new Coords(12, 17) ], [ "Scroll Titled 'Eblib Yloh'", new Coords(13, 17) ], [ "Scroll Titled 'Elam Ebow'", new Coords(14, 17) ], [ "Scroll Titled 'Foobie Bletch'", new Coords(15, 17) ], [ "Scroll Titled 'Garven Deh'", new Coords(16, 17) ], [ "Scroll Titled 'Hackem Muche'", new Coords(17, 17) ], [ "Scroll Titled 'Juyed Awk Yacc'", new Coords(18, 17) ], [ "Scroll Titled 'Kernod Wel'", new Coords(19, 17) ], [ "Scroll Titled 'Kirje'", new Coords(20, 17) ], [ "Scroll Titled 'Lep Gex Ven Zea'", new Coords(21, 17) ], [ "Scroll Titled 'NR 9'", new Coords(22, 17) ], [ "Scroll Titled 'Pratyavayah'", new Coords(23, 17) ], [ "Scroll Titled 'Prirutsenie'", new Coords(24, 17) ], [ "Scroll Titled 'Read Me'", new Coords(25, 17) ], [ "Scroll Titled 'Temov'", new Coords(26, 17) ], [ "Scroll Titled 'Tharr'", new Coords(27, 17) ], [ "Scroll Titled 'Ve Forbryderne'", new Coords(28, 17) ], [ "Scroll Titled 'Velox Neb'", new Coords(29, 17) ], [ "Scroll Titled 'Venzar Borgavve'", new Coords(30, 17) ], [ "Scroll Titled 'Verr Yed Horre'", new Coords(31, 17) ], [ "Scroll Titled 'Xixaxa Xoxaxa Xuxaxa'", new Coords(32, 17) ], [ "Scroll Titled 'Yum Yum'", new Coords(33, 17) ], [ "Scroll Titled 'Zelgo Mer'", new Coords(34, 17) ], // items - spellbooks [ "Parchment Spellbook", new Coords(37, 17) ], [ "Vellum Spellbook", new Coords(38, 17) ], [ "Ragged Spellbook", new Coords(39, 17) ], [ "Dogeared Spellbook", new Coords(0, 18) ], [ "Mottled Spellbook", new Coords(1, 18) ], [ "Stained Spellbook", new Coords(2, 18) ], [ "Cloth Spellbook", new Coords(3, 18) ], [ "Leather Spellbook", new Coords(4, 18) ], [ "White Spellbook", new Coords(5, 18) ], [ "Pink Spellbook", new Coords(6, 18) ], [ "Red Spellbook", new Coords(7, 18) ], [ "Orange Spellbook", new Coords(8, 18) ], [ "Yellow Spellbook", new Coords(9, 18) ], [ "Velvet Spellbook", new Coords(10, 18) ], [ "Light Green Spellbook", new Coords(11, 18) ], [ "Dark Green Spellbook", new Coords(12, 18) ], [ "Turquoise Spellbook", new Coords(13, 18) ], [ "Cyan Spellbook", new Coords(14, 18) ], [ "Light Blue Spellbook", new Coords(15, 18) ], [ "Dark Blue Spellbook", new Coords(16, 18) ], [ "Indigo Spellbook", new Coords(17, 18) ], [ "Magenta Spellbook", new Coords(18, 18) ], [ "Purple Spellbook", new Coords(19, 18) ], [ "Violet Spellbook", new Coords(20, 18) ], [ "Tan Spellbook", new Coords(21, 18) ], [ "Plaid Spellbook", new Coords(22, 18) ], [ "Light Brown Spellbook", new Coords(23, 18) ], [ "Dark Brown Spellbook", new Coords(24, 18) ], [ "Gray Spellbook", new Coords(25, 18) ], [ "Wrinkled Spellbook", new Coords(26, 18) ], [ "Dusty Spellbook", new Coords(27, 18) ], [ "Bronze Spellbook", new Coords(28, 18) ], [ "Copper Spellbook", new Coords(29, 18) ], [ "Silver Spellbook", new Coords(30, 18) ], [ "Gold Spellbook", new Coords(31, 18) ], [ "Glittering Spellbook", new Coords(32, 18) ], [ "Shining Spellbook", new Coords(33, 18) ], [ "Dull Spellbook", new Coords(34, 18) ], [ "Thin Spellbook", new Coords(35, 18) ], [ "Thick Spellbook", new Coords(36, 18) ], // items - stones [ "White Gem", new Coords(27, 19) ], [ "White Gem", new Coords(28, 19) ], [ "Red Gem", new Coords(29, 19) ], [ "Orange Gem", new Coords(30, 19) ], [ "Blue Gem", new Coords(31, 19) ], [ "Black Gem", new Coords(32, 19) ], [ "Green Gem", new Coords(33, 19) ], [ "Green Gem", new Coords(34, 19) ], [ "Yellow Gem", new Coords(35, 19) ], [ "Green Gem", new Coords(36, 19) ], [ "Brownish Gem", new Coords(37, 19) ], [ "Brownish Gem", new Coords(38, 19) ], [ "Black Gem", new Coords(39, 19) ], [ "White Gem", new Coords(0, 20) ], [ "Yellow Gem", new Coords(1, 20) ], [ "Red Gem", new Coords(2, 20) ], [ "Violet Gem", new Coords(3, 20) ], [ "Red Gem", new Coords(4, 20) ], [ "Violet Gem", new Coords(5, 20) ], [ "Black Gem", new Coords(6, 20) ], [ "Orange Gem", new Coords(7, 20) ], [ "Green Gem", new Coords(8, 20) ], [ "White Gem", new Coords(9, 20) ], [ "Blue Gem", new Coords(10, 20) ], [ "Red Gem", new Coords(11, 20) ], [ "Brownish Gem", new Coords(12, 20) ], [ "Orange Gem", new Coords(13, 20) ], [ "Yellow Gem", new Coords(14, 20) ], [ "Black Gem", new Coords(15, 20) ], [ "Green Gem", new Coords(16, 20) ], [ "Violet Gem", new Coords(17, 20) ], [ "Gray Stone", new Coords(18, 20) ], [ "Gray Stone", new Coords(19, 20) ], [ "Gray Stone", new Coords(20, 20) ], [ "Gray Stone", new Coords(21, 20) ], [ "Rock", new Coords(22, 20) ], // items - wands [ "Glass Wand", new Coords(39, 18) ], [ "Balsa Wand", new Coords(0, 19) ], [ "Crystal Wand", new Coords(1, 19) ], [ "Maple Wand", new Coords(2, 19) ], [ "Pine Wand", new Coords(3, 19) ], [ "Oak Wand", new Coords(4, 19) ], [ "Ebony Wand", new Coords(5, 19) ], [ "Marble Wand", new Coords(6, 19) ], [ "Tin Wand", new Coords(7, 19) ], [ "Brass Wand", new Coords(8, 19) ], [ "Copper Wand", new Coords(9, 19) ], [ "Silver Wand", new Coords(10, 19) ], [ "Platinum Wand", new Coords(11, 19) ], [ "Iridium Wand", new Coords(12, 19) ], [ "Zinc Wand", new Coords(13, 19) ], [ "Aluminum Wand", new Coords(14, 19) ], [ "Uranium Wand", new Coords(15, 19) ], [ "Iron Wand", new Coords(16, 19) ], [ "Steel Wand", new Coords(17, 19) ], [ "Hexagonal Wand", new Coords(18, 19) ], [ "Short Wand", new Coords(19, 19) ], [ "Runed Wand", new Coords(20, 19) ], [ "Long Wand", new Coords(21, 19) ], [ "Curved Wand", new Coords(22, 19) ], [ "Forked Wand", new Coords(23, 19) ], [ "Spiked Wand", new Coords(24, 19) ], [ "Jeweled Wand", new Coords(25, 19) ], // items - tools [ "Key", new Coords(32, 14) ], [ "Lockpick", new Coords(33, 14) ], [ "Credit Card", new Coords(34, 14) ], [ "Candle", new Coords(35, 14) ], [ "Candle2", new Coords(36, 14) ], [ "Lantern", new Coords(37, 14) ], [ "Oil Lamp", new Coords(38, 14) ], [ "Magic Lamp", new Coords(39, 14) ], [ "Expensive Camera", new Coords(0, 15) ], [ "Mirror", new Coords(1, 15) ], [ "Crystal Orb", new Coords(2, 15) ], [ "Eyeglasses", new Coords(3, 15) ], [ "Blindfold", new Coords(4, 15) ], [ "Towel", new Coords(5, 15) ], [ "Saddle", new Coords(6, 15) ], [ "Leash", new Coords(7, 15) ], [ "Stethoscope", new Coords(8, 15) ], [ "Tinning Kit", new Coords(9, 15) ], [ "Tin Opener", new Coords(10, 15) ], [ "Can of Grease", new Coords(11, 15) ], [ "Figurine", new Coords(12, 15) ], [ "Magic Marker", new Coords(13, 15) ], [ "Unarmed Land Mine", new Coords(14, 15) ], [ "Unarmed Bear Trap", new Coords(15, 15) ], [ "Tin Whistle", new Coords(16, 15) ], [ "Magic Whistle", new Coords(17, 15) ], [ "Flute", new Coords(18, 15) ], [ "Flute2", new Coords(19, 15) ], [ "Tooled Horn", new Coords(20, 15) ], [ "Horn of Cold", new Coords(21, 15) ], [ "Horn of Plenty", new Coords(22, 15) ], [ "Horn4", new Coords(23, 15) ], [ "Harp", new Coords(24, 15) ], [ "Harp2", new Coords(25, 15) ], [ "Bell", new Coords(26, 15) ], [ "Trumpet", new Coords(27, 15) ], [ "Drum", new Coords(28, 15) ], [ "Earthquake Drum", new Coords(29, 15) ], [ "Pickaxe", new Coords(30, 15) ], [ "Grappling Hook", new Coords(31, 15) ], [ "Unicorn Horn", new Coords(32, 15) ], [ "Candelabra", new Coords(33, 15) ], [ "Bell of Opening", new Coords(34, 15) ], // items - weapons [ "Arrow", new Coords(10, 10) ], [ "Silver Arrow", new Coords(10, 10) ], [ "Battle Axe", new Coords(22, 10) ], [ "Hand Axe", new Coords(21, 10) ], [ "Bow", new Coords(19, 11) ], [ "Bow2", new Coords(20, 11) ], [ "Bow3", new Coords(21, 11) ], [ "Bow4", new Coords(22, 11) ], [ "Sling", new Coords(23, 11) ], [ "Crossbow", new Coords(24, 11) ], [ "Crossbow Bolt", new Coords(16, 10) ], [ "Dagger", new Coords(12, 10) ], [ "Elven Dagger", new Coords(13, 10) ], [ "Orcish Dagger", new Coords(11, 10) ], [ "Silver Dagger", new Coords(14, 10) ], [ "Knife", new Coords(17, 10) ], [ "Polearm1", new Coords(10, 10) ], [ "Rapier0?", new Coords(15, 10) ], [ "Rapier1?", new Coords(18, 10) ], [ "Rapier2?", new Coords(20, 10) ], [ "Sword", new Coords(23, 10) ], [ "WormTooth", new Coords(19, 10) ], // movers [ "Rogue", new Coords(25, 8) ], [ "Player1", new Coords(26, 8) ], [ "Player2", new Coords(27, 8) ], [ "Goblin", new Coords(32, 1) ], ]; for (var i = 0; i < tileNamesAndPositions.length; i++) { var tileNameAndPosition = tileNamesAndPositions[i]; var tileName = tileNameAndPosition[0]; var tilePos = tileNameAndPosition[1]; var image = imagesForTiles[tilePos.y][tilePos.x]; image.name = tileName; returnValue.push(image); returnValue[tileName] = image; } var agentNames = DemoData.buildAgentDatas(); var tilePos = new Coords(0, 0); var imageSizeInTiles = new Coords(40, 27); for (var i = 0; i < agentNames.length; i++) { var tileName = agentNames[i][0]; var image = imagesForTiles[tilePos.y][tilePos.x]; image.name = tileName; returnValue.push(image); returnValue[tileName] = image; tilePos.x++; if (tilePos.x >= imageSizeInTiles.x) { tilePos.y++; tilePos.x = 0; } } var imagesForReticlesClockwiseFromE = []; var reticlePixelSetsAsStringArrays = [ [ "................", "................", "................", "................", "............w...", "............ww..", "............w.w.", "............w..w", "............w.w.", "............ww..", "............w...", "................", "................", "................", "................", "................", ], [ "................", "................", "................", "................", "................", "................", "................", "................", "................", "................", "................", "................", ".....wwwwwww....", "......w...w.....", ".......w.w......", "........w.......", ], [ "................", "................", "................", "................", "................", "...w............", "..ww............", ".w.w............", "w..w............", ".w.w............", "..ww............", "...w............", "................", "................", "................", "................", ], [ "........w.......", ".......w.w......", "......w...w.....", ".....wwwwwww....", "................", "................", "................", "................", "................", "................", "................", "................", "................", "................", "................", "................", ], ]; for (var i = 0; i < reticlePixelSetsAsStringArrays.length; i++) { var imageName = "Reticle" + i; var pixelsAsStrings = reticlePixelSetsAsStringArrays[i]; var imageForReticle = ImageHelper.buildImageFromStrings ( imageName, pixelsAsStrings ); returnValue[imageName] = imageForReticle; } return returnValue; } DemoData.buildFont = function() { var characterImages = ImageHelper.buildImagesFromStringArrays ( "Font", [ [ ".rrr..", "r...r.", "rrrrr.", "r...r.", "r...r.", ], [ "rrrr..", "r...r.", "rrrr..", "r...r.", "rrrr..", ], [ ".rrrr.", "r.....", "r.....", "r.....", ".rrrr.", ], [ "rrrr..", "r...r.", "r...r.", "r...r.", "rrrr..", ], [ "rrrrr.", "r.....", "rrrr..", "r.....", "rrrrr.", ], [ "rrrrr.", "r.....", "rrrr..", "r.....", "r.....", ], [ ".rrrr.", "r.....", "r..rr.", "r...r.", ".rrrr.", ], [ "r...r.", "r...r.", "rrrrr.", "r...r.", "r...r.", ], [ "rrrrr.", "..r...", "..r...", "..r...", "rrrrr.", ], [ ".rrrrr.", "....r..", "....r..", ".r..r..", "..rr...", ], [ "r...r.", "r..r..", "rrr...", "r..r..", "r...r.", ], [ "r.....", "r.....", "r.....", "r.....", "rrrrr.", ], [ "r...r.", "rr.rr.", "r.r.r.", "r...r.", "r...r.", ], [ "r...r.", "rr..r.", "r.r.r.", "r..rr.", "r...r.", ], [ ".rrr..", "r...r.", "r...r.", "r...r.", ".rrr..", ], [ "rrrr..", "r...r.", "rrrr..", "r.....", "r......", ], [ ".rrr..", "r...r.", "r...r.", ".rrr..", "..r...", ], [ "rrrr..", "r...r.", "rrrr..", "r..r..", "r...r.", ], [ ".rrrr.", "r.....", ".rrr..", "....r.", "rrrr..", ], [ "rrrrr.", "..r...", "..r...", "..r...", "..r...", ], [ "r...r.", "r...r.", "r...r.", "r...r.", ".rrr..", ], [ "r...r.", "r...r.", ".r.r..", ".r.r..", "..r...", ], [ "r...r.", "r...r.", "r.r.r.", "rr.rr.", "r...r.", ], [ "r...r.", ".r.r..", "..r...", ".r.r..", "r...r.", ], [ "r...r.", ".r.r..", "..r...", "..r...", "..r...", ], [ "rrrrr.", "...r..", "..r...", ".r....", "rrrrr.", ], // space [ "......", "......", "......", "......", "......", ], // numerals [ ".rrr..", "r...r.", "r.r.r.", "r...r.", ".rrr..", ], [ "..r...", ".rr...", "..r...", "..r...", "rrrrr.", ], [ "rrrr..", "....r.", ".rrrr.", "r.....", "rrrrr.", ], [ "rrrr..", "....r.", "..rr..", "....r.", "rrrr..", ], [ "r...r.", "r...r.", "rrrrr.", "....r.", "....r.", ], [ "rrrrr.", "r.....", "rrrr..", "....r.", "rrrr..", ], [ ".rrr..", "r.....", "rrrr..", "r...r.", ".rrr..", ], [ "rrrrr.", "....r.", "....r.", "....r.", "....r.", ], [ ".rrr..", "r...r.", ".rrr..", "r...r.", ".rrr..", ], [ ".rrr..", "r...r.", ".rrrr.", "....r.", "....r.", ], // symbols [ "......", "......", "......", "......", "r.....", ], [ "......", "......", "rrrrr.", "......", "......", ], [ "..g...", "..g...", "ggggg.", "..g...", "..g...", ], ] ); var returnValue = new Font ( "ABCDEFGHIJKLMNOPQRSTUVWXYZ " + "0123456789" + ".-+", new Coords(6, 5), // characterSize characterImages ); return returnValue; } } // run new Simulation().main(); </script> </body> </html>