big steppy
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

1890 行
50 KiB

  1. /*
  2. function defaultSumDST(thing) {
  3. return function() {
  4. var counts = {};
  5. if (thing.name != "Container") //if a container is detected, sets counts
  6. counts[thing.name] = thing.count;
  7. for (var key in thing.contents) {
  8. if (thing.contents.hasOwnProperty(key)) {
  9. var subcount = thing.contents[key].sum();
  10. for (var subkey in subcount) {
  11. if (!counts.hasOwnProperty(subkey)) {
  12. counts[subkey] = 0;
  13. }
  14. counts[subkey] += subcount[subkey];
  15. }
  16. }
  17. }
  18. return counts;
  19. };
  20. }
  21. function defaultSumProperty(thing) {
  22. return function(prop) {
  23. var total = 0;
  24. total += thing[prop] * thing.count;
  25. for (var key in thing.contents) {
  26. if (thing.contents.hasOwnProperty(key)) {
  27. total += thing.contents[key].sum_property(prop);
  28. }
  29. }
  30. return total;
  31. };
  32. }
  33. function defaultArea(thing) {
  34. return areas[thing.name];
  35. }
  36. function DefaultDestructable() {
  37. this.name = this.defaults.name;
  38. this.area = this.defaults.area;
  39. this.mass = this.defaults.mass;
  40. this.sum = defaultSumDST;
  41. this.sum_property = defaultSumProperty;
  42. this.merge = defaultMerge;
  43. this.multiply = defaultMultiply;
  44. this.describeSimple = defaultDescribeSimple;
  45. return this;
  46. }
  47. function copy_defaultsDST(self,proto) {
  48. for (var key in proto) {
  49. if (proto.hasOwnProperty(key)) {
  50. self[key] = proto[key](self);
  51. }
  52. }
  53. }
  54. personVar = {
  55. name: "Person",
  56. area: 0.33,
  57. mass: 80,
  58. clusters: 5,
  59. cluster_chances: .8,
  60. contents: [],
  61. body: [["skinny", -10,0],["fat", 15,.05],["tall", 7, 0],["short",-7,0],["stocky",5,.02],["spindly",-5,-.02],["muscular",7,0],["fit",0,0],["multi-colored",0,0]],//["bodytype", mass modifier, area modifier]
  62. sex: [["male",2,.02],["female",2,.02]],//["sex", mass modifier, area modifier]
  63. species: [["wolf",80,.35],["cat",70,.3],["dog",75,.31],["squirrel",68,.29],["horse",90,.4],["hyena",78,.32],["fox",72,.3],["jackal",74,.32],["crux",90,.33],["sergal",77,.34]],//["species", mass modifier, area modifier]
  64. singular: "person",
  65. plural: "people"
  66. }
  67. function PersonDST(count = 1) {
  68. this.defaults = personVar;
  69. copy_defaultsDST(this,new DefaultDestructable());
  70. this.count = count;
  71. this.contents = initContents(this.name,this.count);
  72. this.describeOne = function (verbose=true) {
  73. var body = random_desc(this.properties.body, (verbose ? 0.6 : 0));
  74. var sex = random_desc(this.properties.sex, (verbose ? 1 : 0));
  75. var species = random_desc(this.properties.species);
  76. return "a " + merge_desc([body,sex,species]);
  77. };
  78. this.describe = function(verbose=true) {
  79. if (verbose) {
  80. if (count <= 3) {
  81. var list = [];
  82. for (var i = 0; i < count; i++) {
  83. list.push(this.describeOne(this.count <= 2));
  84. }
  85. return merge_things(list);
  86. } else {
  87. return this.count + " people";
  88. }
  89. } else {
  90. return (this.count > 1 ? this.count + " people" : "a person");
  91. }
  92. };
  93. return this;
  94. }
  95. */
  96. 'use strict';
  97. var things =
  98. {
  99. "Container": {
  100. "Container": Container,
  101. mass: 0,
  102. area: 0,
  103. clusters: 0,
  104. cluster_chances: 0,
  105. contents: [],
  106. },
  107. //Creatures
  108. "Person": {
  109. "Person": Person,
  110. mass: 80,
  111. area: .33,
  112. clusters: 5,
  113. cluster_chances: .8,
  114. contents: [],
  115. },
  116. "Human": {
  117. "Human": Human,
  118. mass: 80,
  119. area: .33,
  120. clusters: 5,
  121. cluster_chances: .8,
  122. contents: [],
  123. },
  124. "Cow": {
  125. "Cow": Cow,
  126. mass: 300,
  127. area: 2,
  128. clusters: 15,
  129. cluster_chances: .5,
  130. contents: [],
  131. },
  132. "Micro": {
  133. "Micro": Micro,
  134. mass: .01,
  135. area: .05,
  136. clusters: 50,
  137. cluster_chances: 1,
  138. contents: [[]],
  139. },
  140. "Macro": {
  141. "Macro": Macro,
  142. mass: 8e4,
  143. area: 100,
  144. clusters: 0,
  145. cluster_chances: 0,
  146. contents: [[]],
  147. },
  148. //Vehicles
  149. "Empty Car": {
  150. "Empty Car": EmptyCar,
  151. mass: 1000,
  152. area: 4,
  153. clusters: 2,
  154. cluster_chances: .3,
  155. contents: [[]],
  156. },
  157. "Car": {
  158. "Car": Car,
  159. mass: 1000,
  160. area: 4,
  161. clusters: 4,
  162. cluster_chances: .5,
  163. contents: [["Person",1,4]],
  164. },
  165. "Bus": {
  166. "Bus": Bus,
  167. mass: 5000,
  168. area: 12,
  169. clusters: 1,
  170. cluster_chances: .25,
  171. contents: [["Person",2,30]],
  172. },
  173. "Tram": {
  174. "Tram": Tram,
  175. mass: 1e4,
  176. area: 20,
  177. clusters: 1,
  178. cluster_chances: .2,
  179. contents: [["Person",10,50]],
  180. },
  181. "Train": {
  182. "Train": Train,
  183. mass: 5e4,
  184. area: 40,
  185. clusters: 2,
  186. cluster_chances: .1,
  187. contents: [["Person",1,4,"engine"],["Train Car",2,10]],
  188. },
  189. "Train Car": {
  190. "Train Car": TrainCar,
  191. mass: 7500,
  192. area: 20,
  193. clusters: 1,
  194. cluster_chances: .05,
  195. contents: [["Person",10,40]],
  196. },
  197. //Buildings
  198. "House": {
  199. "House": House,
  200. mass: 1e4,
  201. area: 150,
  202. clusters: 5,
  203. cluster_chances: .5,
  204. contents: [["Person",0,8],["Empty Car",0,2]],
  205. },
  206. "Business": {
  207. "Business": Business,
  208. mass: 5e4,
  209. area: 400,
  210. clusters: 5,
  211. cluster_chances: .25,
  212. contents: [["Person",0,30],["Car",0,5],["Empty Car",0,20]],
  213. },
  214. "Barn": {
  215. "Barn": Barn,
  216. mass: 5e3,
  217. area: 300,
  218. clusters: 1,
  219. cluster_chances: .1,
  220. contents: [["Person",0,2],["Cow",30,70]],
  221. },
  222. "Small Skyscraper": {
  223. "Small Skyscraper": SmallSkyscraper,
  224. mass: 1e7,
  225. area: 1000,
  226. clusters: 2,
  227. cluster_chances: .25,
  228. contents: [["Person",150,750],["Empty Car",10,50]],
  229. },
  230. "Large Skyscraper": {
  231. "Large Skyscraper": LargeSkyscraper,
  232. mass: 8e7,
  233. area: 2000,
  234. clusters: 1,
  235. cluster_chances: .25,
  236. contents: [["Person",500,1500],["Empty Car",20,100]],
  237. },
  238. "Parking Garage": {
  239. "Parking Garage": ParkingGarage,
  240. mass: 1e7,
  241. area: 750,
  242. clusters: 1,
  243. cluster_chances: .1,
  244. contents: [["Person",10,200],["Empty Car",100,300],["Car",5,30]],
  245. },
  246. //Places
  247. "Town": {
  248. "Town": Town,
  249. mass: 1,
  250. area: 1e7,
  251. clusters: 5,
  252. cluster_chances: .1,
  253. contents: [["Person",10000,100000],["House",5000,50000],["Empty Car",200,800],["Car",500,80000],["Bus",5,25],["Train",5,25],["Business",500,5000]],
  254. },
  255. "City": {
  256. "City": City,
  257. mass: 1,
  258. area: 1e9,
  259. clusters: 0,
  260. cluster_chances: .2,
  261. 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]],
  262. },
  263. "Continent": {
  264. "Continent": Continent,
  265. mass: 1e21,
  266. area: 1.5e13,
  267. clusters: 5,
  268. cluster_chances: .5,
  269. contents: [["Person",1000000,15000000],["House",2500,10000],["Car",25000,375000],["Train",50,500],["Town",500,1000],["City",50,250],["Business",250,1000]],
  270. },
  271. "Planet": {
  272. "Planet": Planet,
  273. mass: 5.972e24,
  274. area: 2.5e14,
  275. clusters: 0,
  276. cluster_chances: 1,
  277. contents: [["Continent",4,9]],
  278. },
  279. "Star": {
  280. "Star": Star,
  281. mass: 1e40,
  282. area: 3e18,
  283. clusters: 1,
  284. cluster_chances: 1,
  285. contents: [],
  286. },
  287. "Solar System": {
  288. "Solar System": SolarSystem,
  289. mass: 1,
  290. area: 3e21,
  291. clusters: 1,
  292. cluster_chances: 1,
  293. contents: [["Star",1,1],["Planet",5,15]],
  294. },
  295. "Galaxy": {
  296. "Galaxy": Galaxy,
  297. mass: 1,
  298. area: 2e45,
  299. clusters: 1,
  300. cluster_chances: 1,
  301. contents: [["Star",1e9,500e9],["Solar System",1e8,500e8]],
  302. },
  303. "Cluster": {
  304. "Cluster": Cluster,
  305. mass: 1,
  306. area: 2e49,
  307. clusters: 1,
  308. cluster_chances: 1,
  309. contents: [["Galaxy",200,5000]],
  310. },
  311. "Universe": {
  312. "Universe": Universe,
  313. mass: 1,
  314. area: 7e53,
  315. clusters: 1,
  316. cluster_chances: 1,
  317. contents: [["Cluster",1.5e9,2.5e9]],
  318. },
  319. "Multiverse": {
  320. "Multiverse": Multiverse,
  321. mass: 1,
  322. area: 5e56,
  323. clusters: 1,
  324. cluster_chances: 1,
  325. contents: [["Universe",100,1000]],
  326. },
  327. //Military
  328. "Soldier": {
  329. "Soldier": Soldier,
  330. mass: 80,
  331. area: 1,
  332. clusters: 2,
  333. cluster_chances: .2,
  334. contents: [],
  335. },
  336. "Tank": {
  337. "Tank": Tank,
  338. mass: 5000,
  339. area: 20,
  340. clusters: 2,
  341. cluster_chances: .25,
  342. contents: [["Soldier",3,5]],
  343. },
  344. "Artillery": {
  345. "Artillery": Artillery,
  346. mass: 7000,
  347. area: 25,
  348. clusters: 3,
  349. cluster_chances: .5,
  350. contents: [["Soldier",4,6]],
  351. },
  352. "Helicopter": {
  353. "Helicopter": Helicopter,
  354. mass: 1500,
  355. area: 12,
  356. clusters: 0,
  357. cluster_chances: 0,
  358. contents: [["Soldier",4,16]],
  359. },
  360. "Squad": {
  361. "Squad": Squad,
  362. mass: 1,
  363. area: 30,
  364. clusters: 20,
  365. cluster_chances: .05,
  366. contents: [["Soldier",6,9]],
  367. },
  368. "Platoon": {
  369. "Platoon": Platoon,
  370. mass: 100,
  371. area: 150,
  372. clusters: 2,
  373. cluster_chances: .1,
  374. contents: [["Soldier",16,44]],
  375. },
  376. "Company": {
  377. "Company": Company,
  378. mass: 500,
  379. area: 600,
  380. clusters: 2,
  381. cluster_chances: .1,
  382. contents: [["Soldier",60,200]],
  383. },
  384. "Battalion": {
  385. "Battalion": Battalion,
  386. mass: 1000,
  387. area: 3500,
  388. clusters: 2,
  389. cluster_chances: .1,
  390. contents: [["Soldier",300,1000]],
  391. },
  392. "Brigade": {
  393. "Brigade": Brigade,
  394. mass: 1500,
  395. area: 2e4,
  396. clusters: 2,
  397. cluster_chances: .1,
  398. contents: [["Soldier",1500,3200]],
  399. },
  400. "Division": {
  401. "Division": Division,
  402. mass: 2000,
  403. area: 8e4,
  404. clusters: 3,
  405. cluster_chances: .1,
  406. contents: [["Soldier",10000,16000]],
  407. },
  408. "Tank Division": {
  409. "Tank Division": TankDivision,
  410. mass: 3000,
  411. area: 1e5,
  412. clusters: 1,
  413. cluster_chances: .15,
  414. contents: [["Soldier",8000,1200],["Tank",250,500]],
  415. },
  416. "Army": {
  417. "Army": Army,
  418. mass: 5000,
  419. area: 1e6,
  420. clusters: 2,
  421. cluster_chances: .1,
  422. contents: [["Soldier",40000,75000]],
  423. },
  424. };
  425. //Alterante Army Structuring, may be used later
  426. //"Squad": [["Soldier",6,9]],
  427. // "Platoon": [["Squad",3,4]],
  428. //"Company": [["Platoon",3,5],["Squad",0,2]],
  429. //"Battalion": [["Company",4,6]],
  430. //"Brigade": [["Battalion",2,5],["Company",0,3]],
  431. //"Division": [["Brigade",2,4]],
  432. //"Tank Division": [["Brigade",2,4],["Tank",250,500]],
  433. //"Army": [["Division",3,8],["Tank Division",1,5]],
  434. var clusters =
  435. {
  436. "Container": 0,
  437. //Creatures
  438. "Person": 5,
  439. "Human": 5,
  440. "Cow": 15,
  441. "Micro": 10,
  442. "Macro": 0,
  443. //Vehicles
  444. "Car": 3,
  445. "Bus": 1,
  446. "Tram": 1,
  447. "Train": 2,
  448. "Train Car": 1,
  449. //Buildings
  450. "House": 5,
  451. "Business": 5,
  452. "Barn": 1,
  453. "Small Skyscraper": 2,
  454. "Large Skyscraper": 1,
  455. "Parking Garage": 1,
  456. //Places
  457. "Town": 5,
  458. "City": 1,
  459. "Continent": 5,
  460. "Planet": 1,
  461. "Star": 1,
  462. "Solar System": 1,
  463. "Galaxy": 1,
  464. "Cluster": 1,
  465. "Universe": 1,
  466. "Multiverse": 1,
  467. //Military
  468. "Soldier": 0,
  469. "Tank": 0,
  470. "Artillery": 0,
  471. "Helicopter": 0,
  472. "Squad": 20,
  473. "Platoon": 2,
  474. "Company": 2,
  475. "Battalion": 2,
  476. "Brigade": 2,
  477. "Division": 3,
  478. "Tank Division": 1,
  479. "Army": 2,
  480. };
  481. var cluster_chances =
  482. {
  483. "Container": 0,
  484. //Creatures
  485. "Person": 0.8,
  486. "Human": 0.8,
  487. "Cow": 0.5,
  488. "Micro": 10,
  489. "Macro": 0,
  490. //Vehicles
  491. "Car": 0.5,
  492. "Bus": 0.25,
  493. "Tram": 0.2,
  494. "Train": 0.1,
  495. "Train Car": 0.05,
  496. //Buildings
  497. "House": 0.5,
  498. "Business": .05,
  499. "Barn": 0.1,
  500. "Small Skyscraper": 0.25,
  501. "Large Skyscraper": 0.25,
  502. "Parking Garage": 0.1,
  503. //Places
  504. "Town": 0.1,
  505. "City": 0.2,
  506. "Continent": 0.5,
  507. "Planet": 1,
  508. "Star": 1,
  509. "Solar System": 1,
  510. "Galaxy": 1,
  511. "Cluster": 1,
  512. "Universe": 1,
  513. "Multiverse": 1,
  514. //Military
  515. "Soldier": 0,
  516. "Tank": 0,
  517. "Artillery": 0,
  518. "Helicopter": 0,
  519. "Squad": .05,
  520. "Platoon": .05,
  521. "Company": .1,
  522. "Battalion": .1,
  523. "Brigade": .1,
  524. "Division": .1,
  525. "Tank Division": 0.15,
  526. "Army": .1,
  527. };
  528. var contents =
  529. {
  530. "Container": [],
  531. //Creatures
  532. "Person": [],
  533. "Human": [],
  534. "Cow": [],
  535. "Micro": [[]],
  536. "Macro": [[]],
  537. //Vehicles
  538. "Car": [["Person",1,4]],
  539. "Bus": [["Person",2,30]],
  540. "Tram": [["Person",10,50]],
  541. "Train": [["Person",1,4,"engine"],["Train Car",2,10]],
  542. "Train Car": [["Person",10,40]],
  543. //Buildings
  544. "House": [["Person",0,8],["Empty Car",0,2]],
  545. "Business": [["Person",0,30],["Car",0,20]],
  546. "Barn": [["Person",0,2],["Cow",30,70]],
  547. "Small Skyscraper": [["Person",150,750],["Empty Car",10,50]],
  548. "Large Skyscraper": [["Person",500,1500],["Empty Car",20,100]],
  549. "Parking Garage": [["Person",10,200],["Empty Car",100,300],["Car",5,30]],
  550. //Places
  551. "Town": [["Person",10000,100000],["House",5000,50000],["Empty Car",200,800],["Car",500,80000],["Bus",5,25],["Train",5,25],["Business",500,5000]],
  552. "City": [["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]],
  553. "Continent": [["Person",1000000,15000000],["House",2500,10000],["Car",25000,375000],["Train",50,500],["Town",500,1000],["City",50,250],["Business",250,1000]],
  554. "Planet": [["Continent",4,9]],
  555. "Star": [],
  556. "Solar System": [["Star",1,1],["Planet",5,15]],
  557. "Galaxy": [["Star",1e9,500e9],["Solar System",1e8,500e8]],
  558. "Cluster": [["Galaxy",200,5000]],
  559. "Universe": [["Cluster",1.5e9,2.5e9]],
  560. "Multiverse": [["Universe",100,1000]],
  561. //Military
  562. "Soldier": [],
  563. "Tank": [["Soldier",3,5]],
  564. "Artillery": [["Soldier",4,6]],
  565. "Helicopter": [["Soldier",4,16]],
  566. //Alterante Army Structuring, may be used later
  567. //"Squad": [["Soldier",6,9]],
  568. // "Platoon": [["Squad",3,4]],
  569. //"Company": [["Platoon",3,5],["Squad",0,2]],
  570. //"Battalion": [["Company",4,6]],
  571. //"Brigade": [["Battalion",2,5],["Company",0,3]],
  572. //"Division": [["Brigade",2,4]],
  573. //"Tank Division": [["Brigade",2,4],["Tank",250,500]],
  574. //"Army": [["Division",3,8],["Tank Division",1,5]],
  575. "Squad": [["Soldier",6,9]],
  576. "Platoon": [["Soldier",16,44]],
  577. "Company": [["Soldier",60,200]],
  578. "Battalion": [["Soldier",300,1000]],
  579. "Brigade": [["Soldier",1500,3200]],
  580. "Division": [["Soldier",10000,16000]],
  581. "Tank Division": [["Soldier",8000,1200],["Tank",250,500]],
  582. "Army": [["Soldier",40000,75000]],
  583. };
  584. // replace all instances of from with to
  585. function contents_substitute(from,to) {
  586. for (let key in contents) {
  587. if (contents.hasOwnProperty(key)) {
  588. let type = contents[key];
  589. for (let i=0; i<type.length; i++) {
  590. if (type[i][0] == from) {
  591. type[i][0] = to;
  592. }
  593. }
  594. }
  595. }
  596. }
  597. // remove all instances of thing
  598. function contents_remove(thing) {
  599. for (let key in contents) {
  600. if (contents.hasOwnProperty(key)) {
  601. let type = contents[key];
  602. for (let i=0; i<type.length; i++) {
  603. if (type[i][0] == thing) {
  604. type.splice(i,1);
  605. --i;
  606. }
  607. }
  608. }
  609. }
  610. }
  611. // adds thing to parent
  612. function contents_insert(parent,thing,min,max,label) {
  613. let owner = contents[parent];
  614. if (label == undefined)
  615. owner.push([thing,min,max]);
  616. else
  617. owner.push([thing,min,max,label]);
  618. }
  619. function initContents(name,count) { //builds the contents for each destrucable(thing) when called
  620. let result = {};
  621. let type = things[name].contents;
  622. for (let i=0; i<type.length; i++) {
  623. 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
  624. if (amount > 0) {
  625. // if a custom label is supplied, use it!
  626. if (type[i].length == 4) //if has optional name
  627. result[type[i][3]] = new things[type[i][0]][type[i][0]](amount); //creates a "thing name" under the key of "optional name"
  628. else
  629. result[type[i][0]] = new things[type[i][0]][type[i][0]](amount);
  630. }
  631. }
  632. return result;
  633. }
  634. function get_living_prey(sum) {
  635. let total = 0;
  636. for (let key in sum) {
  637. if (sum.hasOwnProperty(key)) {
  638. if (key == "Micro" || key == "Macro" || key == "Person" || key == "Cow" || key == 'Soldier')
  639. total += sum[key];
  640. }
  641. }
  642. return total;
  643. }
  644. // general logic: each step fills in a fraction of the remaining space
  645. function fill_area(area, weights, variance=0.15)
  646. {
  647. area = area + Math.random() * variance * 2 * area - variance * area;
  648. var result = [];
  649. var candidates = [];
  650. for (var key in weights) {
  651. if (weights.hasOwnProperty(key)) {
  652. candidates.push({"name": key, "area": things[key].area, "weight": weights[key]});
  653. }
  654. }
  655. candidates = candidates.sort(function (x,y) {
  656. return x.area - y.area;
  657. });
  658. while(candidates.length > 0) {
  659. var candidate = candidates.pop();
  660. if (candidate.area > area)
  661. continue;
  662. var max = Math.floor(area / candidate.area);
  663. var limit = Math.min(max, 100);
  664. var count = 0;
  665. var loopvar = limit;
  666. // for small amounts, actually do the randomness
  667. // the first few ones get a much better shot
  668. // if we have nothing at all, it's even better!
  669. if (limit > 0 && result.length == 0) {
  670. ++count;
  671. ++loopvar;
  672. }
  673. while (loopvar < limit) {
  674. if (loopvar <= clusters[candidate.name] && loopvar == 0 && Math.random() < cluster_chances[candidate.name]) {
  675. ++count;
  676. }
  677. else if (loopvar <= clusters[candidate.name]) {
  678. if (Math.random() < candidate.weight ? 1 : 0 || Math.random() < 0.75 * cluster_chances[candidate.name]) {
  679. ++count;
  680. }
  681. }
  682. else {
  683. count += Math.random() < candidate.weight ? 1 : 0;
  684. }
  685. ++loopvar;
  686. }
  687. if (limit < max) {
  688. count += Math.round((max-limit) * candidate.weight);
  689. }
  690. area -= count * candidate.area;
  691. if (count > 0)
  692. result.push(new things[candidate.name][candidate.name](count));
  693. }
  694. return new Container(result);
  695. }
  696. // describes everything in the container
  697. function describe_all(contents,verbose=true,except=[]) {
  698. var things = [];
  699. for (var key in contents) {
  700. if (contents.hasOwnProperty(key) && !except.includes(key)) {
  701. things.push(contents[key].describe(verbose));
  702. }
  703. }
  704. return merge_things(things);
  705. }
  706. function random_desc(list, odds=1) {
  707. if (Math.random() < odds)
  708. return list[Math.floor(Math.random() * list.length)];
  709. else
  710. return "";
  711. }
  712. // combine strings into a list with proper grammar
  713. function merge_things(list,semicolons=false) {
  714. if (list.length == 0) {
  715. return "";
  716. } else if (list.length == 1) {
  717. return list[0];
  718. } else if (list.length == 2) {
  719. return list[0] + " and " + list[1];
  720. } else {
  721. var result = "";
  722. list.slice(0,list.length-1).forEach(function(term) {
  723. result += term + ", ";
  724. });
  725. result += "and " + list[list.length-1];
  726. return result;
  727. }
  728. }
  729. // combine the adjectives for something into a single string
  730. function merge_desc(list) {
  731. var result = "";
  732. list.forEach(function(term) {
  733. if (term != "")
  734. result += term + " ";
  735. });
  736. // knock off the last space
  737. if (result.length > 0) {
  738. result = result.substring(0, result.length - 1);
  739. }
  740. return result;
  741. }
  742. // maybe make this something that approximates a
  743. // normal distribution; doing this 15,000,000 times is bad...
  744. // solution: only a few are random lul
  745. // improvement: take up to 100 samples, then use that to scale the final result
  746. function distribution(min, max, samples) {
  747. var result = 0;
  748. var limit = Math.min(100,samples);
  749. if (limit < samples) {
  750. let dist = 0;
  751. for (let i = 0; i < limit; i++) {
  752. dist += Math.random();
  753. }
  754. dist /= 100;
  755. return Math.floor(dist * samples * (max - min + 1) + samples * min);
  756. } else {
  757. for (let i = 0; i < limit; i++) {
  758. result += Math.floor(Math.random() * (max - min + 1) + min);
  759. }
  760. }
  761. return result;
  762. }
  763. function defaultMultiply(thing) {
  764. return function(amount) {
  765. thing.count *= amount;
  766. for (var key in thing.contents) {
  767. if (thing.contents.hasOwnProperty(key)) {
  768. thing.contents[key].multiply(amount);
  769. }
  770. }
  771. };
  772. }
  773. function defaultArea(thing) {
  774. return things[thing.name].area;
  775. }
  776. function defaultMass(thing) {
  777. return things[thing.name].mass;
  778. }
  779. function defaultMerge(thing) { //this merges all objects into one containers
  780. return function(container) {
  781. var newCount = this.count + container.count;
  782. var newThing = new things[thing.name][thing.name](newCount);
  783. newThing.contents = {};
  784. for (var key in this.contents) {
  785. if (this.contents.hasOwnProperty(key)) {
  786. newThing.contents[key] = this.contents[key];
  787. }
  788. }
  789. for (key in container.contents) {
  790. if (container.contents.hasOwnProperty(key)) {
  791. if (this.contents.hasOwnProperty(key)) {
  792. newThing.contents[key] = this.contents[key].merge(container.contents[key]);
  793. } else {
  794. newThing.contents[key] = container.contents[key];
  795. }
  796. }
  797. }
  798. return newThing;
  799. };
  800. }
  801. function listSum(sum) {
  802. let result = [];
  803. for (let key in sum) {
  804. if (sum.hasOwnProperty(key)) {
  805. result.push(new things[key][key](sum[key]).describe(false));
  806. }
  807. }
  808. return merge_things(result);
  809. }
  810. // turn a nested object into a container with everything on one level
  811. function flatten(thing) {
  812. let dict = defaultSum(thing)();
  813. let list = [];
  814. Object.entries(dict).forEach(function([key, val]) {
  815. let obj = new things[key][key](val);
  816. obj.contents = [];
  817. list.push(obj);
  818. });
  819. list.sort(function(x,y) {
  820. if (y.area != x.area){
  821. return y.area - x.area;
  822. } else {
  823. return x.name.localeCompare(y.name);
  824. }
  825. });
  826. return new Container(list);
  827. }
  828. function defaultSum(thing) {
  829. return function() {
  830. var counts = {};
  831. if (thing.name != "Container")
  832. counts[thing.name] = thing.count;
  833. for (var key in thing.contents) {
  834. if (thing.contents.hasOwnProperty(key)) {
  835. var subcount = thing.contents[key].sum();
  836. for (var subkey in subcount) {
  837. if (!counts.hasOwnProperty(subkey)) {
  838. counts[subkey] = 0;
  839. }
  840. counts[subkey] += subcount[subkey];
  841. }
  842. }
  843. }
  844. return counts;
  845. };
  846. }
  847. function defaultSumProperty(thing) {
  848. return function(prop) {
  849. var total = 0;
  850. total += thing[prop] * thing.count;
  851. for (var key in thing.contents) {
  852. if (thing.contents.hasOwnProperty(key)) {
  853. total += thing.contents[key].sum_property(prop);
  854. }
  855. }
  856. return total;
  857. };
  858. }
  859. function defaultAddContent(thing) {
  860. return function(name, min, max, count) {
  861. if (min == max) {
  862. let object = new things[name](min*count);
  863. thing.contents[object.name] = object;
  864. } else {
  865. let object = new things[name](distribution(min, max, count));
  866. thing.contents[object.name] = object;
  867. }
  868. };
  869. }
  870. function defaultDescribeSimple(thing) {
  871. return function(flat) {
  872. if (flat) {
  873. return flatten(thing).describe(false)
  874. } else {
  875. return thing.describe(false);
  876. }
  877. }
  878. }
  879. function DefaultEntity() {
  880. this.sum = defaultSum;
  881. this.area = defaultArea;
  882. this.mass = defaultMass;
  883. this.sum_property = defaultSumProperty;
  884. this.merge = defaultMerge;
  885. this.multiply = defaultMultiply;
  886. this.describeSimple = defaultDescribeSimple;
  887. return this;
  888. }
  889. // god I love reinventing the wheel
  890. function copy_defaults(self,proto) { //loads the values defined in things into the fuction that calls it
  891. for (var key in proto) { //proto will always be a new DefaultEntity, self is the parent function
  892. if (proto.hasOwnProperty(key)) {
  893. self[key] = proto[key](self);
  894. }
  895. }
  896. }
  897. function Container(contents = []) {
  898. this.name = "Container";
  899. copy_defaults(this,new DefaultEntity());
  900. if (Number.isInteger(contents))
  901. this.count = contents;
  902. else
  903. this.count = 0;
  904. this.contents = {};
  905. for (var i=0; i < contents.length; i++) {
  906. this.contents[contents[i].name] = contents[i];
  907. }
  908. for (var key in this.contents) {
  909. if (this.contents.hasOwnProperty(key)) {
  910. this.count += this.contents[key].count;
  911. }
  912. }
  913. this.describe = function(verbose = true) {
  914. return describe_all(this.contents,verbose);
  915. };
  916. return this;
  917. }
  918. function Person(count = 1) {
  919. this.name = "Person";
  920. copy_defaults(this,new DefaultEntity());
  921. this.count = count;
  922. this.contents = initContents(this.name,this.count);
  923. this.describeOne = function (verbose=true) {
  924. var body = random_desc(["skinny","fat","tall","short","stocky","spindly","muscular","fit","multi-colored"], (verbose ? 0.6 : 0));
  925. var sex = random_desc(["male", "female"], (verbose ? 0.75 : 0));
  926. var species = "";
  927. species = random_desc(["wolf","cat","dog","squirrel","horse","hyena","fox","jackal","crux","sergal","coyote","rabbit","lizard","avian"]);
  928. return "a " + merge_desc([body,sex,species]);
  929. };
  930. this.describe = function(verbose=true) {
  931. if (verbose) {
  932. if (count <= 3) {
  933. var list = [];
  934. for (var i = 0; i < count; i++) {
  935. list.push(this.describeOne(this.count <= 2));
  936. }
  937. return merge_things(list);
  938. } else {
  939. return this.count + " people";
  940. }
  941. } else {
  942. return (this.count > 1 ? this.count + " people" : "a person");
  943. }
  944. };
  945. return this;
  946. }
  947. function Human(count = 1) {
  948. this.name = "Person";
  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 body = random_desc(["skinny","fat","tall","short","stocky","spindly","muscular","fit","tanned"], (verbose ? 0.6 : 0));
  954. var sex = random_desc(["man", "woman"], 1);
  955. return "a " + merge_desc([body,sex]);
  956. };
  957. this.describe = function(verbose=true) {
  958. if (verbose) {
  959. if (count <= 3) {
  960. var list = [];
  961. for (var i = 0; i < count; i++) {
  962. list.push(this.describeOne(this.count <= 2));
  963. }
  964. return merge_things(list);
  965. } else {
  966. return this.count + " people";
  967. }
  968. } else {
  969. return (this.count > 1 ? this.count + " people" : "a person");
  970. }
  971. };
  972. return this;
  973. }
  974. function Cow(count = 1) {
  975. this.name = "Cow";
  976. copy_defaults(this,new DefaultEntity());
  977. this.count = count;
  978. this.contents = initContents(this.name,this.count);
  979. this.describeOne = function (verbose=true) {
  980. var body = random_desc(["skinny","fat","tall","short","stocky","spindly"], (verbose ? 0.6 : 0));
  981. var sex = random_desc(["male", "female"], (verbose ? 1 : 0));
  982. return "a " + merge_desc([body,sex,"cow"]);
  983. };
  984. this.describe = function(verbose=true) {
  985. if (verbose) {
  986. if (count <= 3) {
  987. var list = [];
  988. for (var i = 0; i < count; i++) {
  989. list.push(this.describeOne(this.count <= 2));
  990. }
  991. return merge_things(list);
  992. } else {
  993. return this.count + " cattle";
  994. }
  995. } else {
  996. return (this.count > 1 ? this.count + " cattle" : "a cow");
  997. }
  998. };
  999. return this;
  1000. }
  1001. function EmptyCar(count = 1) {
  1002. this.name = "Car";
  1003. copy_defaults(this,new DefaultEntity());
  1004. this.count = count;
  1005. this.contents = initContents(this.name,this.count);
  1006. this.describeOne = function(verbose=true) {
  1007. var color = random_desc(["black","black","gray","gray","blue","red","tan","white","white"]);
  1008. var adjective = random_desc(["rusty","brand-new","luxury","beat-up","dented","restored","classic"],0.3);
  1009. var type = random_desc(["SUV","coupe","sedan","truck","van","convertible"]);
  1010. return "a parked " + merge_desc([adjective,color,type]);
  1011. };
  1012. this.describe = function(verbose = true) {
  1013. if (verbose) {
  1014. if (this.count <= 3) {
  1015. var list = [];
  1016. for (var i = 0; i < this.count; i++) {
  1017. list.push(this.describeOne());
  1018. }
  1019. return merge_things(list);
  1020. } else {
  1021. return this.count + " parked cars";
  1022. }
  1023. } else {
  1024. return (this.count > 1 ? this.count + " parked cars" : "a parked car");
  1025. }
  1026. };
  1027. }
  1028. function Car(count = 1) {
  1029. this.name = "Car";
  1030. copy_defaults(this,new DefaultEntity());
  1031. this.count = count;
  1032. this.contents = initContents(this.name,this.count);
  1033. this.describeOne = function(verbose=true) {
  1034. var color = random_desc(["black","black","gray","gray","blue","red","tan","white","white"], (verbose ? 1 : 0));
  1035. var adjective = random_desc(["rusty","brand-new","luxury","beat-up","dented","restored","classic"], (verbose ? 0.3 : 0));
  1036. var type = random_desc(["SUV","coupe","sedan","truck","van","convertible"]);
  1037. return "a " + merge_desc([adjective,color,type]);
  1038. };
  1039. this.describe = function(verbose = true) {
  1040. if (verbose) {
  1041. if (this.count <= 3) {
  1042. var list = [];
  1043. for (var i = 0; i < this.count; i++) {
  1044. list.push(this.describeOne(this.count < 2));
  1045. }
  1046. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  1047. } else {
  1048. return this.count + " cars with " + describe_all(this.contents,verbose) + " inside";
  1049. }
  1050. } else {
  1051. return (this.count > 1 ? this.count + " cars" : "a car");
  1052. }
  1053. };
  1054. }
  1055. function Bus(count = 1) {
  1056. this.name = "Bus";
  1057. copy_defaults(this,new DefaultEntity());
  1058. this.count = count;
  1059. this.contents = initContents(this.name,this.count);
  1060. this.describeOne = function(verbose=true) {
  1061. var adjective = random_desc(["rusty","brand-new","aging","modern"], (verbose ? 0.3 : 0));
  1062. var color = random_desc(["black","tan","gray"], (verbose ? 1 : 0));
  1063. var type = random_desc(["bus","double-decker bus","articulating bus","open-top bus","sleeper bus","intercity bus"]);
  1064. return "a " + merge_desc([adjective,color,type]);
  1065. };
  1066. this.describe = function(verbose = true) {
  1067. if (verbose) {
  1068. if (this.count <= 3) {
  1069. var list = [];
  1070. for (var i = 0; i < this.count; i++) {
  1071. list.push(this.describeOne(this.count < 2));
  1072. }
  1073. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  1074. } else {
  1075. return this.count + " buses with " + describe_all(this.contents,verbose) + " inside";
  1076. }
  1077. } else {
  1078. return (this.count > 1 ? this.count + " buses" : "a bus");
  1079. }
  1080. };
  1081. }
  1082. function Tram(count = 1) {
  1083. this.name = "Tram";
  1084. copy_defaults(this,new DefaultEntity());
  1085. this.count = count;
  1086. this.contents = initContents(this.name,this.count);
  1087. this.describeOne = function(verbose=true) {
  1088. var adjective = random_desc(["rusty","weathered","well-maintained",], (verbose ? 0.3 : 0));
  1089. var color = random_desc(["blue","brown","gray"], (verbose ? 1 : 0));
  1090. var type = random_desc(["tram"]);
  1091. return "a " + merge_desc([adjective,color,type]);
  1092. };
  1093. this.describe = function(verbose = true) {
  1094. if (verbose) {
  1095. if (this.count == 1) {
  1096. var list = [];
  1097. for (var i = 0; i < this.count; i++) {
  1098. list.push(this.describeOne(verbose));
  1099. }
  1100. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  1101. } else {
  1102. return this.count + " trams with " + describe_all(this.contents,verbose) + " inside";
  1103. }
  1104. } else {
  1105. return (this.count > 1 ? this.count + " trams" : "a tram");
  1106. }
  1107. };
  1108. this.anal_vore = function() {
  1109. return "You slide " + this.describe() + " up your tight ass";
  1110. };
  1111. }
  1112. function Train(count = 1) {
  1113. this.name = "Train";
  1114. copy_defaults(this,new DefaultEntity());
  1115. this.count = count;
  1116. this.contents = initContents(this.name,this.count);
  1117. this.describeOne = function(verbose=true) {
  1118. var adjective = random_desc(["rusty","brand-new","steam","freshly-painted"], (verbose ? 0.3 : 0));
  1119. var color = random_desc(["black","tan","gray"], (verbose ? 1 : 0));
  1120. var type = random_desc(["train","passenger train","freight train"]);
  1121. return "a " + merge_desc([adjective,color,type]);
  1122. };
  1123. this.describe = function(verbose = true) {
  1124. if (verbose) {
  1125. if (this.count == 1) {
  1126. var list = [];
  1127. for (var i = 0; i < this.count; i++) {
  1128. list.push(this.describeOne(verbose));
  1129. }
  1130. return merge_things(list) + " with " + this.contents["engine"].describe(false) + " in the engine and " + this.contents["Train Car"].describe() + " attached";
  1131. } else {
  1132. return this.count + " trains with " + this.contents["engine"].describe(false) + " in the engine and " + this.contents["Train Car"].describe() + " attached";
  1133. }
  1134. } else {
  1135. return (this.count > 1 ? this.count + " trains" : "a train");
  1136. }
  1137. };
  1138. this.anal_vore = function() {
  1139. 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");
  1140. return "You snatch up " + this.describeOne() + " and stuff it into your pucker, moaning as " + cars;
  1141. };
  1142. }
  1143. function TrainCar(count = 1) {
  1144. this.name = "Train Car";
  1145. copy_defaults(this,new DefaultEntity());
  1146. this.count = count;
  1147. this.contents = initContents(this.name,this.count);
  1148. this.describeOne = function(verbose=true) {
  1149. var adjective = random_desc(["rusty","brand-new","vintage","graffitied","well-maintained"], (verbose ? 0.3 : 0));
  1150. var color = random_desc(["black","tan","gray","yellow","steel","wooden"], (verbose ? 1 : 0));
  1151. var type = random_desc(["train car","passenger train car","freight train car"]);
  1152. return "a " + merge_desc([adjective,color,type]);
  1153. };
  1154. this.describe = function(verbose = true) {
  1155. if (verbose) {
  1156. return (this.count > 1 ? this.count + " train cars" : "a train car") + " with " + describe_all(this.contents) + " inside";
  1157. } else {
  1158. return (this.count > 1 ? this.count + " train cars" : "a train car");
  1159. }
  1160. };
  1161. }
  1162. function House(count = 1) {
  1163. this.name = "House";
  1164. copy_defaults(this,new DefaultEntity());
  1165. this.count = count;
  1166. this.contents = initContents(this.name,this.count);
  1167. this.describeOne = function(verbose=true) {
  1168. var size = random_desc(["little","two-story","large","well-built","run-down","cheap",], (verbose ? 0.5 : 0));
  1169. var color = random_desc(["blue","white","gray","tan","green","wooden","brick"], (verbose ? 0.5 : 0));
  1170. var name = random_desc(["house","home","house","house","house","trailer"], 1);
  1171. return "a " + merge_desc([size,color,name]);
  1172. };
  1173. this.describe = function(verbose = true) {
  1174. if (verbose) {
  1175. if (this.count <= 3) {
  1176. var list = [];
  1177. for (var i = 0; i < this.count; i++) {
  1178. list.push(this.describeOne(this.count < 2));
  1179. }
  1180. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  1181. } else {
  1182. return this.count + " homes with " + describe_all(this.contents,verbose) + " inside";
  1183. }
  1184. } else {
  1185. return (this.count > 1 ? this.count + " houses" : "a house");
  1186. }
  1187. };
  1188. }
  1189. //might split this into a general business and resutrant categories
  1190. function Business(count = 1) {
  1191. this.name = "Business";
  1192. copy_defaults(this,new DefaultEntity());
  1193. this.count = count;
  1194. this.contents = initContents(this.name,this.count);
  1195. this.describeOne = function(verbose=true) {
  1196. var size = random_desc(["little","two-story","large","well-built","run-down","cheap","aging","corner"], (verbose ? 0.5 : 0));
  1197. var color = random_desc(["blue","white","gray","tan","green","brick","concrete"], (verbose ? 0.5 : 0));
  1198. 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);
  1199. return "a " + merge_desc([size,color,name]);
  1200. };
  1201. this.describe = function(verbose = true) {
  1202. if (verbose) {
  1203. if (this.count <= 3) {
  1204. var list = [];
  1205. for (var i = 0; i < this.count; i++) {
  1206. list.push(this.describeOne(this.count < 2));
  1207. }
  1208. return merge_things(list) + " with " + describe_all(this.contents,verbose);
  1209. } else {
  1210. return this.count + " local business containing " + describe_all(this.contents,verbose);
  1211. }
  1212. } else {
  1213. return (this.count > 1 ? this.count + " buildings" : "a local business");
  1214. }
  1215. };
  1216. }
  1217. function Barn(count = 1) {
  1218. this.name = "Barn";
  1219. copy_defaults(this,new DefaultEntity());
  1220. this.count = count;
  1221. this.contents = initContents(this.name,this.count);
  1222. this.describeOne = function(verbose=true) {
  1223. var size = random_desc(["little","big","large","weathered","rotted","new"], (verbose ? 0.5 : 0));
  1224. var color = random_desc(["blue","white","gray","tan","green","red"], (verbose ? 0.5 : 0));
  1225. var name = random_desc(["barn","barn","barn","barn","barn","farmhouse"], 1);
  1226. return "a " + merge_desc([size,color,name]);
  1227. };
  1228. this.describe = function(verbose = true) {
  1229. if (verbose) {
  1230. if (this.count <= 3) {
  1231. var list = [];
  1232. for (var i = 0; i < this.count; i++) {
  1233. list.push(this.describeOne(this.count < 2));
  1234. }
  1235. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  1236. } else {
  1237. return this.count + " barns with " + describe_all(this.contents,verbose) + " inside";
  1238. }
  1239. } else {
  1240. return (this.count > 1 ? this.count + " barns" : "a barn");
  1241. }
  1242. };
  1243. }
  1244. function SmallSkyscraper(count = 1) {
  1245. this.name = "Small Skyscraper";
  1246. copy_defaults(this,new DefaultEntity());
  1247. this.count = count;
  1248. this.contents = initContents(this.name,this.count);
  1249. this.describeOne = function(verbose=true) {
  1250. var color = random_desc(["blue","white","gray","tan","green"], (verbose ? 0.5 : 0));
  1251. var name = random_desc(["skyscraper","office tower","office building","high rise"], 1);
  1252. return "a " + merge_desc([color,name]);
  1253. };
  1254. this.describe = function(verbose = true) {
  1255. if (verbose) {
  1256. if (this.count <= 3) {
  1257. var list = [];
  1258. for (var i = 0; i < this.count; i++) {
  1259. list.push(this.describeOne(this.count < 2));
  1260. }
  1261. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  1262. } else {
  1263. return this.count + " small skyscrapers with " + describe_all(this.contents,verbose) + " inside";
  1264. }
  1265. } else {
  1266. return (this.count > 1 ? this.count + " small skyscrapers" : "a small skyscraper");
  1267. }
  1268. };
  1269. }
  1270. function LargeSkyscraper(count = 1) {
  1271. this.name = "Large Skyscraper";
  1272. copy_defaults(this,new DefaultEntity());
  1273. this.count = count;
  1274. this.contents = initContents(this.name,this.count);
  1275. this.describeOne = function(verbose=true) {
  1276. var color = random_desc(["blue","white","gray","tan","green","glass"], (verbose ? 0.5 : 0));
  1277. var name = random_desc(["skyscraper","office tower","office building"], 1);
  1278. return "a " + merge_desc(["towering",color,name]);
  1279. };
  1280. this.describe = function(verbose = true) {
  1281. if (verbose) {
  1282. if (this.count <= 3) {
  1283. var list = [];
  1284. for (var i = 0; i < this.count; i++) {
  1285. list.push(this.describeOne(this.count < 2));
  1286. }
  1287. return merge_things(list) + " with " + describe_all(this.contents,verbose) + " inside";
  1288. } else {
  1289. return this.count + " large skyscrapers with " + describe_all(this.contents,verbose) + " inside";
  1290. }
  1291. } else {
  1292. return (this.count > 1 ? this.count + " large skyscrapers" : "a large skyscraper");
  1293. }
  1294. };
  1295. }
  1296. function ParkingGarage(count = 1) {
  1297. this.name = "Parking Garage";
  1298. copy_defaults(this,new DefaultEntity());
  1299. this.count = count;
  1300. this.contents = initContents(this.name,this.count);
  1301. this.describeOne = function(verbose=true) {
  1302. return "a parking garage";
  1303. };
  1304. this.describe = function(verbose = true) {
  1305. if (verbose) {
  1306. return (this.count == 1 ? "a parking garage" : this.count + " parking garages") + " with " + describe_all(this.contents, verbose);
  1307. } else {
  1308. return (this.count == 1 ? "a parking garage" : this.count + " parking garages");
  1309. }
  1310. };
  1311. }
  1312. function Town(count = 1) {
  1313. this.name = "Town";
  1314. copy_defaults(this,new DefaultEntity());
  1315. this.count = count;
  1316. this.contents = initContents(this.name,this.count);
  1317. this.describe = function(verbose = true) {
  1318. if (verbose) {
  1319. return (this.count == 1 ? "a town" : this.count + " towns") + " with " + describe_all(this.contents, verbose) + " in " + (this.count == 1 ? "it" : "them");
  1320. } else {
  1321. return (this.count == 1 ? "a town" : this.count + " towns");
  1322. }
  1323. };
  1324. }
  1325. function City(count = 1) {
  1326. this.name = "City";
  1327. copy_defaults(this,new DefaultEntity());
  1328. this.count = count;
  1329. this.contents = initContents(this.name,this.count);
  1330. this.describe = function(verbose = true) {
  1331. if (verbose) {
  1332. return (this.count == 1 ? "a city" : this.count + " cities") + " with " + describe_all(this.contents, verbose) + " in " + (this.count == 1 ? "it" : "them");
  1333. } else {
  1334. return (this.count == 1 ? "a city" : this.count + " cities");
  1335. }
  1336. };
  1337. }
  1338. function Continent(count = 1) {
  1339. this.name = "Continent";
  1340. copy_defaults(this,new DefaultEntity());
  1341. this.count = count;
  1342. this.contents = initContents(this.name,this.count);
  1343. this.describe = function(verbose = true) {
  1344. if (verbose) {
  1345. return (this.count == 1 ? "a continent" : this.count + " continents") + " with " + describe_all(this.contents, verbose) + " on " + (this.count == 1 ? "it" : "them");
  1346. } else {
  1347. return (this.count == 1 ? "a continent" : this.count + " continents");
  1348. }
  1349. };
  1350. }
  1351. function Planet(count = 1) {
  1352. this.name = "Planet";
  1353. copy_defaults(this,new DefaultEntity());
  1354. this.count = count;
  1355. this.contents = initContents(this.name,this.count);
  1356. this.describe = function(verbose = true) {
  1357. if (verbose) {
  1358. return (this.count == 1 ? "a planet" : this.count + " planets") + " with " + describe_all(this.contents, verbose) + " on " + (this.count == 1 ? "it" : "them");
  1359. } else {
  1360. return (this.count == 1 ? "a planet" : this.count + " planets");
  1361. }
  1362. };
  1363. }
  1364. function Star(count = 1) {
  1365. this.name = "Star";
  1366. copy_defaults(this,new DefaultEntity());
  1367. this.count = count;
  1368. this.contents = initContents(this.name,this.count);
  1369. this.describe = function(verbose = true) {
  1370. return (this.count == 1 ? "a star" : this.count + " stars");
  1371. };
  1372. }
  1373. function SolarSystem(count = 1) {
  1374. this.name = "Solar System";
  1375. copy_defaults(this,new DefaultEntity());
  1376. this.count = count;
  1377. this.contents = initContents(this.name,this.count);
  1378. this.describe = function(verbose = true) {
  1379. if (verbose) {
  1380. return (this.count == 1 ? "a solar system" : this.count + " solar systems") + " made up of " + describe_all(this.contents, verbose);
  1381. } else {
  1382. return (this.count == 1 ? "a solar system" : this.count + " solar systems");
  1383. }
  1384. };
  1385. }
  1386. function Galaxy(count = 1) {
  1387. this.name = "Galaxy";
  1388. copy_defaults(this,new DefaultEntity());
  1389. this.count = count;
  1390. this.contents = initContents(this.name,this.count);
  1391. this.describe = function(verbose = true) {
  1392. if (verbose) {
  1393. return (this.count == 1 ? "a galaxy" : this.count + " galaxies") + " made up of " + describe_all(this.contents, verbose);
  1394. } else {
  1395. return (this.count == 1 ? "a galaxy" : this.count + " galaxies");
  1396. }
  1397. };
  1398. }
  1399. function Cluster(count = 1) {
  1400. this.name = "Cluster";
  1401. copy_defaults(this,new DefaultEntity());
  1402. this.count = count;
  1403. this.contents = initContents(this.name,this.count);
  1404. this.describe = function(verbose = true) {
  1405. if (verbose) {
  1406. return (this.count == 1 ? "a cluster" : this.count + " clusters") + " made up of " + describe_all(this.contents, verbose);
  1407. } else {
  1408. return (this.count == 1 ? "a cluster" : this.count + " clusters");
  1409. }
  1410. };
  1411. }
  1412. function Universe(count = 1) {
  1413. this.name = "Universe";
  1414. copy_defaults(this,new DefaultEntity());
  1415. this.count = count;
  1416. this.contents = initContents(this.name,this.count);
  1417. this.describe = function(verbose = true) {
  1418. if (verbose) {
  1419. return (this.count == 1 ? "a universe" : this.count + " universes") + " made up of " + describe_all(this.contents, verbose);
  1420. } else {
  1421. return (this.count == 1 ? "a universe" : this.count + " universes");
  1422. }
  1423. };
  1424. }
  1425. function Multiverse(count = 1) {
  1426. this.name = "Multiverse";
  1427. copy_defaults(this,new DefaultEntity());
  1428. this.count = count;
  1429. this.contents = initContents(this.name,this.count);
  1430. this.describe = function(verbose = true) {
  1431. if (verbose) {
  1432. return (this.count == 1 ? "a multiverse" : this.count + " multiverses") + " made up of " + describe_all(this.contents, verbose);
  1433. } else {
  1434. return (this.count == 1 ? "a multiverse" : this.count + " multiverses");
  1435. }
  1436. };
  1437. }
  1438. function Soldier(count = 1) {
  1439. this.name = "Soldier";
  1440. copy_defaults(this,new DefaultEntity());
  1441. this.count = count;
  1442. this.contents = initContents(this.name,this.count);
  1443. this.describe = function(verbose = true) {
  1444. return (this.count == 1 ? "a soldier" : this.count + " soldiers");
  1445. };
  1446. }
  1447. function Tank(count = 1) {
  1448. this.name = "Tank";
  1449. copy_defaults(this,new DefaultEntity());
  1450. this.count = count;
  1451. this.contents = initContents(this.name,this.count);
  1452. this.describe = function(verbose = true) {
  1453. if (verbose) {
  1454. return (this.count == 1 ? "a tank" : this.count + " tanks") + " with " + describe_all(this.contents, verbose) + " trapped inside";
  1455. } else {
  1456. return (this.count == 1 ? "a tank" : this.count + " tanks");
  1457. }
  1458. };
  1459. }
  1460. function Artillery(count = 1) {
  1461. this.name = "Artillery";
  1462. copy_defaults(this,new DefaultEntity());
  1463. this.count = count;
  1464. this.contents = initContents(this.name,this.count);
  1465. this.describe = function(verbose = true) {
  1466. if (verbose) {
  1467. return (this.count == 1 ? "an artillery unit" : this.count + " artillery units") + " with " + describe_all(this.contents, verbose) + " trapped inside";
  1468. } else {
  1469. return (this.count == 1 ? "an artillery unit" : this.count + " artillery units");
  1470. }
  1471. };
  1472. }
  1473. function Helicopter(count = 1) {
  1474. this.name = "Helicopter";
  1475. copy_defaults(this,new DefaultEntity());
  1476. this.count = count;
  1477. this.contents = initContents(this.name,this.count);
  1478. this.describe = function(verbose = true) {
  1479. if (verbose) {
  1480. return (this.count == 1 ? "a helicopter" : this.count + " helicopters") + " with " + describe_all(this.contents, verbose) + " riding inside";
  1481. } else {
  1482. return (this.count == 1 ? "a helicopter" : this.count + " helicopters");
  1483. }
  1484. };
  1485. }
  1486. function Micro(count = 1) {
  1487. this.name = "Micro";
  1488. copy_defaults(this,new DefaultEntity());
  1489. this.count = count;
  1490. this.contents = initContents(this.name,this.count);
  1491. this.describe = function(verbose = true) {
  1492. return (this.count == 1 ? "a micro" : this.count + " micros");
  1493. };
  1494. }
  1495. function Macro(count = 1) {
  1496. this.name = "Macro";
  1497. copy_defaults(this,new DefaultEntity());
  1498. this.count = count;
  1499. this.contents = initContents(this.name,this.count);
  1500. this.describe = function(verbose = true) {
  1501. return (this.count == 1 ? "a smaller macro" : this.count + " smaller macros");
  1502. };
  1503. }
  1504. function Squad(count = 1) {
  1505. this.name = "Squad";
  1506. copy_defaults(this,new DefaultEntity());
  1507. this.count = count;
  1508. this.contents = initContents(this.name,this.count);
  1509. this.describeOne = function(verbose=true) {
  1510. return "a squad";
  1511. };
  1512. this.describe = function(verbose = true) {
  1513. if (verbose) {
  1514. return (this.count == 1 ? "a squad" : this.count + " squads") + " made up of " + describe_all(this.contents, verbose);
  1515. } else {
  1516. return (this.count == 1 ? "a squad" : this.count + " squads");
  1517. }
  1518. };
  1519. }
  1520. function Platoon(count = 1) {
  1521. this.name = "Platoon";
  1522. copy_defaults(this,new DefaultEntity());
  1523. this.count = count;
  1524. this.contents = initContents(this.name,this.count);
  1525. this.describeOne = function(verbose=true) {
  1526. return "a military platoon";
  1527. };
  1528. this.describe = function(verbose = true) {
  1529. if (verbose) {
  1530. return (this.count == 1 ? "a platoon" : this.count + " platoons") + " consisting of " + describe_all(this.contents, verbose);
  1531. } else {
  1532. return (this.count == 1 ? "a platoon" : this.count + " platoons");
  1533. }
  1534. };
  1535. }
  1536. function Company(count = 1) {
  1537. this.name = "Company";
  1538. copy_defaults(this,new DefaultEntity());
  1539. this.count = count;
  1540. this.contents = initContents(this.name,this.count);
  1541. this.describeOne = function(verbose=true) {
  1542. return "a company of soldiers";
  1543. };
  1544. this.describe = function(verbose = true) {
  1545. if (verbose) {
  1546. return (this.count == 1 ? "a company" : this.count + " companies") + " of " + describe_all(this.contents, verbose);
  1547. } else {
  1548. return (this.count == 1 ? "a company" : this.count + " companies");
  1549. }
  1550. };
  1551. }
  1552. function Battalion(count = 1) {
  1553. this.name = "Battalion";
  1554. copy_defaults(this,new DefaultEntity());
  1555. this.count = count;
  1556. this.contents = initContents(this.name,this.count);
  1557. this.describeOne = function(verbose=true) {
  1558. return "a battalion";
  1559. };
  1560. this.describe = function(verbose = true) {
  1561. if (verbose) {
  1562. return (this.count == 1 ? "a battalion" : this.count + " battalions") + " containing " + describe_all(this.contents, verbose);
  1563. } else {
  1564. return (this.count == 1 ? "a battalion" : this.count + " battalions");
  1565. }
  1566. };
  1567. }
  1568. function Brigade(count = 1) {
  1569. this.name = "Brigade";
  1570. copy_defaults(this,new DefaultEntity());
  1571. this.count = count;
  1572. this.contents = initContents(this.name,this.count);
  1573. this.describeOne = function(verbose=true) {
  1574. return "a brigade";
  1575. };
  1576. this.describe = function(verbose = true) {
  1577. if (verbose) {
  1578. return (this.count == 1 ? "a brigade" : this.count + " brigades") + " made up of " + describe_all(this.contents, verbose);
  1579. } else {
  1580. return (this.count == 1 ? "a brigade" : this.count + " brigades");
  1581. }
  1582. };
  1583. }
  1584. function Division(count = 1) {
  1585. this.name = "Division";
  1586. copy_defaults(this,new DefaultEntity());
  1587. this.count = count;
  1588. this.contents = initContents(this.name,this.count);
  1589. this.describeOne = function(verbose=true) {
  1590. return "a division";
  1591. };
  1592. this.describe = function(verbose = true) {
  1593. if (verbose) {
  1594. return (this.count == 1 ? "a division" : this.count + " divisions") + " of " + describe_all(this.contents, verbose);
  1595. } else {
  1596. return (this.count == 1 ? "a division" : this.count + " divisions");
  1597. }
  1598. };
  1599. }
  1600. function TankDivision(count = 1) {
  1601. this.name = "Tank Division";
  1602. copy_defaults(this,new DefaultEntity());
  1603. this.count = count;
  1604. this.contents = initContents(this.name,this.count);
  1605. this.describeOne = function(verbose=true) {
  1606. return "a tank division";
  1607. };
  1608. this.describe = function(verbose = true) {
  1609. if (verbose) {
  1610. return (this.count == 1 ? "a tank division" : this.count + " tank divisions") + " of " + describe_all(this.contents, verbose);
  1611. } else {
  1612. return (this.count == 1 ? "a tank division" : this.count + " tank divisions");
  1613. }
  1614. };
  1615. }
  1616. function Army(count = 1) {
  1617. this.name = "Army";
  1618. copy_defaults(this,new DefaultEntity());
  1619. this.count = count;
  1620. this.contents = initContents(this.name,this.count);
  1621. this.describeOne = function(verbose=true) {
  1622. return "an army";
  1623. };
  1624. this.describe = function(verbose = true) {
  1625. if (verbose) {
  1626. return (this.count == 1 ? "an army" : this.count + " armies") + " made up of " + describe_all(this.contents, verbose);
  1627. } else {
  1628. return (this.count == 1 ? "an army" : this.count + " armies");
  1629. }
  1630. };
  1631. }
  1632. //todo
  1633. //redo everything
  1634. //airports
  1635. //farms
  1636. //racetracks
  1637. //more building types
  1638. //nebula
  1639. //grand army
  1640. //armada