Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tarea 2 - Entrega Parcial 4 #5

Open
wants to merge 48 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8e33838
EST Added initial packages and first tests
JTJetc Apr 7, 2024
a82eb05
FIX Corrected magictrainer mana test
JTJetc Apr 7, 2024
3afe36b
FEAT Added Unit trait and AbstractCharacter abstract class
JTJetc Apr 7, 2024
2ff14a7
FEAT Added Character Class and fixed typos
JTJetc Apr 7, 2024
cf11a5e
FEAT Added auxiliary constructors for Character class and refactored …
JTJetc Apr 7, 2024
1c796b5
FIX Added Weapon trait and current tests run successfully
JTJetc Apr 7, 2024
b9b01f7
FIX Improved coverage
JTJetc Apr 7, 2024
f44cab7
REFACTOR Added ICharacter trait between Units and AbstractCharacter f…
JTJetc Apr 7, 2024
157d60e
FEAT Added Party class
JTJetc Apr 7, 2024
c6c21bd
REFACTOR Added DummyCharacter for isAlive method
JTJetc Apr 7, 2024
7316535
REFACTOR Split Character into two classes, adding MagicCharacter
JTJetc Apr 9, 2024
4e2e4d3
FEAT! Added Character 'Classes' aka Professions
JTJetc Apr 9, 2024
5cf2f38
FEAT Added Enemy Trait
JTJetc Apr 10, 2024
054eefe
FEAT Added Common and Magic Weapons
JTJetc Apr 10, 2024
1a084eb
DOC Added project explaining to the readme
JTJetc Apr 10, 2024
d6df54f
FEAT Added EnemyClass
JTJetc Apr 12, 2024
8b23970
DOC Added documentation and renamed WhiteMage and BlackMage to White …
JTJetc Apr 13, 2024
3dfb2bc
DOC Added more documentation and fixed miscellaneous typos
JTJetc Apr 13, 2024
4f28259
Branch Creation
JTJetc Apr 16, 2024
22ded8d
FEAT Added Programmer Class and tests
JTJetc Apr 16, 2024
ead7b7a
FEAT Added add methods to programmer
JTJetc Apr 21, 2024
ee4be6c
FEAT Added actionbar for characters
JTJetc Apr 21, 2024
bfca82b
FEAT Added actionbar for enemies
JTJetc Apr 21, 2024
f54fac7
FEAT Added step method
JTJetc Apr 21, 2024
4e0fe65
FEAT Added anyturn checking method
JTJetc Apr 21, 2024
0da4276
FEAT Added getTurn method
JTJetc Apr 21, 2024
9f42b4e
FEAT Added setting actionbar back to zero
JTJetc Apr 21, 2024
9cac4ca
FEAT Added last touchs for finding and getting turns
JTJetc Apr 23, 2024
b2af248
FEAT Added remove method for party and programmer
JTJetc Apr 23, 2024
4e46173
DOC Added more documentation
JTJetc Apr 23, 2024
e5034d6
Branch creation
JTJetc Apr 25, 2024
327833c
Added Privatization
JTJetc May 11, 2024
c012df9
Added placeholderEquipWeapon method
JTJetc May 11, 2024
5f3f2a3
Added Max values, and the use of require to avoid illegal values
JTJetc May 11, 2024
46ce456
Added attacking and taking damage methods
JTJetc May 12, 2024
33ec4a7
Added more tests
JTJetc May 12, 2024
3262013
Branch Creation
JTJetc May 12, 2024
a6ddae2
FEAT Added some equipping tests
JTJetc May 17, 2024
1eb6ebe
FEAT Added getOwner method for weapons
JTJetc May 17, 2024
dfa1adf
FEAT Fixed added tests
JTJetc May 17, 2024
d4d63f8
FEAT Started addeing new methods and Added InvalidWeaponException
JTJetc May 17, 2024
4e508fb
FEAT Added equip weapon methods and related exceptions
JTJetc May 17, 2024
36cc442
FEAT Added more equipping weapons tests and fixed placeholder tests
JTJetc May 17, 2024
a41c7dc
FEAT Fixed oopsies and added more tests
JTJetc May 17, 2024
e225625
FEAT Fixed more oopsies and added more coverage
JTJetc May 17, 2024
4751936
DOC Added more info to the README
JTJetc May 17, 2024
83a60aa
FEAT Added mor code for full party exception
JTJetc May 23, 2024
cf64048
Added a bit of comments
JTJetc May 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 49 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,56 @@
# Final Reality

