Browse Source

Add an AI system, with only random AI for now

master
Fen Dweller 5 years ago
parent
commit
b67d4eb5d0
4 changed files with 47 additions and 1 deletions
  1. +9
    -0
      src/components/Combat.vue
  2. +6
    -1
      src/components/Statblock.vue
  3. +30
    -0
      src/game/ai.ts
  4. +2
    -0
      src/game/creature.ts

+ 9
- 0
src/components/Combat.vue View File

@@ -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))
}
}
}
}



+ 6
- 1
src/components/Statblock.vue View File

@@ -60,6 +60,9 @@
<button v-if="subject.perspective === POV.Third" @click.stop="subject.perspective = POV.Second">Second-person</button>
<button v-if="subject.perspective === POV.First" @click.stop="subject.perspective = POV.Third">Third-person</button>
<button v-if="subject.perspective === POV.Second" @click.stop="subject.perspective = POV.First">First-person</button>
<select @change="subject.ai = new ais[$event.target.selectedIndex]()">
<option v-for="(ai, index) in ais" :key="'ai-' + index">{{ ai.name }}</option>
</select>
</div>
</div>
</template>
@@ -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: {


+ 30
- 0
src/game/ai.ts View File

@@ -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)
}
}

+ 2
- 0
src/game/creature.ts View File

@@ -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<Action> = [];
@@ -16,6 +17,7 @@ export class Creature extends Vore implements Combatant {
side: Side;
title = "Lv. 1 Creature";
equipment: Map<EquipmentSlot, Equipment> = new Map()
ai: AI = new NoAI()

constructor (name: Noun, kind: Noun, pronouns: Pronoun, stats: Stats, preyPrefs: Set<VoreType>, predPrefs: Set<VoreType>, mass: number) {
super(name, kind, pronouns, stats, preyPrefs, predPrefs, mass)


Loading…
Cancel
Save