Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

[help] Draw without replacement

Hello everyone, I m sorry but I ask again for your help. :p My problem is as follows : In my game we have a Poush with 42 pieces : 3 red 6 green 12 blue 18 white 3 black In the game we take one or two or three, etc, pieces in once and we chose what colore we need. In roll 20 we don't have the possibility to draw in a poush without remplacement If you have a solution to this probleme I will love to read it. Thx for reading Ps : I french and my english is not perfect ^^
1587392125
The Aaron
Roll20 Production Team
API Scripter
If I understand correctly, you have a pouch with 42 colored pieces in it, and each player is choosing so many pieces from it of the color they desire. You could create a Deck with Cards for each color, and allow players to choose the cards from it that they need.  That should get you the same behavior as the above. Another option is to create tokens for each color and put them on the table, then let players drag those tokens to a zone that is designated as theirs. Hopefully I understood that correctly and this is helpful. If not, definitely post back and we can look for more solutions.
1587399486

Edited 1587400086
The draw are random The card systeme need more and more manipulation to draw, call back, and mix for me, I need a more smooth solution, because I need concetration on my game . Is-it not possible to have an API to make this ? In math is just (for two) : var listeblattes = [a,b,c,d,e,f] var firstDraw = listeBlattes[random(0, listeblattes.length)] var subList = listeblattes.copy().remove(firstDraw ) var secondDraw = subList [random(0, subList.length)]
1587400369
The Aaron
Roll20 Production Team
API Scripter
Oh, I'm sorry, I missed that this was for the API. Yes, the API can definitely handle doing this, it's just a question of the interface. It sounds like the operations you need are: Player takes a piece at random, if any are available.  Possibly more than one. Player returns one or more pieces GM recalls all pieces. Players need to know: Which pieces they have and how many GMs need to know who has what. Do players need to know which pieces the other players have?
1587418493

