diff --git a/_config.yml b/_config.yml deleted file mode 100644 index fc24e7a..0000000 --- a/_config.yml +++ /dev/null @@ -1 +0,0 @@ -theme: jekyll-theme-hacker \ No newline at end of file diff --git a/game_engine.coffee b/game_engine.coffee index 14999b3..ce12066 100644 --- a/game_engine.coffee +++ b/game_engine.coffee @@ -4,6 +4,10 @@ class GameLog @content = "" @onChange = onChange + clear: -> + @content = "" + @onChange(this) + echoInput: (text)-> @content += "
> " + text + "
" @onChange(this) @@ -21,22 +25,33 @@ class GameLog class Inventory constructor: -> - @items = {} - @length = 0 + @clear() + + # Properties ################################################################################### + + Object.defineProperties @prototype, + length: + get: -> return @_length + + # Public Methods ############################################################################### add: (item)-> - if not @items[item.name] - @items[item.name] = item - @length += 1 + if not @_items[item.name] + @_items[item.name] = item + @_length += 1 all: -> - return (item for name, item of @items) + return (item for name, item of @_items) + + clear: -> + @_items = {} + @_length = 0 describe: (options={})-> options.simple ?= false result = [] - for name, item of @items + for name, item of @_items if options.simple result.push(item.name) else @@ -45,16 +60,16 @@ class Inventory return result.join("\n") eachItem: (withItem=(->))-> - for name, item of @items + for name, item of @_items withItem(item) has: (item)-> - return !! @items[item.name] + return !! @_items[item.name] remove: (itemToRemove)-> - if @items[itemToRemove.name] - delete @items[itemToRemove.name] - @length -= 1 + if @_items[itemToRemove.name] + delete @_items[itemToRemove.name] + @_length -= 1 ######################################################################################################################## @@ -96,6 +111,8 @@ class Location @transitions = [] @visited = false + # Public Methods ############################################################################### + addTransition: (direction, toLocation, locked=false)-> @transitions[direction] = new Transition(direction, toLocation, locked) @@ -111,6 +128,7 @@ class Location result.push("\n") result.push(@description) + console.log("@inventory.length: #{@inventory.length}") if @inventory.length > 0 result.push("") result.push(@inventory.describe()) @@ -142,10 +160,7 @@ class ParseError extends Error class Parser constructor: (@story)-> - @aliases = {} - @directions = [] - @verbs = {} - @fillerWords = new Set() + @restart() addAliases: (aliasMap)-> for alias, meaning of aliasMap @@ -178,6 +193,12 @@ class Parser @_validateSentence(sentence) return sentence + restart: -> + @aliases = {} + @directions = [] + @fillerWords = new Set() + @verbs = {} + # Private Methods ############################################################################## _normalizeSentence: (sentence)-> @@ -278,9 +299,7 @@ class Player constructor: (@story)-> @inventory = new Inventory() @onChange = (->) - @verbs = {} - - @_score = 0 + @restart() # Properties ################################################################################### @@ -326,6 +345,12 @@ class Player @story.arrive(location) + restart: -> + @verbs = {} + @inventory.clear() + @score = 0 + @_configureDefaultVerbs() + take: (item)-> localItems = @story.currentLocation.inventory if not item @@ -338,13 +363,51 @@ class Player if not foundTakeableItem then @story.log.writeln("There's nothing here you can take.") else if localItems.has(item) - console.log(item) if item.take() localItems.remove(item) @inventory.add(item) else throw new ParseError("There isn't a #{item} here.") + # Private Methods ############################################################################## + + _configureDefaultVerbs: -> + @addVerb "drop", (sentence)=> + if sentence.has(item: 0) + @drop() + else + for itemToken in sentence.tokens.item + @drop(itemToken.referant) + + @addVerb "go", (sentence)=> + if sentence.has(location: 1) + @move(sentence.location) + else + throw new ParseError("I'm not sure where you want to go...") + + @addVerb "inventory", => + if @inventory.length is 0 + @story.log.writeln("You're not carrying anything.") + else + @story.log.writeln("You have:") + @story.log.writeln(@inventory.describe(simple: true)) + + @addVerb "look", (sentence)=> + if sentence.has(item: 1) + @story.log.writeln(sentence.item.describe(verbose: true)) + else + @story.log.writeln(@story.currentLocation.describe(verbose: true)) + + @addVerb "restart", => + @story.restart() + + @addVerb "take", (sentence)=> + if sentence.has(item: 0) + @take() + else + for item in sentence.items + @take(item) + ######################################################################################################################## @@ -377,6 +440,8 @@ class Sentence Object.defineProperties @prototype, "item": get: -> return @tokens.item[0].referant + "items": + get: -> (i.referant for i in @tokens.item) "location": get: -> return @tokens.location[0].referant "verb": @@ -387,18 +452,12 @@ class Sentence class Story - constructor: (@title)-> - @currentLocation = null - @items = [] - @locations = [] + constructor: (@title, @onRestart=(->))-> @log = new GameLog() - @onChange = (->) @parser = new Parser(this) @player = new Player(this) - @_turns = 0 - - @_configure() + @onChange = (->) # Properties ################################################################################### @@ -434,11 +493,6 @@ class Story location.visited = true - begin: -> - @log.writeln(@title) - @log.writeln() - @arrive(@currentLocation) - interpret: (userInput)-> try @log.echoInput(userInput) @@ -453,67 +507,31 @@ class Story # Private Methods ############################################################################## - _configure: -> + restart: -> + @currentLocation = null + @items = [] + @locations = [] + @turns = 0 + + @log.clear() + @parser.restart() + @player.restart() + @parser.addDirections( "north", "northeast", "east", "southeast", "south", "southwest", "west", "northwest", "up", "down" ) @parser.addFillerWords( - "a", - "an", - "around", - "at", - "of", - "the", - "to" + "a", "all", "an", "around", "at", "everything", "of", "the", "to" ) @parser.addAliases({ - "d": "down", - "e": "east", - "everything": "all", - "g": "go" - "i": "inventory" - "l": "look", - "n": "north", - "ne": "northeast", - "nw": "northwest", - "s": "south", - "se": "southeast", - "sw": "southwest", - "u": "up", - "w": "west", + "d": "down", "e": "east", "g": "go", "i": "inventory", "l": "look", "n": "north", "ne": "northeast", + "nw": "northwest", "s": "south", "se": "southeast", "sw": "southwest", "u": "up", "w": "west", }) - @player.addVerb "drop", (sentence)=> - if sentence.has(item: 0) - @player.drop() - else - for itemToken in sentence.tokens.item - @player.drop(itemToken.referant) - - @player.addVerb "go", (sentence)=> - if sentence.has(location: 1) - @player.move(sentence.location) - else - throw new ParseError("I'm not sure where you want to go...") - - @player.addVerb "inventory", => - if @player.inventory.length is 0 - @log.writeln("You're not carrying anything.") - else - @log.writeln("You have:") - @log.writeln(@player.inventory.describe(simple: true)) - - @player.addVerb "look", (sentence)=> - if sentence.has(item: 1) - @log.writeln(sentence.item.describe(verbose: true)) - else - @log.writeln(@currentLocation.describe(verbose: true)) - - @player.addVerb "take", (sentence)=> - if sentence.has(item: 1) - @player.take(sentence.item) - else if sentence.has(item: 0) - @player.take() + @onRestart() + @log.writeln(@title) + @log.writeln() + @arrive(@currentLocation) ######################################################################################################################## diff --git a/index.html b/index.html index 617b53d..c74dfd8 100644 --- a/index.html +++ b/index.html @@ -2,14 +2,16 @@ -
-   -   +
+
+   +   +
+
+

