poor-pokemon-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitmodules +3 -0
- data/.learn +8 -0
- data/CONTRIBUTING.md +37 -0
- data/Gemfile +4 -0
- data/LICENSE.md +7 -0
- data/README.md +20 -0
- data/bin/poor-pokemon +4 -0
- data/config/environment.rb +12 -0
- data/lib/poor-pokemon.rb +4 -0
- data/lib/poor-pokemon/basePlayer.rb +14 -0
- data/lib/poor-pokemon/cli.rb +420 -0
- data/lib/poor-pokemon/enemy.rb +27 -0
- data/lib/poor-pokemon/move.rb +15 -0
- data/lib/poor-pokemon/player.rb +14 -0
- data/lib/poor-pokemon/pokedex.rb +40 -0
- data/lib/poor-pokemon/pokedexPokemon.rb +14 -0
- data/lib/poor-pokemon/pokemon.rb +190 -0
- data/lib/poor-pokemon/version.rb +3 -0
- data/poor-pokemon-cli-gem.gemspec +23 -0
- data/spec.md +9 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 71a2535678f62aa37ce2ea61459c07bc293c79b9
|
4
|
+
data.tar.gz: 98be132e33af240a9ed13348841e467909b40055
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a4ad6f238655a8a9d04d41a7e881e715191bf0e7c945f999d263a57eca5c4a76dbd7c6cfc96dc58bd24c0bce620878ea666f55b86ebfbf1fe4a0dd7241e2c901
|
7
|
+
data.tar.gz: 3438f2ae091c97b176b0b727aadc4a40fecf7b03c30d7f799e944c63bfe728c69e86bf80493c4a17019902a544e3f3b676cbfeb11ee6b6f947f3f157b868d215
|
data/.gitmodules
ADDED
data/.learn
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Contributing to Learn.co Curriculum
|
2
|
+
|
3
|
+
We're really exited that you're about to contribute to the [open curriculum](https://learn.co/content-license) on [Learn.co](https://learn.co). If this is your first time contributing, please continue reading to learn how to make the most meaningful and useful impact possible.
|
4
|
+
|
5
|
+
## Raising an Issue to Encourage a Contribution
|
6
|
+
|
7
|
+
If you notice a problem with the curriculum that you believe needs improvement
|
8
|
+
but you're unable to make the change yourself, you should raise a Github issue
|
9
|
+
containing a clear description of the problem. Include relevant snippets of
|
10
|
+
the content and/or screenshots if applicable. Curriculum owners regularly review
|
11
|
+
issue lists and your issue will be prioritized and addressed as appropriate.
|
12
|
+
|
13
|
+
## Submitting a Pull Request to Suggest an Improvement
|
14
|
+
|
15
|
+
If you see an opportunity for improvement and can make the change yourself go
|
16
|
+
ahead and use a typical git workflow to make it happen:
|
17
|
+
|
18
|
+
* Fork this curriculum repository
|
19
|
+
* Make the change on your fork, with descriptive commits in the standard format
|
20
|
+
* Open a Pull Request against this repo
|
21
|
+
|
22
|
+
A curriculum owner will review your change and approve or comment on it in due
|
23
|
+
course.
|
24
|
+
|
25
|
+
# Why Contribute?
|
26
|
+
|
27
|
+
Curriculum on Learn is publicly and freely available under Learn's
|
28
|
+
[Educational Content License](https://learn.co/content-license). By
|
29
|
+
embracing an open-source contribution model, our goal is for the curriculum
|
30
|
+
on Learn to become, in time, the best educational content the world has
|
31
|
+
ever seen.
|
32
|
+
|
33
|
+
We need help from the community of Learners to maintain and improve the
|
34
|
+
educational content. Everything from fixing typos, to correcting
|
35
|
+
out-dated information, to improving exposition, to adding better examples,
|
36
|
+
to fixing tests—all contributions to making the curriculum more effective are
|
37
|
+
welcome.
|
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
#Learn.co Educational Content License
|
2
|
+
|
3
|
+
Copyright (c) 2015 Flatiron School, Inc
|
4
|
+
|
5
|
+
The Flatiron School, Inc. owns this Educational Content. However, the Flatiron School supports the development and availability of educational materials in the public domain. Therefore, the Flatiron School grants Users of the Flatiron Educational Content set forth in this repository certain rights to reuse, build upon and share such Educational Content subject to the terms of the Educational Content License set forth [here](http://learn.co/content-license) (http://learn.co/content-license). You must read carefully the terms and conditions contained in the Educational Content License as such terms govern access to and use of the Educational Content.
|
6
|
+
|
7
|
+
Flatiron School is willing to allow you access to and use of the Educational Content only on the condition that you accept all of the terms and conditions contained in the Educational Content License set forth [here](http://learn.co/content-license) (http://learn.co/content-license). By accessing and/or using the Educational Content, you are agreeing to all of the terms and conditions contained in the Educational Content License. If you do not agree to any or all of the terms of the Educational Content License, you are prohibited from accessing, reviewing or using in any way the Educational Content.
|
data/README.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Poor-Pokemon-CLI-Gem
|
2
|
+
###Poorly Designed Pokemon Remake (PDPR)!
|
3
|
+
|
4
|
+
## Overview
|
5
|
+
In this simple CLI gem game, the player selects whatever pokemon they want from their pokedex to be added to their roster of 6, and then battles against an opponent, "Poorly Designed Boss".
|
6
|
+
|
7
|
+
The pokedex is constructed from this website (http://pokedream.com/pokedex/pokemon?display=gen1) and parsed using the gem Nokogiri.
|
8
|
+
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
You can install this gem via `gem install poor-pokemon-cli`. The `poor-pokemon` CLI will be installed and you can run `poor-pokemon` to start playing the game right in your command line.
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
Run: `poor-pokemon` after installing the gem.
|
15
|
+
|
16
|
+
## Contributing
|
17
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/mahdiASC/cli-data-gem-assessment-v-000. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
18
|
+
|
19
|
+
## License
|
20
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/bin/poor-pokemon
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
require_relative "../lib/poor-pokemon/basePlayer"
|
6
|
+
require_relative "../lib/poor-pokemon/pokedexPokemon"
|
7
|
+
require_relative "../lib/poor-pokemon/pokedex"
|
8
|
+
require_relative "../lib/poor-pokemon/pokemon"
|
9
|
+
require_relative "../lib/poor-pokemon/player"
|
10
|
+
require_relative "../lib/poor-pokemon/enemy"
|
11
|
+
require_relative "../lib/poor-pokemon/move"
|
12
|
+
require_relative "../lib/poor-pokemon/cli"
|
data/lib/poor-pokemon.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class PoorPokemon::BasePlayer
|
2
|
+
attr_accessor :roster, :currentPokemon
|
3
|
+
|
4
|
+
def allDead?
|
5
|
+
# returns true if no more pokemon left to play
|
6
|
+
!@roster.any?{|pokemon| pokemon.alive?}
|
7
|
+
end
|
8
|
+
|
9
|
+
def changeCurrent(number)
|
10
|
+
#changes currentPokemon to the pokemon in roster under "number" index
|
11
|
+
@currentPokemon = @roster[number]
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,420 @@
|
|
1
|
+
class PoorPokemon::CLI
|
2
|
+
attr_accessor :player, :enemy, :pokedex, :difficulty
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@player = PoorPokemon::Player.new()
|
6
|
+
@pokedex = PoorPokemon::Pokedex.new()
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
intro
|
11
|
+
difficulty
|
12
|
+
pokedexSelection
|
13
|
+
beginFight
|
14
|
+
declareWinner
|
15
|
+
restart
|
16
|
+
end
|
17
|
+
|
18
|
+
def intro
|
19
|
+
puts 'Welcome to Poorly Designed Pokemon Remake (PDPR)!'
|
20
|
+
puts 'I\'ve scraped Pokemon and their stats from a website and created a pokedex.'
|
21
|
+
puts 'You\'ll battle \'Poorly Designed Boss\', who has the 6 best pokemon with perfect stats!'
|
22
|
+
puts 'To battle him, you\'ll select 6 pokemon from the pokedex to add to your roster'
|
23
|
+
puts 'Then you\'ll take turns attacking his pokemon with yours.'
|
24
|
+
puts 'Unfortunately, \'Poorly Designed Boss\' has sabatoged your pokemon by giving them random attacks and imperfect stats!'
|
25
|
+
puts 'Can you still defeat him, despite being at a disadvantage!?'
|
26
|
+
puts 'Good luck, and have fun!'
|
27
|
+
end
|
28
|
+
|
29
|
+
def difficulty
|
30
|
+
#Sets difficulty of Enemy AI
|
31
|
+
userInput = ""
|
32
|
+
choices = ['e','h','easy','hard']
|
33
|
+
until choices.include?(userInput) do
|
34
|
+
puts "Select Difficulty: (e)asy (h)ard"
|
35
|
+
userInput = gets.strip.downcase
|
36
|
+
end
|
37
|
+
@difficulty = userInput
|
38
|
+
if userInput == "e" || userInput == "easy"
|
39
|
+
@enemy = PoorPokemon::Enemy.new(@pokedex.randSix(true))
|
40
|
+
fillMoves(@enemy, "easy")
|
41
|
+
elsif userInput == "h" || userInput == "hard"
|
42
|
+
@enemy = PoorPokemon::Enemy.new(@pokedex.bestSix(true))
|
43
|
+
fillMoves(@enemy, "hard")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def fillMoves(char, diff=nil)
|
48
|
+
#fills char's pokemon roster with appropriate moves
|
49
|
+
#moves are different for enemy
|
50
|
+
if char.is_a?(PoorPokemon::Player)
|
51
|
+
char.roster.each{|pokemon|
|
52
|
+
output = []
|
53
|
+
output.push(PoorPokemon::Move.new("Normal Attack",randAtt(45),"Normal",30))
|
54
|
+
output.push(PoorPokemon::Move.new("Big Normal Attack",randAtt(110),"Normal",10))
|
55
|
+
output.push(PoorPokemon::Move.new("Special Attack",randAtt(70),randType,20))
|
56
|
+
output.push(PoorPokemon::Move.new("Big Special Attack",randAtt(100),randType,5))
|
57
|
+
pokemon.moves = output
|
58
|
+
}
|
59
|
+
else
|
60
|
+
#Enemy player
|
61
|
+
if diff == "easy"
|
62
|
+
char.roster.each{|pokemon|
|
63
|
+
output = []
|
64
|
+
output.push(PoorPokemon::Move.new("Normal Attack",randAtt(45),"Normal",30))
|
65
|
+
output.push(PoorPokemon::Move.new("Big Normal Attack",randAtt(110),"Normal",10))
|
66
|
+
output.push(PoorPokemon::Move.new("Special Attack",randAtt(70),randType,20))
|
67
|
+
output.push(PoorPokemon::Move.new("Big Special Attack",randAtt(100),randType,5))
|
68
|
+
pokemon.moves = output
|
69
|
+
}
|
70
|
+
elsif diff == "hard"
|
71
|
+
char.roster.each{|pokemon|
|
72
|
+
output=[]
|
73
|
+
output.push(PoorPokemon::Move.new("Normal Attack",40,"Normal",30))
|
74
|
+
output.push(PoorPokemon::Move.new("Big Normal Attack",100,"Normal",10))
|
75
|
+
output.push(PoorPokemon::Move.new("Special Attack",65,pokemon.type1,20))
|
76
|
+
output.push(PoorPokemon::Move.new("Big Special Attack",90,pokemon.type1,5))
|
77
|
+
pokemon.moves = output
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
def randType
|
85
|
+
["Bug","Dragon","Ice","Fighting","Fire","Flying","Grass","Ghost","Ground","Electric","Normal","Poison","Psychic","Rock","Water"].sample
|
86
|
+
end
|
87
|
+
|
88
|
+
def randAtt(num)
|
89
|
+
var = (num * 0.1).round
|
90
|
+
rand(var)+num-var
|
91
|
+
end
|
92
|
+
|
93
|
+
def displayPokemon(pokeGroup)
|
94
|
+
#pokeGroup is an array of PokedexPokemon
|
95
|
+
#must have at least 1 item in array
|
96
|
+
#Displays the group for the user
|
97
|
+
maxNameLength = pokeGroup.sort{|a,b| a.name.length<=>b.name.length}.last.name.length+5
|
98
|
+
|
99
|
+
pokeGroup.each_index{|i|
|
100
|
+
name = "#{i+1}. #{pokeGroup[i].name.capitalize}"
|
101
|
+
until name.length >= maxNameLength do
|
102
|
+
name = name + " "
|
103
|
+
end
|
104
|
+
types = pokeGroup[i].type2 != "" ? pokeGroup[i].type1.capitalize + "+" + pokeGroup[i].type2.capitalize : pokeGroup[i].type1.capitalize
|
105
|
+
puts "#{name} TYPE:#{types} HP:#{pokeGroup[i].hp} ATT:#{pokeGroup[i].att} DEF:#{pokeGroup[i].def} SPD:#{pokeGroup[i].spd} SP-ATT:#{pokeGroup[i].spAtt} SP-DEF:#{pokeGroup[i].spDef}"
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
def pokedexSelection
|
110
|
+
#player will begin selecting desired pokemon from pokedex
|
111
|
+
#Ends when player has full roster
|
112
|
+
until @player.roster.length>=6 do
|
113
|
+
showPlayerRoster
|
114
|
+
playerSelection
|
115
|
+
end
|
116
|
+
showPlayerRoster
|
117
|
+
fillMoves(@player)
|
118
|
+
end
|
119
|
+
|
120
|
+
def showPlayerRoster
|
121
|
+
puts "YOUR ROSTER:"
|
122
|
+
if @player.roster.length>0
|
123
|
+
@player.roster.each_index{|i|
|
124
|
+
puts "#{i+1}. #{@player.roster[i].name.capitalize}"
|
125
|
+
}
|
126
|
+
else
|
127
|
+
puts "{There are no pokemon in your roster}"
|
128
|
+
end
|
129
|
+
sepLine
|
130
|
+
end
|
131
|
+
|
132
|
+
def playerSelection
|
133
|
+
userInput = ""
|
134
|
+
until ["1","2"].include?(userInput) do
|
135
|
+
puts "Select a pokemon from the Pokedex, to add to your roster (#{6-@player.roster.length} left to pick)"
|
136
|
+
puts "Options: (1)List all pokemon (2)Search by name"
|
137
|
+
userInput = gets.strip
|
138
|
+
case userInput
|
139
|
+
when "1"
|
140
|
+
searchResults = @pokedex.pokeList #full list of pokemon
|
141
|
+
when "2"
|
142
|
+
searchResults = []
|
143
|
+
until searchResults.length>0 do
|
144
|
+
puts 'Type in a name or partial name to search: '
|
145
|
+
searchInput = gets.strip
|
146
|
+
searchResults = @pokedex.searchName(searchInput)
|
147
|
+
if searchResults.length<1
|
148
|
+
puts "{No results found. Try again.}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
else
|
152
|
+
invalid
|
153
|
+
end
|
154
|
+
end
|
155
|
+
sepLine
|
156
|
+
# Either list all pokemon, or allow for search by name
|
157
|
+
displayPokemon(searchResults)
|
158
|
+
sepLine
|
159
|
+
#User selects pokemon
|
160
|
+
validSelection = ""
|
161
|
+
until (1..searchResults.length).map{|x| x.to_s}.include?(validSelection) do
|
162
|
+
puts "Select the number of the pokemon to add to your roster"
|
163
|
+
validSelection=gets.strip
|
164
|
+
end
|
165
|
+
sepLine
|
166
|
+
@player.add(searchResults[validSelection.to_i-1].clone)
|
167
|
+
end
|
168
|
+
|
169
|
+
def sepLine
|
170
|
+
puts "____________________"
|
171
|
+
end
|
172
|
+
|
173
|
+
def invalid
|
174
|
+
puts "{Invalid selection. Try again.}"
|
175
|
+
end
|
176
|
+
|
177
|
+
def beginFight
|
178
|
+
puts "\'Poorly Designed Boss\' wants to battle!"
|
179
|
+
displayBothRosters
|
180
|
+
playerSwitch
|
181
|
+
until @player.allDead? || @enemy.allDead? do
|
182
|
+
turnOrder
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def displayBothRosters
|
187
|
+
maxLength = @player.roster.sort{|a,b| a.name.length<=>b.name.length}.last.name.length+2
|
188
|
+
title = "You"
|
189
|
+
until title.length >= maxLength do
|
190
|
+
title = " " + title
|
191
|
+
end
|
192
|
+
puts title + " || Enemy"
|
193
|
+
sepLine
|
194
|
+
@player.roster.each_index{|i|
|
195
|
+
text = @player.roster[i].name.upcase
|
196
|
+
until text.length >= maxLength do
|
197
|
+
text = " " + text
|
198
|
+
end
|
199
|
+
typeText = @enemy.roster[i].type2!="" ? " (#{@enemy.roster[i].type1.capitalize}+#{@enemy.roster[i].type2.capitalize})" : " (#{@enemy.roster[i].type1.capitalize})"
|
200
|
+
text = text + " || " + @enemy.roster[i].name.upcase + typeText
|
201
|
+
puts text
|
202
|
+
}
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
def declareWinner
|
207
|
+
if @player.allDead?
|
208
|
+
puts "You lost!"
|
209
|
+
else
|
210
|
+
puts "You won!"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def turnOrder
|
215
|
+
#decides turn order based on each player's current pokemon's speed
|
216
|
+
#in event of tie, random
|
217
|
+
if @player.currentPokemon.spd == @enemy.currentPokemon.spd
|
218
|
+
if rand()>0.5
|
219
|
+
playerTurn
|
220
|
+
if @enemy.currentPokemon.alive?
|
221
|
+
enemyTurn
|
222
|
+
end
|
223
|
+
else
|
224
|
+
enemyTurn
|
225
|
+
if @player.currentPokemon.alive?
|
226
|
+
playerTurn
|
227
|
+
end
|
228
|
+
end
|
229
|
+
elsif @player.currentPokemon.spd>@enemy.currentPokemon.spd
|
230
|
+
playerTurn
|
231
|
+
if @enemy.currentPokemon.alive?
|
232
|
+
enemyTurn
|
233
|
+
end
|
234
|
+
elsif @player.currentPokemon.spd<@enemy.currentPokemon.spd
|
235
|
+
enemyTurn
|
236
|
+
if @player.currentPokemon.alive?
|
237
|
+
playerTurn
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
#switch if any dead and player still has usable pokemon
|
242
|
+
if !@player.currentPokemon.alive?
|
243
|
+
puts "Your #{@player.currentPokemon.name.upcase} fainted!"
|
244
|
+
if !@player.allDead?
|
245
|
+
playerSwitch
|
246
|
+
end
|
247
|
+
end
|
248
|
+
if !@enemy.currentPokemon.alive?
|
249
|
+
puts "Enemy #{@enemy.currentPokemon.name.upcase} fainted!"
|
250
|
+
if !@enemy.allDead?
|
251
|
+
@enemy.switch
|
252
|
+
puts "Enemy sent out #{@enemy.currentPokemon.name.upcase}!"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
if !gameWon?
|
257
|
+
currentStatus
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def playerTurn
|
262
|
+
puts "###Your Turn###"
|
263
|
+
typeText = @player.currentPokemon.type2 != "" ? "#{@player.currentPokemon.type1}+#{@player.currentPokemon.type2}" : "#{@player.currentPokemon.type1}"
|
264
|
+
puts "Current Pokemon: #{@player.currentPokemon.name.upcase} HP:#{@player.currentPokemon.hp} TYPE: #{typeText.upcase}"
|
265
|
+
typeText = @enemy.currentPokemon.type2 != "" ? "#{@enemy.currentPokemon.type1}+#{@enemy.currentPokemon.type2}" : "#{@enemy.currentPokemon.type1}"
|
266
|
+
puts "Enemy Pokemon: #{@enemy.currentPokemon.name.upcase} HP:#{@enemy.currentPokemon.hp} TYPE: #{typeText.upcase}"
|
267
|
+
sepLine
|
268
|
+
puts "What would you like to do? (a)ttack (s)witch"
|
269
|
+
userInput = ""
|
270
|
+
choices = ["a","attack","s","switch"]
|
271
|
+
until choices.include?(userInput) do
|
272
|
+
userInput = gets.strip.downcase
|
273
|
+
if (userInput == "s" || userInput == "switch")
|
274
|
+
playerSwitch
|
275
|
+
elsif(userInput == "a" || userInput == "attack")
|
276
|
+
playerAttacks(@enemy.currentPokemon)
|
277
|
+
else
|
278
|
+
invalid
|
279
|
+
end
|
280
|
+
end
|
281
|
+
sepLine
|
282
|
+
end
|
283
|
+
|
284
|
+
def playerSwitch
|
285
|
+
#Player switches current pokemon from roster
|
286
|
+
sepLine
|
287
|
+
if @player.currentPokemon
|
288
|
+
puts "Select Pokemon from your roster to switch to:"
|
289
|
+
else
|
290
|
+
puts "Select Pokemon from your roster to start with:"
|
291
|
+
end
|
292
|
+
userInput = "0"
|
293
|
+
until @player.valids.include?(@player.roster[userInput.to_i-1]) && userInput != "0" do
|
294
|
+
showPlayerSwitchRoster
|
295
|
+
userInput = gets.strip
|
296
|
+
if !@player.valids.include?(@player.roster[userInput.to_i-1])
|
297
|
+
invalid
|
298
|
+
end
|
299
|
+
end
|
300
|
+
if @player.currentPokemon
|
301
|
+
puts "#{@player.currentPokemon.name.upcase} returns!"
|
302
|
+
end
|
303
|
+
@player.changeCurrent(userInput.to_i-1)
|
304
|
+
puts "#{@player.currentPokemon.name.upcase} enters the battle!"
|
305
|
+
end
|
306
|
+
|
307
|
+
def showPlayerSwitchRoster
|
308
|
+
maxLength = @player.roster.sort{|a,b| a.name.length<=>b.name.length}.last.name.length+5
|
309
|
+
|
310
|
+
@player.roster.each_index{|i|
|
311
|
+
health = @player.roster[i].alive? ? @player.roster[i].hp.to_s + " HP" : "FAINTED!"
|
312
|
+
text = "#{i+1}. #{@player.roster[i].name.upcase}"
|
313
|
+
until text.length >= maxLength do
|
314
|
+
text = text + " "
|
315
|
+
end
|
316
|
+
if health !="FAINTED!"
|
317
|
+
puts "#{text}| STATUS: #{health} spAtt1:#{@player.roster[i].moves[2].name.match(/(?<=\().*(?=\))/)[0].upcase}/PP #{@player.roster[i].moves[2].pp} spAtt2:#{@player.roster[i].moves[3].name.match(/(?<=\().*(?=\))/)[0].upcase}/PP #{@player.roster[i].moves[3].pp}"
|
318
|
+
else
|
319
|
+
puts "#{text}| STATUS: #{health}"
|
320
|
+
end
|
321
|
+
}
|
322
|
+
sepLine
|
323
|
+
end
|
324
|
+
|
325
|
+
def playerAttacks(enemyPokemon)
|
326
|
+
#gives user options on what move to attack with
|
327
|
+
sepLine
|
328
|
+
if @player.currentPokemon.canAttack?
|
329
|
+
userInput = "0"
|
330
|
+
availMoves = @player.currentPokemon.usableMoves
|
331
|
+
until availMoves.include?(@player.currentPokemon.moves[userInput.to_i-1]) && userInput!="0" do
|
332
|
+
puts "Which move should #{@player.currentPokemon.name.capitalize} use?"
|
333
|
+
maxLength = @player.currentPokemon.moves.sort{|a,b| a.name.length<=>b.name.length}.last.name.length+5
|
334
|
+
@player.currentPokemon.moves.each_index{|i|
|
335
|
+
move = @player.currentPokemon.moves[i]
|
336
|
+
text = "#{i+1}. #{move.name.upcase}"
|
337
|
+
until text.length >= maxLength do
|
338
|
+
text = text + " "
|
339
|
+
end
|
340
|
+
puts "#{text} > PP: #{move.pp}"
|
341
|
+
}
|
342
|
+
userInput = gets.strip
|
343
|
+
if !availMoves.include?(@player.currentPokemon.moves[userInput.to_i-1]) && userInput!="0"
|
344
|
+
invalid
|
345
|
+
end
|
346
|
+
end
|
347
|
+
move = @player.currentPokemon.moves[userInput.to_i-1]
|
348
|
+
puts "#{@player.currentPokemon.name.upcase} used #{move.name.split(" (")[0].upcase} (#{move.type})!"
|
349
|
+
puts dmgText(@player.currentPokemon.attacks(enemyPokemon,move))
|
350
|
+
else
|
351
|
+
#current pokemon is out of PP for all moves, defaults to "Struggle"
|
352
|
+
struggle = PoorPokemon::Move.new("Struggle",40,"Normal",99)
|
353
|
+
puts "#{@player.currentPokemon.name.upcase} is out of moves!"
|
354
|
+
puts "#{@player.currentPokemon.name.upcase} used STRUGGLE! #{struggle.type}"
|
355
|
+
puts dmgText(@player.currentPokemon.attacks(enemyPokemon,struggle))
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
def dmgText(dmgArray)
|
360
|
+
#depending on the number, will evaluate the effectiveness of the attack
|
361
|
+
#returns a string to communicate that effectiveness
|
362
|
+
dmg = dmgArray[0]
|
363
|
+
num = dmgArray[1]
|
364
|
+
|
365
|
+
if num == 0
|
366
|
+
output = "No effect!"
|
367
|
+
elsif num == 0.5 || num == 0.25
|
368
|
+
output = "It's not very effective."
|
369
|
+
elsif num == 2
|
370
|
+
output = "It's super-effective!"
|
371
|
+
elsif num == 4
|
372
|
+
output = "Critical hit!" #Not a true critical hit
|
373
|
+
else
|
374
|
+
output = "It hit!"
|
375
|
+
end
|
376
|
+
output + " (#{dmg} dmg)"
|
377
|
+
end
|
378
|
+
|
379
|
+
def enemyTurn
|
380
|
+
puts "###Enemy Turn###"
|
381
|
+
if @enemy.currentPokemon.canAttack?
|
382
|
+
attackArray = @enemy.attacks(@player.currentPokemon,@difficulty)
|
383
|
+
puts "#{@enemy.currentPokemon.name.upcase} used #{attackArray[1].name.split(" (")[0].upcase} (#{attackArray[1].type})!"
|
384
|
+
puts dmgText(attackArray[0])
|
385
|
+
else
|
386
|
+
#current pokemon is out of PP for all moves, defaults to "Struggle"
|
387
|
+
struggle = PoorPokemon::Move.new("Struggle",40,"Normal",99)
|
388
|
+
attackArray = @enemy.attacks(@player.currentPokemon, @difficulty, struggle)
|
389
|
+
puts "Enemy #{@enemy.currentPokemon.name.upcase} is out of moves!"
|
390
|
+
puts "Enemy #{@enemy.currentPokemon.name.upcase} used STRUGGLE #{struggle.type}!"
|
391
|
+
puts dmgText(attackArray[0])
|
392
|
+
end
|
393
|
+
sepLine
|
394
|
+
end
|
395
|
+
|
396
|
+
def currentStatus
|
397
|
+
#prints current status for both sides
|
398
|
+
puts "Your #{@player.currentPokemon.name.capitalize} has #{@player.currentPokemon.hp} HP"
|
399
|
+
puts "Enemy #{@enemy.currentPokemon.name.capitalize} has #{@enemy.currentPokemon.hp} HP"
|
400
|
+
sepLine
|
401
|
+
end
|
402
|
+
|
403
|
+
def gameWon?
|
404
|
+
@enemy.allDead? || @player.allDead?
|
405
|
+
end
|
406
|
+
|
407
|
+
def restart
|
408
|
+
sepLine
|
409
|
+
puts "Would you like to play again? (y)es (n)o"
|
410
|
+
choices = ["y","n","yes","no"]
|
411
|
+
userInput = ''
|
412
|
+
until choices.include?(userInput) do
|
413
|
+
userInput = gets.strip.downcase
|
414
|
+
end
|
415
|
+
|
416
|
+
if(userInput == "y" || userInput == "yes")
|
417
|
+
call
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class PoorPokemon::Enemy < PoorPokemon::BasePlayer
|
2
|
+
def initialize(pokeGroup)
|
3
|
+
@roster = pokeGroup
|
4
|
+
@currentPokemon = @roster[0]
|
5
|
+
end
|
6
|
+
|
7
|
+
def switch
|
8
|
+
#switches current pokemon (should be dead) for another valid pokemon
|
9
|
+
@currentPokemon = @roster.select{|pokemon|pokemon.alive?}.sample
|
10
|
+
end
|
11
|
+
|
12
|
+
def attacks(oppPokemon, diff, move=nil)
|
13
|
+
#determines how enemy AI attacks depending on difficulty
|
14
|
+
if move
|
15
|
+
dmg = @currentPokemon.attacks(oppPokemon, move)
|
16
|
+
else
|
17
|
+
if diff == "easy" || diff =='e'
|
18
|
+
move = @currentPokemon.usableMoves.sample
|
19
|
+
dmg = @currentPokemon.attacks(oppPokemon, move)
|
20
|
+
elsif diff == "hard" || diff =="h"
|
21
|
+
move = @currentPokemon.usableMoves.sort{|moveA,moveB| moveA.dmg<=>moveB.dmg}.last
|
22
|
+
dmg = @currentPokemon.attacks(oppPokemon, move)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
[dmg, move]
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class PoorPokemon::Move
|
2
|
+
attr_accessor :name, :dmg, :type, :pp
|
3
|
+
|
4
|
+
def initialize (name, dmg, type, pp)
|
5
|
+
@name = "#{name} (#{type})"
|
6
|
+
@dmg = dmg
|
7
|
+
@type = type
|
8
|
+
@pp = pp
|
9
|
+
end
|
10
|
+
|
11
|
+
def usable?
|
12
|
+
#returns true if move has enough PP to be used
|
13
|
+
@pp>0
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class PoorPokemon::Pokedex
|
2
|
+
attr_accessor :pokeList
|
3
|
+
def initialize
|
4
|
+
# Pokemon database
|
5
|
+
# http://pokedream.com/pokedex/pokemon?display=gen1
|
6
|
+
pokemonDoc = Nokogiri::HTML(open("http://pokedream.com/pokedex/pokemon?display=gen1"))
|
7
|
+
@pokeList = pokemonDoc.css(".UILinkedTableRow").map{ |row|
|
8
|
+
rowData = row.children().map{ |col|
|
9
|
+
if col.attribute("class")
|
10
|
+
col.attribute("class").value
|
11
|
+
else
|
12
|
+
col.text()
|
13
|
+
end
|
14
|
+
}.reject{|val| val == "\n" || val == "---"}
|
15
|
+
rowData
|
16
|
+
}.map{|row|
|
17
|
+
PoorPokemon::PokedexPokemon.new(row)
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def bestSix(flag=false)
|
22
|
+
#flag is for enemy to have perfect stats
|
23
|
+
@pokeList.sort{|pokemonA,pokemonB| pokemonB.totalStats <=> pokemonA.totalStats}.take(6).map{|pokemon|pokemon.clone(flag)}
|
24
|
+
end
|
25
|
+
|
26
|
+
def randSix(flag=false)
|
27
|
+
#flag is for enemy to have perfect stats
|
28
|
+
randArray = []
|
29
|
+
6.times do
|
30
|
+
randArray.push(@pokeList.sample.clone(flag))
|
31
|
+
end
|
32
|
+
randArray
|
33
|
+
end
|
34
|
+
|
35
|
+
def searchName(word)
|
36
|
+
@pokeList.select{|pokemon| pokemon.name[word]}
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class PoorPokemon::PokedexPokemon
|
2
|
+
attr_accessor :name, :num, :type1, :type2, :hp, :att, :def, :spAtt, :spDef, :spd, :totalStats
|
3
|
+
|
4
|
+
def initialize(arr)
|
5
|
+
@name, @num, @type1, @type2, @hp, @att, @def, @spAtt, @spDef, @spd, @totalStats = arr
|
6
|
+
end
|
7
|
+
|
8
|
+
def clone (flag=false)
|
9
|
+
# creates a copy of this pokedexPokemon object as a pokemon object
|
10
|
+
# moves is an array of moves
|
11
|
+
#flag is for enemy to have perfect stats
|
12
|
+
return PoorPokemon::Pokemon.new([@name, @type1, @type2, @hp.to_i, @att.to_i, @def.to_i, @spAtt.to_i, @spDef.to_i, @spd.to_i], flag)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
class PoorPokemon::Pokemon
|
2
|
+
attr_accessor :name, :type1, :type2, :hp, :att, :def, :spAtt, :spDef, :spd, :moves
|
3
|
+
|
4
|
+
|
5
|
+
def initialize(arr, flag=false)
|
6
|
+
#flag is for enemy to have perfect stats
|
7
|
+
@name, @type1, @type2, @hp, @att, @def, @spAtt, @spDef, @spd = arr
|
8
|
+
|
9
|
+
#Determines proper stats
|
10
|
+
#https://www.dragonflycave.com/mechanics/stats
|
11
|
+
#Individual stats (0-15)
|
12
|
+
atkIV = flag ? 15: rand(15)
|
13
|
+
@att += atkIV
|
14
|
+
@att = @att*2+68
|
15
|
+
|
16
|
+
|
17
|
+
defIV = flag ? 15:rand(15)
|
18
|
+
@def += defIV
|
19
|
+
@def = @def*2+68
|
20
|
+
|
21
|
+
spdIV = flag ? 15:rand(15)
|
22
|
+
@spd += spdIV
|
23
|
+
@spd = @spd*2+68
|
24
|
+
|
25
|
+
spIV = flag ? 15:rand(15)
|
26
|
+
@spAtt += spIV
|
27
|
+
@spAtt = @spAtt*2+68
|
28
|
+
@spDef += spIV
|
29
|
+
@spDef = @spDef*2+68
|
30
|
+
|
31
|
+
#how HP and IV are connected
|
32
|
+
if atkIV%2==1
|
33
|
+
@hp += 8
|
34
|
+
end
|
35
|
+
|
36
|
+
if defIV%2==1
|
37
|
+
@hp += 4
|
38
|
+
end
|
39
|
+
|
40
|
+
if spdIV%2==1
|
41
|
+
@hp += 2
|
42
|
+
end
|
43
|
+
|
44
|
+
if spIV%2==1
|
45
|
+
@hp += 1
|
46
|
+
end
|
47
|
+
@hp = @hp*2+110
|
48
|
+
|
49
|
+
@moves = []
|
50
|
+
end
|
51
|
+
|
52
|
+
def alive?
|
53
|
+
@hp > 0
|
54
|
+
end
|
55
|
+
|
56
|
+
def attacks(oppPokemon, move)
|
57
|
+
#dmg calculations
|
58
|
+
attackStat = ["normal", "fighting", "flying", "poison", "ground", "rock", "bug", "ghost"].include?(move.type) ? @att : @spAtt
|
59
|
+
attackPower = move.dmg
|
60
|
+
defenseStat = ["normal", "fighting", "flying", "poison", "ground", "rock", "bug", "ghost"].include?(move.type) ? oppPokemon.def : oppPokemon.spDef
|
61
|
+
randNum = rand(255-217)+217
|
62
|
+
stab = move.type == @type1 || move.type == @type2 ? 1.5 : 1
|
63
|
+
weakResist = calcWeakResist(oppPokemon,move)
|
64
|
+
|
65
|
+
#dmg equation
|
66
|
+
damageTotal = (((((42 * attackStat.to_f * (attackPower.to_f/defenseStat.to_f))/50)+2)*stab.to_f*weakResist.to_f)*randNum.to_f/255).floor
|
67
|
+
|
68
|
+
#applying dmg
|
69
|
+
move.pp -= 1
|
70
|
+
oppPokemon.hp -= damageTotal
|
71
|
+
if oppPokemon.hp < 0
|
72
|
+
oppPokemon.hp = 0 #just in case HP checked
|
73
|
+
end
|
74
|
+
[damageTotal,weakResist]
|
75
|
+
end
|
76
|
+
|
77
|
+
def calcWeakResist(oppPokemon,move, typeInput=nil)
|
78
|
+
#returns multiplier for attack effectiveness
|
79
|
+
#0.25, 0.5, 1, 2, or 4
|
80
|
+
# http://unrealitymag.com/wp-content/uploads/2014/11/rby-rules.jpg
|
81
|
+
type = (typeInput || oppPokemon.type1).downcase
|
82
|
+
output = 1; #number returned as modifier
|
83
|
+
case move.type.downcase
|
84
|
+
when 'normal'
|
85
|
+
if ['ghost'].include?(type)
|
86
|
+
output *= 0
|
87
|
+
end
|
88
|
+
when 'bug'
|
89
|
+
if ['fire','flying',"rock"].include?(type)
|
90
|
+
output*=0.5
|
91
|
+
elsif ['grass','poison',"psychic"].include?(type)
|
92
|
+
output*=2
|
93
|
+
end
|
94
|
+
when 'dragon'
|
95
|
+
#No effectiveness
|
96
|
+
when 'ice'
|
97
|
+
if ['ice','water'].include?(type)
|
98
|
+
output*=0.5
|
99
|
+
elsif ['dragon','flying','grass','ground'].include?(type)
|
100
|
+
output*=2
|
101
|
+
end
|
102
|
+
when 'fighting'
|
103
|
+
if ['flying','psychic'].include?(type)
|
104
|
+
output*=0.5
|
105
|
+
elsif ['ice','normal','rock'].include?(type)
|
106
|
+
output*=2
|
107
|
+
elsif ['ghost'].include?(type)
|
108
|
+
output*=0
|
109
|
+
end
|
110
|
+
when 'fire'
|
111
|
+
if ['rock','water'].include?(type)
|
112
|
+
output*=0.5
|
113
|
+
elsif ['bug','grass','ice'].include?(type)
|
114
|
+
output*=2
|
115
|
+
end
|
116
|
+
when 'flying'
|
117
|
+
if ['electric','rock'].include?(type)
|
118
|
+
output*=0.5
|
119
|
+
elsif ['bug','fighting',"grass"].include?(type)
|
120
|
+
output*=2
|
121
|
+
end
|
122
|
+
when 'grass'
|
123
|
+
if ['bug','fire','flying','grass','poison'].include?(type)
|
124
|
+
output*=0.5
|
125
|
+
elsif ['ground','rock','water'].include?(type)
|
126
|
+
output*=2
|
127
|
+
end
|
128
|
+
when 'ghost'
|
129
|
+
if ['normal','psychic'].include?(type)
|
130
|
+
output*=0
|
131
|
+
end
|
132
|
+
when 'ground'
|
133
|
+
if ['grass'].include?(type)
|
134
|
+
output*=0.5
|
135
|
+
elsif ['electric','fire','poison','rock'].include?(type)
|
136
|
+
output*=2
|
137
|
+
elsif ['flying'].include?(type)
|
138
|
+
output*=0
|
139
|
+
end
|
140
|
+
when 'electric'
|
141
|
+
if ['electric','grass'].include?(type)
|
142
|
+
output*=0.5
|
143
|
+
elsif ['flying','water'].include?(type)
|
144
|
+
output*=2
|
145
|
+
elsif ['ground'].include?(type)
|
146
|
+
output*=0
|
147
|
+
end
|
148
|
+
when 'poison'
|
149
|
+
if ['ground','poison','rock'].include?(type)
|
150
|
+
output*=0.5
|
151
|
+
elsif ['bug','grass'].include?(type)
|
152
|
+
output*=2
|
153
|
+
end
|
154
|
+
when 'psychic'
|
155
|
+
if ['psychic'].include?(type)
|
156
|
+
output*=0.5
|
157
|
+
elsif ['fighting','poison'].include?(type)
|
158
|
+
output*=2
|
159
|
+
end
|
160
|
+
when 'rock'
|
161
|
+
if ['fighting','rock'].include?(type)
|
162
|
+
elsif ['bug','fire','flying','ice'].include?(type)
|
163
|
+
end
|
164
|
+
when 'water'
|
165
|
+
if ['grass','ice'].include?(type)
|
166
|
+
output*=0.5
|
167
|
+
elsif ['fire','ground','rock'].include?(type)
|
168
|
+
output*=2
|
169
|
+
end
|
170
|
+
else
|
171
|
+
puts "SOMETHING WENT WRONG WITH TYPE DMG"
|
172
|
+
puts "MoveType: #{move.type.downcase} Type: #{type.downcase}"
|
173
|
+
end
|
174
|
+
|
175
|
+
if(typeInput.nil? && oppPokemon.type2 !="")
|
176
|
+
output *= calcWeakResist(oppPokemon,move, oppPokemon.type2)
|
177
|
+
end
|
178
|
+
output
|
179
|
+
end
|
180
|
+
|
181
|
+
def canAttack?
|
182
|
+
#returns true if pokemon has enough PP to attack
|
183
|
+
@moves.any?{|move| move.usable?}
|
184
|
+
end
|
185
|
+
|
186
|
+
def usableMoves
|
187
|
+
#returns array of usable moves
|
188
|
+
@moves.select{|move| move.usable?}
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "poor-pokemon/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.authors = ["Mahdi Shadkam-Farrokhi"]
|
8
|
+
spec.email = ["mahdi@allstarcode.org"]
|
9
|
+
spec.description = "A simple pokemon CLI"
|
10
|
+
spec.summary = "In this simple CLI gem game, the player selects whatever pokemon they want from their pokedex to be added to their roster of 6, and then battles against an opponent, \"Poorly Designed Boss\"."
|
11
|
+
spec.version = PoorPokemon::VERSION
|
12
|
+
spec.homepage = 'http://rubygems.org/gems/poor-pokemon'
|
13
|
+
spec.date = Time.now.utc.strftime("%Y-%m-%d")
|
14
|
+
spec.files = `git ls-files`.split($\)
|
15
|
+
spec.executables = ["poor-pokemon"]
|
16
|
+
spec.name = "poor-pokemon-cli"
|
17
|
+
spec.require_paths = ["lib", "lib/poor-pokemon"]
|
18
|
+
spec.license = "MIT"
|
19
|
+
|
20
|
+
spec.add_development_dependency "pry"
|
21
|
+
|
22
|
+
spec.add_dependency "nokogiri"
|
23
|
+
end
|
data/spec.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Specifications for the CLI Assessment
|
2
|
+
|
3
|
+
Specs:
|
4
|
+
- [x] Have a CLI for interfacing with the application
|
5
|
+
-I've created a working Ruby CLI for playing pokemon.
|
6
|
+
- [x] Pull data from an external source
|
7
|
+
-The application properly pulls data from an external website using the 'open-uri' gem.
|
8
|
+
- [x] Implement both list and detail views
|
9
|
+
-The application uses a 'pokedex' to allow users to interact with a list of pokemon (both from a full list or by searching). The users select their pokemon and store them in a roster, from which they can battle an opponent.
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: poor-pokemon-cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mahdi Shadkam-Farrokhi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-07-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nokogiri
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: A simple pokemon CLI
|
42
|
+
email:
|
43
|
+
- mahdi@allstarcode.org
|
44
|
+
executables:
|
45
|
+
- poor-pokemon
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- ".gitmodules"
|
50
|
+
- ".learn"
|
51
|
+
- CONTRIBUTING.md
|
52
|
+
- Gemfile
|
53
|
+
- LICENSE.md
|
54
|
+
- README.md
|
55
|
+
- bin/poor-pokemon
|
56
|
+
- config/environment.rb
|
57
|
+
- lib/poor-pokemon.rb
|
58
|
+
- lib/poor-pokemon/basePlayer.rb
|
59
|
+
- lib/poor-pokemon/cli.rb
|
60
|
+
- lib/poor-pokemon/enemy.rb
|
61
|
+
- lib/poor-pokemon/move.rb
|
62
|
+
- lib/poor-pokemon/player.rb
|
63
|
+
- lib/poor-pokemon/pokedex.rb
|
64
|
+
- lib/poor-pokemon/pokedexPokemon.rb
|
65
|
+
- lib/poor-pokemon/pokemon.rb
|
66
|
+
- lib/poor-pokemon/version.rb
|
67
|
+
- poor-pokemon-cli-gem.gemspec
|
68
|
+
- spec.md
|
69
|
+
homepage: http://rubygems.org/gems/poor-pokemon
|
70
|
+
licenses:
|
71
|
+
- MIT
|
72
|
+
metadata: {}
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
- lib/poor-pokemon
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 2.5.2
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: In this simple CLI gem game, the player selects whatever pokemon they want
|
94
|
+
from their pokedex to be added to their roster of 6, and then battles against an
|
95
|
+
opponent, "Poorly Designed Boss".
|
96
|
+
test_files: []
|