Skip to content

Commit

Permalink
player terrain
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanseifert committed Dec 6, 2024
1 parent 95a9d13 commit 209a4a5
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 20 deletions.
58 changes: 45 additions & 13 deletions src/components/setup/AutomaSetup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,38 @@
<ol>
<li v-if="isTwoPlayerGame" v-html="t('setupGameAutoma.noTwoPlayerSpecialRules')"></li>
<li v-html="t('setupGameAutoma.palaceTiles', {count:palaceTileCount})"></li>
<li v-if="isTwoHumanPlayers" v-html="t('setupGameAutoma.factionSelectionTwoHumanPlayer')"></li>
<li v-if="isTwoHumanPlayers">
<span v-html="t('setupGameAutoma.factionSelectionTwoHumanPlayer')"></span>
<ul>
<li v-for="(player,i) in playerCount" :key="player">
<i>{{t(`setup.players.player`, {player})}}</i>:
<div class="terrainSelection">
<div class="form-check form-check-inline" v-for="terrain in terrains" :key="terrain">
<label class="form-check-label">
<input class="form-check-input" type="radio" :name="`playerTerrain${i}`" v-model="playerTerrain[i]" :value="terrain">
<AppIcon type="terrain" :name="terrain" extension="webp" class="terrainIcon"/>
</label>
</div>
</div>
</li>
</ul>
</li>
<li v-else>
<span v-html="t('setupGameAutoma.factionSelection.title')"></span>
<ol type="a">
<li v-html="t('setupGameAutoma.factionSelection.planningDisplayCards')"></li>
<li v-html="t('setupGameAutoma.factionSelection.factionTiles')"></li>
<li v-html="t('setupGameAutoma.factionSelection.chooseSet')"></li>
<li>
<span v-html="t('setupGameAutoma.factionSelection.chooseSet')"></span>
<div class="terrainSelection">
<div class="form-check form-check-inline" v-for="terrain in terrains" :key="terrain">
<label class="form-check-label">
<input class="form-check-input" type="radio" :name="`playerTerrainSingle`" v-model="playerTerrain[0]" :value="terrain">
<AppIcon type="terrain" :name="terrain" extension="webp" class="terrainIcon"/>
</label>
</div>
</div>
</li>
</ol>
</li>
<li>
Expand Down Expand Up @@ -100,6 +125,7 @@ import Terrain from '@/services/enum/Terrain'
export default defineComponent({
name: 'AutomaSetup',
emits: {
playerTerrain: (_playerTerrain: (Terrain|undefined)[]) => true, // eslint-disable-line @typescript-eslint/no-unused-vars
botTerrain: (_botTerrain: (Terrain|undefined)[]) => true // eslint-disable-line @typescript-eslint/no-unused-vars
},
components: {
Expand All @@ -108,43 +134,44 @@ export default defineComponent({
setup() {
const { t } = useI18n()
const state = useStateStore()
return { t, state }
const { playerCount, botCount, botFaction } = state.setup.playerSetup
return { t, state, playerCount, botCount, botFaction }
},
data() {
return {
playerTerrain: [undefined, undefined] as (Terrain|undefined)[],
botTerrain: [undefined, undefined] as (Terrain|undefined)[]
}
},
computed: {
palaceTileCount() : number {
return this.state.setup.playerSetup.playerCount + 1
return this.playerCount + 1
},
bonusCardCount() : number {
return this.state.setup.playerSetup.botCount + this.state.setup.playerSetup.playerCount + 3
return this.playerCount + this.botCount + 3
},
randomCard(): Card {
const allCards = Cards.getAll()
const index = rollDice(allCards.length)
return allCards[index - 1]
},
isFactionSymbionts() : boolean {
return this.state.setup.playerSetup.botFaction.includes(BotFaction.SYMBIONTS)
return this.botFaction.includes(BotFaction.SYMBIONTS)
},
isFactionBlight() : boolean {
return this.state.setup.playerSetup.botFaction.includes(BotFaction.BLIGHT)
return this.botFaction.includes(BotFaction.BLIGHT)
},
isFactionGognomes() : boolean {
return this.state.setup.playerSetup.botFaction.includes(BotFaction.GOGNOMES)
return this.botFaction.includes(BotFaction.GOGNOMES)
},
factions() : BotFaction[] {
return this.state.setup.playerSetup.botFaction
return this.botFaction
},
isTwoPlayerGame() : boolean {
const { playerCount, botCount } = this.state.setup.playerSetup
return (playerCount + botCount) == 2
return (this.playerCount + this.botCount) == 2
},
isTwoHumanPlayers() : boolean {
return this.state.setup.playerSetup.playerCount === 2
return this.playerCount === 2
},
terrains() : Terrain[] {
return Object.values(Terrain)
Expand All @@ -156,7 +183,12 @@ export default defineComponent({
}
},
watch: {
// whenever question changes, this function will run
playerTerrain: {
handler(newValue) {
this.$emit('playerTerrain', newValue)
},
deep: true
},
botTerrain: {
handler(newValue) {
this.$emit('botTerrain', newValue)
Expand Down
3 changes: 2 additions & 1 deletion src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"title": "Spieler",
"playerCount": "Menschliche Spieler",
"playerCountItem": "{count} Spieler",
"player": "Spieler {player}",
"botCount": "Automa",
"botCountItem": "{count} Automa | {count} Automas (Experimentell)",
"botFaction": "Automa Gemeinschaft | Automa {bot} Gemeinschaft",
Expand Down Expand Up @@ -53,7 +54,7 @@
},
"factionSelectionTwoHumanPlayer": "Wähle deine <b>Gemeinschaft</b> und Rundenbonus nach den üblichen Regeln für ein Spiel mit 3 Spielern.",
"chooseAutomaTerrain": "Wähle eine <b>Heimatlandschaft</b> für Automa, die anders ist als deine.",
"invalidTerrainSelection": "Bitte wähle eine Heimatlandschaft für Automa aus.",
"invalidTerrainSelection": "Bitte wähle gültige Heimatlandschaften für dich und für Automa aus.",
"automaComponents": {
"title": "Verteile Automas Spielsteine wie folgt:",
"buildings": "Lege alle <b>Gebäude</b> ihrer Farbe in ihren Bereich.",
Expand Down
3 changes: 2 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"title": "Player",
"playerCount": "Human Players",
"playerCountItem": "{count} Player | {count} Players",
"player": "Player {player}",
"botCount": "Automa",
"botCountItem": "{count} Automa | {count} Automas (Experimental)",
"botFaction": "Automa Faction | Automa {bot} Faction",
Expand Down Expand Up @@ -53,7 +54,7 @@
},
"factionSelectionTwoHumanPlayer": "Choose your <b>Faction</b> and Round Bonus following the usual rules for a 3-Player game.",
"chooseAutomaTerrain": "Choose a <b>Native terrain</b> for Automa different from yours.",
"invalidTerrainSelection": "Please select a terrain for Automa.",
"invalidTerrainSelection": "Please select a terrain for you and for Automa.",
"automaComponents": {
"title": "Distribute the Automa components as follows:",
"buildings": "Place all her <b>buildings</b> in her play area.",
Expand Down
3 changes: 3 additions & 0 deletions src/store/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export const useStateStore = defineStore(`${name}.store`, {
resetGame() {
this.setup.roundScoreTiles = undefined
this.setup.roundScoreFinalTile = undefined
this.setup.playerTerrain = undefined
this.setup.botTerrain = undefined
this.setup.setupBookActions = undefined
this.setup.setupCompetencyTiles = undefined
this.setup.setupInnovationTiles = undefined
Expand All @@ -57,6 +59,7 @@ export interface Setup {
playerSetup: PlayerSetup
roundScoreTiles?: number[]
roundScoreFinalTile?: number
playerTerrain?: Terrain[]
botTerrain?: Terrain[]
// parameters not relevant for the application, but persisted for back button support in setup screens
setupBookActions?: number[]
Expand Down
4 changes: 4 additions & 0 deletions src/util/NavigationState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default class NavigationState {
readonly turn : number
readonly turnOrderIndex : number
readonly player : number
readonly playerTerrain? : Terrain
readonly bot : number
readonly botFaction? : BotFaction
readonly botTerrain? : Terrain
Expand Down Expand Up @@ -54,6 +55,9 @@ export default class NavigationState {
this.preferredScienceDiscipline = roundScoreTile.scienceDiscipline
}
}
else {
this.playerTerrain = (setup.playerTerrain ?? [])[this.player - 1]
}
}

}
Expand Down
15 changes: 10 additions & 5 deletions src/views/SetupGameAutoma.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<h1>{{t('setupGameAutoma.title')}}</h1>

<div class="instructions">
<AutomaSetup @botTerrain="value => botTerrain = value"/>
<AutomaSetup @playerTerrain="value => playerTerrain = value" @botTerrain="value => botTerrain = value"/>
</div>

<div class="container-fluid" v-if="!isValidTerrainSelection">
Expand Down Expand Up @@ -41,23 +41,28 @@ export default defineComponent({
},
data() {
return {
botTerrain: [] as (Terrain|undefined)[]
botTerrain: [] as (Terrain|undefined)[],
playerTerrain: [] as (Terrain|undefined)[],
}
},
computed: {
isValidTerrainSelection() : boolean {
if (this.botTerrain[0] === undefined) {
const { playerCount, botCount } = this.state.setup.playerSetup
const allTerrains = [...this.playerTerrain.slice(0, playerCount), ...this.botTerrain.slice(0, botCount)]
// ensure no missing terrain
if (allTerrains.some(terrain => terrain === undefined)) {
return false
}
if (this.state.setup.playerSetup.botCount === 2
&& (this.botTerrain[1] === undefined || this.botTerrain[1] === this.botTerrain[0])) {
// ensure no duplicate terrain
if (new Set(allTerrains).size !== playerCount + botCount) {
return false
}
return true
}
},
methods: {
startGame() : void {
this.state.setup.playerTerrain = this.playerTerrain.filter(terrain => terrain !== undefined)
this.state.setup.botTerrain = this.botTerrain.filter(terrain => terrain !== undefined)
// prepare first round with initial player order
const { playerCount, botCount } = this.state.setup.playerSetup
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/helper/mockState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default function (params?: MockStateParams) : State {
},
roundScoreTiles: params?.roundScoreTiles,
roundScoreFinalTile: params?.roundScoreFinalTile,
playerTerrain: params?.playerTerrain,
botTerrain: params?.botTerrain
},
rounds: params?.rounds ?? []
Expand All @@ -29,6 +30,7 @@ export interface MockStateParams {
botFaction?: BotFaction[]
roundScoreTiles?: number[]
roundScoreFinalTile?: number
playerTerrain?: Terrain[]
botTerrain?: Terrain[]
rounds?: Round[]
}
11 changes: 11 additions & 0 deletions tests/unit/util/NavigationState.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import { CardDeckPersistence } from '@/store/state'
import { RouteParams } from 'vue-router'
import NavigationState from '@/util/NavigationState'
import ScienceDiscipline from '@/services/enum/ScienceDiscipline'
import Terrain from '@/services/enum/Terrain'

const state = mockState({playerCount:1, botCount:2,
roundScoreTiles: [1,4,5,9,11,12], roundScoreFinalTile: 2,
playerTerrain: [Terrain.LAKE], botTerrain: [Terrain.DESERT,Terrain.MOUNTAIN],
rounds:[
mockRound({round:1, playerOrder:[{player:1},{bot:1},{bot:2}], turns:[
mockTurn({round:1,turn:1,player:1}),
Expand Down Expand Up @@ -81,6 +83,15 @@ describe('util/NavigationState', () => {
expect(navigationState({round:'6',turn:'1',bot:'1'}).passVictoryPoints).to.eq(6)
expect(navigationState({round:'6',turn:'1',bot:'1'}).preferredScienceDiscipline).to.eq(ScienceDiscipline.LAW)
})

it('playerTerrain', () => {
expect(navigationState({round:'1',turn:'1',player:'1'}).playerTerrain).to.eq(Terrain.LAKE)
})

it('botTerrain', () => {
expect(navigationState({round:'1',turn:'1',bot:'1'}).botTerrain).to.eq(Terrain.DESERT)
expect(navigationState({round:'1',turn:'1',bot:'2'}).botTerrain).to.eq(Terrain.MOUNTAIN)
})
})

function cardDeck(deck:string[], discard:string[], reserve:string[]) : CardDeckPersistence {
Expand Down

0 comments on commit 209a4a5

Please sign in to comment.