@jeremyckahn/farmhand
Version:
A farming game
86 lines (70 loc) • 2.21 kB
text/typescript
import { random } from '../../common/utils.js'
import { doesPlotContainCrop } from '../../utils/index.js'
import { CROW_CHANCE, MAX_CROWS } from '../../constants.js'
import { CROWS_DESTROYED } from '../../templates.js'
import { randomNumberService } from '../../common/services/randomNumber.js'
import { modifyFieldPlotAt } from './modifyFieldPlotAt.js'
import { fieldHasScarecrow } from './helpers.js'
/**
* @param {farmhand.state} state
* @callback {forEachPlotCallback} callback
*/
export function forEachPlot(state, callback) {
state.field.forEach((row, y) =>
row.forEach((plotContents, x) => callback(plotContents, x, y))
)
}
/**
* @callback forEachPlotCallback
* @param {object} plotContents - the contents of the plot
* @param {number} x - the X coordinate for the plot
* @param {number} y - the Y coordinate for the plot
*/
/**
* @param {farmhand.state} state
* @returns {farmhand.state}
*/
export const applyCrows = state => {
const { field, purchasedField } = state
if (
fieldHasScarecrow(field) ||
randomNumberService.isRandomNumberLessThan(1 - CROW_CHANCE)
) {
return state
}
const newDayNotifications = [...state.newDayNotifications]
let notificationMessages = []
const plotsWithCrops = []
forEachPlot(state, (_plotContents, x, y) => {
if (doesPlotContainCrop(state.field[y][x])) {
// @ts-expect-error
plotsWithCrops.push({ x, y })
}
})
const numCrows = Math.min(
plotsWithCrops.length,
Math.floor(random() * (purchasedField + 1) * MAX_CROWS)
)
let numCropsDestroyed = 0
for (let i = 0; i < numCrows; i++) {
const attackPlotId = Math.floor(random() * plotsWithCrops.length)
const target = plotsWithCrops.splice(attackPlotId, 1)[0]
// @ts-expect-error
state = modifyFieldPlotAt(state, target.x, target.y, () => null)
numCropsDestroyed += 1
}
if (numCropsDestroyed > 0) {
// @ts-expect-error
notificationMessages.push(CROWS_DESTROYED('', numCropsDestroyed))
}
if (notificationMessages.length) {
newDayNotifications.push({
message: notificationMessages.join('\n\n'),
severity: 'error',
})
}
return {
...state,
newDayNotifications,
}
}