Feast 2.0!
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 

503 rindas
13 KiB

  1. import { Entity, POV } from './entity'
  2. import { LogEntry, LogLine } from './interface'
  3. export type SoloLine<T> = (user: T) => LogEntry
  4. export type SoloLineArgs<T, V> = (user: T, args: V) => LogEntry
  5. export type PairLine<T> = (user: T, target: T) => LogEntry
  6. export type PairLineArgs<T, V> = (user: T, target: T, args: V) => LogEntry
  7. export class POVPair<K extends Entity, V extends Entity> {
  8. run (user: K, target: V): LogEntry {
  9. const choice = this.options.find(element => element[0][0] === user.perspective && element[0][1] === target.perspective)
  10. if (choice === undefined) {
  11. return new LogLine("Fen didn't write any text for this...")
  12. } else {
  13. return choice[1](user, target)
  14. }
  15. }
  16. constructor (private options: Array<[[POV, POV], (user: K, target: V) => LogEntry]>) {
  17. }
  18. }
  19. export class POVPairArgs<K extends Entity, V extends Entity, U> {
  20. run (user: K, target: V, args: U): LogEntry {
  21. const choice = this.options.find(element => element[0][0] === user.perspective && element[0][1] === target.perspective)
  22. if (choice === undefined) {
  23. return new LogLine("Fen didn't write any text for this...")
  24. } else {
  25. return choice[1](user, target, args)
  26. }
  27. }
  28. constructor (private options: Array<[[POV, POV], (user: K, target: V, args: U) => LogEntry]>) {
  29. }
  30. }
  31. export class POVSolo<K extends Entity> {
  32. run (user: K): LogEntry {
  33. const choice = this.options.find(element => element[0][0] === user.perspective)
  34. if (choice === undefined) {
  35. return new LogLine("Fen didn't write any text for this...")
  36. } else {
  37. return choice[1](user)
  38. }
  39. }
  40. constructor (private options: Array<[[POV], (user: K) => LogEntry]>) {
  41. }
  42. }
  43. enum NounKind {
  44. Specific,
  45. Nonspecific,
  46. All
  47. }
  48. enum VowelSound {
  49. Default,
  50. Vowel,
  51. NonVowel
  52. }
  53. enum VerbKind {
  54. Root,
  55. Singular,
  56. Present,
  57. Past,
  58. PastParticiple
  59. }
  60. export interface Pluralizable {
  61. isPlural: boolean;
  62. }
  63. interface WordOptions {
  64. plural: boolean;
  65. capital: boolean;
  66. allCaps: boolean;
  67. proper: boolean;
  68. nounKind: NounKind;
  69. verbKind: VerbKind;
  70. vowel: VowelSound;
  71. count: boolean;
  72. possessive: boolean;
  73. objective: boolean;
  74. }
  75. const emptyConfig: WordOptions = {
  76. allCaps: false,
  77. capital: false,
  78. count: false,
  79. nounKind: NounKind.Specific,
  80. verbKind: VerbKind.Root,
  81. plural: false,
  82. proper: false,
  83. vowel: VowelSound.Default,
  84. possessive: false,
  85. objective: false
  86. }
  87. export type TextLike = { toString: () => string }
  88. // updates as needed
  89. export class LiveText<T> {
  90. toString (): string {
  91. return this.run(this.contents).toString()
  92. }
  93. constructor (private contents: T, private run: (thing: T) => TextLike) {
  94. }
  95. }
  96. export class DynText {
  97. private parts: Array<TextLike>
  98. constructor (...parts: TextLike[]) {
  99. this.parts = parts
  100. }
  101. toString (): string {
  102. return (this.parts.map(part => part.toString())).join('')
  103. }
  104. }
  105. export abstract class Word {
  106. constructor (public opt: WordOptions = emptyConfig) {
  107. }
  108. abstract configure (opts: WordOptions): Word;
  109. abstract toString (): string;
  110. // These functions are pure; they don't mutate the original object.
  111. // This is necessary to avoid causing chaos.
  112. get allCaps (): this {
  113. const opts: WordOptions = Object.assign({}, this.opt)
  114. opts.allCaps = true
  115. return this.configure(opts) as this
  116. }
  117. get capital (): this {
  118. const opts: WordOptions = Object.assign({}, this.opt)
  119. opts.capital = true
  120. return this.configure(opts) as this
  121. }
  122. get plural (): this {
  123. const opts: WordOptions = Object.assign({}, this.opt)
  124. opts.plural = true
  125. return this.configure(opts) as this
  126. }
  127. get proper (): this {
  128. const opts: WordOptions = Object.assign({}, this.opt)
  129. opts.proper = true
  130. return this.configure(opts) as this
  131. }
  132. get improper (): this {
  133. const opts: WordOptions = Object.assign({}, this.opt)
  134. opts.proper = false
  135. return this.configure(opts) as this
  136. }
  137. get specific (): this {
  138. const opts: WordOptions = Object.assign({}, this.opt)
  139. opts.nounKind = NounKind.Specific
  140. return this.configure(opts) as this
  141. }
  142. get nonspecific (): this {
  143. const opts: WordOptions = Object.assign({}, this.opt)
  144. opts.nounKind = NounKind.Nonspecific
  145. return this.configure(opts) as this
  146. }
  147. get all (): this {
  148. const opts: WordOptions = Object.assign({}, this.opt)
  149. opts.nounKind = NounKind.All
  150. return this.configure(opts) as this
  151. }
  152. get uncountable (): this {
  153. const opts: WordOptions = Object.assign({}, this.opt)
  154. opts.count = false
  155. return this.configure(opts) as this
  156. }
  157. get root (): this {
  158. const opts: WordOptions = Object.assign({}, this.opt)
  159. opts.verbKind = VerbKind.Root
  160. return this.configure(opts) as this
  161. }
  162. get singular (): this {
  163. const opts: WordOptions = Object.assign({}, this.opt)
  164. opts.verbKind = VerbKind.Singular
  165. return this.configure(opts) as this
  166. }
  167. get present (): this {
  168. const opts: WordOptions = Object.assign({}, this.opt)
  169. opts.verbKind = VerbKind.Present
  170. return this.configure(opts) as this
  171. }
  172. get past (): this {
  173. const opts: WordOptions = Object.assign({}, this.opt)
  174. opts.verbKind = VerbKind.Past
  175. return this.configure(opts) as this
  176. }
  177. get pastParticiple (): this {
  178. const opts: WordOptions = Object.assign({}, this.opt)
  179. opts.verbKind = VerbKind.PastParticiple
  180. return this.configure(opts) as this
  181. }
  182. get possessive (): this {
  183. const opts: WordOptions = Object.assign({}, this.opt)
  184. opts.possessive = true
  185. return this.configure(opts) as this
  186. }
  187. get objective (): this {
  188. const opts: WordOptions = Object.assign({}, this.opt)
  189. opts.objective = true
  190. return this.configure(opts) as this
  191. }
  192. }
  193. export class RandomWord extends Word {
  194. private history: { last: number }
  195. constructor (public choices: Array<Word>, opt: WordOptions = emptyConfig, history: { last: number } = { last: -1 }) {
  196. super(opt)
  197. this.history = history
  198. }
  199. configure (opts: WordOptions): Word {
  200. return new RandomWord(this.choices, opts, this.history)
  201. }
  202. toString (): string {
  203. let choice
  204. do {
  205. choice = Math.floor(Math.random() * this.choices.length)
  206. } while (choice === this.history.last)
  207. this.history.last = choice
  208. return this.choices[choice].configure(this.opt).toString()
  209. }
  210. }
  211. export class Noun extends Word {
  212. constructor (protected singularNoun: string, protected pluralNoun: string|null = null, protected possessiveNoun: string|null = null, protected options: WordOptions = emptyConfig) {
  213. super(options)
  214. }
  215. configure (opts: WordOptions): Word {
  216. return new Noun(this.singularNoun, this.pluralNoun, this.possessiveNoun, opts)
  217. }
  218. toString (): string {
  219. let result: string
  220. // TODO: plural possessive nouns?
  221. if (this.options.possessive) {
  222. if (this.possessiveNoun === null) {
  223. result = this.singularNoun + "'s"
  224. } else {
  225. result = this.possessiveNoun
  226. }
  227. } else if (this.options.plural) {
  228. if (this.pluralNoun === null) {
  229. result = this.singularNoun
  230. } else {
  231. result = (this.pluralNoun as string)
  232. }
  233. } else {
  234. result = this.singularNoun
  235. }
  236. if (!this.options.proper) {
  237. if (this.options.nounKind === NounKind.Nonspecific && this.options.count) {
  238. if (this.options.plural) {
  239. result = 'some ' + result
  240. } else {
  241. if (this.options.vowel === VowelSound.Default) {
  242. if ('aeiouAEIOU'.indexOf(result.slice(0, 1)) >= 0) {
  243. result = 'an ' + result
  244. } else {
  245. result = 'a ' + result
  246. }
  247. } else if (this.options.vowel === VowelSound.Vowel) {
  248. result = 'an ' + result
  249. } else if (this.options.vowel === VowelSound.NonVowel) {
  250. result = 'a ' + result
  251. }
  252. }
  253. } else if (this.options.nounKind === NounKind.Specific) {
  254. result = 'the ' + result
  255. }
  256. }
  257. if (this.options.allCaps) {
  258. result = result.toUpperCase()
  259. } else if (this.options.capital) {
  260. result = result.slice(0, 1).toUpperCase() + result.slice(1)
  261. }
  262. return result
  263. }
  264. conjugate (verb: Word): Word {
  265. if (this.opt.plural) {
  266. return verb.root
  267. } else {
  268. return verb.singular
  269. }
  270. }
  271. }
  272. export class ImproperNoun extends Noun {
  273. constructor (singularNoun: string, pluralNoun: string = singularNoun, possessiveNoun: string = singularNoun + "'s") {
  274. super(singularNoun, pluralNoun, null, { plural: false, allCaps: false, capital: false, proper: false, nounKind: NounKind.Specific, verbKind: VerbKind.Root, vowel: VowelSound.Default, count: true, possessive: false, objective: false })
  275. }
  276. }
  277. export class ProperNoun extends Noun {
  278. constructor (singularNoun: string) {
  279. super(singularNoun, null, null, { plural: false, allCaps: false, capital: false, proper: true, nounKind: NounKind.Specific, verbKind: VerbKind.Root, vowel: VowelSound.Default, count: true, possessive: false, objective: false })
  280. }
  281. }
  282. export class Adjective extends Word {
  283. constructor (private adjective: string, opt: WordOptions = emptyConfig) {
  284. super(opt)
  285. }
  286. configure (opts: WordOptions): Word {
  287. return new Adjective(this.adjective, opts)
  288. }
  289. // TODO caps et al.
  290. toString (): string {
  291. return this.adjective
  292. }
  293. }
  294. export class Verb extends Word {
  295. configure (opts: WordOptions): Word {
  296. return new Verb(
  297. this._root,
  298. this._singular,
  299. this._present,
  300. this._past,
  301. this._pastParticiple,
  302. opts
  303. )
  304. }
  305. toString (): string {
  306. let choice: string
  307. switch (this.opt.verbKind) {
  308. case VerbKind.Root: choice = this._root; break
  309. case VerbKind.Singular: choice = this._singular; break
  310. case VerbKind.Present: choice = this._present; break
  311. case VerbKind.Past: choice = this._past; break
  312. case VerbKind.PastParticiple: choice = this._pastParticiple; break
  313. }
  314. if (this.opt.allCaps) {
  315. choice = choice.toUpperCase()
  316. } else if (this.opt.capital) {
  317. choice = choice.slice(0, 1).toUpperCase() + choice.slice(1)
  318. }
  319. return choice
  320. }
  321. constructor (private _root: string, private _singular: string = _root + "s", private _present: string = _root + "ing", private _past: string = _root + "ed", private _pastParticiple: string = _past, public opt: WordOptions = emptyConfig) {
  322. super(opt)
  323. }
  324. }
  325. interface PronounDict {
  326. subjective: string;
  327. objective: string;
  328. possessive: string;
  329. reflexive: string;
  330. }
  331. export class Pronoun implements Pluralizable {
  332. constructor (private pronouns: PronounDict, private capitalize: boolean = false, public isPlural: boolean = false) {
  333. }
  334. get capital (): Pronoun {
  335. return new Pronoun(this.pronouns, true)
  336. }
  337. get subjective (): string {
  338. return this.caps(this.pronouns.subjective)
  339. }
  340. get objective (): string {
  341. return this.caps(this.pronouns.objective)
  342. }
  343. get possessive (): string {
  344. return this.caps(this.pronouns.possessive)
  345. }
  346. get reflexive (): string {
  347. return this.caps(this.pronouns.reflexive)
  348. }
  349. private caps (input: string): string {
  350. if (this.capitalize) {
  351. return input.slice(0, 1).toUpperCase() + input.slice(1)
  352. } else {
  353. return input
  354. }
  355. }
  356. }
  357. export class PronounAsNoun extends Noun {
  358. constructor (private pronouns: Pronoun, opt: WordOptions = emptyConfig) {
  359. super(pronouns.subjective, pronouns.subjective, pronouns.possessive, opt)
  360. this.options.nounKind = NounKind.All
  361. this.options.plural = true
  362. }
  363. configure (opts: WordOptions): Word {
  364. return new PronounAsNoun(this.pronouns, opts)
  365. }
  366. toString (): string {
  367. if (this.options.objective) {
  368. return new Noun(this.pronouns.objective, this.pronouns.objective, this.pronouns.possessive, this.options).toString()
  369. } else {
  370. return super.toString()
  371. }
  372. }
  373. }
  374. export const MalePronouns = new Pronoun({
  375. subjective: 'he',
  376. objective: 'him',
  377. possessive: 'his',
  378. reflexive: 'himself'
  379. })
  380. export const FemalePronouns = new Pronoun({
  381. subjective: 'she',
  382. objective: 'her',
  383. possessive: 'her',
  384. reflexive: 'herself'
  385. })
  386. export const TheyPronouns = new Pronoun({
  387. subjective: 'they',
  388. objective: 'them',
  389. possessive: 'their',
  390. reflexive: 'themself'
  391. }, false, true)
  392. export const TheyPluralPronouns = new Pronoun({
  393. subjective: 'they',
  394. objective: 'them',
  395. possessive: 'their',
  396. reflexive: 'themselves'
  397. }, false, true)
  398. export const ObjectPronouns = new Pronoun({
  399. subjective: 'it',
  400. objective: 'it',
  401. possessive: 'its',
  402. reflexive: 'itself'
  403. })
  404. export const SecondPersonPronouns = new Pronoun({
  405. subjective: 'you',
  406. objective: 'you',
  407. possessive: 'your',
  408. reflexive: 'yourself'
  409. })
  410. export const FirstPersonPronouns = new Pronoun({
  411. subjective: 'I',
  412. objective: 'me',
  413. possessive: 'my',
  414. reflexive: 'myself'
  415. })