/
Avatar.scala
143 lines (120 loc) · 4.25 KB
/
Avatar.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package com.programmera.scalaland_immutable3
object CreatureType extends Enumeration{
val Elf, Dwarf = Value
}
object ProfessionalType extends Enumeration{
val Thief, Warrior, Wizard = Value
}
class Avatar(
val name: String,
optionalFeatures: Option[CreatureFeatureSet],
optionalItems: Option[MagicalItemList])
extends Professional {
// Fields
val items = optionalItems.getOrElse(new MagicalItemList())
// Initialize class
protected val _features: CreatureFeatureSet =
optionalFeatures.getOrElse(generateCreatureFeatures())
// Override getters
override def strength = super.strength +
items.calculateModifier(CreatureFeature.Strength)
override def wisdom = super.wisdom +
items.calculateModifier(CreatureFeature.Wisdom)
override def charisma = super.charisma +
items.calculateModifier(CreatureFeature.Charisma)
// Private helper method used to update a feature
private def withCreatureFeature(
newFeatures: CreatureFeatureSet): Avatar =
Avatar(this.items, newFeatures, this)
// Setters
def withStrength(s: Int): Avatar =
withCreatureFeature(_features.copy(strength = s))
def withWisdom(w: Int): Avatar =
withCreatureFeature(_features.copy(wisdom = w))
def withCharisma(c: Int): Avatar =
withCreatureFeature(_features.copy(charisma = c))
def withHitpoints(h: Int): Avatar = {
println("setHitpoints() old value: " + hitpoints + ", new value: " + h)
if (h > 0)
withCreatureFeature(_features.copy(hitpoints = h))
else
throw new DeathException(name + " died!")
}
// Suffer damage
def sufferDamage(damage: Int): Avatar = {
println("Hitpoints before attack: "+ hitpoints)
println("Damage: "+ damage)
if (damage > 0) {
val newHitpoints = hitpoints - damage
withHitpoints(newHitpoints)
} else {
this
}
}
// Handy method
def addItem(newItem: MagicalItem): Avatar =
Avatar(this.items.add(newItem), this._features, this)
// super will call toString in Creature
override def toString = super.toString + "\n" + items.toString
}
object Avatar {
// Used first time an avatar is created
def apply(
name: String,
creature: CreatureType.Value,
profession: ProfessionalType.Value): Avatar = {
constructor(name, None, None, creature, profession)
}
// Used when the avatar already exists
def apply(
newItems: MagicalItemList,
newFeatures: CreatureFeatureSet,
avatar: Avatar): Avatar = {
// Warning! Hard to manage this code
val creatureType = avatar match {
case e: Elf => CreatureType.Elf
case d: Dwarf => CreatureType.Dwarf
case _ => throw new Exception("Unknown creature type: " + avatar.name)
}
// Warning! Hard to manage this code
val professionalType = avatar match {
case t: Thief => ProfessionalType.Thief
case w: Warrior => ProfessionalType.Warrior
case m: Wizard => ProfessionalType.Wizard
case _ => throw new Exception("Unknown profession: " + avatar.name)
}
constructor(avatar.name, Some(newFeatures), Some(newItems),
creatureType, professionalType)
}
// Avatar main factory method
private def constructor(
name: String,
optFeats: Option[CreatureFeatureSet],
optItems: Option[MagicalItemList],
creature: CreatureType.Value,
profession: ProfessionalType.Value): Avatar = {
// Warning! Hard to manage this code
creature match {
case CreatureType.Dwarf => {
profession match {
case ProfessionalType.Thief =>
new Avatar(name, optFeats, optItems) with Dwarf with Thief
case ProfessionalType.Warrior =>
new Avatar(name, optFeats, optItems) with Dwarf with Warrior
case ProfessionalType.Wizard =>
new Avatar(name, optFeats, optItems) with Dwarf with Wizard
}
}
case CreatureType.Elf => {
profession match {
case ProfessionalType.Thief =>
new Avatar(name, optFeats, optItems) with Elf with Thief
case ProfessionalType.Warrior =>
new Avatar(name, optFeats, optItems) with Elf with Warrior
case ProfessionalType.Wizard =>
new Avatar(name, optFeats, optItems) with Elf with Wizard
}
}
}
}
}