Skip to content

Commit

Permalink
Small Improvements (#2)
Browse files Browse the repository at this point in the history
- fix card age duration display
- add debug mode
- improve intro, setup and difficulty level descriptions
- persist tech card drafting
  • Loading branch information
stefanseifert authored Dec 29, 2024
1 parent 67083e0 commit cd41012
Show file tree
Hide file tree
Showing 14 changed files with 171 additions and 35 deletions.
71 changes: 71 additions & 0 deletions src/components/round/DebugInfo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<template>
<div class="mt-4" v-if="state.setup.debugMode">
<hr/>
<p class="debug">
<b>draftingRow</b>: <span v-html="getCardDeckInfo(draftingRow)"></span><br/>
<b>draftingPriority</b>: <span v-html="getCardDeckInfo(draftingPriority)"></span><br/>
<b>construction</b>: <span v-html="getCardDeckInfo(construction)"></span><br/>
<b>war</b>: <span v-html="getCardDeckInfo(war)"></span><br/>
</p>
</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { useStateStore } from '@/store/state'
import CardDeck from '@/services/CardDeck'
import Card from '@/services/Card'
import NavigationState from '@/util/NavigationState'
import DraftingRowCard from '@/services/DraftingRowCard'
import DraftingPriorityCard from '@/services/DraftingPriorityCard'
import ConstructionCard from '@/services/ConstructionCard'
import WarCard from '@/services/WarCard'
export default defineComponent({
name: 'DebugInfo',
setup() {
const state = useStateStore()
return { state }
},
props: {
navigationState: {
type: NavigationState,
required: true
}
},
computed: {
draftingRow() : CardDeck<DraftingRowCard> {
return this.navigationState.botCards.draftingRow
},
draftingPriority() : CardDeck<DraftingPriorityCard> {
return this.navigationState.botCards.draftingPriority
},
construction() : CardDeck<ConstructionCard> {
return this.navigationState.botCards.construction
},
war() : CardDeck<WarCard> {
return this.navigationState.botCards.war
}
},
methods: {
getCardDeckInfo(deck: CardDeck<Card>) : string {
return `<i>pile</i>: ${deck.pile.map(this.getCardInfo)}, <i>discard</i>: ${deck.discard.map(this.getCardInfo)}`
},
getCardInfo(card: any) : string { // eslint-disable-line @typescript-eslint/no-explicit-any
return '{' + Object.keys(card)
.filter(key => key !== 'id')
.map(key => `${key}: ${card[key]}`)
.join(',') + '}'
}
}
})
</script>

<style lang="scss" scoped>
.debug {
font-size: small;
}
p.debug, ul.debug {
margin: 0;
}
</style>
7 changes: 6 additions & 1 deletion src/components/round/TechCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<AppIcon name="prosperity-money" class="icon"/>
</div>
<div class="durations">
<div class="duration" v-for="age of getDuration(tech)" :key="age" :style="{'z-index':100-age}"><div>{{age}}</div></div>
<div class="duration" v-for="duration of getDuration(tech)" :key="duration" :style="{'z-index':100-duration}"><div>{{duration + round - 1}}</div></div>
</div>
</div>
</template>
Expand Down Expand Up @@ -46,6 +46,11 @@ export default defineComponent({
required: true
}
},
computed: {
round() : number {
return this.navigationState.round
}
},
methods: {
isArmy(tech: Tech) : boolean {
return tech == Tech.ARMY
Expand Down
30 changes: 19 additions & 11 deletions src/components/round/TechCardDraft.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { defineComponent, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { Round, useStateStore } from '@/store/state'
import { useStateStore } from '@/store/state'
import NavigationState from '@/util/NavigationState'
import TechCardSelection from '@/services/TechCardSelection'
import Tech from '@/services/enum/Tech'
Expand All @@ -77,10 +77,16 @@ export default defineComponent({
TechCard,
AppIcon
},
setup() {
setup(props) {
const { t } = useI18n()
const state = useStateStore()
return { t, state }
const roundData = state.rounds.find(item => item.round == props.navigationState.round)!
const botTechs = ref(roundData.botTechs ?? [])
const playerTechs = ref(roundData.playerTechs ?? [])
const playerSpecialActions = ref(roundData.playerSpecialActions ?? 0)
return { t, state, roundData, botTechs, playerTechs, playerSpecialActions }
},
props: {
navigationState: {
Expand All @@ -95,9 +101,6 @@ export default defineComponent({
data() {
return {
removeAnimation: false,
botTechs: [] as Tech[],
playerTechs: [] as Tech[],
playerSpecialActions: 0,
playerTurn: false
}
},
Expand All @@ -119,9 +122,6 @@ export default defineComponent({
},
playerIncomeLockedTotal() : number {
return this.playerTechs.map(tech => this.techCardSelection.getIncome(tech)).filter(value => value == 5).reduce((a,b) => a+b, 0)
},
roundData() : Round {
return this.state.rounds.find(item => item.round == this.navigationState.round)!
}
},
methods: {
Expand All @@ -143,6 +143,7 @@ export default defineComponent({
await new Promise(resolve => setTimeout(resolve, 400));
this.removeAnimation = false
this.navigationState.techCardSelection.remove(tech)
this.persist()
},
async nextTurn() {
if (this.draftingCompleted) {
Expand Down Expand Up @@ -197,7 +198,7 @@ export default defineComponent({
await this.nextTurn()
},
async reset() {
this.navigationState.techCardSelection.reset()
this.techCardSelection.reset()
this.navigationState.botCards.draftingRow.reset()
this.navigationState.botCards.draftingPriority.reset()
this.roundData.nextStartPlayer = undefined
Expand All @@ -208,6 +209,7 @@ export default defineComponent({
this.playerTechs = []
this.playerSpecialActions = 0
this.persist()
await this.nextTurn()
},
async next() {
Expand All @@ -219,6 +221,12 @@ export default defineComponent({
this.playerTurn = false
await this.nextTurn()
}
},
persist() : void {
this.roundData.techCardSelection = this.techCardSelection.toPersistence()
this.roundData.botTechs = this.botTechs
this.roundData.playerTechs = this.playerTechs
this.roundData.playerSpecialActions = this.playerSpecialActions
}
},
mounted() {
Expand Down
18 changes: 10 additions & 8 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"home": {
"title": "Millennia Solo Helper",
"play1": "Play Millennia against Automa, the solo opponent.",
"play2": "This application replaces the Automa cards, and guides you through the game flow.",
"play2": "This application replaces the Automa cards, and guides you through the game flow. Additionally, it automates the tech card drafting and prosperity card selection.",
"feedback": "Discussion and Feedback:"
},
"setup": {
Expand All @@ -24,9 +24,10 @@
"title": "Setup Automa",
"setup": {
"gameBoard": "Setup the game the same way as a 2-player game.",
"techCards": "The tech cards and blank techs are randomized by the application, you are drafting them in the application against Automa.",
"playerColor": "Choose a player color for the automa. The automa only needs 2 track tokens.",
"trackTokens": "Place the automa track tokens on the <b>war track</b> and on the <b>VP track</b> (starting with 10 VP).",
"prosperityCards": "You do not need to set up the prosperity cards, they are managed and displayed by the application.",
"techCards": "The tech cards and blank techs are randomized by the application, you are drafting them in the application against Automa. After each tech drafting phase in the app, pick the cards your drafted from the stack of the corresponding age.",
"playerColor": "Choose a player color for the automa. The automa only needs 1 track marker and 1 VP marker.",
"trackTokens": "Place the automa markers on the <b>war track</b> and on the <b>VP track</b> (starting with 10 VP).",
"startPlayer": {
"player": "<b>You</b> are the start player. Take 10 Gold. Take the first player token.",
"bot": "<b>Automa</b> is the start player. Give it the first player token."
Expand All @@ -41,7 +42,7 @@
"noGold": "The automa never has or gains any gold.",
"noActions": "The automa does not perform any actions in the action phase.",
"onlyWarTrack": "The automa only promotes on the war track and the VP track but on no other tracks.",
"noVP": "The automa does not gain or lose any VP other than from the war phase."
"noVP": "The automa does not gain any VP other than from the war phase."
}
},
"phaseADrafting": {
Expand Down Expand Up @@ -74,7 +75,8 @@
"advance": "Automa advances {steps} steps on the war track.",
"outmax": "If the automa maxes out the war track, it gains 1 VP per step beyond 7.",
"resolve": "Then the war phase is resolved normally.",
"trackVP": "Track the VP the automa during the war phase on the VP track. "
"resolveLastRound": "<i>Last Round</i>: Do not reduce war power.",
"trackVP": "Track the VP the automa gains during the war phase on the VP track. "
},
"phaseGUpkeep": {
"title": "G: Upkeep",
Expand All @@ -89,8 +91,8 @@
"round": "Age {round}"
},
"difficultyLevel": {
"1": "Normal",
"2": "Hard"
"1": "Normal - without 5-step war cards",
"2": "Hard - all war cards"
},
"age": {
"1": "Bronze age",
Expand Down
2 changes: 2 additions & 0 deletions src/store/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ export interface Round {
techCardSelection: TechCardSelectionPersistence
nextStartPlayer?: Player
nextArchitectPlayer?: Player
botTechs?: Tech[]
playerTechs?: Tech[]
playerSpecialActions?: number
}

export interface BotCardsPersistence {
Expand Down
32 changes: 24 additions & 8 deletions src/util/NavigationState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { State } from '@/store/state'
import { Round, State } from '@/store/state'
import { RouteLocation } from 'vue-router'
import getIntRouteParam from '@brdgm/brdgm-commons/src/util/router/getIntRouteParam'
import Player from '@/services/enum/Player'
Expand All @@ -10,27 +10,43 @@ import TechCardSelection from '@/services/TechCardSelection'
export default class NavigationState {

readonly round : number

readonly startPlayer : Player
readonly architectPlayer : Player
readonly prosperityCards : ProsperityCards
readonly botCards : BotCards
readonly rowPlaceholders : RowPlaceholders
readonly techCardSelection : TechCardSelection

private readonly roundData : Round

constructor(route: RouteLocation, state: State) {
this.round = getIntRouteParam(route, 'round')

const roundData = state.rounds.find(item => item.round === this.round)
let roundData = state.rounds.find(item => item.round === this.round)
if (!roundData) {
throw new Error(`Round ${this.round} not found`)
// should never happen
const rowPlaceholders = RowPlaceholders.new()
roundData = {
round: this.round,
startPlayer: Player.PLAYER,
architectPlayer: Player.BOT,
prosperityCards: ProsperityCards.new().toPersistence(),
botCards: BotCards.new(state.setup.difficultyLevel).toPersistence(),
rowPlaceholders: rowPlaceholders.toPersistence(),
techCardSelection: TechCardSelection.new(rowPlaceholders.rows, this.round).toPersistence()
}
}
this.startPlayer = roundData.nextStartPlayer ?? roundData.startPlayer
this.architectPlayer = roundData.nextArchitectPlayer ?? roundData.architectPlayer
this.roundData = roundData
this.prosperityCards = ProsperityCards.fromPersistence(roundData.prosperityCards)
this.botCards = BotCards.fromPersistence(roundData.botCards)
this.rowPlaceholders = RowPlaceholders.fromPersistence(roundData.rowPlaceholders)
this.techCardSelection = TechCardSelection.fromPersistence(roundData.techCardSelection, this.round)
}

public get startPlayer() : Player {
return this.roundData.nextStartPlayer ?? this.roundData.startPlayer
}

public get architectPlayer() : Player {
return this.roundData.nextArchitectPlayer ?? this.roundData.architectPlayer
}

}
6 changes: 5 additions & 1 deletion src/views/PhaseADrafting.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

<TechCardDraft :navigationState="navigationState" :nextButtonRouteTo="nextButtonRouteTo"/>

<DebugInfo :navigationState="navigationState"/>

<FooterButtons :backButtonRouteTo="backButtonRouteTo" endGameButtonType="abortGame"/>
</template>

Expand All @@ -17,13 +19,15 @@ import { useStateStore } from '@/store/state'
import SideBar from '@/components/round/SideBar.vue'
import NavigationState from '@/util/NavigationState'
import TechCardDraft from '@/components/round/TechCardDraft.vue'
import DebugInfo from '@/components/round/DebugInfo.vue'
export default defineComponent({
name: 'PhaseADrafting',
components: {
FooterButtons,
SideBar,
TechCardDraft
TechCardDraft,
DebugInfo
},
setup() {
const { t } = useI18n()
Expand Down
6 changes: 5 additions & 1 deletion src/views/PhaseBProsperity.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
{{t('action.next')}}
</button>

<DebugInfo :navigationState="navigationState"/>

<FooterButtons :backButtonRouteTo="backButtonRouteTo" endGameButtonType="abortGame"/>
</template>

Expand All @@ -20,12 +22,14 @@ import { useRoute } from 'vue-router'
import { useStateStore } from '@/store/state'
import SideBar from '@/components/round/SideBar.vue'
import NavigationState from '@/util/NavigationState'
import DebugInfo from '@/components/round/DebugInfo.vue'
export default defineComponent({
name: 'PhaseBProsperity',
components: {
FooterButtons,
SideBar
SideBar,
DebugInfo
},
setup() {
const { t } = useI18n()
Expand Down
6 changes: 5 additions & 1 deletion src/views/PhaseCIncome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
{{t('action.next')}}
</button>

<DebugInfo :navigationState="navigationState"/>

<FooterButtons :backButtonRouteTo="backButtonRouteTo" endGameButtonType="abortGame"/>
</template>

Expand All @@ -34,13 +36,15 @@ import SideBar from '@/components/round/SideBar.vue'
import NavigationState from '@/util/NavigationState'
import Tech from '@/services/enum/Tech'
import AppIcon from '@/components/structure/AppIcon.vue'
import DebugInfo from '@/components/round/DebugInfo.vue'
export default defineComponent({
name: 'PhaseCIncome',
components: {
FooterButtons,
SideBar,
AppIcon
AppIcon,
DebugInfo
},
setup() {
const { t } = useI18n()
Expand Down
Loading

0 comments on commit cd41012

Please sign in to comment.