forked from erreurt/MahjongAI
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added code analysis comments, collated structure with gitignore, and …
…added local fake server mode.
- Loading branch information
Showing
33 changed files
with
410 additions
and
4,184 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# Byte-compiled / optimized / DLL files | ||
*/__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
MANIFEST | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# celery beat schedule file | ||
celerybeat-schedule | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ | ||
|
||
#UltraEdit | ||
*.bak | ||
|
||
#AI | ||
logger/log_jianyang_ai_1/ |
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#coding=utf-8 | ||
from functools import wraps | ||
import inspect | ||
import sys | ||
|
||
def LogTrace(func): | ||
if '--stdio' in sys.argv: | ||
LogTrace.out=sys.stdout | ||
else: | ||
LogTrace.out=open('FuncTrace.log','w') | ||
LogTrace.FuncArgsList=[] #if func.name in this list, print args | ||
print(inspect.getargspec(func)) | ||
@wraps(func) | ||
def wrapper(*args,**kwargs): | ||
if not hasattr(LogTrace,'level'): | ||
LogTrace.level=0 | ||
LogLevel=''.join([' ' for i in range(LogTrace.level)]) | ||
LogStr=LogLevel+'I : '+func.__module__+'.'+func.__name__ | ||
try: | ||
spec=inspect.getcallargs(func,*args,**kwargs) | ||
if 'self' in spec: | ||
spec.pop('self') | ||
LogStr+=' '+str(spec) | ||
except Exception: | ||
LogStr+=' ParseArgError' | ||
#LogTrace.out.write(LogStr+'\n') | ||
#print(inspect.getargspec(func)) | ||
#print(inspect.getsource(func)) | ||
LogTrace.level+=1 | ||
ret = func(*args,**kwargs) | ||
LogTrace.level-=1 | ||
LogStr=LogLevel+'O : '+func.__module__+'.'+func.__name__ | ||
try: | ||
|
||
LogStr+=' '+str(ret) | ||
except Exception: | ||
LogStr+=' ParseRetError' | ||
#LogTrace.out.write(LogStr+'\n') | ||
LogTrace.out.flush() | ||
return ret | ||
|
||
return wrapper | ||
|
||
def AnaLog(s,msg): | ||
if not hasattr(AnaLog,'out'): | ||
if '--stdio' in sys.argv: | ||
AnaLog.out=sys.stdout | ||
else: | ||
AnaLog.out=open('AnaMsg.log','w') | ||
AnaLog.out.write(s+' : '+str(msg)+'\n') | ||
AnaLog.out.flush() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#coding=utf-8 | ||
from analyzer import * | ||
|
||
class A(): | ||
@LogTrace | ||
def __init__(self,b=2): | ||
self.b=2 | ||
@LogTrace | ||
def q(self,a): | ||
return g(a) | ||
def __call__(self): | ||
print(self) | ||
|
||
class B(): | ||
f=A() | ||
|
||
@LogTrace | ||
def f(a,b=0,*c,**d): | ||
return g(a-1)+g(a-2) | ||
|
||
@LogTrace | ||
def g(a): | ||
return h(a-1)+h(a-2) | ||
|
||
|
||
@LogTrace | ||
def p(): | ||
pass | ||
|
||
@LogTrace | ||
def h(a): | ||
p() | ||
if a<2: return 1 | ||
return h(a-1)+h(a-2) | ||
|
||
def _decorator(foo): | ||
def magic( self ) : | ||
print("start magic") | ||
foo( self ) | ||
print("end magic") | ||
return magic | ||
|
||
class Test(object): | ||
|
||
@_decorator | ||
def bar( self ) : | ||
print("normal call") | ||
|
||
test = Test() | ||
|
||
test.bar() | ||
|
||
if __name__=='__main__': | ||
a=A() | ||
a.q(5) | ||
#print(f(5)) | ||
AnaLog(['123','456']) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
包格式分析: | ||
|
||
所有牌采用tile136格式传输,tile136//4对应tile34格式,其中AI讲将{16: 35, 52: 36, 88: 37}视为特殊的三个红宝牌(tile136:tile34) | ||
传输给bot的所有牌tile136不能相同 | ||
|
||
LookingForAGame期间: | ||
先send <JOIN lobby_type,game_type寻找房间 (lobby_type固定为'0') | ||
<REJOIN : _send('<JOIN t="{}, r" />'.format(game_type)) | ||
<GO : _send('<GOK /') & _send('<NEXTREADY />') & parse_game_type & _parse_game_rule | ||
<UN : parse_names_and_levels | ||
n0 n1 n2 n3 : URL编码的自己开始逆时针4个用户名 | ||
dan="9,11,10,10" 从自己开始逆时针四个人的段位(9=1级,10=初段,11=二段) | ||
<TAIKYOKU : parse_log_link 保存replay链接有关 | ||
<LN : _send(self._pxr_tag()) | ||
|
||
GameLoop在tenhou_client.continue_game,对_get的msg按\0分割后一次parse每个包的类型 | ||
<INIT : _handle_initial_msg | ||
<REINIT : _handle_reconnection_msg | ||
<T : 自己draw tile | ||
<U <V <W : 逆时针顺序其余三家 | ||
<DORA : _handle_new_bonus_indicator | ||
<REACH : _handle_reach_claim (step="1") | ||
<AGARI : _handle_round_end | ||
<RYUUKYOKU : _handle_liuju | ||
<N who= : _handle_meld_call(msg, meld_tile) | ||
TenhouParser.is_discard_msg : _handle_opponent_discard | ||
owari : _handle_final_scores | ||
<PROF : continue_game = False | ||
msg has win_suggestions : _call_win | ||
after draw: | ||
win_suggestions = ['t="16"', 't="48"'] _send('<N type="7" />') #主动和牌 | ||
't="64"':九種九牌 _send('<N type="9" />') #主动流局 | ||
|
||
_handle_initial_msg : | ||
format : | ||
seed="round_number,honba_sticks,reach_sticks,?,?,bonus_tile_indicator1,bonus_tile_indicator2......." | ||
ten="scores0,scores1,scores2,scores3" | ||
oya="dealer" | ||
hai="tile1,tile2,...,tile13" | ||
'round_number': round_info[0], #0=东1局 | ||
'honba_sticks': round_info[1], #连庄棒 | ||
'reach_sticks': round_info[2], #立直棒 | ||
'bonus_tile_indicator': round_info[5:], #明宝牌 | ||
'dealer': dealer, #庄家 | ||
'scores': scores #四家分数 | ||
'tiles' : parse_initial_hand #起始手牌(tile136) | ||
|
||
_handle_draw_tile : | ||
format : | ||
<T136\> | ||
如果含有t="32"表示可以立直 | ||
TenhouParser.parse_tile : | ||
ex. <E133/> -> 133 (r'^<[tefgEFGTUVWD]+\d*') | ||
'' | ||
|
||
_handle_new_bonus_indicator : | ||
format : | ||
<DORA hai="tile136" /> | ||
|
||
_handle_reach_claim : | ||
format : | ||
<REACH who="0-3" step="1"/> | ||
|
||
_handle_round_end : | ||
format : | ||
<AGARI ba="0,1" hai="4,7,8,12,16,18,23,27,69,70,71,88,89,90" machi="27" ten="50,8000,1" yaku="1,1,2,1,54,2,53,0" doraHai="50" doraHaiUra="46" who="1" fromWho="0" sc="250,-80,240,90,250,0,250,0" /> | ||
关键字段:who(胡牌者0-3),fromWho(点炮者0-3),machi(点炮牌),hai(胡牌者手牌),ten(符数?、点数、?) | ||
|
||
_handle_liuju : | ||
format : | ||
<RYUUKYOKU ba="0,0" sc="170,10,410,10,250,10,170,-30" hai1="0,1,50,55,81,85,88" hai2="46,47,58,61,65,79,82" hai3="tile136..." /> | ||
|
||
_handle_opponent_discard : | ||
format <--: | ||
r"^<[defgDEFG]+\d*" | ||
'd': 0, 'e': 1, 'f': 2, 'g': 3 小写字母座位顺序lower() ,小写为摸切,大写非摸切 | ||
包含"t="说明有吃碰杠操作 | ||
if t="3"' in msg or 't="7" in msg :bot可以选择杠牌 | ||
t="1" 可以碰 t="4" 可以吃 | ||
如果包含t=需要send<N\>包回复是否吃碰杠 | ||
format -->: | ||
<N type="3" hai0="26" hai1="29" /> | ||
type=1表示碰操作,type=3表示吃操作 | ||
return -1 表示自己出牌或者杠 | ||
return -2 表示以缓存完毕无需其他操作 | ||
return >=0表示尝试吃碰,记录一下吃碰的牌等服务器返回<N\>结果 | ||
|
||
_handle_meld_call : | ||
#某人成功吃碰杠 | ||
format <--: | ||
<N who="0=3" m="(int)data"\> | ||
有很复杂的编码,详见parser | ||
如果是自己吃碰需要回复一个<D\>包指明要出的牌 | ||
|
||
|
||
send format : | ||
<REACH hai="tile136"/> #宣告立直 | ||
<N type="5" hai="meld_tile136"/> #加杠 | ||
<N type="4" hai="meld_tile136"/> #暗杠 | ||
<N type="3" hai0="tile136" hai1="tile136" /> #回应吃 | ||
<N type="2" /> #回应明杠 | ||
<N type="1" hai0="tile136" hai1="tile136" /> #回应碰 | ||
<N\> #回应吃碰杠,不操作 | ||
<D p="tile136"/> #出牌 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Oops, something went wrong.