Final Reality is a simplified clone of the renowned game, Final Fantasy. Its main purpose is to
>Final Reality is a simplified clone of the renowned game, Final Fantasy. Its main purpose is to
serve as an educational tool, teaching foundational programming concepts.

This README is yours to complete it. Take this opportunity to describe your contributions, the
design decisions you've made, and any other information you deem necessary.
*This README is yours to complete it. Take this opportunity to describe your contributions, the
design decisions you've made, and any other information you deem necessary.*

## 1° Assigment
### Partial Assigment 1
- Made sure to not use words "Unit", "Class", "def" for naming, to avoid problems with existing
fields, instead used "Units", "Profession", and "defense".
- Packages/folders for Weapons, Professions, and Units which correspond to Characters and Enemies.
- Units trait for common stats between enemies and player characters.
- ICharacter trait adds profession field and Enemy trait adds damage.
- Abstract class for empty held weapon and isAlive method, common in all characters.
- Party class, with default dummy characters, can ask members if they are alive to determine if whole party
is alive, and can add members up to three.
- Profession trait with name implemented by each profession extending from abstract class
constructor, which will be easier to compare later.
- Weapon trait for common attributes, and two abstract classes for common and magic weapons with magic damage.
- Tests with munit.FunSuite, mainly of constructors, making sure to have good coverage.
### Partial Assigment 2
- Programmer class in charge to manage actionbar changes and determining which enemy or character can get a turn
- Programmer can add and remove units (max 3 party members, max 5 enemies per battle)
- Programmer for now has an arbitrary amount k to increase the actionbar each step
- They ideal combat manager will step the programmer, then ask if any member can perform a turn, and if true,
perform an action with returned unit, otherwise keep stepping to increase actionbars
- Maybe one programmer object can be used for each different battle, making sure to destroy the leftover object
### Final Assigment 1
- Started the privatization of values and methods, making sure that var type values where at least protected, while
val types can be public. And added methods to view some now private or protected values.
- Decided to add a maxLife value for units, it could be useful in the future for not healing over the maximum.
- Used require to avoid using illegal values in constructors.
- Added methods for character attacking enemies, enemies attacking characters, character taking damage by enemies,
and enemies taking damage by characters.
- Added more tests for more code coverage.

## 2° Assigment
### Partial Assigment 3
- Added two exceptions for invalid weapon for profession and weapon already being used by someone else.
- Added methods to characters and weapons using double dispatch to ask the weapon itself for equipping and even
throwing exceptions if required. The idea for the future is to check if weapons can be equipped, then equip
the weapon later, but if trying to force equip something that should not be equipped, exceptions get thrown
for equipping something null, for weapons already being used by someone else, and by invalid weapons for a
certain profession.
- Added methods for un-equipping weapons and made sure to update the max action bar after equipping and
un-equipping weapons.
- Also added method to weapons to get the owner for comparing.
### Partial Assigment 4
- I already had implemented un-equipping weapons, max of 3 party members, and enemies can only attack players,
and players can only attack enemies. But still added a bit of more code to make it look better and even added
more tests.

This project is licensed under the
[Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/).
112 changes: 112 additions & 0 deletions src/main/scala/combatsystem/Programmer.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package combatsystem
import unit.{Enemy, ICharacter, IParty, Units}

import scala.collection.mutable.ListBuffer

