Proof Of Concept - Breeding Game

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Message
Author
Euter Space
Newbie
Posts: 9
Joined: Mon Apr 25, 2016 7:26 pm
Contact:

Proof Of Concept - Breeding Game

#1 Post by Euter Space »

Deleted.
Last edited by Euter Space on Thu Dec 02, 2021 3:32 pm, edited 7 times in total.

Euter Space
Newbie
Posts: 9
Joined: Mon Apr 25, 2016 7:26 pm
Contact:

Re: Ant-Fly [ProofOfConcept/Breeding/Stat Raising/Management

#2 Post by Euter Space »

Deleted.
Last edited by Euter Space on Thu Dec 02, 2021 3:32 pm, edited 2 times in total.

drKlauz
Veteran
Posts: 239
Joined: Mon Oct 12, 2015 3:04 pm
Contact:

Re: Ant-Fly [ProofOfConcept/Breeding/StatRaising/Management]

#3 Post by drKlauz »

>Is there a way to display the leading zeros when randomly generating numbers through randint()?

Code: Select all

$name = '%04d'%renpy.random.randint(0000, 9999)
>Is there a way to change or add to the name of a variable?

Wrong:

Code: Select all

$BoxName + BoxNumber = nameN 
Less wrong:

Code: Select all

$nameN = BoxName + str(BoxNumber) 
Left side is where result should be, right side is what you want there.

You really should use more complex structures for such game, i believe.

Kinda ok:

Code: Select all

init python:
  class TAnt(renpy.store.object):
    def __init__(self,Name,Color):
      self.BoxNumber=None
      self.Name=Name if Name is not None else '%04d'%renpy.random.randint(0000, 9999)
      self.Color=Color
    def Place(self,BoxNumber=None):
      if self.BoxNumber is not None:
        Boxes[self.BoxNumber].remove(self)
      self.BoxNumber=BoxNumber
      if BoxNumber is not None:
        Boxes[BoxNumber].append(self)

  def ListAntsInBox(BoxNumber):
    rv=[]
    for Ant in Boxes[BoxNumber]:
      rv.append(Ant.Name)
    return ','.join(rv) if len(rv)>0 else 'noone'

label start:
  $Boxes=[[]]*11

label test:
  $AntNames=ListAntsInBox(2)
  "In box#2 lives [AntNames]"
  $Ant=TAnt('Bob','Lilac')
  $Ant.Place(2)
  "[Ant.Name] was put in box [Ant.BoxNumber]."
  $Ant=TAnt('Alice','Yellow')
  $Ant.Place(2)
  "[Ant.Name] was put in box [Ant.BoxNumber]."
  $AntNames=ListAntsInBox(2)
  "In box#2 lives [AntNames]"
  $Ant.Place(None)
  "[Ant.Name] was removed from box."
  $AntNames=ListAntsInBox(2)
  "In box#2 lives [AntNames]"

  "byebye"
return
>Is there an easy way to group things and check for dependencies between the grouped objects?

You can play with sets or dicts. Need to see whole picture (how many traits, how they defined, how they can be combined, etc) to properly suggest solution.
Or simply write huge if/elif/else mostrosity, heh.

Euter Space
Newbie
Posts: 9
Joined: Mon Apr 25, 2016 7:26 pm
Contact:

Re: Ant-Fly [ProofOfConcept/Breeding/StatRaising/Management]

#4 Post by Euter Space »

Deleted.
Last edited by Euter Space on Thu Dec 02, 2021 3:33 pm, edited 2 times in total.

drKlauz
Veteran
Posts: 239
Joined: Mon Oct 12, 2015 3:04 pm
Contact:

Re: Proof Of Concept - Breeding Game

#5 Post by drKlauz »

Code: Select all

    if BoxNumber == 1:
        $BoxName1 = nameN
    elif Boxnumber == 2:
        $BoxName2 = nameN
    #etc.
List+Index is much better solution to this. This way you can change total boxnumbers, change how you name boxes. If you hardcode something, like box definition, you will suffer later, when you decide to add different box types for example.

>Mostly so i could follow your example in the first place.^^

If you decide to focus on game mechanics, i'm available for hire as programmer/consultant haha

Anyway, if you plan something complex, then it's good idea to make things as generic as possible. Don't hardcode any constants, don't copy paste code, don't write huge if/elif/else bedsheets.

>Is there an easy way to group things and check for dependencies between the grouped objects?
>Not gonna lie, at this point the whole game is one big if/elif/else monstrosity...^^

You can do something like this:

Code: Select all

init python:
  AntBaseValue=5
  ValueBonuses=[
    [{'Color':'Rainbow'}, 1000],
    [{'EyeColor':'Pink'}, 7],
    [{'Color':'Lilac','EyeColor':'Pink'},10],
    [{'Color':'White','EyeColor':'Red'}, 100],
    ]

  class TAnt(renpy.store.object):
    def __init__(self,Name,Color,EyeColor):
      self.BoxNumber=None
      self.Name=Name if Name is not None else '%04d'%renpy.random.randint(0000, 9999)
      self.Color=Color
      self.EyeColor=EyeColor
    def Place(self,BoxNumber=None):
      if self.BoxNumber is not None:
        Boxes[self.BoxNumber].remove(self)
      self.BoxNumber=BoxNumber
      if BoxNumber is not None:
        Boxes[BoxNumber].append(self)
    @property
    def Value(self):
      Value=AntBaseValue
      for BonusReq,Bonus in ValueBonuses:
        Match=True
        for Attr,Val in BonusReq.items():
          if getattr(self,Attr)!=Val:
            Match=False
            break
        if Match:
          Value+=Bonus
      return Value

label start:
  $Alice=TAnt('Alice','White','Red')
  $Bob=TAnt('Bob','White','Pink')
  $Charlie=TAnt('Charlie','Rainbow','Pink')
  "[Alice.Name] cost [Alice.Value], [Bob.Name] cost [Bob.Value], [Charlie.Name] cost [Charlie.Value]"

  "byebye"
return

Euter Space
Newbie
Posts: 9
Joined: Mon Apr 25, 2016 7:26 pm
Contact:

Re: Proof Of Concept - Breeding Game

#6 Post by Euter Space »

Deleted.
Last edited by Euter Space on Thu Dec 02, 2021 3:33 pm, edited 3 times in total.

drKlauz
Veteran
Posts: 239
Joined: Mon Oct 12, 2015 3:04 pm
Contact:

Re: Proof Of Concept - Breeding Game

#7 Post by drKlauz »

I wonder if there's a better/shorter way to do it.
Python is very expressive language, there is some bad sides too, but overall i pretty much love it. Once you learn it you can really do things incredible easy and quick.
Would it be possible to add a value bonus to everything, BUT a certain combination?
Set basic value to higher value and specific combination bonus to negative number.
You can actually use function as combination buff:

Code: Select all

  def ApplyRainbowGen(Child):
    Child.Color='Rainbow'

  InheritanceBonuses=[
    [{'Color':'Rainbow'}, ApplyRainbowGen],
    ]

  def ApplyInheritanceBonus(Child,Parent):
    for BonusReq,Bonus in ValueBonuses:
      Match=True
      for Attr,Val in BonusReq.items():
        if getattr(Parent,Attr)!=Val:
          Match=False
          break
      if Match and callable(Bonus):
        Bonus(Child)

  def MakeBaby(Male,Female):
    Child=TAnt(None,'Black','Black')
    ApplyInheritance(Child,Male)
    ApplyInheritance(Child,Female)
After re-reading, i think you can indeed use something like this

Code: Select all

  ValueBonuses=[
    # notice !Red
    [{'Color':'White','EyeColor':'!Red'}, 100],
    ]

    def Value(self):
      Value=AntBaseValue
      for BonusReq,Bonus in ValueBonuses:
        Match=True
        for Attr,Val in BonusReq.items():
          if Val[0]=='!':
            Val=Val[1:]
            Test=lambda a,b: a!=b
          else:
            Test=lambda a,b: a==b
          if not Test(getattr(self,Attr),Val):
            Match=False
            break
        if Match:
          Value+=Bonus
      return Value
How to access the boxes?
I would create class for Box, then maybe class AntFarm, which will contain and handle boxes.
During Ant.Place method, i would call Box.CanPlace(Ant) to check if ant will fit.
How to add a new Ant-Fly to the Ant class?
Ants probable shouldn't be predefined at all. During ant creation you should keep it in generic variable "Ant", once you created it fully, then place ant in box, so only box will handle it, and forget about Ant. Tho you should be careful if you interconnect box and ant, if you link box by number, everything ok, but if you keep box link in ant as direct reference, then you can get memory leak. It's kinda tricky sometimes.
Thank you for offering, but this is only an ambitious learning project.
It was half-joke, but still while i can answer simple question during teatime or when i want distraction from my main project, i can't answer all questions.
I may be available for hire, check my thread: viewtopic.php?f=66&t=51350

Euter Space
Newbie
Posts: 9
Joined: Mon Apr 25, 2016 7:26 pm
Contact:

Re: Proof Of Concept - Breeding Game

#8 Post by Euter Space »

Deleted.
Last edited by Euter Space on Thu Dec 02, 2021 3:33 pm, edited 2 times in total.

drKlauz
Veteran
Posts: 239
Joined: Mon Oct 12, 2015 3:04 pm
Contact:

Re: Proof Of Concept - Breeding Game

#9 Post by drKlauz »

Zero-matches (combinations of traits from three different archetypes) still give me trouble, though.
Don't understand what exactly you want to get. It really helps if you provide not only description of problem, but also test cases. Something simple code like:

Code: Select all

#i have some ant
Ant=TAnt('Green','White')
#...

#...
#here i want to check if his eyes are white
WhiteEyes=...?
#...

#...
#here i use WhiteEyes
if WhiteEyes:
  '[Ant.Name] is blind :('
For complex combinations you can actually use classes(again):

Code: Select all

init python:
  AntBaseValue=5

  class TAnt(renpy.store.object):
    def __init__(self,Name,Color,EyeColor):
      self.BoxNumber=None
      self.Name=Name if Name is not None else '%04d'%renpy.random.randint(0000, 9999)
      self.Color=Color
      self.EyeColor=EyeColor
      self.CalculateValue()
    def Place(self,BoxNumber=None):
      if self.BoxNumber is not None:
        Boxes[self.BoxNumber].remove(self)
      self.BoxNumber=BoxNumber
      if BoxNumber is not None:
        Boxes[BoxNumber].append(self)
    def CalculateValue(self):
      self.Value=AntBaseValue
      for Bonus in Bonuses:
        if Bonus.DoCheck(self):
          Bonus.DoApply(self)
      return self.Value

  Bonuses=[]

  class BonusMeta(type):
    def __init__(cls,name,bases,dct):
      #this black magic allow Bonuses autoregistration
      #no need to manually add every bonus to list
      if name!='TBonusBase':
        Bonuses.append(cls)
      #this black magic allow to ignore boilerplate code, like @staticmethod
      cls.Check=staticmethod(cls.Check.__func__)
      cls.Apply=staticmethod(cls.Apply.__func__)

  #it can be anything, not just bonuses, genetic inheritance fit here quite nicely
  class BonusBase:
    __metaclass__=BonusMeta #part of black magic, mentioned above
    @classmethod
    def DoCheck(cls,Ant):
      for parent in cls.__mro__:
        if parent is BonusBase: break
        if not parent.Check(Ant): return False
      return True
    @classmethod
    def DoApply(cls,Ant):
      cls.Apply(Ant)
#     if you want cascade bonuses, then uncomment next 3 lines and comment previous
#      for parent in cls.__mro__:
#        if parent is BonusBase: break
#        parent.Apply(Ant)
    def Check(Ant):
      return True
    def Apply(Ant):
      pass

  #Add value if Ant color is Rainbow
  class BonusRainbowColor(BonusBase):
    def Check(Ant):
      return Ant.Color=='Rainbow'
    def Apply(Ant):
      Ant.Value+=100

  #Add value if Ant color is Rainbow AND Ant eye color in Rainbow
  class BonusRainbowColorAndEyeColor(BonusRainbowColor):
    def Check(Ant):
      return Ant.EyeColor=='Rainbow'
    def Apply(Ant):
      Ant.Value+=150
      #if you cascade bonuses then total bonus will be +100 for color, +100+150 for color+eyes
      #if you not cascade then total bonus will be +100 for color, +150 for color+eyes
      #Apply cascading allow some tricky, but make things more complicated
      #you probably should keep cascading of Checks, but not cascading of Apply

  #Add value if Ant color wasn't unlocked before
  #When player sell Ant for example, you add Ant color to UnlockedColors
  #Or you can change bonuses to grant bonus only to first Ant with such color
  class BonusNewColor(BonusBase):
    def Check(Ant):
      return Ant.Color not in UnlockedColors
    def Apply(Ant):
      Ant.Value+=10

label start:
  $UnlockedColors=['White']

  $Alice=TAnt('Alice','Red','Red') #+10 for Unlocked color, +5 default value
  $Bob=TAnt('Bob','White','Pink') #+5 default value
  $Charlie=TAnt('Charlie','Rainbow','Pink') #+100 for Color, +10 for Unlocked color, +5 default value
  $Diana=TAnt('Diana','Rainbow','Rainbow') #+150 for Color+Eye, +100 for Color, +10 for Unlocked color, +5 default value
  "[Alice.Name] cost [Alice.Value], [Bob.Name] cost [Bob.Value], [Charlie.Name] cost [Charlie.Value], [Diana.Name] cost [Diana.Value]"

  "byebye"
return
The boxes themselves consist of several lists (boxname, boxgender, etc.), so I can make use of the list position to dynamically change and display the stats of a specific ant in a specific box.
So instead of "Boxes[BoxNumber][AntNumber].Name" you use "boxname[BoxNumber][AntNumber]"? Not sure i can see any benefit in this tbh, but it's your choice heh.
Works just fine as dialogue in the script.rpy, but adding the same variables to a label or just plain text either makes the label/text not appear or gives me an error. I wonder why that is?
I can't see problem just from this line, what error, what code, etc?
Best option (if you don't mind sharing game) is put you game on http://github.com and share link, so if you have something not working, someone can simple download you game and see what is wrong there.
Answer questions as long as you're having fun
What can i say, i LOVE programming, especially tricky. Especially in python.
I may be available for hire, check my thread: viewtopic.php?f=66&t=51350

Euter Space
Newbie
Posts: 9
Joined: Mon Apr 25, 2016 7:26 pm
Contact:

Re: Proof Of Concept - Breeding Game

#10 Post by Euter Space »

Deleted.
Last edited by Euter Space on Thu Dec 02, 2021 3:33 pm, edited 3 times in total.

drKlauz
Veteran
Posts: 239
Joined: Mon Oct 12, 2015 3:04 pm
Contact:

Re: Proof Of Concept - Breeding Game

#11 Post by drKlauz »

So, what I'm trying to do is the following:

Code: Select all

...
I hope this is a little better.
NSFW link https://www.youtube.com/watch?v=7Dt5Nf7ct5c

Ooooookey... You see i'm not native english speaker (it's obvious i guess), also i know nothing about ant-flies, heck i know very little about regular ants. So you should excuse me for my ignorance.

I don't understand what you want to get, but i think Bonus class i showed in previous post can handle it. It provide generic way to check any conditions you want, and, if conditions met, generic way to alter ant or box or anything else you want. Once you understand how it works.

Let's try it from different angle.
This is mostly because I didn't (and probably still don't) fully understand classes (but I'm working on it!)
Pretty much everything in python (and renpy, more or less) is object.

You have book ("Big Fancy Dictionary 2nd ed.").
This dictionary book contain entries ("Squirel (noun) - little squiky pest").
"Squirel" is key, by which you find entry.
"Little squeaky pest" is value, bound to key.
"(noun)" is additional technical information about value.

Object is like dictionary book.
You have book (Ant).
It has keys (Name, Color, Value).
Some keys has additional info (Name and Color are simple Attributes, containing string or number or list, but CaclulateValue is code Attribute, so it's defined bit differently).
And each key has value (Name->"Alice", Color->"Lilac"). Some keys contain not string values, but code values, it's called methods.
You can consider simple Attributes(Name,Color) as Nouns, and Methods(CalculateValue) as Verbs.
There is things like "property", which behave like Noun, but Verb under cover.

Object created by Class. Class is template, blueprint for object. Like real dictionary book created by telling printer to print from PDF file, Object created by telling Python to create Instance from Class.

Classes can cascade using inheritance. It's like "Squirel - *see Big Book of Biology vol. III*", so you have base book which you can look if you not found entry in current book.

Class - blueprint of object.
Object - generic name for thing created from class.
Instance of Class X - specific object created from specific class X.
Attribute - dictionary entry, Key:Value
Method - Attribute with executable code Value.

Code: Select all

init python:
  #python and renpy ignore everything "#", it's called single-line comment
  #new class TAnt(with parent class, need in RenPy, but can be omited in real python for this case)
  class TAnt(renpy.store.object):
    #this special method __init__ used when you tell Python to create Instance of class TAnt
    #it's always must be called __init__, this how Python understand what to call
    #self, Name, Color is function arguments
    #self is special argument, it automatically added as first argument to every class method call
    #self is variable pointing on object itself
    #it can be called anyway you wish, but better keep it as "self"
    #Name and Color is your arguments used to initialize Ant
    def __init__(self,Name,Color):
      #we set values to keys of object
      self.Name=Name
      self.Color=Color
      #notice we didn't used CalculateValue(self), as self is auto added by python
      CalculateValue()
    #this is method, it calculate and set ant value
    def CalculateValue(self):
      #we set attribute Value of instance self
      self.Value=10
      #methods as function return things, we can skip this part, then function return None
      return self.Value

#world of python is ended, we entered renpy world
start:
  #lines in RenPy world started with $ are python code lines
  #we tell python to create instance of class TAnt, with arguments Name: "Alice" and Color: "Red"
  #now in variable Alice point to object, newly created instance of TAnt
  $Alice=TAnt('Alice','Red')

  #RenPy read from object Alice, value bound to key Name, which is string "Alice"
  "[Alice.Name] is lovely."
return
I'm very bad teacher, so here some better option:
https://www.codecademy.com/learn/python
https://www.quora.com/Which-online-Pyth ... s-the-best - some more

Some code i use is simple (Ant class). Some is harder (mix of methods, dictionaries and inheritance). Some hard code is optional, used in one place, to make other global codes simpler, like with metaclass thing.

If you don't understand some of my code, simple tell "i don't understand this line, please explain". It's ok to not know at start, it's not ok to hide ignorance until it's too late.

Or if you don't want to dive too deep in python, i can stop torturing you and leave you alone :lol:
After all you have some working ways you already understand. Noone really care if game code good looking, bad or ugly, if game itself is good. Not everything i do is good for everyone.
So if my code confuse you too much, simple tell "sorry, i don't understand your code and don't have time to learn", it's normal situation.
This situation is reason why gamedev teams consists of artists, game designers, coders, composers, writers, proofreaders and others. Each guy doing certain role he know.
I may be available for hire, check my thread: viewtopic.php?f=66&t=51350

Euter Space
Newbie
Posts: 9
Joined: Mon Apr 25, 2016 7:26 pm
Contact:

Re: Proof Of Concept - Breeding Game

#12 Post by Euter Space »

Deleted.
Last edited by Euter Space on Thu Dec 02, 2021 3:33 pm, edited 2 times in total.

drKlauz
Veteran
Posts: 239
Joined: Mon Oct 12, 2015 3:04 pm
Contact:

Re: Proof Of Concept - Breeding Game

#13 Post by drKlauz »

Sounds like a bit weird, but nice breeding game coming up sooner or later :D
I may be available for hire, check my thread: viewtopic.php?f=66&t=51350

Euter Space
Newbie
Posts: 9
Joined: Mon Apr 25, 2016 7:26 pm
Contact:

Re: Proof Of Concept - Breeding Game

#14 Post by Euter Space »

Deleted.
Last edited by Euter Space on Thu Dec 02, 2021 3:33 pm, edited 2 times in total.

drKlauz
Veteran
Posts: 239
Joined: Mon Oct 12, 2015 3:04 pm
Contact:

Re: Proof Of Concept - Breeding Game

#15 Post by drKlauz »

Point of using Farm->Box->Ant hierarchy is so Farm and Box doesn't care about what Ant is.
One of core points of using classes is incapsulation. Parent object (Box) don't know and don't care what stored inside it, as long as child behave. All Ant properties (name or color) must be incapsulated inside Ant itself. Only very limited functionality should be shared between Parent object and Child. In case of Box/Ant it's location of specific ant in specific box.

Code: Select all

Box[boxnumber]_[antnumber].name
You can't normally do such thing, most importantly you shouldn't do such thing. It void whole point of using independent boxes and ants. And if you void independence of elements you get big monolithic rigid mess. Once you decide to change something, whole monolith will resist.

Regarding why you can't simple do it. Python translate your written code into internal commands. One of such commands is "Load content stored in variable called X123, bound to memory cell at location 0x12345678". Well, kinda. Anyway, instead of giving name as "Box1_1", you give expression "Box[x]_[y]", and not just expression, but special expression which make sense only in limited area.

You can do this when necessary:

Code: Select all

varname='Box'+str(boxnumber)+'_'+str(antnumber)
ant=globals().get(varname)
ant.name='Bobb'
But it's usually means you doing things very wrong.

Code: Select all

$Boxes[boxnumber].Place(Ant)
By using this approach you decouple Boxes and Ants, and delegate job of moving ants to box class, if you decide to move ant then you simple tell box to do it. It's called delegation. Which is also very useful concept, not only in programming.

If you want simple solution:

Code: Select all

start:
  $boxes=[None]*11
  $boxnumber=2
  $boxes[boxnumber]=TAnt('vini',...colorsetc...)

  "Box [boxnumber] contain [boxes[boxnumber].name]"
It is as simple as possible without sacrificing too much flexibility. You can remove classes completely and use simple dictionaries if you want to manually manipulate properties.

Think how you will move ant. You have Box1_1 variable which contain "vani" fella. Then you decide to add "bobb" fella in box 1, guess you will put him into Box1_2 variable. How will you know it's Box1_2? What will happen when you decide to sell "vani"? Probably "bobb" should move from Box1_2 to Box1_1? How will you know which variables is empty, which must be moved, where they must be moved?
If you want to make building you get bricks and cement em together properly. If you try use sand, then sooner or later (actually sooner) your building will collapse.
Same with your code. Classes, functions, complex data structures are your bricks. You combine simple commands into more complex command. Then you don't write simple commands again, but you your new command. Then you combine such more complex commands. You make sure your bricks are good and use them, you don't reinvent brick every time you need one.

---

Learn basic programming concepts and basic python if you want to make game of any complexity above simple visual novel with couple of flags.

https://www.codecademy.com/learn/python

Programming is not simple knowing how to write code, it's understanding of concepts, paradigms, it's way of thinking, way of approaching problems, ability to recognize and apply patterns.

P.S.: *sacrifice virgin at crossroad* I summon you, Xela, from the darkest depths of the Warp to provide simple to understand solution to problem!.. please? :|
P.P.S.: i have feeling i have more chance to seduce cute jehovah witness door-to-door missionary into bdsm ls than help here, sorry
I may be available for hire, check my thread: viewtopic.php?f=66&t=51350

Post Reply

Who is online

Users browsing this forum: Google [Bot]