Skip to content

Commit

Permalink
feat: tunnel
Browse files Browse the repository at this point in the history
  • Loading branch information
Mezeman1 committed Sep 13, 2024
1 parent 97ba8ed commit 0b98e26
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .eslintcache

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/stores/gameStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const useGameStore = defineStore('gameStore', {
larvaeProductionRate: 1, // Larvae produced per queen per minute
collectionRatePerAnt: 60, // Seeds collected per ant per minute

collectionRatePerWorker: 600, // Seeds collected per worker per minute
collectionRatePerWorker: 6000, // Seeds collected per worker per minute
},

resourceCosts: {
Expand Down Expand Up @@ -781,7 +781,7 @@ export const useGameStore = defineStore('gameStore', {
larvaeProductionRate: 1,
collectionRatePerAnt: 60,

collectionRatePerWorker: 600,
collectionRatePerWorker: 6000,
}

// Reset storage to initial caps
Expand Down
9 changes: 9 additions & 0 deletions src/stores/prestigeStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,15 @@ export const usePrestigeStore = defineStore('prestige', {
return usePrestigeStore().upgradePurchased('eliteAnts')
},
},
{
id: 'tunnels',
name: 'Tunnels',
description: 'Unlock the tunnel system for exploration',
cost: 500,
category: 'expansion',
applyOnPrestige: true,
oneTimePurchase: true,
},
] as PrestigeShopItem[], // List of items in the prestige shop

// Prestige-related variables
Expand Down
143 changes: 143 additions & 0 deletions src/stores/tunnelStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { defineStore } from 'pinia'
import { useGameStore } from '@/stores/gameStore'

export const useTunnelStore = defineStore('tunnelStore', {
state: () => ({
antsInTunnel: 0, // Current ants in tunnel
initialAntsInTunnel: 0, // Ants at the start of exploration
tunnelDepth: 0,
tunnelProgress: 0, // Progress towards next depth point
depthBoost: 0, // Boost for initial depth scaling
resourcesFound: {
seeds: 0,
mineralShards: 0, // New resource for tunnel upgrades
},
trapsEncountered: 0,
lootFound: [], // Loot added to the player's inventory
activeUpgrades: [], // Tunnel-related upgrades
autoTunnelActive: false, // Whether the tunnel exploration is auto-running
tunnelSpeedMultiplier: 1, // Affects speed of digging
animationFrameId: 0, // ID for managing animation frames
}),

getters: {
progressToNextDepth(state) {
return Math.min(state.tunnelProgress / 100, 1)
},
getAvailableAnts() {
const gameStore = useGameStore()
return gameStore.resources.ants
},
},

actions: {
// Start the tunnel exploration
startTunnelExploration(antsToSend: number) {
if (this.antsInTunnel > 0) return // Prevent sending more ants if the tunnel is active

this.antsInTunnel = antsToSend
this.initialAntsInTunnel = antsToSend // Store the starting number of ants

// **New Calculation**: Linear-Logarithmic scaling for initial depth
const linearFactor = this.initialAntsInTunnel * 0.00001 // Linear boost for every ant sent
const logFactor = Math.log10(this.initialAntsInTunnel + 10) // Logarithmic component to maintain balance
this.depthBoost = linearFactor + logFactor // Combine linear and log scaling
this.tunnelDepth = 0
this.tunnelProgress = 0
this.autoTunnelActive = true // Set auto mode

this.runTunnelLoop(performance.now()) // Start the loop
},

// Main tunnel loop to run exploration and events
runTunnelLoop(timestamp: number) {
if (this.antsInTunnel <= 0 || !this.autoTunnelActive) return

// Process ants in batches for better performance
const batchSize = Math.max(10, Math.min(1000, this.antsInTunnel)) // Process at least 10 ants or up to 1000
const progressGain = Math.log(batchSize) * 0.2 * this.tunnelSpeedMultiplier // Logarithmic scaling for progress
this.tunnelProgress += progressGain

// Check if we've reached the next depth point
if (this.tunnelProgress >= 100) {
this.tunnelDepth += 1
this.tunnelProgress = 0

// Handle events (find resources, encounter traps, etc.)
this.triggerTunnelEvent()
}

// Continue the loop using requestAnimationFrame
if (this.antsInTunnel > 0) {
this.animationFrameId = requestAnimationFrame(this.runTunnelLoop)
} else {
console.log('Tunnel exploration complete.')
this.stopTunnelExploration() // Stop if no ants remain
}
},

// Stop the tunnel exploration
stopTunnelExploration() {
this.autoTunnelActive = false
cancelAnimationFrame(this.animationFrameId)
this.antsInTunnel = 0
console.log('Tunnel exploration stopped.')
},

// Handle random events (resources, traps, loot)
triggerTunnelEvent() {
const eventChance = Math.random()

// Adjust depth multiplier to scale logarithmically for better control at higher depths
const depthMultiplier = Math.log2(this.tunnelDepth + 2) // Logarithmic scaling: log2(depth + 2)

// Scale event rewards based on the initial number of ants sent
const antMultiplier = Math.pow(this.initialAntsInTunnel, 0.25) // Use a 0.25 power scale for rewards and event intensity

// Trap chance scaling slower, maxing at 50% but taking more depth to reach there
const trapChance = Math.min(0.2 + this.tunnelDepth * 0.01, 0.5) // Max out at 0.5 but slower scaling per depth

if (eventChance < 0.3) {
// Find resources (seeds or mineral shards)
const seedsFound = Math.floor((Math.random() * 50 + 10) * depthMultiplier * antMultiplier)
const shardsFound = Math.floor((Math.random() * 5 + 1) * depthMultiplier * antMultiplier)

this.resourcesFound.seeds += seedsFound
this.resourcesFound.mineralShards += shardsFound
} else if (eventChance < trapChance) {
if (this.tunnelDepth < this.depthBoost) return // Prevent traps at the start (linear boost)

// Calculate percentage loss based on depth
const baseLossPercentage = 0.05 // Base 5% loss
const maxLossPercentage = 0.3 // Max 30% loss at very deep levels
const depthFactor = Math.log2(this.tunnelDepth + 2) / 10 // Scale the depth factor logarithmically
const percentageLost = Math.min(baseLossPercentage + depthFactor, maxLossPercentage) // Ensure it doesn’t exceed max loss

const antsLost = Math.floor(this.initialAntsInTunnel * percentageLost)

this.antsInTunnel = Math.max(0, this.antsInTunnel - antsLost)
this.trapsEncountered += 1
} else {
// Find better loot in deeper tunnels, loot value scaling with depth and ant group size
const lootValue = Math.floor((Math.random() * 100 + 50) * depthMultiplier * antMultiplier)
const loot = { name: 'Rare Artifact', value: lootValue }

this.lootFound.push(loot)
}
},

// Reset tunnel data
resetTunnel() {
this.antsInTunnel = 0
this.initialAntsInTunnel = 0 // Reset the initial ants as well
this.tunnelDepth = 0
this.tunnelProgress = 0
this.resourcesFound = { seeds: 0, mineralShards: 0 }
this.trapsEncountered = 0
this.lootFound = []
this.autoTunnelActive = false
cancelAnimationFrame(this.animationFrameId)
console.log('Tunnel progress reset.')
},
},
})
14 changes: 14 additions & 0 deletions src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@
</button>
</li>

<li class="flex-shrink-0">
<button
:class="activeTab === 'tunnels' ? activeTabClasses : defaultTabClasses"
:disabled="!usePrestigeStore().upgradePurchased('tunnels')"
class="inline-block p-2 w-auto border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 text-2xs md:text-sm disabled:cursor-not-allowed"
@click.prevent="setActiveTab('tunnels')"
>
Tunnels
</button>
</li>

<li class="flex-shrink-0">
<button
:class="activeTab === 'inventory' ? activeTabClasses : defaultTabClasses"
Expand Down Expand Up @@ -117,6 +128,7 @@
<AntResources v-show="activeTab === 'resources'" />
<Adventure v-show="activeTab === 'adventure'" />
<Inventory v-show="activeTab === 'inventory'" />
<Tunnels v-show="activeTab === 'tunnels'" />
<Debugger v-show="activeTab === 'debugger'" />
<Settings v-show="activeTab === 'settings'" />
</div>
Expand Down Expand Up @@ -187,6 +199,8 @@ import firebase from 'firebase/compat'
import Settings from './Settings.vue'
import {useAdventureStore} from '../stores/adventureStore'
import {useDebounce, useDebounceFn} from '@vueuse/core'
import Tunnels from '@/views/Tunnels.vue'
import {usePrestigeStore} from '@/stores/prestigeStore'
const gameStore = useGameStore()
const adventureStore = useAdventureStore()
Expand Down
180 changes: 180 additions & 0 deletions src/views/Tunnels.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<template>
<div class="p-6 bg-gradient-to-br from-gray-800 to-gray-900 text-white rounded-lg shadow-lg space-y-6">
<div class="text-center">
<p>
Note: this feature does not work yet.
<br>
You can play around with the slider and start the exploration to get an idea of how it would look like.
<br>
This is just a UI to show how it would look like. The actual implementation is not done.
</p>
</div>
<!-- Title and Tunnel Info -->
<div class="text-center">
<h1 class="text-2xl font-bold text-yellow-300 mb-1">
Ant Tunnel Exploration
</h1>
<p class="text-sm text-gray-300">
Send your ants deep into the tunnels to discover resources, loot, and dangers!
</p>
</div>

<!-- Ants sent and progress section -->
<div class="flex flex-col items-center space-y-4">
<div class="flex items-center space-x-4">
<p class="text-base font-semibold text-yellow-400">
Ants in Tunnels: <strong>{{ formatNumber(antsInTunnel, 0) }}</strong>
</p>
<button
v-if="antsInTunnel > 0"
class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg shadow-lg text-sm font-medium transition-all duration-300"
@click="stopTunnelExploration"
>
Stop Exploration
</button>
</div>

<!-- Tunnel Progress Bar -->
<div class="relative w-full bg-gray-700 rounded-full h-4 shadow-inner">
<div
class="absolute top-0 left-0 bg-green-500 h-full rounded-full"
:style="{ width: (progressToNextDepth * 100) + '%' }"
/>
</div>
<p class="text-sm text-gray-300">
Depth: <span class="font-semibold text-green-400">{{ tunnelDepth }}</span>
</p>
</div>

<!-- Slider for selecting ants to send -->
<div class="flex flex-col items-center space-y-2">
<label
for="ants-slider"
class="text-base font-semibold text-gray-300"
>Select the number of ants to send:</label>
<input
id="ants-slider"
v-model="selectedAnts"
type="range"
:min="10"
:max="availableAnts"
:step="getSteps"
class="w-full slider"
>
<p class="text-sm text-gray-300">
Ants to send: <strong class="text-yellow-400">{{ formatNumber(selectedAnts, 0) }}</strong>
</p>
</div>

<!-- Send button -->
<div class="flex justify-center">
<button
class="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg shadow-md font-medium transition-all duration-300"
:disabled="selectedAnts > availableAnts"
@click="startTunnelExploration(selectedAnts)"
>
Start Digging
</button>
</div>

<!-- Events section with scrollable box -->
<div class="space-y-2">
<h2 class="text-lg font-bold text-yellow-400">
Events
</h2>
<p
v-if="antsInTunnel <= 0"
class="text-xs text-gray-400"
>
No ants in tunnels. Start exploration to find resources and face traps.
</p>
<div class="max-h-40 overflow-y-auto bg-gray-800 bg-opacity-50 rounded-lg p-3 space-y-2">
<ul class="list-disc list-inside text-sm text-gray-300">
<li
v-if="resourcesFound.seeds > 0"
class="text-green-400"
>
Found {{ resourcesFound.seeds }} seeds
</li>
<li
v-if="resourcesFound.mineralShards > 0"
class="text-blue-400"
>
Found {{ resourcesFound.mineralShards }} mineral shards
</li>
<li
v-if="trapsEncountered > 0"
class="text-red-400"
>
Encountered {{ trapsEncountered }} traps
</li>
<li
v-for="(loot, index) in lootFound"
:key="index"
class="text-purple-400"
>
Found loot: {{ loot.name }}
</li>
</ul>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { useTunnelStore } from '@/stores/tunnelStore'
import { storeToRefs } from 'pinia'
import { ref, computed } from 'vue'
import {useGameStore} from '@/stores/gameStore'
const tunnelStore = useTunnelStore()
const gameStore = useGameStore()
const formatNumber = gameStore.formatNumber
// Destructure state and actions
const {
antsInTunnel,
tunnelDepth,
progressToNextDepth,
resourcesFound,
trapsEncountered,
lootFound,
} = storeToRefs(tunnelStore)
const { startTunnelExploration, stopTunnelExploration } = tunnelStore
// Slider for selecting ants to send
const selectedAnts = ref(10)
const availableAnts = computed(() => tunnelStore.getAvailableAnts) // Assume there's a method that returns available ants
const getSteps = computed(() => (availableAnts.value > 100 ? 10 : 1))
</script>

<style scoped>
/* Add slider styling */
.slider {
-webkit-appearance: none;
width: 100%;
height: 10px;
border-radius: 8px;
background: #374151;
outline: none;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 24px;
height: 24px;
border-radius: 50%;
background: #2563eb;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 24px;
height: 24px;
border-radius: 50%;
background: #2563eb;
cursor: pointer;
}
</style>

0 comments on commit 0b98e26

Please sign in to comment.