3 # Copyright (c) 2010, Alex Munroe
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions, and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright notice,
12 # this list of conditions, and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the author of this software nor the name of
15 # contributors to this software may be used to endorse or promote products
16 # derived from this software without specific prior written consent.
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
32 import supybot
.conf
as conf
33 import supybot
.utils
as utils
34 from supybot
.commands
import *
35 import supybot
.plugins
as plugins
36 import supybot
.ircutils
as ircutils
37 import supybot
.callbacks
as callbacks
40 import pokedex
.db
.tables
as tables
46 def get_stat_color(stat
):
63 class Pokedex(callbacks
.Plugin
):
64 """Add the help for "@plugin help Pokedex" here
65 This should describe *how* to use this plugin."""
66 def __init__(self
, irc
):
67 self
.__parent
= super(Pokedex
, self
)
68 self
.__parent
.__init__(irc
)
69 self
.db
= pokedex
.db
.connect(self
.registryValue('databaseURL'))
70 self
.lookup
= pokedex
.lookup
.PokedexLookup(
71 directory
=conf
.supybot
.directories
.data
.dirize('pokedex-index'),
75 def pokedex(self
, irc
, msg
, args
, thing
):
78 Looks up <thing> in the veekun Pokédex."""
81 if not isinstance(thing
, unicode):
84 thing
= ascii_thing
.decode('utf8')
85 except UnicodeDecodeError:
86 thing
= ascii_thing
.decode('latin1')
88 # Similar logic to the site, here.
89 results
= self
.lookup
.lookup(thing
)
93 self
._reply(irc
, "I don't know what that is.")
96 # Multiple matches; propose them all
99 reply
= "Are you looking for"
101 reply
= "Did you mean"
103 # For exact name matches with multiple results, use type prefixes
104 # (item:Metronome). For anything else, omit them
105 use_prefixes
= (results
[0].exact
107 and '?' not in thing
)
110 for result
in results
:
111 result_string
= result
.object.name
113 # Prepend, e.g., pokemon: if necessary
115 # Table classes know their singular names
116 prefix
= result
.object.__singlename__
117 result_string
= prefix
+ ':' + result_string
119 # Identify foreign language names
121 result_string
+= u
""" ({0}: {1})""".format(
122 result
.iso3166
, result
.name
)
124 result_strings
.append(result_string
)
126 self
._reply(irc
, u
"{0}: {1}?".format(reply
, '; '.join(result_strings
)))
129 # If we got here, there's an exact match; hurrah!
132 if isinstance(obj
, tables
.Pokemon
):
134 u
"""#{id} {name}, {type}-type Pokémon. Has {abilities}. """ \
136 """http://veekun.com/dex/pokemon/{link_name}"""
139 name
= '{form} {name}'.format(
140 form
=obj
.forme_name
.title(),
146 if obj
.forme_base_pokemon
:
147 # Can't use urllib.quote() on the whole thing or it'll
148 # catch "?" and "=" where it shouldn't.
149 # XXX Also we need to pass urllib.quote() things explicitly
150 # encoded as utf8 or else we get a UnicodeEncodeError.
151 link_name
= '{name}?form={form}'.format(
152 name
=urllib
.quote(obj
.name
.lower().encode('utf8')),
153 form
=urllib
.quote(obj
.forme_name
.lower().encode('utf8')),
156 link_name
= urllib
.quote(obj
.name
.lower().encode('utf8'))
158 # a/b/c/d/e/f sucks. Put stats in a more readable format.
159 # Also, color-code them by good-osity.
162 for pokemon_stat
in obj
.stats
:
163 base_stat
= pokemon_stat
.base_stat
164 stat_total
+= base_stat
165 color
= get_stat_color(base_stat
)
167 colored_stats
.append(
168 "\x03{0:02d}{1}\x0f".format(color
, base_stat
)
171 colored_stat_total
= "\x03{0:02d}{1}\x0f".format(
172 get_stat_color(stat_total
/ 6),
175 stats
= """{0} HP, {1}/{2} phys, {3}/{4} spec, {5} speed; {total} total""" \
176 .format(*colored_stats
, total
=colored_stat_total
)
177 self
._reply(irc
, reply_template
.format(
180 type='/'.join(_
.name
for _
in obj
.types
),
181 abilities
=' or '.join(_
.name
for _
in obj
.abilities
),
187 elif isinstance(obj
, tables
.Move
):
189 u
"""{name}, {type}-type {damage_class} move. """ \
190 """{power} power; {accuracy}% accuracy; {pp} PP. """ \
192 """http://veekun.com/dex/moves/{link_name}"""
193 self
._reply(irc
, reply_template
.format(
196 damage_class
=obj
.damage_class
.name
,
198 accuracy
=obj
.accuracy
,
200 effect
=unicode(obj
.short_effect
.as_text
),
201 link_name
=urllib
.quote(obj
.name
.lower().encode('utf8')),
205 elif isinstance(obj
, tables
.Type
):
206 reply_template
= u
"""{name}, a type. """
208 offensive_reply_factors
= {
209 200: u
'\x03092×\x0f',
214 offensive_modifiers
= {}
215 for matchup
in obj
.damage_efficacies
:
216 if matchup
.damage_factor
!= 100:
217 offensive_modifiers
.setdefault(matchup
.damage_factor
, []) \
218 .append(matchup
.target_type
.name
)
219 if offensive_modifiers
:
220 reply_template
+= u
"""{offensive_modifiers}. """
221 for factor
in offensive_modifiers
:
222 offensive_modifiers
[factor
] = u
'{factor} against {types}'.format(
223 factor
=offensive_reply_factors
[factor
],
224 types
=', '.join(sorted(offensive_modifiers
[factor
]))
227 defensive_reply_factors
= {
228 200: u
'\x03042×\x0f',
233 defensive_modifiers
= {}
234 for matchup
in obj
.target_efficacies
:
235 if matchup
.damage_factor
!= 100:
236 defensive_modifiers
.setdefault(matchup
.damage_factor
, []) \
237 .append(matchup
.damage_type
.name
)
238 if defensive_modifiers
:
239 reply_template
+= u
"""{defensive_modifiers}. """
240 for factor
in defensive_modifiers
:
241 defensive_modifiers
[factor
] = u
'{factor} from {types}'.format(
242 factor
=defensive_reply_factors
[factor
],
243 types
=', '.join(sorted(defensive_modifiers
[factor
]))
246 reply_template
+= u
"""http://veekun.com/dex/types/{link_name}"""
248 self
._reply(irc
, reply_template
.format(
249 name
=obj
.name
.capitalize(),
250 offensive_modifiers
='; '.join(offensive_modifiers
[_
]
251 for _
in sorted(offensive_modifiers
)),
252 defensive_modifiers
='; '.join(defensive_modifiers
[_
]
253 for _
in sorted(defensive_modifiers
)),
254 link_name
=urllib
.quote(obj
.name
.lower().encode('utf8')),
258 elif isinstance(obj
, tables
.Item
):
260 u
"""{name}, an item. """ \
261 """http://veekun.com/dex/items/{link_pocket}/{link_name}"""
262 self
._reply(irc
, reply_template
.format(
264 link_pocket
=urllib
.quote(obj
.pocket
.name
.lower().encode('utf8')),
265 link_name
=urllib
.quote(obj
.name
.lower().encode('utf8')),
269 elif isinstance(obj
, tables
.Ability
):
271 u
"""{name}, an ability. {effect} """ \
272 """http://veekun.com/dex/abilities/{link_name}"""
273 self
._reply(irc
, reply_template
.format(
275 effect
=obj
.short_effect
.as_text
,
276 link_name
=urllib
.quote(obj
.name
.lower().encode('utf8')),
280 elif isinstance(obj
, tables
.Nature
):
282 u
"""{name}, a nature. """ \
283 u
"""Raises \x0303{up}\x0f, lowers \x0304{down}\x0f. """ \
284 u
"""http://veekun.com/dex/natures/{link_name}"""
285 self
._reply(irc
, reply_template
.format(
287 up
=obj
.increased_stat
.name
,
288 down
=obj
.decreased_stat
.name
,
289 link_name
=urllib
.quote(obj
.name
.lower().encode('utf8')),
294 # This can only happen if lookup.py is upgraded and we are not
295 self
._reply(irc
, "Uhh.. I found that, but I don't know what it is. :(")
297 pokedex
= wrap(pokedex
, [rest('something')])
299 def _reply(self
, irc
, response
):
300 """Wraps irc.reply() to do some Unicode decoding."""
301 if isinstance(response
, str):
304 irc
.reply(response
.encode('utf8'))
310 # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: