Skip to content

Commit

Permalink
refactor: improve how random trait values are computed
Browse files Browse the repository at this point in the history
  • Loading branch information
natelandau committed Nov 15, 2023
1 parent f45913a commit 80e16c5
Show file tree
Hide file tree
Showing 44 changed files with 1,103 additions and 624 deletions.
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
- [ ] Campaign: View any campaign, not just active one
- [ ] CharGen: Add backgrounds to freebie point picker
- [ ] CharGen: Add changelings
- [ ] CharGen: Add edges for hunters
- [x] CharGen: Add edges for hunters
- [ ] CharGen: Add ghouls
- [ ] CharGen: Add mages
- [ ] CharGen: Add merits/flaws to freebie point picker
Expand Down
371 changes: 186 additions & 185 deletions poetry.lock

Large diffs are not rendered by default.

36 changes: 23 additions & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@
typer = { extras = ["all"], version = "^0.9.0" }

[tool.poetry.group.test.dependencies]
dirty-equals = "^0.6.0"
faker = "^19.13.0"
polyfactory = "^2.11.0"
pytest = "^7.4.3"
pytest-asyncio = "^0.21.1"
pytest-clarity = "^1.0.1"
pytest-env = "^1.1.1"
pytest-mock = "^3.12.0"
pytest-pretty-terminal = "^1.1.0"
pytest-xdist = "^3.3.1"
dirty-equals = "^0.6.0"
faker = "^19.13.0"
polyfactory = "^2.11.0"
pytest = "^7.4.3"
pytest-asyncio = "^0.21.1"
pytest-clarity = "^1.0.1"
pytest-env = "^1.1.1"
pytest-mock = "^3.12.0"
pytest-sugar = "^0.9.7"
pytest-xdist = "^3.3.1"

[tool.poetry.group.dev.dependencies]
commitizen = "^3.12.0"
Expand Down Expand Up @@ -94,10 +94,19 @@
data_file = "reports/.coverage"
omit = [
"src/valentina/__version__.py",
"src/valentina/bot.py",
"src/valentina/cogs/*",
"src/valentina/characters/add_from_sheet.py",
"src/valentina/characters/buttons.py",
"src/valentina/characters/reallocate_dots.py",
"src/valentina/characters/spend_experience.py",
"src/valentina/main.py",
"src/valentina/models/bot.py",
"src/valentina/models/errors.py",
"src/valentina/utils/discord_utils.py",
"src/valentina/utils/errors.py",
"src/valentina/utils/logging.py",
"src/valentina/utils/types.py",
"src/valentina/views/*",
"tests/*",
]
source = ["src"]

Expand Down Expand Up @@ -128,12 +137,13 @@

[tool.pytest.ini_options]

