!calciv (個体値表示)
!calciv ポケモン名[*] レベル H A B C D S !calciv ポケモン名[*] レベル 個体値を調べたい場所(HABCDS) 対応する箇所の実数値
実数値から個体値を計算します。
性格の補正については、上昇補正/下降補正がついている場合は実数値の後に+/-を付けてください。
個体値を調べたい場所を入力しなかった場合は、全ての場所の個体値を求めます。
引数はHABCDSの順で全ての数値を入力してください。
使用例
実数値から個体値を計算するプログラム
概要
実数値(観測値)から個体値を計算するには、!stのときに作ったbst2ast_ij関数を最利用して、
個体値が0~31のときの実数値(理論値)を求め、観測値と一致するような個体値の最小値・最大値を返せばいい。
今回も、H,A,B,C,D,Sをj=1,2,3,4,5,6に対応させて、
j番目の観測値をobst_j,個体値がiのときの理論値をast_ijとする。
l2s=lambda s,l:s.join(map(str,l)) cplist=lambda org:[org,org,org,org,org,org] #種族値をj番目の実数値に変換 def bst2ast_ij(j,bst,lv,iv,ev,ncor): f=lambda bst,iv,ev,lv:int(int(bst*2+iv+ev/4)*lv/100)+5 if j==0: ast_j=f(bst[j],iv[j],ev[j],lv)+lv+5 else: ast_j=int((f(bst[j],iv[j],ev[j],lv))*ncor[j]) return ast_j #種族値を実数値リストに変換 def bst2ast(bst,lv,iv,ev,ncor): ast_i=[] for j in range(6): ast_j=bst2ast_ij(j,bst,lv,iv,ev,ncor) ast_i.append(ast_j) return ast_i #グラードンの種族値リスト bst=[100,150,140,100,90,90] #デフォルトのLv lv=50 #個体値・努力値・性格補正 b2a_i=[cplist(31),cplist(252),cplist(1.1)] ast_i=bst2ast(bst,lv,*b2a_i) print(ast_i) #出力:[207, 222, 211, 167, 156, 156]
[207, 222, 211, 167, 156, 156]
そのためには、bst2ast_ijの引数である、
種族値・努力値・レベル・性格補正、すなわち bst, ev, lv, ncor を決定しなければならない。
- bst…与えられた名前をDBを検索して種族値を取得
- ev…捕獲直後を想定するため、すべて0を仮定
- lv…与えられる。
- ncor…与えられる。(実数値の後ろに+,-をつけて表現する。デフォルト=[1,1,1,1,1,1])
入力形式について
!calcivは引数の入力を省略できるので、両方の入力形式に対応する必要がある。
def calciv(name,lv,*args): print(name,lv,args) #省略しない場合 calciv("グラードン",70,"240","236","240+","160","144","117-") #省略する場合 calciv("グラードン",70,'A','S',"236","117-")
グラードン 70 ('240', '236', '240+', '160', '144', '117-')
グラードン 70 ('A', 'S', '236', '117-')
省略する場合を考えると、次のようなプログラムでどのステータスの個体値を調べたいのかを判定できる。
省略されなかった場合は、すべてFalseになる。
しかし、それだとどこも調べてくれないので、例外的に処理する必要がある。
args=list(('A','S',"236","117-")) #個体値を調べたいステータスにフラグを立てる search_st=[st in args for st in ['H','A','B','C','D','S']] print(search_st) #Trueの出現回数 print(search_st.count(True))
[False, True, False, False, False, True]
2
argsの "A", "S" の要素はもう必要ないので削除。
del args[:search_st.count(1)] print(args)
['236', '117-']
次に、args=('236', '117-') について考える。
文字列に、'+', '-' が含まれているかどうかを判定する。
そのために、reモジュールをimportして、特定の文字列があるかどうかを判定する。
ついでに、'+', '-' を除去して、数値型に変換する。
import re obst=[] ncor_flag=[] for arg in args: #上昇補正 if re.search(r'\+',arg): arg=arg.strip('+') ncor_flag.append(1.1) #下降補正 if re.search(r'\-',arg): arg=arg.strip('-') ncor_flag.append(0.9) #無補正 else: ncor_flag.append(1) obst.append(int(arg)) print(obst) print(ncor_flag)
[236, 117]
[1, 0.9]
これで、bst2ast_ijが使えるようになった。
#arg='117-'をobst_j=117, ncor_j=0.9に分離する関数 def args2ast_j(arg): #上昇補正 if re.search(r'\+',arg): ast_j=arg.strip('+') ncor_j=1.1 #下降補正 elif re.search(r'\-',arg): ast_j=arg.strip('-') ncor_j=0.9 #無補正 else: ast_j=arg ncor_j=1 return int(ast_j),ncor_j def calciv(name,lv,*args): args=list(args) #個体値を調べたい場所にフラグを立てる search_st=[st in args for st in ['H','A','B','C','D','S']] del args[:search_st.count(1)] iter_args=iter(args) #観測したステータス obst=[] ncor=[] for j in range(6): #フラグがあるか、ひとつもない場合 if search_st[j] or search_st.count(True)==0: arg=next(iter_args) obst_j,ncor_j=args2ast_j(arg) obst.append(obst_j) ncor.append(ncor_j) #フラグがない場合 else: obst.append(0) ncor.append(1) bst=(100, 150, 140, 100, 90, 90) lv=lv ev=cplist(0) i_maxmindict={} i_matchdict={} #H~Sでループ for j in range(6): if search_st[j] or search_st.count(True)==0: i_matchdict[j]=[] #個体値0~31でループ for i in range(32): iv=cplist(i) #実数値が一致したときの個体値 if obst[j]==bst2ast_ij(j,bst,lv,iv,ev,ncor): i_matchdict[j].append(i) if len(i_matchdict[j])==0: pass elif len(i_matchdict[j])==1: i_maxmindict[j]=i_matchdict[j] else: i_maxmindict[j]=[min(i_matchdict[j]),max(i_matchdict[j])] keys=['H','A','B','C','D','S'] for item in i_maxmindict.items(): print(f"{keys[item[0]]}:{l2s('~',item[1])}")
#省略しない場合 calciv("グラードン*",69,"240","236","240+","160","144","117-")
B:31
C:25~26
D:22
S:2~4
#省略する場合 calciv("グラードン",70,'A','S',"236","117-")
A:30~31
S:0~1
これでほとんど完成!
PostgreSQLから種族値データを取得する
DBの検索には、!stのときのPostgreSQLから種族値データを取得する関数を再利用する
import psycopg2,os,re import numpy as np from dotenv import load_dotenv DATABASE_URL=os.environ["DATABASE_URL"] conn=psycopg2.connect(DATABASE_URL) l2s=lambda s,l:s.join(map(str,l))
#種族値データを取得 def fetch_bst(cur,name): #アイコンを生成 cur.execute( f"select icon from pokedex where name='{name}'" ) icon=cur.fetchone()[0] #種族値を検索 cur.execute( f"select h,a,b,c,d,s from pokedex where name ='{name}'" ) bst=cur.fetchone() return icon,bst #初めに呼び出される関数 def get_bst(name): with conn: with conn.cursor() as cur: #名前の最後に"*"をつけるとあいまい検索になる #あいまい検索している場合 if re.findall(r'\*',name): name=name.strip('\*') #DBから名前をあいまい検索 cur.execute( f""" select name from pokedex where name like '{name}%' order by id """ ) #ヒットしたすべての結果:fnames fnames=np.array(cur.fetchall()).flatten() for fname in fnames: icon,bst=fetch_bst(cur,fname) print(bst) #あいまい検索でない場合 else: icon,bst=fetch_bst(cur,name) print(bst) #'*'なし、普通の検索 get_bst("グラードン")
(100, 150, 140, 100, 90, 90)
!calcev(努力値計算)
!calcev ポケモン名[*] レベル H A B C D S !calcev ポケモン名[*] レベル 努値を調べたい場所(HABCDS) 対応する箇所の実数値
性格の補正については、上昇補正/下降補正がついている場合は実数値の後に+/-を付けてください。
努力値を調べたい場所を入力しなかった場合は、全ての場所の努力値を求めます。
努力値を調べたい場所を入力した場合は、その場所のみを求めます。
使用例
※個体値が31でない場合は、努力値を0と仮定して、個: [個体値] の形式で出力される
実数値から努力値を計算するプログラム
概要
実は、calcivの条件をほんの少し変えるだけで作れる。
個体値 | 努力値 | |
---|---|---|
calciv | 不明 | 0と仮定 |
calcev | 31と仮定 | 不明 |
#calcev name="グラードン" lv=100 iv=cplist(31) ast=[341,399,316,200,216,306] ncor=[1,1,1,0.9,1,1.1] i_maxmindict={} i_matchdict={} #H~Sでループ for j in range(6): i_matchdict[j]=[] #努力値0~252でループ(0,4,12,20...) for i in range(64): ev_i=4*i ev=cplist(ev_i) #実数値が一致したときの努力値 if ast[j]==bst2ast_ij(j,bst,lv,iv,ev,ncor): i_matchdict[j].append(ev_i) if len(i_matchdict[j])==0: pass elif len(i_matchdict[j])==1: i_maxmindict[j]=i_matchdict[j] else: i_maxmindict[j]=[min(i_matchdict[j]),max(i_matchdict[j])] keys=['H','A','B','C','D','S'] for item in i_maxmindict.items(): print(f"{keys[item[0]]}:{l2s('~',item[1])}")
H:0
A:252
B:0
D:0
S:252
個体値が31より低い場合
個体値が31より低い場合は、努力値を0と仮定し、calciv_jを呼び出して、個体値を求めることにする。
例:Lv100 グラードン 陽気 の特攻が200だったとき、とりうる個体値
def calciv_j(ast_j,j,bst,lv,ncor): ev=cplist(0) #個体値0~31でループ i_matchdict_j=[] for i in range(32): iv=cplist(i) #実数値が一致したときの個体値 if ast_j==bst2ast_ij(j,bst,lv,iv,ev,ncor): i_matchdict_j.append(i) if len(i_matchdict_j)==0: pass elif len(i_matchdict_j)==1: i_maxmin_j=str(i_matchdict_j[0]) else: i_maxmin_j=f"{min(i_matchdict_j)}~{max(i_matchdict_j)}" print(i_maxmin_j) name="グラードン" ast_j=200 j=3 bst=[100,150,140,100,90,90] lv=100 ncor=[1,1,1,0.9,1,1.1] print("C個体値") calciv_j(ast_j,j,bst,lv,ncor)
C個体値
18
あとはプログラムをdiscord.pyの形式に修正し、出力形式をembedにすればOK!