RPG attributes generator: Difference between revisions
(Added rusty C++ solution) |
mNo edit summary |
||
Line 83: | Line 83: | ||
</pre> |
</pre> |
||
=={{header| |
=={{header|C++}}== |
||
GCC 4.9.2, unoptimised. |
GCC 4.9.2, unoptimised. |
||
<lang C++>#include <algorithm> |
<lang C++>#include <algorithm> |
Revision as of 20:56, 19 July 2018
You're running a tabletop RPG, and your players are creating characters.
Each character has six core attributes: strength, dexterity, constitution, intelligence, wisdom, and charisma.
One way of generating values for these attributes is to roll four, 6-sided dice (d6) and sum the three highest rolls, discarding the lowest roll.
Some players like to assign values to their attributes in the order they're rolled.
To ensure generated characters don't put players at a disadvantage, the following requirements must be satisfied:
- The total of all character attributes must be at least 75.
- At least two of the attributes must be at least 15.
However, this can require a lot of manual dice rolling. A programatic solution would be much faster.
Task
Write a program that:
- Generates 4 random, whole values between 1 and 6.
- Saves the sum of the 3 largest values.
- Generates a total of 6 values this way.
- Displays the total, and all 6 values once finished.
- The order in which each value was generated must be preserved.
- The total of all 6 values must be at least 75.
- At least 2 of the values must be 15 or more.
C
<lang c>#include <stdio.h>
- include <stdlib.h>
- include <time.h>
int compareInts(const void *i1, const void *i2) {
int a = *((int *)i1); int b = *((int *)i2); return a - b;
}
int main() {
int i, j, nsum, vsum, vcount, values[6], numbers[4]; srand(time(NULL)); for (;;) { vsum = 0; for (i = 0; i < 6; ++i) { for (j = 0; j < 4; ++j) { numbers[j] = 1 + rand() % 6; } qsort(numbers, 4, sizeof(int), compareInts); nsum = 0; for (j = 1; j < 4; ++j) { nsum += numbers[j]; } values[i] = nsum; vsum += values[i]; } if (vsum < 75) continue; vcount = 0; for (j = 0; j < 6; ++j) { if (values[j] >= 15) vcount++; } if (vcount < 2) continue; printf("The 6 random numbers generated are:\n"); printf("["); for (j = 0; j < 6; ++j) printf("%d ", values[j]); printf("\b]\n"); printf("\nTheir sum is %d and %d of them are >= 15\n", vsum, vcount); break; } return 0;
}</lang>
- Output:
Sample run:
The 6 random numbers generated are: [9 15 15 17 13 8] Their sum is 77 and 3 of them are >= 15
C++
GCC 4.9.2, unoptimised. <lang C++>#include <algorithm>
- include <ctime>
- include <iostream>
- include <cstdlib>
- include <string>
using namespace std;
int main() {
srand(time(0)); unsigned int attributes_total = 0; unsigned int count = 0; int attributes[6] = {}; int rolls[4] = {}; while(attributes_total < 75 || count < 2) { attributes_total = 0; count = 0; for(int attrib = 0; attrib < 6; attrib++) { for(int roll = 0; roll < 4; roll++) { rolls[roll] = 1 + (rand() % 6); } sort(rolls, rolls + 4); int roll_total = rolls[1] + rolls[2] + rolls[3]; attributes[attrib] = roll_total; attributes_total += roll_total; if(roll_total >= 15) count++; } } cout << "Attributes generated : ["; cout << attributes[0] << ", "; cout << attributes[1] << ", "; cout << attributes[2] << ", "; cout << attributes[3] << ", "; cout << attributes[4] << ", "; cout << attributes[5]; cout << "]\nTotal: " << attributes_total; cout << ", Values above 15 : " << count; return 0;
}</lang>
Go
<lang go>package main
import (
"fmt" "math/rand" "sort" "time"
)
func main() {
s := rand.NewSource(time.Now().UnixNano()) r := rand.New(s) for { var values [6]int vsum := 0 for i := range values { var numbers [4]int for j := range numbers { numbers[j] = 1 + r.Intn(6) } sort.Ints(numbers[:]) nsum := 0 for _, n := range numbers[1:] { nsum += n } values[i] = nsum vsum += values[i] } if vsum < 75 { continue } vcount := 0 for _, v := range values { if v >= 15 { vcount++ } } if vcount < 2 { continue } fmt.Println("The 6 random numbers generated are:") fmt.Println(values) fmt.Println("\nTheir sum is", vsum, "and", vcount, "of them are >= 15") break }
}</lang>
- Output:
Sample run:
The 6 random numbers generated are: [16 15 7 14 9 15] Their sum is 76 and 3 of them are >= 15
JavaScript
<lang javascript>function roll() {
const stats = { total: 0, rolls: [] } let count = 0;
for(let i=0;i<=5;i++) { let d6s = [];
for(let j=0;j<=3;j++) { d6s.push(Math.ceil(Math.random() * 6)) }
d6s.sort().splice(0, 1); rollTotal = d6s.reduce((a, b) => a+b, 0);
stats.rolls.push(rollTotal); stats.total += rollTotal; } return stats;
}
let rolledCharacter = roll();
while(rolledCharacter.total < 75 || rolledCharacter.rolls.filter(a => a >= 15).length < 2){
rolledCharacter = roll();
}
console.log(rolledCharacter.total, rolledCharacter.rolls.join(', ')); </lang>
- Output:
Sample run:
80 "16, 15, 13, 13, 13, 10"
Kotlin
<lang scala>// Version 1.2.51
import java.util.Random
fun main(args: Array<String>) {
val r = Random() while (true) { val values = IntArray(6) for (i in 0..5) { val numbers = IntArray(4) { 1 + r.nextInt(6) } numbers.sort() values[i] = numbers.drop(1).sum() } val vsum = values.sum() val vcount = values.count { it >= 15 } if (vsum < 75 || vcount < 2) continue println("The 6 random numbers generated are:") println(values.asList()) println("\nTheir sum is $vsum and $vcount of them are >= 15") break }
}</lang>
- Output:
Sample run:
The 6 random numbers generated are: [13, 14, 13, 15, 17, 8] Their sum is 80 and 2 of them are >= 15
Perl 6
<lang perl6>sub heroic_attr { + @^a.grep: * >= 15 }
my @attr; repeat until @attr.sum >= 75 and heroic_attr(@attr) >= 2 {
@attr = map { (1..6).roll(4).sort(+*).skip(1).sum }, ^6;
}
say @attr; say "Sum: {@attr.sum}, with {heroic_attr(@attr)} attributes >= 15";</lang>
- Output:
[15 17 13 10 10 15] Sum: 80, with 3 attributes >= 15
PHP
<lang php><?php
$attributesTotal = 0; $count = 0;
while($attributesTotal < 75 || $count < 2) {
$attributes = []; foreach(range(0, 5) as $attribute) { $rolls = []; foreach(range(0, 3) as $roll) { $rolls[] = rand(1, 6); } sort($rolls); array_shift($rolls); $total = array_sum($rolls); if($total >= 15) { $count += 1; } $attributes[] = $total; } $attributesTotal = array_sum($attributes);
}
print_r($attributes);</lang>
Python
Python: Simple
<lang python>import random random.seed() attributes_total = 0 count = 0
while attributes_total < 75 or count < 2:
attributes = []
for attribute in range(0, 6): rolls = [] for roll in range(0, 4): result = random.randint(1, 6) rolls.append(result) sorted_rolls = sorted(rolls) largest_3 = sorted_rolls[1:] rolls_total = sum(largest_3) if rolls_total >= 15: count += 1 attributes.append(rolls_total)
attributes_total = sum(attributes)
print(attributes_total, attributes)</lang>
- Output:
Sample run:
(74, [16, 10, 12, 9, 16, 11])
Python: Nested List Comprehensions
<lang python>import random random.seed() total = 0 count = 0
while total < 75 or count < 2:
attributes = [(sum(sorted([random.randint(1, 6) for roll in range(0, 4)])[1:])) for attribute in range(0, 6)] for attribute in attributes: if attribute >= 15: count += 1 total = sum(attributes)
print(total, attributes)</lang>
- Output:
Sample run:
(77, [17, 8, 15, 13, 12, 12])
REXX
<lang rexx>/* REXX Generates 4 random, whole values between 1 and 6. Saves the sum of the 3 largest values. Generates a total of 6 values this way. Displays the total, and all 6 values once finished.
- /
Do try=1 By 1
ge15=0 sum=0 ol= Do i=1 To 6 rl= Do j=1 To 4 rl=rl (random(5)+1) End rl=wordsort(rl) rsum.i=maxsum() If rsum.i>=15 Then ge15=ge15+1 sum=sum+rsum.i ol=ol right(rsum.i,2) End Say ol '->' ge15 sum If ge15>=2 & sum>=75 Then Leave End
Say try 'iterations' Say ol '=>' sum Exit
maxsum: procedure Expose rl /**********************************************************************
- Comute the sum of the 3 largest values
- /
m=0 Do i=2 To 4 m=m+word(rl,i) End Return m
wordsort: Procedure /**********************************************************************
- Sort the list of words supplied as argument. Return the sorted list
- /
Parse Arg wl wa.= wa.0=0 Do While wl<> Parse Var wl w wl Do i=1 To wa.0 If wa.i>w Then Leave End If i<=wa.0 Then Do Do j=wa.0 To i By -1 ii=j+1 wa.ii=wa.j End End wa.i=w wa.0=wa.0+1 End swl= Do i=1 To wa.0 swl=swl wa.i End Return strip(swl)</lang>
- Output:
I:\>rexx cast 13 13 8 15 14 11 -> 1 74 10 9 13 7 15 9 -> 1 63 15 15 14 13 17 14 -> 3 88 3 iterations 15 15 14 13 17 14 => 88
zkl
<lang zkl>reg attrs=List(), S,N; do{
attrs.clear(); do(6){ abcd:=(4).pump(List(),(0).random.fp(1,7)); // list of 4 [1..6] randoms attrs.append(abcd.sum(0) - (0).min(abcd)); // sum and substract min }
}while((S=attrs.sum(0))<75 or (N=attrs.filter('>=(15)).len())<2); println("Random numbers: %s\nSum to %d, number over 15: %d"
.fmt(attrs.concat(","),S,N));</lang>
- Output:
Random numbers: 16,16,13,14,16,11 Sum to 86, number over 15: 3