addopts = "--color=yes --doctest-modules --exitfirst --failed-first --strict-config --strict-markers --verbosity=2 --junitxml=reports/pytest.xml --ignore=src/valentina/cogs/test_cog.py"
addopts = "--color=yes --doctest-modules --exitfirst --failed-first --strict-config --strict-markers --junitxml=reports/pytest.xml --ignore=src/valentina/cogs/test_cog.py"
asyncio_mode = "auto"
env = [
"VALENTINA_AWS_ACCESS_KEY_ID=access_key",
"VALENTINA_AWS_SECRET_ACCESS_KEY=secred_access_key",
"VALENTINA_S3_BUCKET_NAME=bucket",
"VALENTINA_TEST_CONFIG_KEY=testing",
]
filterwarnings = ["error", "ignore::DeprecationWarning"]
markers = [
Expand Down
61 changes: 11 additions & 50 deletions src/valentina/characters/chargen.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
from valentina.models import Campaign, Character, CharacterSheetSection, CharacterTrait, User
from valentina.models.bot import Valentina, ValentinaContext
from valentina.utils.helpers import (
adjust_sum_to_match_total,
divide_into_three,
divide_total_randomly,
fetch_random_name,
get_max_trait_value,
)
Expand Down Expand Up @@ -566,23 +565,13 @@ async def random_attributes(self, character: Character) -> Character:

category_traits = cat.get_trait_list(CharClass[character.char_class_name])

# Generate initial random distribution for the traits in the category
mean, distribution = self.experience_level.value
random_values = [
max(min(x, 5), 0)
for x in _rng.normal(mean, distribution, len(category_traits)).astype(int32)
]

# Adjust the sum of the list to match the total dots for the category
final_values = adjust_sum_to_match_total(
random_values, category_dots, max_value=5, min_value=1
)
trait_values = divide_total_randomly(category_dots, len(category_traits), 5, 1)

# Create the attributes and assign them to the character
for t in category_traits:
trait = CharacterTrait(
name=t,
value=final_values.pop(0),
value=trait_values.pop(0),
max_value=get_max_trait_value(t, cat.name),
character=str(character.id),
category_name=cat.name,
Expand Down Expand Up @@ -634,22 +623,13 @@ async def random_abilities(self, character: Character) -> Character:
category_dots = total_dots.pop(0)

category_traits = cat.get_trait_list(CharClass[character.char_class_name])

# Generate initial random distribution for the traits in the category
mean, distribution = self.experience_level.value
random_values = [
max(min(x, 5), 0)
for x in _rng.normal(mean, distribution, len(category_traits)).astype(int32)
]

# Adjust the sum of the list to match the total dots for the category
final_values = adjust_sum_to_match_total(random_values, category_dots, max_value=5)
trait_values = divide_total_randomly(category_dots, len(category_traits), 5, 0)

# Create the attributes and assign them to the character
traits = [
CharacterTrait(
name=t,
value=final_values.pop(0),
value=trait_values.pop(0),
max_value=get_max_trait_value(t, cat.name),
character=str(character.id),
category_name=cat.name,
Expand Down Expand Up @@ -748,11 +728,8 @@ async def random_virtues(self, character: Character) -> Character:
}
total_dots = starting_dots + extra_dots_map[self.experience_level]

# Divide total dots for each category into three to produce a value for each attribute
dots_for_each = divide_into_three(total_dots)

# Adjust the sum of the list to match the total dots for the category
values = adjust_sum_to_match_total(dots_for_each, total_dots, max_value=5, min_value=1)
# Divide total dots to produce a value for each attribute
values = divide_total_randomly(total_dots, len(virtues), max_value=5, min_value=1)

# Create the traits and assign them to the character
for v in virtues:
Expand Down Expand Up @@ -797,21 +774,13 @@ async def random_backgrounds(self, character: Character) -> Character:
if total_dots == 0:
return character

# Generate initial random distribution for the traits in the category
mean, distribution = self.experience_level.value
initial_values = [
max(min(x, 5), 0)
for x in _rng.normal(mean, distribution, len(backgrounds)).astype(int32)
]

# Adjust the sum of the list to match the total dots for the category
values = adjust_sum_to_match_total(initial_values, total_dots, max_value=5)
trait_values = divide_total_randomly(total_dots, len(backgrounds), 5, 0)

# Create the backgrounds and assign them to the character
for b in backgrounds:
trait = CharacterTrait(
name=b,
value=values.pop(0),
value=trait_values.pop(0),
max_value=get_max_trait_value(b, TraitCategory.BACKGROUNDS.name),
character=str(character.id),
category_name=TraitCategory.BACKGROUNDS.name,
Expand Down Expand Up @@ -920,21 +889,13 @@ async def random_hunter_traits(self, character: Character) -> Character:
RNGCharLevel.ELITE: 2,
}
total_dots = starting_dots + extra_dots_map[self.experience_level]

# Generate initial random distribution for the traits in the category
mean, distribution = self.experience_level.value
initial_values = [
max(min(x, 3), 0) for x in _rng.normal(mean, distribution, len(edges)).astype(int32)
]

# Adjust the sum of the list to match the total dots for the category
values = adjust_sum_to_match_total(values=initial_values, total=total_dots, max_value=3)
trait_values = divide_total_randomly(total_dots, len(edges), 5, 0)

# Create the edges and assign them to the character
for e in edges:
trait = CharacterTrait(
name=e,
value=values.pop(0),
value=trait_values.pop(0),
max_value=get_max_trait_value(e, TraitCategory.EDGES.name),
character=str(character.id),
category_name=TraitCategory.EDGES.name,
Expand Down
38 changes: 20 additions & 18 deletions src/valentina/cogs/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ async def add_role(
"""Add user to role."""
# Confirm the action
title = f"Add {member.display_name} to {role.name}"
is_confirmed, confirmation_response_msg = await confirm_action(
is_confirmed, msg, confirmation_embed = await confirm_action(
ctx, title, description=reason, hidden=hidden
)
if not is_confirmed:
return

await member.add_roles(role, reason=reason)

await confirmation_response_msg
await msg.edit_original_response(embed=confirmation_embed, view=None)

@user.command()
@discord.guild_only()
Expand Down Expand Up @@ -109,15 +109,15 @@ async def kick(

# Confirm the action
title = f"Kick {member.display_name} from this guild"
is_confirmed, confirmation_response_msg = await confirm_action(
is_confirmed, interaction, confirmation_embed = await confirm_action(
ctx, title, description=reason, hidden=hidden
)
if not is_confirmed:
return

await member.kick(reason=reason)

await confirmation_response_msg
await interaction.edit_original_response(embed=confirmation_embed, view=None)

@user.command()
@discord.guild_only()
Expand Down Expand Up @@ -147,7 +147,7 @@ async def ban(

# Confirm the action
title = f"Ban {user.display_name} from this guild"
is_confirmed, confirmation_response_msg = await confirm_action(
is_confirmed, interaction, confirmation_embed = await confirm_action(
ctx, title, description=reason, hidden=hidden
)
if not is_confirmed:
Expand All @@ -157,7 +157,7 @@ async def ban(
discord.Object(id=user.id), reason=f"{ctx.author} ({ctx.author.id}): {reason}"
)

await confirmation_response_msg
await interaction.edit_original_response(embed=confirmation_embed, view=None)

@user.command()
@discord.guild_only()
Expand All @@ -175,7 +175,7 @@ async def unban(
"""Revoke ban from a banned user."""
# Confirm the action
title = f"Unban {user.display_name} from this guild"
is_confirmed, confirmation_response_msg = await confirm_action(ctx, title, hidden=hidden)
is_confirmed, msg, confirmation_embed = await confirm_action(ctx, title, hidden=hidden)
if not is_confirmed:
return

Expand All @@ -190,7 +190,7 @@ async def unban(
)
return

await confirmation_response_msg
await msg.edit_original_response(embed=confirmation_embed, view=None)

@user.command()
@discord.guild_only()
Expand Down Expand Up @@ -232,7 +232,7 @@ async def massban(

# Confirm the action
title = f"Mass ban {count} {p.plural_noun('member', count)} from this guild"
is_confirmed, confirmation_response_msg = await confirm_action(
is_confirmed, interaction, confirmation_embed = await confirm_action(
ctx, title, description=reason, hidden=hidden
)
if not is_confirmed:
Expand All @@ -250,7 +250,7 @@ async def massban(

await ctx.guild.ban(user, reason=f"{ctx.author} ({ctx.author.id}): {reason}")

await confirmation_response_msg
await interaction.edit_original_response(embed=confirmation_embed, view=None)

## SETTINGS COMMANDS #############################################################################

Expand Down Expand Up @@ -324,7 +324,7 @@ async def emoji_add(

# Confirm the action
title = f"Add custom emoji :{name}:"
is_confirmed, confirmation_response_msg = await confirm_action(ctx, title, hidden=hidden)
is_confirmed, msg, confirmation_embed = await confirm_action(ctx, title, hidden=hidden)
if not is_confirmed:
return

Expand All @@ -333,7 +333,7 @@ async def emoji_add(

# Send confirmation
await ctx.post_to_audit_log(title)
await confirmation_response_msg
await msg.edit_original_response(embed=confirmation_embed, view=None)

@guild.command(name="emoji_delete")
@discord.option("name", description="The name of the emoji to delete.")
Expand Down Expand Up @@ -410,13 +410,15 @@ async def slowmode(

# Confirm the action
title = f"Set slowmode to {seconds} seconds"
is_confirmed, confirmation_response_msg = await confirm_action(ctx, title, hidden=hidden)
is_confirmed, interaction, confirmation_embed = await confirm_action(
ctx, title, hidden=hidden
)
if not is_confirmed:
return

await ctx.channel.edit(slowmode_delay=seconds)

await confirmation_response_msg
await interaction.edit_original_response(embed=confirmation_embed, view=None)

@channel.command()
@discord.guild_only()
Expand Down Expand Up @@ -449,7 +451,7 @@ async def lock(

# Confirm the action
title = "Lock this channel"
is_confirmed, confirmation_response_msg = await confirm_action(
is_confirmed, interaction, confirmation_embed = await confirm_action(
ctx, title, description=reason, hidden=hidden
)
if not is_confirmed:
Expand All @@ -460,7 +462,7 @@ async def lock(
reason=f"{ctx.author} ({ctx.author.id}): {reason}",
)

await confirmation_response_msg
await interaction.edit_original_response(embed=confirmation_embed, view=None)

@channel.command()
@discord.guild_only()
Expand Down Expand Up @@ -492,7 +494,7 @@ async def unlock(

# Confirm the action
title = "Unlock this channel"
is_confirmed, confirmation_response_msg = await confirm_action(
is_confirmed, interaction, confirmation_embed = await confirm_action(
ctx, title, description=reason, hidden=hidden
)
if not is_confirmed:
Expand All @@ -502,7 +504,7 @@ async def unlock(
overwrites={ctx.guild.default_role: discord.PermissionOverwrite(send_messages=None)},
reason=f"{ctx.author} ({ctx.author.id}): {reason}",
)
await confirmation_response_msg
await interaction.edit_original_response(embed=confirmation_embed, view=None)

@channel.command()
@commands.has_permissions(administrator=True)
Expand Down
Loading

0 comments on commit 80e16c5

Please sign in to comment.