From 517d478bc42f2add39c2ac531e355f42b786e017 Mon Sep 17 00:00:00 2001 From: n0lavar Date: Tue, 11 Jun 2024 23:21:32 +0100 Subject: [PATCH] now runs with the same seed always give the same result --- cp_red_npc_generator/requirements.txt | 3 ++- cp_red_npc_generator/src/generate_ammo.py | 5 +++-- cp_red_npc_generator/src/generate_stats.py | 4 ++-- cp_red_npc_generator/src/generate_weapon.py | 8 +++---- cp_red_npc_generator/src/main.py | 4 ++-- .../src/normal_distribution.py | 4 ++-- cp_red_npc_generator/src/utils.py | 21 +++++++------------ 7 files changed, 22 insertions(+), 27 deletions(-) diff --git a/cp_red_npc_generator/requirements.txt b/cp_red_npc_generator/requirements.txt index dc8eddc..a0885ab 100644 --- a/cp_red_npc_generator/requirements.txt +++ b/cp_red_npc_generator/requirements.txt @@ -1,2 +1,3 @@ +PyInstaller dataclass_wizard -PyInstaller \ No newline at end of file +numpy \ No newline at end of file diff --git a/cp_red_npc_generator/src/generate_ammo.py b/cp_red_npc_generator/src/generate_ammo.py index a2a0d10..4f69cfe 100644 --- a/cp_red_npc_generator/src/generate_ammo.py +++ b/cp_red_npc_generator/src/generate_ammo.py @@ -2,8 +2,8 @@ # -*- coding: utf-8 -*- import logging -import random from typing import List, Dict +import numpy as np from item import Item, ItemType from npc import Npc @@ -88,7 +88,8 @@ def add_basic_ammo(ammo_type: str) -> bool: add_basic_ammo("Bullets") or add_basic_ammo("Slugs") or add_basic_ammo("Arrows") for _ in range(RANDOM_GENERATING_NUM_ATTEMPTS): - required_ammo_type, magazine_size = random.choice(list(required_ammo_types.items())) + required_ammo_type = list(required_ammo_types.keys())[np.random.choice(len(required_ammo_types))] + magazine_size = required_ammo_types[required_ammo_type] try_add_ammo(required_ammo_type, choose_exponential_random_element(preferred_ammo_modifications, True), magazine_size) diff --git a/cp_red_npc_generator/src/generate_stats.py b/cp_red_npc_generator/src/generate_stats.py index 0dee17a..e570cc9 100644 --- a/cp_red_npc_generator/src/generate_stats.py +++ b/cp_red_npc_generator/src/generate_stats.py @@ -3,7 +3,7 @@ import functools import logging -import random +import numpy as np from typing import List, Optional, Callable from npc import Npc @@ -93,7 +93,7 @@ def distribute_points(weights: List[float], stats_data = load_data("configs/stats.json") streetrat_stats_table: List[List[int]] = stats_data["streetrat_stats"][npc_template.role.name] - streetrat_chosen_table: List[int] = random.choice(streetrat_stats_table) + streetrat_chosen_table: List[int] = streetrat_stats_table[np.random.choice(len(streetrat_stats_table))] stats_mean_clamped_distributed = distribute_points(streetrat_chosen_table, npc_template.rank.stats_budget.generate(), 2, diff --git a/cp_red_npc_generator/src/generate_weapon.py b/cp_red_npc_generator/src/generate_weapon.py index 735c32b..a3957ff 100644 --- a/cp_red_npc_generator/src/generate_weapon.py +++ b/cp_red_npc_generator/src/generate_weapon.py @@ -4,7 +4,7 @@ import copy import logging import dataclass_wizard -import random +import numpy as np from typing import List, Optional, Set, Tuple from dataclasses import dataclass, field, replace @@ -29,7 +29,7 @@ def pick_weapon(budget: int, return None, 0 for _ in range(RANDOM_GENERATING_NUM_ATTEMPTS): - preferred_weapon: str = random.choice(list(preferred_weapons)) + preferred_weapon: str = np.random.choice(sorted(list(preferred_weapons))) for cyberware in installed_cyberware: if preferred_weapon in cyberware.item.tags: logging.debug(f"\t\tFound a cyberware that acts like a preferred weapon: {cyberware.item}") @@ -46,7 +46,7 @@ def pick_weapon(budget: int, case _: raise AssertionError - preferred_quality: ItemQuality = random.choice(list(preferred_qualities)) + preferred_quality: ItemQuality = np.random.choice(preferred_qualities) logging.debug(f"\t\tChosen quality: {preferred_quality}") preferred_weapon_item: ItemWithNames = next(w for w in all_weapons if preferred_weapon in w.tags) @@ -70,7 +70,7 @@ def pick_weapon(budget: int, weapon = replace(weapon_copy, price=price, quality=preferred_quality, - name=f"{random.choice(list(weapon_copy.possible_names))} ({weapon_copy.name})") + name=f"{np.random.choice(list(weapon_copy.possible_names))} ({weapon_copy.name})") logging.debug(f"\t\tPicked weapon: {weapon}") logging.debug(f"\t\tMoney left: {budget - price}") diff --git a/cp_red_npc_generator/src/main.py b/cp_red_npc_generator/src/main.py index bab1ec8..839e243 100644 --- a/cp_red_npc_generator/src/main.py +++ b/cp_red_npc_generator/src/main.py @@ -2,11 +2,11 @@ # -*- coding: utf-8 -*- import argparse -import random import dataclass_wizard import logging import time import sys +import numpy as np from generate_ammo import generate_ammo from generate_armor import generate_armor @@ -45,7 +45,7 @@ def main(args) -> int: seed = args.seed else: seed = int(time.time()) - random.seed(seed) + np.random.seed(seed) rank_data = dataclass_wizard.fromdict(Rank, next(r for r in ranks if r["name"] == args.rank)) role_data = dataclass_wizard.fromdict(Role, next(r for r in roles if r["name"] == args.role)) diff --git a/cp_red_npc_generator/src/normal_distribution.py b/cp_red_npc_generator/src/normal_distribution.py index 7ed50b1..0c54b05 100644 --- a/cp_red_npc_generator/src/normal_distribution.py +++ b/cp_red_npc_generator/src/normal_distribution.py @@ -1,8 +1,8 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import random from dataclasses import dataclass +import numpy as np @dataclass @@ -11,4 +11,4 @@ class NormalDistribution: standard_deviation: float = 0 def generate(self) -> float: - return random.gauss(mu=self.mean, sigma=self.standard_deviation) + return np.random.normal(self.mean, self.standard_deviation) diff --git a/cp_red_npc_generator/src/utils.py b/cp_red_npc_generator/src/utils.py index aabb79c..dc229d4 100644 --- a/cp_red_npc_generator/src/utils.py +++ b/cp_red_npc_generator/src/utils.py @@ -2,8 +2,8 @@ # -*- coding: utf-8 -*- import json -import random -import math + +import numpy as np RANDOM_GENERATING_NUM_ATTEMPTS: int = 200 @@ -12,18 +12,11 @@ def left_align(obj, offset: int = 0, char: str = "\t") -> str: return char * offset + obj -def choose_exponential_random_element(elements, reverse: bool = False): - def generate_exponential_random(lambda_param): - u = random.random() - return -math.log(1 - u) / lambda_param - - exp_values = [generate_exponential_random(1.0) for _ in elements] - total = sum(exp_values) - probabilities = [v / total for v in exp_values] - if reverse: - probabilities = [1.0 - p for p in probabilities] - - return random.choices(elements, weights=probabilities, k=1)[0] +def choose_exponential_random_element(elements, reverse: bool = False, scale=1.0): + weights = np.random.exponential(scale, len(elements)) + probabilities = weights / weights.sum() + index = np.random.choice(len(elements), p=list(reversed(probabilities)) if reverse else probabilities) + return elements[index] def load_data(json_path: str):