/** Class representing a programmer of turns.
*
* Uses a [[unit.Party]] and a ListBuffer type [[unit.Enemy]] to up to 5 enemies, has many methods to ask and change the actionbar of the units, and then check and retrieve who could perform an action
*
* @param party A Party of Characters
* @param enemies A ListBuffer of enemies
*
* @constructor Creates a new programmer for turns checking.
*
* @author Javier Torres
* @since 1.0.0
* @version 1.0.1
*/
class Programmer(private var party: IParty, private val enemies: ListBuffer[Enemy]) {
/**An arbitrary amount to increase the actionbar*/
protected var k: Int = 3
/**A ListBuffer to save the units that have completed their actionbars and can perform a turn, initialized empty*/
private var readyList: ListBuffer[Units] = ListBuffer() //required to be var because otherwise cant be sorted
//When the constructors builds, make sure to set all units actionbar to zero in case they already had some from another battle
party.step(0)
for (n <- enemies) n.setActionBar(0)

/** Adds a Character to the programmer, who then makes sure add to the party and set its actionbar to zero
*
* @param who The character to add to the programmer
*/
def add(who: ICharacter): Unit = {
party.add(who)
who.setActionBar(0)
}

/** Adds an enemy to the programmer, who then makes sure add to the ListBuffer and set its actionbar to zero.
* Can only add an enemy if there is space (max 5 enemies)
* @param who The enemy to add to the programmer
*/
def add(who: Enemy): Unit = {
if (enemies.length < 5) {
enemies.addOne(who)
who.setActionBar(0)
}
}

/** Removes a specific character from the programmer, who makes sure to remove it from the party too
*
* @param who The character to remove from the programmer
*/
def remove(who: ICharacter): Unit = {
party.remove(who)
}

/** Removes a specific enemy from the programmer
*
* @param who The enemy to remove from the programmer
*/
def remove(who: Enemy): Unit = {
enemies -= who
}

/** Method to make progress in the actionbar on each party member and enemy in the ListBuffer*/
def step(): Unit = {
party.step(k)
for (n <- enemies) n.setActionBar(k)
}

/** Checks all the units actionbars, and if they completed it, gets added to readyList ListBuffer
*
* @return True if any unit can perform a turn
*/
def anyTurn: Boolean = {
readyList.clear() //First clears the list to avoid duplicates
readyList = party.anyTurnForProgrammer(readyList)
for (n <- enemies) {
if (n.getActionBar >= 0) readyList.addOne(n) //Check getActionBar in EnemyClass for more details
}
//If at least one unit in list, someone can perform a turn, then returns true
if (readyList.nonEmpty) true
else false
}

/**Sorts the readyList by actionbar, then extracts the one unit with more excess and resets its actionbar to zero
*
* @return The character or enemy that can perform an action, prioritizing the one with more excess actionbar
*/
def getTurn: Units = {
readyList = readyList.sortWith(_.getActionBar < _.getActionBar) //this way, the last one in list is the one with priority to have a turn
val result: Units = readyList.last //character or enemy to return
readyList.last.setActionBar(0)
readyList.dropRightInPlace(1)
result
}

/** Gets the stored party
*
* @return The Programmer's Party
*/
def getParty: IParty = {
party
}

/** Gets the stored enemies
*
* @return The Programmer's Enemies List
*/
def getEnemies: ListBuffer[Enemy] = {
enemies
}
}
16 changes: 16 additions & 0 deletions src/main/scala/profession/AbstractProfession.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package profession

/** Abstract class representing professions.
*
* Professions name must be provided by the subclasses.
*
* Used by [[profession.Warrior]], [[profession.Paladin]], [[profession.Ninja]], [[profession.BlackMage]], and [[profession.WhiteMage]]
*
* @param name The name of the profession.
*
* @author Javier Torres
* @since 1.0.0
* @version 1.0.0
*/
class AbstractProfession(val name:String) extends Profession {
}
15 changes: 15 additions & 0 deletions src/main/scala/profession/BlackMage.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package profession

