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.
 
 
temptress-bot/src/game/gameState.ts

274 lines
12 KiB

import { RenderableText } from '../util/renderableText'
import { DiceCombo, DieResult, DieType } from './dieState'
export interface AIWeights {
// How much this AI likes to choose actions that increase the damage bonus
// damageBonusWeight is static and does not change
readonly damageBonusWeight: number
// How much this AI likes to choose actions that increase the requirement of stop dice in a turn
// stopWeight is multiplied by the number of stop dice both players can gain
readonly stopWeight: number
// How much this AI likes to choose actions that decrease the limit of fail dice in a turn
// failWeight is multiplied by the number of fail dice both players can lose
readonly failWeight: number
// How much this AI likes to choose actions that are finishers for the opponent.
// finisherWeight is multiplied by the percentage of max damage the opponent has taken
readonly finisherWeight: number
// How much this AI dislikes choosing actions that are finishers for itself.
// selfFinisherWeight is multiplied by the percentage of max damage the AI has taken
// If this would reduce the weight of an action to 0 or less, that action has a weight of 0 and will only be
// selected randomly if all actions have a weight of 0.
readonly selfFinisherWeight: number
// Approximate lead that the AI would prefer to have before ending its turn when it has the option to keep pressing
readonly desiredLead: number
// Approximate damage behind the previous turn total that the AI is willing to take to play it safe,
// assuming doing so wouldn't be fatal (not enough damage to kill or not a finisher)
// When there's one fail die left, the AI will prioritize stopping as long as the damage it will be taking is within
// a randomly selected 50-150% of this value
readonly allowedDamage: number
// Integer from 0-100:
// 100 means AI keeps rolling until it has one fail die left before trying to stop
// 0 means AI always stops as soon as it has at least the desired lead
// Anything in between is the percentage chance of continuing, which is rolled once for each fail die remaining
// besides the last. If the chance fails once, then the AI uses that turn as if it were trying to stop.
// This roll is only performed when the AI already has the lead, is ahead by a value within an acceptable distance
// of the desired lead, and the AI has at least two additional fail dice remaining before failing.
readonly recklessnessPercent: number
// Integer from 0-100:
// 0 means AI never holds stops until it's ready to end its turn
// 100 means AI always holds stops it sees
// Anything in between is the percentage chance of locking a new stop die that appears, rolled once per stop die
// needed to end the turn per die that comes up stop. If the chance succeeds once, then the AI holds that stop die.
// This roll is only performed when the AI is not already stopping its turn.
readonly holdStopsPercent: number
}
export interface PlayerStartingState extends Pick<PlayerState, 'damageMax' | 'stopCount' | 'failCount'> {
// Percentage of damage that this player starts off dealing
readonly damageBonusBase: number
// Percentage of damage this player's damage increases by with each damage bonus earned
readonly damageBonusIncrement: number
// Maximum number of damage bonuses that this player can have, or 0 if there's no upper limit
readonly maxDamageBonuses: number
// Minimum number of dice required to stop
readonly minStopCount: number
// Minimum number of dice required to fail
readonly minFailCount: number
// Maximum number of dice required to stop
readonly maxStopCount: number
// Maximum number of dice required to fail
readonly maxFailCount: number
// Base amount of damage that must be dealt to recover, or 0 if recovery is forbidden
// Defaults to 1000
readonly recoverBase?: number
// Amount by which the amount needed to recover increases each time recovery is earned
// Defaults to 1000
readonly recoverIncrement?: number
// Percentage of current damage taken that is removed when recovery is earned
// Defaults to 50
readonly recoverPercent?: number
// Instructions for if this player is an AI player. If not specified, this player cannot be played by the AI.
readonly aiData?: AIWeights
}
export interface Difficulty {
// Name of the difficulty in the select menu
readonly name: string
// Short description of the difficulty in the select menu
readonly shortDescription?: string
// Description of the difficulty when selected
readonly description?: string
// The player who should start in this difficulty; defaults to random
readonly startingPlayer?: PlayerSide | null
// Starting values for each character
readonly stats: {
readonly [x in PlayerSide]: PlayerStartingState
}
}
export interface PlayerText {
// Possible random names for this player
readonly names?: readonly string[]
// Text given at the start of the game from this side
readonly startText?: TriggeredText
// Text given at the end of the game from this side
readonly endText?: TriggeredText
// The name of the damage value for this player
readonly damage: string
// The name of the player's damage limit, defaulting to "Max " + damage
readonly maxDamage?: string
// The name of this player's stop count requirement
readonly stopCount: string
// The name of this player's fail count limit
readonly failCount: string
// The name of this player's incoming damage bonus
readonly damageBonus: string
}
export interface GameTheme {
readonly name: string
readonly shortDescription: string
readonly description: string
readonly diceCombos: readonly DiceCombo[]
readonly actions: readonly GameAction[]
readonly difficulties: readonly Difficulty[]
readonly commonText?: { readonly [key: string]: RenderableText | undefined }
readonly narratorName: string
readonly text: {
readonly [x in PlayerSide]: PlayerText
}
}
export interface TriggeredText {
// The dialogues that can be triggered for this action.
// Dialogue can be disabled for characters run by human players.
readonly dialogue?: RenderableText
// The descriptions that can be triggered for this action.
// Descriptions are always displayed, regardless of player.
readonly description?: RenderableText
}
export interface ActionText {
// Name of the action in the select list for this side
readonly name: string
// Description of the action in the select list for this side
readonly shortDescription: string
// Description of the action when selected for this side
readonly description: string
// Text given when this side selects this action.
readonly selectAction?: TriggeredText
// Text given when the other side selects this action.
readonly opponentSelectsAction?: TriggeredText
// Text given when this side finishes a turn in this action without failing.
readonly passTurn?: TriggeredText
// Text given when this side receives a turn from the opponent in this action.
readonly opponentPassesTurn?: TriggeredText
// Text given when this side rerolls the dice for this action.
readonly reroll?: TriggeredText
// Text given when the opposing side rerolls the dice for this action.
readonly opponentRerolls?: TriggeredText
// Text given the first time each turn this side is one fail die away from failing
readonly aboutToFailTurn?: TriggeredText
// Text given the first time each turn the opposing side is one fail die away from failing
readonly opponentAboutToFailTurn?: TriggeredText
// Text given when this side fails the turn by accumulating fail dice
readonly failTurn?: TriggeredText
// Text given when the opposing side fails the turn by accumulating fail dice
readonly opponentFailsTurn?: TriggeredText
// Text given when this side fails the turn by stopping without enough points
readonly abandonTurn?: TriggeredText
// Text given when the opposing side fails the turn by stopping without enough points
readonly opponentAbandonsTurn?: TriggeredText
// Text given when this side is defeated by being pushed over their max damage with this action
readonly defeated?: TriggeredText
// Text given when this side defeats the opponent by pushing them over their max damage with this action
readonly opponentDefeated?: TriggeredText
}
export interface GameAction {
// The text from each player's perspective.
readonly text: {
readonly [x in PlayerSide]: ActionText
}
// The dice that are rolled for this action
readonly dice: readonly DieType[]
// True if the loser of this action increases the amount of damage they take
readonly givesDamageBonus: boolean
// True if the loser of this action has to get an additional stop die to end their turn
readonly givesStopCount: boolean
// True if the loser of this action has one fewer buffer for fail dice
readonly givesFailCount: boolean
// Whether this action can end the game in a loss for the top
readonly canFinishTop: boolean
// Whether this action can end the game in a loss for the bottom
readonly canFinishBottom: boolean
}
export enum PlayerSide {
TOP = 'top',
BOTTOM = 'bottom',
}
export interface PlayerState {
// This player's name
readonly name: string
// Amount of damage taken so far this battle
readonly damage: number
// Max damage that can be taken, 0 for endless mode
readonly damageMax: number
// The total damage taken across this battle
readonly damageTotal: number
// Number of stop dice required to end a turn with stops
readonly stopCount: number
// Number of fail dice required to fail a turn by accumulating too many fail dice
readonly failCount: number
// Incoming damage for this side is multiplied by 100% + 10% * damageBonuses
readonly damageBonuses: number
// Amount that Total Damage must reach to reduce this player's damage by 50% of its current value
// 0 means no recovery is allowed for this player
readonly nextRecoverAt: number
// Number of times damage was recovered so far this game (adds 1000 + 100 * timesRecovered to nextRecoverAt)
readonly timesRecovered: number
}
export enum GamePhase {
ROUND_START = 'round_start',
TURN_START = 'turn_start',
TURN_ROLLED = 'turn_rolled',
TURN_FAILED = 'turn_failed',
ABORTED = 'aborted',
VICTORY = 'victory',
}
export interface GameState {
// The theme that defines this game for the players.
readonly theme: GameTheme
// The difficulty selected for this game.
readonly difficulty: Difficulty
// The current phase of the game.
readonly gamePhase: GamePhase
// The owner of the current phase, or null if the phase is Aborted
readonly phaseOwner: PlayerSide | null
// The state of each player in the game.
readonly players: {
readonly [x in PlayerSide]: PlayerState
}
// The action chosen for this round. Defaults to the first action in the list.
readonly action: GameAction
// The total for the previous turn, or 0 if the current player is taking the first turn
// If the current player fails when the turn total is 0, they take the penalty and pass the initiative without taking damage.
// This can still end the game if the current action is capable of ending the game for this player and
// this player has more damage than their maximum.
readonly lastTurnTotal: number
// The dice available for the current turn
readonly lastRoll: readonly DieResult[]
// The total value of the selected dice, or 0 if the selected dice cannot be scored.
readonly selectedDiceValue: number
// Whether the selected dice are sufficient to end the turn.
readonly selectedDiceEndTurn: boolean
// The number of dice that have come up failures so far in the current turn, including the lastRoll.
readonly countedFails: number
// The total of the dice that have been scored so far this turn
readonly currentTurnTotal: number
}