big steppy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

977 lines
25 KiB

  1. 'use strict';
  2. var things =
  3. {
  4. "Container": Container,
  5. "Person": Person,
  6. "Cow": Cow,
  7. "Empty Car": EmptyCar,
  8. "Car": Car,
  9. "Bus": Bus,
  10. "Tram": Tram,
  11. "House": House,
  12. "Barn": Barn,
  13. "Small Skyscraper": SmallSkyscraper,
  14. "Large Skyscraper": LargeSkyscraper,
  15. "Train": Train,
  16. "Train Car": TrainCar,
  17. "Parking Garage": ParkingGarage,
  18. "Town": Town,
  19. "City": City,
  20. "Continent": Continent,
  21. "Planet": Planet,
  22. "Star": Star,
  23. "Solar System": SolarSystem,
  24. "Galaxy": Galaxy
  25. };
  26. var areas =
  27. {
  28. "Container": 0,
  29. "Person": 1,
  30. "Cow": 2,
  31. "Car": 4,
  32. "Bus": 12,
  33. "Tram": 20,
  34. "House": 150,
  35. "Barn": 300,
  36. "Small Skyscraper": 1000,
  37. "Large Skyscraper": 2000,
  38. "Train": 40,
  39. "TrainCar": 20,
  40. "Parking Garage": 750,
  41. "Town": 1e7,
  42. "City": 1e9,
  43. "Continent": 1.5e13,
  44. "Planet": 2.5e14,
  45. "Star": 3e18,
  46. "Solar System": 3e21,
  47. "Galaxy": 2e42,
  48. };
  49. var masses =
  50. {
  51. "Container": 0,
  52. "Person": 80,
  53. "Cow": 300,
  54. "Car": 1000,
  55. "Bus": 5000,
  56. "Tram": 10000,
  57. "House": 10000,
  58. "Barn": 5000,
  59. "Small Skyscraper": 10000000,
  60. "Large Skyscraper": 80000000,
  61. "Train": 50000,
  62. "Train Car": 7500,
  63. "Parking Garage": 10000000,
  64. "Town": 1,
  65. "City": 1,
  66. "Continent": 1e21,
  67. "Planet": 5.972e24,
  68. "Star": 1e40,
  69. "Solar System": 1,
  70. "Galaxy": 1
  71. };
  72. var clusters =
  73. {
  74. "Container": 0,
  75. "Person": 5,
  76. "Cow": 15,
  77. "Car": 3,
  78. "Bus": 1,
  79. "Tram": 1,
  80. "House": 5,
  81. "Barn": 1,
  82. "Small Skyscraper": 2,
  83. "Large Skyscraper": 1,
  84. "Train": 2,
  85. "Train Car": 1,
  86. "Parking Garage": 1,
  87. "Town": 1,
  88. "City": 1,
  89. "Continent": 5,
  90. "Planet": 1,
  91. "Star": 1,
  92. "Solar System": 1,
  93. "Galaxy": 1
  94. };
  95. // general logic: each step fills in a fraction of the remaining space
  96. function fill_area(area, weights, variance=0.15)
  97. {
  98. area = area + Math.random() * variance * 2 - variance;
  99. var result = [];
  100. var candidates = [];
  101. for (var key in weights) {
  102. if (weights.hasOwnProperty(key)) {
  103. candidates.push({"name": key, "area": areas[key], "weight": weights[key]});
  104. }
  105. }
  106. candidates = candidates.sort(function (x,y) {
  107. return x.area - y.area;
  108. });
  109. while(candidates.length > 0) {
  110. var candidate = candidates.pop();
  111. if (candidate.area > area)
  112. continue;
  113. var max = Math.floor(area / candidate.area);
  114. var limit = Math.min(max, 100);
  115. var count = 0;
  116. var loopvar = limit;
  117. // for small amounts, actually do the randomness
  118. // the first few ones get a much better shot
  119. while (loopvar > 0) {
  120. if (loopvar <= clusters[candidate.name])
  121. count += 1;
  122. else
  123. count += Math.random() < candidate.weight ? 1 : 0;
  124. --loopvar;
  125. }
  126. if (limit < max) {
  127. count += Math.round((max-limit) * candidate.weight);
  128. }
  129. area -= count * candidate.area;
  130. if (count > 0)
  131. result.push(new things[candidate.name](count));
  132. }
  133. if (result.length > 0)
  134. return new Container(result);
  135. else
  136. return new Container([new Person(1)]);
  137. }
  138. // describes everything in the container
  139. function describe_all(contents,verbose=true,except=[]) {
  140. var things = [];
  141. for (var key in contents) {
  142. if (contents.hasOwnProperty(key) && !except.includes(key)) {
  143. things.push(contents[key].describe(verbose));
  144. }
  145. }
  146. return merge_things(things);
  147. }
  148. function random_desc(list, odds=1) {
  149. if (Math.random() < odds)
  150. return list[Math.floor(Math.random() * list.length)];
  151. else
  152. return "";
  153. }
  154. // combine strings into a list with proper grammar
  155. function merge_things(list,semicolons=false) {
  156. if (list.length == 0) {
  157. return "";
  158. } else if (list.length == 1) {
  159. return list[0];
  160. } else if (list.length == 2) {
  161. return list[0] + " and " + list[1];
  162. } else {
  163. var result = "";
  164. list.slice(0,list.length-1).forEach(function(term) {
  165. result += term + ", ";
  166. });
  167. result += "and " + list[list.length-1];
  168. return result;
  169. }
  170. }
  171. // combine the adjectives for something into a single string
  172. function merge_desc(list) {
  173. var result = "";
  174. list.forEach(function(term) {
  175. if (term != "")
  176. result += term + " ";
  177. });
  178. // knock off the last space
  179. if (result.length > 0) {
  180. result = result.substring(0, result.length - 1);
  181. }
  182. return result;
  183. }
  184. // maybe make this something that approximates a
  185. // normal distribution; doing this 15,000,000 times is bad...
  186. // solution: only a few are random lul
  187. // improvement: take up to 100 samples, then use that to scale the final result
  188. function distribution(min, max, samples) {
  189. var result = 0;
  190. var limit = Math.min(100,samples);
  191. if (limit < samples) {
  192. for (let i = 0; i < limit; i++) {
  193. result += (i/10 + 1) * Math.floor(Math.random() * (max - min + 1) + min);
  194. }
  195. result = Math.round((result / 595) * samples * (max - min) + min);
  196. } else {
  197. for (let i = 0; i < limit; i++) {
  198. result += Math.floor(Math.random() * (max - min + 1) + min);
  199. }
  200. }
  201. return result;
  202. }
  203. function defaultArea(thing) {
  204. return areas[thing.name];
  205. }
  206. function defaultMass(thing) {
  207. return masses[thing.name];
  208. }
  209. function defaultMerge(thing) {
  210. return function(container) {
  211. var newCount = this.count + container.count;
  212. var newThing = new things[thing.name](newCount);
  213. newThing.contents = {};
  214. for (var key in this.contents) {
  215. if (this.contents.hasOwnProperty(key)) {
  216. newThing.contents[key] = this.contents[key];
  217. }
  218. }
  219. for (key in container.contents) {
  220. if (container.contents.hasOwnProperty(key)) {
  221. if (this.contents.hasOwnProperty(key)) {
  222. newThing.contents[key] = this.contents[key].merge(container.contents[key]);
  223. } else {
  224. newThing.contents[key] = container.contents[key];
  225. }
  226. }
  227. }
  228. return newThing;
  229. };
  230. }
  231. function defaultSum(thing) {
  232. return function() {
  233. var counts = {};
  234. if (thing.name != "Container")
  235. counts[thing.name] = thing.count;
  236. for (var key in thing.contents) {
  237. if (thing.contents.hasOwnProperty(key)) {
  238. var subcount = thing.contents[key].sum();
  239. for (var subkey in subcount) {
  240. if (!counts.hasOwnProperty(subkey)) {
  241. counts[subkey] = 0;
  242. }
  243. counts[subkey] += subcount[subkey];
  244. }
  245. }
  246. }
  247. return counts;
  248. };
  249. }
  250. function defaultSumProperty(thing) {
  251. return function(prop) {
  252. var total = 0;
  253. total += thing[prop] * thing.count;
  254. for (var key in thing.contents) {
  255. if (thing.contents.hasOwnProperty(key)) {
  256. total += thing.contents[key].sum_property(prop);
  257. }
  258. }
  259. return total;
  260. };
  261. }
  262. function defaultAddContent(thing) {
  263. return function(name, min, max, count) {
  264. if (min == max) {
  265. let object = new things[name](min*count);
  266. thing.contents[object.name] = object;
  267. } else {
  268. let object = new things[name](distribution(min, max, count));
  269. thing.contents[object.name] = object;
  270. }
  271. };
  272. }
  273. function DefaultEntity() {
  274. this.sum = defaultSum;
  275. this.area = defaultArea;
  276. this.mass = defaultMass;
  277. this.sum_property = defaultSumProperty;
  278. this.merge = defaultMerge;
  279. this.addContent = defaultAddContent;
  280. return this;
  281. }
  282. // god I love reinventing the wheel
  283. function copy_defaults(self,proto) {
  284. for (var key in proto) {
  285. if (proto.hasOwnProperty(key)) {
  286. self[key] = proto[key](self);
  287. }
  288. }
  289. }
  290. function Container(contents = []) {
  291. this.name = "Container";
  292. copy_defaults(this,new DefaultEntity());
  293. if (Number.isInteger(contents))
  294. this.count = contents;
  295. else
  296. this.count = 0;
  297. this.contents = {};
  298. for (var i=0; i < contents.length; i++) {
  299. this.contents[contents[i].name] = contents[i];
  300. }
  301. for (var key in this.contents) {
  302. if (this.contents.hasOwnProperty(key)) {
  303. this.count += this.contents[key].count;
  304. }
  305. }
  306. this.describe = function(verbose = true) {
  307. return describe_all(this.contents,verbose);
  308. };
  309. return this;
  310. }
  311. function Person(count = 1) {
  312. this.name = "Person";
  313. copy_defaults(this,new DefaultEntity());
  314. this.count = count;
  315. this.contents = {};
  316. this.describeOne = function (verbose=true) {
  317. var body = random_desc(["skinny","fat","tall","short","stocky","spindly"], (verbose ? 0.6 : 0));
  318. var sex = random_desc(["male", "female"], (verbose ? 1 : 0));
  319. var species = "";
  320. if (!humanMode)
  321. species = random_desc(["wolf","cat","dog","squirrel","horse","hyena","fox","jackal","crux","sergal"]);
  322. else
  323. species = random_desc(["jogger","police officer","road worker","pastor","dog-walker","clerk","accountant","CEO","millionaire","mailman"]);
  324. return "a " + merge_desc([body,sex,species]);
  325. };
  326. this.describe = function(verbose=true) {
  327. if (verbose) {
  328. if (count <= 3) {
  329. var list = [];
  330. for (var i = 0; i < count; i++) {
  331. list.push(this.describeOne(this.count <= 2));
  332. }
  333. return merge_things(list);
  334. } else {
  335. return this.count + " people";
  336. }
  337. } else {
  338. return (this.count > 1 ? this.count + " people" : "a person");
  339. }
  340. };
  341. return this;
  342. }
  343. function Cow(count = 1) {
  344. this.name = "Cow";
  345. copy_defaults(this,new DefaultEntity());
  346. this.count = count;
  347. this.contents = {};
  348. this.describeOne = function (verbose=true) {
  349. var body = random_desc(["skinny","fat","tall","short","stocky","spindly"], (verbose ? 0.6 : 0));
  350. var sex = random_desc(["male", "female"], (verbose ? 1 : 0));
  351. return "a " + merge_desc([body,sex,"cow"]);
  352. };
  353. this.describe = function(verbose=true) {
  354. if (verbose) {
  355. if (count <= 3) {
  356. var list = [];
  357. for (var i = 0; i < count; i++) {
  358. list.push(this.describeOne(this.count <= 2));
  359. }
  360. return merge_things(list);
  361. } else {
  362. return this.count + " cattle";
  363. }
  364. } else {
  365. return (this.count > 1 ? this.count + " cattle" : "a cow");
  366. }
  367. };
  368. return this;
  369. }
  370. function EmptyCar(count = 1) {
  371. this.name = "Car";
  372. copy_defaults(this,new DefaultEntity());
  373. this.count = count;
  374. this.contents = {};
  375. this.describeOne = function(verbose=true) {
  376. var color = random_desc(["black","black","gray","gray","blue","red","tan","white","white"]);
  377. var adjective = random_desc(["rusty","brand-new"],0.3);
  378. var type = random_desc(["SUV","coupe","sedan","truck","van","convertible"]);
  379. return "a parked " + merge_desc([adjective,color,type]);
  380. };
  381. this.describe = function(verbose = true) {
  382. if (verbose) {
  383. if (this.count <= 3) {
  384. var list = [];
  385. for (var i = 0; i < this.count; i++) {
  386. list.push(this.describeOne());
  387. }
  388. return merge_things(list);
  389. } else {
  390. return this.count + " parked cars";
  391. }
  392. } else {
  393. return (this.count > 1 ? this.count + " parked cars" : "a parked car");
  394. }
  395. };
  396. }
  397. function Car(count = 1) {
  398. this.name = "Car";
  399. copy_defaults(this,new DefaultEntity());
  400. this.count = count;
  401. this.contents = {};
  402. this.addContent("Person", 1, 4, count);
  403. this.describeOne = function(verbose=true) {
  404. var color = random_desc(["black","black","gray","gray","blue","red","tan","white","white"], (verbose ? 1 : 0));
  405. var adjective = random_desc(["rusty","brand-new"], (verbose ? 0.3 : 0));
  406. var type = random_desc(["SUV","coupe","sedan","truck","van","convertible"]);
  407. return "a " + merge_desc([adjective,color,type]);
  408. };
  409. this.describe = function(verbose = true) {
  410. if (verbose) {
  411. if (this.count <= 3) {
  412. var list = [];
  413. for (var i = 0; i < this.count; i++) {
  414. list.push(this.describeOne(this.count < 2));
  415. }
  416. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  417. } else {
  418. return this.count + " cars with " + describe_all(this.contents,verbose) + " inside";
  419. }
  420. } else {
  421. return (this.count > 1 ? this.count + " cars" : "a car");
  422. }
  423. };
  424. }
  425. function Bus(count = 1) {
  426. this.name = "Bus";
  427. copy_defaults(this,new DefaultEntity());
  428. this.count = count;
  429. this.contents = {};
  430. this.addContent("Person",2,30,count);
  431. this.describeOne = function(verbose=true) {
  432. var adjective = random_desc(["rusty","brand-new"], (verbose ? 0.3 : 0));
  433. var color = random_desc(["black","tan","gray"], (verbose ? 1 : 0));
  434. var type = random_desc(["bus","double-decker bus","articulating bus"]);
  435. return "a " + merge_desc([adjective,color,type]);
  436. };
  437. this.describe = function(verbose = true) {
  438. if (verbose) {
  439. if (this.count <= 3) {
  440. var list = [];
  441. for (var i = 0; i < this.count; i++) {
  442. list.push(this.describeOne(this.count < 2));
  443. }
  444. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  445. } else {
  446. return this.count + " buses with " + describe_all(this.contents,verbose) + " inside";
  447. }
  448. } else {
  449. return (this.count > 1 ? this.count + " buses" : "a bus");
  450. }
  451. };
  452. }
  453. function Tram(count = 1) {
  454. this.name = "Tram";
  455. copy_defaults(this,new DefaultEntity());
  456. this.count = count;
  457. this.contents = {};
  458. this.addContent("Person",10,50,count);
  459. this.describeOne = function(verbose=true) {
  460. var adjective = random_desc(["rusty","weathered"], (verbose ? 0.3 : 0));
  461. var color = random_desc(["blue","brown","gray"], (verbose ? 1 : 0));
  462. var type = random_desc(["tram"]);
  463. return "a " + merge_desc([adjective,color,type]);
  464. };
  465. this.describe = function(verbose = true) {
  466. if (verbose) {
  467. if (this.count == 1) {
  468. var list = [];
  469. for (var i = 0; i < this.count; i++) {
  470. list.push(this.describeOne(verbose));
  471. }
  472. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  473. } else {
  474. return this.count + " trams with " + describe_all(this.contents,verbose) + " inside";
  475. }
  476. } else {
  477. return (this.count > 1 ? this.count + " trams" : "a tram");
  478. }
  479. };
  480. this.anal_vore = function() {
  481. return "You slide " + this.describe() + " up your tight ass";
  482. };
  483. }
  484. function Train(count = 1) {
  485. this.name = "Train";
  486. copy_defaults(this,new DefaultEntity());
  487. this.count = count;
  488. this.contents = {};
  489. this.addContent("Person", 1, 4, count);
  490. this.addContent("Train Car", 2, 10, count);
  491. this.describeOne = function(verbose=true) {
  492. var adjective = random_desc(["rusty","brand-new"], (verbose ? 0.3 : 0));
  493. var color = random_desc(["black","tan","gray"], (verbose ? 1 : 0));
  494. var type = random_desc(["train","passenger train","freight train"]);
  495. return "a " + merge_desc([adjective,color,type]);
  496. };
  497. this.describe = function(verbose = true) {
  498. if (verbose) {
  499. if (this.count == 1) {
  500. var list = [];
  501. for (var i = 0; i < this.count; i++) {
  502. list.push(this.describeOne(verbose));
  503. }
  504. return merge_things(list) + " with " + this.contents["Person"].describe(false) + " in the engine and " + this.contents["Train Car"].describe() + " attached";
  505. } else {
  506. return this.count + " trains with " + this.contents["Person"].describe(false) + " in the engine and " + this.contents["Train Car"].describe() + " attached";
  507. }
  508. } else {
  509. return (this.count > 1 ? this.count + " trains" : "a train");
  510. }
  511. };
  512. this.anal_vore = function() {
  513. var cars = (this.contents["Train Car"].count == 1 ? this.contents["Train Car"].describe() + " follows it inside" : this.contents["Train Car"].describe() + " are pulled slowly inside");
  514. return "You snatch up " + this.describeOne() + " and stuff it into your pucker, moaning as " + cars;
  515. };
  516. }
  517. function TrainCar(count = 1) {
  518. this.name = "Train Car";
  519. copy_defaults(this,new DefaultEntity());
  520. this.count = count;
  521. this.contents = {};
  522. this.addContent("Person",10,40,count);
  523. this.describeOne = function(verbose=true) {
  524. var adjective = random_desc(["rusty","brand-new"], (verbose ? 0.3 : 0));
  525. var color = random_desc(["black","tan","gray"], (verbose ? 1 : 0));
  526. var type = random_desc(["train car","passenger train car","freight train car"]);
  527. return "a " + merge_desc([adjective,color,type]);
  528. };
  529. this.describe = function(verbose = true) {
  530. if (verbose) {
  531. return (this.count > 1 ? this.count + " train cars" : "a train car") + " with " + describe_all(this.contents) + " inside";
  532. } else {
  533. return (this.count > 1 ? this.count + " train cars" : "a train car");
  534. }
  535. };
  536. }
  537. function House(count = 1) {
  538. this.name = "House";
  539. copy_defaults(this,new DefaultEntity());
  540. this.count = count;
  541. this.contents = {};
  542. this.addContent("Person",0,8,count);
  543. this.addContent("Empty Car",0,2,count);
  544. this.describeOne = function(verbose=true) {
  545. var size = random_desc(["little","two-story","large"], (verbose ? 0.5 : 0));
  546. var color = random_desc(["blue","white","gray","tan","green"], (verbose ? 0.5 : 0));
  547. var name = random_desc(["house","house","house","house","house","trailer"], 1);
  548. return "a " + merge_desc([size,color,name]);
  549. };
  550. this.describe = function(verbose = true) {
  551. if (verbose) {
  552. if (this.count <= 3) {
  553. var list = [];
  554. for (var i = 0; i < this.count; i++) {
  555. list.push(this.describeOne(this.count < 2));
  556. }
  557. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  558. } else {
  559. return this.count + " homes with " + describe_all(this.contents,verbose) + " inside";
  560. }
  561. } else {
  562. return (this.count > 1 ? this.count + " houses" : "a house");
  563. }
  564. };
  565. }
  566. function Barn(count = 1) {
  567. this.name = "Barn";
  568. copy_defaults(this,new DefaultEntity());
  569. this.count = count;
  570. this.contents = {};
  571. this.addContent("Person",0,2,count);
  572. this.addContent("Cow",30,70,count);
  573. this.describeOne = function(verbose=true) {
  574. var size = random_desc(["little","big","large"], (verbose ? 0.5 : 0));
  575. var color = random_desc(["blue","white","gray","tan","green"], (verbose ? 0.5 : 0));
  576. var name = random_desc(["barn","barn","barn","barn","barn","farmhouse"], 1);
  577. return "a " + merge_desc([size,color,name]);
  578. };
  579. this.describe = function(verbose = true) {
  580. if (verbose) {
  581. if (this.count <= 3) {
  582. var list = [];
  583. for (var i = 0; i < this.count; i++) {
  584. list.push(this.describeOne(this.count < 2));
  585. }
  586. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  587. } else {
  588. return this.count + " barns with " + describe_all(this.contents,verbose) + " inside";
  589. }
  590. } else {
  591. return (this.count > 1 ? this.count + " barns" : "a barn");
  592. }
  593. };
  594. }
  595. function SmallSkyscraper(count = 1) {
  596. this.name = "Small Skyscraper";
  597. copy_defaults(this,new DefaultEntity());
  598. this.count = count;
  599. this.contents = {};
  600. this.addContent("Person",50,500,count);
  601. this.addContent("Empty Car",10,50,count);
  602. this.describeOne = function(verbose=true) {
  603. var color = random_desc(["blue","white","gray","tan","green"], (verbose ? 0.5 : 0));
  604. var name = random_desc(["skyscraper","office tower","office building"], 1);
  605. return "a " + merge_desc([color,name]);
  606. };
  607. this.describe = function(verbose = true) {
  608. if (verbose) {
  609. if (this.count <= 3) {
  610. var list = [];
  611. for (var i = 0; i < this.count; i++) {
  612. list.push(this.describeOne(this.count < 2));
  613. }
  614. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  615. } else {
  616. return this.count + " small skyscrapers with " + describe_all(this.contents,verbose) + " inside";
  617. }
  618. } else {
  619. return (this.count > 1 ? this.count + " small skyscrapers" : "a small skyscraper");
  620. }
  621. };
  622. }
  623. function LargeSkyscraper(count = 1) {
  624. this.name = "Large Skyscraper";
  625. copy_defaults(this,new DefaultEntity());
  626. this.count = count;
  627. this.contents = {};
  628. this.addContent("Person",150,1500,count);
  629. this.addContent("Empty Car",20,100,count);
  630. this.describeOne = function(verbose=true) {
  631. var color = random_desc(["blue","white","gray","tan","green"], (verbose ? 0.5 : 0));
  632. var name = random_desc(["skyscraper","office tower","office building"], 1);
  633. return "a " + merge_desc(["towering",color,name]);
  634. };
  635. this.describe = function(verbose = true) {
  636. if (verbose) {
  637. if (this.count <= 3) {
  638. var list = [];
  639. for (var i = 0; i < this.count; i++) {
  640. list.push(this.describeOne(this.count < 2));
  641. }
  642. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  643. } else {
  644. return this.count + " large skyscrapers with " + describe_all(this.contents,verbose) + " inside";
  645. }
  646. } else {
  647. return (this.count > 1 ? this.count + " large skyscrapers" : "a large skyscraper");
  648. }
  649. };
  650. }
  651. function ParkingGarage(count = 1) {
  652. this.name = "Parking Garage";
  653. copy_defaults(this,new DefaultEntity());
  654. this.count = count;
  655. this.contents = {};
  656. this.addContent("Person",10,200,count);
  657. this.addContent("Empty Car",100,300,count);
  658. this.addContent("Car",5,30,count);
  659. this.describeOne = function(verbose=true) {
  660. return "a parking garage";
  661. };
  662. this.describe = function(verbose = true) {
  663. if (verbose) {
  664. return (this.count == 1 ? "a parking garage" : this.count + " parking garages") + " with " + describe_all(this.contents, verbose) + " inside";
  665. } else {
  666. return (this.count == 1 ? "a parking garage" : this.count + " parking garages");
  667. }
  668. };
  669. }
  670. function Town(count = 1) {
  671. this.name = "Town";
  672. copy_defaults(this,new DefaultEntity());
  673. this.count = count;
  674. this.contents = {};
  675. this.addContent("Person",500,1000,count);
  676. this.addContent("House",200,400,count);
  677. this.addContent("Empty Car",200,800,count);
  678. this.addContent("Car",50,100,count);
  679. this.addContent("Bus",5,25,count);
  680. this.addContent("Train",5,25,count);
  681. this.describe = function(verbose = true) {
  682. if (verbose) {
  683. return (this.count == 1 ? "a town" : this.count + " towns") + " with " + describe_all(this.contents, verbose) + " in " + (this.count == 1 ? "it" : "them");
  684. } else {
  685. return (this.count == 1 ? "a town" : this.count + " towns");
  686. }
  687. };
  688. }
  689. function City(count = 1) {
  690. this.name = "City";
  691. copy_defaults(this,new DefaultEntity());
  692. this.count = count;
  693. this.contents = {};
  694. this.addContent("Person",1000,15000,count);
  695. this.addContent("House",500,1000,count);
  696. this.addContent("Empty Car",2500,3750,count);
  697. this.addContent("Car",500,1000,count);
  698. this.addContent("Bus",50,100,count);
  699. this.addContent("Train",10,50,count);
  700. this.addContent("Tram",5,25,count);
  701. this.addContent("Small Skyscraper",10,50,count);
  702. this.addContent("Large Skyscraper",5,20,count);
  703. this.addContent("Parking Garage",5,10,count);
  704. this.describe = function(verbose = true) {
  705. if (verbose) {
  706. return (this.count == 1 ? "a city" : this.count + " cities") + " with " + describe_all(this.contents, verbose) + " in " + (this.count == 1 ? "it" : "them");
  707. } else {
  708. return (this.count == 1 ? "a city" : this.count + " cities");
  709. }
  710. };
  711. }
  712. function Continent(count = 1) {
  713. this.name = "Continent";
  714. copy_defaults(this,new DefaultEntity());
  715. this.count = count;
  716. this.contents = {};
  717. this.addContent("Person",100000,1500000,count);
  718. this.addContent("House",500,10000,count);
  719. this.addContent("Car",2500,37500,count);
  720. this.addContent("Train",50,100,count);
  721. this.addContent("Town",100,200,count);
  722. this.addContent("City",5,10,count);
  723. this.describe = function(verbose = true) {
  724. if (verbose) {
  725. return (this.count == 1 ? "a continent" : this.count + " continents") + " with " + describe_all(this.contents, verbose) + " on " + (this.count == 1 ? "it" : "them");
  726. } else {
  727. return (this.count == 1 ? "a continent" : this.count + " continents");
  728. }
  729. };
  730. }
  731. function Planet(count = 1) {
  732. this.name = "Planet";
  733. copy_defaults(this,new DefaultEntity());
  734. this.count = count;
  735. this.contents = {};
  736. this.addContent("Continent",4,9,count);
  737. this.describe = function(verbose = true) {
  738. if (verbose) {
  739. return (this.count == 1 ? "a planet" : this.count + " planets") + " with " + describe_all(this.contents, verbose) + " on " + (this.count == 1 ? "it" : "them");
  740. } else {
  741. return (this.count == 1 ? "a planet" : this.count + " planets");
  742. }
  743. };
  744. }
  745. function Star(count = 1) {
  746. this.name = "Star";
  747. copy_defaults(this,new DefaultEntity());
  748. this.count = count;
  749. this.contents = {};
  750. this.describe = function(verbose = true) {
  751. return (this.count == 1 ? "a star" : this.count + " stars");
  752. };
  753. }
  754. function SolarSystem(count = 1) {
  755. this.name = "Solar System";
  756. copy_defaults(this,new DefaultEntity());
  757. this.count = count;
  758. this.contents = {};
  759. this.addContent("Star",1,1,count);
  760. this.addContent("Planet",5,15,count);
  761. this.describe = function(verbose = true) {
  762. if (verbose) {
  763. return (this.count == 1 ? "a solar system" : this.count + " solar systems") + " made up of " + describe_all(this.contents, verbose);
  764. } else {
  765. return (this.count == 1 ? "a solar system" : this.count + " solar systems");
  766. }
  767. };
  768. }
  769. function Galaxy(count = 1) {
  770. this.name = "Galaxy";
  771. copy_defaults(this,new DefaultEntity());
  772. this.count = count;
  773. this.contents = {};
  774. this.addContent("Star",1e9,500e9,count);
  775. this.addContent("Solar System",1e8,500e8,count);
  776. this.describe = function(verbose = true) {
  777. if (verbose) {
  778. return (this.count == 1 ? "a galaxy" : this.count + " galaxies") + " made up of " + describe_all(this.contents, verbose);
  779. } else {
  780. return (this.count == 1 ? "a galaxy" : this.count + " galaxies");
  781. }
  782. };
  783. }