Looping Dice-Roller Advice?

40 views Asked by At

I'm very new to coding, (started about 5 days ago) and I was wondering if I could get some help with a current project. I'm attempting to create a dice roller, modeled after the dnd ability system (roll 4 d6, subtract the lowest number) that creates 8 sets of rolls with the same total value (my friends and I want to want to make a fair game using rolled stats) and I'm having some issues figuring out how to create a loop that will speed up the process.

Here's what I have so far:

clc, clearvars, format compact
num1 = randi(6,1,4);
num2 = randi(6,1,4);
num3 = randi(6,1,4);
num4 = randi(6,1,4);
num5 = randi(6,1,4);
num6 = randi(6,1,4);

ab1 = sum(num1,"all") - min(num1);
ab2 = sum(num2,"all") - min(num2);
ab3 = sum(num3,"all") - min(num3);
ab4 = sum(num4,"all") - min(num4);
ab5 = sum(num5,"all") - min(num5);
ab6 = sum(num6,"all") - min(num6);

set = [ab1 ab2 ab3 ab4 ab5 ab6];
settot = sum(set,"all");
threshold = 78

while true
    if settot >= threshold
        disp(settot)
        break
    end
    disp("done")
end

I'd love any advice on how to streamline the whole thing, (it feels clunky) and on how to solve my loop issue. Thanks! - Teodoro

P.S. I use matlab. not sure if that's relevant or not. P.P.S if you have any ideas on if I should use a seperate loop or another function I don't know about, feel free to rip into my code and let me know haha.

1

There are 1 answers

1
Ferro Luca On

I think you can avoid using loops altogether by using proper array/matrix operations and recursion.

function dndRoll
rolled=randi(6,6,4); %6x4 matrix
ab=sum(rolled,2)-min(rolled,[],2); %sum rows and subtracts min of row
abtot=sum(ab);
ths=78;
if abtot>ths
    disp(abtot)
    disp(ab)
else
    disp('Reroll')
    dndRoll %recursive call to reroll
end
end

Some things like the threshold are hardcoded which is not ideal. Since it is now a function you could set the threshold as an input for better usage as well. Same applies to the number and values of dices.

function dndRoll(numOfDice,numOfAb,sizeOfDice,ths)
rolled=randirandi(sizeOfDice,numOfAb,numOfDice);
ab=sum(rolled,2)-min(rolled,[],2);
abtot=sum(ab);
if abtot>ths
    disp(abtot)
else
    disp('Reroll')
    dndRoll(numOfDice,sizeOfDice,ths)
end
end

Since there is a possibility of infinite recursion it is also better to add some sort of control on it.

function dndRoll(numOfDice,numOfAb,sizeOfDice,ths,varargin)
if isempty(varargin)
    itNum=0;
else 
    itNum=varargin{1};
end

if itNum>25 
    disp('Max rerolling reached.')
    return
end

rolled=randi(sizeOfDice,numOfAb,numOfDice);
ab=sum(rolled,2)-min(rolled,[],2);
abtot=sum(ab);
if abtot>ths
    disp(abtot)
else
    disp('Reroll')
    itNum=itNum+1;
    dndRoll(numOfDice,numOfAb,sizeOfDice,ths,itNum)
end
end

EDIT: as pointed out in the comments for loops are faster than recursion, so here is a version using those:

function dndRoll(numOfDice,numOfAb,sizeOfDice,ths)
for rr=1:25 %max iterations
  rolled=randi(sizeOfDice,numOfAb,numOfDice);
  ab=sum(rolled,2)-min(rolled,[],2);
  abtot=sum(ab);
  if abtot>ths
    disp(abtot)
    return
  else
    disp('Reroll')
  end
end
disp('Max rerolling reached.')
end