#๐Ÿ”’ YAAA

110 messages ยท Page 1 of 1 (latest)

languid junco
deep zincBOT
#

@languid junco

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

languid junco
#

One of each kind.

Passive:
"Resonant."
Characters statistics are increased by their teams current resonance.

Conditional:
"Second Wind."
Character regains their discord in health when they dip below half health.

Acting:
"Companion."
Character may call on a companion to grant them a +2 bonus to a roll, three times per fight.

#

Current system:
Characters are brought into a fight object.
Round 1 begins. They use Tribulate_Percents() to choose their action. Hype, Harmony, or (Non-functional) Discord.
If two opposing members choose the same action, they clash. Roll 2d6 + Base attribute. Winner has action go through.
Continue until a win condition is met.

obtuse zealot
#

This is unrelated to the question, but one thing I'd note: if you can, avoid mutating things at all costs. For example: ```py
@dataclass
class Stat:
base: int = 0
hype_mod: int = 0
mod_mod: int = 0
item_mod: int = 0
external_mod: int = 0
total: int = 0

def update_total(self):
    self.total = self.base + self.hype_mod + self.mod_mod + self.item_mod + self.external_mod

this class is not easy to work with, because you have to remember to update the total every time you do something with it. Instead you could have a method to calculate the total:py
@dataclass
class Stat:
base: int = 0
hype_mod: int = 0
mod_mod: int = 0
item_mod: int = 0
external_mod: int = 0

def total(self):
    return self.base + self.hype_mod + self.mod_mod + self.item_mod + self.external_mod
languid junco
#

added to two random.randint(1,6)'s

obtuse zealot
languid junco
#

Okay so:
Resonance is built through successful Harmony actions. At 10, the match is ended in favor of those who built it.
If a character is Resonant, they would benefit from the current resonance on their team. Say it's round two, team1 resonance is 1. They gain +1 to Harmony, Hype, and Discord (mod_mod's)

#

That would filter into future actions and clashes to make their success more likely

obtuse zealot
#

So you have resonance (which is a number that applies to the whole team), and when a creature has a Resonant modifier, it has a bonus added to their base stats, correct?

languid junco
#

Ye

#

