Arithmetic Sequence Ignoring Last Step (Subtracting Non-Decimal Currency) [Solved]

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.
Post Reply
Message
Author
verysunshine
Veteran
Posts: 339
Joined: Wed Sep 24, 2014 5:03 pm
Organization: Wild Rose Interactive
Contact:

Arithmetic Sequence Ignoring Last Step (Subtracting Non-Decimal Currency) [Solved]

#1 Post by verysunshine »

I'm working with the old Great British Pound, meaning that currency is written as Pound - Shilling - Pence. This is similar to the way money works in Harry Potter (Galleon - Sickle - Knut). There are 12 pence in a shilling and 20 shillings in a pound.

Adding this stuff is easy. Just add the number, check to see if any of the values are over what they should be, and if they are, round it up.

Subtraction is more complicated. The steps should be:

1. Subtract the number from pence, as all transaction amounts are in pence
2. If pence < 0, subtract the correct number of shillings and add the related number of pence
3. if shillings is < 0, subtract the correct number of pounds and add the related number of shillings
4. If pounds is <= 0, reset the transaction and say something has gone wrong


This results in the following code:

Code: Select all

        if transaction_pence > (pence + (shilling * 12) + (pound * 240)):
            jump nosale
        $ pence = pence + transaction_pence
        if pence <= 0:
            $ shilling += (transaction_pence / 12)
            $ pence -= ((transaction_pence / 12)+1)*12
        if shilling < 0:
            $ pound += (transaction_pence / 240)
            $ shilling -= ((transaction_pence / 240)+1)*20
            
So, if you have 0 pounds 3 shillings 0 pence and want to subtract 5 pence, the steps would be:
1. Subtract 5 pence, (0, 3, -5)
2. Pence is negative, so remove 1 shilling from the shillings
3. add 12 pence to the pence
3. Shillings is positive, so nothing happens

This gives the correct result of 0, 2, 7. (Excuse the lack of currency symbols.)

Instead, the code gives me 0, 2, -5

Code: Select all

        if pence <= 0:
            3 += (-5 / 12)  = 2
            -5 - ((-5 / 12)+1)*12
            	-5 += (-0+1)*12
            	-5 += 1*12
            	-5 + 12 = 7
        if 2 < 0: it is positive, nothing more to do
 
Why is the code ignoring the addition at the end?
Last edited by verysunshine on Thu Feb 15, 2018 6:09 pm, edited 2 times in total.

Build the basics first, then add all the fun bits.

Please check out my games on my itch.io page!

irredeemable
Regular
Posts: 78
Joined: Thu Feb 08, 2018 7:57 am
Contact:

Re: Arithmetic Sequence Ignoring Last Step (Subtracting Non-Decimal Currency)

#2 Post by irredeemable »

Didn't check your code, but what you want to do in this situation is handle everything in the smallest denomination, internally. So all of your interactions with shops or whatever would be in terms of pence, then you'd convert when you needed to display. Conversion is simple enough: pounds = pence / 240, shillings = pence % 240 / 12, pence = pence % 240 % 12.

Code: Select all

label start:
    $ pence = 1337
    $ renpy.say("Ye Olde Englishman", "I have {0} pounds, {1} shilling, and {2} pence.".format(pence / 240, pence % 240 / 12, pence % 240 % 12))

verysunshine
Veteran
Posts: 339
Joined: Wed Sep 24, 2014 5:03 pm
Organization: Wild Rose Interactive
Contact:

Re: Arithmetic Sequence Ignoring Last Step (Subtracting Non-Decimal Currency)

#3 Post by verysunshine »

irredeemable wrote: Thu Feb 15, 2018 3:28 am Didn't check your code, but what you want to do in this situation is handle everything in the smallest denomination, internally. So all of your interactions with shops or whatever would be in terms of pence, then you'd convert when you needed to display. Conversion is simple enough: pounds = pence / 240, shillings = pence % 240 / 12, pence = pence % 240 % 12.

Code: Select all

label start:
    $ pence = 1337
    $ renpy.say(None, "I have {0} pounds, {1} shilling, and {2} pence.".format(pence / 240, pence % 240 / 12, pence % 240 % 12))
I was already holding my transactions in pence internally. "transaction_pence" was used to handle division. When I was initially writing this code, I forgot that dividing in python will give you an integer.

Your code works perfectly! I did tweak it a bit to fit different uses, as renpy.say doesn't always work, and threw in the correct symbols.

Code: Select all

text "Money: {0}£, {1}s, and {2}d.".format(pence / 240, pence % 240 / 12, pence % 240 % 12)
On a less serious note, did you choose that number randomly? It spells "leet". ( Fun fact: leet pence would be 5 pounds, 11 shillings, and 5 pence.)

Build the basics first, then add all the fun bits.

Please check out my games on my itch.io page!

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Arithmetic Sequence Ignoring Last Step (Subtracting Non-Decimal Currency) [Half-Solved]

#4 Post by Remix »