/** Class representing Black Mage Profession.
*
* Sends "Black Mage" for name to [[profession.AbstractProfession]] superclass
*
* @constructor Creates a new Black Mage Profession.
*
* @author Javier Torres
* @since 1.0.0
* @version 1.0.0
*/
class BlackMage extends AbstractProfession("Black Mage") {

}
15 changes: 15 additions & 0 deletions src/main/scala/profession/Ninja.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package profession

/** Class representing Ninja Profession.
*
* Sends "Ninja" for name to [[profession.AbstractProfession]] superclass
*
* @constructor Creates a new Ninja Profession.
*
* @author Javier Torres
* @since 1.0.0
* @version 1.0.0
*/
class Ninja extends AbstractProfession("Ninja") {

}
15 changes: 15 additions & 0 deletions src/main/scala/profession/Paladin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package profession

/** Class representing Paladin Profession.
*
* Sends "Paladin" for name to [[profession.AbstractProfession]] superclass
*
* @constructor Creates a new Paladin Profession.
*
* @author Javier Torres
* @since 1.0.0
* @version 1.0.0
*/
class Paladin extends AbstractProfession("Paladin") {

}
9 changes: 9 additions & 0 deletions src/main/scala/profession/Profession.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package profession

/** Trait mainly used for type in constructors.
* Also provides a name for the profession.
* Used by [[profession.AbstractProfession]]
*/
trait Profession {
val name: String
}
14 changes: 14 additions & 0 deletions src/main/scala/profession/Warrior.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package profession

/** Class representing Warrior Profession.
*
* Sends "Warrior" for name to [[profession.AbstractProfession]] superclass
*
* @constructor Creates a new Warrior Profession.
*
* @author Javier Torres
* @since 1.0.0
* @version 1.0.0
*/
class Warrior extends AbstractProfession("Warrior") {
}
15 changes: 15 additions & 0 deletions src/main/scala/profession/WhiteMage.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package profession

/** Class representing White Mage Profession.
*
* Sends "White Mage" for name to [[profession.AbstractProfession]] superclass
*
* @constructor Creates a new White Mage Profession.
*
* @author Javier Torres
* @since 1.0.0
* @version 1.0.0
*/
class WhiteMage extends AbstractProfession("White Mage") {

}
64 changes: 64 additions & 0 deletions src/main/scala/unit/AbstractCharacter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package unit

import weapon.{InvalidWeaponException, UsedWeaponException, Weapon}

/** Abstract class representing Characters.
*
* Used by [[unit.Character]], and [[unit.MagicCharacter]]
*
* @author Javier Torres
* @since 1.0.0
* @version 1.0.3
*/
abstract class AbstractCharacter extends ICharacter {
/** The weapon this character is holding.
*
* Starts by default empty, meaning no held weapon.
*/
protected var heldweapon: Weapon = null
/*
/** Placeholder method to equip a weapon */
def placeholderEquipWeapon(weapon:Weapon) : Unit ={
heldweapon = weapon
}*/
/** Returns the equipped weapon */
def getHeldWeapon : Weapon = heldweapon

def isAlive: Boolean = {
if (life > 0) true
else false
}

def getLife: Int = {
life
}
def getDefense: Int ={
defense
}

def attackAnEnemy(who:Enemy) : Unit = {
if(heldweapon != null) who.hurtByCharacter(this) //nothing happens if no weapon is held
}
def hurtByEnemy(who:Enemy) : Unit ={
var howMuchWillItHurt : Int = who.getDamage - defense
if(howMuchWillItHurt < 0) howMuchWillItHurt = 0
life -= howMuchWillItHurt
if(life < 0) life = 0
}

def canEquipWeapon(weapon:Weapon) : Boolean = {
if(weapon != null) weapon.canEquipTo(this)
else false
}
def removeWeapon(): Unit = {
if(heldweapon != null) { heldweapon.removeOwner() }
heldweapon = null
updateMaxActionbar()
}
def equipWeapon(weapon:Weapon) : Unit = {
removeWeapon()
weapon.equipTo(this)
heldweapon = weapon
updateMaxActionbar()
}
}
Loading