Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

I'm free. Here be dragons!

  • Loading branch information...
commit d1027c9e4e896b63a08e481d6c2222dd089db42e 1 parent 93d428b
@hdragomir hdragomir authored
Showing with 8,804 additions and 0 deletions.
  1. +13 −0 .gitignore
  2. +45 −0 README.md
  3. +9 −0 Rakefile
  4. +367 −0 bin/autogoal.js
  5. +332 −0 bin/autogoal.test.js
  6. +121 −0 bin/extract_files
  7. +32 −0 bin/generate_tiles
  8. +73 −0 bin/json_to_script
  9. +66 −0 bin/only_one_css_or_script
  10. +82 −0 bin/update_index
  11. +8 −0 bin/yuicompressor
  12. BIN  bin/yuicompressor-2.4.7.jar
  13. +2,540 −0 config/entities.json
  14. +1 −0  config/extra_build_files
  15. +605 −0 config/levels.json
  16. +296 −0 config/player.json
  17. +54 −0 config/shop.json
  18. +304 −0 config/tutorial.json
  19. +67 −0 css/animations.less
  20. +193 −0 css/castle-complete.less
  21. +52 −0 css/dev-menu.less
  22. +23 −0 css/font.less
  23. +458 −0 css/goals.less
  24. +738 −0 css/hud.less
  25. +544 −0 css/main.less
  26. +588 −0 css/popup.less
  27. +473 −0 css/shop.less
  28. +473 −0 css/ui.less
  29. +56 −0 docs/goals.csv
  30. +108 −0 docs/subgoals.csv
  31. BIN  images/coins.png
  32. BIN  images/comic/blue-panels.jpg
  33. BIN  images/default-ipad.jpg
  34. BIN  images/entities/backgrounds/coast.png
  35. BIN  images/entities/backgrounds/hilite.png
  36. BIN  images/entities/backgrounds/unlockies.png
  37. BIN  images/entities/buildings/artist_studio-icon.png
  38. BIN  images/entities/buildings/artist_studio.png
  39. BIN  images/entities/buildings/axe_icon.png
  40. BIN  images/entities/buildings/bakery-icon.png
  41. BIN  images/entities/buildings/bakery.png
  42. BIN  images/entities/buildings/bath_house-icon.png
  43. BIN  images/entities/buildings/bath_house.png
  44. BIN  images/entities/buildings/coming_soon.png
  45. BIN  images/entities/buildings/crazy_hogs_pub-icon.png
  46. BIN  images/entities/buildings/crazy_hogs_pub.png
  47. BIN  images/entities/buildings/dwarf_house-icon.png
  48. BIN  images/entities/buildings/dwarf_house.png
  49. BIN  images/entities/buildings/elves-hidden.png
  50. BIN  images/entities/buildings/elves.png
  51. BIN  images/entities/buildings/elves_icon.png
  52. BIN  images/entities/buildings/fairy_house-icon.png
  53. BIN  images/entities/buildings/fairy_house.png
  54. BIN  images/entities/buildings/food_icon.png
  55. BIN  images/entities/buildings/fortress-hidden.png
  56. BIN  images/entities/buildings/fortress.png
  57. BIN  images/entities/buildings/fortress_icon.png
  58. BIN  images/entities/buildings/gingerbread_house-icon.png
  59. BIN  images/entities/buildings/gingerbread_house.png
  60. BIN  images/entities/buildings/goldBoost_icon.png
  61. BIN  images/entities/buildings/gold_mine-icon.png
  62. BIN  images/entities/buildings/gold_mine.png
  63. BIN  images/entities/buildings/horse_stable-icon.png
  64. BIN  images/entities/buildings/horse_stable.png
  65. BIN  images/entities/buildings/jokers_house-icon.png
  66. BIN  images/entities/buildings/jokers_house.png
  67. BIN  images/entities/buildings/knights_house-icon.png
  68. BIN  images/entities/buildings/knights_house.png
  69. BIN  images/entities/buildings/ladys_house-icon.png
  70. BIN  images/entities/buildings/ladys_house.png
  71. BIN  images/entities/buildings/lighthouse-hidden.png
  72. BIN  images/entities/buildings/lighthouse.png
  73. BIN  images/entities/buildings/lighthouse_icon.png
  74. BIN  images/entities/buildings/medieval_university-icon.png
  75. BIN  images/entities/buildings/medieval_university.png
  76. BIN  images/entities/buildings/moveBuilding_icon.png
  77. BIN  images/entities/buildings/moveFarm_icon.png
  78. BIN  images/entities/buildings/move_icon.png
  79. BIN  images/entities/buildings/observatory-icon.png
  80. BIN  images/entities/buildings/observatory.png
  81. BIN  images/entities/buildings/ozzystent-hidden.png
  82. BIN  images/entities/buildings/ozzystent.png
  83. BIN  images/entities/buildings/ozzystent_icon.png
  84. BIN  images/entities/buildings/poor_house-icon.png
  85. BIN  images/entities/buildings/poor_house.png
  86. BIN  images/entities/buildings/rock_icon.png
  87. BIN  images/entities/buildings/royal_summer_house-icon.png
  88. BIN  images/entities/buildings/royal_summer_house.png
  89. BIN  images/entities/buildings/ship_stage_1.png
  90. BIN  images/entities/buildings/ship_stage_2.png
  91. BIN  images/entities/buildings/ship_stage_3.png
  92. BIN  images/entities/buildings/ship_stage_4.png
  93. BIN  images/entities/buildings/ship_stage_5.png
  94. BIN  images/entities/buildings/ship_stage_6.png
  95. BIN  images/entities/buildings/shoe_house-icon.png
  96. BIN  images/entities/buildings/shoe_house.png
  97. BIN  images/entities/buildings/silver_mine-icon.png
  98. BIN  images/entities/buildings/silver_mine.png
  99. BIN  images/entities/buildings/skull_01.png
  100. BIN  images/entities/buildings/skull_02.png
  101. BIN  images/entities/buildings/straight_a_schoolhouse-icon.png
  102. BIN  images/entities/buildings/straight_a_schoolhouse.png
  103. BIN  images/entities/buildings/tailor_shop-icon.png
  104. BIN  images/entities/buildings/tailor_shop.png
  105. BIN  images/entities/buildings/taxes_icon.png
  106. BIN  images/entities/buildings/theatre-icon.png
  107. BIN  images/entities/buildings/theatre.png
  108. BIN  images/entities/buildings/tree_house-icon.png
  109. BIN  images/entities/buildings/unicorn_stable-icon.png
  110. BIN  images/entities/buildings/unicorn_stable.png
  111. BIN  images/entities/buildings/upgrade_icon.png
  112. BIN  images/entities/buildings/vikingsmith-hidden.png
  113. BIN  images/entities/buildings/vikingsmith.png
  114. BIN  images/entities/buildings/vikingsmith_icon.png
  115. BIN  images/entities/buildings/villager_house-icon.png
  116. BIN  images/entities/buildings/villager_house.png
  117. BIN  images/entities/buildings/wedding_chapel-icon.png
  118. BIN  images/entities/buildings/wedding_chapel.png
  119. BIN  images/entities/buildings/wizards_house-icon.png
  120. BIN  images/entities/buildings/wizards_house.png
  121. BIN  images/entities/buildings0.png
  122. +6 −0 images/entities/buildings0.sprite
  123. BIN  images/entities/buildings10.png
  124. +4 −0 images/entities/buildings10.sprite
  125. BIN  images/entities/buildings20.png
  126. +5 −0 images/entities/buildings20.sprite
  127. BIN  images/entities/buildings30.png
  128. +6 −0 images/entities/buildings30.sprite
  129. BIN  images/entities/buildings40.png
  130. +5 −0 images/entities/buildings40.sprite
  131. BIN  images/entities/castles.png
  132. +21 −0 images/entities/castles.sprite
  133. BIN  images/entities/castles/castle-icon.png
  134. BIN  images/entities/castles/castle_1.png
  135. BIN  images/entities/castles/castle_10.png
  136. BIN  images/entities/castles/castle_11.png
  137. BIN  images/entities/castles/castle_12.png
  138. BIN  images/entities/castles/castle_13.png
  139. BIN  images/entities/castles/castle_14.png
  140. BIN  images/entities/castles/castle_15.png
  141. BIN  images/entities/castles/castle_16.png
  142. BIN  images/entities/castles/castle_17.png
  143. BIN  images/entities/castles/castle_18.png
  144. BIN  images/entities/castles/castle_19.png
  145. BIN  images/entities/castles/castle_2.png
  146. BIN  images/entities/castles/castle_20.png
  147. BIN  images/entities/castles/castle_3.png
  148. BIN  images/entities/castles/castle_4.png
  149. BIN  images/entities/castles/castle_5.png
  150. BIN  images/entities/castles/castle_6.png
  151. BIN  images/entities/castles/castle_7.png
  152. BIN  images/entities/castles/castle_8.png
  153. BIN  images/entities/castles/castle_9.png
  154. BIN  images/entities/castles/castle_construction.png
  155. BIN  images/entities/castles/castles.png
  156. BIN  images/entities/characters/baby_icon.png
  157. BIN  images/entities/characters/giant.png
  158. BIN  images/entities/characters/goblins.png
  159. BIN  images/entities/characters/person-blue-left.png
  160. BIN  images/entities/characters/person-blue-right.png
  161. BIN  images/entities/characters/person-blue.png
  162. BIN  images/entities/characters/person-green-left.png
  163. BIN  images/entities/characters/person-green-right.png
  164. BIN  images/entities/characters/person-green.png
  165. BIN  images/entities/characters/person-purple-left.png
  166. BIN  images/entities/characters/person-purple-right.png
  167. BIN  images/entities/characters/person-purple.png
  168. BIN  images/entities/characters/person-red-left.png
  169. BIN  images/entities/characters/person-red-right.png
  170. BIN  images/entities/characters/person-red.png
  171. BIN  images/entities/characters/person-turqoise-left.png
  172. BIN  images/entities/characters/person-turqoise-right.png
  173. BIN  images/entities/characters/person-turqoise.png
  174. BIN  images/entities/characters/poof.png
  175. BIN  images/entities/characters/troll-icon.png
  176. BIN  images/entities/characters/troll.png
  177. BIN  images/entities/coastmap.png
  178. BIN  images/entities/construction.png
  179. +6 −0 images/entities/construction.sprite
  180. BIN  images/entities/construction/2x2.png
  181. BIN  images/entities/construction/3x2.png
  182. BIN  images/entities/construction/3x3.png
  183. BIN  images/entities/construction/4x2.png
  184. BIN  images/entities/construction/4x3.png
  185. BIN  images/entities/construction/4x4.png
  186. BIN  images/entities/contracts/contract.png
  187. BIN  images/entities/contracts/dryd_01.png
  188. BIN  images/entities/contracts/dryd_02.png
  189. BIN  images/entities/contracts/dryd_03.png
  190. BIN  images/entities/contracts/exclamation_mark.png
  191. BIN  images/entities/contracts/food.png
  192. BIN  images/entities/contracts/gold.png
  193. BIN  images/entities/contracts/level.png
  194. BIN  images/entities/contracts/no_road.png
  195. BIN  images/entities/decorations.png
  196. +17 −0 images/entities/decorations.sprite
  197. BIN  images/entities/decorations/fairy_lamp_post-icon.png
  198. BIN  images/entities/decorations/fairy_lamp_post.png
  199. BIN  images/entities/decorations/flower_daisy-icon.png
  200. BIN  images/entities/decorations/flower_daisy.png
  201. BIN  images/entities/decorations/flower_dalia-icon.png
  202. BIN  images/entities/decorations/flower_dalia.png
  203. BIN  images/entities/decorations/flower_rose-icon.png
  204. BIN  images/entities/decorations/flower_rose.png
  205. BIN  images/entities/decorations/flower_sunflower-icon.png
  206. BIN  images/entities/decorations/flower_sunflower.png
  207. BIN  images/entities/decorations/fountain_gold-icon.png
  208. BIN  images/entities/decorations/fountain_gold.png
  209. BIN  images/entities/decorations/fountain_rock-icon.png
  210. BIN  images/entities/decorations/fountain_rock.png
  211. BIN  images/entities/decorations/haybale-icon.png
  212. BIN  images/entities/decorations/haybale.png
  213. BIN  images/entities/decorations/magic_pond-icon.png
  214. BIN  images/entities/decorations/magic_pond.png
  215. BIN  images/entities/decorations/magic_windmill-icon.png
  216. BIN  images/entities/decorations/magic_windmill.png
  217. BIN  images/entities/decorations/pond-icon.png
  218. BIN  images/entities/decorations/pond.png
  219. BIN  images/entities/decorations/scarecrow-icon.png
  220. BIN  images/entities/decorations/scarecrow.png
  221. BIN  images/entities/decorations/statue-icon.png
  222. BIN  images/entities/decorations/statue.png
  223. BIN  images/entities/decorations/watchtower-icon.png
  224. BIN  images/entities/decorations/watchtower.png
  225. BIN  images/entities/decorations/well-icon.png
  226. BIN  images/entities/decorations/well.png
  227. BIN  images/entities/decorations/well_of_youth-icon.png
  228. BIN  images/entities/decorations/well_of_youth.png
  229. BIN  images/entities/decorations/windmill-icon.png
  230. BIN  images/entities/decorations/windmill.png
  231. BIN  images/entities/diamond.png
  232. BIN  images/entities/drydock.png
  233. +5 −0 images/entities/drydock.sprite
  234. BIN  images/entities/farming.png
  235. +8 −0 images/entities/farming.sprite
  236. BIN  images/entities/farming/basic_plot-icon.png
  237. BIN  images/entities/farming/basic_plot.png
  238. BIN  images/entities/farming/seed-beans-icon.png
  239. BIN  images/entities/farming/seed-beans.png
  240. BIN  images/entities/farming/seed-clover-icon.png
  241. BIN  images/entities/farming/seed-clover.png
  242. BIN  images/entities/farming/seed-melon-icon.png
  243. BIN  images/entities/farming/seed-melon.png
  244. BIN  images/entities/farming/seed-pumpkin-icon.png
  245. BIN  images/entities/farming/seed-pumpkin.png
  246. BIN  images/entities/farming/seed-strawberry-icon.png
  247. BIN  images/entities/farming/seed-strawberry.png
  248. BIN  images/entities/farming/seed-vineyard-icon.png
  249. BIN  images/entities/farming/seed-vineyard.png
  250. BIN  images/entities/farming/seed-wheat-icon.png
  251. BIN  images/entities/farming/seed-wheat.png
  252. BIN  images/entities/invites/architect.png
  253. BIN  images/entities/invites/carpenter.png
  254. BIN  images/entities/invites/landscaper.png
  255. BIN  images/entities/invites/locksmith.png
  256. BIN  images/entities/invites/mason.png
  257. BIN  images/entities/invites/mechanic.png
  258. BIN  images/entities/invites/painter.png
  259. BIN  images/entities/invites/plumber.png
  260. BIN  images/entities/invites/roofer.png
  261. BIN  images/entities/invites/smith.png
  262. BIN  images/entities/nature/big-treev1-squashed.png
  263. BIN  images/entities/nature/big-treev1/spruce1_bgreen_stage0.png
  264. BIN  images/entities/nature/big-treev1/spruce1_bgreen_stage1.png
  265. BIN  images/entities/nature/big-treev1/spruce1_bgreen_stage2.png
  266. BIN  images/entities/nature/big-treev1/spruce1_bgreen_stage3.png
  267. BIN  images/entities/nature/big-treev1/spruce1_bgreen_stage4.png
  268. BIN  images/entities/nature/big-treev1/spruce1_dgreen_stage0.png
  269. BIN  images/entities/nature/big-treev1/spruce1_dgreen_stage1.png
  270. BIN  images/entities/nature/big-treev1/spruce1_dgreen_stage2.png
  271. BIN  images/entities/nature/big-treev1/spruce1_dgreen_stage3.png
  272. BIN  images/entities/nature/big-treev1/spruce1_dgreen_stage4.png
  273. BIN  images/entities/nature/big-treev1/spruce1_red_stage0.png
  274. BIN  images/entities/nature/big-treev1/spruce1_red_stage1.png
  275. BIN  images/entities/nature/big-treev1/spruce1_red_stage2.png
  276. BIN  images/entities/nature/big-treev1/spruce1_red_stage3.png
  277. BIN  images/entities/nature/big-treev1/spruce1_red_stage4.png
  278. BIN  images/entities/nature/big-treev1/spruce1_ygreen_stage0.png
  279. BIN  images/entities/nature/big-treev1/spruce1_ygreen_stage1.png
  280. BIN  images/entities/nature/big-treev1/spruce1_ygreen_stage2.png
  281. BIN  images/entities/nature/big-treev1/spruce1_ygreen_stage3.png
  282. BIN  images/entities/nature/big-treev1/spruce1_ygreen_stage4.png
  283. BIN  images/entities/nature/big-treev2-squashed.png
  284. BIN  images/entities/nature/big-treev2/spruce2_bgreen_stage0.png
  285. BIN  images/entities/nature/big-treev2/spruce2_bgreen_stage1.png
  286. BIN  images/entities/nature/big-treev2/spruce2_bgreen_stage2.png
  287. BIN  images/entities/nature/big-treev2/spruce2_bgreen_stage3.png
  288. BIN  images/entities/nature/big-treev2/spruce2_bgreen_stage4.png
  289. BIN  images/entities/nature/big-treev2/spruce2_dgreen_stage0.png
  290. BIN  images/entities/nature/big-treev2/spruce2_dgreen_stage1.png
  291. BIN  images/entities/nature/big-treev2/spruce2_dgreen_stage2.png
  292. BIN  images/entities/nature/big-treev2/spruce2_dgreen_stage3.png
  293. BIN  images/entities/nature/big-treev2/spruce2_dgreen_stage4.png
  294. BIN  images/entities/nature/big-treev2/spruce2_red_stage0.png
  295. BIN  images/entities/nature/big-treev2/spruce2_red_stage1.png
  296. BIN  images/entities/nature/big-treev2/spruce2_red_stage2.png
  297. BIN  images/entities/nature/big-treev2/spruce2_red_stage3.png
  298. BIN  images/entities/nature/big-treev2/spruce2_red_stage4.png
  299. BIN  images/entities/nature/big-treev2/spruce2_ygreen_stage0.png
  300. BIN  images/entities/nature/big-treev2/spruce2_ygreen_stage1.png
