RPG   =   Role Playing Game.



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.

 
/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program rpg64.s   */
 
/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
 
.equ NBTIRAGES,     4
.equ NBTIRAGESOK,   3
.equ NBVALUES,      6
.equ TOTALMIN,      75
.equ MAXVALUE,      15
.equ NBMAXVALUE,    2
 
/*********************************/
/* Initialized data              */
/*********************************/
.data
sMessResult:        .asciz "Value  = @ \n"
szCarriageReturn:   .asciz "\n"
sMessResultT:       .asciz "Total  = @ \n"
sMessResultQ:       .asciz "Values above 15  = @ \n"
 
 
.align 4
qGraine:  .quad 123456789
 
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss  
tqTirages:               .skip  8 * NBTIRAGES
tqValues:                .skip  8 * NBVALUES
 
sZoneConv:               .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                                  // entry of program 
 
1:                                     // begin loop 1
    mov x2,0                           // counter value >15
    mov x4,0                           // loop indice
    mov x5,0                           // total
    ldr x3,qAdrtqValues                // table values address
2:
    bl genValue                        // call generate value 
    str x0,[x3,x4,lsl 3]               // store in table
    add x5,x5,x0                       // compute total
    cmp x0,MAXVALUE                    // count value >= 15
    add x6,x2,1
    csel x2,x6,x2,ge
    add x4,x4,1                        // increment indice
    cmp x4,NBVALUES                    // end ?
    blt 2b
    cmp x5,TOTALMIN                    // compare 75
    blt 1b                             // < loop
    cmp x2,#NBMAXVALUE                 // compare value > 15
    blt 1b                             // < loop
    ldr x0,qAdrtqValues                // display values
    bl displayTable
    mov x0,x5                          // total
 
    ldr x1,qAdrsZoneConv               // display value
    bl conversion10                    // call conversion decimal
    ldr x0,qAdrsMessResultT
    ldr x1,qAdrsZoneConv   
    bl strInsertAtCharInc              // insert result at @ character
    bl affichageMess                   // display message
 
     mov x0,x2                         // counter value > 15
    ldr x1,qAdrsZoneConv               // display value
    bl conversion10                    // call conversion decimal
    ldr x0,qAdrsMessResultQ
    ldr x1,qAdrsZoneConv       
    bl strInsertAtCharInc              // insert result at @ character
    bl affichageMess                   // display message
 
100:                                   // standard end of the program 
    mov x0,0                           // return code
    mov x8,EXIT                        // request to exit program
    svc 0                              // perform the system call
 
qAdrsZoneConv:            .quad sZoneConv
qAdrszCarriageReturn:     .quad szCarriageReturn
qAdrsMessResult:          .quad sMessResult
qAdrsMessResultT:         .quad sMessResultT
qAdrsMessResultQ:         .quad sMessResultQ
qAdrtqValues:             .quad tqValues
/******************************************************************/
/*     generate value                                  */ 
/******************************************************************/
/* x0 returns the value             */
genValue:
    stp x1,lr,[sp,-16]!            // save  registers
    stp x2,x3,[sp,-16]!            // save  registers
    mov x3,0                       // indice loop
    ldr x1,qAdrtqTirages           // table tirage address
1:
    mov x0,6
    bl genereraleas                // result 0 to 5
    add x0,x0,#1                   // for 1 to 6
    str x0,[x1,x3,lsl 3]           // store tirage
    add x3,x3,1                    // increment indice
    cmp x3,NBTIRAGES               // end ?
    blt 1b                         // no -> loop
    ldr x0,qAdrtqTirages           // table tirage address
    mov x1,#0                      // first item
    mov x2,#NBTIRAGES              // number of tirages
    bl shellSort                   // sort table decreasing
    mov x3,#0                      // raz indice loop
    mov x0,#0                      // total
    ldr x1,qAdrtqTirages           // table tirage address
2:
    ldr x2,[x1,x3,lsl 3]           // read tirage
    add x0,x0,x2                   // compute sum
    add x3,x3,1                    // increment indice
    cmp x3,NBTIRAGESOK             // end ?
    blt 2b