You (as irredeemable says) want to hold all values as one variable based on the lowest denominator, e.g. player_pence, item_cost_pence etc.

If a player has 1337 pence, you can easily test of he can afford something for 2526 pence ( 1337 >= 2526 ? = No )
If he spends 584 pence, you can easily calculate how much he has left

Then just use a function for displaying those pence where-ever needed:

Code: Select all

init python:
    # note: 1000 denotes max pounds
    # increase if you use over that number (or add sovereigns, guineas or whatever they were called by adding more indices to the radices)
    def number_to_mixed_radix(number, radices=(1000,20,12)):
        result = [0]*(len(radices))
        for i in range(len(radices)-1, -1, -1):
            result[i] = number % radices[i]
            number = number / radices[i]
        return result
     
    # You should not need this fuinction, just added for completeness
    def mixed_radix_to_number(radix_number, radices=(1000,20,12)):
        result = 0
        for i in range(len(radices)):
            result = result * radices[i] + radix_number[i]
        return result

label start:
    $ v = renpy.random.randint(0, 1000)
    
    $ r = number_to_mixed_radix( v )
    "Pence to Mixed: [v] >>> [r]"

    $ s = mixed_radix_to_number( r )
    "Mixed to Pence: [r] >>> [s]"

    jump start
Frameworks & Scriptlets:

verysunshine
Veteran
Posts: 339
Joined: Wed Sep 24, 2014 5:03 pm
Organization: Wild Rose Interactive
Contact:

Re: Arithmetic Sequence Ignoring Last Step (Subtracting Non-Decimal Currency) [Half-Solved]

#5 Post by verysunshine »

Remix wrote: Thu Feb 15, 2018 6:51 am

Code: Select all

init python:
    # note: 1000 denotes max pounds
    # increase if you use over that number (or add sovereigns, guineas or whatever they were called by adding more indices to the radices)
    def number_to_mixed_radix(number, radices=(1000,20,12)):
        result = [0]*(len(radices))
        for i in range(len(radices)-1, -1, -1):
            result[i] = number % radices[i]
            number = number / radices[i]
        return result
     
    # You should not need this fuinction, just added for completeness
    def mixed_radix_to_number(radix_number, radices=(1000,20,12)):
        result = 0
        for i in range(len(radices)):
            result = result * radices[i] + radix_number[i]
        return result

label start:
    $ v = renpy.random.randint(0, 1000)
    
    $ r = number_to_mixed_radix( v )
    "Pence to Mixed: [v] >>> [r]"

    $ s = mixed_radix_to_number( r )
    "Mixed to Pence: [r] >>> [s]"

    jump start
Your code does everything it's supposed to, and unlike irredeemable's, it displays in a menu because of the substitution.

Code: Select all

label storetest:
    $ r = number_to_mixed_radix( pence )
    menu:
        "Pence to Mixed: [pence] >>> [r]"
        "Add 5d.":
            $ pence += 5
        "Add 1s.":
            $ pence += 12
        "Add 50d.":
            $ pence += 50
        "Subtract 5d.":
            $ pence -= 5
        "Subtract 1s.":
            $ pence -= 12
        "Subtract 50d.":
            $ pence -= 50
        "Clear funds":
            $ pence = 0
    jump storetest
One problem: I want to display the result as "5£ 11s 5d", not "[5, 11, 5]". It appears I can't split up the result (radix?) into its components to add the letters, and because I don't know what kind of method is being used, I don't know where the brackets surrounding "[5, 11, 5]" are coming from.

Build the basics first, then add all the fun bits.

Please check out my games on my itch.io page!

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Arithmetic Sequence Ignoring Last Step (Subtracting Non-Decimal Currency) [Half-Solved]

#6 Post by Remix »

verysunshine wrote: Thu Feb 15, 2018 2:35 pm One problem: I want to display the result as "5£ 11s 5d", not "[5, 11, 5]". It appears I can't split up the result (radix?) into its components to add the letters, and because I don't know what kind of method is being used, I don't know where the brackets surrounding "[5, 11, 5]" are coming from.
The return of the number_to_mixed_radix( pence ) call is a python list. Just a sequence of numbers stored as a list type, denoted by the [ and ] symbols.

Code: Select all

# format method, basically expands the list to fit the {n} bits...
r = "{0}£ {1}s {2}d".format( *number_to_mixed_radix( pence ) )

# by index
r = number_to_mixed_radix( pence )
t = "[r[0]]£ [r[1]]s [r[2]]d"
If you *always* display the result as "n£ ns nd" it would likely be best to just alter the return of the radix function

Code: Select all

    
    def number_to_mixed_radix(number, radices=(1000,20,12)):
        result = [0]*(len(radices))
        for i in range(len(radices)-1, -1, -1):
            result[i] = number % radices[i]
            number = number / radices[i]
        return  "{0}£ {1}s {2}d".format( *result )
        