Sorry, we could not display the entire diff because too many files (534) changed.
View
13 .gitignore
@@ -0,0 +1,13 @@
+css/*.css
+build/
+node_modules/
+.DS_Store
+.pt
+app.tar
+js/config.js
+config/goals.json
+*.sublime-project
+*.sublime-workspace
+config/version
+images/entities/*.json
+images/entities-*
View
45 README.md
@@ -0,0 +1,45 @@
+# Build Dependencies
+
+To build the game you need the following tools:
+
+* __brew__ http://mxcl.github.com/homebrew/
+* __ruby__ http://www.ruby-lang.org/en/downloads/
+* __gem__ http://rubygems.org/pages/download
+* __rake__ `gem install rake`
+* __markdown__ `brew install markdown`
+* __gcc__ (you should install XCode)
+* __node__ & npm http://nodejs.org/
+* __lessc__ `npm install -g less`
+* __jslint__ `npm install -g jslint`
+* __spritopia__ `gem install spritopia`
+* __pngcrush__ (optional) `brew install pngcrush`
+
+
+# Getting Started
+
+`git clone git@github.com:wooga/pocket_island.git`
+
+## Rake tasks
+
+- `rake all` : # Build the exact version that will be shipped to the wrapper
+- `rake check_missing_files` : # List files that are reference on the game, but doesn't exists
+- `rake clean` : # Remove any temporary products.
+- `rake clobber` : # Remove any generated file.
+- `rake default` : # Update local files like index.html with the content of the config files, or the css from the less files
+- `rake lint` : # Look for syntax errors in the files
+- `rake list_extra_files` : # List the files that are not references from the game but are still present
+- `rake remove_trailing_spaces` : # Remove trailing spaces at the end of the line
+
+
+### Adding new sprites
+
+Start with creating a ``.sprite`` file that lists individual images
+that should be included in the sprite. Then run:
+
+ rake sprite_name.png
+
+to generate the image based on ``sprite_name.sprite`` file.
+An image and ``sprite_name.json`` will be generated.
+Use the value from the json file to update ``entities.json`` with
+``width``, ``height``, ``spritey`` and ``offsetY`` values.
+Remember to divide pixel values by 48 before entering them in ``entities.json``.
View
9 Rakefile
@@ -0,0 +1,9 @@
+require 'rubygems'
+require 'bundler/setup'
+
+VERBOSE=RakeFileUtils.verbose_flag
+def SILENT(s); VERBOSE ? '' : s; end
+def which(s); system("which #{s} >/dev/null 2>&1") ; end
+
+import 'tasks/build.rake'
+import 'tasks/lint.rake'
View
367 bin/autogoal.js
@@ -0,0 +1,367 @@
+#!/usr/bin/env node
+var fs = require('fs'),
+ paths = {
+ "entities": "config/entities.json",
+ "goals": "docs/goals.csv",
+ "subgoals": "docs/subgoals.csv",
+ "save_goals_to": "config/goals.json"
+ },
+ actionsMap = {
+ "harvest": "game:contract/collect",
+ "plant": "game:contract/start",
+ "connect": "game:building/connected",
+ "contract": "game:contract/start",
+ "collect": "game:contract/collect",
+ "whack": "game:entity/whack-complete",
+ "buy": "game:entity/buy",
+ "move": "game:entity/move",
+ "boost": "game:boosts/maybe-change",
+ "upgrade": "game:castle/upgrade"
+ };
+
+function _entityDefinitions () {
+ if(! _entityDefinitions.entities ) {
+ _entityDefinitions.entities = JSON.parse( fs.readFileSync(paths.entities));
+ }
+ return _entityDefinitions.entities;
+}
+
+function sift (needle, haystack) {
+ for( var i in haystack ){
+ if(-1 !== i.indexOf(needle) && haystack[i]){
+ haystack[i].key = haystack[i].key || i; //otherwise, we will never have access to it
+ return haystack[i];
+ }
+ }
+ return null;
+}
+
+function _entityDefinition (key) {
+ if("undefined" === typeof _entityDefinition.cache[key]) {
+ _entityDefinition.cache[key] = sift(key, _entityDefinition.cache) || sift(key, _entityDefinitions());
+ }
+ return _entityDefinition.cache[key];
+}
+
+_entityDefinition.cache = {};
+
+function csv_parser (path, key_translation) {
+ var raw_data = fs.readFileSync(path, 'utf-8'),
+ lines = raw_data.split("\n"),
+ keys, objects = [],
+ breakAt = lines.indexOf('');
+ key_translation = key_translation || {};
+ if (-1 !== breakAt){
+ lines = lines.slice(0, breakAt);
+ }
+ keys = lines.shift().split(',');
+ lines.forEach(function (line) {
+ var obj = {}, values = line.split(',');
+ keys.forEach(function (key, nth) {
+ if("" !== key){
+ obj[ key_translation[key] || key ] = values[nth];
+ }
+ });
+ objects.push(obj);
+ });
+ return objects;
+}
+
+var utils = {
+ "merge": function (a, b) {
+ [].slice.call(arguments, 1).forEach(function (extObj) {
+ for (var property in extObj) {
+ a[property] = extObj[property];
+ }
+ });
+ return a;
+ },
+ "pluck": function (array) {
+ return array.length? array.splice(Math.floor(Math.random() * array.length), 1)[0] : undefined;
+ }
+}
+
+var E = {
+ "entity": _entityDefinition,
+ "entities": _entityDefinitions,
+ "sift": sift
+ },
+ subgoal_utils = {
+ "map_action": function (string) {
+ return actionsMap[string];
+ },
+ "basic_validator": function (string) {
+ var mapping = {
+ "harvest": {
+ "entity.definition.class": "farm"
+ },
+ "plant": {
+ "entity.definition.class": "farm"
+ },
+ "contract": {
+ "entity.definition.class": "house"
+ },
+ "connect": {
+ },
+ "collect": {
+ "entity.definition.class": "house"
+ },
+ "whack": {
+ "entity.definition.class": "whackable"
+ },
+ "buy": {
+ "entity.definition.class": "house"
+ },
+ "move": {
+
+ }
+ };
+ return mapping[string] || {};
+ },
+ "validator": function (subgoal) {
+ var validator = subgoal_utils.basic_validator(subgoal.action),
+ re, entityClass, target;
+ if(subgoal.target){
+ re = /^\*/;
+ if(re.test(subgoal.target)){
+ entityClass = subgoal.target.replace(re, '');
+ validator['entity.definition.class'] = entityClass;
+ if('boost' === subgoal.action){
+ validator['entity.boost'] = subgoal.amount;
+ subgoal.amount = 1;
+ } else if ("connect" === subgoal.action) {
+ validator['definition.class'] = validator['entity.definition.class'];
+ validator['connected'] = true;
+ delete validator['entity.definition.class'];
+ }
+ } else {
+ target = E.entity(subgoal.target) || 0;
+ switch(subgoal.action){
+ case "harvest":
+ case "plant":
+ validator['contract.seedName'] = target.key;
+ break;
+ case "buy":
+ validator = {'entity.key': target.key};
+ break;
+ case "connect":
+ validator = {'key': target.key, "connected": true};
+ break;
+ case "boost":
+ validator["entity.boost"] = subgoal.amount;
+ if(target){
+ validator['entity.key'] = target.key;
+ }
+ subgoal.amount = 1;
+ break;
+ case "whack":
+ if (/characters/i.test(target.key)) {
+ validator = {'entity.key': target.key};
+ }
+ default:
+ validator['entity.key'] = target.key;
+ }
+ }
+ }
+ return validator;
+ },
+ "action": function (subgoal) {
+ subgoal.event = subgoal_utils.map_action(subgoal.action);
+ if(subgoal.target){
+ re = /^\*/;
+ if(! re.test(subgoal.target)){
+ var target = E.entity(subgoal.target) || 0;
+ if (/characters/i.test(target.key)) {
+ subgoal.event = "game:enemy/kill";
+ }
+ }
+ if ('*enemy' === subgoal.target) {
+ //hooray for edge cases!
+ subgoal.event = "game:enemy/kill";
+ }
+ }
+ return subgoal;
+ },
+ "amount": function (subgoal) {
+ return subgoal.amount || 1;
+ },
+ "rewards": function (config) {
+ var reward = [];
+ if("object" !== typeof config.reward){
+ reward.push({"type": config.rewardType||"gold", "amount": config.reward});
+ }
+ return reward;
+ },
+ "subgoal": function (data) {
+ var subgoal = subgoal_utils.action(data),
+ target;
+ subgoal.objects = subgoal_utils.validator(subgoal);
+ subgoal.amount = subgoal_utils.amount(subgoal);
+ subgoal.rewards = subgoal_utils.rewards(subgoal);
+ subgoal.subgoalText = (subgoal.name+"").replace(/#/g, subgoal.amount);
+ subgoal.subgoalHint = subgoal.hint;
+ subgoal.type = subgoal.type || "listen";
+ subgoal.action = subgoal.event;
+ if(! subgoal.icon){
+ target = E.entity(subgoal.target);
+ if(! target) {
+ console.error(subgoal.target + ' was not found!!');
+ } else {
+ subgoal.icon = target.icon;
+ }
+ }
+ delete subgoal.hint;
+ delete subgoal.name;
+ delete subgoal.target;
+ delete subgoal.reward;
+ delete subgoal.scheme;
+ return subgoal;
+ }
+ },
+ subgoal_finder = {
+ "subgoals": function () {
+ if(! subgoal_finder.__subgoals){
+ subgoal_finder.__subgoals = csv_parser(paths.subgoals, {
+ "Name": "name",
+ "Reward": "reward",
+ "Reward_Type": "rewardType",
+ "Finished": "finished",
+ "Min_Level": "level",
+ "Level": "level",
+ "Hint": "hint",
+ "Target": "target",
+ "Amount": "amount",
+ "Action": "action",
+ "Scheme": "scheme",
+ "type": 'type'
+ });
+ // uncomment to turn on alteration verification
+ // subgoal_finder.o = ff(subgoal_finder.__subgoals);
+ }
+ return subgoal_finder.__subgoals;
+ },
+ /** subgoals alteration verifier
+ "___v": function () {
+ if (subgoal_finder.o !== ff(subgoal_finder.__subgoals)) {
+ console.error('fuck!');
+ }
+ },
+ */
+ "_find": function (constraints) {
+ return [].concat(subgoal_finder.subgoals().filter(subgoal_finder.__seeker(constraints))).map(function (e) {
+ return utils.merge({}, e);
+ });
+ },
+ "__seeker": function (config) {
+ return (function (c) {
+ return function (candidate) {
+ return (candidate.scheme === c.scheme) && ( c.level ? parseInt(candidate.level||0, 10) <= parseInt(c.level, 10) : true );
+ };
+ } (config));
+ },
+ "find": function (count, constraints) {
+
+ var schemes = constraints.scheme.split('-'),
+ total = count,
+ found = [], pool = [];
+
+ schemes.forEach( function (scheme) {
+ var set = subgoal_finder._find(utils.merge({}, constraints, {"scheme": scheme}));
+ if(set.length){
+ found.push(utils.pluck(set));
+ pool = pool.concat(set);
+ total--;
+ }
+ });
+ // turns on step by step subgoal data alteration verification
+ // subgoal_finder.___v();
+
+
+ while((total * pool.length) > 0) {
+ found.push(utils.pluck(pool));
+ }
+
+ return found;
+ }
+ },
+ goals_builder = {
+ //returns definitions!
+ "goals": function () {
+ if(! goals_builder.__goals){
+ goals_builder.__goals = csv_parser(paths.goals, {
+ "Name": "name",
+ "Reward": "reward",
+ "Reward_Type": "rewardType",
+ "Finished": "finished",
+ "Min_Level": "level",
+ "Scheme": "scheme"
+ });
+ }
+ return goals_builder.__goals;
+ },
+ //returns definitions!
+ "subgoals": function (count, goal) {
+ return subgoal_finder.find(count, goal);
+ },
+ "_subgoalIDGenerator": function (seed) {
+ return function (subgoal, nth) {
+ subgoal.subgoalID = seed + "s" + (nth+1);
+ };
+ },
+ "goal": function (subgoal_count, goal_data) {
+ var goal = utils.merge({}, goal_data);
+ goal.subgoals = goals_builder.subgoals(subgoal_count, goal).map(subgoal_utils.subgoal);
+ goal.subgoals.forEach(goals_builder._subgoalIDGenerator(goal.goalID));
+ goal.rewardType = goal.rewardType || "xp";
+ goal.rewards = subgoal_utils.rewards(goal);
+ goal.storyTitle = goal.name;
+ goal.finishedText = goal.finished;
+ goal.Icon = '';
+ delete goal.finished;
+ delete goal.name;
+ delete goal.reward;
+ delete goal.rewardType;
+ delete goal.scheme;
+ return goal;
+ },
+ "generate": function (config) {
+ var all = goals_builder.goals().concat([]),
+ goals = {};
+ all.splice(config.count || all.length);
+ all.map(function (goal_data, nth) {
+ goal_data.goalID = 1e2 + nth;
+ var goal = goals_builder.goal(config.subgoal_count[0], goal_data);
+ if(goal && goal.subgoals && goal.subgoals.length > 0){
+ this['goals/' + goal.goalID] = goal;
+ }
+ }, goals);
+ return goals;
+ }
+ };
+
+function __build (goals_no, min_subgoal_no, max_subgoal_no) {
+ fs.writeFile(paths.save_goals_to, JSON.stringify(
+ {"line/1": {"goals": goals_builder.generate({
+ "count": goals_no,
+ "subgoal_count": [min_subgoal_no, max_subgoal_no]
+ })}}));
+}
+
+module.exports = {
+ "E": E,
+ "utils": utils,
+ "subgoal_utils": subgoal_utils,
+ "s": subgoal_finder,
+ "g": goals_builder,
+ "build": __build
+};
+
+/** poorman's crc
+var ff = function (a) {
+ return a.reduce(function (v, c) {
+ return v + c.scheme;
+ }, '');
+};
+*/
+
+__build(120, 2, 7);
View
332 bin/autogoal.test.js
@@ -0,0 +1,332 @@
+var assert = require('assert'),
+ autogoal = require('./autogoal.js');
+function bfe () {
+ autogoal.g.__goals = [
+ {
+ "name": "a goal name",
+ "finished": "Contratulatory text",
+ "icon": "king01.png",
+ "reward": 100,
+ "rewardType": "xp",
+ "scheme": "intro",
+ "level": 10
+ },
+ {
+ "name": "a goal name two",
+ "finished": "Contratulatory text",
+ "icon": "king02.png",
+ "reward": 100,
+ "rewardType": "xp",
+ "scheme": "hjk",
+ "level": 10
+ }
+ ];
+ autogoal.s.__subgoals = [
+ {
+ "name": "a subgoal name",
+ "hint": "a subgoal hint",
+ "reward": 50,
+ "action": 'harvest',
+ "amount": 1,
+ "target": "melon",
+ "scheme": "intro",
+ "_scheme": "intro",
+ "level": 1
+ },
+ {
+ "name": "a subgoal name two",
+ "hint": "a subgoal hint",
+ "reward": 30,
+ "action": 'contract',
+ "amount": 2,
+ "target": "poor_house",
+ "scheme": "intro",
+ "_scheme": "intro",
+ "level": 2
+ },
+ {
+ "name": "a subgoal name three",
+ "hint": "a subgoal hint",
+ "reward": 30,
+ "action": 'buy',
+ "amount": 2,
+ "icon": "hell",
+ "target": "villager",
+ "scheme": "build",
+ "_scheme": "build",
+ "level": 1
+ }
+ ];
+}
+beforeEach( function () {
+ bfe();
+} );
+
+describe('entities parsing', function () {
+ it("loads entities properly", function (be) {
+ var entities = autogoal.E.entities();
+ expect(typeof entities).toEqual("object");
+ });
+
+ it("finds an entity", function(be) {
+ expect(typeof autogoal.E.entity('villager')).toEqual("object");
+ });
+});
+
+describe('single subgoal validator generation', function () {
+ it("creates basic validators", function () {
+ var validator = autogoal.subgoal_utils.basic_validator('harvest'),
+ longKey = "entity.definition.class", validatorValue = "farm";
+ expect(validator[longKey]).toEqual(validatorValue);
+ });
+ it("creates extended validators", function () {
+ expect(autogoal.subgoal_utils.validator({
+ "action": "harvest",
+ "target": "melon"
+ })["contract.seedName"]).toEqual( "farming/seed-melon");
+ });
+ it("creates extended validators for houses", function () {
+ expect(autogoal.subgoal_utils.validator({
+ "action": "contract",
+ "target": "wizard"
+ })["entity.key"]).toEqual("buildings/wizards_house");
+ });
+ it("creates extended validators for whackables", function () {
+ expect(autogoal.subgoal_utils.validator({
+ "action": "whack",
+ "target": "tree-small"
+ })["entity.key"]).toEqual("nature/tree-small-b");
+ });
+ it("creates validators for AND class type constraings", function () {
+ expect(autogoal.subgoal_utils.validator({
+ "action": "move",
+ "target": "*farm"
+ })["entity.definition.class"]).toEqual("farm");
+ });
+});
+
+describe('single subgoal gets rewards', function () {
+ it('sets the rewards', function () {
+ var reward = autogoal.subgoal_utils.rewards({"reward": 10})[0];
+ expect(reward.type).toEqual('gold');
+ });
+});
+
+describe('single subgoal generator', function () {
+ it("maps action strings", function () {
+ expect(autogoal.subgoal_utils.map_action("harvest")).toEqual("game:contract/collect");
+ });
+ it("overrides action based on target", function () {
+ expect(autogoal.subgoal_utils.action({"action": "whack", "target": "troll"}).event).toEqual('game:enemy/kill'); //action gets overwritten at the last moment in the subgoal processor
+ });
+ it("autmagically adds amount IF missing", function () {
+ var subgoal = autogoal.subgoal_utils.subgoal({
+ "action": "whack", "target": "troll"
+ });
+ expect(subgoal.amount).toEqual(1);
+ subgoal = autogoal.subgoal_utils.subgoal({
+ "action": "whack", "target": "troll",
+ "amount": 3
+ });
+ expect(subgoal.amount).toEqual(3);
+ });
+ it("stitches a subgoal together", function () {
+ var subgoal = autogoal.subgoal_utils.subgoal({
+ "action": "whack", "target": "troll", "name": "", "hint": ""
+ });
+ expect(typeof subgoal).toEqual('object');
+ expect(subgoal.action).toEqual('game:enemy/kill');
+ expect(subgoal.type).toBeDefined();
+ expect(subgoal.subgoalText).toBeDefined();
+ expect(subgoal.subgoalHint).toBeDefined();
+ });
+ it("renders the title correctly", function () {
+
+ var subgoal = autogoal.subgoal_utils.subgoal({
+ "action": "whack", "target": "troll", "name": "whack troll #x", "hint": "", "icon": "troll-icon"
+ });
+ expect(subgoal.subgoalText).toEqual("whack troll 1x");
+
+ });
+ it("adds an icon to the subgoal", function () {
+ var subgoal = autogoal.subgoal_utils.subgoal({
+ "action": "buy", "target": "villager", "name": "buy a villager house", "hint": ""
+ });
+ expect(subgoal.icon).toBeDefined();
+ expect(subgoal.icon.indexOf('villager')).not.toEqual(-1);
+ });
+ it("adds icon only if none was specified", function () {
+
+ var subgoal = autogoal.subgoal_utils.subgoal({
+ "action": "buy", "target": "villager", "name": "buy a villager house", "hint": "",
+ "icon": 'xxx'
+ });
+ expect(subgoal.icon).toEqual('xxx');
+ });
+ it("creates validator even if no target is passed", function () {
+ var subgoal = autogoal.subgoal_utils.subgoal({
+ "name": "a subgoal name three",
+ "hint": "a subgoal hint",
+ "reward": 30,
+ "action": 'buy',
+ "amount": 2,
+ "icon": "villager_house",
+ "target": "",
+ "scheme": "general",
+ "_scheme": "general",
+ "level": 1
+ });
+ expect(subgoal).toBeDefined();
+ expect(subgoal.action).toEqual('game:entity/buy');
+ expect(subgoal.objects).toBeDefined();
+ expect(subgoal.objects['entity.definition.class']).toEqual('house');
+ });
+});
+
+describe('subgoal finder', function () {
+ it("has a pool of subgoals", function () {
+ var subgoals = autogoal.s.subgoals();
+ expect(typeof subgoals).toEqual("object");
+ expect(subgoals.length).not.toEqual(0);
+ });
+ it("finds subgoal by scheme", function () {
+ var subgoals = autogoal.s._find({
+ "scheme": "intro"
+ });
+ expect(subgoals).toBeDefined();
+ expect(subgoals.length).not.toEqual(0);
+ var empty = autogoal.s._find({
+ "scheme": "x" + Math.random()
+ });
+ expect(empty.length).toEqual(0);
+ });
+ it("finds requested number of subgoals for constraints", function () {
+ var setIntroWith1 = autogoal.s.find(1, {"scheme": "intro"}),
+ a
+ ;
+ expect(setIntroWith1.length).toEqual(1);
+ });
+ it("finds requested number of subgoals for constraints", function () {
+ var setIntroWith2 = autogoal.s.find(2, {"scheme": "intro", level: 20}),
+ a
+ ;
+ expect(setIntroWith2.length).toEqual(2);
+ });
+ it("finds requested number of subgoals for constraints", function () {
+ var setIntroWith = autogoal.s.find(3, {"scheme": "intro", level: 20}),
+ a
+ ;
+ expect(setIntroWith.length).toEqual(2);
+ });
+ it("filters by requested level", function () {
+ var set = autogoal.s.find(2, {"scheme": "intro", "level": 1});
+ expect(set.length).toEqual(1);
+ });
+ it("cares for multiple schemes", function () {
+ var set = autogoal.s.find(2, {"scheme": "intro-build"});
+ expect(set.length).not.toEqual(0);
+ var hasIntro = set.some(function (sg) {return sg._scheme === "intro";}),
+ hasBuild = set.some(function (sg) {return sg._scheme === "build";});
+ expect(hasIntro).toEqual(true);
+ expect(hasBuild).toEqual(true);
+ });
+});
+
+describe('12 is not smaller than 2', function () {
+
+ beforeEach(function () {
+
+ autogoal.g.__goals = [
+ {
+ "name": "a goal name",
+ "finished": "Contratulatory text",
+ "icon": "king01.png",
+ "reward": 100,
+ "rewardType": "xp",
+ "scheme": "intro",
+ "level": 10
+ },
+ {
+ "name": "a goal name two",
+ "finished": "Contratulatory text",
+ "icon": "king02.png",
+ "reward": 100,
+ "rewardType": "xp",
+ "scheme": "hjk",
+ "level": 10
+ }
+ ];
+ autogoal.s.__subgoals = [
+ {
+ "name": "a subgoal name",
+ "hint": "a subgoal hint",
+ "reward": 50,
+ "action": 'harvest',
+ "amount": 1,
+ "target": "melon",
+ "scheme": "intro",
+ "_scheme": "intro",
+ "level": 1
+ },
+ {
+ "name": "a subgoal name two",
+ "hint": "a subgoal hint",
+ "reward": 30,
+ "action": 'contract',
+ "amount": 2,
+ "target": "poor_house",
+ "scheme": "intro",
+ "_scheme": "intro",
+ "level": "2"
+ },
+ {
+ "name": "a subgoal name three",
+ "hint": "a subgoal hint",
+ "reward": 30,
+ "action": 'buy',
+ "amount": 2,
+ "icon": "hell",
+ "target": "villager",
+ "scheme": "intro",
+ "_scheme": "intro",
+ "level": "12"
+ }
+ ];
+ });
+
+ it("casts strings to numbers when checking for unlock level", function () {
+ var set = autogoal.s.find(3, {"scheme": "intro", "level": "2"});
+ expect(set.length).toEqual(2);
+ });
+
+});
+
+describe("goal builder", function () {
+ beforeEach(bfe);
+ it("has a pool of goals", function () {
+ var goals = autogoal.g.goals();
+ expect(typeof goals).toEqual("object");
+ expect(goals.length).not.toEqual(0);
+ });
+ it("stitches the parts to form a goal", function () {
+ var goal = autogoal.g.goal(2, autogoal.g.goals()[0]);
+ expect(goal.subgoals.length).toEqual(2);
+ expect(goal.rewards).toBeDefined();
+ expect(goal.storyTitle).toBeDefined();
+ expect(goal.finishedText).toBeDefined();
+ });
+ it("drops goals with no subgoals", function () {
+ var goal = autogoal.utils.merge({}, autogoal.g.goals()[1]);
+ var orig_scheme = goal.scheme;
+ goal.scheme = "xxjj " + Math.random();
+ var subgoals = autogoal.g.subgoals(1, goal);
+ expect(subgoals.length).toEqual(0);
+ goal.scheme = orig_scheme;
+ });
+
+ it("generates subgoals for goal constraints", function () {
+ var goal = [].concat(autogoal.g.goals())[0];
+ var subgoals = autogoal.g.subgoals(2, goal);
+ expect(subgoals.length).toEqual(2);
+ });
+});
View
121 bin/extract_files
@@ -0,0 +1,121 @@
+#!/usr/bin/env ruby
+
+module ExtractFiles
+ VERSION = "0.0.2"
+
+ extend self
+
+ DEFAULT_EXTENSIONS = %w(png jpeg jpg gif css js)
+
+ # Process the input io, or anything that respond to __read__ and return a string.
+ # options are:
+ #
+ # * **extensions**: Array of extensions to look for. Default is DEFAULT_EXTENSIONS
+ #
+ # * **base**: Base directory. Image a relative path for a image **bg.png** in a css file inside the **styles** folder. The default output
+ # will say "../images/bg.png". If you say that the base directory is "styles" the output will be "styles/../images/bg.png". Is unset by default.
+ #
+ # * **expand**: If the output is somehing like "sytles/../images/bg.png" expand will convert that in "images/bg.png". Is enabled by false.
+ #
+ # * **full_path**: Show the full_path
+ #
+ # If no **block** is passed, it will output to the stdout throught puts. If a block is given, it will yield each founded entry.
+ #
+ def extract!(io, options = {})
+ raise "Incorrect format for IO" unless io.respond_to?(:read)
+
+ options = {:extensions => DEFAULT_EXTENSIONS}.merge(options)
+
+ ext = "(" + options[:extensions].join("|") + ")"
+ re = /([a-z0-9\-_\/\.]*[a-z0-9]*\.#{ext})/i
+
+ io.read.scan(re).each do |match|
+ path = match[0]
+ path = File.join(options[:base], path) if options[:base]
+ path = simplify_path(path) if options[:expand]
+ path = File.expand_path(path) if options[:full_path]
+ if block_given?
+ yield path
+ else
+ puts path
+ end
+ end
+
+ end
+
+ # get! is a wrapper for extract! that returns and array of the matches.
+ def get!(io,options)
+ matches = []
+ extract!(io,options){|match| matches<<match}
+ matches
+ end
+
+ protected
+
+ def simplify_path(string)
+ string.gsub(/[^\/]*\/\.\.\//,'').gsub(/^\.\//,'').gsub(/\.\//,'')
+ end
+
+
+end
+
+require 'optparse'
+
+
+options = {:extensions => []}
+OptionParser.new do |opts|
+ opts.banner = "Usage: #{File.basename $0} [options] file"
+
+
+ opts.on("-e", "--ext EXT", "Extract files with extension EXT. Can be used several times.") do |v|
+ options[:extensions] << v
+ end
+
+ opts.separator ""
+
+ opts.on("-b", "--base-directory DIR", "Use DIR as a base directory") do |base_dir|
+ options[:base] = base_dir
+ end
+
+ opts.on("-p", "--expand-path", "Remove .. from output directories") do |e|
+ options[:expand] = true
+ end
+
+ opts.on("-f", "--full-path", "Show full path") do
+ options[:full_path] = true
+ end
+
+ opts.separator ""
+
+ opts.on("-v", "--version", "Show the version") do
+ puts ExtractFiles::VERSION
+ exit 0
+ end
+
+ opts.on_tail("-h", "--help", "Show this help") do
+ puts opts
+ exit 0
+ end
+
+end.parse!
+
+if ARGV.empty? && !$stdin.tty?
+ ExtractFiles.extract!($stdin, options)
+ exit 0
+end
+
+ARGV.each do |file|
+ (raise "File #{file} not found" ; exit -1) unless File.exists?(file)
+
+ if options[:extensions].any?
+
+ begin
+ file = File.open(file)
+ ExtractFiles.extract!(file, options)
+ ensure
+ file.close
+ end
+ end
+
+
+end
View
32 bin/generate_tiles
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+cd public/images
+
+cd entities
+
+echo Generating buildings.png ...
+files=`find buildings -type f -name "*.png" | grep -v "icon" |sort `
+montage -background transparent -tile x9999999 -geometry +0+0 $files buildings.png
+
+echo Generating castles.png
+files=`find castles/castle_* castles/campsite.png | sort`
+montage -background transparent -tile x9999999 -geometry +0+0 $files castles.png
+
+echo Generating decorations.png
+files=`find decorations -type f | grep -v icon | sort`
+montage -background transparent -tile x9999999 -geometry +0+0 $files decorations.png
+
+echo Generating farming.png
+files=`find farming -type f | grep -v icon | sort`
+montage -background transparent -tile x9999999 -geometry +0+0 $files farming.png
+
+echo Generating nature.png
+files=`find nature -type f | grep -v icon | sort`
+montage -background transparent -tile x9999999 -geometry +0+0 $files nature.png
+
+echo Generating paths.png
+files=`find paths -type f | grep -v icon | sort`
+montage -background transparent -tile x9999999 -geometry +0+0 $files paths.png
+
+
+
View
73 bin/json_to_script
@@ -0,0 +1,73 @@
+#!/usr/bin/env ruby
+
+require 'rubygems'
+require 'optparse'
+require 'json'
+
+def process_parameter(parameter)
+ key,file = parameter.split(":")
+ raise "The key #{key} is not valid" unless key =~ /[\w_\a\z]+/i
+ raise "File not found #{file}" unless File.file?(file)
+ return key,file
+end
+
+options = {:actions => []}
+OptionParser.new do |opts|
+ opts.banner = "Usage: #{File.basename $0} options"
+
+ opts.on("-o","--oneline key:file", "Read the json from file, remove the newlines and generate a line with the form ' key = file ; '.") do |f|
+ key,file = process_parameter(f)
+ options[:actions] << [:oneline, key, file]
+ end
+
+ opts.on("-r","--reparse key:file", "Read the json, parse it and serialize it in the form ' key = file ; '.") do |f|
+ key,file = process_parameter(f)
+ options[:actions] << [:reparse, key, file]
+ end
+
+ opts.on("-s","--stringify key:file", "Put the content of the file as an string WITHOUT SCAPE") do |f|
+ key,file = process_parameter(f)
+ options[:actions] << [:stringify, key, file]
+ end
+
+ opts.on("-f", "--file FILE", "Set the output to a file instead of the STDOUT") do |f|
+ options[:file] = f
+ end
+
+ opts.on("-h", "--help", "Shows the help") do
+ puts opts
+ exit 0
+ end
+
+
+end.parse!
+
+begin
+ output = options[:file] ? File.open(options[:file],"w") : $stdout
+
+ options[:actions].each do |action|
+ action, key, file = *action
+
+ json = ''
+
+ content = File.read(file)
+ case action
+ when :reparse
+ json = JSON.fast_generate(JSON.parse(content))
+ when :oneline
+ json = content.gsub(/\n/,'')
+ when :stringify
+ json = "\"#{content.gsub('"','\"')}\""
+ else
+ exit -1
+ end
+ output.print key, " = ", json, " ;\n"
+ end
+
+ensure
+ output.close
+end
+
+
+
+
View
66 bin/only_one_css_or_script
@@ -0,0 +1,66 @@
+#!/usr/bin/env ruby
+
+require 'optparse'
+
+
+OPTIONS = {}
+$help = nil;
+OptionParser.new do |opts|
+ $help = opts
+ opts.banner = "Usage: only_one_css_or_script [OPTIONS]"
+
+
+ opts.separator ""
+ opts.separator "Read from stdin an html file, looks for '<script src='...'' or <link rel='stylesheet' href='...' and agrupate all of the in just one. Then output the result in the stdout."
+ opts.separator ""
+
+ opts.on("-j", "--js-name FILENAME", "Generated js filename") do |filename|
+ OPTIONS[:js_filename] = filename
+ end
+
+ opts.on("-c", "--css-name FILENAME", "Generated css filename") do |filename|
+ OPTIONS[:css_filename] = filename
+ end
+
+ opts.separator ""
+
+ opts.on("-h", "--help", "Show this help") do
+ puts opts
+ exit 0
+ end
+
+end.parse!
+
+if $stdin.tty?
+ die("You should use this command inside a pipe")
+end
+
+def die(msg)
+ puts "ERROR: #{msg}"
+ puts $help
+ exit -1
+end
+
+
+JS_REGEXP = /^.*(\<script\s*src\=("|')([^'"]*)('|")\s*([^>]*\s*)*>)\s*<\/script>.*$/i
+CSS_REGEXP = /^.*\<link\s*(rel\=("|')stylesheet('|")\s*href\=("|')([^'"]*)('|"))\s*\/\>.*$/i
+@body = $stdin.read
+
+
+if OPTIONS[:js_filename]
+ count = 0
+ @body.gsub!(JS_REGEXP){|f|
+ count += 1
+ count == 1 ? "<script language=\"javascript\" src=\"#{OPTIONS[:js_filename]}\"></script>" : ''
+ }
+end
+
+if OPTIONS[:css_filename]
+ count = 0
+ @body.gsub!(CSS_REGEXP){|f|
+ count +=1
+ count == 1 ? "<link rel=\"stylesheet\" href=\"#{OPTIONS[:css_filename]}\"/>" : ''
+ }
+end
+
+$stdout.print @body
View
82 bin/update_index
@@ -0,0 +1,82 @@
+#!/usr/bin/env ruby
+
+begin
+ require 'rubygems'
+ require 'json'
+rescue LoadError
+ $stderr.puts "Install json: \"gem install json\" to continue."
+ exit -1
+end
+
+require 'optparse'
+require 'stringio'
+
+
+INSERTIONS = {
+ 'entityDefinitions' => 'entities.json',
+ 'goals' => 'goals.json',
+ 'playerData' => 'player.json',
+ 'levels' => 'levels.json',
+ 'shopItems' => 'shop.json',
+ 'tutorial' => 'tutorial.json',
+ 'version' => 'version'}
+
+CONFDIR = 'config'
+
+if ARGV.include?('--config-files')
+ puts INSERTIONS.values.map{|f| "#{CONFDIR}/#{f}"}.join("\n")
+ exit 0
+end
+
+if $stdin.tty? && ARGV.size != 1
+ $stderr.puts "Usage: #{File.basename $0} [input_file|--config-files] "
+ $stderr.puts " Update the index.html with the values of the config/*.json files"
+ $stderr.puts " --config-files\tList dependcies config fiels"
+ exit -1
+end
+
+
+
+
+def update!(input_stream, output_stream)
+ input_stream.each_line do |line|
+
+ line.gsub!(/(window\.wooga\.castle\.(#{INSERTIONS.keys.join("|")})\s*=\s*).*(;)/) do |s|
+ filename = File.join(CONFDIR, INSERTIONS[$2])
+ $1 << get_json(filename) << $3 #update with the content of the file
+ end
+
+ output_stream << line
+ end
+end
+
+
+def get_json(filename)
+ raise "File #{filename} not found" unless File.file?(filename)
+
+ contents = File.read(filename)
+ if filename =~ /goals\.json/
+ contents.gsub(/\n/,'')
+ else
+ JSON.fast_generate(JSON.parse(contents))
+ end
+rescue JSON::ParserError => e
+ $stderr.puts e.class.to_s
+ $stderr.puts "Syntax error in #{file}"
+ $stderr.puts e.message
+ exit -1
+end
+
+pipe = $stdin.tty? && !ARGV.empty?
+
+input = pipe ? File.open(ARGV[0],'r') : $stdin
+output = StringIO.new
+
+update!(input,output)
+
+input.close
+output.rewind
+real_output = pipe ? File.open(ARGV[0],'w') : $stdout
+real_output.write output.read
+real_output.close
+
View
8 bin/yuicompressor
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+BASEDIR=`dirname $0`
+PROGRAM_NAME=`basename $0`
+VERSION=2.4.7
+JAR_PATH=$BASEDIR/$PROGRAM_NAME-$VERSION.jar
+exec java -jar $JAR_PATH $*
+
View
BIN  bin/yuicompressor-2.4.7.jar
Binary file not shown
View
2,540 config/entities.json
@@ -0,0 +1,2540 @@
+{
+ "coastmap": {
+ "url": "coastmap.png"
+ },
+ "backgrounds/coast": {
+ "url": "backgrounds/coast.png"
+ },
+ "buildings/castle_construction": {
+ "url": "castles/castle_construction.png"
+ },
+ "invites/carpenter": {
+ "name": "Hire a Carpenter",
+ "cost": 200,
+ "specialistImg": "invites/carpenter.png"
+ },
+ "invites/mason": {
+ "name": "Hire a Mason",
+ "cost": 1000,
+ "specialistImg": "invites/mason.png"
+ },
+ "invites/locksmith": {
+ "name": "Hire a Locksmith",
+ "cost": 3000,
+ "specialistImg": "invites/locksmith.png"
+ },
+ "invites/roofer": {
+ "name": "Hire a Roofer",
+ "cost": 5000,
+ "specialistImg": "invites/roofer.png"
+ },
+ "invites/mechanic": {
+ "name": "Hire a Mechanic",
+ "cost": 10000,
+ "specialistImg": "invites/mechanic.png"
+ },
+ "invites/architect": {
+ "name": "Hire an Architect",
+ "cost": 20000,
+ "specialistImg": "invites/architect.png"
+ },
+ "invites/smith": {
+ "name": "Hire a Smith",
+ "cost": 30000,
+ "specialistImg": "invites/smith.png"
+ },
+ "invites/painter": {
+ "name": "Hire a Painter",
+ "cost": 40000,
+ "specialistImg": "invites/painter.png"
+ },
+ "invites/plumber": {
+ "name": "Hire a Plumber",
+ "cost": 50000,
+ "specialistImg": "invites/plumber.png"
+ },
+ "invites/landscaper": {
+ "name": "Hire a Landscaper",
+ "cost": 50000,
+ "specialistImg": "invites/landscaper.png"
+ },
+ "buildings/castle_1": {
+ "class": "castle",
+ "name": "Castle 1",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 8,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 175,
+ "population": 5,
+ "friendsToUpgrade": 1,
+ "partyInvites": [
+ "invites/carpenter"
+ ],
+ "upgradeTo": "buildings/castle_2",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_2": {
+ "class": "castle",
+ "name": "Castle 2",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 16,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 50,
+ "population": 7,
+ "friendsToUpgrade": 1,
+ "partyInvites": [
+ "invites/mason"
+ ],
+ "upgradeTo": "buildings/castle_3",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_3": {
+ "class": "castle",
+ "name": "Castle 3",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 24,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 1025,
+ "population": 9,
+ "friendsToUpgrade": 1,
+ "partyInvites": [
+ "invites/mason"
+ ],
+ "upgradeTo": "buildings/castle_4",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_4": {
+ "class": "castle",
+ "name": "Castle 4",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 32,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 300,
+ "population": 11,
+ "friendsToUpgrade": 1,
+ "partyInvites": [
+ "invites/locksmith"
+ ],
+ "upgradeTo": "buildings/castle_5",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_5": {
+ "class": "castle",
+ "name": "Castle 5",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 40,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 675,
+ "population": 13,
+ "friendsToUpgrade": 3,
+ "partyInvites": [
+ "invites/carpenter",
+ "invites/locksmith",
+ "invites/mason"
+ ],
+ "upgradeTo": "buildings/castle_6",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_6": {
+ "class": "castle",
+ "name": "Castle 6",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 48,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 750,
+ "population": 15,
+ "friendsToUpgrade": 2,
+ "partyInvites": [
+ "invites/mason",
+ "invites/roofer"
+ ],
+ "upgradeTo": "buildings/castle_7",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_7": {
+ "class": "castle",
+ "name": "Castle 7",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 56,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 925,
+ "population": 17,
+ "friendsToUpgrade": 2,
+ "partyInvites": [
+ "invites/locksmith",
+ "invites/roofer"
+ ],
+ "upgradeTo": "buildings/castle_8",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_8": {
+ "class": "castle",
+ "name": "Castle 8",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 64,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 7000,
+ "population": 19,
+ "friendsToUpgrade": 3,
+ "partyInvites": [
+ "invites/mason",
+ "invites/locksmith",
+ "invites/carpenter"
+ ],
+ "upgradeTo": "buildings/castle_9",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_9": {
+ "class": "castle",
+ "name": "Castle 9",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 72,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 500,
+ "population": 21,
+ "friendsToUpgrade": 4,
+ "partyInvites": [
+ "invites/mason",
+ "invites/locksmith",
+ "invites/roofer",
+ "invites/mechanic"
+ ],
+ "upgradeTo": "buildings/castle_10",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_10": {
+ "class": "castle",
+ "name": "Castle 10",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 80,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 8000,
+ "population": 23,
+ "friendsToUpgrade": 4,
+ "partyInvites": [
+ "invites/mason",
+ "invites/locksmith",
+ "invites/roofer",
+ "invites/mechanic"
+ ],
+ "upgradeTo": "buildings/castle_11",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_11": {
+ "class": "castle",
+ "name": "Castle 11",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 88,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 2000,
+ "population": 25,
+ "friendsToUpgrade": 4,
+ "partyInvites": [
+ "invites/mason",
+ "invites/roofer",
+ "invites/mechanic",
+ "invites/architect"
+ ],
+ "upgradeTo": "buildings/castle_12",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_12": {
+ "class": "castle",
+ "name": "Castle 12",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 96,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 12000,
+ "population": 27,
+ "friendsToUpgrade": 4,
+ "partyInvites": [
+ "invites/mason",
+ "invites/roofer",
+ "invites/mechanic",
+ "invites/architect"
+ ],
+ "upgradeTo": "buildings/castle_13",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_13": {
+ "class": "castle",
+ "name": "Castle 13",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 104,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 24000,
+ "population": 29,
+ "friendsToUpgrade": 4,
+ "partyInvites": [
+ "invites/mason",
+ "invites/roofer",
+ "invites/mechanic",
+ "invites/architect"
+ ],
+ "upgradeTo": "buildings/castle_14",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_14": {
+ "class": "castle",
+ "name": "Castle 14",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 112,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 8000,
+ "population": 31,
+ "friendsToUpgrade": 5,
+ "partyInvites": [
+ "invites/mason",
+ "invites/roofer",
+ "invites/mechanic",
+ "invites/architect",
+ "invites/smith"
+ ],
+ "upgradeTo": "buildings/castle_15",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_15": {
+ "class": "castle",
+ "name": "Castle 15",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 120,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 23000,
+ "population": 33,
+ "friendsToUpgrade": 5,
+ "partyInvites": [
+ "invites/mason",
+ "invites/roofer",
+ "invites/mechanic",
+ "invites/architect",
+ "invites/smith"
+ ],
+ "upgradeTo": "buildings/castle_16",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_16": {
+ "class": "castle",
+ "name": "Castle 16",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 128,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 1000,
+ "population": 35,
+ "friendsToUpgrade": 6,
+ "partyInvites": [
+ "invites/mason",
+ "invites/roofer",
+ "invites/mechanic",
+ "invites/architect",
+ "invites/smith",
+ "invites/painter"
+ ],
+ "upgradeTo": "buildings/castle_17",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_17": {
+ "class": "castle",
+ "name": "Castle 17",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 136,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 17200,
+ "population": 37,
+ "friendsToUpgrade": 6,
+ "partyInvites": [
+ "invites/mason",
+ "invites/roofer",
+ "invites/mechanic",
+ "invites/architect",
+ "invites/smith",
+ "invites/painter"
+ ],
+ "upgradeTo": "buildings/castle_18",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_18": {
+ "class": "castle",
+ "name": "Castle 18",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 144,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 1000,
+ "population": 39,
+ "friendsToUpgrade": 5,
+ "partyInvites": [
+ "invites/mason",
+ "invites/architect",
+ "invites/smith",
+ "invites/painter",
+ "invites/landscaper"
+ ],
+ "upgradeTo": "buildings/castle_19",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/castle_19": {
+ "class": "castle",
+ "name": "Castle 19",
+ "url": "castles.png",
+ "icon": "castles/castle-icon.png",
+ "spritey": 152,
+ "width": 5,
+ "height": 8,
+ "offsetY": -3,
+ "selectable": true,
+ "draggable": false,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "upgradeCost": 500,
+ "population": 41,
+ "friendsToUpgrade": 4,
+ "partyInvites": [
+ "invites/architect",
+ "invites/painter",
+ "invites/plumber",
+ "invites/landscaper"
+ ],
+ "upgradeTo": "buildings/castle_19",
+ "diamondCost": 0,
+ "destroyGainGold": 125,
+ "rootRoadPosition": {
+ "x": 2,
+ "y": 5
+ }
+ },
+ "buildings/poor_house": {
+ "class": "uhouse",
+ "name": "Peasant House",
+ "url": "buildings0.png",
+ "spritey": 5,
+ "icon": "buildings/poor_house-icon.png",
+ "width": 2,
+ "height": 3,
+ "offsetY": -1,
+ "selectable": true,
+ "draggable": true,
+ "unlockCondition": "level",
+ "population": 1,
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 150,
+ "diamondCost": 1,
+ "destroyGainGold": 50,
+ "contract": {
+ "requiredFood": 0,
+ "requiredTime": 180000,
+ "providedGold": 10,
+ "providedXP": 1,
+ "constructionTime": 5000
+ }
+ },
+ "buildings/villager_house": {
+ "class": "uhouse",
+ "name": "Villager's House",
+ "url": "buildings0.png",
+ "spritey": 8,
+ "icon": "buildings/villager_house-icon.png",
+ "width": 3,
+ "height": 3,
+ "offsetY": -1,
+ "selectable": true,
+ "draggable": true,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 500,
+ "diamondCost": 1,
+ "destroyGainGold": 167,
+ "contract": {
+ "requiredFood": 0,
+ "requiredTime": 300000,
+ "providedGold": 15,
+ "providedXP": 1,
+ "constructionTime": 30000
+ }
+ },
+ "buildings/bakery": {
+ "class": "house",
+ "name": "Bakery",
+ "url": "buildings20.png",
+ "spritey": 14,
+ "icon": "buildings/bakery-icon.png",
+ "width": 4,
+ "height": 4,
+ "offsetY": -2,
+ "selectable": true,
+ "draggable": true,
+ "unlockCondition": "level",
+ "unlockValue": 1,
+ "unlockCost": 10,
+ "goldCost": 800,
+ "diamondCost": 1,
+ "destroyGainGold": 267,
+ "contract": {
+ "requiredFood": 15,
+ "requiredTime": 60000,
+ "providedGold": 35,
+ "providedXP": 1,
+ "constructionTime": 60000
+ }
+ },
+ "buildings/crazy_hogs_pub": {
+ "class": "house",
+ "name": "Crazy Hogs Pub",
+ "url": "buildings30.png",
+ "spritey": 11,
+ "icon": "buildings/crazy_hogs_pub-icon.png",
+ "width": 4,
+ "height": 4,
+ "offsetY": -1,
+ "selectable": true,
+ "draggable": true,
+ "unlockCondition": "level",
+ "unlockValue": 2,
+ "unlockCost": 10,
+ "goldCost": 600,
+ "diamondCost": 2,
+ "destroyGainGold": 200,
+ "contract": {
+ "requiredFood": 40,
+ "requiredTime": 30000,
+ "providedGold": 62,
+ "providedXP": 1,
+ "constructionTime": 300000
+ }
+ },
+ "buildings/fairy_house": {
+ "class": "uhouse",
+ "name": "Fairy's House",
+ "url": "buildings0.png",
+ "spritey": 15,
+ "icon": "buildings/fairy_house-icon.png",
+ "width": 3,
+ "height": 4,
+ "offsetY": -1,
+ "selectable": true,
+ "draggable": true,
+ "unlockCondition": "level",
+ "unlockValue": 3,
+ "unlockCost": 10,
+ "goldCost": 1100,
+ "diamondCost": 3,
+ "destroyGainGold": 367,
+ "contract": {
+ "requiredFood": 0,
+ "requiredTime": 7200000,
+ "providedGold": 100,
+ "providedXP": 2,
+ "constructionTime": 600000
+ }
+ },
+ "buildings/knights_house": {
+ "class": "uhouse",
+ "name": "Knight's House",
+ "url": "buildings0.png",
+ "spritey": 11,
+ "icon": "buildings/knights_house-icon.png",
+ "width": 3,
+ "height": 4,
+ "offsetY": -2,
+ "selectable": true,
+ "draggable": true,
+ "unlockCondition": "level",
+ "unlockValue": 4,
+ "unlockCost": 10,
+ "goldCost": 800,
+ "diamondCost": 4,
+ "destroyGainGold": 267,
+ "contract": {
+ "requiredFood": 0,
+ "requiredTime": 82800000,
+ "providedGold": 200,
+ "providedXP": 28,
+ "constructionTime": 6000000
+ }
+ },
+ "buildings/dwarf_house": {
+ "class": "uhouse",
+ "name": "Dwarf's House",
+ "url": "buildings20.png",
+ "spritey": 11,
+ "icon": "buildings/dwarf_house-icon.png",
+ "width": 4,
+ "height": 3,
+ "offsetY": -1,
+ "selectable": true,
+ "draggable": true,
+ "unlockCondition": "level",
+ "unlockValue": 5,
+ "unlockCost": 10,
+ "goldCost": 1400,
+ "diamondCost": 5,
+ "destroyGainGold": 467,
+ "contract": {
+ "requiredFood": 0,
+ "requiredTime": 32400000,
+ "providedGold": 160,
+ "providedXP": 11,
+ "constructionTime": 12000000
+ }