|
- import { CombatTest, Stat, Vigor } from '../combat'
- import { Creature } from '../entity'
- import { LogEntry, LogLines, PropElem, LogLine } from '../interface'
-
- function logistic (x0: number, L: number, k: number): (x: number) => number {
- return (x: number) => {
- return L / (1 + Math.exp(-k * (x - x0)))
- }
- }
-
- abstract class RandomTest implements CombatTest {
- test (user: Creature, target: Creature): boolean {
- return Math.random() < this.odds(user, target)
- }
-
- abstract odds(user: Creature, target: Creature): number
- abstract explain(user: Creature, target: Creature): LogEntry
- }
-
- export class StatVigorTest extends RandomTest {
- private f: (x: number) => number
-
- constructor (public readonly stat: Stat, k = 0.1) {
- super()
- this.f = logistic(0, 1, k)
- }
-
- odds (user: Creature, target: Creature): number {
- let userPercent = 1
- let targetPercent = 1
-
- Object.keys(Vigor).forEach(key => {
- userPercent *= user.vigors[key as Vigor] / user.maxVigors[key as Vigor]
- targetPercent *= target.vigors[key as Vigor] / target.maxVigors[key as Vigor]
-
- userPercent = Math.max(0, userPercent)
- targetPercent = Math.max(0, targetPercent)
- })
-
- if (userPercent === 0) {
- targetPercent *= 4
- }
-
- if (targetPercent === 0) {
- userPercent *= 4
- }
-
- console.log(userPercent, targetPercent, this.f(user.stats[this.stat] * userPercent - target.stats[this.stat] * targetPercent))
- return this.f(user.stats[this.stat] * userPercent - target.stats[this.stat] * targetPercent)
- }
-
- explain (user: Creature, target: Creature): LogEntry {
- let result: LogEntry
-
- let userPercent = 1
- let targetPercent = 1
-
- Object.keys(Vigor).forEach(key => {
- userPercent *= user.vigors[key as Vigor] / user.maxVigors[key as Vigor]
- targetPercent *= target.vigors[key as Vigor] / target.maxVigors[key as Vigor]
-
- userPercent = Math.max(0, userPercent)
- targetPercent = Math.max(0, targetPercent)
- })
-
- if (userPercent === 0) {
- targetPercent *= 4
- }
-
- if (targetPercent === 0) {
- userPercent *= 4
- }
- const userMod = user.stats[this.stat] * userPercent
- const targetMod = target.stats[this.stat] * targetPercent
- const delta = (userMod - targetMod)
-
- if (delta === 0) {
- result = new LogLine('You and the target have the same effective', new PropElem(this.stat), '.')
- } else if (delta < 0) {
- result = new LogLine('You effectively have ', new PropElem(this.stat, -delta), ' less than your foe.')
- } else {
- result = new LogLine('You effectively have ', new PropElem(this.stat, delta), ' more than you foe.')
- }
-
- result = new LogLine(result, 'Your odds of success are ' + (100 * this.odds(user, target)).toFixed(1) + '%')
-
- return result
- }
- }
-
- export class StatTest extends RandomTest {
- private f: (x: number) => number
-
- constructor (public readonly stat: Stat, k = 0.1) {
- super()
- this.f = logistic(0, 1, k)
- }
-
- odds (user: Creature, target: Creature): number {
- return this.f(user.stats[this.stat] - target.stats[this.stat])
- }
-
- explain (user: Creature, target: Creature): LogEntry {
- const delta: number = user.stats[this.stat] - target.stats[this.stat]
- let result: LogEntry
-
- if (delta === 0) {
- result = new LogLine('You and the target have the same ', new PropElem(this.stat), '.')
- } else if (delta < 0) {
- result = new LogLine('You have ', new PropElem(this.stat, -delta), ' less than your foe.')
- } else {
- result = new LogLine('You have ', new PropElem(this.stat, delta), ' more than you foe.')
- }
-
- result = new LogLine(result, 'Your odds of success are ' + (100 * this.odds(user, target)).toFixed(1) + '%')
-
- return result
- }
- }
-
- export class ChanceTest extends RandomTest {
- constructor (public readonly chance: number) {
- super()
- }
-
- odds (user: Creature, target: Creature): number {
- return this.chance
- }
-
- explain (user: Creature, target: Creature): LogEntry {
- return new LogLine('You have a flat ' + (100 * this.chance) + '% chance.')
- }
- }
|