工程棋比赛

2021-06-09 20:53:17

这是我试图赢得棋子的比赛的故事。 Asingle Freaking游戏。什么是如此特别?我很擅长象棋吗?一点也不。我在这个过程中改善了我的游戏吗?也没有。这是关于“Thejourney而不是目的地”的故事吗?并不真地。我至少有流程有趣吗?不太确定。这是我试图成为不敏感的故事,可能是最多研究的游戏,并使用我的软浪费背景对于可能不需要它的东西。

虽然我在国际象棋中灾难,但这篇文章对Whoeversery想要改善他们的游戏,我仍然认为它是值得分享的,可以将软件工程原则应用于一个问题。是顽皮的?你会看到最后。

在2020年Covid19大流行期间,我的兄弟和许多其他人一起举行了激情在线棋。在玩几个月的时候开始讲述它并挑战其他家庭,但我父亲会突然出现(并获得数字屠宰)。有一件事,我避免了深入消耗的爱好令人潜在的耗时。我知道国际象棋,了解甚至是一个平庸的业余俱乐部球员,你仍然需要在比赛中千分之一间沉入数百个。我承认我也不喜欢对我哥哥的思想,这是当时肯定的,因为他已经在他的腰带下徘徊了,我没有。

有一天,我终于给了他,接受了他的挑战。毋庸置疑,我完全失去了。我知道游戏的规则和基本的,曾经像一个孩子一起玩了一点点,但我的兄弟显然没有匹配。在赛前的赛后分析中,我认为我的劣势只长大,移动,移动,直到达到+9评估(相当于失去一个车,主教和典击到零),这是一个卷曲的任何希望,我辞职。这款蓝图随访了另一个比赛,我明白我不得不每次拆除麻木的事情。

我首次尝试在游戏中提高的尝试是做明显的:Headto Reddit和YouTube看看其他学习者推荐的内容。来自GM Naroditsky,Somereading和Puzze在Lichess的艺术课程之间,我也用互联网上随机播放了Awew Games。我的评级保持着漂亮的Lown,Lownever(1300 - 1400 Rapids在Lichess上)。

经过另一对对阵我哥哥的困境之后,它恍然大悟,我不希望殴打他。我跟着他相同的措施改进(玩,学习游戏,看视频),但我致力于更少的时间。他每月播放数百场比赛,我愿意玩Maymaybe 10.在那个步伐里,我只会进一步进一步落后。

在那一点上,我有第二次实现:我没有真正的争夺游戏,我不想在国际象棋中真正改善,我唯一只殴打一个人:我的兄弟。

国际象棋匹配通常可以分为三个阶段:开口,中间名和最终名称。在最终的胜利期间将尽职优势转换为胜利通常是“简单的”,后遗症的一些基本的检查模式,所以对我的问题是如何在第一个地方获得该优势。在一个中,在中间场期间的优势通常是通过长期战略实现的。和战术。第一个可以通过阅读和研究游戏原则(我可以享受的东西)堕落,而第二种只是通过做谜题(我不属于这样做)。我知道我会在这里缺点,Giventhat我的兄弟在Chess.com上每天做大约20个谜题,我永远无法赶上。这只留下了一种可能性:开幕期间的Gaitadadvantage。

国际象棋开放理论是谦虚的,涉及记忆的长序列和移动的长度,以及可能的对手的答复。初学者真的需要记住很多,但有些熟悉最常用的人可以走很长的路(或者我被告知)。我试过的是看起来我哥哥的大赛随机游戏,并尝试研究他是令人思想的开口。我看着意大利开幕式西西里人在利思赛中辩护,审议了他们背后的基本想法。我也看过一堆视频onyoutube。

显然,我的兄弟已经在我面前(更好)和SOI又一次地丢失了所有这些。更不用说,记住毫无意义(至少给我)开放动作是无聊和艰苦的。我并没有真正获得任何权利。另一个问题是,在我的对手偏离知识书的举动之后,我不知道如何做出反应,因为我并没有真正的职位。

是时候回来了,再次思考了。我意识到那时我并没有真正击败我的兄弟,但我试图改善我的游戏,对你的游戏完全发挥同样的开口。我可以更具体吗?我可以对我哥哥的弱点准备吗?显然,这不对他以外的任何球员努力,但仍然满足MyoGal。

