Skip to content

Commit

Permalink
1.4.0 Nanobot
Browse files Browse the repository at this point in the history
  • Loading branch information
bboonstra committed Sep 28, 2024
1 parent a8e179b commit 178c9d8
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 23 deletions.
52 changes: 52 additions & 0 deletions idlegame/battle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from typing import List
from idlegame.data import AutosavedPlayer
from idlegame.nanobots import Nanobot
import random

def simulate_defense(player: AutosavedPlayer, defending_bots: List[Nanobot]) -> int:
"""Simulate defense against invasions using the given nanobots.
Args:
player (AutosavedPlayer): The player who owns the nanobots.
defending_bots (List[Nanobot]): The nanobots assigned to defend.
Returns:
int: The number of nanobots that were broken during the defense.
"""
if not defending_bots:
return 0 # No bots to defend

# Calculate total defense power from the defending bots
total_defense_power = sum(bot.defense_rating for bot in defending_bots)

# Simulate the invasion strength (could be a random number or based on game state)
invasion_strength = random.randint(1, 10) # Example invasion strength
print(f"Invasion strength: {invasion_strength}, Total defense power: {total_defense_power}")

# Calculate the ratio of defense power to invasion strength
defense_ratio = total_defense_power / invasion_strength if invasion_strength > 0 else 1

# Determine the chance of breaking bots based on defense ratio
# If defense_ratio is high, break chance is low; if low, break chance is high
# Exponential scaling for break chance:
if defense_ratio >= 2:
break_chance = 0 # Strong advantage
elif defense_ratio >= 1:
break_chance = (1 - (defense_ratio - 1) / 1) * 0.5 # Linear decrease
else:
# Exponential growth in break chance for heavily disadvantaged scenario
break_chance = min(1, 0.5 * (1 - defense_ratio)) # Break chance up to 50% max

bots_broken = 0

# Determine how many bots break based on calculated break chance
for bot in defending_bots:
if random.random() < break_chance:
player.nanos.remove(bot) # Remove the broken bot from the player's list
print(f"One of your defending bots, '{bot.name}', was broken during an invasion!")
bots_broken += 1

if bots_broken == 0:
print(f"Your defenses held against an invasion (Strength: {invasion_strength}).")

return bots_broken
22 changes: 21 additions & 1 deletion idlegame/config.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,22 @@
from datetime import timedelta

save_file = 'savedata.pickle'
disallowed_usernames = ['cancel']
disallowed_usernames = ['cancel']
base_mining_rate = 1
sim_chunk_duration = 600 # 600 seconds = 10 minutes
invasion_chance_per_chunk = 0.05 # 5% per 10 mins

def handle_sudo(player, *args, **kwargs):
key = kwargs.get('k', '')
if key.lower() != "verysecure":
print("Invalid command. Try 'man commands'!")
return

ts = kwargs.get('lengthen-uptime', 0)

if ts:
# Subtract the specified number of seconds from the last claim timestamp
player.last_claim_timestamp -= timedelta(seconds=int(ts))
print(f"Added {int(ts)/60} mins to uptime")


77 changes: 60 additions & 17 deletions idlegame/idle.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,85 @@
from datetime import datetime, timezone
from .data import AutosavedPlayer
from datetime import datetime, timezone, timedelta
from idlegame.data import AutosavedPlayer
from idlegame.battle import simulate_defense
import idlegame.config as config
import random

