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.
 
 
 

1530 lines
41 KiB

  1. 'use strict';
  2. var things =
  3. {
  4. "Container": {
  5. "Container": Container,
  6. mass: 0,
  7. area: 0,
  8. clusters: 0,
  9. cluster_chances: 0,
  10. contents: [],
  11. descriptor: ["", ""]
  12. },
  13. //Creatures
  14. "Person": {
  15. "Person": Person,
  16. mass: 80,
  17. area: .33,
  18. clusters: 5,
  19. cluster_chances: .8,
  20. contents: [],
  21. descriptor: ["a person", "people"]
  22. },
  23. "Human": {
  24. "Human": Human,
  25. mass: 80,
  26. area: .33,
  27. clusters: 5,
  28. cluster_chances: .8,
  29. contents: [],
  30. descriptor: ["a person", "people"]
  31. },
  32. "Cow": {
  33. "Cow": Cow,
  34. mass: 300,
  35. area: 2,
  36. clusters: 15,
  37. cluster_chances: .5,
  38. contents: [],
  39. descriptor: ["a cow", "cattle"]
  40. },
  41. "Micro": {
  42. "Micro": Micro,
  43. mass: .01,
  44. area: .05,
  45. clusters: 50,
  46. cluster_chances: 1,
  47. contents: [],
  48. descriptor: ["a micro", "micros"]
  49. },
  50. "Macro": {
  51. "Macro": Macro,
  52. mass: 8e4,
  53. area: 100,
  54. clusters: 0,
  55. cluster_chances: 0,
  56. contents: [],
  57. descriptor: ["a smaller macro", "smaller macros"]
  58. },
  59. //Vehicles
  60. "Empty Car": {
  61. "Empty Car": EmptyCar,
  62. mass: 1000,
  63. area: 4,
  64. clusters: 2,
  65. cluster_chances: .3,
  66. contents: [],
  67. descriptor: ["a parked car", "parked cars"]
  68. },
  69. "Car": {
  70. "Car": Car,
  71. mass: 1000,
  72. area: 4,
  73. clusters: 4,
  74. cluster_chances: .5,
  75. contents: [["Person",1,4]],
  76. descriptor: ["a car", "cars"]
  77. },
  78. "Bus": {
  79. "Bus": Bus,
  80. mass: 5000,
  81. area: 12,
  82. clusters: 1,
  83. cluster_chances: .25,
  84. contents: [["Person",2,30]],
  85. descriptor: ["a bus", "busses"]
  86. },
  87. "Tram": {
  88. "Tram": Tram,
  89. mass: 1e4,
  90. area: 20,
  91. clusters: 1,
  92. cluster_chances: .2,
  93. contents: [["Person",10,50]],
  94. descriptor: ["a tram", "trams"]
  95. },
  96. "Train": {
  97. "Train": Train,
  98. mass: 5e4,
  99. area: 40,
  100. clusters: 2,
  101. cluster_chances: .1,
  102. contents: [["Person",1,4,"engine"],["Train Car",2,10]],
  103. descriptor: ["a train", "trains"]
  104. },
  105. "Train Car": {
  106. "Train Car": TrainCar,
  107. mass: 7500,
  108. area: 20,
  109. clusters: 1,
  110. cluster_chances: .05,
  111. contents: [["Person",10,40]],
  112. descriptor: ["a train car", "train cars"]
  113. },
  114. "Business Jet": {
  115. "Business Jet": BusinessJet,
  116. mass: 6500,
  117. area: 50,
  118. clusters: 1,
  119. cluster_chances: .05,
  120. contents: [["Person",2,9]],
  121. descriptor: ["a business jet", "business jets"]
  122. },
  123. "Airliner": {
  124. "Airliner": Airliner,
  125. mass: 6500,
  126. area: 50,
  127. clusters: 1,
  128. cluster_chances: .05,
  129. contents: [["Person",5,300]],
  130. descriptor: ["an airliner", "airliners"]
  131. },
  132. //Buildings
  133. "House": {
  134. "House": House,
  135. mass: 1e4,
  136. area: 150,
  137. clusters: 5,
  138. cluster_chances: .5,
  139. contents: [["Person",0,8],["Empty Car",0,2]],
  140. descriptor: ["house", "houses"]
  141. },
  142. "Business": {
  143. "Business": Business,
  144. mass: 5e4,
  145. area: 400,
  146. clusters: 5,
  147. cluster_chances: .25,
  148. contents: [["Person",0,30],["Car",0,5],["Empty Car",0,20]],
  149. descriptor: ["a local business", "buildings"]
  150. },
  151. "Barn": {
  152. "Barn": Barn,
  153. mass: 5e3,
  154. area: 300,
  155. clusters: 1,
  156. cluster_chances: .1,
  157. contents: [["Person",0,2],["Cow",30,70]],
  158. descriptor: ["a barn", "barns"]
  159. },
  160. "Small Skyscraper": {
  161. "Small Skyscraper": SmallSkyscraper,
  162. mass: 1e7,
  163. area: 1000,
  164. clusters: 2,
  165. cluster_chances: .25,
  166. contents: [["Person",150,750],["Empty Car",10,50]],
  167. descriptor: ["a small skyscraper", "small skyscrapers"]
  168. },
  169. "Large Skyscraper": {
  170. "Large Skyscraper": LargeSkyscraper,
  171. mass: 8e7,
  172. area: 2000,
  173. clusters: 1,
  174. cluster_chances: .25,
  175. contents: [["Person",500,1500],["Empty Car",20,100]],
  176. descriptor: ["a large skyscraper", "large skyscrapers"]
  177. },
  178. "Parking Garage": {
  179. "Parking Garage": ParkingGarage,
  180. mass: 1e7,
  181. area: 750,
  182. clusters: 1,
  183. cluster_chances: .1,
  184. contents: [["Person",10,200],["Empty Car",100,300],["Car",5,30]],
  185. descriptor: ["a parking garage", "parking garages"]
  186. },
  187. //Places
  188. "Town": {
  189. "Town": Town,
  190. mass: 1,
  191. area: 1e7,
  192. clusters: 5,
  193. cluster_chances: .1,
  194. contents: [["Person",10000,100000],["House",5000,50000],["Empty Car",200,800],["Car",500,80000],["Bus",5,25],["Train",5,25],["Business",500,5000]],
  195. descriptor: ["a town", "towns"]
  196. },
  197. "City": {
  198. "City": City,
  199. mass: 1,
  200. area: 1e9,
  201. clusters: 0,
  202. cluster_chances: .2,
  203. contents: [["Person",100000,1500000],["House",20000,200000],["Empty Car",10000,100000],["Car",7500,125000],["Bus",200,400],["Train",10,50],["Tram",25,100],["Small Skyscraper",50,300],["Large Skyscraper",10,75],["Parking Garage",5,10],["Business",2000,10000]],
  204. descriptor: ["a city", "cities"]
  205. },
  206. "Continent": {
  207. "Continent": Continent,
  208. mass: 1e21,
  209. area: 1.5e13,
  210. clusters: 5,
  211. cluster_chances: .5,
  212. contents: [["Person",1000000,15000000],["House",2500,10000],["Car",25000,375000],["Train",50,500],["Town",500,1000],["City",50,250],["Business",250,1000]],
  213. descriptor: ["a continent", "continents"]
  214. },
  215. "Planet": {
  216. "Planet": Planet,
  217. mass: 5.972e24,
  218. area: 2.5e14,
  219. clusters: 0,
  220. cluster_chances: 1,
  221. contents: [["Continent",4,9]],
  222. descriptor: ["a planet", "planets"]
  223. },
  224. "Star": {
  225. "Star": Star,
  226. mass: 1e40,
  227. area: 3e18,
  228. clusters: 1,
  229. cluster_chances: 1,
  230. contents: [],
  231. descriptor: ["a star", "stars"]
  232. },
  233. "Solar System": {
  234. "Solar System": SolarSystem,
  235. mass: 1,
  236. area: 3e21,
  237. clusters: 1,
  238. cluster_chances: 1,
  239. contents: [["Star",1,1],["Planet",5,15]],
  240. descriptor: ["a solar system", "solar systems"]
  241. },
  242. "Galaxy": {
  243. "Galaxy": Galaxy,
  244. mass: 1,
  245. area: 2e45,
  246. clusters: 1,
  247. cluster_chances: 1,
  248. contents: [["Star",1e9,500e9],["Solar System",1e8,500e8]],
  249. descriptor: ["a galaxy", "galaxies"]
  250. },
  251. "Cluster": {
  252. "Cluster": Cluster,
  253. mass: 1,
  254. area: 2e49,
  255. clusters: 1,
  256. cluster_chances: 1,
  257. contents: [["Galaxy",200,5000]],
  258. descriptor: ["a cluster", "clusters"]
  259. },
  260. "Universe": {
  261. "Universe": Universe,
  262. mass: 1,
  263. area: 7e53,
  264. clusters: 1,
  265. cluster_chances: 1,
  266. contents: [["Cluster",1.5e9,2.5e9]],
  267. descriptor: ["a universe", "universes"]
  268. },
  269. "Multiverse": {
  270. "Multiverse": Multiverse,
  271. mass: 1,
  272. area: 5e56,
  273. clusters: 1,
  274. cluster_chances: 1,
  275. contents: [["Universe",100,1000]],
  276. descriptor: ["a multiverse", "multiverses"]
  277. },
  278. //Military
  279. "Soldier": {
  280. "Soldier": Soldier,
  281. mass: 80,
  282. area: 1,
  283. clusters: 2,
  284. cluster_chances: .2,
  285. contents: [],
  286. descriptor: ["a soldier","soldiers"]
  287. },
  288. "Tank": {
  289. "Tank": Tank,
  290. mass: 5000,
  291. area: 20,
  292. clusters: 2,
  293. cluster_chances: .25,
  294. contents: [["Soldier",3,5]],
  295. descriptor: ["a tank", "tanks"]
  296. },
  297. "Artillery": {
  298. "Artillery": Artillery,
  299. mass: 7000,
  300. area: 25,
  301. clusters: 3,
  302. cluster_chances: .5,
  303. contents: [["Soldier",4,6]],
  304. descriptor: ["an artillery tank", "artillery tanks"]
  305. },
  306. "Helicopter": {
  307. "Helicopter": Helicopter,
  308. mass: 1500,
  309. area: 12,
  310. clusters: 0,
  311. cluster_chances: 0,
  312. contents: [["Soldier",4,16]],
  313. descriptor: ["a helicoptor", "helicoptors"]
  314. },
  315. "Squad": {
  316. "Squad": Squad,
  317. mass: 1,
  318. area: 30,
  319. clusters: 20,
  320. cluster_chances: .05,
  321. contents: [["Soldier",6,9]],
  322. descriptor: ["a squad", "squads"]
  323. },
  324. "Platoon": {
  325. "Platoon": Platoon,
  326. mass: 100,
  327. area: 150,
  328. clusters: 2,
  329. cluster_chances: .1,
  330. contents: [["Soldier",16,44]],
  331. descriptor: ["a military platoon", "platoons"]
  332. },
  333. "Company": {
  334. "Company": Company,
  335. mass: 500,
  336. area: 600,
  337. clusters: 2,
  338. cluster_chances: .1,
  339. contents: [["Soldier",60,200]],
  340. descriptor: ["a company of soldiers", "companies"]
  341. },
  342. "Battalion": {
  343. "Battalion": Battalion,
  344. mass: 1000,
  345. area: 3500,
  346. clusters: 2,
  347. cluster_chances: .1,
  348. contents: [["Soldier",300,1000]],
  349. descriptor: ["a battalion", "battalions"]
  350. },
  351. "Brigade": {
  352. "Brigade": Brigade,
  353. mass: 1500,
  354. area: 2e4,
  355. clusters: 2,
  356. cluster_chances: .1,
  357. contents: [["Soldier",1500,3200]],
  358. descriptor: ["a brigade", "brigades"]
  359. },
  360. "Division": {
  361. "Division": Division,
  362. mass: 2000,
  363. area: 8e4,
  364. clusters: 3,
  365. cluster_chances: .1,
  366. contents: [["Soldier",10000,16000]],
  367. descriptor: ["a division", "divisions"]
  368. },
  369. "Tank Division": {
  370. "Tank Division": TankDivision,
  371. mass: 3000,
  372. area: 1e5,
  373. clusters: 1,
  374. cluster_chances: .15,
  375. contents: [["Soldier",8000,1200],["Tank",250,500]],
  376. descriptor: ["a tank division", "tank divisions"]
  377. },
  378. "Army": {
  379. "Army": Army,
  380. mass: 5000,
  381. area: 1e6,
  382. clusters: 2,
  383. cluster_chances: .1,
  384. contents: [["Soldier",40000,75000]],
  385. descriptor: ["an army", "armies"]
  386. },
  387. };
  388. //Alterante Army Structuring, may be used later
  389. //"Squad": [["Soldier",6,9]],
  390. // "Platoon": [["Squad",3,4]],
  391. //"Company": [["Platoon",3,5],["Squad",0,2]],
  392. //"Battalion": [["Company",4,6]],
  393. //"Brigade": [["Battalion",2,5],["Company",0,3]],
  394. //"Division": [["Brigade",2,4]],
  395. //"Tank Division": [["Brigade",2,4],["Tank",250,500]],
  396. //"Army": [["Division",3,8],["Tank Division",1,5]],
  397. // replace all instances of from with to
  398. function contents_substitute(from,to) {
  399. for (let key in contents) {
  400. if (contents.hasOwnProperty(key)) {
  401. let type = contents[key];
  402. for (let i=0; i<type.length; i++) {
  403. if (type[i][0] == from) {
  404. type[i][0] = to;
  405. }
  406. }
  407. }
  408. }
  409. }
  410. // remove all instances of thing
  411. function contents_remove(thing) {
  412. for (let key in contents) {
  413. if (contents.hasOwnProperty(key)) {
  414. let type = contents[key];
  415. for (let i=0; i<type.length; i++) {
  416. if (type[i][0] == thing) {
  417. type.splice(i,1);
  418. --i;
  419. }
  420. }
  421. }
  422. }
  423. }
  424. // adds thing to parent
  425. function contents_insert(parent,thing,min,max,label) {
  426. let owner = things[parent].contents;
  427. if (label == undefined)
  428. owner.push([thing,min,max]);
  429. else
  430. owner.push([thing,min,max,label]);
  431. }
  432. function initContents(name,count) { //builds the contents for each destrucable(thing) when called
  433. let result = {};
  434. let type = things[name].contents;
  435. for (let i=0; i<type.length; i++) {
  436. let amount = distribution(type[i][1],type[i][2],count); //arrays of contents look like ["thing name",min,max,"optional name"] so those values have to pulled out
  437. if (amount > 0) {
  438. // if a custom label is supplied, use it!
  439. if (type[i].length == 4) //if has optional name
  440. result[type[i][3]] = new things[type[i][0]][type[i][0]](amount); //creates a "thing name" under the key of "optional name"
  441. else
  442. result[type[i][0]] = new things[type[i][0]][type[i][0]](amount);
  443. }
  444. }
  445. return result;
  446. }
  447. function get_living_prey(sum) {
  448. let total = 0;
  449. for (let key in sum) {
  450. if (sum.hasOwnProperty(key)) {
  451. if (key == "Micro" || key == "Macro" || key == "Person" || key == "Cow" || key == 'Soldier')
  452. total += sum[key];
  453. }
  454. }
  455. return total;
  456. }
  457. // general logic: each step fills in a fraction of the remaining space
  458. function fill_area(area, weights, variance=0.15)
  459. {
  460. area = area + Math.random() * variance * 2 * area - variance * area;
  461. var result = [];
  462. var candidates = [];
  463. for (var key in weights) {
  464. if (weights.hasOwnProperty(key)) {
  465. candidates.push({"name": key, "area": things[key].area, "weight": weights[key]});
  466. }
  467. }
  468. candidates = candidates.sort(function (x,y) {
  469. return x.area - y.area;
  470. });
  471. while(candidates.length > 0) {
  472. var candidate = candidates.pop();
  473. if (candidate.area > area)
  474. continue;
  475. var max = Math.floor(area / candidate.area);
  476. var limit = Math.min(max, 1000);
  477. var count = 0;
  478. var loopvar = 0;
  479. // for small amounts, actually do the randomness
  480. // the first few ones get a much better shot
  481. // if we have nothing at all, it's even better!
  482. while (loopvar < limit) {
  483. if (loopvar == 0 && result.length == 0) {
  484. ++count;
  485. }
  486. else if (loopvar <= things[candidate.name].clusters) {
  487. if (Math.random() < candidate.weight ? 1 : Math.random() < things[candidate.name].cluster_chances) {
  488. ++count;
  489. }
  490. }
  491. else {
  492. count += Math.random() < candidate.weight ? 1 : 0;
  493. }
  494. ++loopvar;
  495. }
  496. // if we're doing more than the limit, then we just add on the rest, with some variance
  497. if (limit < max) {
  498. const base = (max-limit) * candidate.weight;
  499. count += Math.round(base - base / 10 + base * Math.random() / 5);
  500. }
  501. area -= count * candidate.area;
  502. if (count > 0)
  503. result.push(new things[candidate.name][candidate.name](count));
  504. }
  505. return new Container(result);
  506. }
  507. // maybe make this something that approximates a
  508. // normal distribution; doing this 15,000,000 times is bad...
  509. // solution: only a few are random lul
  510. // improvement: take up to 100 samples, then use that to scale the final result
  511. function distribution(min, max, samples) {
  512. var result = 0;
  513. var limit = Math.min(100,samples);
  514. if (limit < samples) {
  515. let dist = 0;
  516. for (let i = 0; i < limit; i++) {
  517. dist += Math.random();
  518. }
  519. dist /= 100;
  520. return Math.floor(dist * samples * (max - min + 1) + samples * min);
  521. } else {
  522. for (let i = 0; i < limit; i++) {
  523. result += Math.floor(Math.random() * (max - min + 1) + min);
  524. }
  525. }
  526. return result;
  527. }
  528. function defaultMultiply(thing) {
  529. return function(amount) {
  530. thing.count *= amount;
  531. for (var key in thing.contents) {
  532. if (thing.contents.hasOwnProperty(key)) {
  533. thing.contents[key].multiply(amount);
  534. }
  535. }
  536. };
  537. }
  538. function defaultArea(thing) {
  539. return things[thing.name].area;
  540. }
  541. function defaultMass(thing) {
  542. return things[thing.name].mass;
  543. }
  544. function defaultDescribeOne(thing) {
  545. return things[thing.name].descriptor[0];
  546. }
  547. function defaultMerge(thing) { //this merges all objects into one containers
  548. return function(container) {
  549. var newCount = this.count + container.count;
  550. var newThing = new things[thing.name][thing.name](newCount);
  551. newThing.contents = {};
  552. for (var key in this.contents) {
  553. if (this.contents.hasOwnProperty(key)) {
  554. newThing.contents[key] = this.contents[key];
  555. }
  556. }
  557. for (key in container.contents) {
  558. if (container.contents.hasOwnProperty(key)) {
  559. if (this.contents.hasOwnProperty(key)) {
  560. newThing.contents[key] = this.contents[key].merge(container.contents[key]);
  561. } else {
  562. newThing.contents[key] = container.contents[key];
  563. }
  564. }
  565. }
  566. return newThing;
  567. };
  568. }
  569. function listSum(sum) {
  570. let result = [];
  571. for (let key in sum) {
  572. if (sum.hasOwnProperty(key)) {
  573. result.push(new things[key][key](sum[key]).describe(false));
  574. }
  575. }
  576. return merge_things(result);
  577. }
  578. // turn a nested object into a container with everything on one level
  579. function flatten(thing) {
  580. let dict = defaultSum(thing)();
  581. let list = [];
  582. Object.entries(dict).forEach(function([key, val]) {
  583. let obj = new things[key][key](val);
  584. obj.contents = [];
  585. list.push(obj);
  586. });
  587. list.sort(function(x,y) {
  588. if (y.area != x.area){
  589. return y.area - x.area;
  590. } else {
  591. return x.name.localeCompare(y.name);
  592. }
  593. });
  594. return new Container(list);
  595. }
  596. function defaultSum(thing) {
  597. return function() {
  598. var counts = {};
  599. if (thing.name != "Container")
  600. counts[thing.name] = thing.count;
  601. for (var key in thing.contents) {
  602. if (thing.contents.hasOwnProperty(key)) {
  603. var subcount = thing.contents[key].sum();
  604. for (var subkey in subcount) {
  605. if (!counts.hasOwnProperty(subkey)) {
  606. counts[subkey] = 0;
  607. }
  608. counts[subkey] += subcount[subkey];
  609. }
  610. }
  611. }
  612. return counts;
  613. };
  614. }
  615. function defaultSumProperty(thing) {
  616. return function(prop) {
  617. var total = 0;
  618. total += thing[prop] * thing.count;
  619. for (var key in thing.contents) {
  620. if (thing.contents.hasOwnProperty(key)) {
  621. total += thing.contents[key].sum_property(prop);
  622. }
  623. }
  624. return total;
  625. };
  626. }
  627. function defaultAddContent(thing) {
  628. return function(name, min, max, count) {
  629. if (min == max) {
  630. let object = new things[name](min*count);
  631. thing.contents[object.name] = object;
  632. } else {
  633. let object = new things[name](distribution(min, max, count));
  634. thing.contents[object.name] = object;
  635. }
  636. };
  637. }
  638. function DefaultEntity() {
  639. this.sum = defaultSum;
  640. this.area = defaultArea;
  641. this.mass = defaultMass;
  642. this.sum_property = defaultSumProperty;
  643. this.merge = defaultMerge;
  644. this.multiply = defaultMultiply;
  645. this.describeSimple = defaultDescribeSimple;
  646. this.describeOne = defaultDescribeOne;
  647. return this;
  648. }
  649. // god I love reinventing the wheel
  650. function copy_defaults(self,proto) { //loads the values defined in things into the fuction that calls it
  651. for (var key in proto) { //proto will always be a new DefaultEntity, self is the parent function
  652. if (proto.hasOwnProperty(key)) {
  653. self[key] = proto[key](self);
  654. }
  655. }
  656. }
  657. // combine strings into a list with proper grammar
  658. function merge_things(list,semicolons=false) {
  659. if (list.length == 0) {
  660. return "";
  661. } else if (list.length == 1) {
  662. return list[0];
  663. } else if (list.length == 2) {
  664. return list[0] + " and " + list[1];
  665. } else {
  666. var result = "";
  667. list.slice(0,list.length-1).forEach(function(term) {
  668. result += term + ", ";
  669. });
  670. result += "and " + list[list.length-1];
  671. return result;
  672. }
  673. }
  674. // combine the adjectives for something into a single string
  675. function merge_desc(list) {
  676. var result = "";
  677. list.forEach(function(term) {
  678. if (term != "")
  679. result += term + " ";
  680. });
  681. // knock off the last space
  682. if (result.length > 0) {
  683. result = result.substring(0, result.length - 1);
  684. }
  685. let article = "a "
  686. //a/an overwriting terms
  687. let forcedTerms = ["honor","heir"]; //words that need to start with an but don't start with a,e,i,o,u
  688. let force = false;
  689. for (let i of forcedTerms){
  690. if (i === result.substring(0, i.length)){force = true;}
  691. }
  692. let exceptionTerms = ["uniform","unique"]; //words that need to start with a and start with a,e,i,o,u
  693. let exception = false;
  694. for (let i of exceptionTerms){
  695. if (i === result.substring(0, i.length)){exception = true;}
  696. }
  697. //check if the string should start with an
  698. if ((force == true) || (exception == false && ((result.charAt(0) == "a")||(result.charAt(0) == "e")||(result.charAt(0) == "i")||(result.charAt(0) == "o")||(result.charAt(0) == "u")))){
  699. article = "an ";
  700. }
  701. result = article + result;
  702. return result;
  703. }
  704. // describes everything in the container
  705. function describe_all(contents,verbose=true,except=[]) {
  706. var things = [];
  707. for (var key in contents) {
  708. if (contents.hasOwnProperty(key) && !except.includes(key)) {
  709. things.push(contents[key].describe(verbose));
  710. }
  711. }
  712. return merge_things(things);
  713. }
  714. function random_desc(list, odds=1) { //strings together an array into a series of words
  715. if (Math.random() < odds)
  716. return list[Math.floor(Math.random() * list.length)];
  717. else
  718. return "";
  719. }
  720. function defaultDescribeSimple(thing) {
  721. return function(flat) {
  722. if (flat) {
  723. return flatten(thing).describe(false)
  724. } else {
  725. return thing.describe(false);
  726. }
  727. }
  728. }
  729. function defaultDescribe(verbose=true, parent, descAs){
  730. let descriptorEnd = " inside";
  731. let descriptorConjunction = " with ";
  732. let groupLessThan3 = false;
  733. switch(descAs) {
  734. case "vehicle":
  735. descriptorEnd = pickString(" inside"," inside"," inside", " inside"," riding inside", " trapped inside", " sitting inside");
  736. break;
  737. case "community":
  738. groupLessThan3 = true;
  739. descriptorEnd = " in " + (parent.count == 1 ? "it" : "them");
  740. break;
  741. case "celestial":
  742. groupLessThan3 = true;
  743. descriptorConjunction = pickString(" made up of "," consisting of "," containing ");
  744. descriptorEnd = "";
  745. break;
  746. case "military":
  747. groupLessThan3 = true;
  748. descriptorConjunction = pickString(" of "," of "," made up of "," comprised of "," containing ");
  749. descriptorEnd = "";
  750. break;
  751. case "generic vehicle":
  752. groupLessThan3 = true;
  753. descriptorEnd = pickString(" inside"," inside"," inside", " inside"," riding inside", " trapped inside", " sitting inside");
  754. break;
  755. } if (verbose) {
  756. if (parent.count = 1 ) { //singular parent (specifying single to catch cases where groupLessThan3 = true, otherwise it would output "1 towns" instead of "a town"
  757. if (things[parent.name].contents.length > 0){
  758. return (things[parent.name].descriptor[0] + descriptorConjunction + describe_all(parent.contents,false) + descriptorEnd);
  759. } else {
  760. return parent.describeOne(verbose);
  761. }
  762. }
  763. else if (parent.count <= 3 && groupLessThan3 == false) { // less than 3 parents and an ojbect that has varety when described
  764. var list = [];
  765. for (var i = 0; i < parent.count; i++) {
  766. list.push(parent.describeOne(parent.count <= 2));
  767. }
  768. if (things[parent.name].contents.length > 0){
  769. return (merge_things(list) + descriptorConjunction + describe_all(parent.contents,false) + descriptorEnd);
  770. } else {
  771. return merge_things(list);
  772. }
  773. } else {//if there are more than 3 of the object
  774. if (things[parent.name].contents.length > 0){
  775. return (parent.count + " " + things[parent.name].descriptor[1] + descriptorConjunction + describe_all(parent.contents,false) + descriptorEnd);
  776. } else {
  777. return (parent.count + " " + things[parent.name].descriptor[1]);
  778. }
  779. }
  780. } else {//not verbose
  781. return (parent.count > 1 ? (parent.count + " " + things[parent.name].descriptor[1]) : things[parent.name].descriptor[0]);
  782. }
  783. }
  784. function Container(contents = []) {
  785. this.name = "Container";
  786. copy_defaults(this,new DefaultEntity());
  787. if (Number.isInteger(contents))
  788. this.count = contents;
  789. else
  790. this.count = 0;
  791. this.contents = {};
  792. for (var i=0; i < contents.length; i++) {
  793. this.contents[contents[i].name] = contents[i];
  794. }
  795. for (var key in this.contents) {
  796. if (this.contents.hasOwnProperty(key)) {
  797. this.count += this.contents[key].count;
  798. }
  799. }
  800. this.describe = function(verbose = true) {
  801. return describe_all(this.contents,verbose);
  802. };
  803. return this;
  804. }
  805. function Person(count = 1) {
  806. this.name = "Person";
  807. copy_defaults(this,new DefaultEntity());
  808. this.mass = ((Math.random() -.5)*20)+this.mass;
  809. this.count = count;
  810. this.contents = initContents(this.name,this.count);
  811. this.describeOne = function (verbose=true) {
  812. var body = random_desc(["skinny","fat","tall","short","stocky","spindly","muscular","fit","multi-colored"], (verbose ? 0.6 : 0));
  813. var sex = random_desc(["male", "female"], (verbose ? 0.75 : 0));
  814. var species = "";
  815. species = random_desc(["wolf","cat","dog","squirrel","horse","hyena","fox","jackal","crux","sergal","coyote","rabbit","lizard","avian"]);
  816. return merge_desc([body,sex,species]);
  817. };
  818. this.describe = function(verbose=true) {
  819. return defaultDescribe(verbose, this);
  820. }
  821. return this;
  822. }
  823. function Human(count = 1) {
  824. this.name = "Person";
  825. copy_defaults(this,new DefaultEntity());
  826. this.mass = ((Math.random() -.5)*20)+this.mass;
  827. this.count = count;
  828. this.contents = initContents(this.name,this.count);
  829. this.describeOne = function (verbose=true) {
  830. var body = random_desc(["skinny","fat","tall","short","stocky","spindly","muscular","fit","tanned"], (verbose ? 0.6 : 0));
  831. var sex = random_desc(["man", "woman"], 1);
  832. return merge_desc([body,sex]);
  833. };
  834. this.describe = function(verbose=true) {
  835. return defaultDescribe(verbose, this);
  836. }
  837. return this;
  838. }
  839. function Cow(count = 1) {
  840. this.name = "Cow";
  841. copy_defaults(this,new DefaultEntity());
  842. this.count = count;
  843. this.contents = initContents(this.name,this.count);
  844. this.describeOne = function (verbose=true) {
  845. var body = random_desc(["skinny","fat","tall","short","stocky","spindly"], (verbose ? 0.6 : 0));
  846. var sex = random_desc(["male", "female"], (verbose ? 1 : 0));
  847. return merge_desc([body,sex,"cow"]);
  848. };
  849. this.describe = function(verbose=true) {
  850. return defaultDescribe(verbose, this);
  851. }
  852. return this;
  853. }
  854. function EmptyCar(count = 1) {
  855. this.name = "Empty Car";
  856. copy_defaults(this,new DefaultEntity());
  857. this.count = count;
  858. this.contents = initContents(this.name,this.count);
  859. this.describeOne = function(verbose=true) {
  860. var color = random_desc(["black","black","gray","gray","blue","red","tan","white","white"]);
  861. var adjective = random_desc(["rusty","brand-new","luxury","beat-up","dented","restored","classic"],0.3);
  862. var type = random_desc(["SUV","coupe","sedan","truck","van","convertible"]);
  863. return merge_desc(["parked",adjective,color,type]);
  864. };
  865. this.describe = function(verbose=true) {
  866. return defaultDescribe(verbose, this);
  867. }
  868. }
  869. function Car(count = 1) {
  870. this.name = "Car";
  871. copy_defaults(this,new DefaultEntity());
  872. this.count = count;
  873. this.contents = initContents(this.name,this.count);
  874. this.describeOne = function(verbose=true) {
  875. var color = random_desc(["black","black","gray","gray","blue","red","tan","white","white"], (verbose ? 1 : 0));
  876. var adjective = random_desc(["rusty","brand-new","luxury","beat-up","dented","restored","classic"], (verbose ? 0.3 : 0));
  877. var type = random_desc(["SUV","coupe","sedan","truck","van","convertible"]);
  878. return merge_desc([adjective,color,type]);
  879. };
  880. this.describe = function(verbose=true) {
  881. return defaultDescribe(verbose, this, "vehicle");
  882. }
  883. }
  884. function Bus(count = 1) {
  885. this.name = "Bus";
  886. copy_defaults(this,new DefaultEntity());
  887. this.count = count;
  888. this.contents = initContents(this.name,this.count);
  889. this.describeOne = function(verbose=true) {
  890. var adjective = random_desc(["rusty","brand-new","aging","modern"], (verbose ? 0.3 : 0));
  891. var color = random_desc(["black","tan","gray"], (verbose ? 1 : 0));
  892. var type = random_desc(["bus","double-decker bus","articulating bus","open-top bus","sleeper bus","intercity bus"]);
  893. return merge_desc([adjective,color,type]);
  894. };
  895. this.describe = function(verbose=true) {
  896. return defaultDescribe(verbose, this, "vehicle");
  897. }
  898. }
  899. function Tram(count = 1) {
  900. this.name = "Tram";
  901. copy_defaults(this,new DefaultEntity());
  902. this.count = count;
  903. this.contents = initContents(this.name,this.count);
  904. this.describeOne = function(verbose=true) {
  905. var adjective = random_desc(["rusty","weathered","well-maintained",], (verbose ? 0.3 : 0));
  906. var color = random_desc(["blue","brown","gray"], (verbose ? 1 : 0));
  907. var type = random_desc(["tram"]);
  908. return merge_desc([adjective,color,type]);
  909. };
  910. this.describe = function(verbose=true) {
  911. return defaultDescribe(verbose, this, "vehicle");
  912. }
  913. this.anal_vore = function() {
  914. return "You slide " + this.describe() + " up your tight ass";
  915. };
  916. }
  917. function BusinessJet(count = 1) {
  918. this.name = "Business Jet";
  919. copy_defaults(this,new DefaultEntity());
  920. this.count = count;
  921. this.contents = initContents(this.name,this.count);
  922. this.describeOne = function(verbose=true) {
  923. var adjective = random_desc(["brand-new","aging","modern"], (verbose ? 0.2 : 0));
  924. var color = random_desc(["blue","white","white","blue and white","red and white","black","gold"], (verbose ? 0.9 : 0));
  925. var type = random_desc(["luxury jet","business jet","single-engine plane","light aircraft"]);
  926. return merge_desc([adjective,color,type]);
  927. };
  928. this.describe = function(verbose=true) {
  929. return defaultDescribe(verbose, this, "vehicle");
  930. }
  931. }
  932. function Airliner(count = 1) {
  933. this.name = "Airliner";
  934. copy_defaults(this,new DefaultEntity());
  935. this.count = count;
  936. this.contents = initContents(this.name,this.count);
  937. this.describeOne = function(verbose=true) {
  938. var adjective = random_desc(["brand-new","aging","modern"], (verbose ? 0.2 : 0));
  939. var color = random_desc(["blue","white","white","blue and white"], (verbose ? 0.9 : 0));
  940. var type = random_desc(["airliner","twin-engine jet","trijet","four engine jet","double-decker airliner","widebody airliner","passenger jet","airliner"]);
  941. return merge_desc([adjective,color,type]);
  942. };
  943. this.describe = function(verbose=true) {
  944. return defaultDescribe(verbose, this, "vehicle");
  945. }
  946. }
  947. function Train(count = 1) {
  948. this.name = "Train";
  949. copy_defaults(this,new DefaultEntity());
  950. this.count = count;
  951. this.contents = initContents(this.name,this.count);
  952. this.describeOne = function(verbose=true) {
  953. var adjective = random_desc(["rusty","brand-new","steam","freshly-painted"], (verbose ? 0.3 : 0));
  954. var color = random_desc(["black","tan","gray"], (verbose ? 1 : 0));
  955. var type = random_desc(["train","passenger train","freight train"]);
  956. return merge_desc([adjective,color,type]);
  957. };
  958. this.describe = function(verbose = true) {
  959. if (verbose) {
  960. if (this.count == 1) {
  961. var list = [];
  962. for (var i = 0; i < this.count; i++) {
  963. list.push(this.describeOne(verbose));
  964. }
  965. return merge_things(list) + " with " + this.contents["engine"].describe(false) + " in the engine and " + this.contents["Train Car"].describe() + " attached";
  966. } else {
  967. return this.count + " trains with " + this.contents["engine"].describe(false) + " in the engine and " + this.contents["Train Car"].describe() + " attached";
  968. }
  969. } else {
  970. return (this.count > 1 ? this.count + " trains" : "a train");
  971. }
  972. };
  973. this.anal_vore = function() {
  974. 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");
  975. return "You snatch up " + this.describeOne() + " and stuff it into your pucker, moaning as " + cars;
  976. };
  977. }
  978. function TrainCar(count = 1) {
  979. this.name = "Train Car";
  980. copy_defaults(this,new DefaultEntity());
  981. this.count = count;
  982. this.contents = initContents(this.name,this.count);
  983. this.describeOne = function(verbose=true) {
  984. var adjective = random_desc(["rusty","brand-new","vintage","graffitied","well-maintained"], (verbose ? 0.3 : 0));
  985. var color = random_desc(["black","tan","gray","yellow","steel","wooden"], (verbose ? 1 : 0));
  986. var type = random_desc(["train car","passenger train car","freight train car"]);
  987. return merge_desc([adjective,color,type]);
  988. };
  989. this.describe = function(verbose=true) {
  990. return defaultDescribe(verbose, this, "vehicle");
  991. }
  992. }
  993. function House(count = 1) {
  994. this.name = "House";
  995. copy_defaults(this,new DefaultEntity());
  996. this.count = count;
  997. this.contents = initContents(this.name,this.count);
  998. this.describeOne = function(verbose=true) {
  999. var size = random_desc(["little","two-story","large","well-built","run-down","cheap",], (verbose ? 0.5 : 0));
  1000. var color = random_desc(["blue","white","gray","tan","green","wooden","brick"], (verbose ? 0.5 : 0));
  1001. var name = random_desc(["house","home","duplex","house","house","trailer"], 1);
  1002. return merge_desc([size,color,name]);
  1003. };
  1004. this.describe = function(verbose=true) {
  1005. return defaultDescribe(verbose, this);
  1006. }
  1007. }
  1008. //might split this into a general business and resutrant categories
  1009. function Business(count = 1) {
  1010. this.name = "Business";
  1011. copy_defaults(this,new DefaultEntity());
  1012. this.count = count;
  1013. this.contents = initContents(this.name,this.count);
  1014. this.describeOne = function(verbose=true) {
  1015. var size = random_desc(["little","two-story","large","well-built","run-down","cheap","aging","corner"], (verbose ? 0.5 : 0));
  1016. var color = random_desc(["blue","white","gray","tan","green","brick","concrete"], (verbose ? 0.5 : 0));
  1017. var name = random_desc(["mall","resturant","bank","clinic","shop","post office","tire shop","chain resturant","grocery store","barber shop","pizza resturant","hardware store","movie theather","gas station"], 1);
  1018. return merge_desc([size,color,name]);
  1019. };
  1020. this.describe = function(verbose=true) {
  1021. return defaultDescribe(verbose, this);
  1022. }
  1023. }
  1024. function Barn(count = 1) {
  1025. this.name = "Barn";
  1026. copy_defaults(this,new DefaultEntity());
  1027. this.count = count;
  1028. this.contents = initContents(this.name,this.count);
  1029. this.describeOne = function(verbose=true) {
  1030. var size = random_desc(["little","big","large","weathered","rotted","new"], (verbose ? 0.5 : 0));
  1031. var color = random_desc(["blue","white","gray","tan","green","red"], (verbose ? 0.5 : 0));
  1032. var name = random_desc(["barn","barn","barn","barn","barn","farmhouse"], 1);
  1033. return merge_desc([size,color,name]);
  1034. };
  1035. this.describe = function(verbose=true) {
  1036. return defaultDescribe(verbose, this);
  1037. }
  1038. }
  1039. function SmallSkyscraper(count = 1) {
  1040. this.name = "Small Skyscraper";
  1041. copy_defaults(this,new DefaultEntity());
  1042. this.count = count;
  1043. this.contents = initContents(this.name,this.count);
  1044. this.describeOne = function(verbose=true) {
  1045. var color = random_desc(["blue","white","gray","tan","green"], (verbose ? 0.5 : 0));
  1046. var name = random_desc(["skyscraper","office tower","office building","high rise"], 1);
  1047. return merge_desc([color,name]);
  1048. };
  1049. this.describe = function(verbose=true) {
  1050. return defaultDescribe(verbose, this);
  1051. }
  1052. }
  1053. function LargeSkyscraper(count = 1) {
  1054. this.name = "Large Skyscraper";
  1055. copy_defaults(this,new DefaultEntity());
  1056. this.count = count;
  1057. this.contents = initContents(this.name,this.count);
  1058. this.describeOne = function(verbose=true) {
  1059. var color = random_desc(["blue","white","gray","tan","green","glass"], (verbose ? 0.5 : 0));
  1060. var name = random_desc(["skyscraper","office tower","office building"], 1);
  1061. return merge_desc(["towering",color,name]);
  1062. };
  1063. this.describe = function(verbose=true) {
  1064. return defaultDescribe(verbose, this);
  1065. }
  1066. }
  1067. function ParkingGarage(count = 1) {
  1068. this.name = "Parking Garage";
  1069. copy_defaults(this,new DefaultEntity());
  1070. this.count = count;
  1071. this.contents = initContents(this.name,this.count);
  1072. this.describe = function(verbose=true) {
  1073. return defaultDescribe(verbose, this);
  1074. }
  1075. }
  1076. function Town(count = 1) {
  1077. this.name = "Town";
  1078. copy_defaults(this,new DefaultEntity());
  1079. this.count = count;
  1080. this.contents = initContents(this.name,this.count);
  1081. this.describe = function(verbose=true) {
  1082. return defaultDescribe(verbose, this, "community");
  1083. }
  1084. }
  1085. function City(count = 1) {
  1086. this.name = "City";
  1087. copy_defaults(this,new DefaultEntity());
  1088. this.count = count;
  1089. this.contents = initContents(this.name,this.count);
  1090. this.describe = function(verbose=true) {
  1091. return defaultDescribe(verbose, this, "community");
  1092. }
  1093. }
  1094. function Continent(count = 1) {
  1095. this.name = "Continent";
  1096. copy_defaults(this,new DefaultEntity());
  1097. this.count = count;
  1098. this.contents = initContents(this.name,this.count);
  1099. this.describe = function(verbose=true) {
  1100. return defaultDescribe(verbose, this, "community");
  1101. }
  1102. }
  1103. function Planet(count = 1) {
  1104. this.name = "Planet";
  1105. copy_defaults(this,new DefaultEntity());
  1106. this.count = count;
  1107. this.contents = initContents(this.name,this.count);
  1108. this.describe = function(verbose=true) {
  1109. return defaultDescribe(verbose, this, "community");
  1110. }
  1111. }
  1112. function Star(count = 1) {
  1113. this.name = "Star";
  1114. copy_defaults(this,new DefaultEntity());
  1115. this.count = count;
  1116. this.contents = initContents(this.name,this.count);
  1117. this.describe = function(verbose = true) {
  1118. return (this.count == 1 ? "a star" : this.count + " stars");
  1119. };
  1120. }
  1121. function SolarSystem(count = 1) {
  1122. this.name = "Solar System";
  1123. copy_defaults(this,new DefaultEntity());
  1124. this.count = count;
  1125. this.contents = initContents(this.name,this.count);
  1126. this.describe = function(verbose=true) {
  1127. return defaultDescribe(verbose, this, "celestial");
  1128. }
  1129. }
  1130. function Galaxy(count = 1) {
  1131. this.name = "Galaxy";
  1132. copy_defaults(this,new DefaultEntity());
  1133. this.count = count;
  1134. this.contents = initContents(this.name,this.count);
  1135. this.describe = function(verbose=true) {
  1136. return defaultDescribe(verbose, this, "celestial");
  1137. }
  1138. }
  1139. function Cluster(count = 1) {
  1140. this.name = "Cluster";
  1141. copy_defaults(this,new DefaultEntity());
  1142. this.count = count;
  1143. this.contents = initContents(this.name,this.count);
  1144. this.describe = function(verbose=true) {
  1145. return defaultDescribe(verbose, this, "celestial");
  1146. }
  1147. }
  1148. function Universe(count = 1) {
  1149. this.name = "Universe";
  1150. copy_defaults(this,new DefaultEntity());
  1151. this.count = count;
  1152. this.contents = initContents(this.name,this.count);
  1153. this.describe = function(verbose=true) {
  1154. return defaultDescribe(verbose, this, "celestial");
  1155. }
  1156. }
  1157. function Multiverse(count = 1) {
  1158. this.name = "Multiverse";
  1159. copy_defaults(this,new DefaultEntity());
  1160. this.count = count;
  1161. this.contents = initContents(this.name,this.count);
  1162. this.describe = function(verbose=true) {
  1163. return defaultDescribe(verbose, this, "celestial");
  1164. }
  1165. }
  1166. function Soldier(count = 1) {
  1167. this.name = "Soldier";
  1168. copy_defaults(this,new DefaultEntity());
  1169. this.count = count;
  1170. this.contents = initContents(this.name,this.count);
  1171. this.describe = function(verbose=true) {
  1172. return defaultDescribe(verbose, this, "military");
  1173. }
  1174. }
  1175. function Tank(count = 1) {
  1176. this.name = "Tank";
  1177. copy_defaults(this,new DefaultEntity());
  1178. this.count = count;
  1179. this.contents = initContents(this.name,this.count);
  1180. this.describe = function(verbose=true) {
  1181. return defaultDescribe(verbose, this, "generic vehicle");
  1182. }
  1183. }
  1184. function Artillery(count = 1) {
  1185. this.name = "Artillery";
  1186. copy_defaults(this,new DefaultEntity());
  1187. this.count = count;
  1188. this.contents = initContents(this.name,this.count);
  1189. this.describe = function(verbose=true) {
  1190. return defaultDescribe(verbose, this, "generic vehicle");
  1191. }
  1192. }
  1193. function Helicopter(count = 1) {
  1194. this.name = "Helicopter";
  1195. copy_defaults(this,new DefaultEntity());
  1196. this.count = count;
  1197. this.contents = initContents(this.name,this.count);
  1198. this.describe = function(verbose=true) {
  1199. return defaultDescribe(verbose, this, "generic vehicle");
  1200. }
  1201. }
  1202. function Micro(count = 1) {
  1203. this.name = "Micro";
  1204. copy_defaults(this,new DefaultEntity());
  1205. this.count = count;
  1206. this.contents = initContents(this.name,this.count);
  1207. this.describe = function(verbose=true) {
  1208. return defaultDescribe(verbose, this);
  1209. }
  1210. }
  1211. function Macro(count = 1) {
  1212. this.name = "Macro";
  1213. copy_defaults(this,new DefaultEntity());
  1214. this.count = count;
  1215. this.contents = initContents(this.name,this.count);
  1216. this.describe = function(verbose=true) {
  1217. return defaultDescribe(verbose, this);
  1218. }
  1219. }
  1220. function Squad(count = 1) {
  1221. this.name = "Squad";
  1222. copy_defaults(this,new DefaultEntity());
  1223. this.count = count;
  1224. this.contents = initContents(this.name,this.count);
  1225. this.describe = function(verbose=true) {
  1226. return defaultDescribe(verbose, this, "military");
  1227. }
  1228. }
  1229. function Platoon(count = 1) {
  1230. this.name = "Platoon";
  1231. copy_defaults(this,new DefaultEntity());
  1232. this.count = count;
  1233. this.contents = initContents(this.name,this.count);
  1234. this.describe = function(verbose=true) {
  1235. return defaultDescribe(verbose, this, "military");
  1236. }
  1237. }
  1238. function Company(count = 1) {
  1239. this.name = "Company";
  1240. copy_defaults(this,new DefaultEntity());
  1241. this.count = count;
  1242. this.contents = initContents(this.name,this.count);
  1243. this.describe = function(verbose=true) {
  1244. return defaultDescribe(verbose, this, "military");
  1245. }
  1246. }
  1247. function Battalion(count = 1) {
  1248. this.name = "Battalion";
  1249. copy_defaults(this,new DefaultEntity());
  1250. this.count = count;
  1251. this.contents = initContents(this.name,this.count);
  1252. this.describe = function(verbose=true) {
  1253. return defaultDescribe(verbose, this, "military");
  1254. }
  1255. }
  1256. function Brigade(count = 1) {
  1257. this.name = "Brigade";
  1258. copy_defaults(this,new DefaultEntity());
  1259. this.count = count;
  1260. this.contents = initContents(this.name,this.count);
  1261. this.describe = function(verbose=true) {
  1262. return defaultDescribe(verbose, this, "military");
  1263. }
  1264. }
  1265. function Division(count = 1) {
  1266. this.name = "Division";
  1267. copy_defaults(this,new DefaultEntity());
  1268. this.count = count;
  1269. this.contents = initContents(this.name,this.count);
  1270. this.describe = function(verbose=true) {
  1271. return defaultDescribe(verbose, this, "military");
  1272. }
  1273. }
  1274. function TankDivision(count = 1) {
  1275. this.name = "Tank Division";
  1276. copy_defaults(this,new DefaultEntity());
  1277. this.count = count;
  1278. this.contents = initContents(this.name,this.count);
  1279. this.describe = function(verbose=true) {
  1280. return defaultDescribe(verbose, this, "military");
  1281. }
  1282. }
  1283. function Army(count = 1) {
  1284. this.name = "Army";
  1285. copy_defaults(this,new DefaultEntity());
  1286. this.count = count;
  1287. this.contents = initContents(this.name,this.count);
  1288. this.describe = function(verbose=true) {
  1289. return defaultDescribe(verbose, this, "military");
  1290. }
  1291. }
  1292. //todo
  1293. //airports
  1294. //farms
  1295. //racetracks
  1296. //more building types
  1297. //cranes and other construction equipment
  1298. //nebula
  1299. //chemical factory
  1300. //grand army
  1301. //armada