+
+
-
-

-
- diff --git a/run_game.coffee b/run_game.coffee index 33a4a94..52e9544 100644 --- a/run_game.coffee +++ b/run_game.coffee @@ -33,5 +33,5 @@ $(document).ready -> STORY.onChange(STORY) # start the story - STORY.begin() + STORY.restart() $input.focus() diff --git a/story.coffee b/story.coffee index 466afde..540179b 100644 --- a/story.coffee +++ b/story.coffee @@ -1,39 +1,43 @@ -window.STORY = s = new Story("A Walk Through My House") +window.STORY = new Story "A Walk Through My House", -> -# Items ################################################################################################################ + # Items ################################################################################################################ -boxOfTile = s.addItem("box of tiles") -boxOfTile.description = - "This appears to be a box of flooring tiles. The tiles appear to be a very light color of natural stone. It is - quite heavy." -boxOfTile.take = -> - s.log.writeln("Oof! It's too heavy.") - return false + boxOfTile = @addItem "box of tiles" + boxOfTile.description = + "This appears to be a box of flooring tile@ The tiles appear to be a very light color of natural stone. It is + quite heavy." + boxOfTile.take = => + @log.writeln "Oof! It's too heavy." + return false -hose = s.addItem("garden hose") -hose.description = "It's a pretty ordinary garden hose about 20' long." + car = @addItem "your car" + car.description = + "Your car isn't anything special, but it gets you from place to place." -# Locations ############################################################################################################ + hose = @addItem "garden hose" + hose.description = "It's a pretty ordinary garden hose about 20' long." -driveway = s.addLocation("Driveway") -driveway.description = - "The driveway extends slightly uphill a short way to the west back to the street. At this part, it's recessed a - little below the level of the lawn with a stone wall defining the boundary. To the south are three garage doors - which make up the entire side of the house. Above the doors are a few windows. The back yard is to the east, and - the some steps lead up to the front porch to the southwest." -driveway.addItem(hose) + # Locations ############################################################################################################ -frontPorch = s.addLocation("Front Porch") -frontPorch.description = - "You're standing on the front porch. It's a large wooden deck with an overhang above, and a railing all about. To - the north, a staircase leads down a dozen steps or so to the driveway. To the south double door leads inside the - house. It has a fancy crystal inset in the windows, so while you can see a light on inside the house, you can't make - out any details." -frontPorch.addItem(boxOfTile) + driveway = @addLocation "Driveway" + driveway.description = + "The driveway extends slightly uphill a short way to the west back to the street. At this part, it's recessed a + little below the level of the lawn with a stone wall defining the boundary. To the south are three garage doors + which make up the entire side of the house. Above the doors are a few windows. The back yard is to the east, and + the some steps lead up to the front porch to the southwest." + driveway.addItem hose -# Configure Map ######################################################################################################## + frontPorch = @addLocation "Front Porch" + frontPorch.description = + "You're standing on the front porch. It's a large wooden deck with an overhang above, and a railing all about. + To the north, a staircase leads down a dozen steps or so to the driveway. To the south double door leads inside + the house. It has a fancy crystal inset in the windows, so while you can see a light on inside the house, you + can't make out any details." + frontPorch.addItem boxOfTile -driveway.addTransition("southwest", frontPorch) -frontPorch.addTransition("north", driveway) + # Configure Map ######################################################################################################## -s.currentLocation = frontPorch + driveway.addTransition "southwest", frontPorch + frontPorch.addTransition "north", driveway + + @currentLocation = frontPorch diff --git a/styles.css b/styles.css index d803f7a..b26643c 100644 --- a/styles.css +++ b/styles.css @@ -3,47 +3,59 @@ } body { - align-items: center; display: flex; + align-items: stretch; font-size: 16px; font-family: monospace; - flex-direction: column; - justify-content: center; + height: 100%; + margin: 0; +} + +html { + height: 100%; } .entry { background: black; border: none; - border-top: 1px solid gray; + border-top: 1px solid #444; color: green; + flex: 0 0 auto; font-family: monospace; font-size: 16px; margin: 0; outline: none; padding: 0.5em 1em; - width: 800px; +} + +.game { + display: flex; + flex: 1 1 100%; + flex-direction: column; + align-items: stretch; + justify-content: stretch; + height: 100%; } .log { background: black; color: green; - height: 600px; + flex: 1 1 100%; overflow-y: auto; padding: 0.25em 1em; - width: 800px; } .status { background: black; border: none; - border-bottom: 1px solid gray; + border-bottom: 1px solid #444; color: green; display: flex; + flex: 0 0 auto; font-family: monospace; font-size: 16px; margin: 0; padding: 0.5em 1em; - width: 800px; } .score {