def handle_claim(player: AutosavedPlayer, *args, **kwargs) -> None:
"""Claim rewards in the game.
"""See what occurred while you were offline!
Usage:
claim [--reward <reward>] [--silent]
uptime [--silent]
Options:
--reward <reward> Specify the reward to claim.
--silent Suppress output messages.
"""

now = datetime.now(timezone.utc) # Use UTC time

# Check for the --silent option
silent_mode = kwargs.get('silent', False)

if player.last_claim_timestamp is None:
# If the player has never claimed, just set it to now
# If the player has never claimed, initialize last claim timestamp and give 1 core.
player.last_claim_timestamp = now
player.save()
print("You have claimed your first reward of 1 regular nanocore!")
player.nano_cores['normal'] += 1
player.save()
print("You have claimed your first reward of 1 regular nano core!")
return

# Calculate time difference since last claim
time_offline = now - player.last_claim_timestamp
minutes_offline = int(time_offline.total_seconds() // 60)
gold_gain = minutes_offline
if minutes_offline < 1:
total_seconds_offline = int(time_offline.total_seconds())

if total_seconds_offline < 600:
if not silent_mode:
print("You haven't been offline for long enough to get any rewards!")
print("Nothing has happened yet. You need to wait for at least 10 minutes to claim rewards!")
return

player.gold += gold_gain

# Update last claim timestamp to now
player.last_claim_timestamp = now
num_chunks = total_seconds_offline // config.sim_chunk_duration

gold_gathered = 0
invasions_handled = 0
nanobots_broken = 0

# Simulate each 10-minute chunk
for _ in range(num_chunks):
invasion_occurred = random.random() < config.invasion_chance_per_chunk

# Collect all defenders for this chunk
defending_bots = []

for bot in player.nanos:
# Do event actions if applicable
for event, action in bot.event_actions.items():
if event.lower() in ['battle.defense', 'defense', 'invasion'] and action in ['defend', 'join', 'support', 'defense'] and invasion_occurred:
defending_bots.append(bot)
print(bot.name)
continue
else:
# Otherwise do idle actions
if bot.idle_action == 'mine':
gold_gathered += config.base_mining_rate # mine resources for this chunk

# Simulate defense if an invasion occurred
if invasion_occurred:
invasions_handled += 1
nanobots_broken += simulate_defense(player, defending_bots)
# TODO logic if you lose


# Add gathered gold to player
player.gold += gold_gathered

# Update last claim timestamp to reflect only complete chunked increments
leftover_time = total_seconds_offline % config.sim_chunk_duration
player.last_claim_timestamp = now - timedelta(seconds=leftover_time)
player.save()

# Print the results unless in silent mode
if not silent_mode:
print(f"You have claimed {gold_gain} gold for being offline for {minutes_offline} minutes!")
print(f"You were offline for {total_seconds_offline // 60} minutes.")
print(f"You mined {gold_gathered} gold!")
print(f"{invasions_handled} invasions were handled during your offline time.")
if nanobots_broken > 0:
print(f"{nanobots_broken} of your bots was broken during the invasions.")
2 changes: 2 additions & 0 deletions idlegame/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from idlegame.idle import handle_claim
from idlegame.profile import handle_profile
from idlegame.nanobots import handle_nano, handle_list, handle_remove
from idlegame.config import handle_sudo
import colorama as c
c.init()
class CommandLineInterface(cmd.Cmd):
Expand All @@ -25,6 +26,7 @@ def __init__(self, player):
"nano": handle_nano,
"rm": handle_remove,
"ls": handle_list,
"sudo": handle_sudo,
}

def handle_alias(self, player, *args, **kwargs):
Expand Down
6 changes: 4 additions & 2 deletions idlegame/nanobots.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from prompt_toolkit import prompt
from idlegame.data import AutosavedPlayer
from enum import Enum

Expand All @@ -15,6 +14,9 @@ def __init__(self, name: str, logic: str, type: Nanotype):
self.idle_action = None
self.event_actions = {}
self.type = type
self.defense_rating = 1
if self.type == Nanotype.FIGHTER:
self.defense_rating += 1
self.parse_logic(logic)

def parse_logic(self, logic: str) -> None:
Expand Down Expand Up @@ -58,7 +60,7 @@ def handle_nano(player: AutosavedPlayer, *args, **kwargs) -> None:
Use the `on` parameter for an event-driven job
Use the `done` parameter to finish scripting
Example:
idle harvest
idle mine
on attacking attack
on defending defend
done
Expand Down
2 changes: 1 addition & 1 deletion idlegame/profile.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .data import AutosavedPlayer
from idlegame.data import AutosavedPlayer

def handle_profile(player: AutosavedPlayer, *args, **kwargs) -> None:
"""Check your profile.
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
colorama==0.4.6
setuptools==75.1.0
prompt_toolkit==3.0.48
Binary file modified savedata.pickle
Binary file not shown.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='idlegame',
version='1.3.2',
version='1.4.0',
packages=find_packages(),
install_requires=[
'colorama',
Expand Down

0 comments on commit 178c9d8

Please sign in to comment.