{"id":16434619,"url":"https://github.com/halfrost/2017_ele_hackathon_tank","last_synced_at":"2025-03-23T08:31:50.209Z","repository":{"id":91082396,"uuid":"112484021","full_name":"halfrost/2017_ele_hackathon_tank","owner":"halfrost","description":"🏆【2017 饿了么 黑客马拉松】 初赛第二题","archived":false,"fork":false,"pushed_at":"2017-12-17T12:13:22.000Z","size":26941,"stargazers_count":16,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-01T23:26:13.571Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/halfrost.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-11-29T14:16:19.000Z","updated_at":"2024-12-10T06:21:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"7ca87895-864f-4ed7-a830-4fedd2c4ad9d","html_url":"https://github.com/halfrost/2017_ele_hackathon_tank","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halfrost%2F2017_ele_hackathon_tank","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halfrost%2F2017_ele_hackathon_tank/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halfrost%2F2017_ele_hackathon_tank/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halfrost%2F2017_ele_hackathon_tank/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/halfrost","download_url":"https://codeload.github.com/halfrost/2017_ele_hackathon_tank/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244287029,"owners_count":20428885,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T08:49:41.182Z","updated_at":"2025-03-23T08:31:50.179Z","avatar_url":"https://github.com/halfrost.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [饿了么-百度外卖 2017 黑客马拉松](https://hackathon.ele.me/?introduce.html) 初赛第二题 Tank 大战\n\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/hackathon_2017_1.png'\u003e\n\u003c/p\u003e\n\n\n## 比赛形式\n1. 比赛采取循环赛制，即每组队伍循环和其他队伍进行两两对战，单局比赛获胜方得3分，败者得0分，平局各得1分。最终获得分数高的队伍获胜。\n2. 组委会提供5张对战地图。第一个星期一张（公开），第二个星期一张（公开），最后一天提供三张（不公开）。最终单局比赛成绩取**最后一天**两只队伍在**5张地图**上的对战结果计算，每局比赛胜利算一分，最终分数高的获胜。然后各个队伍间按循环赛积分进行排名。\n3. 前期的比赛只公布各团队的积分，对对战过程进行保密。\n\n\n## 比赛细节描述\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/hackathon_2017_3.png'\u003e\n\u003c/p\u003e\n\n1. 地图大小为N*N（每张地图可能大小不一致），中心旋转对称，队伍的tank出生在地图的两个对边角上。\n2. 地图上有以下元素（但是不保证所有的元素在每一张地图中都会出现）\n    1. 障碍物，不可被摧毁。地图的最外围会被一圈障碍物覆盖。\n    2. 战旗，始终固定在地图中心出现。可被经过的tank获得。战旗消失后会在固定回合后重新出现。\n    3. 森林，处于森林中的tank不会被敌方发现。处于森里中的炮弹对双方均不可见。\n3. 每只队伍M量tank。  \n4. 每辆tank在地图上最多只能存在一发炮弹。必须在之前发射的炮弹消失掉之后才能进行开火的操作。  \n5. tank可以进行如下操作：左转，右转，掉头，前进，原地不动，开火。开火方向可以和坦克的行进方向不一样。开火方向限制在上下左右四个方向（**游戏中所有的方向均以地图为基准**，即向左转向会转到地图向左的方向，而不是tank自己的左方。）。每个回合只能执行一个操作。前进只能走完tank速度的全程。\n6. tank速度为x，炮弹速度为y，其中x\u003cy。\n7. 炮弹之间不能互相抵消，炮弹不区分敌我。\n8. tank有H格血量，每发炮弹只能打掉tank一格血量。\n9. 炮弹具有最高优先结算权，即游戏首先结算炮弹的行进，然后再结算tank的开火，最后结算行进和移动操作。如果炮弹击毁一辆tank，此辆tank将不具有进行下一步操作的权利。炮弹命中tank或障碍物之后炮弹即消失。多发炮弹命中同一量坦克后，所有炮弹全部消失，即使被命中的tank只有一滴HP。tank行进路上遭遇炮弹会被判定为被击中。\n10. 同一坐标不允许有两辆tank存在，即两辆tank的下一步操作导致进入相同坐标，这两辆tank的位置停留在进入相同坐标前的位置。例如，如果两辆坦克行进两格后会处于同于位置，则两辆坦克各自行进一格。\n11. 单场地图比赛获胜条件：\n\tA）在限定的回合当中，一方的坦克被全部击毁则游戏结束，幸存的一方获胜。\n\tB）在限定的回合结束后，双方均有坦克存留，按以下方式结算：\n    1. 每辆剩余的tank获得i分\n    2. 每一面获取的战旗得j分\n    3. i+j分数高的一方获胜\n\n\n## 游戏方式\n\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/hackathon_2017_4.png'\u003e\n\u003c/p\u003e\n\n\n回合制。每回合敌我双方都有行动一次的机会。子弹先行动。\n\n## 游戏引擎设计\n1. 参赛选手的程序和判题程序通过thrift协议交互。idl定义在 src/main/resources/player.idl中。\n2. 参赛选手的程序部署在独立的docker上，并启动相应的thrift服务。\n3. 游戏初始，判题程序向参赛双方提供如下数据：地图，每辆坦克的属性\n4. 之后判题程序工作于询问模式，每回合询问参赛双方一次操作指令，然后对操作指令进行结算，并将结算结果返回参赛双方，并进入下一回合。\n5. 每回个超时时间为s毫秒，如果超时则视参赛方tank不进行任何操作。\n6. 比赛最多进行t回合。如果t回合之前一方tank全部被击毁，游戏结束。\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/hackathon_2017_5.png'\u003e\n\u003c/p\u003e\n\n\n## 选手程序设计\n1. 参赛选手的程序需要实现src/main/resources/player.idl中定义的服务，并启动在80端口上。\n2. 参赛选手需要自己订制docker容器，启动脚本为 /data/start.sh\n\n为了保证比赛的公平性以及区分度，组委会保留对以上描述中的变量（n,m,x,y,h,i,j,t）进行临时调整的权利。大致范围如下\nN\u003c30,M\u003c5, X\u003cY\u003c=4, h\u003c4, i=j, t\u003c=200, s\u003c=2000ms\n\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/hackathon_2017_2.png'\u003e\n\u003c/p\u003e\n\n\n## 构建\n\n1.由于比赛需要2名玩家，所以本地要先构建出2名玩家的 server。项目文件夹下有2个文件夹，一个是8080，另一个是8081，分别代表2名玩家。分别进入到2个文件夹下，执行\n\n```go\ngo build server.go\n\n```\n\n编译出最新的 server 的可执行文件。\n\n注：比赛由于需要提交 80 端口的程序，运行在 Docker 内。所以在 Mac 上需要交叉编译 Linux 平台，编译命令 ：\n\n```go\n\nGOOS=linux GOARCH=amd64 go build server.go\n\n```\n\n至于 Docker 打包成 image 的步骤见另外 repo 内另外一份 [docker文档](./docker.md)\n\n2.执行 play\\_game 文件夹下的 start\\_play\\_game.sh 文件，把游戏引擎跑起来。最终游戏输出的结果会存在  play\\_game/data/logs 路径下。\n\n3.上传 log 文件到[游戏回放网页](https://tank-replayer.faas.elenet.me/#/)观看游戏回放。[游戏回放网页](https://tank-replayer.faas.elenet.me/#/) 可能会变成内网访问。\n\n游戏最终结果由于游戏引擎判出：\n\n```\n\nGame result: {\n  \"result\" : \"draw\",\n  \"win\" : null,\n  \"state\" : \"localhost:8080: 6,localhost:8081: 6\",\n  \"reason\" : \"\"\n}\n\n\n```\n\n\n## 更改游戏参数\n\n更改游戏参数和游戏地图都是在 start\\_play\\_game.sh 文件中进行更改的。\n\n```\n\n#! /bin/bash\n\n\nexec java -cp ./data/client/tank.jar:./data/client/classes ele.me.hackathon.tank.GameEngine ./data/secondweekmap.txt 4 1 2 1 1 1 100 2000 localhost:8080 localhost:8081 2\u003e\u00261  | tee ./data/logs/engine.log\n\n\n```\n\n依次说明一下参数：\n\n./data/secondweekmap.txt 地图。目前在 ./play_game/data/ 路径下包含7张地图可以选择。\n\n4 坦克数量  \n1 坦克速度  \n2 炮弹速度  \n1 每辆坦克的血量格  \n1 击毁坦克得分  \n1 夺旗得分  \n100 比赛最多进行的回合数  \n2000 每回个超时时间毫秒  \n\n依次更改上述的参数可以达到游戏选关和难度调整的目的。\n\n7张地图依次是：\n\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/map_1.png'\u003e\n\u003c/p\u003e\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/map_2.png'\u003e\n\u003c/p\u003e\n\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/map_3.png'\u003e\n\u003c/p\u003e\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/map_4.png'\u003e\n\u003c/p\u003e\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/map_5.png'\u003e\n\u003c/p\u003e\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/map_6.png'\u003e\n\u003c/p\u003e\n\n\n\u003cp align='center'\u003e\n\u003cimg src='./image/map_7.png'\u003e\n\u003c/p\u003e\n\n## 我方坦克策略\n\n寻路：A* 寻路  \n\n躲避：A* 自动判断。把子弹2回合以后的行径路线上标识为不可达。为何是2回合？因为坦克转向需要一回合，另外一个回合移动。所以要先预判2回合。\n\n坦克角色分配：\n\n第一辆坦克，“杀手”职业，追着敌方坦克打。  \n第二辆坦克，“夺旗”职业，围着地图中心点周围 9 * 9 的格子徘徊。  \n第三辆坦克，“辅助”职业，围着地图中心点周围四分之一地图大小徘徊。  \n第四辆坦克，“猥琐”职业，专门躲在草丛中，放暗剑，在草丛中游走。  \n\n这四辆坦克的重要性依次降低。最重要的就是第一辆。所以每死一辆坦克，职业都要进行重新排列，按照坦克编号重新编排一下职业。这里就会有职业转换的问题。  \n\n第一辆坦克有可能找不到敌方的坦克，因为敌方都躲在草里。这时候，杀手就会开启“扫荡”模式，走到每个草丛前，朝着草丛开一枪就走人，换下个草丛，依次轮过去。  \n\n\n# 作者\n\nProduced by [halfrost](https://github.com/halfrost)、[mmoaay](https://github.com/mmoaay) and [EyreFree](https://github.com/EyreFree).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalfrost%2F2017_ele_hackathon_tank","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhalfrost%2F2017_ele_hackathon_tank","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalfrost%2F2017_ele_hackathon_tank/lists"}