# or 

    def number_to_lsd_string(number):
        radices = (1000,20,12)
        result = [0]*3
        for i in [2,1,0]:
            result[i] = number % radices[i]
            number = number / radices[i]
        return  "{0}£ {1}s {2}d".format( *result )
Frameworks & Scriptlets:

verysunshine
Veteran
Posts: 339
Joined: Wed Sep 24, 2014 5:03 pm
Organization: Wild Rose Interactive
Contact:

Re: Arithmetic Sequence Ignoring Last Step (Subtracting Non-Decimal Currency) [Half-Solved]

#7 Post by verysunshine »

Remix wrote: Thu Feb 15, 2018 4:46 pm
verysunshine wrote: Thu Feb 15, 2018 2:35 pm One problem: I want to display the result as "5£ 11s 5d", not "[5, 11, 5]". It appears I can't split up the result (radix?) into its components to add the letters, and because I don't know what kind of method is being used, I don't know where the brackets surrounding "[5, 11, 5]" are coming from.
The return of the number_to_mixed_radix( pence ) call is a python list. Just a sequence of numbers stored as a list type, denoted by the [ and ] symbols.

Code: Select all

# format method, basically expands the list to fit the {n} bits...
r = "{0}£ {1}s {2}d".format( *number_to_mixed_radix( pence ) )

# by index
r = number_to_mixed_radix( pence )
t = "[r[0]]£ [r[1]]s [r[2]]d"
If you *always* display the result as "n£ ns nd" it would likely be best to just alter the return of the radix function

Code: Select all

    
    def number_to_mixed_radix(number, radices=(1000,20,12)):
        result = [0]*(len(radices))
        for i in range(len(radices)-1, -1, -1):
            result[i] = number % radices[i]
            number = number / radices[i]
        return  "{0}£ {1}s {2}d".format( *result )
        
# or 

    def number_to_lsd_string(number):
        radices = (1000,20,12)
        result = [0]*3
        for i in [2,1,0]:
            result[i] = number % radices[i]
            number = number / radices[i]
        return  "{0}£ {1}s {2}d".format( *result )
I'll always be displaying the result that way, so that display format is perfect. Thank you. Now I know a little bit more about how lists work!

Build the basics first, then add all the fun bits.

Please check out my games on my itch.io page!

irredeemable
Regular
Posts: 78
Joined: Thu Feb 08, 2018 7:57 am
Contact:

Re: Arithmetic Sequence Ignoring Last Step (Subtracting Non-Decimal Currency) [Half-Solved]

#8 Post by irredeemable »

I only intended to demonstrate how to do the conversion. At any rate, if you wanted to put it in a menu for some reason it's just as easy to set a variable equal to (pence / 240) as it is to set a variable equal to the value of some function. If you think you're going to be using those strings very often, though, try this:

Code: Select all

init python:
    class Purse(renpy.store.object):
        def __init__(self, pence=0):
            self.wealth = pence

        @property
        def wealth(self):
            return self._wealth
        @wealth.setter
        def wealth(self, value):
            self._wealth = value
            self.l = str(value / 240)
            self.s = str(value % 240 / 12)
            self.d = str(value % 240 % 12)
            self.tally = "{0}£ {1}s {2}d".format(self.l, self.s, self.d)

default purse = Purse(500)

label start:
    "I have [purse.tally]."
    $ purse.wealth += 250
    "Now I have [purse.l] pounds, [purse.s] shillings, and [purse.d] pence."

verysunshine
Veteran
Posts: 339
Joined: Wed Sep 24, 2014 5:03 pm
Organization: Wild Rose Interactive
Contact:

Re: Arithmetic Sequence Ignoring Last Step (Subtracting Non-Decimal Currency) [Half-Solved]

#9 Post by verysunshine »

irredeemable wrote: Thu Feb 15, 2018 5:02 pm I only intended to demonstrate how to do the conversion. At any rate, if you wanted to put it in a menu for some reason it's just as easy to set a variable equal to (pence / 240) as it is to set a variable equal to the value of some function. If you think you're going to be using those strings very often, though, try this:

Code: Select all

init python:
    class Purse(renpy.store.object):
        def __init__(self, pence=0):
            self.wealth = pence

        @property
        def wealth(self):
            return self._wealth
        @wealth.setter
        def wealth(self, value):
            self._wealth = value
            self.l = str(value / 240)
            self.s = str(value % 240 / 12)
            self.d = str(value % 240 % 12)
            self.tally = "{0}£ {1}s {2}d".format(self.l, self.s, self.d)

default purse = Purse(500)

label start:
    "I have [purse.tally]."
    $ purse.wealth += 250
    "Now I have [purse.l] pounds, [purse.s] shillings, and [purse.d] pence."
Thanks. I didn't realise you were only explaining how to do the conversion since your code worked as actual code. The use of "renpy.say" should have tipped me off. As far as I know, the numbers are only going to be displayed in a few places, but that could change.

Build the basics first, then add all the fun bits.

Please check out my games on my itch.io page!

Post Reply

Who is online

Users browsing this forum: apocolocyntose, DewyNebula