bumcatxian 发表于 2021-9-1 00:15:14

[python]networkx-我在北侠学画图

本帖最后由 bumcatxian 于 2021-9-1 12:14 AM 编辑

来北侠已经有一段时间了,对于我来说,玩这个游戏的意义一直都是编程第一,江湖第二。用python也有一些年头了,python的特点之一就是工具多,不用重复造轮子,最近发现有个图形相关的工具包networkx,用于构建和操作复杂的图结构,并提供分析图的算法。正好拿来北侠小试牛刀。一、安装直接pip安装就行,matplotlib主要用来提供绘图能力pip install networkx
pip install matplotlib二、图的定义接下来我会用最近刚上线的万兽山庄为例,演示如何用networkx作图。首先我们看看万兽山庄的lm:接下来开始定义# -*- coding: utf-8 -*-
import networkx as nx
import matplotlib.pyplot as plt
#创建一个有向图
g = nx.DiGraph(area = '万兽山庄')

#添加名字为1的节点,并加上一个roomname属性,赋值为'大门'
g.add_node(1)
g.nodes['roomname'] = '大门'

#添加节点时同时加上属性也是可以的
g.add_node(2,roomname = '土路')

#添加2个节点之间的边,weight表示权重,path属性用来存储出口信息
g.add_edge(1,2, weight = 1,path = 'north')
g.add_edge(2,1, weight = 1,path = 'south')这样就画好了两个节点和一条边,如此类推,我把大门附近的房间也画了一下,并用matplotlib展示出来pos = nx.spring_layout(g)
nx.draw(g,pos,node_size=900)
#取出节点的roomname属性,并画出
node_labels = nx.get_node_attributes(g,'roomname')
nx.draw_networkx_labels(g,pos,labels = node_labels)
#取出边的path属性,并画出
edge_labels = nx.get_edge_attributes(g,'path')
nx.draw_networkx_edge_labels(g,pos,edge_labels = edge_labels,label_pos=0.3)
plt.show()运行结果是这样子的,双向的label画上去后有些丑。。
到目前为止,一个简单的图就基本画完了。三、路径计算为了方便看出效果,我重新画了一幅只有房间号的图接下来直接利用networkx自带的dijkstra_path函数计算路径,即使是像我这样的算法小白也能轻松搞定#使用dijkstra算法计算2点间的最短路径
print(nx.dijkstra_path(g,6,10))

#输出:然后配合之前的path属性,我们可以很简单的生成需要发送给mud的命令def cal_path(g,start,end):
    path = nx.dijkstra_path(g,start,end)
    cmd = []
    index = 0
    while index < len(path) - 1:
      cmd.append(g]]['path'])
      index += 1
    return ';'.join(cmd)

print(cal_path(g,6,10))
#输出:east;south;enter;east
networkx同样也为我们提供了遍历算法,下面以DFS为例#以节点6为起点,用DFS算法遍历图g
print(list(nx.dfs_preorder_nodes(g,6)))
#输出:同理,获取遍历路径的命令就很容易实现了def DFS(g,source,depth_limit=len(g)):
    path = list(nx.dfs_preorder_nodes(g,source,depth_limit))
    path.append(source)#把起点加到最后,遍历完成后回到起点
    cmd = []
    index = 0
    while index < len(path) - 1:
      cmd.append(cal_path(g,path,path))
      index += 1
    return ';'.join(cmd)
print(DFS(g,6))
#输出:northeast;northdown;southup;southup;south;west;east;east;west;enter;west;east;east;west;out;north;west
四、结尾networkx的基本使用大概就介绍到这了,当然,只靠上面的内容是不足以做出一个可以在游戏里走路的工具的,后面我大概还会写两篇,一个是python与mush客户端的配合,讲讲如何利用trigger制作录制工具,另一个是其他问题的解决思路,例如房间的定位等等。当然也不排除就这样鸽了。最后附上两个参考网站,对networkx有兴趣的同学可以去学习一下。networkx是什么networkx手册



xurufeng 发表于 2021-9-1 10:00:00

不明觉厉yct27

vivia 发表于 2021-9-1 10:01:04

哇,膜拜

jarlyyn 发表于 2021-9-1 13:32:48

其实dijkstra 自己实现下也不复杂

建议在做mapper的时候加入几个元素

第一,路径实际花费时间,和你权重类似,最后应该可以算出来路上花的时间

第二,tag,就是可以通过tag来开启和关闭一些路径

第三,直接到达的路径。就是任何地方都能直接前往的地方。

jarlyyn 发表于 2021-9-1 13:35:36

给一个我用go实现的mapper做参考,其实没几行代码

https://github.com/jarlyyn/hellclient/blob/master/src/vendor/modules/mapper/mapper.go

原始结构

https://github.com/jarlyyn/hellclient/blob/master/src/vendor/modules/mapper/walking.go

寻路逻辑

还有部分优化空间

jarlyyn 发表于 2021-9-1 13:51:33

另外这一块本身是完全可以在js/lua等脚本语言里实现的。

但由于mushclient非常老,性能上是有点问题的(以我玩的mud为例,同样的配置,同样的js机器人,用mushclient 5跑5个id会阿卡,用mushclient 4 10个id会卡 我用的客户端我收集到的信息是能挂18个id)

所以,推荐在mushclient里实现的话,还是用dll甚至acrtivex的形式实现

bumcatxian 发表于 2021-9-1 14:48:55

jarlyyn 发表于 2021-9-1 01:51 PM
另外这一块本身是完全可以在js/lua等脚本语言里实现的。

但由于mushclient非常老,性能上是有点问题的(以 ...

感谢大佬提供代码学习,我有空去研究一下。用python更多的原因是出于个人喜好,而且在游戏之外的领域也是我主要使用的语言。客户端的确是比较棘手的问题,支持py的客户端并不多,我所知的就只有mush或tintin。个人也对大量账号同时在线没啥需求,就先用mush 凑合着吧。

mathematics 发表于 2021-9-1 14:50:38

好贴留名yct2.yct70

tianzaishui 发表于 2021-9-2 00:35:00

学习学习

windygreen 发表于 2021-9-3 10:41:19

膜拜
页: [1] 2
查看完整版本: [python]networkx-我在北侠学画图