Talk:Can you modify experience outside of battle with plotscripting?

From OHRRPGCE-Wiki
Jump to: navigation, search

Heh... worth asking. I knew that you could modify levels that way... The easiest way to add XP is a 'fake' fight with an enemy with incredible speed with a suicidal attack. Not the most noble way to do so...


NeoTA: it should be doable, like this:

set hero experience( heronum, high, low)
get hero experience hi( heronum)
get hero experience lo( heronum)

.. get* commands would take the high and low 16 bits of the exp, respectively. so 'high' is the number of 65536's, and low is the number of ones. Low is 'unsigned'( so the set command has to remap -32767 - +32768 to 0 - 65535, since all numbers in scripts are signed.). add hero experience would be similar to set. a simple hack.

TMC: But it's too complicated to be understood by most. They wouldn't understand how to use the two variables.

I suggested a simple command to add experience, and I suppose subtract it too, in the range -32768 to 32767. This way, you could reward the player (which is what you normally want to do with experience). The command would have an optional argument to not level a hero when they reached the right amount of experience, and return the amount actually subtracted/added.

Also, a command to correctly adjust level. These would improve experience to the possition of money.

NeoTA: ok, sneakier hack:

set hero experience( Hero:Bob, 1,000,000,000)

add hero experience( Hero:Bob, 1,000,000,000)

With 5 parameters, the last 4 creating the number (as it would be written with commas every third digit from right). The last 3 parameters would be optional and default to 32767. this would be used to detect the end of the pseudo-number.

Mike: Um... wow, that's clever. But, not everyone's used to typing commas in numbers, much less in any sort of scripting. However, there's something you're missing: the highest experience one can aquire is 51183838. Rather, that's the experience required to get to level 100. So, we wouldn't need 4 number parameters. In fact, it could be dangerous, since:

set hero experience( Hero:Bob, 2,147,483,648) (note that it's the max + 1)

would cause an overflow.

Bob: How about we implement NeoTA's high/low suggestion as "advanced" commands, and then use those as a base to implement the other suggestions in hamsterspeak? (same for gold also)

Patsen: It sounds solid... Being able to modify experience out of combat allows for non-murder based experience. Considering I'm currently working on a D&D based engine, it would be quite an asset. I read of a way to adjust levels, but that's dodgy at best. Even combatless games could enjoy some way of gaining experience, with levels being a parameter for out of combat random things, or simply a score of some sort. Regardless, I'd love hearing news on development of the like. Flawless code being nigh impossible, clever hacks show a programmer's guile.

Patsen: In reality, I should log in before posting. In reply to NeoTA's post, he claims it's already possible. I just want to make sure, I'm still working on stats before I start any scripting, so I'd like to know what I have to work with before I start.

NeoTA: I meant it is possible to implement.

My other suggestions have to be hardcoded too, cause they require division by 65536. TMC's suggestions could work ok written in HS.

TMC: D'oh. I suggested the 1,000,000,000 trick elsewhere and forgot about it.

Hard coding them is not necessary. Firstly, you can divide by 65535 with signed shorts (if you are sneaky), but is there a real need to remap the number range anyway? Why not just have the highno as exp/32768?

Mike: Heh,

Being able to modify experience out of combat allows for non-murder based experience.

Is it really murder, since they ambush you? ;)

In any case, at least some command needs to be hard coded. I don't think we can hijack get/setherostat(). Well, actually, we could, now that I think about it.

Hmm, the implementation of the 1,000,000,000 Exp Function*... Urgh, not only do we need to work with the seprate Words, we need to convert from the "Decimal Words" to the "Binary Words". And given the small number space, I suspect it'll be easier to hard code.

* - Attempted parody of the $64,000 Question (or should it be the $65536 Question? ;) )

NeoTA: Ok, I have a prototype in Python. The only python-ism it uses are lists (ie. you know the number of 'fragments' in advance rather than having to look for the first 32767.)

Prototype follows:

"""Prototype of conversion decimal-list to number
for 'set hero experience' command"""


# a list of testcases.
# Termination is implied and is needed for the actual HSpeak stuff.
# 
testcases = [
   [123], 
   [  2,345],
   [111,012],
   [  1,234,456],
   [ 55,444,333],
   [ 999,999,999,999,999,999,999], #silliness. python handles it correctly.
]