解决的问题变得:发现了我兄弟(从现在开始的球员X的开放的位置可能会达到和处于AdisAdvantage。请记住,我们都不是游戏的专家,在沃尔维尔球员上没有非常准确地演奏。唯一可以追随书籍的唯一方法将是准确的,因为你至少知道是没有动的动手,他们可以获得一个优势。当你对阵俱乐部球员的时候,这个故事是有关的。如果你知道你的对手不太可能比博语找到正确的回应,所以你可以冒险(即博览会上的缺点)。

我还有500多场比赛的名单,我的兄弟在Chess.com上播放。作为Asoftware工程师,它对我来说是自然的,以便将此作为任何其他工程问题。

我首先通过使用Chess.com API和黑色和白色游戏之间的斯普利特来回下载他扮演的游戏。我专注于他扮演黑色的游戏,因为我觉得我在引导我想要的游戏时有更好的机会,如果我扮演了白色。

导入JSON导入请求DEF GET_MONTH_GAMES(播放器,YYYY_MM):URL =' https://api.chess.com/pub/player/ {} / games / {}' r =请求.get(url .format(播放器,yyyy_mm))如果不是r .ok:提出异常(' get_month_games失败')games = json .loads(r .content)#format:{游戏: [{url,pgn},......]}回程游戏['游戏']#...

导入Chomess.PGN导入IO导入JSON与打开(' games.json')作为f:data = json .load(f)games = []用于数据中的游戏:pgn = io .stringio(游戏)游戏.append(棋.pgn .read_game(pgn))black_games = [g g g gm g.headers [" black"] ==" playerx"]

然后我以这种方式制定了这个问题:“给出了所有职位球员的角色,他可能会在大量劣势的赫斯出来的地方伸出口是什么?”。

现在我有一个完美的问题,我终于在我曾经的域名玩过。我决定在Python进行分析,特别是使用jupyter笔记本,因为我真的不想创造一个可重用的工具,而是仅探索可用的数据并找到onesolution。事实证明,Python已经拥有漂亮的奇妙棋法:Python-Chess(移动生成,验证,可视化)和Python鳕鱼(使用着名的臭鱼国际象棋引擎评估Achess位置的绑定)。

我以这种方式将问题转换为图形问题:节点是一个棋子位置(在Fen符号中描述).An Edge链接两个节点,通过执行有效的移动,从源源处访问目的地。有一个特殊的初始节点是Commonto所有游戏:初始位置。

然后,我构建了Playerx作为黑色播放的所有游戏的图表,另外用特定移动播放的次数注释每个边缘。

Class GameGraph():def __init __(self):self .graph = igraph .graph(定向= true)def add_move(self,start_fen,end_fen,uci):vs = self ._ensure_vertex(start_fen)vt = self ._ensure_vertex(END_FEN )尝试:e = self .graph。.find(_source = vs .index,_target = vt .index)e [" count"] + = 1除外:e = self .graph .add_edge(vs ,vt)e [" uci"] = UCI E [" count"] = 1 @property def start_node(self):返回自我.graph .vs .find(chess .starting_fen) def _ensure_vertex(self,fen):尝试:返回自我.graph .vs .find(fen)除:v = self .graph .add_vertex(name = fen)v [" fen"] = fen [ "转弯"] =国际象棋.bess .board(fen).turn return v

什么结果是加权指示图(不是树,因为一个位置可以用不同的动作序列逐次)(合成的序列)(一种合成的序列,因为真实的一个是太大而无法适合这里):

这里初始位置是平方节点,颜色指示是否从黑色或白色转弯的位置。

我也希望在优势方面进行评估,因为Whiteand这样做,我使用了库存。鉴于评估数千个位置的过程有点耗时,我决定单独和创建一个JSON对象将每个独特的粪便映射到其系上的课程。

从鳕鱼中导入attribtifishstock =鳕鱼(参数= {"线程&#34 ;: 8})库存.set_depth(20)库存.set_skill_level(20)def eval_pos(fen):股票.set_fen_position(fen)返回股票.get_evaliumate ()#fens是FEN字符串和图形节点之间的映射。 fen,图形中的节点.Fens .Items():node .eva = eval_pos(fen)

评估在蜈蚣Adailition或“Mate-In XMoves”中返回,其中正数意味着白色和负数是黑色的AdadadaDap:

{"类型&#34 ;:" cp&#34 ;,"值&#34 ;: 12}#12 for white for white。{"类型&#34 ;:&#34 ;配偶&#34 ;,"价值&#34 ;: - 3}#黑色有三个。

100蜈蚣代表了比你oboponent更典当的优势,300个是像主教等一块次要作品。然而,请注意,即使在板上的碎片上,它也是根据其位置对碎片的价值。

我需要将此评估映射到更可管理的东西,如Number20和1.这样做,我任意决定,300+被映射到1.0的优势,300+的缺点映射到0.此外,任何matein x (即使x为20)也是1或0。

#返回[-1; 1] def等级(ev,fen):val = ev ["值"]如果ev ["类型"] ==" cp&#34 ;:#钳位至-300,+300。赢得一块就足够了。 val = max( - 300,min(300,val))返回x:也是最大额定值的Val / 300.0#mate。如果val> 0:返回1.0如果val< 0:返回 - 1.0#这已经是mate,但是是白色或黑色的吗? B =棋.best .bork 1.0如果b .turn == chess .white - 1.0#返回[0; 1],其中0是min,1是黑色的最大优势。 def rating_black(ev,fen):返回-rating(ev,fen)* 0.5 + 0.5

然后,信息就在那里,我只需要找到图表中的节点(即位置),其中黑色处于劣势,以及最有可能达到它的序列。我需要在这样的远处重视边缘,可以容易地计算达到鉴定的概率。我的推理如下:

在每个位置,我们可以评估一定移动的概率,并通过从该位置完成的动作的总值拍摄相应边缘拍摄的次数。

每个边缘现在都有0到1之间的重量,其中越高,较高的,边缘从该位置拍摄的概率越高。

然后,一定路径的概率是遍历边缘的概率的乘积。

要解决标准图形算法的问题,我需要以这样的方式在边缘处转换重量:

它们代表距离而不是概率(即较长的误差,路径的概率越低)。

两个节点之间的距离是遍历的权重的总和(与概率的乘积相反)。

def compute_edges_edges_edges_weight(顶点):all_count = sum(map(lambda x:x [" count" count" fortex .out_edges()))for边缘在顶点.out_edges():prob =边缘[&#34 ;计数"] / all_count边缘[" prob"] = prob边缘["重量"] = -math .log(prob)

采用边缘的对数将提供负数,因为概率在0到1之间。我们不必担心概率为零的概率(它会将对数拍摄为减去无穷大),因为每个边缘图表已经至少拍了一次。较低的可使能,对数越负,因此反转其签名使其满足我们的要求,因为:

Logarithms的总和与Initarguments的乘积的对数相同:log(a)+ log(b)= log(a * b)。

配备此数据,我们可以使用Dijkstra的算法计算InitialNode和所有其他节点之间的ShortestPath。结果是每个节点和初始位置的最短路径之间的映射,这表示最可能降落在本集会中的移动序列。

此时,我任意选择了最小的优势,并对路径进行了排序。前几条路径代表了我最佳机会,以获得对球员的开口的散系。

我发现了什么?这是由上面的算法(白色的Tomove)返回的位置:

正如你可以看到黑色的情况非常糟糕(+8.9根据Tostockfish),因为G6,黑色的最后一个举动,是一个错误。白会腾出,乘坐E5典当和车。黑色的游戏几乎没有结束,斯蒂斯争夺拯救骑士,H7典当和主教。另一个结果这个(白色移动):

这里的问题是,这些问题是玩家唯一只有他的第一场比赛而不是再次重复的问题。早期的女王攻击是由非常擅长的球员进行的,他们是那个级别的唯一有效的球员。球员x并没有为那个陷阱而堕落,因为最好的陷阱,因为更好的对手不起那种举动!我仰视我真的无法使用这个开放,因为玩家x知道如何保护它现在,不会再堕落它。

另一个问题与只有一次发生一次的动作序列有关。最终位置的概率是最后一个公共位置的概率,因为每个边缘都有1.0的可追随性(鉴于没有播放其他可能性)。在下面的示例(标有其概率的边缘)中,您可以遵循edgeswith 7和6(移动2的最常见位置),但随后从该点开始遵循一个内容,所有后续移动都将具有只有一次(因为只有单一匹配达到该位置),而且达到的步骤将具有1.0的概率。

这直观地不正确,因为它是不可能的,即相同的序列移动将以绝对的确定性播放。我们没有足够的游戏,这些职位扮演了这一点。

着名的报价(来自Brewster?)“在理论上没有理论和实践之间没有区别,而在实践中,在实践中”,在这种情况下也是如此,所以我需要一些调整和手工读数来寻找更好的候选人职位。

为了纠正第二个问题,我决定将一个上限绑定到边缘的可Probiabity,因此只有一次反向失去概率的长度的动作序列。

def compute_edges_edges_epeges_weight(顶点,prob_ceiling = 0.9):all_count = sum(map(lambda x:x [" count" fortex .out_edges()),用于顶点中的边缘.out_edges():#certainty并未#39; t存在......让' s放置概率上限(默认为90%)。 prob = min(边缘[" count"] / all_count,prob_ceiling)边缘[" prob"] = prob边缘["权重"] = -math .log(概率)

对于第一个问题,我只是手动筛选了不好的建议。在最后一天,我只需要一个或两个良好的位置来工作。

另一个调整与我不希望白人的概率中不希望影响路径的可能性,因为我正在玩白色,并且可以弥合哪个路径。因此,我将所有白人概率设置为1.0(零重量)。最终结果是这样的图形:

根据LiChess的说法,这是一个含有啤酒的防御(两个典当攻击)。在此属中,黑色(NB6)和黑色只有一个好的举动,仍处于aslorlight的劣势(根据库存+0.6)。但是,从该位置播放播放NF4,这是坏的(+2.3)。我在LiChess的一项研究中创建了一项研究,看了几种变化(Playerx播放的好的动作和动作)。最终结果是我试图记忆安德朗德的可能性树。例如,我需要知道D5的动作是什么,为什么移动NF4坏了并准备了最好的响应。

我没有花太多时间这样做,因为我很快厌倦了,但是idid准备了即将到来的比赛。

好像我在预测未来,在我对球员的比赛中,我们进入了Analekhine Defense。放在压力下,他确实最终起来了他的骑士atmove 5.甚至比你最终更好的球员比你在劣势的时候更好地误解了另一个。当你赢得时,很容易玩,但是当你失去时,你可以保持酷吗?在移动10i处于A + 7.1的优势,几乎不可能失去,但我也在准备时。看看黑人的立场是如何以及我的操作系统都指向敌人的国王:

我开始从那一点开始犯了一堆错误,但我仍然可以保持非凡的优势直到移动27:

不幸的是,我准时很低(这是一个快速的10分钟比赛),所以我赶紧迅速移动。我最终弄乱了32和33,给了Myhalf-Devonent对手伴侣:/。

我从这个努力中学到了什么?一些事情,大多数似乎显着回顾:

较低水平的球员不擅长惩罚来自特色的可疑动作。进入棘手的位置,在只有一个响应是正确的方法来获得优势的方法。

开口不是一切。如果您在时间管理和策略时不好,则可能失去完全获胜的职位。国际象棋游戏可以被一个糟糕的举动铺板。

学习游戏很重要,如果你的对手比你好,而且没有银耳子弹,但可以采用特定准备缩小技能差距。

将软件工程原则应用于国际象棋很有趣。在殴打你的兄弟时,做到这一点更有趣!我希望有一天我能做到:)

您可以找到我在github repo中使用的代码。请注意,我没有输入数据,代码相当凌乱,但我希望它可以是某种东西,特别是对于考虑计算机SCIEncemight的人,尤其是考虑到他们的人。看,你可以解决“现实世界”问题,这不仅仅是在周围移动的比特!

这就是所有的人,我希望我能有一天能赢得哥哥的比赛,但直到那时,我会继续尝试& mldr我自己的方式。 原始用户名被编辑出来,因为我没有让我的兄弟的人发布比赛。 在他发现之前,我还希望再次尝试这个技巧:)♥