313 lines
7.4 KiB
Swift
313 lines
7.4 KiB
Swift
//
|
|
// Dice.swift
|
|
// Bunch O' Dice
|
|
//
|
|
// Created by Rory Hinnen on 22/2/20.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
struct Dice {
|
|
// MARK: Private
|
|
private var d6: Int {
|
|
get {
|
|
return Int.random(in: 1...6)
|
|
}
|
|
}
|
|
|
|
// MARK: Enums
|
|
enum DiceType: Int, CaseIterable{
|
|
case one = 1
|
|
case two = 2
|
|
case three = 3
|
|
case four = 4
|
|
case five = 5
|
|
case six = 6
|
|
}
|
|
|
|
enum RollModifiers: Int {
|
|
case negative = -1
|
|
case none = 0
|
|
case positive = 1
|
|
|
|
func add() -> RollModifiers {
|
|
switch self {
|
|
case .negative:
|
|
return RollModifiers.none
|
|
case .none:
|
|
return RollModifiers.positive
|
|
case .positive:
|
|
return RollModifiers.positive
|
|
}
|
|
}
|
|
|
|
func remove() -> RollModifiers {
|
|
switch self {
|
|
case .negative:
|
|
return RollModifiers.negative
|
|
case .none:
|
|
return RollModifiers.negative
|
|
case .positive:
|
|
return RollModifiers.none
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: Variables
|
|
var one = 0
|
|
var two = 0
|
|
var three = 0
|
|
var four = 0
|
|
var five = 0
|
|
var six = 0
|
|
|
|
// MARK: Roll controllers
|
|
// clear and roll the die
|
|
mutating func roll(howMany: Int) {
|
|
clear()
|
|
var y = howMany
|
|
while y > 0 {
|
|
switch d6 {
|
|
case 1:
|
|
one += 1
|
|
case 2:
|
|
two += 1
|
|
case 3:
|
|
three += 1
|
|
case 4:
|
|
four += 1
|
|
case 5:
|
|
five += 1
|
|
default:
|
|
six += 1
|
|
}
|
|
y -= 1
|
|
}
|
|
}
|
|
|
|
// calculate basic roll
|
|
func total(cutoff: Int, modifier: Dice.RollModifiers) -> Int {
|
|
var total = six
|
|
|
|
switch modifier {
|
|
case .none:
|
|
switch cutoff {
|
|
case 5:
|
|
total += five
|
|
case 4:
|
|
total += four + five
|
|
case 3:
|
|
total += three + four + five
|
|
case 2:
|
|
total += two + three + four + five
|
|
default:
|
|
break
|
|
}
|
|
case .negative:
|
|
switch cutoff {
|
|
case 4:
|
|
total += five
|
|
case 3:
|
|
total += four + five
|
|
case 2:
|
|
total += three + four + five
|
|
case 1:
|
|
total += two + three + four + five
|
|
default:
|
|
break
|
|
}
|
|
case .positive:
|
|
switch cutoff {
|
|
case 6:
|
|
total += five
|
|
case 5:
|
|
total += four + five
|
|
case 4:
|
|
total += three + four + five
|
|
case 3, 2:
|
|
total += two + three + four + five
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
return total
|
|
}
|
|
|
|
// Calculate different rolls
|
|
func hit(die: Int, cutoff: Int, modifier: Int) -> Int {
|
|
return total(cutoff: cutoff, modifier: Dice.RollModifiers(rawValue: modifier) ?? .none)
|
|
}
|
|
|
|
func wound(die: Int, mortal: Bool, cutoff: Int, modifier: Int) -> Int {
|
|
if mortal {
|
|
return total(cutoff: 2, modifier: Dice.RollModifiers(rawValue: modifier) ?? .none)
|
|
} else {
|
|
return total(cutoff: cutoff, modifier: Dice.RollModifiers(rawValue: modifier) ?? .none)
|
|
}
|
|
}
|
|
|
|
func armour(die: Int, invulnerable: Bool, save: Int, armourPenetration: Int) -> Int {
|
|
var total = 0
|
|
switch invulnerable ? save : (save - armourPenetration) {
|
|
case 7...:
|
|
total = six + five + four + three + two + one
|
|
case 6:
|
|
total = five + four + three + two + one
|
|
case 5:
|
|
total = four + three + two + one
|
|
case 4:
|
|
total = three + two + one
|
|
case 3:
|
|
total = two + one
|
|
default:
|
|
total = one
|
|
}
|
|
return total
|
|
}
|
|
|
|
// MARK: roll utilities
|
|
// Utility functions
|
|
mutating func clear() {
|
|
one = 0
|
|
two = 0
|
|
three = 0
|
|
four = 0
|
|
five = 0
|
|
six = 0
|
|
}
|
|
|
|
mutating func add(pool: Dice) {
|
|
one += pool.one
|
|
two += pool.two
|
|
three += pool.three
|
|
four += pool.four
|
|
five += pool.five
|
|
six += pool.six
|
|
}
|
|
|
|
func value(which: DiceType) -> Int {
|
|
switch which {
|
|
case .one:
|
|
return one
|
|
case .two:
|
|
return two
|
|
case .three:
|
|
return three
|
|
case .four:
|
|
return four
|
|
case .five:
|
|
return five
|
|
case .six:
|
|
return six
|
|
}
|
|
}
|
|
|
|
// MARK: Extra
|
|
mutating func increment(die: DiceType) {
|
|
switch die {
|
|
case .one:
|
|
one += 1
|
|
case .two:
|
|
two += 1
|
|
case .three:
|
|
three += 1
|
|
case .four:
|
|
four += 1
|
|
case .five:
|
|
five += 1
|
|
case .six:
|
|
six += 1
|
|
}
|
|
}
|
|
|
|
mutating func decrement(die: DiceType) {
|
|
switch die {
|
|
case .one:
|
|
if one > 0 {
|
|
one -= 1
|
|
}
|
|
case .two:
|
|
if two > 0 {
|
|
two -= 1
|
|
}
|
|
case .three:
|
|
if three > 0 {
|
|
three -= 1
|
|
}
|
|
case .four:
|
|
if four > 0 {
|
|
four -= 1
|
|
}
|
|
case .five:
|
|
if five > 0 {
|
|
five -= 1
|
|
}
|
|
case .six:
|
|
if six > 0 {
|
|
six -= 1
|
|
}
|
|
}
|
|
}
|
|
|
|
mutating func reroll(dice: DiceType) {
|
|
var rerolls = Dice()
|
|
switch dice {
|
|
case .one:
|
|
rerolls.roll(howMany: one)
|
|
one = 0
|
|
self.add(pool: rerolls)
|
|
case .two:
|
|
rerolls.roll(howMany: two)
|
|
two = 0
|
|
self.add(pool: rerolls)
|
|
case .three:
|
|
rerolls.roll(howMany: three)
|
|
three = 0
|
|
self.add(pool: rerolls)
|
|
case .four:
|
|
rerolls.roll(howMany: four)
|
|
four = 0
|
|
self.add(pool: rerolls)
|
|
case .five:
|
|
rerolls.roll(howMany: five)
|
|
five = 0
|
|
self.add(pool: rerolls)
|
|
case .six:
|
|
rerolls.roll(howMany: six)
|
|
six = 0
|
|
self.add(pool: rerolls)
|
|
}
|
|
}
|
|
|
|
mutating func rerollBelow(cutoff: Int) {
|
|
var count = 0
|
|
for faceValue in 1..<cutoff {
|
|
guard let face = DiceType(rawValue: faceValue) else { continue }
|
|
count += value(which: face)
|
|
switch face {
|
|
case .one: one = 0
|
|
case .two: two = 0
|
|
case .three: three = 0
|
|
case .four: four = 0
|
|
case .five: five = 0
|
|
case .six: six = 0
|
|
}
|
|
}
|
|
var rerolls = Dice()
|
|
rerolls.roll(howMany: count)
|
|
add(pool: rerolls)
|
|
}
|
|
|
|
mutating func blowup(dice: DiceType) {
|
|
var rolls = Dice()
|
|
if dice == .six {
|
|
rolls.roll(howMany: six)
|
|
self.add(pool: rolls)
|
|
} else if dice == .five {
|
|
rolls.roll(howMany: six + five)
|
|
self.add(pool: rolls)
|
|
}
|
|
}
|
|
}
|
|
|