(Resonance is technically a stadium attribute but that's honestly something I may change lol- just felt right at the time)

obtuse zealot
#

Do you have other examples of passive modifiers?

languid junco
#

I can whip em up

#

"Resilient"
This character gains 5 health at the start of each fight, which is not replenishable.
"Regenerative"
This character regains 1 health at the start of each round.
"Slasher"
This character deals twice the damage to opponents under half health.

hot lynx
#

how you're structuring the game code doesn't feel too great to me

languid junco
#

Oh it probably isn't- it's intended to be a browser game, where characters are unplayable. Sorta like watching a football simulator where players can throw molotovs

#

(Is also my first major project hehehe )

hot lynx
obtuse zealot
#

ah, those are the modifiers you currently have?..

#

I think I don't quite understand the game

#

@languid junco Can you outline the general design? Like, what stats do you have and how a fight works

languid junco
#

Oh, it'd be checked in order of attainment, on account of being appended as they come. So if they get a +2 and x2, it'd happen in that order

obtuse zealot
hot lynx
languid junco
# obtuse zealot <@270025030144884738> Can you outline the general design? Like, what stats do yo...

Bet-
So. Characters are generated in teams of 3. Maybe 4 I haven't decided.
Fights will be an 8-team round robin format. Fight until all teams have fought one another, and then the top half move up to the next bracket. Repeat until there is one decisive victor.
Now, Characters.
Characters have three statistics.
Harmony, representing peace and equivalence.
Hype, representing expression and engagement.
Discord, representing disorder and resentment.
Along with this, they have 12 'ticks' of health. When they reach 0, 4, and 8 (Or 0, 1, and 2/3rds of their maximum health) they suffer injuries. The first injury is a character-wide -1. The second is a character-wide -3. The third removes the ability to act.

Now, the fights:
Each fight, characters decide on the statistic they wish to personally use. Each has a corresponding effect.

Harmony builds Resonance. If a team attains 10 Resonance, they are victorious.
Hype exaggerates ability. Allies of the user will gain a bonus equivalent to the users hype statistic.
Discord harms others. Characters deal 2 damage to a target of their choice.

If two opposing team members choose the same statistic, they clash. Each rolls 2d6 and adds the result to their statistic value. The higher roller wins, and their action goes through. The loser has their action denied.

Fights continue until Resonance is obtained, or there is nobody left to fight.

obtuse zealot
#

damn, 40000 fights

#

So each character starts a fight with 12 ticks of health, which regenerate at the end of the fight?

languid junco
#

As for modifiers and such:
Modifiers are character traits granted through Rehearsal. These are various and many, coming in three basic kinds.
Passive. A modifier which is active at all times.
Conditional. A modifier which creates a condition that must be met.
Acting. A modifier which creates a unique course of action.
Modifiers can be permanent or impermanent.

Rehearsal occurs when a team is removed from end-season contention. Each character is granted one of three choices of positive boost to take, often in the form of modifiers. The team overall has a chance to acquire the same.

languid junco
#

(But as discord, which uses an injury modifier, isn't in use yet, I haven't worked on the regeneration)

#

(No it doesn't absolutely need to use a modifier but if I ever make a modifier which has the ability to remove temporary mods, or to benefit from how many mods a character has, it'll be pretty damn cool)

obtuse zealot
#

Do injuries stay with a character forever?

languid junco
#

nope, removed when they regain past that health threshold

obtuse zealot
#

so injuries are temporary debuffs that are removed at the end of a fight?

languid junco
#

so usually it'll be at the end of a fight. but idk maybe a char regenerates past that point with a modifier

hot lynx
languid junco
#

Ye- It should remove the effect B had weee

#

So if it's like
A is +1, B is *3, C is +4.
Total stat is 15.
B wears off
Total stat is 5

#

essentially gets whatever the equivalent of rpg-commented out is

hot lynx
languid junco
#

How so?

hot lynx
#

if it was checked in order of attainment, you should get (((+1) * 3) + 4) = +7

languid junco
#

Ohhh like pemdas you mean

#

hmmcat Ig I hadn't considered that yea-

#

I mean it'd be cooler to do multiplication last, since otherwise it feels a bit underwhelming

hot lynx
# languid junco Ohhh like pemdas you mean

no
I mean you said that "modifiers should be applied in order of attainment," so you should apply the modifiers in order A -> B -> C instead of grouping the + and * together to get (A -> C) -> B

obtuse zealot
# languid junco ye

Purplys is saying that simply storing the results of applying modifiers will not let you remove the middle one

languid junco
#

Oh yeah that's an issue i'll come across huh hmmcat

hot lynx
hot lynx
languid junco
#

hmmcat Ig ideally it'd be like.
Character has... 5 harmony and "Adrenaline" which is a *3 1/fight, and Companion.
It makes most sense to have it function as.
Harmony first.
Adrenaline is an action called on (by weighted rng) and makes their harmony 15.
Opponent somehow puts their harmony up to 16.
Character uses Companion to add +2.
Opponent dies a nerd

#

OHHH

#

Ig it depends on modifier.
Passives should come first in attainment. They don't exactly wear off, so there's not much risk.

#

Active and Conditional (Actions) apply in order of whatever the rng used to decide secondary actions does

#

since that rng will basically just be "if im losing do a thing"

hot lynx
languid junco
#

Yeah that's a concern aeugh I will. Simply not make that for a while lol- mainly because I have no idea how i'd do that

#

Tho ig i'd need something to disable actives and conditionals anyways, if i'm using limited uses

#

probably just a counter

hot lynx
#

I guess what I'd do in this situation is to just store the base stat, and have another function calculate the actual stat on the fly
something like... oh idk,

class Character:
    stat_harmony_base: int = 0
    modifiers: list[Modifier] = []

    def effective_harmony(self):
        result = self.stat_harmony_base
        for mod in self.modifiers:
            result = mod(result)
        return result
languid junco
#

raises by 1 each time that mod is used. if counter is (use cases) break

languid junco
hot lynx
# languid junco :nod: Though how would that account for external factors and hype bonuses?

Hype exaggerates ability. Allies of the user will gain a bonus equivalent to the users hype statistic.
hmm... well you can have a HypeModifier always in that list

class HypeHarmonyModifier(Modifier):
    def __call__(self, char: Character, harmony: int):
        return stat + char.stat_hype_base

class Character:
    stat_harmony_base: int = 0
    stat_hype_base: int = 0
    modifiers: list[Modifier] = [HypeHarmonyModifier()]

    def effective_harmony(self):
        result = self.stat_harmony_base
        for mod in self.modifiers:
            result = mod(self, result)
        return result
#

and be careful of circular dependency

languid junco
#

ah, infinite recursion my beloved

obtuse zealot
#

Maybe something more general like ```py
@dataclass(frozen=True)
class Stats:
harmony: int
hype: int
discord: int

@dataclass
class Character:
base_stats: BaseStats
modifiers: list[Callable[[Stats], Stats]]

def effective_stats(self) -> Stats:
    stats = base_stats
    for modifier in self.modifiers:
        stats = modifier(stats)
    return stats
hot lynx
#

that seems nice, then you can have

class HypeHarmonyModifier(Modifier):
    def __call__(self, stats: Stats):
        return Stats(
            hype=stats.hype, 
            harmony=stats.harmony + stats.hype, 
            discord=stats.discord + stats.hype
        )
```so `hype` doesn't infinitely blow up or something
obtuse zealot
#

Instead of a function, you could have something like py @dataclass(frozen=True) class Modifier: name: str description: str modify: Callable[[Stats], Stats] and then store list[Modifier] as purplys suggested

#

so now you can e.g. print the modifiers a character has to a human

languid junco
#

lol I really need to learn what callable is

obtuse zealot
#

Type annotations are a whole other language on top of Python, don't learn two languages at once

hot lynx
languid junco
#

but what if I learn it with python and become uber-einstein

languid junco
#

So Callable[[Stats], Stats] would be thing... wait if its just converting stats to stats whats that do lol

hot lynx
languid junco
#

Now I don't know what that is either fingergunsderp

#

or well

#

function named add 5 which takes an integer(x) and returns integer + 5

#

but I- okay yea lol

#

the lack of newline fucked me up lmao

obtuse zealot
#

For example, if you want a modifier that adds 3 to hype:

def add_3_to_hype(stats: Stats) -> Stats:
    return Stats(hype=stats.hype + 3, discord=stats.discord, harmony=stats.harmony)
```  Now you can do: ```py
Character(stats=some_base_stats, modifiers=[add_3_to_hype])
#

Or with this thing #1243456439926919218 message:

modifier = Modifier(
    name="Coffee",
    description="+3 to hype",
    modify=add_3_to_hype,
)
Character(stats=some_base_stats, modifiers=[modifier])
#

If you want modifiers to have other inputs and other outputs, you can do that. Add more arguments and return a tuple with various changes

languid junco
#

hmmcat you mighta lost me- or well. Ig sorta ksad
So when you huck Character(stats=blablbla, modifiers=[modifier] in there, is that seperate from the modifier variable, or part of it?

obtuse zealot
#

Do you understand passing functions as arguments to other functions?

languid junco
#

since I understand how add3 would work, but would the variable just call on the add3 function (per modify) which then serves for stats:Stats -> to update with the result of that function?

obtuse zealot
deep zincBOT
languid junco
#

maybe for clarity: As I read that, line by line
apply_twice is a function which accepts a function.
It returns... function(function(arg)), with arg presumably being inputted
add3 blabla
double blabla easy

print takes that apply_twice(100, add3) and uses 100 as x for the add3 function, bringing it into itself.
Now- I don't beleive I quite understand the staging of that function(function(arg)) part. If... say add3 requires x right after it, shouldn't it be print(apply_twice(add3, 100)?

#

or well

#

ig it goes arg, function

#

just returns function(arg)

#

nvm weee

#

I think I get it

languid junco
#

oh wait

#

thats reallt simple djcjnc

#

it just returns add3(add3(100))

#

because function is called twice akjdbd

#

i still dont understand though- whats callable?

obtuse zealot
#

essentially, that's how you specify a function in type annotations

#

For example:

def apply_twice(arg: int, function: Callable[[int], int]) -> int:
    return function(function(arg))
languid junco
#

ahhh

deep zincBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.