Feast 2.0!
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 

134 lines
4.0 KiB

  1. import { CombatTest, Stat, Vigor } from '../combat'
  2. import { Creature } from '../entity'
  3. import { LogEntry, LogLines, PropElem, LogLine } from '../interface'
  4. function logistic (x0: number, L: number, k: number): (x: number) => number {
  5. return (x: number) => {
  6. return L / (1 + Math.exp(-k * (x - x0)))
  7. }
  8. }
  9. abstract class RandomTest implements CombatTest {
  10. test (user: Creature, target: Creature): boolean {
  11. return Math.random() < this.odds(user, target)
  12. }
  13. abstract odds(user: Creature, target: Creature): number
  14. abstract explain(user: Creature, target: Creature): LogEntry
  15. }
  16. export class StatVigorTest extends RandomTest {
  17. private f: (x: number) => number
  18. constructor (public readonly stat: Stat, k = 0.1) {
  19. super()
  20. this.f = logistic(0, 1, k)
  21. }
  22. odds (user: Creature, target: Creature): number {
  23. let userPercent = 1
  24. let targetPercent = 1
  25. Object.keys(Vigor).forEach(key => {
  26. userPercent *= user.vigors[key as Vigor] / user.maxVigors[key as Vigor]
  27. targetPercent *= target.vigors[key as Vigor] / target.maxVigors[key as Vigor]
  28. userPercent = Math.max(0, userPercent)
  29. targetPercent = Math.max(0, targetPercent)
  30. })
  31. if (userPercent === 0) {
  32. targetPercent *= 4
  33. }
  34. if (targetPercent === 0) {
  35. userPercent *= 4
  36. }
  37. console.log(userPercent, targetPercent, this.f(user.stats[this.stat] * userPercent - target.stats[this.stat] * targetPercent))
  38. return this.f(user.stats[this.stat] * userPercent - target.stats[this.stat] * targetPercent)
  39. }
  40. explain (user: Creature, target: Creature): LogEntry {
  41. let result: LogEntry
  42. let userPercent = 1
  43. let targetPercent = 1
  44. Object.keys(Vigor).forEach(key => {
  45. userPercent *= user.vigors[key as Vigor] / user.maxVigors[key as Vigor]
  46. targetPercent *= target.vigors[key as Vigor] / target.maxVigors[key as Vigor]
  47. userPercent = Math.max(0, userPercent)
  48. targetPercent = Math.max(0, targetPercent)
  49. })
  50. if (userPercent === 0) {
  51. targetPercent *= 4
  52. }
  53. if (targetPercent === 0) {
  54. userPercent *= 4
  55. }
  56. const userMod = user.stats[this.stat] * userPercent
  57. const targetMod = target.stats[this.stat] * targetPercent
  58. const delta = (userMod - targetMod)
  59. if (delta === 0) {
  60. result = new LogLine('You and the target have the same effective', new PropElem(this.stat), '.')
  61. } else if (delta < 0) {
  62. result = new LogLine('You effectively have ', new PropElem(this.stat, -delta), ' less than your foe.')
  63. } else {
  64. result = new LogLine('You effectively have ', new PropElem(this.stat, delta), ' more than you foe.')
  65. }
  66. result = new LogLine(result, 'Your odds of success are ' + (100 * this.odds(user, target)).toFixed(1) + '%')
  67. return result
  68. }
  69. }
  70. export class StatTest extends RandomTest {
  71. private f: (x: number) => number
  72. constructor (public readonly stat: Stat, k = 0.1) {
  73. super()
  74. this.f = logistic(0, 1, k)
  75. }
  76. odds (user: Creature, target: Creature): number {
  77. return this.f(user.stats[this.stat] - target.stats[this.stat])
  78. }
  79. explain (user: Creature, target: Creature): LogEntry {
  80. const delta: number = user.stats[this.stat] - target.stats[this.stat]
  81. let result: LogEntry
  82. if (delta === 0) {
  83. result = new LogLine('You and the target have the same ', new PropElem(this.stat), '.')
  84. } else if (delta < 0) {
  85. result = new LogLine('You have ', new PropElem(this.stat, -delta), ' less than your foe.')
  86. } else {
  87. result = new LogLine('You have ', new PropElem(this.stat, delta), ' more than you foe.')
  88. }
  89. result = new LogLine(result, 'Your odds of success are ' + (100 * this.odds(user, target)).toFixed(1) + '%')
  90. return result
  91. }
  92. }
  93. export class ChanceTest extends RandomTest {
  94. constructor (public readonly chance: number) {
  95. super()
  96. }
  97. odds (user: Creature, target: Creature): number {
  98. return this.chance
  99. }
  100. explain (user: Creature, target: Creature): LogEntry {
  101. return new LogLine('You have a flat ' + (100 * this.chance) + '% chance.')
  102. }
  103. }