100:
    ldp x2,x3,[sp],16              // restaur  2 registers
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
qAdrtqTirages:           .quad tqTirages
/***************************************************/
/*   shell Sort  decreasing                                  */
/***************************************************/
/* x0 contains the address of table */
/* x1 contains the first element but not use !!   */
/*   this routine use first element at index zero !!!  */
/* x2 contains the number of element */
shellSort:
    stp x1,lr,[sp,-16]!          // save  registers
    stp x2,x3,[sp,-16]!          // save  registers
    stp x4,x5,[sp,-16]!          // save  registers
    stp x6,x7,[sp,-16]!          // save  registers
    stp x8,x9,[sp,-16]!          // save  registers
    sub x2,x2,1                     // index last item
    mov x1,x2                    // init gap = last item
1:                               // start loop 1
    lsr x1,x1,1                 // gap = gap / 2
    cbz x1,100f                     // if gap = 0 -> end
    mov x3,x1                    // init loop indice 1 
2:                               // start loop 2
    ldr x4,[x0,x3,lsl 3]         // load first value
    mov x5,x3                    // init loop indice 2
3:                               // start loop 3
    cmp x5,x1                    // indice < gap
    blt 4f                       // yes -> end loop 2
    sub x6,x5,x1                 // index = indice - gap
    ldr x8,[x0,x6,lsl 3]         // load second value
    cmp x4,x8                    // compare values
    ble 4f
    str x8,[x0,x5,lsl 3]         // store if >
    sub x5,x5,x1                    // indice = indice - gap
    b 3b                         // and loop
4:                               // end loop 3
    str x4,[x0,x5,lsl 3]         // store value 1 at indice 2
    add x3,x3,1                  // increment indice 1
    cmp x3,x2                    // end ?
    ble 2b                       // no -> loop 2
    b 1b                         // yes loop for new gap
 
100:                             // end function
    ldp x8,x9,[sp],16            // restaur  2 registers
    ldp x6,x7,[sp],16            // restaur  2 registers
    ldp x4,x5,[sp],16            // restaur  2 registers
    ldp x2,x3,[sp],16            // restaur  2 registers
    ldp x1,lr,[sp],16            // restaur  2 registers
    ret                          // return to address lr x30
 
/******************************************************************/
/*      Display table elements                                */ 
/******************************************************************/
/* x0 contains the address of table */
displayTable:
    stp x1,lr,[sp,-16]!            // save  registers
    stp x2,x3,[sp,-16]!            // save  registers
    mov x2,x0                      // table address
    mov x3,0
1:                                 // loop display table
    ldr x0,[x2,x3,lsl 3]
    ldr x1,qAdrsZoneConv           // display value
    bl conversion10                // call function
    ldr x0,qAdrsMessResult
    ldr x1,qAdrsZoneConv  
    bl strInsertAtCharInc          // insert result at @ character
    bl affichageMess               // display message
    add x3,x3,1
    cmp x3,NBVALUES - 1
    ble 1b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
100:
    ldp x2,x3,[sp],16              // restaur  2 registers
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
 
/***************************************************/
/*   Generation random number                      */
/*    algo xorshift (see wikipedia)                */
/***************************************************/
/* x0 contains limit  */
genereraleas:
    stp x1,lr,[sp,-16]!            // save  registers
    stp x2,x3,[sp,-16]!            // save  registers
    cbz x0,100f
    mov x3,x0           // maxi value
    ldr x0,qAdrqGraine  // graine
    ldr x2,[x0]
    lsl x1,x2,13
    eor x2,x2,x1
    lsr x1,x2,7
    eor x2,x2,x1
    lsl x1,x2,17
    eor x1,x2,x1
    str x1,[x0]         // sauver graine
    udiv x2,x1,x3       // 
    msub x0,x2,x3,x1    // compute result modulo limit
 
100:                    // end function
    ldp x2,x3,[sp],16              // restaur  2 registers
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/*****************************************************/
qAdrqGraine: .quad qGraine
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
 