nhguy03276 Posted January 30, 2017 Share Posted January 30, 2017 I have the need to Display 26 items from a Formlist of 60 items, and I want each time they are displayed, for the display to pick a random 26 from the list, without them repeating... It took me the better part of the day to figure out a way to do it, but it seems highly convoluted, and there has to be a simpler method of getting a list of non-repeating numbers... However, The following does work. Function SelectPaintingstoDisplay() int i = Pas_CanBeDisplayed.getsize() int k = 0 while k < i Pas_IsBeingDisplayed.addform(Pas_CanBeDisplayed.GetAt(k)) k +=1 EndWhile int J = 0 While J < 26 int L = Pas_IsBeingDisplayed.getsize() L -=1 int Jindex = utility.randomInt(0,L) Form kReference = Pas_IsBeingDisplayed.GetAt(Jindex) As Form AddBooks(kReference, 1) Pas_IsBeingDisplayed.RemoveAddedForm(kReference) J +=1 Endwhile Pas_IsBeingDisplayed.Revert() EndFunction Does anyone know of a way that doesn't take the long way? Link to comment Share on other sites More sharing options...
irswat Posted January 30, 2017 Share Posted January 30, 2017 looks pretty efficient Link to comment Share on other sites More sharing options...
NexusComa Posted January 31, 2017 Share Posted January 31, 2017 Beautiful little function. Great work. Link to comment Share on other sites More sharing options...
monsto Posted January 31, 2017 Share Posted January 31, 2017 Papyrus is about half a language. I mean the while versus for loop argument in any language can rage for time immemorial, but there are definitely preferential use cases for both. But you only have while loops here and without a break command. All the hard limitations on the length of arrays. And then there's the general single threaded nature of the entire thing. Consequently, and it's been my experience -- especially over the last few days -- that if you've done something, but you think it's kludgy, and you're wondering if there's a better way to do it? Probably not. However, you might look into JContainers or PapyrusUtil for your backend storage. JContainers allows basically json-like data-mapping, and PapyrusUtil does not but can be directly attached to a form and has lots of little helper methods that JContainers does not. TBPH in my little GalleryCam mod i'm using them both sidebyside because of each of their strengths. Anyway, storing your formlist in a JC construct or directly on an in-game entity with PU (they both have special types for forms) will likely greatly simplify how you deal with the whole thing. In my mod, i have an camera positions in a 2 dimensional JC array... index at the top, with a map of key/value pairs on each index of the array. The user can add/remove camera positions on the list. A "random tour" reads the length of the list, chooses one, gets the data off the position, and uses it for the char. It sounds like you could have a similar thing. Have your 60 paintings (is it?) as assets/forms and your list of Property entries. OnInit, fill a JC Array (so that you get position keys) with the info you need for all 60 items. Then when you need your 26, you do a "while < 26" with Utility.RandomInt(60) and read the entries. I just last night finally got my head wrapped around JC. A couple weeks ago, I got my head wrapped around PU. I'd be happy to help if you have any questions. (Just ask here for the discussion aspect) Link to comment Share on other sites More sharing options...
irswat Posted January 31, 2017 Share Posted January 31, 2017 Maybe you could create a Jcontainers tutorial. I'd love to make a shift from arrays upon arrays to something more efficient. Link to comment Share on other sites More sharing options...
monsto Posted January 31, 2017 Share Posted January 31, 2017 Maybe you could create a Jcontainers tutorial. I'd love to make a shift from arrays upon arrays to something more efficient. I dunno about all that. I got enough of it to understand it, but the deeper features and interactions are beyond me because i didn't need them. What did you want to know about it? Maybe I can help any a different way. Link to comment Share on other sites More sharing options...
Surilindur Posted January 31, 2017 Share Posted January 31, 2017 (edited) Edit: Hmm. Well. I moved the thing to a spoiler. It does not produce random variables at all now that I think of it. Sorry. :blush: Your idea is already quite good. It does not even use Array.Find which is great. I have not tested this at all, but maybe something like the following would work as an idea (SKSE is required for array creation)? Not too random, though, but something at least. If it works. It is just an idea! It could be that it fails miserably, and probably will do exactly that. :tongue: Int[] Function RandList(Int n, Int a=0, Int b=100) Float md = Math.Abs((a + b) / 2) Float dv = Math.Abs(b - md) Int[] NumArr = Utility.CreateIntArray(n, (md as Int)) Float h = 180.0 / (n - 1) While (n > 0) n -= 1 NumArr[n] += ((Math.Cos(180.0 - (n * h)) * dv) as Int) If (n + 1 < NumArr.Length && NumArr[n] == NumArr[n+1]) NumArr[n] += 1 ; if the rounded number is the same as the previous one? EndIf EndWhile Return NumArr EndFunction Edited January 31, 2017 by Contrathetix Link to comment Share on other sites More sharing options...
Surilindur Posted February 1, 2017 Share Posted February 1, 2017 (edited) Finally cracked it! :dance: Sort of. It took some thinking, but if you want to generate a list of all numbers between a and b, and shuffle them, then the following script should do the trick. I have not tested the script itself (yet), but the Python version works. The Python version edit: that finally works with all sorts of a and b as long as b is larger than a: import random def random_list(a=0, b=100): b = b - a l = [0] * b i = 0 while (i < b): k = random.randint(0, i) l[i] = l[k] l[k] = i + a i += 1 return l if __name__ == '__main__': o = random_list(-7, -2) print(o) The Papyrus version (untested): Int[] Function ShuffledIntList(Int a=0, Int b=100) b = b - a Int i = 0 Int k Int[] NumArr = Utility.CreateIntArray(b) While (i < b) k = Utility.RandomInt(0, i) NumArr[i] = NumArr[k] NumArr[k] = i + a i += 1 EndWhile Return NumArr EndFunctionIf you need n numbers from [x,y] you could just generate the whole shuffled list from x to y and use the first n numbers from it. Function PrintFirstN(Int n, Int x, Int y) Int[] Shuffled = ShuffledIntList(x, y) While (n > 0) n -= 1 Debug.MessageBox(Shuffled[n]) EndWhile EndFunctionHopefully that helps a bit. :smile: Edited February 1, 2017 by Contrathetix Link to comment Share on other sites More sharing options...
nhguy03276 Posted February 1, 2017 Author Share Posted February 1, 2017 ...that if you've done something, but you think it's kludgy, and you're wondering if there's a better way to do it.... Kludgy... Probably the best description of Papyrus I've heard yet. I've been a hobby programmer off and on since the time of Commodore 64 basic, (no expert programmer, but know enough to know there it a right way, a wrong way, and a nuckin kludgy way to write script...) and Papyrus has got to be one of the worst languages I've ever had to work with. It seems Bethesda took great pleasure in creating a language replete with "you can't get there from here" functions, and making things that should be straight forward simple the most complicated headache possible. As for the Jcontainers, I'll start looking into them... I think they might be that piece I felt was missing. As for those of you complimenting what I did in my posted script, Thank you. Link to comment Share on other sites More sharing options...
Recommended Posts