From 5c9dbdf0a40f4a8b77ada0510ef37dbc93755587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Thu, 23 Feb 2017 10:10:08 +0100 Subject: [PATCH 01/23] Adds a little tiny stupid comment. --- Sources/swift_exercises.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index c51721d..8a44219 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -121,6 +121,7 @@ func ==(lhs: Species, rhs: Species) -> Bool { return lhs.id == rhs.id } +// wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww ho-oh a l'air chiant // TODO: create some species // Do you use an enum, a map or constants/variables? // http://bulbapedia.bulbagarden.net/wiki/List_of_Pokémon_by_National_Pokédex_number From 414e4800b03e966b533b66a0a52f8e870b590124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Thu, 23 Feb 2017 10:41:52 +0100 Subject: [PATCH 02/23] Minor change. --- Sources/swift_exercises.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 8a44219..c47c7ec 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -122,6 +122,7 @@ func ==(lhs: Species, rhs: Species) -> Bool { } // wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww ho-oh a l'air chiant +// tulio c'est un baka qui sèche les cours donc je lui montre comment ça marche git // TODO: create some species // Do you use an enum, a map or constants/variables? // http://bulbapedia.bulbagarden.net/wiki/List_of_Pokémon_by_National_Pokédex_number From 964ca27aee4802b5b75eedcc87b1ff4a486762ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 27 Feb 2017 09:40:55 +0100 Subject: [PATCH 03/23] Implemented the typeModifier function --- Sources/swift_exercises.swift | 61 +++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index c47c7ec..f119712 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -1,23 +1,23 @@ // http://bulbapedia.bulbagarden.net/wiki/Type -enum Type { - case bug - case dark - case dragon - case electric - case fairy - case fighting - case fire - case flying - case ghost - case grass - case ground - case ice - case normal - case poison - case psychic - case rock - case steel - case water +enum Type: Int { + case bug = 6 + case dark = 16 + case dragon = 15 + case electric = 12 + case fairy = 17 + case fighting = 1 + case fire = 9 + case flying = 2 + case ghost = 7 + case grass = 11 + case ground = 4 + case ice = 14 + case normal = 0 + case poison = 3 + case psychic = 13 + case rock = 5 + case steel = 8 + case water = 10 } // http://bulbapedia.bulbagarden.net/wiki/Damage_category @@ -156,8 +156,27 @@ struct Environment { // http://bulbapedia.bulbagarden.net/wiki/Type/Type_chart func typeModifier(attacking: Type, defending : Type) -> Double { - // TODO: encode type/type chart - return 1 + let chart: [[Double]] = [[1, 1, 1, 1, 1, 0.5, 1, 0, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1,], + [2, 1, 0.5, 0.5, 1, 2, 0.5, 0, 2, 1, 1, 1, 1, 0.5, 2, 1, 2, 0.5,], + [1, 2, 1, 1, 1, 0.5, 2, 1, 0.5, 1, 1, 2, 0.5, 1, 1, 1, 1, 1,], + [1, 1, 1, 0.5, 0.5, 0.5, 1, 0.5, 0, 1, 1, 2, 1, 1, 1, 1, 1, 2,], + [1, 1, 0, 2, 1, 2, 0.5, 1, 2, 2, 1, 0.5, 2, 1, 1, 1, 1, 1,], + [1, 0.5, 2, 1, 0.5, 1, 2, 1, 0.5, 2, 1, 1, 1, 1, 2, 1, 1, 1,], + [1, 0.5, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 0.5, 1, 2, 1, 2, 1, 1, 2, 0.5,], + [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 0.5, 1,], + [1, 1, 1, 1, 1, 2, 1, 1, 0.5, 0.5, 0.5, 1, 0.5, 1, 2, 1, 1, 2,], + [1, 1, 1, 1, 1, 0.5, 2, 1, 2, 0.5, 0.5, 2, 1, 1, 2, 0.5, 1, 1,], + [1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 0.5, 0.5, 1, 1, 1, 0.5, 1, 1,], + [1, 1, 0.5, 0.5, 2, 2, 0.5, 1, 0.5, 0.5, 2, 0.5, 1, 1, 1, 0.5, 1, 1,], + [1, 1, 2, 1, 0, 1, 1, 1, 1, 1, 2, 0.5, 0.5, 1, 1, 0.5, 1, 1,], + [1, 2, 1, 2, 1, 1, 1, 1, 0.5, 1, 1, 1, 1, 0.5, 1, 1, 0, 1,], + [1, 1, 2, 1, 2, 1, 1, 1, 0.5, 0.5, 0.5, 2, 1, 1, 0.5, 2, 1, 1,], + [1, 1, 1, 1, 1, 1, 1, 1, 0.5, 1, 1, 1, 1, 1, 1, 2, 1, 0,], + [1, 0.5, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 0.5, 0.5,], + [1, 2, 1, 0.5, 1, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 1, 1, 2, 2, 1]] + + print(chart[attacking.rawValue][defending.rawValue]) + return chart[attacking.rawValue][defending.rawValue] } // http://bulbapedia.bulbagarden.net/wiki/Damage From 3eb39fc5fad152b73c422f81a8443787559d75e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 27 Feb 2017 10:57:40 +0100 Subject: [PATCH 04/23] Added building and testing scripts --- compile.sh | 1 + test.sh | 1 + 2 files changed, 2 insertions(+) create mode 100755 compile.sh create mode 100755 test.sh diff --git a/compile.sh b/compile.sh new file mode 100755 index 0000000..d942049 --- /dev/null +++ b/compile.sh @@ -0,0 +1 @@ +sudo docker build . diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..6457f63 --- /dev/null +++ b/test.sh @@ -0,0 +1 @@ +sudo wercker build From f476841223befecd9e374b9895da4001d41139c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 27 Feb 2017 10:58:53 +0100 Subject: [PATCH 05/23] Started implementing the damage function --- Sources/swift_exercises.swift | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index f119712..8a6250a 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -121,8 +121,6 @@ func ==(lhs: Species, rhs: Species) -> Bool { return lhs.id == rhs.id } -// wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww ho-oh a l'air chiant -// tulio c'est un baka qui sèche les cours donc je lui montre comment ça marche git // TODO: create some species // Do you use an enum, a map or constants/variables? // http://bulbapedia.bulbagarden.net/wiki/List_of_Pokémon_by_National_Pokédex_number @@ -175,13 +173,26 @@ func typeModifier(attacking: Type, defending : Type) -> Double { [1, 0.5, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 0.5, 0.5,], [1, 2, 1, 0.5, 1, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 1, 1, 2, 2, 1]] - print(chart[attacking.rawValue][defending.rawValue]) return chart[attacking.rawValue][defending.rawValue] } // http://bulbapedia.bulbagarden.net/wiki/Damage func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pokemon) -> Int { - // TODO + let pkmType = pokemon.species.type; + let tarType = target.species.type; + + let targets: Double = 1 + let weather: Double = 1 + let badge: Double = 1 + let critical: Double = 1 + let random: Double = 1 + let stab: Double = (move.type == pkmType.0 || move.type == pkmType.1!) ? 1.5 : 1 + let type: Double = typeModifier(attacking: move.type, defending: tarType.0) * ((tarType.1 != nil) ? typeModifier(attacking: move.type, defending: tarType.1!) : 1) + let burn: Double = 1 + let other: Double = 1 + + let modifier: Double = targets * weather * badge * critical * random * stab * type * burn * other + return 0 } From 63d6661d25b669dcec010b2b13974c16bc7156e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 27 Feb 2017 11:37:30 +0100 Subject: [PATCH 06/23] Added the critical hit computation --- Sources/swift_exercises.swift | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 8a6250a..6861bdb 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -1,3 +1,7 @@ +// For random numbers in linux: +import Glibc +import Foundation + // http://bulbapedia.bulbagarden.net/wiki/Type enum Type: Int { case bug = 6 @@ -184,14 +188,14 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok let targets: Double = 1 let weather: Double = 1 let badge: Double = 1 - let critical: Double = 1 - let random: Double = 1 + let critical: Double = Int(random() % 256) > (pokemon.species.base_values.speed / 2) ? 1.5 : 0 + let random_value: Double = 1 let stab: Double = (move.type == pkmType.0 || move.type == pkmType.1!) ? 1.5 : 1 let type: Double = typeModifier(attacking: move.type, defending: tarType.0) * ((tarType.1 != nil) ? typeModifier(attacking: move.type, defending: tarType.1!) : 1) let burn: Double = 1 let other: Double = 1 - let modifier: Double = targets * weather * badge * critical * random * stab * type * burn * other + let modifier: Double = targets * weather * badge * critical * random_value * stab * type * burn * other return 0 } From 2704eb1707f9d7bba355ce8c12d695d2d52cd5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 27 Feb 2017 15:30:18 +0100 Subject: [PATCH 07/23] Implemented the effective stats --- Sources/swift_exercises.swift | 113 ++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 33 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 6861bdb..8c56edc 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -32,32 +32,32 @@ enum Category { } // http://bulbapedia.bulbagarden.net/wiki/Nature -enum Nature { - case hardy - case lonely - case brave - case adamant - case naughty - case bold - case docile - case relaxed - case impish - case lax - case timid - case hasty - case serious - case jolly - case naive - case modest - case mild - case quiet - case bashful - case rash - case calm - case gentle - case sassy - case careful - case quirky +enum Nature: Int { + case hardy = 0 + case lonely = 1 + case brave = 2 + case adamant = 3 + case naughty = 4 + case bold = 5 + case docile = 6 + case relaxed = 7 + case impish = 8 + case lax = 9 + case timid = 10 + case hasty = 11 + case serious = 12 + case jolly = 13 + case naive = 14 + case modest = 15 + case mild = 16 + case quiet = 17 + case bashful = 18 + case rash = 19 + case calm = 20 + case gentle = 21 + case sassy = 22 + case careful = 23 + case quirky = 24 } // http://bulbapedia.bulbagarden.net/wiki/Weather @@ -131,7 +131,6 @@ func ==(lhs: Species, rhs: Species) -> Bool { struct Pokemon { let nickname : String? - let hitpoints : Int // remaining hitpoints let size : Int let weight : Int let experience : Int @@ -143,8 +142,56 @@ struct Pokemon { let effort_values : Stats // TODO: implement the effective stats as a computed property: // https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-ID259 - // var effective_stats : Stats { - // } + var effective_stats : Stats { + get { + // attack, defence, special attack, special defense, speed + let natureChart: [[Double]] = [[1.1, 0.9, 1, 1, 1], + [1.1, 1, 1, 1, 0.9], + [1.1, 1, 0.9, 1, 1], + [1.1, 1, 1, 0.9, 1], + [0.9, 1.1, 1, 1, 1], + [1, 1, 1, 1, 1], + [1, 1.1, 1, 1, 0.9], + [1, 1.1, 0.9, 1, 1], + [1, 1.1, 1, 0.9, 1], + [0.9, 1.1, 1, 1, 1.1], + [1, 0.9, 1, 1, 1.1], + [1, 1, 1, 1, 1], + [1, 1.1, 0.9, 1, 1.1], + [1, 1.1, 1, 0.9, 1.1], + [0.9, 1, 1.1, 1, 1], + [1, 0.9, 1.1, 1, 1], + [1, 1, 1.1, 1, 0.9], + [1, 1, 1, 1, 1], + [1, 1, 1.1, 0.9, 1], + [0.9, 1, 1, 1.1, 1], + [1, 0.9, 1, 1.1, 1], + [1, 1, 1, 1.1, 0.9], + [1, 1, 0.9, 1.1, 1], + [1, 1, 1, 1, 1]] + + // var to compute the different stats in multiple lines without declaring tons of temporary variables + var hp = Int((2 * species.base_values.hitpoints + individual_values.hitpoints + Int(effort_values.hitpoints / 4) * level) / 100) + hp = hp + level + 10; + + var att = Int((2 * species.base_values.attack + individual_values.attack + Int(effort_values.attack / 4) * level) / 100) + att = Int(Double(att + 5) * natureChart[nature.rawValue][0]) + + var def = Int((2 * species.base_values.defense + individual_values.defense + Int(effort_values.defense / 4) * level) / 100) + def = Int(Double(def + 5) * natureChart[nature.rawValue][1]) + + var satt = Int((2 * species.base_values.special_attack + individual_values.special_attack + Int(effort_values.special_attack / 4) * level) / 100) + satt = Int(Double(satt + 5) * natureChart[nature.rawValue][2]) + + var sdef = Int((2 * species.base_values.special_defense + individual_values.special_defense + Int(effort_values.special_defense / 4) * level) / 100) + sdef = Int(Double(sdef + 5) * natureChart[nature.rawValue][3]) + + var spe = Int((2 * species.base_values.speed + individual_values.speed + Int(effort_values.speed / 4) * level) / 100) + spe = Int(Double(spe + 5) * natureChart[nature.rawValue][4]) + + return Stats(hitpoints: hp, attack: att, defense: def, special_attack: satt, special_defense: sdef, speed: spe) + } + } } struct Trainer { @@ -185,11 +232,11 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok let pkmType = pokemon.species.type; let tarType = target.species.type; - let targets: Double = 1 + let targets: Double = 1 // won't be implemented let weather: Double = 1 - let badge: Double = 1 - let critical: Double = Int(random() % 256) > (pokemon.species.base_values.speed / 2) ? 1.5 : 0 - let random_value: Double = 1 + let badge: Double = 1 // won't be implemented + let critical: Double = Int(random() % 256) > (pokemon.species.base_values.speed / 2) ? 1.5 : 1 + let random_value: Double = (100 - Double(random() % 16))/100 let stab: Double = (move.type == pkmType.0 || move.type == pkmType.1!) ? 1.5 : 1 let type: Double = typeModifier(attacking: move.type, defending: tarType.0) * ((tarType.1 != nil) ? typeModifier(attacking: move.type, defending: tarType.1!) : 1) let burn: Double = 1 From 68c95592d4ff16b679ce0c6f80f7ca2b4ae3cd53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 27 Feb 2017 17:50:25 +0100 Subject: [PATCH 08/23] Implemented Ho-Oh and Groundquake --- Sources/swift_exercises.swift | 47 +++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 8c56edc..de8d904 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -80,6 +80,18 @@ enum Terrain { case misty } +let earthquake: Move = Move( + id: 89, + name: "Earthquake", + description: "Tough but useless vs. flying foes.", + category: .physical, + type: .ground, + power: 100, + accuracy: 100, + powerpoints: 10, + priority: 0 +) + // http://bulbapedia.bulbagarden.net/wiki/Move struct Move : Hashable { let id : Int @@ -129,17 +141,36 @@ func ==(lhs: Species, rhs: Species) -> Bool { // Do you use an enum, a map or constants/variables? // http://bulbapedia.bulbagarden.net/wiki/List_of_Pokémon_by_National_Pokédex_number +let hooh: Pokemon = Pokemon( + nickname: "fuck pokemon", + size: 3.8, + weight: 199, + level: 100, + nature: .relaxed, + species: Species( + id: 253, name: "Ho-Oh", evolutions: [], attacks: [], type: (.fire, .flying), base_values: Stats(hitpoints: 106, attack: 130, defense: 90, special_attack: 110, special_defense: 154, speed: 90) + ), + moves: [:], + individual_values: Stats(hitpoints: 15, attack: 21, defense: 23, special_attack: 12, special_defense: 26, speed: 24), + effort_values: Stats(hitpoints: 66, attack: 100, defense: 60, special_attack: 30, special_defense: 75, speed: 90) +) + + + struct Pokemon { let nickname : String? - let size : Int - let weight : Int - let experience : Int + let size : Double + let weight : Double let level : Int + var experience : Int { + return 4*level*level*level/45 + } let nature : Nature let species : Species let moves : [Move: Int] // Move -> remaining powerpoints let individual_values : Stats let effort_values : Stats + // TODO: implement the effective stats as a computed property: // https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-ID259 var effective_stats : Stats { @@ -170,6 +201,8 @@ struct Pokemon { [1, 1, 0.9, 1.1, 1], [1, 1, 1, 1, 1]] + // ****************************** ASK 4 HALP CUZ IDK HOW TO TEST THIS SHIT AND WHETHER I HAVE TO USE SELF. + // var to compute the different stats in multiple lines without declaring tons of temporary variables var hp = Int((2 * species.base_values.hitpoints + individual_values.hitpoints + Int(effort_values.hitpoints / 4) * level) / 100) hp = hp + level + 10; @@ -232,11 +265,11 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok let pkmType = pokemon.species.type; let tarType = target.species.type; - let targets: Double = 1 // won't be implemented + let targets: Double = 1 // won't be implemented... soon let weather: Double = 1 - let badge: Double = 1 // won't be implemented + let badge: Double = 1 // won't be implemented... son let critical: Double = Int(random() % 256) > (pokemon.species.base_values.speed / 2) ? 1.5 : 1 - let random_value: Double = (100 - Double(random() % 16))/100 + let random_value: Double = (100 - Double(random() % 16)) / 100 let stab: Double = (move.type == pkmType.0 || move.type == pkmType.1!) ? 1.5 : 1 let type: Double = typeModifier(attacking: move.type, defending: tarType.0) * ((tarType.1 != nil) ? typeModifier(attacking: move.type, defending: tarType.1!) : 1) let burn: Double = 1 @@ -248,7 +281,7 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok } struct State { - // TODO: describe a battle state + } func battle(trainers: inout [Trainer], behavior: (State, Trainer) -> Move) -> () { From 08c3521ec37d4cb872f5d785c34d68a168fa90be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 6 Mar 2017 09:42:48 +0100 Subject: [PATCH 09/23] Started implementing the battle / state --- Sources/swift_exercises.swift | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index de8d904..b2cb8c3 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -229,6 +229,7 @@ struct Pokemon { struct Trainer { let pokemons : [Pokemon] + let human: Bool } struct Environment { @@ -260,6 +261,17 @@ func typeModifier(attacking: Type, defending : Type) -> Double { return chart[attacking.rawValue][defending.rawValue] } +enum Action { + case attack + case change_pokemon + case use_item + case run +} + +func trainer_choose_action(trainer: Trainer) -> Action { + return .attack +} + // http://bulbapedia.bulbagarden.net/wiki/Damage func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pokemon) -> Int { let pkmType = pokemon.species.type; @@ -281,7 +293,30 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok } struct State { + let environment: Environment + let pokemon_fighting: [Pokemon] + let active_trainer: Int // 0 if first player, 1 if second + let on_going: Bool // do we need to initialize everything, or is it already done and pokemon are fighting +} + +func select_pokemon(trainer: Trainer) -> Pokemon? { + var selected: Pokemon? = nil; + + for pkm in trainer.pokemons { + if pkm.effective_stats.hitpoints > 0 { + selected = pkm; + break; + } + } + + return selected +} + +func battle_init(trainers: [Trainer]) -> State { + let environment: Environment = Environment(weather: .clear_skies, terrain: .normal); + let pkm: [Pokemon] = [select_pokemon(trainer: trainers[0])!, select_pokemon(trainer: trainers[1])!]; + return State(environment: environment, pokemon_fighting: pkm, active_trainer: 0, on_going: true) } func battle(trainers: inout [Trainer], behavior: (State, Trainer) -> Move) -> () { From 00766639599ba92685072cc87689afc81323e242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 6 Mar 2017 10:49:42 +0100 Subject: [PATCH 10/23] Updated the state initialization --- Sources/swift_exercises.swift | 50 ++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index b2cb8c3..4de263c 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -292,21 +292,32 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok return 0 } +enum Winner { + case p1 + case p2 + case none +} + +// has to be initialized before calling battle struct State { let environment: Environment - let pokemon_fighting: [Pokemon] + let trainers: [Trainer] + let pokemon_fighting: [Int] // Indice of the fighting pokemon for the two players let active_trainer: Int // 0 if first player, 1 if second - let on_going: Bool // do we need to initialize everything, or is it already done and pokemon are fighting + let finished: Bool + let winner: Winner } -func select_pokemon(trainer: Trainer) -> Pokemon? { - var selected: Pokemon? = nil; +func select_pokemon(trainer: Trainer) -> Int? { + var selected: Int? = nil; + var indice: Int = 0 for pkm in trainer.pokemons { if pkm.effective_stats.hitpoints > 0 { - selected = pkm; + selected = indice; break; } + indice += 1; } return selected @@ -314,11 +325,32 @@ func select_pokemon(trainer: Trainer) -> Pokemon? { func battle_init(trainers: [Trainer]) -> State { let environment: Environment = Environment(weather: .clear_skies, terrain: .normal); - let pkm: [Pokemon] = [select_pokemon(trainer: trainers[0])!, select_pokemon(trainer: trainers[1])!]; + let pkm1: Int? = select_pokemon(trainer: trainers[0]); + let pkm2: Int? = select_pokemon(trainer: trainers[1]); + var active_trainer: Int = 0; + var winner: Winner = .none; + var finished: Bool = true; + + if(pkm1 == nil && pkm2 != nil) { + winner = .p2; + } + + else if(pkm1 != nil && pkm2 == nil) { + winner = .p1; + } + + else if(pkm1 != nil && pkm2 != nil) { + if(trainers[0].pokemons[pkm2!].effective_stats.speed < trainers[1].pokemons[pkm2!].effective_stats.speed) { + active_trainer = 1; + } + finished = false; + } - return State(environment: environment, pokemon_fighting: pkm, active_trainer: 0, on_going: true) + return State(environment: environment, trainers: trainers, pokemon_fighting: [pkm1!, pkm2!], active_trainer: active_trainer, finished: finished, winner: winner) } -func battle(trainers: inout [Trainer], behavior: (State, Trainer) -> Move) -> () { - // TODO: simulate battle +// var state: State = battle_init(trainers) +// state = battle(state) +func battle(state: State) -> State { + return state } From a781d5652997f9fb78160bcdd89679040373db0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 6 Mar 2017 11:43:53 +0100 Subject: [PATCH 11/23] Organized the battle function a bit more, implemented the 'change pokemon' action --- Sources/swift_exercises.swift | 66 ++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 4de263c..1ecbd98 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -261,17 +261,6 @@ func typeModifier(attacking: Type, defending : Type) -> Double { return chart[attacking.rawValue][defending.rawValue] } -enum Action { - case attack - case change_pokemon - case use_item - case run -} - -func trainer_choose_action(trainer: Trainer) -> Action { - return .attack -} - // http://bulbapedia.bulbagarden.net/wiki/Damage func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pokemon) -> Int { let pkmType = pokemon.species.type; @@ -308,6 +297,17 @@ struct State { let winner: Winner } +enum Action { + case attack + case change_pokemon + case use_item + case run +} + +func choose_action(trainer: Trainer) -> Action { + return .attack +} + func select_pokemon(trainer: Trainer) -> Int? { var selected: Int? = nil; var indice: Int = 0 @@ -352,5 +352,47 @@ func battle_init(trainers: [Trainer]) -> State { // var state: State = battle_init(trainers) // state = battle(state) func battle(state: State) -> State { - return state + if(state.finished) { + return state + } + + let environment: Environment = state.environment; + + let active_trainer_indice: Int = state.active_trainer; + let other_trainer_indice: Int = (active_trainer_indice+1)%2; + + let active_trainer: Trainer = state.trainers[active_trainer_indice]; + let other_trainer: Trainer = state.trainers[other_trainer_indice]; + + var active_pkm_indice: Int = state.pokemon_fighting[active_trainer_indice]; + var other_pkm_indice: Int = state.pokemon_fighting[other_trainer_indice]; + + var active_pkm: Pokemon = active_trainer.pokemons[active_pkm_indice]; + var other_pkm: Pokemon = other_trainer.pokemons[other_pkm_indice]; + + var winner: Winner = state.winner; + var finished: Bool = false; + + switch choose_action(trainer: active_trainer) { + case .attack: + print("lol"); + case .run: + print("lol"); + case .change_pokemon: + let new_indice = select_pokemon(trainer: active_trainer); + if(new_indice == nil) { + winner = (active_trainer_indice == 0) ? .p2 : .p1; + finished = true + } + else { + active_pkm_indice = new_indice!; + active_pkm = active_trainer.pokemons[active_pkm_indice]; + } + case .use_item: + print("lol"); + } + + return battle(state: State( environment: environment, trainers: [active_trainer, other_trainer], + pokemon_fighting: [active_pkm_indice, other_pkm_indice], + active_trainer: other_trainer_indice, finished: finished, winner: winner)) } From 76557e72e995d84398c1176e49f8910dc2f8a12a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 6 Mar 2017 11:52:38 +0100 Subject: [PATCH 12/23] Implemented the 'run' action --- Sources/swift_exercises.swift | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 1ecbd98..e27a5f8 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -371,25 +371,26 @@ func battle(state: State) -> State { var other_pkm: Pokemon = other_trainer.pokemons[other_pkm_indice]; var winner: Winner = state.winner; - var finished: Bool = false; + var finished: Bool = state.finished; switch choose_action(trainer: active_trainer) { - case .attack: - print("lol"); - case .run: - print("lol"); - case .change_pokemon: - let new_indice = select_pokemon(trainer: active_trainer); - if(new_indice == nil) { - winner = (active_trainer_indice == 0) ? .p2 : .p1; - finished = true - } - else { - active_pkm_indice = new_indice!; - active_pkm = active_trainer.pokemons[active_pkm_indice]; - } - case .use_item: - print("lol"); + case .attack: + print("lol"); + case .run: + winner = (active_trainer_indice == 0) ? .p2 : .p1; + finished = true; + case .change_pokemon: + let new_indice = select_pokemon(trainer: active_trainer); + if(new_indice == nil) { + winner = (active_trainer_indice == 0) ? .p2 : .p1; + finished = true + } + else { + active_pkm_indice = new_indice!; + active_pkm = active_trainer.pokemons[active_pkm_indice]; + } + case .use_item: + print("lol"); } return battle(state: State( environment: environment, trainers: [active_trainer, other_trainer], From 3afa149213775edd0fa723352b2280a79a1b69f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 6 Mar 2017 15:49:26 +0100 Subject: [PATCH 13/23] Corrected the battle structure, now uses the priority --- Sources/swift_exercises.swift | 101 ++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index e27a5f8..272b2f4 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -155,8 +155,6 @@ let hooh: Pokemon = Pokemon( effort_values: Stats(hitpoints: 66, attack: 100, defense: 60, special_attack: 30, special_defense: 75, speed: 90) ) - - struct Pokemon { let nickname : String? let size : Double @@ -167,7 +165,7 @@ struct Pokemon { } let nature : Nature let species : Species - let moves : [Move: Int] // Move -> remaining powerpoints + let moves : [Move: Int] // Move -> remaining powerpoints ------> c'est un dictionnaire, `moves[earthquake]` = let individual_values : Stats let effort_values : Stats @@ -292,8 +290,6 @@ struct State { let environment: Environment let trainers: [Trainer] let pokemon_fighting: [Int] // Indice of the fighting pokemon for the two players - let active_trainer: Int // 0 if first player, 1 if second - let finished: Bool let winner: Winner } @@ -301,7 +297,7 @@ enum Action { case attack case change_pokemon case use_item - case run + //case run } func choose_action(trainer: Trainer) -> Action { @@ -327,9 +323,7 @@ func battle_init(trainers: [Trainer]) -> State { let environment: Environment = Environment(weather: .clear_skies, terrain: .normal); let pkm1: Int? = select_pokemon(trainer: trainers[0]); let pkm2: Int? = select_pokemon(trainer: trainers[1]); - var active_trainer: Int = 0; var winner: Winner = .none; - var finished: Bool = true; if(pkm1 == nil && pkm2 != nil) { winner = .p2; @@ -339,61 +333,84 @@ func battle_init(trainers: [Trainer]) -> State { winner = .p1; } - else if(pkm1 != nil && pkm2 != nil) { - if(trainers[0].pokemons[pkm2!].effective_stats.speed < trainers[1].pokemons[pkm2!].effective_stats.speed) { - active_trainer = 1; - } - finished = false; - } + return State(environment: environment, trainers: trainers, pokemon_fighting: [pkm1!, pkm2!], winner: winner) +} - return State(environment: environment, trainers: trainers, pokemon_fighting: [pkm1!, pkm2!], active_trainer: active_trainer, finished: finished, winner: winner) +func choose_move(pokemon: Pokemon) -> Move { + let available_moves: [Move] = Array(pokemon.moves.keys).filter{pokemon.moves[$0]! > 0}; // we filter our dict to get an array of moves with PP > 0 + return available_moves[random() % available_moves.count] } // var state: State = battle_init(trainers) // state = battle(state) func battle(state: State) -> State { - if(state.finished) { + if(state.winner != .none) { return state } let environment: Environment = state.environment; - let active_trainer_indice: Int = state.active_trainer; - let other_trainer_indice: Int = (active_trainer_indice+1)%2; - - let active_trainer: Trainer = state.trainers[active_trainer_indice]; - let other_trainer: Trainer = state.trainers[other_trainer_indice]; + let p1: Trainer = state.trainers[0]; + let p2: Trainer = state.trainers[1]; - var active_pkm_indice: Int = state.pokemon_fighting[active_trainer_indice]; - var other_pkm_indice: Int = state.pokemon_fighting[other_trainer_indice]; + var pkm1_ind: Int = state.pokemon_fighting[0]; + var pkm2_ind: Int = state.pokemon_fighting[1]; - var active_pkm: Pokemon = active_trainer.pokemons[active_pkm_indice]; - var other_pkm: Pokemon = other_trainer.pokemons[other_pkm_indice]; + var pkm1: Pokemon = p1.pokemons[pkm1_ind]; + var pkm2: Pokemon = p2.pokemons[pkm2_ind]; var winner: Winner = state.winner; - var finished: Bool = state.finished; - switch choose_action(trainer: active_trainer) { + var move1: Move = earthquake; + var move2: Move = earthquake; + + switch choose_action(trainer: p1) { case .attack: + move1 = choose_move(pokemon: pkm1); + case .change_pokemon: + let new_indice = select_pokemon(trainer: p1); + pkm1_ind = new_indice!; + pkm1 = p1.pokemons[pkm1_ind]; + case .use_item: print("lol"); - case .run: - winner = (active_trainer_indice == 0) ? .p2 : .p1; - finished = true; + } + + switch choose_action(trainer: p2) { + case .attack: + move2 = choose_move(pokemon: pkm2); case .change_pokemon: - let new_indice = select_pokemon(trainer: active_trainer); - if(new_indice == nil) { - winner = (active_trainer_indice == 0) ? .p2 : .p1; - finished = true - } - else { - active_pkm_indice = new_indice!; - active_pkm = active_trainer.pokemons[active_pkm_indice]; - } + let new_indice = select_pokemon(trainer: p2); + pkm2_ind = new_indice!; + pkm2 = p2.pokemons[pkm2_ind]; case .use_item: print("lol"); } - return battle(state: State( environment: environment, trainers: [active_trainer, other_trainer], - pokemon_fighting: [active_pkm_indice, other_pkm_indice], - active_trainer: other_trainer_indice, finished: finished, winner: winner)) + let first_to_attack: Int; + + if(pkm1.moves[move1]! > pkm1.moves[move2]!) { + first_to_attack = 0; + } + + else if(pkm1.moves[move1]! < pkm1.moves[move2]!) { + first_to_attack = 1; + } + + else { + if(pkm1.effective_stats.speed > pkm2.effective_stats.speed) { + first_to_attack = 0; + } + else if(pkm1.effective_stats.speed < pkm2.effective_stats.speed) { + first_to_attack = 1; + } + else { + first_to_attack = random() % 2; + } + } + + + + // new turn + return battle(state: State( environment: environment, trainers: [p1, p2], + pokemon_fighting: [pkm1_ind, pkm2_ind], winner: winner)) } From b4c3465604536573302c4c404cd3b29eee6b514f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Mon, 6 Mar 2017 17:39:57 +0100 Subject: [PATCH 14/23] (Slightly) better organisation, maybe, and somewhat continued to implement the battle --- Sources/swift_exercises.swift | 108 ++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 44 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 272b2f4..5e63e18 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -114,7 +114,7 @@ func ==(lhs: Move, rhs: Move) -> Bool { // http://bulbapedia.bulbagarden.net/wiki/Statistic struct Stats { - let hitpoints : Int + var hitpoints : Int let attack : Int let defense : Int let special_attack : Int @@ -165,7 +165,7 @@ struct Pokemon { } let nature : Nature let species : Species - let moves : [Move: Int] // Move -> remaining powerpoints ------> c'est un dictionnaire, `moves[earthquake]` = + var moves : [Move: Int] // Move -> remaining powerpoints ------> c'est un dictionnaire, `moves[earthquake]` = let individual_values : Stats let effort_values : Stats @@ -341,6 +341,46 @@ func choose_move(pokemon: Pokemon) -> Move { return available_moves[random() % available_moves.count] } +func choose_first(pkm1: Pokemon, pkm2: Pokemon, move1: Move?, move2: Move?) -> [Int] { + var order: [Int]; + + if(move1 == nil) { + order = [1]; + } + + else if(move2 == nil) { + order = [0]; + } + + else if (move1 == nil && move2 == nil) + { + order = []; + } + + else if (pkm1.moves[move1!]! > pkm1.moves[move2!]!) { + order = [0,1]; + } + + else if(pkm1.moves[move1!]! < pkm1.moves[move2!]!) { + order = [1,0]; + } + + else { + if(pkm1.effective_stats.speed > pkm2.effective_stats.speed) { + order = [0,1]; + } + else if(pkm1.effective_stats.speed < pkm2.effective_stats.speed) { + order = [1,0]; + } + else { + let tmp = random() % 2; + order = [tmp, (tmp+1)%2]; + } + } + + return order +} + // var state: State = battle_init(trainers) // state = battle(state) func battle(state: State) -> State { @@ -350,67 +390,47 @@ func battle(state: State) -> State { let environment: Environment = state.environment; - let p1: Trainer = state.trainers[0]; - let p2: Trainer = state.trainers[1]; - - var pkm1_ind: Int = state.pokemon_fighting[0]; - var pkm2_ind: Int = state.pokemon_fighting[1]; - - var pkm1: Pokemon = p1.pokemons[pkm1_ind]; - var pkm2: Pokemon = p2.pokemons[pkm2_ind]; - + let p: [Trainer] = state.trainers; + var pkm_ind: [Int] = state.pokemon_fighting; + var pkm: [Pokemon] = [p[0].pokemons[pkm_ind[0]], p[1].pokemons[pkm_ind[1]]]; var winner: Winner = state.winner; - var move1: Move = earthquake; - var move2: Move = earthquake; + var move: [Move?] = [nil]; - switch choose_action(trainer: p1) { + switch choose_action(trainer: p[0]) { case .attack: - move1 = choose_move(pokemon: pkm1); + move[0] = choose_move(pokemon: pkm[0]); case .change_pokemon: - let new_indice = select_pokemon(trainer: p1); - pkm1_ind = new_indice!; - pkm1 = p1.pokemons[pkm1_ind]; + let new_indice = select_pokemon(trainer: p[0]); + pkm_ind[0] = new_indice!; + pkm[0] = p[0].pokemons[pkm_ind[0]]; case .use_item: print("lol"); } - switch choose_action(trainer: p2) { + switch choose_action(trainer: p[1]) { case .attack: - move2 = choose_move(pokemon: pkm2); + move[1] = choose_move(pokemon: pkm[1]); case .change_pokemon: - let new_indice = select_pokemon(trainer: p2); - pkm2_ind = new_indice!; - pkm2 = p2.pokemons[pkm2_ind]; + let new_indice = select_pokemon(trainer: p[1]); + pkm_ind[1] = new_indice!; + pkm[1] = p[1].pokemons[pkm_ind[1]]; case .use_item: print("lol"); } - let first_to_attack: Int; - - if(pkm1.moves[move1]! > pkm1.moves[move2]!) { - first_to_attack = 0; - } - - else if(pkm1.moves[move1]! < pkm1.moves[move2]!) { - first_to_attack = 1; - } + let order: [Int] = choose_first(pkm1: pkm[0], pkm2: pkm[1], move1: move[0], move2: move[1]); - else { - if(pkm1.effective_stats.speed > pkm2.effective_stats.speed) { - first_to_attack = 0; - } - else if(pkm1.effective_stats.speed < pkm2.effective_stats.speed) { - first_to_attack = 1; - } - else { - first_to_attack = random() % 2; + for ind in order { + pkm[ind].moves[move[ind]!] = 1; + if(random()%100 < move[ind]!.accuracy) { + let dmg = damage(environment: environment, pokemon: pkm[ind], move: move[ind]!, target: pkm[(ind+1)%2]); + //pkm[(ind+1)%2].effective_stats.hitpoints = dmg; } } - // new turn - return battle(state: State( environment: environment, trainers: [p1, p2], - pokemon_fighting: [pkm1_ind, pkm2_ind], winner: winner)) + return battle(state: State( environment: environment, trainers: p, + pokemon_fighting: pkm_ind, winner: winner)) } From 5a5d1229d3cbd33aacc09c67ec357f89f34d9268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Tue, 7 Mar 2017 11:13:30 +0100 Subject: [PATCH 15/23] Added the battle_stats attribut in Pokemon, factorized the battle function --- Sources/swift_exercises.swift | 108 +++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 47 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 5e63e18..e6aac7e 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -165,7 +165,7 @@ struct Pokemon { } let nature : Nature let species : Species - var moves : [Move: Int] // Move -> remaining powerpoints ------> c'est un dictionnaire, `moves[earthquake]` = + var moves : [Move: Int] // Move -> remaining powerpoints (dict) let individual_values : Stats let effort_values : Stats @@ -174,30 +174,30 @@ struct Pokemon { var effective_stats : Stats { get { // attack, defence, special attack, special defense, speed - let natureChart: [[Double]] = [[1.1, 0.9, 1, 1, 1], - [1.1, 1, 1, 1, 0.9], - [1.1, 1, 0.9, 1, 1], - [1.1, 1, 1, 0.9, 1], - [0.9, 1.1, 1, 1, 1], - [1, 1, 1, 1, 1], - [1, 1.1, 1, 1, 0.9], - [1, 1.1, 0.9, 1, 1], - [1, 1.1, 1, 0.9, 1], - [0.9, 1.1, 1, 1, 1.1], - [1, 0.9, 1, 1, 1.1], - [1, 1, 1, 1, 1], - [1, 1.1, 0.9, 1, 1.1], - [1, 1.1, 1, 0.9, 1.1], - [0.9, 1, 1.1, 1, 1], - [1, 0.9, 1.1, 1, 1], - [1, 1, 1.1, 1, 0.9], - [1, 1, 1, 1, 1], - [1, 1, 1.1, 0.9, 1], - [0.9, 1, 1, 1.1, 1], - [1, 0.9, 1, 1.1, 1], - [1, 1, 1, 1.1, 0.9], - [1, 1, 0.9, 1.1, 1], - [1, 1, 1, 1, 1]] + let natureChart: [[Double]] = [ [1.1, 0.9, 1, 1, 1], + [1.1, 1, 1, 1, 0.9], + [1.1, 1, 0.9, 1, 1], + [1.1, 1, 1, 0.9, 1], + [0.9, 1.1, 1, 1, 1], + [1, 1, 1, 1, 1], + [1, 1.1, 1, 1, 0.9], + [1, 1.1, 0.9, 1, 1], + [1, 1.1, 1, 0.9, 1], + [0.9, 1.1, 1, 1, 1.1], + [1, 0.9, 1, 1, 1.1], + [1, 1, 1, 1, 1], + [1, 1.1, 0.9, 1, 1.1], + [1, 1.1, 1, 0.9, 1.1], + [0.9, 1, 1.1, 1, 1], + [1, 0.9, 1.1, 1, 1], + [1, 1, 1.1, 1, 0.9], + [1, 1, 1, 1, 1], + [1, 1, 1.1, 0.9, 1], + [0.9, 1, 1, 1.1, 1], + [1, 0.9, 1, 1.1, 1], + [1, 1, 1, 1.1, 0.9], + [1, 1, 0.9, 1.1, 1], + [1, 1, 1, 1, 1]] // ****************************** ASK 4 HALP CUZ IDK HOW TO TEST THIS SHIT AND WHETHER I HAVE TO USE SELF. @@ -223,6 +223,22 @@ struct Pokemon { return Stats(hitpoints: hp, attack: att, defense: def, special_attack: satt, special_defense: sdef, speed: spe) } } + + var battle_stats : Stats // Copy of effective stats, used during battle + + init(nickname: String?, size: Double, weight: Double, level: Int, nature: Nature, species: Species, moves: [Move: Int], individual_values: Stats, effort_values: Stats) { + self.nickname = nickname; + self.size = size; + self.weight = weight; + self.level = level; + self.nature = nature; + self.species = species; + self.moves = moves; + self.individual_values = individual_values; + self.effort_values = effort_values; + self.battle_stats = self.effort_values; + } + } struct Trainer { @@ -397,38 +413,36 @@ func battle(state: State) -> State { var move: [Move?] = [nil]; - switch choose_action(trainer: p[0]) { - case .attack: - move[0] = choose_move(pokemon: pkm[0]); - case .change_pokemon: - let new_indice = select_pokemon(trainer: p[0]); - pkm_ind[0] = new_indice!; - pkm[0] = p[0].pokemons[pkm_ind[0]]; - case .use_item: - print("lol"); - } - - switch choose_action(trainer: p[1]) { - case .attack: - move[1] = choose_move(pokemon: pkm[1]); - case .change_pokemon: - let new_indice = select_pokemon(trainer: p[1]); - pkm_ind[1] = new_indice!; - pkm[1] = p[1].pokemons[pkm_ind[1]]; - case .use_item: - print("lol"); + for i in 0...1 { + switch choose_action(trainer: p[i]) { + case .attack: + move[i] = choose_move(pokemon: pkm[i]); + case .change_pokemon: + let new_indice = select_pokemon(trainer: p[i]); + pkm_ind[i] = new_indice!; + pkm[i] = p[i].pokemons[pkm_ind[i]]; + case .use_item: + print("lol"); + } } let order: [Int] = choose_first(pkm1: pkm[0], pkm2: pkm[1], move1: move[0], move2: move[1]); for ind in order { - pkm[ind].moves[move[ind]!] = 1; + if(pkm[(ind+1)%2].battle_stats.hitpoints <= 0) { + pkm[ind].moves[move[ind]!]! -= 1; + } if(random()%100 < move[ind]!.accuracy) { let dmg = damage(environment: environment, pokemon: pkm[ind], move: move[ind]!, target: pkm[(ind+1)%2]); - //pkm[(ind+1)%2].effective_stats.hitpoints = dmg; + pkm[(ind+1)%2].battle_stats.hitpoints = dmg; } } + // on calcule une fois *effective* avec IV et effort ey baqse + // on fait une copie d'effective au début de la battle, et on travail avec ça (hitpoints attack speed etc) + // ------------------------------ + // à la fin de la battle, les pkm ont leur effective stats qui ont changé etc... on est obligé de faire une copie ? + // on peut pas juste directement travailler avec ? changer les hp etc // new turn return battle(state: State( environment: environment, trainers: p, From dd5cbd5719b4c3e5df20d53083e859f4fabcea42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Tue, 7 Mar 2017 11:27:48 +0100 Subject: [PATCH 16/23] A player can now change his dead pokemon, and loses if no pokemon left (also simplified the winner attribut) --- Sources/swift_exercises.swift | 48 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index e6aac7e..5901e97 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -142,7 +142,7 @@ func ==(lhs: Species, rhs: Species) -> Bool { // http://bulbapedia.bulbagarden.net/wiki/List_of_Pokémon_by_National_Pokédex_number let hooh: Pokemon = Pokemon( - nickname: "fuck pokemon", + nickname: "kyouko taiga", size: 3.8, weight: 199, level: 100, @@ -295,25 +295,19 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok return 0 } -enum Winner { - case p1 - case p2 - case none -} - // has to be initialized before calling battle struct State { let environment: Environment let trainers: [Trainer] let pokemon_fighting: [Int] // Indice of the fighting pokemon for the two players - let winner: Winner + let winner: Int? // 0 = first player, 1 = second, nil = none } enum Action { case attack case change_pokemon case use_item - //case run + // case run } func choose_action(trainer: Trainer) -> Action { @@ -325,7 +319,7 @@ func select_pokemon(trainer: Trainer) -> Int? { var indice: Int = 0 for pkm in trainer.pokemons { - if pkm.effective_stats.hitpoints > 0 { + if pkm.battle_stats.hitpoints > 0 { selected = indice; break; } @@ -339,14 +333,14 @@ func battle_init(trainers: [Trainer]) -> State { let environment: Environment = Environment(weather: .clear_skies, terrain: .normal); let pkm1: Int? = select_pokemon(trainer: trainers[0]); let pkm2: Int? = select_pokemon(trainer: trainers[1]); - var winner: Winner = .none; + var winner: Int? = nil; if(pkm1 == nil && pkm2 != nil) { - winner = .p2; + winner = 1 } else if(pkm1 != nil && pkm2 == nil) { - winner = .p1; + winner = 0 } return State(environment: environment, trainers: trainers, pokemon_fighting: [pkm1!, pkm2!], winner: winner) @@ -400,7 +394,7 @@ func choose_first(pkm1: Pokemon, pkm2: Pokemon, move1: Move?, move2: Move?) -> [ // var state: State = battle_init(trainers) // state = battle(state) func battle(state: State) -> State { - if(state.winner != .none) { + if(state.winner != nil) { return state } @@ -409,7 +403,7 @@ func battle(state: State) -> State { let p: [Trainer] = state.trainers; var pkm_ind: [Int] = state.pokemon_fighting; var pkm: [Pokemon] = [p[0].pokemons[pkm_ind[0]], p[1].pokemons[pkm_ind[1]]]; - var winner: Winner = state.winner; + var winner: Int? = state.winner; var move: [Move?] = [nil]; @@ -429,21 +423,25 @@ func battle(state: State) -> State { let order: [Int] = choose_first(pkm1: pkm[0], pkm2: pkm[1], move1: move[0], move2: move[1]); for ind in order { - if(pkm[(ind+1)%2].battle_stats.hitpoints <= 0) { + // Damage + if(random() % 100 < move[ind]!.accuracy) { + let dmg = damage(environment: environment, pokemon: pkm[ind], move: move[ind]!, target: pkm[(ind+1)%2]); + pkm[(ind+1)%2].battle_stats.hitpoints -= dmg; pkm[ind].moves[move[ind]!]! -= 1; } - if(random()%100 < move[ind]!.accuracy) { - let dmg = damage(environment: environment, pokemon: pkm[ind], move: move[ind]!, target: pkm[(ind+1)%2]); - pkm[(ind+1)%2].battle_stats.hitpoints = dmg; + + // Check if other pokemon is dead + if(pkm[(ind+1)%2].battle_stats.hitpoints <= 0) { + let new_indice = select_pokemon(trainer: p[ind]); + if(new_indice == nil) { + winner = (ind+1)%2; + break; + } + pkm_ind[ind] = new_indice!; + pkm[ind] = p[ind].pokemons[pkm_ind[ind]]; } } - // on calcule une fois *effective* avec IV et effort ey baqse - // on fait une copie d'effective au début de la battle, et on travail avec ça (hitpoints attack speed etc) - // ------------------------------ - // à la fin de la battle, les pkm ont leur effective stats qui ont changé etc... on est obligé de faire une copie ? - // on peut pas juste directement travailler avec ? changer les hp etc - // new turn return battle(state: State( environment: environment, trainers: p, pokemon_fighting: pkm_ind, winner: winner)) From 434cb073c8997b54ce8a782e76c98a3716fc7a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Tue, 7 Mar 2017 11:33:12 +0100 Subject: [PATCH 17/23] Now uses the type inference a bit more --- Sources/swift_exercises.swift | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 5901e97..1316749 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -330,9 +330,9 @@ func select_pokemon(trainer: Trainer) -> Int? { } func battle_init(trainers: [Trainer]) -> State { - let environment: Environment = Environment(weather: .clear_skies, terrain: .normal); - let pkm1: Int? = select_pokemon(trainer: trainers[0]); - let pkm2: Int? = select_pokemon(trainer: trainers[1]); + let environment = Environment(weather: .clear_skies, terrain: .normal); + let pkm1 = select_pokemon(trainer: trainers[0]); + let pkm2 = select_pokemon(trainer: trainers[1]); var winner: Int? = nil; if(pkm1 == nil && pkm2 != nil) { @@ -347,7 +347,7 @@ func battle_init(trainers: [Trainer]) -> State { } func choose_move(pokemon: Pokemon) -> Move { - let available_moves: [Move] = Array(pokemon.moves.keys).filter{pokemon.moves[$0]! > 0}; // we filter our dict to get an array of moves with PP > 0 + let available_moves = Array(pokemon.moves.keys).filter{pokemon.moves[$0]! > 0}; // we filter our dict to get an array of moves with PP > 0 return available_moves[random() % available_moves.count] } @@ -398,12 +398,12 @@ func battle(state: State) -> State { return state } - let environment: Environment = state.environment; + let environment = state.environment; - let p: [Trainer] = state.trainers; - var pkm_ind: [Int] = state.pokemon_fighting; - var pkm: [Pokemon] = [p[0].pokemons[pkm_ind[0]], p[1].pokemons[pkm_ind[1]]]; - var winner: Int? = state.winner; + let p = state.trainers; + var pkm_ind = state.pokemon_fighting; + var pkm = [p[0].pokemons[pkm_ind[0]], p[1].pokemons[pkm_ind[1]]]; + var winner = state.winner; var move: [Move?] = [nil]; @@ -420,7 +420,7 @@ func battle(state: State) -> State { } } - let order: [Int] = choose_first(pkm1: pkm[0], pkm2: pkm[1], move1: move[0], move2: move[1]); + let order = choose_first(pkm1: pkm[0], pkm2: pkm[1], move1: move[0], move2: move[1]); for ind in order { // Damage From 877c035df280565089572005b4980a218eed4c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Tue, 7 Mar 2017 11:47:35 +0100 Subject: [PATCH 18/23] i want to be ahead in the race of commits --- a | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 a diff --git a/a b/a new file mode 100644 index 0000000..e69de29 From 85b84f307e53b1856ab491bec3bee6ddd438993e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Tue, 7 Mar 2017 11:48:12 +0100 Subject: [PATCH 19/23] deleted a useless file --- a | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 a diff --git a/a b/a deleted file mode 100644 index e69de29..0000000 From 34e897a4fbb3f9021d48150afff08afc560a78b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Tue, 7 Mar 2017 13:50:07 +0100 Subject: [PATCH 20/23] Test the battle function, debbuged the selection of pokemon, and the recursion. runs a simple battle --- Sources/swift_exercises.swift | 42 +++++++++++++------ .../swift_exercisesTests.swift | 10 ++++- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 1316749..af276f0 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -80,7 +80,7 @@ enum Terrain { case misty } -let earthquake: Move = Move( +let earthquake = Move( id: 89, name: "Earthquake", description: "Tough but useless vs. flying foes.", @@ -150,7 +150,7 @@ let hooh: Pokemon = Pokemon( species: Species( id: 253, name: "Ho-Oh", evolutions: [], attacks: [], type: (.fire, .flying), base_values: Stats(hitpoints: 106, attack: 130, defense: 90, special_attack: 110, special_defense: 154, speed: 90) ), - moves: [:], + moves: [earthquake: earthquake.powerpoints], individual_values: Stats(hitpoints: 15, attack: 21, defense: 23, special_attack: 12, special_defense: 26, speed: 24), effort_values: Stats(hitpoints: 66, attack: 100, defense: 60, special_attack: 30, special_defense: 75, speed: 90) ) @@ -242,13 +242,13 @@ struct Pokemon { } struct Trainer { - let pokemons : [Pokemon] + var pokemons : [Pokemon] let human: Bool } struct Environment { - let weather : Weather - let terrain : Terrain + var weather : Weather + var terrain : Terrain } // http://bulbapedia.bulbagarden.net/wiki/Type/Type_chart @@ -292,7 +292,7 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok let modifier: Double = targets * weather * badge * critical * random_value * stab * type * burn * other - return 0 + return 1 } // has to be initialized before calling battle @@ -319,6 +319,7 @@ func select_pokemon(trainer: Trainer) -> Int? { var indice: Int = 0 for pkm in trainer.pokemons { + print("") if pkm.battle_stats.hitpoints > 0 { selected = indice; break; @@ -347,8 +348,16 @@ func battle_init(trainers: [Trainer]) -> State { } func choose_move(pokemon: Pokemon) -> Move { - let available_moves = Array(pokemon.moves.keys).filter{pokemon.moves[$0]! > 0}; // we filter our dict to get an array of moves with PP > 0 - return available_moves[random() % available_moves.count] + var filtered_moves = [Move](); + + for (key, value) in pokemon.moves { + print(value) + if value > 0 { + filtered_moves.append(key) + } + } + + return filtered_moves[random() % filtered_moves.count] } func choose_first(pkm1: Pokemon, pkm2: Pokemon, move1: Move?, move2: Move?) -> [Int] { @@ -398,14 +407,14 @@ func battle(state: State) -> State { return state } - let environment = state.environment; + var environment = state.environment; - let p = state.trainers; + var p = state.trainers; var pkm_ind = state.pokemon_fighting; var pkm = [p[0].pokemons[pkm_ind[0]], p[1].pokemons[pkm_ind[1]]]; var winner = state.winner; - var move: [Move?] = [nil]; + var move: [Move?] = [nil, nil]; for i in 0...1 { switch choose_action(trainer: p[i]) { @@ -421,13 +430,16 @@ func battle(state: State) -> State { } let order = choose_first(pkm1: pkm[0], pkm2: pkm[1], move1: move[0], move2: move[1]); - +print(p[0].pokemons[0].battle_stats.hitpoints); for ind in order { // Damage if(random() % 100 < move[ind]!.accuracy) { let dmg = damage(environment: environment, pokemon: pkm[ind], move: move[ind]!, target: pkm[(ind+1)%2]); pkm[(ind+1)%2].battle_stats.hitpoints -= dmg; pkm[ind].moves[move[ind]!]! -= 1; + p[ind].pokemons[pkm_ind[(ind+1)%2]].battle_stats = pkm[(ind+1)%2].battle_stats; + print("Pokemon ", ind, " attacks pokemon ", (ind+1)%2, " with ", dmg, " damage!"); + } // Check if other pokemon is dead @@ -442,7 +454,11 @@ func battle(state: State) -> State { } } + print("HP pkm 0 : ", p[0].pokemons[0].battle_stats.hitpoints); + print("HP pkm 1 : ", p[1].pokemons[0].battle_stats.hitpoints); + // new turn + return battle(state: State( environment: environment, trainers: p, - pokemon_fighting: pkm_ind, winner: winner)) + pokemon_fighting: pkm_ind, winner: winner)) } diff --git a/Tests/swift-exercisesTests/swift_exercisesTests.swift b/Tests/swift-exercisesTests/swift_exercisesTests.swift index eab452c..d1c1137 100644 --- a/Tests/swift-exercisesTests/swift_exercisesTests.swift +++ b/Tests/swift-exercisesTests/swift_exercisesTests.swift @@ -2,8 +2,16 @@ import XCTest @testable import swift_exercises class swift_exercisesTests: XCTestCase { - + func test_typeModifier() { + let trainer1 = Trainer(pokemons: [hooh], human: false); + let trainer2 = Trainer(pokemons: [hooh], human: false); + var state = battle_init(trainers: [trainer1, trainer2]); + print("AND THEN THERE WERE NONE"); + let state2 = battle(state: state); + if(state.winner == nil) {print("LOOOOOOOOL");} + print(state.trainers[0].pokemons[0].nickname!); + XCTAssertEqual(typeModifier(attacking: Type.normal, defending: Type.normal), 1, "normal/normal should be 1") } From 503d78702fabf6f49ce92981f8510abbb086c406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Wed, 8 Mar 2017 10:55:29 +0100 Subject: [PATCH 21/23] Debbuged few things in the battle function, when a pokemon dies a trainer can now change it --- Sources/swift_exercises.swift | 32 +++++++++---------- .../swift_exercisesTests.swift | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index af276f0..f53146f 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -115,11 +115,11 @@ func ==(lhs: Move, rhs: Move) -> Bool { // http://bulbapedia.bulbagarden.net/wiki/Statistic struct Stats { var hitpoints : Int - let attack : Int - let defense : Int - let special_attack : Int - let special_defense : Int - let speed : Int + var attack : Int + var defense : Int + var special_attack : Int + var special_defense : Int + var speed : Int } struct Species : Hashable { @@ -156,7 +156,7 @@ let hooh: Pokemon = Pokemon( ) struct Pokemon { - let nickname : String? + var nickname : String? let size : Double let weight : Double let level : Int @@ -292,7 +292,7 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok let modifier: Double = targets * weather * badge * critical * random_value * stab * type * burn * other - return 1 + return 1 + (random() % 10)//Int(Double(pokemon.battle_stats.attack) * modifier) } // has to be initialized before calling battle @@ -319,7 +319,6 @@ func select_pokemon(trainer: Trainer) -> Int? { var indice: Int = 0 for pkm in trainer.pokemons { - print("") if pkm.battle_stats.hitpoints > 0 { selected = indice; break; @@ -347,11 +346,11 @@ func battle_init(trainers: [Trainer]) -> State { return State(environment: environment, trainers: trainers, pokemon_fighting: [pkm1!, pkm2!], winner: winner) } +// DOESN'T SEEM TO TAKE POWERPOINTS INTO ACCOUNT func choose_move(pokemon: Pokemon) -> Move { var filtered_moves = [Move](); for (key, value) in pokemon.moves { - print(value) if value > 0 { filtered_moves.append(key) } @@ -430,32 +429,33 @@ func battle(state: State) -> State { } let order = choose_first(pkm1: pkm[0], pkm2: pkm[1], move1: move[0], move2: move[1]); -print(p[0].pokemons[0].battle_stats.hitpoints); + for ind in order { // Damage if(random() % 100 < move[ind]!.accuracy) { let dmg = damage(environment: environment, pokemon: pkm[ind], move: move[ind]!, target: pkm[(ind+1)%2]); pkm[(ind+1)%2].battle_stats.hitpoints -= dmg; pkm[ind].moves[move[ind]!]! -= 1; - p[ind].pokemons[pkm_ind[(ind+1)%2]].battle_stats = pkm[(ind+1)%2].battle_stats; + p[(ind+1)%2].pokemons[pkm_ind[(ind+1)%2]].battle_stats = pkm[(ind+1)%2].battle_stats; print("Pokemon ", ind, " attacks pokemon ", (ind+1)%2, " with ", dmg, " damage!"); } // Check if other pokemon is dead if(pkm[(ind+1)%2].battle_stats.hitpoints <= 0) { - let new_indice = select_pokemon(trainer: p[ind]); + let new_indice = select_pokemon(trainer: p[(ind+1)%2]); + print("NEW INDICE: ", new_indice) if(new_indice == nil) { winner = (ind+1)%2; break; } - pkm_ind[ind] = new_indice!; - pkm[ind] = p[ind].pokemons[pkm_ind[ind]]; + pkm_ind[(ind+1)%2] = new_indice!; + pkm[(ind+1)%2] = p[ind].pokemons[pkm_ind[(ind+1)%2]]; } } - print("HP pkm 0 : ", p[0].pokemons[0].battle_stats.hitpoints); - print("HP pkm 1 : ", p[1].pokemons[0].battle_stats.hitpoints); + print("HP pkm 0 : ", p[0].pokemons[pkm_ind[0]].battle_stats.hitpoints); + print("HP pkm 1 : ", p[1].pokemons[pkm_ind[1]].battle_stats.hitpoints); // new turn diff --git a/Tests/swift-exercisesTests/swift_exercisesTests.swift b/Tests/swift-exercisesTests/swift_exercisesTests.swift index d1c1137..2acdb44 100644 --- a/Tests/swift-exercisesTests/swift_exercisesTests.swift +++ b/Tests/swift-exercisesTests/swift_exercisesTests.swift @@ -4,8 +4,8 @@ import XCTest class swift_exercisesTests: XCTestCase { func test_typeModifier() { - let trainer1 = Trainer(pokemons: [hooh], human: false); - let trainer2 = Trainer(pokemons: [hooh], human: false); + let trainer1 = Trainer(pokemons: [hooh, hooh], human: false); + let trainer2 = Trainer(pokemons: [hooh, hooh], human: false); var state = battle_init(trainers: [trainer1, trainer2]); print("AND THEN THERE WERE NONE"); let state2 = battle(state: state); From de0f360106ff25b8bd458e11a73fb2d6bfc08f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Sun, 12 Mar 2017 22:50:55 +0100 Subject: [PATCH 22/23] Added few moves, debbuged the damage function, continued the battle function --- Sources/swift_exercises.swift | 91 ++++++++++++++----- .../swift_exercisesTests.swift | 10 +- 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index f53146f..931a1a1 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -92,6 +92,42 @@ let earthquake = Move( priority: 0 ) +let solar_beam = Move( + id: 76, + name: "Solar Beam", + description: "Super beam (very strong!!!)", + category: .special, + type: .grass, + power: 120, + accuracy: 100, + powerpoints: 10, + priority: 0 +) + +let thunder = Move( + id: 87, + name: "Thunder", + description: "Super thunder (!!!)", + category: .special, + type: .electric, + power: 110, + accuracy: 70, + powerpoints: 10, + priority: 0 +) + +let facade = Move( + id: 263, + name: "Facade", + description: "it was merely an act xddddddddd", + category: .physical, + type: .normal, + power: 70, + accuracy: 100, + powerpoints: 20, + priority: 0 +) + // http://bulbapedia.bulbagarden.net/wiki/Move struct Move : Hashable { let id : Int @@ -150,7 +186,8 @@ let hooh: Pokemon = Pokemon( species: Species( id: 253, name: "Ho-Oh", evolutions: [], attacks: [], type: (.fire, .flying), base_values: Stats(hitpoints: 106, attack: 130, defense: 90, special_attack: 110, special_defense: 154, speed: 90) ), - moves: [earthquake: earthquake.powerpoints], + moves: [ earthquake: earthquake.powerpoints, solar_beam: solar_beam.powerpoints, + thunder: thunder.powerpoints, facade: facade.powerpoints], individual_values: Stats(hitpoints: 15, attack: 21, defense: 23, special_attack: 12, special_defense: 26, speed: 24), effort_values: Stats(hitpoints: 66, attack: 100, defense: 60, special_attack: 30, special_defense: 75, speed: 90) ) @@ -199,28 +236,32 @@ struct Pokemon { [1, 1, 0.9, 1.1, 1], [1, 1, 1, 1, 1]] - // ****************************** ASK 4 HALP CUZ IDK HOW TO TEST THIS SHIT AND WHETHER I HAVE TO USE SELF. - - // var to compute the different stats in multiple lines without declaring tons of temporary variables - var hp = Int((2 * species.base_values.hitpoints + individual_values.hitpoints + Int(effort_values.hitpoints / 4) * level) / 100) - hp = hp + level + 10; + // swift is shit omfg i can't even do this in one line wtf i non-unironically have to cut this formula in multiple lines and wow i don't even + let hp1 = 2 * species.base_values.hitpoints + individual_values.hitpoints; + let hp2 = Double(hp1 + (effort_values.hitpoints / 4) * level) / 100 + let hp3 = Int(floor(hp2) + Double(level) + 10); - var att = Int((2 * species.base_values.attack + individual_values.attack + Int(effort_values.attack / 4) * level) / 100) - att = Int(Double(att + 5) * natureChart[nature.rawValue][0]) + let att1 = 2 * species.base_values.attack + individual_values.attack; + let att2 = Double(att1 + (effort_values.attack / 4) * level) / 100 + let att3 = Int(floor(Double(floor(att2) + 5) * natureChart[nature.rawValue][0])) - var def = Int((2 * species.base_values.defense + individual_values.defense + Int(effort_values.defense / 4) * level) / 100) - def = Int(Double(def + 5) * natureChart[nature.rawValue][1]) + let def1 = 2 * species.base_values.defense + individual_values.defense + let def2 = Double(def1 + (effort_values.defense / 4) * level) / 100 + let def3 = Int(floor(Double(floor(def2) + 5) * natureChart[nature.rawValue][1])) - var satt = Int((2 * species.base_values.special_attack + individual_values.special_attack + Int(effort_values.special_attack / 4) * level) / 100) - satt = Int(Double(satt + 5) * natureChart[nature.rawValue][2]) + let satt1 = 2 * species.base_values.special_attack + individual_values.special_attack + let satt2 = Double(satt1 + (effort_values.special_attack / 4) * level) / 100 + let satt3 = Int(floor(Double(floor(satt2) + 5) * natureChart[nature.rawValue][2])) - var sdef = Int((2 * species.base_values.special_defense + individual_values.special_defense + Int(effort_values.special_defense / 4) * level) / 100) - sdef = Int(Double(sdef + 5) * natureChart[nature.rawValue][3]) + let sdef1 = 2 * species.base_values.special_defense + individual_values.special_defense + let sdef2 = Double(sdef1 + (effort_values.special_defense / 4) * level) / 100 + let sdef3 = Int(floor(Double(floor(sdef2) + 5) * natureChart[nature.rawValue][3])) - var spe = Int((2 * species.base_values.speed + individual_values.speed + Int(effort_values.speed / 4) * level) / 100) - spe = Int(Double(spe + 5) * natureChart[nature.rawValue][4]) + let spe1 = 2 * species.base_values.speed + individual_values.speed + let spe2 = Double(spe1 + (effort_values.speed / 4) * level) / 100 + let spe3 = Int(floor(Double(floor(spe2) + 5) * natureChart[nature.rawValue][4])) - return Stats(hitpoints: hp, attack: att, defense: def, special_attack: satt, special_defense: sdef, speed: spe) + return Stats(hitpoints: hp3, attack: att3, defense: def3, special_attack: satt3, special_defense: sdef3, speed: spe3) } } @@ -280,9 +321,9 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok let pkmType = pokemon.species.type; let tarType = target.species.type; - let targets: Double = 1 // won't be implemented... soon + let targets: Double = 1 let weather: Double = 1 - let badge: Double = 1 // won't be implemented... son + let badge: Double = 1 let critical: Double = Int(random() % 256) > (pokemon.species.base_values.speed / 2) ? 1.5 : 1 let random_value: Double = (100 - Double(random() % 16)) / 100 let stab: Double = (move.type == pkmType.0 || move.type == pkmType.1!) ? 1.5 : 1 @@ -292,7 +333,7 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok let modifier: Double = targets * weather * badge * critical * random_value * stab * type * burn * other - return 1 + (random() % 10)//Int(Double(pokemon.battle_stats.attack) * modifier) + return Int(Double(pokemon.battle_stats.attack) * modifier) } // has to be initialized before calling battle @@ -435,20 +476,26 @@ func battle(state: State) -> State { if(random() % 100 < move[ind]!.accuracy) { let dmg = damage(environment: environment, pokemon: pkm[ind], move: move[ind]!, target: pkm[(ind+1)%2]); pkm[(ind+1)%2].battle_stats.hitpoints -= dmg; + if(pkm[(ind+1)%2].battle_stats.hitpoints < 0) {pkm[(ind+1)%2].battle_stats.hitpoints = 0}; pkm[ind].moves[move[ind]!]! -= 1; p[(ind+1)%2].pokemons[pkm_ind[(ind+1)%2]].battle_stats = pkm[(ind+1)%2].battle_stats; - print("Pokemon ", ind, " attacks pokemon ", (ind+1)%2, " with ", dmg, " damage!"); + print("Pokemon ", ind, " attacks pokemon ", (ind+1)%2, " with ", move[ind]!.name, " (", dmg, " damage!)"); } + else { + print("Pokemon ", ind, " attacks pokemon ", (ind+1)%2, " with ", move[ind]!.name, " but... misses"); + pkm[ind].moves[move[ind]!]! -= 1; + } + // Check if other pokemon is dead if(pkm[(ind+1)%2].battle_stats.hitpoints <= 0) { let new_indice = select_pokemon(trainer: p[(ind+1)%2]); - print("NEW INDICE: ", new_indice) if(new_indice == nil) { winner = (ind+1)%2; break; } + print("New pokemon for player ", ind) pkm_ind[(ind+1)%2] = new_indice!; pkm[(ind+1)%2] = p[ind].pokemons[pkm_ind[(ind+1)%2]]; } diff --git a/Tests/swift-exercisesTests/swift_exercisesTests.swift b/Tests/swift-exercisesTests/swift_exercisesTests.swift index 2acdb44..5dfdfa9 100644 --- a/Tests/swift-exercisesTests/swift_exercisesTests.swift +++ b/Tests/swift-exercisesTests/swift_exercisesTests.swift @@ -4,13 +4,13 @@ import XCTest class swift_exercisesTests: XCTestCase { func test_typeModifier() { - let trainer1 = Trainer(pokemons: [hooh, hooh], human: false); - let trainer2 = Trainer(pokemons: [hooh, hooh], human: false); + let trainer1 = Trainer(pokemons: [hooh, hooh, hooh, hooh, hooh], human: false); + let trainer2 = Trainer(pokemons: [hooh, hooh, hooh, hooh, hooh], human: false); var state = battle_init(trainers: [trainer1, trainer2]); - print("AND THEN THERE WERE NONE"); + let state2 = battle(state: state); - if(state.winner == nil) {print("LOOOOOOOOL");} - print(state.trainers[0].pokemons[0].nickname!); + + print(state2.winner); XCTAssertEqual(typeModifier(attacking: Type.normal, defending: Type.normal), 1, "normal/normal should be 1") } From b5fbf0eb83412ebc6578958cd039bb1e3e14ad2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A9r=C3=A9mie?= Date: Sun, 12 Mar 2017 23:34:59 +0100 Subject: [PATCH 23/23] Added few comments, please use ./test to run a battle. Works on linux. --- Sources/swift_exercises.swift | 32 +++++++++++++------ .../swift_exercisesTests.swift | 9 +++--- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/Sources/swift_exercises.swift b/Sources/swift_exercises.swift index 931a1a1..84684e3 100644 --- a/Sources/swift_exercises.swift +++ b/Sources/swift_exercises.swift @@ -92,6 +92,7 @@ let earthquake = Move( priority: 0 ) +// Implementation of few moves let solar_beam = Move( id: 76, name: "Solar Beam", @@ -236,7 +237,9 @@ struct Pokemon { [1, 1, 0.9, 1.1, 1], [1, 1, 1, 1, 1]] - // swift is shit omfg i can't even do this in one line wtf i non-unironically have to cut this formula in multiple lines and wow i don't even + // swift is stupid omg i can't do this in one line + // srsly i non-unironically have to cut this formula in multiple lines + // i don't even let hp1 = 2 * species.base_values.hitpoints + individual_values.hitpoints; let hp2 = Double(hp1 + (effort_values.hitpoints / 4) * level) / 100 let hp3 = Int(floor(hp2) + Double(level) + 10); @@ -321,6 +324,7 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok let pkmType = pokemon.species.type; let tarType = target.species.type; + // I haven't implemented everything, but the code is structured in such a way it should be easy let targets: Double = 1 let weather: Double = 1 let badge: Double = 1 @@ -340,7 +344,7 @@ func damage(environment : Environment, pokemon: Pokemon, move: Move, target: Pok struct State { let environment: Environment let trainers: [Trainer] - let pokemon_fighting: [Int] // Indice of the fighting pokemon for the two players + let pokemon_fighting: [Int] // Indice of the fighting pokemon for the two players. For example, trainer 0 have [pikachu, ho-oh]. Indice 0 is for pikachu while 1 is for ho-oh let winner: Int? // 0 = first player, 1 = second, nil = none } @@ -355,6 +359,7 @@ func choose_action(trainer: Trainer) -> Action { return .attack } +// Choose a pokemon between the avaible ones of a trainer (hp > 0) func select_pokemon(trainer: Trainer) -> Int? { var selected: Int? = nil; var indice: Int = 0 @@ -370,6 +375,7 @@ func select_pokemon(trainer: Trainer) -> Int? { return selected } +// Return a correctly initialized State (will be used by battle()) func battle_init(trainers: [Trainer]) -> State { let environment = Environment(weather: .clear_skies, terrain: .normal); let pkm1 = select_pokemon(trainer: trainers[0]); @@ -387,7 +393,7 @@ func battle_init(trainers: [Trainer]) -> State { return State(environment: environment, trainers: trainers, pokemon_fighting: [pkm1!, pkm2!], winner: winner) } -// DOESN'T SEEM TO TAKE POWERPOINTS INTO ACCOUNT +// Choose a random move between the avaible ones of a pokemon (pp > 0) func choose_move(pokemon: Pokemon) -> Move { var filtered_moves = [Move](); @@ -400,6 +406,7 @@ func choose_move(pokemon: Pokemon) -> Move { return filtered_moves[random() % filtered_moves.count] } +// Probably not the shortest function possible for choosing which pokemon goes first, but it works func choose_first(pkm1: Pokemon, pkm2: Pokemon, move1: Move?, move2: Move?) -> [Int] { var order: [Int]; @@ -440,15 +447,14 @@ func choose_first(pkm1: Pokemon, pkm2: Pokemon, move1: Move?, move2: Move?) -> [ return order } -// var state: State = battle_init(trainers) -// state = battle(state) +// This function is recurive. It takes a State and returns a new one (with used items, updated pokemons' hp, the winner etc.) func battle(state: State) -> State { if(state.winner != nil) { return state } - var environment = state.environment; - + // Some variables for the sake of clarity + let environment = state.environment; var p = state.trainers; var pkm_ind = state.pokemon_fighting; var pkm = [p[0].pokemons[pkm_ind[0]], p[1].pokemons[pkm_ind[1]]]; @@ -456,6 +462,7 @@ func battle(state: State) -> State { var move: [Move?] = [nil, nil]; + // Each player choose an action for i in 0...1 { switch choose_action(trainer: p[i]) { case .attack: @@ -465,7 +472,7 @@ func battle(state: State) -> State { pkm_ind[i] = new_indice!; pkm[i] = p[i].pokemons[pkm_ind[i]]; case .use_item: - print("lol"); + print("Not implemented yet."); } } @@ -475,6 +482,9 @@ func battle(state: State) -> State { // Damage if(random() % 100 < move[ind]!.accuracy) { let dmg = damage(environment: environment, pokemon: pkm[ind], move: move[ind]!, target: pkm[(ind+1)%2]); + + // apply weather / environment modifiers + pkm[(ind+1)%2].battle_stats.hitpoints -= dmg; if(pkm[(ind+1)%2].battle_stats.hitpoints < 0) {pkm[(ind+1)%2].battle_stats.hitpoints = 0}; pkm[ind].moves[move[ind]!]! -= 1; @@ -491,10 +501,13 @@ func battle(state: State) -> State { // Check if other pokemon is dead if(pkm[(ind+1)%2].battle_stats.hitpoints <= 0) { let new_indice = select_pokemon(trainer: p[(ind+1)%2]); + + // The other trainer can't change his pokemon --> he loses if(new_indice == nil) { - winner = (ind+1)%2; + winner = ind; break; } + print("New pokemon for player ", ind) pkm_ind[(ind+1)%2] = new_indice!; pkm[(ind+1)%2] = p[ind].pokemons[pkm_ind[(ind+1)%2]]; @@ -505,7 +518,6 @@ func battle(state: State) -> State { print("HP pkm 1 : ", p[1].pokemons[pkm_ind[1]].battle_stats.hitpoints); // new turn - return battle(state: State( environment: environment, trainers: p, pokemon_fighting: pkm_ind, winner: winner)) } diff --git a/Tests/swift-exercisesTests/swift_exercisesTests.swift b/Tests/swift-exercisesTests/swift_exercisesTests.swift index 5dfdfa9..450a39a 100644 --- a/Tests/swift-exercisesTests/swift_exercisesTests.swift +++ b/Tests/swift-exercisesTests/swift_exercisesTests.swift @@ -3,21 +3,22 @@ import XCTest class swift_exercisesTests: XCTestCase { - func test_typeModifier() { + func run_battle() { let trainer1 = Trainer(pokemons: [hooh, hooh, hooh, hooh, hooh], human: false); let trainer2 = Trainer(pokemons: [hooh, hooh, hooh, hooh, hooh], human: false); - var state = battle_init(trainers: [trainer1, trainer2]); + + let state = battle_init(trainers: [trainer1, trainer2]); let state2 = battle(state: state); - print(state2.winner); + print("And the winner is... player ", state2.winner!, "!!!!!!"); XCTAssertEqual(typeModifier(attacking: Type.normal, defending: Type.normal), 1, "normal/normal should be 1") } static var allTests : [(String, (swift_exercisesTests) -> () throws -> Void)] { return [ - ("Type/Type modifiers", test_typeModifier), + ("Run a battle", run_battle), ] } }