import { Embed, MessageCreateOptions, MessagePayload, MessagePayloadOption } from "discord.js" export interface MessageSink { SendMessage(v:MessageCreateOptions):Promise } export const ConsoleMessageSink: MessageSink = { async SendMessage(v) { console.log(v) }, } export interface RandomSource { Range(start:number, stop:number):number } export const DefaultRandom:RandomSource = { Range(start, stop) { const ans = (stop - start) * Math.random() + start return ans } } export interface ActionFactory { next(game: Game): Action } // an action is in charge of the entire state transition export interface Action { Before?(game:Game):MessageCreateOptions[] Play?(game:Game):MessageCreateOptions[] After?(game:Game):MessageCreateOptions[] } export const PlayActions = async (game:Game, actions:Action[]) => { for(let i = 0; i < actions.length; i++) { const a = actions[i]; [a.Before,a.Play,a.After].forEach(async (x)=>{ if(x){ const msgs = x(game) msgs.forEach(async (msg)=>{ await game.sink.SendMessage(msg).catch(console.log) }) } }); } } // track game state export class Game { // players in the game players: {[index: string]:Player} rng: RandomSource sink:MessageSink constructor() { this.players = {} this.rng = DefaultRandom this.sink = ConsoleMessageSink } } // player class tracks a players stats through out the game export class Player { // display name of character name: string // if health reaches 0 ur dead health: number // chance you are selected for combat visibility: number // chance you will win your next combat power: number constructor(name:string) { this.health = 100 this.visibility = 50 this.power = 50 this.name = name } // bool is whether or not player is dead after damage damage(v:number):boolean{ this.health = this.health - v if(this.health <= 0) { this.health = 0 return true } return false } alive() { return this.health > 0 } }