Edited 1587464897
The players don't need to keep the piece. For exemple : my player want figth some guy. I ask him a test, he has 4 on "melee" and the guy has 2 on "defense" . My player have "+2" to touch the guy. He take 2 pieces on poush and keep the best value. He puts back the pieces in the poush.
1587534781
The Aaron
Roll20 Production Team
API Scripter
Here is an extremely rough proof of concept script just to make sure I understand what you're looking for correctly: Call it like this: !pick <number> Example: !pick 3 It will output the results of picking the 3 pieces: Results: black, green, white Source: on('ready',()=>{ const stones = { red: 3, green: 6, blue: 12, white: 18, black: 3 }; const getPouch = ()=>Object.keys(stones).reduce( (m,k)=> [...m, ...Array(stones[k]).fill(k)], []); on('chat:message',(msg)=>{ if('api'===msg.type && /^!pick(\b\s|$)/i.test(msg.content)){ let cmd = msg.content.split(/\s+/); let num = parseInt(cmd[1])||1; let pouch = getPouch(); let picks = []; for(let n = 0; (n<num) && (pouch.length > 0); ++n){ let idx = randomInteger(pouch.length); picks.push(pouch[idx-1]); pouch = pouch.filter((v,i)=>i!==(idx-1)); } sendChat('',`Results: ${picks.join(', ')}`); } }); }); Let me know if that does what you're expecting, and we can see how to improve it. =D
You are the best men on this Earth ! =) This is perfect ! But if I can abuse your kindness, is it possible to have a coloring of the texts ? Thx a lot for all your answer !
1587560865
The Aaron
Roll20 Production Team
API Scripter
Ah, great!  I wanted to make sure I had the right process first before putting too much time into polishing it. Adding color to the text is easy.  I can also add images, if you have some examples of what you would want.
Realy ? I make it this nigth and I take to you ^^
1587578101
The Aaron
Roll20 Production Team
API Scripter
Sounds good!
1587578147
The Aaron
Roll20 Production Team
API Scripter
Also, what game system is this for?  If it's a published one, it would be nice to provide this script for the wider public so they can use it in their games. 
This système is for "Insectopia" a french game who you are Insect or spider in a long future =)
1587583021
The Aaron
Roll20 Production Team
API Scripter
Sounds good!  I'll get you a better version tonight.  Do players ever need to draw in secret, and only show their results to the GM, or blindly hand then cards or anything?
If he can have choice its better ^^ especially for me ;)
1587599223
The Aaron
Roll20 Production Team
API Scripter
Ok, here you are! You can get a selection of pieces using !pick.&nbsp; You can optionally follow it with a number to pick that many.&nbsp; If you don't specify a number, it picks 1. !pick 4 You can optionally follow that with -- and some text: !pick 4 -- Whoo the Queen of the Bees And it will preface the pick with that text: You can use 3 alternate commands: !wpick 4 -- Whispered to the GM and the Player !bpick 4 -- Results sent to the GM, description sent to chat !bwpick 4 -- Results sent to the GM, description whispered to the Player Finally, if you hover any of the picks, it will show you the full sized image: The Code: on('ready',()=&gt;{ const pieces = { red: { name: "Red", image: "<a href="https://s3.amazonaws.com/files.d20.io/images/126044952/9GdBdkOdF5vhPR3fNhvQag/original.jpg?1587581906" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/126044952/9GdBdkOdF5vhPR3fNhvQag/original.jpg?1587581906</a>", num: 3 }, green: { name: "Green", image: "<a href="https://s3.amazonaws.com/files.d20.io/images/126044950/qTuLyFGYDXhu9A_Tzdn6lQ/original.jpg?1587581906" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/126044950/qTuLyFGYDXhu9A_Tzdn6lQ/original.jpg?1587581906</a>", num: 6 }, blue: { name: "Blue", image: "<a href="https://s3.amazonaws.com/files.d20.io/images/126044947/3TVwHcYoAy4HCA-nyK21RA/original.jpg?1587581906" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/126044947/3TVwHcYoAy4HCA-nyK21RA/original.jpg?1587581906</a>", num:12 }, white: { name: "White", image: "<a href="https://s3.amazonaws.com/files.d20.io/images/126044948/9epZ-YPwc_RMQMUOa7qtBA/original.jpg?1587581906" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/126044948/9epZ-YPwc_RMQMUOa7qtBA/original.jpg?1587581906</a>", num: 18 }, black: { name: "Black", image: "<a href="https://s3.amazonaws.com/files.d20.io/images/126044951/eGCv4J08ul7TkyDE0psDUw/original.jpg?1587581906" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/126044951/eGCv4J08ul7TkyDE0psDUw/original.jpg?1587581906</a>", num: 3 } }; const styles = { bspan: 'display:block;', imgTitle: 'font-weight:bold;text-align:center;', img: 'max-width: 2em; max-height: 3em;width:auto;height:auto;border:1px solid #999;float:left;margin: .1em; display: inline-block; float: left;', wrapper: "border: 1px solid #999; background-color:#ffffee; padding: .5em; border-radius: .5em;", desc: "font-weight: bold; padding: .2em; font-size 1.1em;", msg: "padding: .5em;" }; const HE = (() =&gt; { const esRE = (s) =&gt; s.replace(/(\\|\/|\[|\]|\(|\)|\{|\}|\?|\+|\*|\||\.|\^|\$)/g,'\\$1'); const e = (s) =&gt; `&amp;${s};`; const entities = { '&lt;' : e('lt'), '&gt;' : e('gt'), "'" : e('#39'), '@' : e('#64'), '{' : e('#123'), '|' : e('#124'), '}' : e('#125'), '[' : e('#91'), ']' : e('#93'), '"' : e('quot') }; const re = new RegExp(`(${Object.keys(entities).map(esRE).join('|')})`,'g'); return (s) =&gt; s.replace(re, (c) =&gt; (entities[c] || c) ); })(); const makeImageTitle = (k) =&gt; `&lt;span style="${styles.bspan}"&gt;&lt;span style="display:block;background-image: url('${pieces[k].image}');background-repeat: no-repeat;height:247px;width:169px;"&gt;&lt;/span&gt;&lt;span style="${styles.imgTitle}"&gt;${pieces[k].name}&lt;/span&gt;&lt;/span&gt;`; const makeImage = (k) =&gt; `&lt;span class="showtip tipsy" title="${HE(HE(makeImageTitle(k)))}"&gt;&lt;img style="${styles.img}" src="${pieces[k].image}" alt="${pieces[k].name}"&gt;&lt;/span&gt;`; const wrapImages = (t) =&gt; `&lt;div style="${styles.wrapper}"&gt;${t}&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;/div&gt;`; const desc = (d) =&gt; d.length ? `&lt;div style="${styles.desc}"&gt;${d}&lt;/div&gt;` : ''; const buildMsg = (d,i) =&gt; `&lt;div style="${styles.msg}"&gt;${desc(d)}${i}&lt;/div&gt;`; const getPouch = ()=&gt;Object.keys(pieces).reduce( (m,k)=&gt; [...m, ...Array(pieces[k].num).fill(k)], []); on('chat:message',(msg)=&gt;{ if('api'===msg.type){ let match = msg.content.match(/^!(b|w|bw|)pick(?:\b\s|$)/i); if(!match){ return; } let who = (getObj('player',msg.playerid)||{get:()=&gt;'API'}).get('_displayname'); let parts = msg.content.split(/\s+--\s+/); let cmd = parts[0].split(/\s+/); let pouch = getPouch(); let num = Math.min(parseInt(cmd[1])||1,pouch.length); let picks = []; for(let n = 0; (n&lt;num) &amp;&amp; (pouch.length &gt; 0); ++n){ let idx = randomInteger(pouch.length); picks.push(pouch[idx-1]); pouch = pouch.filter((v,i)=&gt;i!==(idx-1)); } let output = buildMsg( parts[1]||'', wrapImages(picks.map(makeImage).join(''))); let blind = buildMsg( parts[1]||'', "...blind results sent to gm..."); switch(match[1]){ case 'w': sendChat(`player|${msg.playerid}`,`/w "gm" ${output}`); sendChat(`player|${msg.playerid}`,`/w "${who}" ${output}`); break; case 'b': sendChat(`player|${msg.playerid}`,`/w "gm" ${output}`); sendChat(`player|${msg.playerid}`,blind); break; case 'bw': sendChat(`player|${msg.playerid}`,`/w "gm" ${output}`); sendChat(`player|${msg.playerid}`,`/w "${who}" ${blind}`); break; default: sendChat(`player|${msg.playerid}`,output); } } }); });
Thx a lot for all your work ! In the future if I take you better pictures, Can you update it ?
1587644697
The Aaron
Roll20 Production Team
API Scripter
Yup, easily.&nbsp;