Skip to content

Commit

Permalink
fix: win prioritized over tie card (#5); cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
tomchen committed Apr 27, 2021
1 parent ef9e81d commit df692ce
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 22 deletions.
15 changes: 6 additions & 9 deletions src/ai/coefs.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
const coefs = {
export const coefs = {
bricks: 1,
gems: 1.28,
recruits: 1.05,
brickProd: 18, // = bricks * 18
gemProd: 23.04, // = gems * 18
recruitProd: 18.9, // = recruits * 18
prod: 18,
tower: 3.67,
wall: 2.02,
playagain: 46,
drawDiscardPlayagain: 27.6,
undiscardable: 2.03,
useDiscardRatio: 2.18,
loseDeduction: 999,
enemy: 1.08,
randomDice: 100,
tieBonus: 999,
losePenalty: 999,
attack: 1.08,
// randomDice: 100,
}

export default coefs
42 changes: 30 additions & 12 deletions src/ai/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,21 @@ import cards from '../data/cards'
import { AiCardListItemType, AiInstructionType } from '../types/ai'
import { PersonStatusType, StatusType, WinSettingsType } from '../types/state'
import { entries, fromEntries } from '../utils/typeHelpers'
import coefs from './coefs'
import { coefs } from './coefs'

const statusCoefs = (() => {
const { bricks, gems, recruits, prod, tower, wall } = coefs
return {
bricks,
gems,
recruits,
brickProd: bricks * prod,
gemProd: gems * prod,
recruitProd: recruits * prod,
tower,
wall,
}
})()

// cardList is a list of all opponent card state objects,
// each card state object includes two additional properties: canUse and canDiscard
Expand All @@ -13,20 +27,22 @@ export const aiDecision = (
status: StatusType,
winSettings: WinSettingsType,
): AiInstructionType | null => {
// cardList is not frozen
// you can edit the elements inside cardList

const { player: pBefore, opponent: oBefore } = status
// p and o are readonly

for (const card of cardList) {
card.score = 0

const { index, n, canuse } = card
const dataCard = cards[n]
const { type, cost, special, effect } = dataCard
const { winTower, winResource } = winSettings
const pAfter: PersonStatusType = { ...pBefore }
const oAfter: PersonStatusType = { ...oBefore }
effect(oAfter, pAfter)

/**
* win immediately (but not tie)
*/
Expand All @@ -48,12 +64,7 @@ export const aiDecision = (
return { index, use: true }
}

/**
* tie immediately
*/
if (canuse && winImm && loseImm) {
return { index, use: true }
}
// =============================

const oDiff = fromEntries<PersonStatusType>(
entries(oBefore).map(([key, value]) => [key, oAfter[key] - value]),
Expand All @@ -65,12 +76,15 @@ export const aiDecision = (
oDiff[resNames[type]] -= cost

const oScore = allStatusNames
.map((statusName) => oDiff[statusName] * coefs[statusName])
.map((statusName) => oDiff[statusName] * statusCoefs[statusName])
.reduce((a, b) => a + b, 0)

// pScore here is positive
const pScore = allStatusNames
.map((statusName) => pDiff[statusName] * coefs[statusName] * coefs.enemy)
.map(
(statusName) =>
pDiff[statusName] * statusCoefs[statusName] * coefs.attack,
)
.reduce((a, b) => a + b, 0)

card.score += oScore - pScore
Expand All @@ -87,8 +101,12 @@ export const aiDecision = (
card.score += coefs.undiscardable
}

if (loseImm) {
card.score -= coefs.loseDeduction
if (winImm && loseImm) {
card.score += coefs.tieBonus
}

if (!winImm && loseImm) {
card.score -= coefs.losePenalty
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/constants/devSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const noDevLog = isProd || _noDevLog

// if useAi is true, even when opponent cards are shown, they are unclickable

export const aiExtraDelay = 5000
export const aiExtraDelay = 4000

// can discard "undiscardable" cards during the discard mode triggered by "draw discard playagain" cards
export const canDiscardUndiscardableWhenDDP = false
Expand Down

0 comments on commit df692ce

Please sign in to comment.