From b67d4eb5d08cfa456f106fbd4e137213de8b2ae4 Mon Sep 17 00:00:00 2001 From: Fen Dweller Date: Tue, 4 Aug 2020 22:50:43 -0400 Subject: [PATCH] Add an AI system, with only random AI for now --- src/components/Combat.vue | 9 +++++++++ src/components/Statblock.vue | 7 ++++++- src/game/ai.ts | 30 ++++++++++++++++++++++++++++++ src/game/creature.ts | 2 ++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/game/ai.ts diff --git a/src/components/Combat.vue b/src/components/Combat.vue index 30e0552..3878639 100644 --- a/src/components/Combat.vue +++ b/src/components/Combat.vue @@ -57,6 +57,7 @@ import { LogEntry, LogLine } from '@/game/interface' import Statblock from './Statblock.vue' import ActionButton from './ActionButton.vue' import { Side, Encounter } from '@/game/combat' +import { NoAI } from '../game/ai' @Component( { @@ -182,6 +183,14 @@ export default class Combat extends Vue { this.scrollParentTo(target) } }) + + if (!(this.encounter.currentMove.ai instanceof NoAI)) { + if (this.encounter.currentMove.side === Side.Heroes) { + this.executedLeft(this.encounter.currentMove.ai.decide(this.encounter.currentMove, this.encounter)) + } else { + this.executedRight(this.encounter.currentMove.ai.decide(this.encounter.currentMove, this.encounter)) + } + } } } diff --git a/src/components/Statblock.vue b/src/components/Statblock.vue index f7dd655..196586d 100644 --- a/src/components/Statblock.vue +++ b/src/components/Statblock.vue @@ -60,6 +60,9 @@ + @@ -68,6 +71,7 @@ import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' import { Creature } from '@/game/creature' import { POV } from '@/game/language' +import { NoAI, RandomAI } from '@/game/ai' import { Stats, Stat, StatIcons, StatDescs, Vigor, VigorIcons, VigorDescs, VoreStatDescs, VoreStatIcons, VisibleStatus } from '@/game/combat' import ContainerView from './ContainerView.vue' import tippy, { delegate, createSingleton } from 'tippy.js' @@ -79,7 +83,8 @@ import 'tippy.js/dist/tippy.css' }, data () { return { - POV: POV + POV: POV, + ais: [NoAI, RandomAI] } }, methods: { diff --git a/src/game/ai.ts b/src/game/ai.ts new file mode 100644 index 0000000..64eef09 --- /dev/null +++ b/src/game/ai.ts @@ -0,0 +1,30 @@ +import { Creature } from './creature' +import { Encounter } from './combat' +import { LogEntry } from './interface' + +export interface AI { + name: string; + decide (actor: Creature, encounter: Encounter): LogEntry; +} + +export class NoAI implements AI { + name = "No AI" + decide (actor: Creature, encounter: Encounter): LogEntry { + throw new Error("This AI cannot be used.") + } +} + +/** + * The RandomAI is **COMPLETELY** random. Good luck. + */ +export class RandomAI implements AI { + name = "Random AI" + decide (actor: Creature, encounter: Encounter): LogEntry { + const actions = encounter.combatants.filter(enemy => enemy !== actor).flatMap(enemy => actor.validActions(enemy).map(action => ({ + target: enemy, + action: action + }))) + const chosen = actions[Math.floor(Math.random() * actions.length)] + return chosen.action.execute(actor, chosen.target) + } +} diff --git a/src/game/creature.ts b/src/game/creature.ts index 6458a8a..7c5db97 100644 --- a/src/game/creature.ts +++ b/src/game/creature.ts @@ -4,6 +4,7 @@ import { LogEntry, LogLines } from './interface' import { Vore, VoreContainer, VoreType } from './vore' import { Item, EquipmentSlot, Equipment } from './items' import { PassAction } from './combat/actions' +import { AI, NoAI } from './ai' export class Creature extends Vore implements Combatant { actions: Array = []; @@ -16,6 +17,7 @@ export class Creature extends Vore implements Combatant { side: Side; title = "Lv. 1 Creature"; equipment: Map = new Map() + ai: AI = new NoAI() constructor (name: Noun, kind: Noun, pronouns: Pronoun, stats: Stats, preyPrefs: Set, predPrefs: Set, mass: number) { super(name, kind, pronouns, stats, preyPrefs, predPrefs, mass)