def dec2num(dec):
   """Unhack a 1,234,456 format number into an ordinary integer.
   Accepts any sequence (eg. list, tuple)
   """
   #find the length
   declen = len(dec)
   mul = 1
   #decide the multiplier for the first fragment
   while (declen > 1):
       mul = mul * 1000
       declen -= 1
   n = 0
   index = 0
   # add the fragments in, highest-first
   while (mul > 0):
       n += dec[index] * mul
       index += 1
       mul /= 1000

   return n

# try each testcase
for tc in testcases:
   print (tc, dec2num(tc) )


The logged results:

([123], 123)
([2, 345], 2345)
([111, 10], 111010)
([1, 234, 456], 1234456)
([55, 444, 333], 55444333)
([999, 999, 999, 999, 999, 999, 999], 999999999999999999999L)

Mike: That's all well and good, but that won't work in HamsterSpeak, even if we try to translate it. Doing it in QB is no problem.

Hmm, on a side note, it seems that Python has the array behaviour that TMC wants. I.e. you can treat your entire argument list as an array (unless, of course, you have to wrap a tuple in [] before you can pass it...)

NeoTA: For the 'args as array' form that you want, you would:

def yourfunc( *args): # 
    # Stuff goes here

then when you wanted to call it:

# assume args is a tuple of arguments.
# I'll assign it here to clarify
yourfunc( 0, 1,2,3) # so in yourfunc, args becomes the tuple (0,1,2,3)
# you can also unpack a sequence, which is functionally equivalent to writing it out manually
args = (0,1,2,3)
yourfunc( *args)


Or you mean the scripting arguments? That's implemented as a tuple in Jormungand. Some of the scripting functions are working. that looks simpler, like :

def setherowalkpalette(v):
   hero, palette = v[0], v[1]
   # do stuff
args = (0, 16)
setherowalkpalette( args ) # this is the convention required by HS, because  default-values are handled by the HS interpreter rather than the Python interpreter.

Also, the difference between lists and tuples is that tuples are immutable, and hence can only contain hashable objects. And tuples are (val, val, val) whereas lists are [val,val,val]

Mike: I didn't ask for a complete description of tuples vs lists, and the methods of passing them. It just... never mind. My first statement still stands.

NeoTA: Certainly. I'm opportunistic.

TMC: HS can too! This prototype generates two numbers for a setexp function, where exp is high * 32768 + low. Just divert your eyes from the screen to avoid retina burns

define script (-1, set hero experience, 0, -1, -1, -1)
script, set hero experience, who, n1, n2, n3, begin
 while (n3 == -1) do (
  n3 := n2  
  n2 := n1
  n1 := 0
 )

  #convert from val = 1000000*n1 + 1000*n2 + n3 to val = 2^20*n1 + 2^10*n2 + n3
 n3 -= n2 * 24    
 n2 += n3 / 1024
 n3 := n3 ,mod, 1024

 n3 -= n1 * 448   #this is (2^20 = 1,048,576) - 1,000,000
 n2 -= n1 * 47

 n2 += n3 / 1024
 n3 := n3 ,mod, 1024
 if (n3 << 0) then (n3 += 1024, n2 -= 1)
 n1 += n2 / 1024
 n2 := n2 ,mod, 1024
 if (n2 << 0) then (n2 += 1024, n1 -= 1)

 variable(vallow, valhigh)
 valhigh := n1 * 32 + n2 / 32
 vallow := (n2 ,mod, 32) * 1024 + n3
 #set experience(who, valhigh, vallow)
)

This isn't suitable for setting money because it overflows if roughly n1 > 70

Ok, I admit it, I did that only for fun.

Mike: O_O *rubs eyes* My brain... not follow...
CAN NOT COMPUTE. GENERAL PROTECTION FAULT AT 0x82384

Patsen: Wow... a complex algorithm depending on constants calculated from seven digit arithmetic with little to no real explanations of the math behind it and why it works... If my degree weren't so entwined with math, I wouldn't even try to decypher it!

32 bit[edit]

Isn't Hamsterspeak 32 bit now? Can we remove the bit about 16 bit limitations, and make a simple plotscripting command to get the hero's experience if it isn't already there? (If it is there, we should document it properly here)