实验鼠竞赛:遗传算法练习


113

这是每两周挑战#3。主题:遗传算法

这个挑战有点实验。我们想看看我们可以用遗传算法做些什么。并非所有内容都是最佳的,但我们尽了最大努力使其变得可访问。如果能够解决问题,谁会知道我们将来会看到什么。也许是希尔的遗传之王?

规格很长!我们已尝试将规范分为基础知识-开始使用框架并提交答案所需的最低知识-和Gory Details-完整规范,以及有关控制器的所有详细信息,可以自己写。
如果您有任何疑问,请随时加入我们的聊天室!

您是行为心理学的研究者。今天是星期五晚上,您和您的同事决定找点乐子,并用您的实验用老鼠参加小老鼠赛跑。实际上,在我们对它们过于迷恋之前,我们称它们为标本

您已经为标本设置了一个小小的赛道,并且为了使其更加有趣,您在赛道上放置了一些墙壁,陷阱和传送器。现在,您的标本仍然是老鼠……他们不知道什么是陷阱或传送器。他们所看到的只是一些颜色不同的东西。他们也没有任何记忆力-他们所能做的就是根据当前环境做出决定。我猜自然选择会从那些不知道如何避免陷阱的标本中挑选出来(这场比赛将需要一段时间...)。让游戏开始!

使用中的木板示例图

†84,465个样本在进行挑战时受到了伤害。

基础

这是一款单人游戏(您和您的同事不想混合人口,因此每个人都建立自己的赛车场)。赛道是一个矩形网格,高15格,宽50格。您从左边缘(其中x = 0)上随机(不一定不同)的15个样本开始。您的标本应尝试达到x≥490≤y≤14的任何单元的目标(标本可能会超出右侧的轨道)。每次发生这种情况,您都会得到一点。您也以1点开始游戏。您应该尝试在10,000转后最大化积分。

多个标本可能占据同一个细胞,并且不会相互作用。

在每个转弯处,每个标本都看到一个5x5的周围网格(自身位于中心)。该网格的每个单元包含一个颜色-115-1表示超出范围的单元格。如果标本超出范围,则标本会死亡。至于其他颜色,它们代表空的单元,陷阱,墙壁和传送器。但是您的标本不知道哪种颜色代表什么,您也不知道。但是有一些限制:

  • 8种颜色代表空单元格。
  • 4种颜色代表一个传送器。传送器会将标本发送到其9x9邻域内的某个单元中。对于所有相同颜色的传送器,此偏移量将相同。
  • 2种颜色代表墙壁。进入墙壁等同于静止不动。
  • 2种颜色代表陷阱。甲陷阱表明一个的9个单元在其近邻的是致死的(不一定是陷阱细胞本身)。对于所有相同颜色的陷阱,此偏移量将相同。

现在,关于自然选择……每个标本都有一个基因组,即一个具有100位的数字。通过杂交两个现有的标本,然后稍微突变基因组,可以创建新的标本。标本越成功,复制的机会就越大。

因此,这是您的任务:您将编写一个函数,该函数接收标本所见颜色的5x5网格及其基因组作为输入。您的函数将返回样本的移动(Δx,Δy),其中Δx和Δy分别为之一{-1, 0, 1}。您不得在函数调用之间保留任何数据。这包括使用您自己的随机数生成器。您的函数将提供带种子的RNG,您可以随意使用它。

您提交的分数将是50条随机轨道上的点数的几何平均值。我们发现该分数存在一定差异。因此,这些分数将是初步的。一旦挑战消失,将宣布截止日期。在截止日期结束时,将随机选择100个委员会,所有提交的意见将在这100个委员会中重新评分。请随意在您的答案中加上预估的分数,但我们会为每份提交的作品评分,以确保没有人作弊。

我们提供了几种语言的控制器程序。目前,您可以使用Python(2或3),RubyC ++C#Java编写提交内容。控制器生成棋盘,运行游戏并为遗传算法提供框架。您所要做的就是提供移动功能。

等一下,那么我该如何处理基因组呢?

挑战在于弄清楚!

由于标本没有记忆,因此您在给定回合中所拥有的只是5x5的颜色网格,对您没有任何意义。因此,您必须使用基因组来达到目标​​。通常的想法是,您使用基因组的一部分来存储有关颜色或网格布局的信息,而您的机器人则根据存储在基因组中的其他信息来做出决定。

现在,您当然不能实际在此处手动存储任何内容。因此,在那里存储的实际信息最初将是完全随机的。但是遗传算法将很快选择那些基因组包含正确信息的标本,同时杀死那些信息错误的标本。您的目标是找到从基因组位和视野到移动的映射,这使您可以快速找到目标的路径,并且始终如一地发展为制胜法宝。

这应该是足够的信息,可以帮助您入门。如果需要,可以跳过下一部分,并从底部的控制器列表中选择您要选择的控制器(还包含有关如何使用该特定控制器的信息)。

继续阅读...

血腥细节

该规范已完成。所有控制器都必须执行这些规则。

除非另有说明,否则所有随机性均使用均匀分布。

轨道生成:

  • 轨道是一个矩形网格,X = 53单元宽,Y = 15单元高。与细胞X≥49目标细胞(其中,X是从零开始)。
  • 每个单元格只有一种颜色,并且可能是致命的,也可能不是致命的 -除非由以下一种单元格类型指定,否则这些单元格不是致命的。
  • 16种不同的单元格颜色,从标记015,其含义将因游戏而异。另外,-1表示超出范围的细胞-这些是致命的
  • 选择8种随机颜色。这些将是空单元格(无效)。
  • 再选择4种随机颜色。这些是传送器。对于其中两种颜色,请在9x9邻域中选择一个非零偏移量(从(-4,-4)到(4,4),除了(0,0)以外)。对于其他两种颜色,请反转这些偏移量。如果样本踩在传送器上,它将立即移动该偏移量。
  • 再选择2种随机颜色。这些是陷阱。对于每种颜色,在3x3邻域中选择一个偏移量(从(-1,-1)到(1,1))。陷阱表示该偏移量处的单元格是致命的注意:陷阱单元本身不一定具有致命性。
  • 剩下2种颜色是墙壁,阻碍运动。尝试移动到墙单元上将使移动变得静止。壁细胞本身具有致命性
  • 对于网格的每个非目标单元,选择一种随机颜色。为每个目标单元选择一个随机的色。
  • 对于轨道左边缘的每个像元,确定是否可以在100转内达到目标(根据下面的转弯顺序规则)。如果是这样,则此单元格是允许的起始单元格。如果起始单元少于10个,则丢弃轨道并生成一个新轨道。
  • 创建15个样本,每个样本具有随机的基因组,年龄为0。将每个标本放在随机的起始细胞上。

转订单:

  1. 对于每个样本,将依次执行以下步骤。标本不会相互作用或看不见,可能会占据同一单元格。
    1. 如果标本的年龄为100岁,则会死亡。否则,将其年龄增加1。
    2. 给标本以其视野-以标本为中心的5x5颜色网格-并在其3x3邻域中返回移动。超出此范围将导致控制器终止。
    3. 如果目标单元是墙,则移动更改为(0,0)。
    4. 如果目标单元是传送器,则样本会按传送器的偏移量移动。注意:此步骤执行一次,而不是迭代执行。
    5. 如果当前被标本占据的细胞(可能是在使用一个传送器之后)是致命的,则标本会死亡。这是样品死亡的唯一时间(除了上述步骤1.1。)。特别是,在致死细胞上产生的新标本不会立即死亡,而是有机会先移出危险细胞。
    6. 如果标本占据目标格,则得分,将标本移至随机起始格,并将其年龄重置为0。
  2. 如果板上剩下的样本少于两个,则游戏结束。
  3. 创建10个年龄为0的新标本。每个基因组(分别)由以下育种规则确定。将每个标本放在随机的起始细胞上。

配种:

  • 创建新标本时,随机选择两个不同的亲本,偏向于向右进一步发展的标本。选择标本的概率与其当前的适应度得分成正比。标本的健身得分为

    1 + x + 50 *达到目标的次数

    其中x是从0开始的水平索引。同一回合中创建的标本不能选择为父本。

  • 在两个亲本中,选择一个随机的一个作为第一个基因组位。

  • 现在,当您沿着基因组行走时,以0.05的概率切换亲本,并继续从所得亲本中获取位。
  • 突变完全组装的基因组:对于每个位,以0.01的概率翻转。

得分:

  • 一局游戏持续10,000回合。
  • 玩家以1分开始游戏(允许使用几何平均值)。
  • 每当标本达到目标时,玩家就会得分。
  • 目前,每个玩家的提交将运行50场比赛,每场比赛都有不同的随机轨迹。
  • 上述方法导致比期望更多的变化。一旦挑战消失,将宣布截止日期。在截止日期结束时,将随机选择100个委员会,所有提交的意见将在这100个委员会中重新评分。
  • 玩家的总得分是这些单个游戏得分的几何平均值

控制器

您可以选择以下任何控制器(因为它们在功能上是等效的)。我们已经测试了所有这些,但是如果您发现错误,想要提高代码或性能或添加图形输出等功能,请在GitHub上发送引发问题或发送拉动请求!也欢迎您添加其他语言的新控制器!

单击每个控制器的语言名称,以转到GitHub上的正确目录,其中包含README.md带有正确用法说明的。

如果您不熟悉git和/或GitHub,则可以从首页以ZIP格式下载整个存储库(请参见侧栏中的按钮)。

蟒蛇

  • 经过最彻底的测试。这是我们的参考实现。
  • 可与Python 2.6+和Python 3.2+一起使用!
  • 非常慢 我们建议与PyPy一起运行以大幅提高速度。
  • 支持使用pygame或进行图形输出tkinter

红宝石

  • 已在Ruby 2.0.0上测试。应该与较新的版本一起使用。
  • 它也相当慢,但是Ruby可能会方便地为提交的原型制作原型。

C ++

  • 需要C ++ 11。
  • (可选)支持多线程。
  • 迄今为止最快的控制器。

C#

  • 使用LINQ,因此需要.NET 3.5。
  • 相当慢。

爪哇

  • 并不是特别慢。并不是特别快。

初步排行榜

所有分数均为初步分数。不过,如果出现明显错误或过时,请通知我。我们列出的示例提交供比较,但没有争用。

  Score   | # Games | User               | Language   | Bot           
===================================================================================
2914.13   |   2000  | kuroi neko         | C++        | Hard Believers
1817.05097|   1000  | TheBestOne         | Java       | Running Star
1009.72   |   2000  | kuroi neko         | C++        | Blind faith
 782.18   |   2000  | MT0                | C++        | Cautious Specimens
 428.38   |         | user2487951        | Python     | NeighborsOfNeighbors
 145.35   |   2000  | Wouter ibens       | C++        | Triple Score
 133.2    |         | Anton              | C++        | StarPlayer
 122.92   |         | Dominik Müller     | Python     | SkyWalker
  89.90   |         | aschmack           | C++        | LookAheadPlayer
  74.7    |         | bitpwner           | C++        | ColorFarSeeker
  70.98   |   2000  | Ceribia            | C++        | WallGuesser
  50.35   |         | feersum            | C++        | Run-Bonus Player
  35.85   |         | Zgarb              | C++        | Pathfinder
 (34.45)  |   5000  | Martin Büttner     | <all>      | ColorScorePlayer
   9.77   |         | DenDenDo           | C++        | SlowAndSteady
   3.7    |         | flawr              | Java       | IAmARobotPlayer
   1.9    |         | trichoplax         | Python     | Bishop
   1.04   |   2000  | fluffy             | C++        | Gray-Color Lookahead

学分

这项挑战是一项巨大的协作努力:

  • Nathan Merril:编写了Python和Java控制器。将挑战概念从山丘之王转变为老鼠赛跑。
  • trichoplax:游戏测试。在Python控制器上工作。
  • feersum:编写了C ++控制器。
  • VisualMelon:编写了C#控制器。
  • 马丁·布特纳(MartinBüttner):概念。写了Ruby控制器。游戏测试。在Python控制器上工作。
  • T亚伯拉罕:游戏测试。测试了Python,并检查了C#和C ++控制器。

以上所有用户(可能还有更多我忘记了的用户)都为挑战的总体设计做出了贡献。

C ++控制器更新

如果将C ++与Visual Studio和多线程一起使用,则应获得最新更新,因为它们的随机数生成器种子存在错误,该错误允许生成重复的电路板。


3
有人不能仅仅通过遗传遗传算法找到针对该问题的最佳遗传算法吗?
mbomb007

1
@ anon3202好吧,这当然会为您提供有关轨道布局的更多信息,因为您可以确定自己的位置。本质上,我们希望使机器人程序的界面保持简单,并使其成为一个纯粹的局部问题,您将需要基因组来了解哪种局部解决方案最有利于您的全球发展。
马丁·恩德

1
@matovitch请参阅Gory Details(完整规格)的Turn order部分的第5 部分:'In particular, a new specimen which spawns on a lethal cell will not die immediately, but has a chance to move off the dangerous cell first.'
trichoplax

1
我调整了C ++代码以显示样本均值,stddev,stderr和99%conf-interval(在“几何”日志/ exp之前),并做出了惊人的发现。“盲信”答案为“在运行50次后,其样本均值为116529 +-2.78337e + 010(99%)stddev = 7.77951e + 010”。将置信区间降至50%并不会明显改善问题。几何平均值更稳定:“平均值159.458 +-117262(99%)stddev = 32.6237”(在更新他的800得分之前)
Mooing Duck 2015年

1
我做了一些关于突变率的实验,我认为,如果将概率从.01提高到.0227,那么挑战将更加有趣(并且控制器运行起来会更快),这使得DNA穿过的可能性只有10%突变保持不变,而不是当前值的37%。这避免了可笑的种群爆炸(从而节省了大量计算时间),并防止了由于多样性不足而导致的大量故障。个人得分较低,但由于更多的比赛产生了赢家,因此全球平均水平趋于上升。

Answers:


37

盲目信仰-C ++-在2000次运行中得分超过800(!)

对基因组进行彩色编码,具有神秘的轨迹反馈和有效的威慑力

#include "./gamelogic.cpp"

#define NUM_COLORS 16

// color meanings for our rats
typedef enum { good, bad, trap } colorType_t;
struct colorInfo_t {
    colorType_t type;
    coord_t offset; // trap relative location
    colorInfo_t() : type(good) {} // our rats are born optimists
};

// all 8 possible neighbours, carefully ordered
coord_t moves_up  [] = { { 1, 0 }, { 1,  1 }, { 1, -1 }, { 0,  1 }, { 0, -1 }, { -1, 0 }, { -1,  1 }, { -1, -1 } };  // toward the goal, going up   first
coord_t moves_down[] = { { 1, 0 }, { 1, -1 }, { 1,  1 }, { 0, -1 }, { 0,  1 }, { -1, 0 }, { -1, -1 }, { -1,  1 } };  // toward the goal, going down first

// map of the surroundings
struct map_t {
    static const size_t size = 5;
    static const int max = size / 2;
    static const int min = -max;
    colorType_t map[size*size];
    colorType_t & operator() (int x, int y) { return map[(x + max)*size + y + max]; }
    colorType_t & operator() (coord_t pos) { return operator()(pos.x, pos.y); }
    bool is_inside(int x, int y) { return abs(x) <= max && abs(y) <= max; }
    bool is_inside(coord_t pos) { return is_inside(pos.x,pos.y); }
};

// trap mapping info
struct trap_t {
    coord_t detector;
    colorInfo_t color;
    trap_t(int x, int y, colorInfo_t & color) : color(color) { detector.x = x; detector.y = y; }
    trap_t() {}
};

coord_t blindFaith(dna_t d, view_t v)
{
    colorInfo_t color[NUM_COLORS]; // color informations

    // decode colors
    for (size_t c = 0; c != 16; c++)
    {
        size_t base = c * 4;
        if (d[base])
        {
            color[c].type = d[base+1] ? good : bad;
        }
        else // decode trap location
        {
            color[c].type = trap;
            int offset = d[base+1] + 2 * d[base+2] + 4 * d[base+3];
            color[c].offset = moves_up[offset]; // the order is irrelevant as long as all 8 neighbours are listed
        }
    }

    // build a map of the surrounding cells
    map_t map;
    unsigned signature = 0;
    int i = 0;
    for (int x = map.min; x <= map.max; x++)
    for (int y = map.min; y <= map.max; y++)
    {
        int c = v(x, y);
        map(x, y) = (c == -1) ? bad : color[c].type;
        if (c != -1) signature ^= v(x, y) << ((i++) % 28);
    }

    // map traps
    for (int x = map.min; x <= map.max; x++)
    for (int y = map.min; y <= map.max; y++)
    {
        if (map(x, y) != trap) continue;
        const colorInfo_t & trap = color[v(x, y)];
        int bad_x = x + trap.offset.x;
        int bad_y = y + trap.offset.y;
        if (!map.is_inside(bad_x, bad_y)) continue;
        map(bad_x, bad_y) = bad;
        map(x, y) = good;
    }

    // pick a vertical direction according to surroundings signature
    int go_up = d[64 + signature % (DNA_BITS - 64)];

    // try to move to a good cell nearer the goal
    for (const coord_t &move : go_up ? moves_up : moves_down) if (map(move.x, move.y) == good) return move;

    // try not to increase fitness of this intellectually impaired specimen
    return{ -1, 0 };
}

int main() {
    time_t start = time(NULL);
    double score = runsimulation(blindFaith);
    slog << "Geometric mean score: " << score << " in " << time(NULL) - start << " seconds";
}

样本结果:

Scores: 15 4113306 190703 1 1 44629 118172 43594 63023 2 4 1 1 205027 1 455951 4194047 1 5 279 1 3863570 616483 17797 42584 1 37442 1 37 1 432545 5 94335 1 1 187036 1 4233379 1561445 1 1 1 1 35246 1 150154 1 1 1 1 90141 6 1 1 1 26849 1 161903 4 123972 1 55 988 7042063 694 4711342 90514 3726251 2 1 383389 1 593029 12088 1 149779 69144 21218 290963 17829 1072904 368771 84 872958 30456 133784 4843896 1 2 37 381780 14 540066 3046713 12 5 1 92181 5174 1 156292 13 1 1 29940 66678 125975 52714 1 5 3 1 101267 69003 1 1 10231 143110 282328 4 71750 324545 25 1 22 102414 1 3884626 4 28202 64057 1 1 1 1 70707 4078970 1623071 5047 1 1 549040 1 1 66 3520283 1 6035495 1 79773 1 1 1 218408 1 1 15 33 589875 310455 112274 1 1 4 1 3716220 14 180123 1 2 12785 113116 12 2 1 59286 822912 2244520 1840950 147151 1255115 1 49 2 182262 109717 2 9 1049697 59297 1 11 64568 1 57093 52588 63990 331081 54110 1 1 1537 3 38043 1514692 360087 1 260395 19557 3583536 1 4 152302 2636569 12 1 105991 374793 14 3934727 1 2 182614 1 1675472 121949 11 5 283271 207686 175468 1 1 173240 1 138778 1 1 59964 3290382 1 4 1757946 1 23520 1 2 94 1 124577 497071 1749760 39238 1 301144 3 1 2871836 1 1 10486 1 11 8 1 111421 11 1807900 1 587479 1 42725 116006 3 1 6 5441895 1 1 22 52465 952 1 18 1 1 46878 2 1 1 1994 4 593858 123513 4692516 820868 4247357 1 1 2 1 2 8770 2 1 95371 4897243 2 22741 1 1 1 1 325142 6 33650 4 51 102993 1 182664 1 4040608 18153 2045673 462339 1 1 617575 2 2551800 3 7760 1 108012 76167 143362 1148457 1 53460 1 71503 1 1 1 1 81482 3208 62286 69 139 1 3503941 1 253624 101903 3081954 80123 84701 9 16 1 1070688 71604 613064 2076 15009 9 1 1 1 199731 1 2 1 63132 1 1843855 27808 1 3569689 273144 1 460524 2703719 22443 10876 51242 1 6972678 4591939 1 140506 43981 45076 2 1 91301 5 1 1874615 1758284 608 13 1 96545 75161 1 618144 4 2056133 1 1 2 57401 1394307 6 188116 83545 1 41883 1 1 467189 371722 1 1122993 1 17912 159499 1 5 3355398 33 1 2 246304 1 2 168349 1 50292 12 141492 2723076 3 1 6 3060433 223360 171472 106409 1 2 1 102729 8814 1 285154 1 11 1 65 930 2 689644 3271116 1 5 4 60 77447 1 1 1477538 256023 100403 2480335 1 39888 1 1 70052 66090 1 250 1 2 8 115371 1523106 1424 168148 1 1 1 42938 17 1 364285 185080 1 1 36 4903764 13 51987 1106 276212 67460 1 251257 2 6867732 1 1 1890073 1 1 8 5 2118932 210 0 3792346 5209168 1 1 1 1 51 1 4621148 1 37 337073 3506096 1 1 1 1 458964 2 16 52930 1 15375 267685 1 1 1259646 14930 3248678 527105 1 103 24 1 3252685 6009 1 1 176340 3971529 121 1722808 1 31483 194232 2314706 95952 3625407 3 216755 56 1 8 1 1 1 1 885 229 9056 172027 31516 2526805 1 76076 1589061 1 1 8 90812 1 21 72036 1681271 2 212431 1581814 85993 79967 4 7 514708 1070070 1 71698 1 23478 15882 94453 1 27382 495493 277308 12127 91928 248593 1 1 1 26540 1709344 2119856 1 1 48867 107017 251374 64041 15924 15 87474 8 1 23 9 48 1 1 1 51793 2 61029 84803 15 689851 1 1 873503 10 140084 420034 87087 82223 1 163273 12 1 5 570463 19 26665 1 170311 1 39983 1 475306 1 2 36417 746105 11 141345 1 3 1 30 3 1 1 1 1 1312289 408117 1 42210 273871 561592 1 1 1 1 4448568 48448 7 378508 1 351858 278331 1 79515 1169309 3670107 14711 4686395 1156554 33 2528441 24537 76 335390 63545 122108 76675 21929 34 1 861361 83000 417781 1 90487 1 1 85116 7 2 1 60129 647991 79 1 2755780 726845 244217 50007 187212 1 3674051 286071 44068 3 307427 26973 1 26059 1957457 230783 58102 545318 1 4 172542 168365 1 89402 1 4 1 1 1 1 2 3 16 62935 5643183 117961 109942 85762 5 117376 118883 1 61 23893 122536 70185 1 64252 208409 179269 55381 1579240 3434491 1 4964284 3356245 3 21 2197119 346542 44340 59976 772220 5590844 199721 90858 63785 125989 57219 129737 81836 1 3671 16810 1 4151040 1 15 40108 1 443679 3224921 2 27498 2 3 146529 169409 19 1 1 1 1 41627 1 3 2722438 1 2013730 1 1649406 1 1 6943 125772 58652 1 1 1 2413522 1 2 48 36067 253807 2 146464 1 248 07 3359223 139896 395985 65241 43988 594638 69033 275085 1 17973 1 1 1 594835 1 1 4468341 3496274 222854 94769 55 161056 36185 8793 277592 3 1 6746 1 138151 66 37365 1 2729315 1 3 57091 22408 249875 246514 85058 1 20 5463152 1 3 1 45293 1 70488 2792458 461 441 951926 2236205 2 171980 1 1 48 3893009 1 458077 1 268203 1 70005 7 19299 1 278978 1 45286 26 2 1883506 274393 342679 1 1 913722 911600 12688 1 1 115020 1249307 1529878 53426 1 226862 3721440 23537 86033 397433 1 1 1 161423 96343 94496 1 1 1 2 1 111576 1 4039782 1 1 1 5742393 3569 46072 1 1 2 1 1 85335 219988 1 78871 115876 43405 1 300835 1 166684 53134 1 3 111487 6 3 3 77 1 115971 3 205782 10 1932578 356857 43258 47998 1 27648 127096 573939 32650 523906 45193 1 2 128992 1 10144 1 257941 1 19841 5077836 14670 5 3 6 1 1 21 14651 2906084 37942 45032 9 304192 3035905 6214026 2 177952 1 51338 1 65594 46426 553875 2676479 245774 95881 3 216364 3064811 1198509 223982 3 6 1 533254 1 590363 264940 68346 127284 1 7 1 1 4617874 5 45400 1 1 3097950 360274 1 3 1 8421 14 469681 418563 3 1 6 1 1 575766 405239 11 2631108 152667 1 1 1 467383 1 1 775499 1 157998 2 1 143351 92021 1 1 1173046 3636579 1 70635 162303 1 1534876 834682 2 1 1 11981 346908 245124 607794 17 1570641 126995 13 57050 1 2 33731 29739 1 1 35460 1 33716 168190 214704 1 443156 701674 2636870 108081 1604895 1 1 11 115901 23 571891 360680 1 1 35 1 2036975 1 1 2555536 4742615 5 360553 287044 1 1814255 7 59632 1 216 41546 1 540920 353424 2625301 223744 1 1 1 15717 3 429871 1 4 2329632 18 11 1 2 4 1 3905 5 1 1 1 2 5431442 1 859628 1 3 338378 15236 13764 1 3384362 1 15 65293 24 619599 152620 2 189921 35854 16647 7 2 404790 360096 1 2 189459 1097768 191610 1 1 470254 1 12 2 330299 364219 2365542 312023 2273374 2 10527 1 115453 1 2 3845592 52388 913449 1 14695 1 44 37352 90302 1 1 1 233577 51639 3474983 44010 1650727 31 2 2 1 8 7 1 3 5 25603 17799 45630 758457 1 4571839 37 4 3 2 1 1 1351271 196673 12 2880765 263886 2926173 1 2 1 241502 5 6 1 278576 9 7 290722 42749 143391 82753 21771 57887 1 1 60400 1766903 1 296392 1 5 2861787 125560 1 9 199218 1 1 308226 517598 2246753 12 1168981 3 98447 1 488613 9 842865 202108 10 1 238493 1 1523706 5383982 29435 1 1 207071 1 8 4 125742 70531 253135 72207 124291 23364 184376 2 40034 9569353 194109 102854 2 3247153 58313 85995 1 598 63 1 2676692 10 3573233 1 36651 118016 2486962 65456 46760 1 5813 723 178120 2 153305 1 1 2 1 2354413 3 1 17126 132953 437123 299778 3070490 1 6490 403704 2261 511439 1 39 33410 173045 1 1 120970 641346 132042 1 44906 1 33940 132124 467702 45472 9 44 1 1 1 107008 1 46635 1 121431 130760 1 7 3 1 56251 1299306 3 1 1 1 15 2147678 215169 1374943 1 332995 231089 269310 1 7816944 1 1 1 46 134426 1 1 1 2 76112 1 1 30438 299927 25 139373 76048 278757 71 3474997 1 294046 1 3126554 2518019 2 1 6 1 3054393 1 1 1 2 525 96 419528 1 1 154718 233 207879 26 1 6 57436 3 5944942 1 1 318198 147536 1 22 420557 1 1 120938 1 1 167412 4082969 73299 1 11 3557361 1 4 330028 269051 1 2569546 2 1 1 4 1 1 377412 1 1 1 213800 58131 1422177 54 109617 117751 12432 3830664 419046 3 6821 741 919 1 22335 1 1 15069 80694 488809 2389 2308679 145548 51411 115786 110984 107713 1 12 6 1 5 8365 1 2001874 210250 4674015 14 1 1204101 314354 89066 1 1 2438200 68350 1 1575329 5593838 2743787 151670 57 16 5948210 597158 128060 189160 23628 1 1 15 4171774 1 8206 4157492 1 2 315607 1618680 24736 18520 4787225 33842 134431 1 1 1 1 1 1115809 17759 1 33016 123117 1 77322 169633 219091 1 321593 57231 135536 175401 4 1 435702 1 253132 100707 114547 1 119324 6382967 1472898 3 72567 1707408 177958 26 208719 1 27083 74 12 576410 19375 177069 4 3 1 31 507048 2 1 1 2 1 2 1 40 7 99892 95202 60649 241396 232370 1 136579 70649 1 2877 280695 13603 102860 404583 29717 112769 1 54089 1 97579 40819 2 868629 64848 2 63432 5 1 1888426 99623 2 1 7911 53646 3047637 1 2 3 152910 1 3244662 105187 1 1 1 1 8966 200347 1 1 22 302654 6 17 1 10 328150 55259 1016 117291 2 1 224524 23846 74645 1 1 1 1 1 3117394 10847 33976 144613 4 201584 1 1 26959 3 4410588 27019 6 66749 55935 23 4126812 4089989 99959 1 1 1 1 55490 1 4275599 13652 33967 2 8126062 337093 320653 128015 4 1 7729132 1 10594 116651 20990 3046630 1 353731 132989 2066431 4 80 15575 147430 1 621461 3100943 2306122 5 33439 407945 25634 1 2911806 32511 2174235 298281 15159 54125 1 2 3063577 2205013 1 407984 1 319713 1 22171 1 2763843 1 2607606 1 100015 3096036 1 55905 1 1 635265 2890760 1 1 1 1 35854 1 352022 2652014 1 2 274366 1 4 1 602980 4 83828 602270 2816 2 59116 25340 1 11 1 5162051 34 8 218372 1186732 142966 1 1 170557 503302 1 84924 5 1 1350329 1 1 1 130273 78055 902762 1 8581 5 1 3635882 1 1 1 224255 44044 61250 2 438453 8 1 2729357 28 1 17658 82640 1 31809 10 1 33 1 1 45495 5798 5000217 40018 588787 67269 1 12 83512 2798339 1 609271 1 3 1 7 67912 189808 3388775 60961 81311 1167 24939 433791 405306 85934 1 1170651 2 1 66 552579 122985 515363 2188340 1 1 1 3807012 1502582 4 13 149593 1 1 2108196 3 34279 24613 1282047 27 1 2 1 1 584435 27487 1 1 5 33278 1 1 1202843 1 1 1 6 3649820 3100 2 266150 13 164117 10 53163 3295075 1 1 1 1 77890 1 286220 90823 18866 3139039 481826 1 3994676 23 116901 132290 6 3927 84948 1 1 1 1 256310 1 11 8 1 102002 8392 887732 98483 444991 1 1 49408 409967 1158979 1 1 1 81469 189764 3960930 296231 64258 1 1 176030 4 1 2 1 486856 1 1135146 31 2 13112 227077 31
Geometric mean score: 831.185 in 14820 seconds

根据feersum自愿进行的长时间测试,我认为2000次运行足以产生可接受的稳定结果。
由于修改后的控制器在每次运行后都会显示当前的几何平均值,因此我通过视觉确认了最近50次运行的变化相对较小(+/- 10点)。

是什么让这些小动物tick

我没有为每种颜色赋予相同的优先级,而是考虑了以下可能的值:

  1. ->老鼠认为它可以安全地进入那里
  2. 不好 ->老鼠不会去那里
  3. 陷阱 ->大鼠会考虑陷阱的位置不好,表示陷阱的细胞良好
    尽管我懒得将其重命名,但它是一个“危险检测器”,指示实际陷阱的位置(假定),墙壁,传送器,等待将毫无戒心的流浪者送到不愉快的地方,甚至是死者的入口。 -结束。简而言之,是一个明智的老鼠宁愿不去的地方。

好的或坏的基因只需要2位来存储(例如1110),但是陷阱需要4位(0ttt其中ttt代表8个“危险”位置之一)。

为了保持每个基因的一致性(即,将其混合到一个完全不同的基因组后仍保持其含义,这要求每个颜色编码基因都位于固定的位置),所有值都编码在4位上(编码为11xx编码为10xx),总共16 * 4 = 64位。

其余的36位用作“防撞墙”(稍后会详细介绍)。25种周围的颜色将散列到这36位的索引中。每一位表示一个优选的垂直方向(上或下),在两个单元之间可能进行选择时使用。

该策略如下:

  • 根据基因组对每种颜色进行解码(或对偏离轨道的“坏”细胞进行直接控制器报告)
  • 绘制周围环境的地图(3x3单元,可能有8个邻居)
  • 计算周围环境的特征(25种颜色的散列(偏离轨道的单元除外))
  • 从签名中选择一个首选的垂直方向(在36个哈希桶中)
  • 尝试移动到提示为“好”的邻居,从最接近目标的目标开始,然后首先沿首选垂直方向前进
  • 如果找不到“好”邻居,请尝试向后移动一个牢房(因此可能是不幸事故的受害者,并避免以任何方式增加健康状况)

啮齿动物,看看你这种敌人

the dreaded wall teleporting loop

种群可能发生的最糟糕的事情是尚未产生任何获胜者,但是许多老鼠要么贴在墙上,要么贴在无限接近目标的无限传送环内,从而有机会被选中进行繁殖
与老鼠被困在陷阱中或被传送到墙壁中相反,这些啮齿动物只会在年老时被杀死。
从一开始,它们就没有表亲卡住了3个细胞的竞争优势,但是他们将有足够的时间繁殖克汀素,直到它们的基因组成为优势基因为止,从而无缘无故地严重损害了遗传多样性。

为了减轻这种现象,我们的想法是让这些坏老鼠的后代更有可能避免跟随其祖先的脚步。
垂直方向指示仅1位长(通常说“尝试在这些环境中先上升或下降”),并且相当多的位可能会影响所遵循的路径,因此突变和/或交叉点应具有显着影响。
许多后代的行为会有所不同,并且最终不会将头撞在同一堵墙上(在挨饿的祖先的尸体中)。
这里的亚妙之处在于,这种迹象并不是大鼠行为的主要因素。在大多数情况下,颜色解释仍将占上风(向上/向下选择仅在确实存在两个“好”的情况下才重要正是大鼠视为一个无害的颜色没有等待,扔在墙上的传送点)。

为什么它(似乎)起作用?

我仍然不知道为什么。

陷阱映射逻辑是仍然未解之谜的绝对运气。毫无疑问,这是成功的基石,但它以其自己的神秘方式起作用。

使用编码后,随机基因组将产生25%的“好”,25%的“差”和50%的“陷印”颜色标识符。
“陷阱”标识符将依次产生与5x5周围环境相关的“好”和“坏”估计。
结果,在给定位置的老鼠会将“世界”视为稳定的和上下文的“执行/不执行”颜色的混合。

正如非常成功的防撞机制似乎表明的那样,轨道上最糟糕的一种元素是可怕的墙(及其在传送环中的表亲,但我想它们很少见)。

结论是,一个成功的程序首先必须设法让老鼠能够检测出导致缓慢饥饿而又未达到目标的位置。

即使没有“猜测”代表墙壁的两种颜色,“陷井”颜色似乎也可以通过允许老鼠绕过一些障碍来帮助避开墙壁,这不是因为它“看见”了墙壁,而是因为“陷井”的估计排除了这些障碍。在这些特定环境中的特定壁单元。

即使老鼠试图朝目标移动(这可能导致认为最“有用的”陷阱指示符是指示前方有危险的指示标),但我认为所有陷阱方向都具有大致相同的影响:指示“背后存在危险的陷阱”位于大鼠前面2个单元格的影响与当大鼠站在其顶部时表示“前方危险”的影响相同。

不幸的是,为什么这种混合具有使基因组如此成功融合的特性,这远远超出了我的数学范围。

我对壁垒式的威慑感到更自在。这只是按计划进行,但大大超出了我的期望(分数基本上乘以四)。

我重击了控制器以显示一些数据。这是几个运行:

Turns:2499 best rat B  B  B  G  B  G  T3 G  T4 B  G  B  B  B  G  G  ^vv^^vv^v^v^^^vvv^v^^^v^^^v^vv^^v^^^ Max fitness: 790 Specimens: 1217 Score: 2800
Turns:4999 best rat B  B  B  G  B  G  T3 G  T4 B  G  B  B  B  G  G  ^vv^^vv^v^v^^^vvv^v^^^v^^^v^vv^^v^^^ Max fitness: 5217 Specimens: 15857 Score: 685986
Turns:7499 best rat B  B  B  G  B  G  T3 G  T4 B  G  B  B  B  G  G  ^vv^^vv^v^v^^^vvv^v^^^vvvvv^^v^v^^^^ Max fitness: 9785 Specimens: 31053 Score: 2695045
Turns:9999 best rat B  B  B  G  B  G  T3 G  T4 B  G  B  B  B  G  G  ^vv^^vv^v^v^^^vvv^v^^^vvvvv^^v^v^^^^ Max fitness: 14377 Specimens: 46384 Score: 6033904
Scored 6035495 in game 146 current mean 466.875

在这里,一种超级大鼠出现得很早(这条赛道很可能是一条直线,第一代的一些幸运鼠就拥有利用它的正确DNA)。最后的标本数量大约是大约100.000只大鼠的理论最大值的一半,这意味着将近一半的小动物获得了无限期地生存在该特定轨道上的能力(!)。
当然,结果分数只是令人讨厌-顺便说一下,计算时间也是如此。

Turns:2499 best rat B  T0 G  B  T7 B  G  B  T6 T0 T3 B  G  G  G  T4 ^v^^^^^v^^v^v^^^^^^^^v^v^v^^vvv^v^^^ Max fitness: 18 Specimens: 772 Score: 1
Turns:4999 best rat T7 G  G  G  G  T7 G  B  T6 T0 T3 T5 G  G  B  T4 ^vvvvvvv^^^vvv^^v^v^^^^^^^^^^^^^v^^^ Max fitness: 26 Specimens: 856 Score: 1
Turns:7499 best rat G  T0 G  T3 G  T0 G  B  T6 T0 T2 B  T4 G  B  T4 ^^v^vvv^^^vv^^v^vvv^v^^vvvv^^^^^^^^^ Max fitness: 55 Specimens: 836 Score: 5
Turns:9999 best rat T6 T0 G  T5 B  T1 G  B  T6 T0 T3 B  T4 G  B  T4 ^^vv^^^^vv^^v^v^^v^^vvv^vv^vvv^^v^^v Max fitness: 590 Specimens: 1223 Score: 10478
Scored 10486 in game 258 current mean 628.564

在这里,我们可以看到工作中的基因组细化。最后两个基因组之间的谱系清晰可见。在坏的评价是最显著。该陷阱迹象似乎振荡,直到他们要么稳定到一个“有用” 的陷阱或变异成

颜色基因似乎具有一些有用的特征:

  • 它们具有独立的含义
    (一种特定的颜色必须以一种特定的方式进行处理)
    每种颜色编码都可以扔到一个完全不同的基因组中,而无需显着改变其行为-除非该颜色实际上是一种决定性的颜色(通常是这种颜色)导致无限循环的墙壁或传送器)。
    对于基本优先级编码,情况就更少了,因为最优先的颜色是用于决定移动位置的唯一信息。在这里,所有“好”颜色都是相等的,因此添加到“好”列表中的给定颜色影响较小。
  • 它们对突变具有相对的抵抗力,
    好的/不好的编码只有4个有效位中的2个有效位,并且陷阱位置在大多数时间都可能会更改,而不会显着改变大鼠的行为。
  • 它们很小(4位),所以被分频器破坏的可能性非常低。
  • 突变产生无害的有意义的改变
    突变为“好”的基因要么影响很小(例如,如果它对应于一个空细胞,它可能允许寻找一条新的,更短的路径,但这也可能导致大鼠直接进入一个陷阱)或一个戏剧性的陷阱(如果颜色代表一堵墙,那只新老鼠很可能会卡在某个地方)。
    翻转为“捕获”的基因将使大鼠失去必需的颜色,或者没有明显的作用。
    陷阱位置的突变只有在确实存在一个陷阱(或任何有害的东西)的情况下才有意义,该可能性相对较小(我会说类似1/3)。

最后,我想最后36位不仅有助于避免老鼠卡住,而且有助于在轨道上更均匀地扩散老鼠,从而保留了遗传多样性,直到获胜的基因组出现并通过颜色编码部分成为主导。

进一步的工作

我必须说,我发现这些小动物令人着迷。
再次感谢所有为这一出色挑战做出贡献的人。

我正在考虑进一步屠宰控制器以显示更重要的数据,例如成功老鼠的祖先。

我也非常想看到这些老鼠的行为,但是这种C ++语言使创建(更不用说动画)图像变得杂乱无章了。

最后,我想至少对陷阱系统进行解释,并可能对其进行改进。

控制器骇客

如果有人感兴趣,我可以发布对控制器所做的修改。
他们很脏又便宜,但是他们能干。

我对GitHub并不精通,因此只需要写一篇文章。


16
拥有10,000场比赛的得分为208.14。我试图对其进行1000次测试,但我从未意识到我键入了一个额外的0,所以它花了7个小时以上。
feersum

大声笑谢谢你。与我的两次1000次运行相比,大约2000次运行可能会产生稳定的结果。

你的意思是什么^^v^vvv^^^vv^^v^vvv^v^^vvvv^^^^^^^^^?其余的我都可以猜到,但是我有点麻烦了?
Mooing Duck

我当时正在考虑制作一个单独的“调试”控制器,该控制器一次运行一只老鼠,每次生成一只新老鼠时,它都会显示父母和孩子的DNA(通过一些可自定义的功能)。这将使检查老鼠的工作方式变得容易得多。
Mooing Duck

2
代表36个“向上/向下”指示位,但是在这些示例中,获胜的DNA已经占据主导地位,因此它们的差异不大。

18

坚定的信徒-C ++-(改进的传送器):2000运行时10.000+

(这是盲目的信仰的演变,因此您可能希望在此之前攀登另一堵文字墙)

#ifndef NDEBUG
#define NDEBUG
#include "./gamelogic.cpp"
#endif // NDEBUG
#include <cassert>

#define NUM_COLORS 16
#define BITS_OFFSET  3
#define BITS_TYPE    2
#define BITS_SUBTYPE 2
#define BITS_COLOR (BITS_TYPE+BITS_OFFSET)

// how our rats see the world
typedef unsigned char enumSupport_t;
typedef unsigned char trapOffset_t;
typedef enum : enumSupport_t {
    danger,   // code      trap detector
    beam,     // code      safe teleporter
    empty,    // code      empty
    block,    // code      wall, pit or teleporter
    trap,     // computed  detected trap
    pit,      // read      off-board cell
} colorType_t;

// color type encoding (4 first bits of a color gene)
// the order is critical. A single block/empty inversion can cost 2000 points or more
const colorType_t type_decoder[16] = {
    /*00xx-*/
    danger,
    empty,
    beam,
    block,
    /*01xx-*/
    beam,
    danger,
    empty,
    block,
    /*10xx-*/
    empty,
    beam,
    block,
    danger,
    /*11xx-*/
    block,
    empty,
    danger,
    beam,
};

// all 8 possible neighbours, carefully ordered
typedef coord_t neighborhood_t[8];
neighborhood_t moves_up =   { { 1, 0 }, { 1,  1 }, { 1, -1 }, { 0,  1 }, { 0, -1 }, { -1, 0 }, { -1,  1 }, { -1, -1 } };  // toward the goal, going up   first
neighborhood_t moves_down = { { 1, 0 }, { 1, -1 }, { 1,  1 }, { 0, -1 }, { 0,  1 }, { -1, 0 }, { -1, -1 }, { -1,  1 } };  // toward the goal, going down first

// using C++ as a macro-assembler to speedup DNA reading
/*
Would work like a charm *if* a well-paid scatterbrain at Microsoft had not defined
std::bitset::operator[] as

bool operator[](size_t _Pos) const
{   // subscript nonmutable sequence
return (test(_Pos));
}

Bounds checking on operator[] violates the spec and defeats the optimization.
Not only does it an unwanted check; it also prevents inlining and thus generates
two levels of function calls where none are necessary.
The fix is trivial, but how long will it take for Microsoft to implement it, if
the bug ever makes it through their thick layer of tech support bullshit artists?
Just one of the many reasons why STL appears not to live up to the dreams of
Mr Stroustrup & friends...
*/
template<size_t BITS> int DNA_read(dna_t dna, size_t base)
{
    const size_t offset = BITS - 1;
    return (dna[base + offset] << offset) | DNA_read<offset>(dna, base);
}
template<> int DNA_read<0>(dna_t, size_t) { return 0; }

// color gene
struct colorGene_t {
    colorType_t  type;
    trapOffset_t offset;  // trap relative location
    colorGene_t() : type(empty) {} // our rats are born optimists
};

// decoded DNA
class dnaInfo_t {
private:
    const dna_t & dna;
    static const size_t
        direction_start = NUM_COLORS*(BITS_TYPE + BITS_OFFSET),
        direction_size = DNA_BITS - direction_start;

public:
    colorGene_t color[NUM_COLORS];
    int         up_down; // anti-wall-banger

    // decode constant informations during construction
    dnaInfo_t(const dna_t & d) : dna(d)
    {
        for (size_t c = 0; c != NUM_COLORS; c++)
        {
            unsigned raw = DNA_read<BITS_COLOR>(d, c * BITS_COLOR);
            color[c].type = type_decoder[raw >> 1];
            if      (color[c].type == danger) color[c].offset = raw & 7;
            else if (color[c].type == beam  ) color[c].offset = raw & 3;
        }
    }

    // update with surroundings signatures
    void update(size_t signature)
    {
        // anti-blocker
        up_down = (direction_size > 0) ? dna[direction_start + signature % direction_size] : 0;
    }
};

// map of the surroundings
class map_t {
    struct cell_t {
        coord_t pos;
        int     color;
    };

    static const size_t size = 5;
    static const int max = size / 2;
    static const int min = -max;

    size_t local_signature[size*size]; // 8 neighbours signatures for teleporters
    cell_t track_cell[size*size]; // on-track cells
    size_t cell_num;
    colorType_t map[size*size];
    size_t raw_index(int x, int y) { size_t res = x * size + y + max + max * size; assert(res < size*size); return res; }
    size_t raw_index(coord_t pos) { return raw_index(pos.x, pos.y); }

    bool is_inside(int x, int y) { return abs(x) <= max && abs(y) <= max; }

public:
    size_t compute_signatures(view_t v, dnaInfo_t genome)
    {
        cell_num = 0;
        size_t signature = 0;
        memset (local_signature, 0, sizeof(local_signature));
        int i = 0;
        for (int x = min; x <= max; x++)
        for (int y = min; y <= max; y++)
        {
            int c = v(x, y);
            if (c == -1)
            {
                (*this)(x, y) = pit; continue;
            }
            track_cell[cell_num++] = { { x, y }, c };
            signature ^= c << (4 * (i++ & 1));

            if (genome.color[c].type == beam)
            {
                int in = 0;
                for (coord_t n : moves_up)
                {
                    coord_t pn = {x+n.x,y+n.y};
                    if (!is_inside(pn)) continue;
                    int cn = v(pn.x, pn.y);
//                    if (cn == -1) continue;
                    local_signature[raw_index(pn.x,pn.y)] ^= cn << (4 * (in++ & 1));
                }
            }
        }
        return signature;
    }

    void build(dnaInfo_t genome)
    {
        coord_t traps[size*size];
        size_t t_num = 0;

        // plot color meanings
        for (size_t c = 0; c != cell_num; c++)
        {
            const cell_t& cell = track_cell[c];
            const colorGene_t& color = genome.color[cell.color];
            (*this)(cell.pos) = (color.type == beam && (local_signature[raw_index(cell.pos.x,cell.pos.y)] % 4) == color.offset)
                    ? block
                    : color.type;

            // build a list of trap locations
            if (color.type == danger)
            {
                coord_t location = cell.pos + moves_up[color.offset];
                if (is_inside(location)) traps[t_num++] = location;
            }
        }

        // plot trap locations
        while (t_num) (*this)(traps[--t_num]) = trap;
    }

    // quick & dirty pathing
    struct candidate_t {
        coord_t pos;
        candidate_t * parent;
        candidate_t() {} // default constructor does not waste time in initializations
        candidate_t(int) : parent(nullptr) { pos.x = pos.y = 0; } // ...this is ugly...
        candidate_t(coord_t pos, candidate_t * parent) : pos(pos), parent(parent) {} // ...but so much fun...
    };

    coord_t path(const neighborhood_t & moves)
    {
        candidate_t pool[size*size]; // private allocation for express garbage collection...
        size_t alloc;

        candidate_t * border[size*size]; // fixed-size FIFO 
        size_t head, tail;

        std::bitset<size*size>closed;

        // breadth first search. A* would be a huge overkill for 25 cells, and BFS is already slow enough.
        alloc = head = tail = 0;
        closed = 0;
        closed[raw_index(candidate_t(0).pos)] = 1;
        border[tail++] = new (&pool[alloc++]) candidate_t(0);
        while (tail > head)
        {
            candidate_t & candidate = *(border[head++]); // FIFO pop
            for (const coord_t move : moves)
            {
                coord_t new_pos = candidate.pos + move;
                if (is_inside(new_pos))
                {
                    size_t signature = raw_index(new_pos);
                    if (closed[signature]) continue;
                    closed[signature] = 1;
                    if ((*this)(new_pos) > empty) continue;
                    if (new_pos.x == 2) goto found_exit; // a path to some location 2 cells forward
                    assert(alloc < size*size);
                    assert(tail < size*size);
                    border[tail++] = new(&pool[alloc++]) candidate_t(new_pos, &candidate); // allocation & FIFO push
                    continue;
                }
                // a path out of the 5x5 grid, though not 2 cells forward
            found_exit:
                if (candidate.parent == nullptr) return move;
                candidate_t * origin;
                for (origin = &candidate; origin->parent->parent != nullptr; origin = origin->parent) {}
                return origin->pos;
            }
        }

        // no escape
        return moves[1]; // one cell forward, either up or down
    }

    colorType_t & operator() (int x, int y) { return map[raw_index(x, y)]; }
    colorType_t & operator() (coord_t pos) { return operator()(pos.x, pos.y); }
    bool is_inside(coord_t pos) { return is_inside(pos.x, pos.y); }
};

std::string trace_DNA(const dna_t d, bool graphics = false)
{
    std::ostringstream res;
    dnaInfo_t genome(d);
    for (size_t c = 0; c != NUM_COLORS; c++)
    {
        if (graphics)
        {
            res << "tbew--"[genome.color[c].type];
            if (genome.color[c].type == danger) res << ' ' << moves_up[genome.color[c].offset].x << ' ' << moves_up[genome.color[c].offset].y;
            if (genome.color[c].type == beam) res << ' ' << genome.color[c].offset << " 0";
            if (c != NUM_COLORS - 1) res << ',';
        }
        else switch (genome.color[c].type)
        {
        case danger: res << "01234567"[genome.color[c].offset]; break;
        case beam  : res <<     "ABCD"[genome.color[c].offset]; break;
        default: res << "!*-#X@"[genome.color[c].type]; break;
        }
    }
    return res.str();
}

coord_t hardBelievers(dna_t d, view_t v)
{
    dnaInfo_t genome(d); // decoded DNA
    map_t     map;       // the surroundings seen by this particular rodent

    // update genome with local context
    genome.update(map.compute_signatures(v, genome));

    // build a map of the surrounding cells
    map.build(genome);

    // move as far to the right as possible, in the contextually preffered direction
    return map.path(genome.up_down ? moves_up : moves_down);
}

int main() {
    time_t start = time(NULL);
    double score = runsimulation(hardBelievers, trace_DNA);
    slog << "Geometric mean score: " << score << " in " << time(NULL) - start << " seconds";
}

第四集:让我们的网格站起来

结果

Scores: 309371 997080 1488635 1 19 45832 9 94637 2893543 210750 742386 1677242 206614 111809 1 1738598 1 1 342984 2868939 190484 3354458 568267 280796 1 1 1 679704 2858998 1 409584 3823 200724 1 973317 849609 3141119 1 1987305 1 1 57105 245412 1223244 2 1603915 2784761 9 12 1 1839136 1 298951 2 14 138989 501726 1365264 308185 707440 22 772719 17342 63461 3142044 19899 3 409837 48074 3549774 138770 32833 1 1 1184121 67473 310905 1996452 4201 1701954 2799895 2041559 218816 174 433010 51036 1731159 1871641 1 23 2877765 1 127305 27875 626814 142177 2101427 167548 2328741 4 8433 2674119 2990146 466684 1 2 8 83193 388542 2350563 1 1140807 100543 1313548 31949 73117 73300 121364 1899620 1280524 1 10726 12852 7 2165 1 3 44728 2 122725 41 2 1902290 3 1 8581 70598 1148129 429767 1 112335 1931563 521942 3513722 1 2400069 1 3331469 141319 220942 205616 57033 63515 34 6 1419147 1983123 1057929 1 599948 2730727 2438494 5586 268312 1728955 1183258 95241 1537803 11 13 1157309 1750630 1 1 2690947 101211 3463501 1 258589 101615 212924 137664 19624 251591 509429 510302 1878788 1 4045925 1 21598 459159 118663 7 3606309 3 13016 17765 640403 1 72841 695439 1 135297 2380810 1 43 31516 14 1442940 1001957 95903 194951 1 238773 773431 1 1 975692 2 4990979 52016 3261784 2 413095 12 3 420624 7905 60087 760051 2702333 2572405 1 1717432 1 12 3040935 1 1 31787 60114 513777 1 3270813 9639 581868 127091 270 164228 274393 1275008 261419 597715 138913 28923 13059 1848733 2895136 7754 14 1 107592 1 3557771 2067538 147790 112677 119004 1 13791082842974 249727 838699 4067558 6 470799 695141 1 3 1 1276069 23691 831013 5 165142 1236901 1 187522 2599203 1 67179 81345 44111 2909946 94752 7 406018 991024 4 1 3 573689 6 748463 2166290 33865 670769 322844 5657 1131171 1990155 5 4536811 1785704 3226501 2030929 25987 3055355 192547 1761201 433330 27235 2 312244 13203 756723 81459 12 1 1 54142 307858 2 25657 30507 1920292 3945574 1 191775 3748702 3348794 4188197 366019 1540980 3638591 1 1840852 1 26151 2888481 112861 8 11 2 1 27231 1 74 106853 3 173389 2390495 25 1 83116 3238625 75443 1 1 2125260 1 49626 1 6 312084 159735 358268 54351 367201 2868856 5779 172554 119016 141728 3 1 6 9 1 1504011 1 168968 1868493 1 5 1 244563 2 2887999 3144375 1598674 1 1578910 45313 176469 30969 8 127652 1911075 9 1300092 224328 168752 8 1619669 292559 9090 2040459 705819 1852774 10 139217 16 1221670 355060 339599 3 2184244 2546028 1 1 11 70958 242187 1 80737 1 190246 3 1 1 577711 150064 1 1047154 3851461 92399 224270 612237 1 3 3330053 1 1 1192533 615756 267923 144724 2 1 150018 4621881 1 6 299247 115996 2 10 6 185495 76351 465554 178786 1802565 257101 56 2491615 1 24547 1 1203267 32 5741149 541203 11393 1 368082 540534 16167 113481 2004136 13045 17 1 12 333803 14 1955075 1 4 38034 1286203 2382725 26777 1 180312 1 87161 4773392 1244024 1146401 3 80598 2983715 1 63741 1 1 2561436 16 1 1 1807854 1239680 200398 2 46153 1400933 11 5058787 8787 1 98841 89162 1106459 112566 1 4138891 2858906 101835 81375 539485 6587808 1 5359988 1 1 869106 443452 120748 436156 2 2 3944932 1 1875599 2 3081185 733911 447824 1 1 23187 3082414 33 3 1 1 2053904 410824 104571 885952 1946162 2 294773 364169 1 101310 2166548 1177524 2192461 12 4 3457016 90975 2356374 573234 53746 187527 7837 1441335 458407 52139 3387239 2030900 38 1648216 215105 212589 8278 1201586 244282 1 1 1897515 3957343 46 1 134481 1 1 2041785 3 1 37593 163173 1565457 3 1026885 1 34530 4655639 2 18 1940645 1550444 593209 1 2270700 706918 1 1 610113 9 1287883 3 1472134 1998685 1916822 1 296017 2 1 1737607 4155665 1510560 553342 56130 14436 13240604 4025888 1 4253261 174177 2043316 504151 2370989 420666 155232 1 219327 3752236 130062 571247 24 1 29015 31392 1020196 3 1117502 460873 7 1 228 8 133656 1 147008 1 93471 1 1 1 513410 4834094 1 14 1875636 182714 1504903 95263 4418053 1 357853 1135536 3698641 3 239316 4237884 131730 3878724 2158931 55650 1906785 1 26372 32 99217 1645677 379838 1 450352 7329657 112909 1 897980 2114198 308917 126215 1 53839 539997 238036 2 2270000 5 2388928 1668820 519153 58227 347528 1 1 2339954 10 5 2031341 54 2341529 2189774 112731 1 21918 748662 2068921 2 2232504 2923457 97740 3858 16604 398940 388755 1875003 667810 53633 315866 839868 1 7 1 14238 185 4 14 1 2 178947 1965719 398323 120849 48 1397222 961772 34124 2 160652 1 252629 246554 14529 1 299866 135255 490837 2863773 8 10 2 1906405 57 9782 118940 870003 255097 6 4187677 50965 3354376 17611 1804789 183601 158748 1539773 116107 77684 34738 2862836 1 2081903 727739 50328 2740070 17 923524 18 3089706 3144082 1 20 205247 347420 2076952 3725220 39270 2 15 49329 422629 5 1693818 2570558 2146654 1 5 129085 653766 47438 102243 389910 59715 21769 1246783 361571 4 120502 255235 1314165 3 3 5 2902624 76351 3117137 174413 2546645 14534 166054 1013583 1 1 2 9 3027288 3173742 338261 94929 1071263 4659804 1 506576 42798 4 984508 1 4 4 1 18541 7 1 269761 188905 2 1 92011 147031 677955 27484 1291675 2420682 99970 57943 1 4081062 1 250953 704904 4 349180 4273479 30528 2092508 2352781 3700946 1 77799 328993 3684623 3930179 1250080 1975798 54981 1621677 91664 1355832 1084049 721612 56950 197563 246868 5031 1 924076 1328694 58562 1 457662 2445958 1345169 957845 1056809 2485300 1687907 199029 3 9474 86928 1 2419980 3585265 570673 1 1514184 437383 1596697 29709 199606 126031 2 1541777 1 3 2090249 2402438 15 19 1423959 28 37852 4 1652596 1 405512 52 3 1948029 1 2 376 1155902 3 631665 3741991 57673 284026 424787 1 11569 5 1200313 1 20 2360854 1 119994 3889143 673424 797763 1 1 144306 1007659 1231874 75607 1 15 66187 8763 21366 146277 2684501 4458542 162223 3 1 5 94232 3036009 401312 19775 510737 3305062 58905 125783 274094 3089988 118483 1 106213 1 1289180 127905 30 528859 2 1215596 1955900 30 2236528 218643 1 2396631 1598175 1148688 452064 1 1840394 198540 1 1307187 107463 341396 2684981 9602 536871 1 148107 4068 4918434 1 2430254 2066144 88915 3585780 6464 259394 3098337 49601 42 79205 925658 1 2513666 26817 2738302 1 28 345735 5086930 361294 505662 386194 1103890 2653001 412247 4074274 2217918 1 519433 1338570 4289317 140138 18 2519983 168656 4546204 8 1 76545 511580 979214 9318 210013 50508 40 152908 17969 922507 1 7 32 1 388579 1 49886 13319 1066048 4663 27883 38419 1418098 2538216 1 778734 3556791 490764 666880 22746 5666164 4 20 1806284 21142 1 527906 2 12417 182224 49536 105029 206917 2427623 294247 1405136 321480 354137 84225 50 128073 1391176 352835 26074 91159 34229 237942 1 1519676 1 2428669 272681 148689 528951 560736 1 3548197 3833513 1438699 286613 1 1290904 47145 3456135 249648 277045 1012397 271073 1 6 149276 94843 11 177134 32336 2772732 7 22 37065 1 105299 76735 44 2211334 511942 30639 522056 5162 1899842 74 1 1448039 1 88817 21 1027532 555416 1 364383 1335609 167332 283252 49564 220972 1006800 3108886 801258 265596 61651 1 2413276 252747 416606 960925 54 311956 267135 3871698 22581 8978 2 10 1966155 3123429 28 46409 1 18433963725323 1769396 114766 49071 1 1 4228762 3483932 1139490 602592 2700468 770273 3 1 1 212087 281247 27093 156094 286299 1204001 18374 1 330780 1 1 25384 906728 99334 1250819 2161201 34 1027892 1 33449 2 129787 52246 94872 1536841 23470 1 1700323 1 1 3785351 1 95315 1014155 56570 22586 66842 7 156840 48752 1 3143722 1 1168309 2 4 101423 385892 42868 2893851 7 1783109 217499 24 460497 2003214 180135 3503010 131137 2 5240 1621601 2754811 11198 1 1 1105643 1 1671021 3 139611 18268 107229 44582 2211034 1 2880152747163 231008 262504 1 257760 1 1 52992 804418 2 2 4811272 1772250 3 1796530 1918647 1 1934549 1 100550 3448657 1681262 3 604526 320865 1901079 556908 2794800 2472000 637735 123663 1 3213187 118199 2553610 1 1750628 2563806 1 1670872 1 999609 50200 654831 1 164612 2865759 1841739 9 3744159 1331395 3202501 1 7 1 1 239868 1 1 581984 112413 401 1 29656 359367 74532 27226 51752 2583 1 645443 1559731 1 114195 1 85473 229474 111353 1 1521653 1 2568733 444398 2593568 18546 1 158085 1211147 1020006 23407 42514941388799 158442 1 1660358 5 34874 1594789 1551270 386464 502417 32280 170606 1954278 72486 3406066 11 52896 345631 4010742 33307 1951926 1441325 1886066 1 3 402778 3089364 351 28028 4301364 1 431569 5 3054030 375986 404966 1 449317 1230292 1 7 763949 1 2 3197443 1537806 335317 2 1 161263 1 1959902 1664530 139136 447570 1 1 50 158825 222939 1842131 11252 1680094 1017889 71 144808 1 53679 1 41278 1226724 1 1 2 10 2 1 112451 42133 1406662 1 112593 2 2832116 1544488 3579017 3029492 2752014 6 255091 731329 540861 1 426725 440330 212602 202358 173553 4 1189793 11031 84073 2084554 3963 1473295 1 642570 1 1423688 34509 75056 163273 490193 3200250 451777 157797 4156542 2386299 2794795 2735308 1332758 1193296 1131014 1001570 414257 4415511 4 3 1 3499595 536583 16731 93839 92382 1 45890 1 17695 8 867246 18 1607123 3197052 5 40009 1 329895 3497309 2416600 2316390 11 118179 2166659 2 136426 76762 2 14 2 3632525 214889 6 3900942 270409 230143 120414 417489 16706 1563597 31418 2 73 468763 88585 428274 3537347 2 1 491461 2806485 1 7 2950804 115684 4 1 429002 85771 2480 285541 186486 1 1 2430862 6 9 4 1833423 17143 353689 2568741 408890 2929237 208679 2198380 1 2501053 1933666 180843 1 1 2569886 1 17035 3449472 71357 246257 217898 1 47601 589824 401679 362878 13178 34464 1076419 1 554417 1 21248 2136449 1068 23029 8 766649 4 302879 274751 19 1 390259 1899931 233910 1392272 184492 2 2752059 55813 1 6 64674 205205 595508 1714309 582492 4821971 63973 1708726 189200 4548446 479425 2866037 1 1 1 2139319 1 1 3 1572621 2086152 2341038 1 619612 1 78942 772466 18932 1404368 936790 2263929 230200 3009227 251065 835010 88225 642856 824193 5559048 1 36348 2338046 481447 108132 2728223 3539009 1 197164 181408 171634 2172263 2317332 1598340 1318829 1746303 7 59657 1 1415452 122924 915828 1063890 40339 430186 4 2165185 2250922 704568 85138 4417453 255 326360 33541 3 49759 72127 912537 599665 1 29169 168741 349838 996835 1548193 2 28449 803521 4 2 2 3359043 3243259 1 491574 1675000 186105 3203018 11 39127 959876 334480 873131 70262 137080 1076591 1 2155613 74804 893022 2473922 1 1 269835 5 2407308 3 55200 905207 1 1 1245609 65934 7 1372126 530582 1383562 1 1 2718341 1 3947638 4 76837 412551 11 1 1 1208080 3024670 277 46485 1 9 562183 46 2985858 3379885 67816 1896527 1 105478 2035453 3026415 1 189256 2992616 2098002 1099666 775250 5913 13 406948 166773 1 322250 41919 480047 64950 17435 2147428 2336270 3330243 352709 86029 1398723 106236 312951 1 408211 252689 847088 2 17 34088 13128 187366 2 1559482 2349010 1651122 2371088 401005 1715445 1 29483921 1464444 50228 2365851 1651636 768715 226704 23677 83501 1 252623 444628 34 3640316 3602127 45369 1 1 1978261 1 3019189 1 25411 2177552 192839 191146 293712 3840622 182598 4069200 175757 1 2250458 4 1 7 2740824 2753005 1 2836428 1 12 19 2 1788326 3302198122211 3386546 1176663 20847 28 1194294 794665 2630378 13624 722012 2273872 1549353 1 3 1735700 1668388 416 970581 258382 295427 1 121571 3193610 3764806 1 368985 20436 89411 3 16130 2 241879 1 2996216 136958 2382095 510146 1762872 1372194 4215387 346915 4423 1 904153 2004500 248495 836598 3529163 27 2547535 1424181 1885308 1 1056747 289743 176929 2299073 170473 1 1 839941 12382 51457 608526 1684239 4843522 34550 929855 2767014 2979286 1 340808 184830 131077 57298 63854 381689 201998 1715328 118687 69190 123466 1 2 69392 159797 382756 1513430 2506318 457 1
Geometric mean score: 10983.8 in 31214 seconds

我切换到g ++ / MinGW和3个线程。
GNU生成的代码的速度是Microsoft的两倍以上。
难怪,令人震惊的STL实现会带来什么。

传送器

传送效应是高度依赖位置的。直到现在,我还是很高兴将传送器视为好(总是被视为空白空间)或总是坏(被当作墙壁,因此没有啮齿动物可以接受)。

这个模型太粗糙了。
给定的传送器可以将老鼠向前推进,直到离目标只有几个格,但是一旦到达该传送器,它就可以将老鼠从板上抛下。
这样的传送器很可能会被认为是合格的(因为它提高适应性的速度比“步行”到相同的x位置时更快),成为显性基因组的一部分,并杀死几乎所有将其视为“永远安全”的大鼠。
由于老鼠无法知道它们的X位置,因此检测这些诡tele的传送者的唯一解决方案是基于唯一可用的上下文数据(即5x5彩色网格)来决定是否踩踏它们。

为此,我定义了4种颜色基因:

  • 危险陷阱探测器
  • 在轨道上的任何地方都是
  • 禁止在赛道上的任何地方封锁
  • 根据周围环境,光束被视为空的块状

这样做的目的是通过查看其紧邻的8个邻居来区分其。由于在给定位置拥有8个相同邻居的可能性非常低,因此应该可以识别每个传送器的唯一实例。

可以将8种相邻颜色组合起来以形成局部签名,该局部签名对于迷宫中的位置是不变的。不幸的是,只有位于3x3视野内部正方形内的单元格才可见8个邻居,因此在视野边缘上的签名将不准确。
尽管如此,这将为我们提供附近社区的恒定上下文信息,这足以增加成功驾驭瞬移传送带的可能性。

基因具有2位可变字段。
对于给定的传送器本地签名,有四分之一的机会将波束单元视为不可通过。该字段的每个值都选择这四种可能性之一。
结果,这两个位上的波束基因突变将循环显示该颜色的4种可能的上下文指示。

此外,最重要的颜色仍然是墙壁和陷阱。这意味着只有老鼠知道墙壁和陷阱的位置之后,才应允许进行传送传送带检测。

这是通过仅少量更新本地签名来完成的。当前更新本地签名的标准是在被识别为潜在隐形传送带的颜色附近。

编码每个颜色基因使用5位,并对类型进行分组以释放3个较低有效位以编码0..7值:

  • 4危险
  • 4空
  • 4块
  • 4光束

每个波束基因有1/4的机会被视为一个区块,有3/4的机会被视为是空的,因此4个波束平均代表1个区块,而3个代表空的。

因此,由16种颜色的随机分布表示的平均比例为:

  • 4危险
  • 7空
  • 5块

到目前为止,这种混合似乎提供了最好的结果,但是我还没有完成调整。

基因变异

可以肯定的是,选择用来代表基因类型的代码值很关键。取反两个值可能要花费2000点或更多。

在此再次说明其原因超出了我的数学范围。

我的猜测是,必须平衡从一种类型到另一种类型的突变的概率,否则,就像在Markow矩阵中一样,累积概率倾向于将值限制为具有最高传入转换概率的子集。

救援之路

路径设置将显着减少访问单元的数量,从而仅测试最有可能达到目标的单元。因此,不仅避免了一些频繁的死角,而且更容易在早期发现错误的颜色代码。
结果,收敛时间大大减少。

但是,这无助于解决基因组无法正确显示轨迹的图谱。

白痴怎么办?

在视觉上看了看赛道之后,我理解了为什么即使在前面似乎只有墙的情况下也尝试前进的默认策略确实比抑制前进更好。
“墙壁”实际上可能是传送器,会产生许多不幸的结果,以致基因组将它们映射为永不踩踏的障碍,但在极少数情况下,这种顽皮的传送器的特定情况会产生积极的(或至少非致命的)影响,因此采取行动而不是后退增加了找到胜利之路的机会。

早期收敛

在我看来,突变率有点低(至少对我的啮齿动物而言)。

当前的0.01设置使DNA完整存活突变过程的机会为37%。将参数更改为0.0227可以将该概率降低到大约10%

神秘的公式是P 1位突变 = 1-P 完整基因组完整1/100,其中100是基因组位长。

例如,对于10%的概率,P 1位突变 = 1 - 0.1 1/100 = 0.0277
为5%的概率,P = 1 - 0.05 1/100 = 0.0295
反相式中,我们发现,0.01给出的是一个37分%的机会不变。

我以10%的概率重新运行了完全相同的测试(使用固定顺序的随机种子)。
在许多地图上,以前的失败变成了(有限的)成功。另一方面,大量的人口爆炸却更少了(这具有大大加快计算速度的有趣副作用)。
即使非常高的分数(超过一百万)并不常见,但成功的跑步次数却足以弥补。
最后,平均数从1400+上升到大约2000。

相反,将P设置为5%则产生的平均值约为600。
我认为突变率是如此之高,以致于获胜大鼠的基因组过于频繁地转化为效率较低的变异体。

这是怎么工作的

使用增加的传送器检测器,失败的游戏数量(得分<10)显着下降。
在2000年的运行试验中,只有1/3的失败。
几何平均数仅从2900上升到3300,但是这个数字不能反映出这种改善。

空色经常被猜为是光束和危险(通常是2到5)。基因组“使用”这些颜色来阻止可能招致老鼠麻烦的路径。

基因组非常擅长猜测陷阱(即一旦老鼠能够达到目标,大约90%的时间就会猜出代表实际陷阱检测器的颜色)。
它也为传送者使用了新的光束代码,尽管这种情况更为罕见(可能是因为“奸诈”的传送者比陷阱更不常见,并且其他光束/危险颜色也逐渐发展为阻塞了通往这些叛徒最后一幕的道路)。

从获胜的基因组经过5000转或更多转会出现的游戏数量来看,我认为这种新品种将从突变率提高中受益匪浅。


由于陷阱,空洞,墙壁和传送带的数量是偶数,因此您只需要3位即可准确存储比例(即使您考虑traps == walls)。另外,您是否考虑/放弃了在反围墙中使用未使用的陷阱偏移位的想法?由于目标是从父母那里继承,因此您实际上可以在反围墙中使用所有位。我认为没有理由让它们独一无二。
Mooing Duck

1
@MooingDuck我测试了您重用偏移量位的想法,但是失败了。正如我担心的那样,将信息用于两个不同的目的似乎没有用。例如,假设基因组需要给定颜色的偏移位,以在给定路径中选择正确的垂直方向,那么该颜色就不能代表有意义的陷阱而不会破坏依赖于相同数据的路径。我还尝试使用6个位,但是由于担心其他4个防撞墙也供应不足。

1
很高兴知道,但是我在那里提出了两种想法,一种是使用所有位(重用一些位),另一种是将未使用的陷阱偏移位用于墙/空。你都尝试过吗?(我完全理解,如果您不想尝试,几乎不需要您尝试)
Mooing Duck 2015年

1
我都尝试过,但都失败了。陷阱偏移量即使在基因不使用它们时也很重要,因为该基因仍然可以突变回陷阱颜色,在这种情况下,陷阱偏移量可能已经突变为最有利可图的背景位,并失去了其作为偏移量的含义。 。现在,它会变异回有利可图的抵销值,并破坏依赖于此作为上下文指标的老鼠的路径。我想我已经用图形工具看到了这种振荡的情况,但是要弄清楚这个问题的实例并不容易。

16

ColorScorePlayer,初步得分≈22

您是挑战赛中在GIF中工作的机器人。

这是我们在整个开发阶段的测试机器人。它使用基因组来存储16种颜色中每种颜色的质量得分。然后,它向前移动,将其移动到得分最高的颜色上(从不移动到-1)。如果出现平局,则在绑定单元之间随机选择一个动作。

我们已将此播放器移植到所有控制器语言中,因此它充当了如何使用它们的示例:

蟒蛇

class ColorScorePlayer(Player):
    def __init__(self):
        Player.__init__(self)
        self.coords = [Coordinate( 1, 0),
                       Coordinate( 1,-1),
                       Coordinate( 1, 1)]
        self.n_moves = len(self.coords)

    def turn(self):
        max_score = max([self.bit_chunk(6*self.vision_at(c.x, c.y), 6) for c in self.coords if self.vision_at(c.x, c.y)>=0])
        restricted_coords = [c for c in self.coords if self.vision_at(c.x, c.y)>=0 and self.bit_chunk(6*self.vision_at(c.x,c.y), 6) == max_score]

        return random.choice(restricted_coords)

红宝石

class ColorScorePlayer < Player
    def initialize(rng)
        super(rng)
        @coords = [Vector2D.new( 1,-1),
                   Vector2D.new( 1, 0),
                   Vector2D.new( 1, 1)]
    end

    def vision_at(vec2d)
        @vision[vec2d.x+2][vec2d.y+2]
    end

    def turn
        max_score = @coords.map { |c|
            color = vision_at(c)
            color < 0 ? -1 : bit_chunk(6*color, 6)
        }.max

        restricted_coords = @coords.select { |c|
            color = vision_at(c)
            color >= 0 && bit_chunk(6*color, 6) == max_score
        }

        restricted_coords.sample(random: @rng)
    end
end

C ++

coord_t colorScorePlayer(dna_t d, view_t v) {
    const int chunklen = DNA_BITS / N_COLORS;
    int ymax[3], nmax, smax = -1;
    for(int y = -1; y <= 1; y++) {
        if(v(1, y) == OUT_OF_BOUNDS) continue;
        int score = dnarange(d, v(1, y)*chunklen, chunklen);
        if(score > smax) {
            smax = score;
            nmax = 0;
        }
        if(score == smax) ymax[nmax++] = y;
    }
    return {1, ymax[v.rng.rint(nmax)]};
}

C#

public static void ColorScorePlayer(GameLogic.IView v, GameLogic.IGenome g, Random rnd, out int ox, out int oy)
{
    ox = 0;
    oy = 0;

    var max_score = cspcoords.Where(c => v[c.x, c.y] > -1).Select(c => g.cutOutInt(6 * v[c.x, c.y], 6)).Max();
    var restrictedCoords = cspcoords.Where(c => v[c.x, c.y] > -1 && g.cutOutInt(6 * v[c.x, c.y], 6) == max_score).ToArray();

    Coord res = restrictedCoords[rnd.Next(restrictedCoords.Length)];

    ox = res.x;
    oy = res.y; 
}

爪哇

package game.players;

import java.awt.*;
import java.util.Map;

public class ColorScorePlayer extends Player{
    private static final Point[] possibleMoves = {new Point(1, 0), new Point(1, -1), new Point(1, 1)};

    @Override
    public Point takeTurn(String genome, Map<Point, Integer> vision) {
        int chunkLength = genome.length()/16;
        int maxSum = -1;
        Point maxSumMove = possibleMoves[0];
        for (Point move: possibleMoves){
            if (vision.get(move) == -1){
                continue;
            }
            int initialPoint = chunkLength*vision.get(move);
            int sum = 0;
            for (int i = initialPoint; i < initialPoint + chunkLength; i++){
                sum = (sum<<1)+Integer.parseInt(genome.charAt(i)+"");
            }
            if (sum > maxSum){
                maxSum = sum;
                maxSumMove = move;
            }
        }
        return maxSumMove;
    }
}

球员得分相当不一致。这是50次随机运行:

Scores: 1 1 1132581 3 43542 1 15 67 57 1 11 8 623162 1 1 1 134347 93198 6 1 2 1 1 245 3 1 1 27 1 31495 65897 9 5 1 2 20 2 117715 1 1 1 20 64616 5 38 1 2 1 2 12

12

ColorFarSeeker,C ++≈74.7

如果您尝试的话,这一挑战确实非常有趣且简单。

不要被冗长的描述所困扰。
只需访问GitHub并检查一下...一切将变得更加清晰!:)

强烈建议使用C ++模拟器以提高速度。即使在我将python程序转换为C ++之后,python模拟仍然没有停止。

这是ColorScorePlayer的改进版本。为了充分利用其5x5视图,它考虑使用加权函数从其移动2步。向前移动1步具有较高的权重,因为它们对生存率具有更直接的影响。将前进2步的重量较小。

尝试向前移动,但是如果看不到安全移动...则尝试侧向...如果其他所有方法均失败,则随机向后移动。

coord_t colorFarSeeker(dna_t d, view_t v) {
#define s(w,x,y) (v(x,y)>-1?((b+dnarange(d,l+m+n*v(x,y),n))*w):0)
#define max2(a,b) (((a)>(b))?(a):(b))
#define max3(a,b,c) (max2(a,max2(b,c)))
#define push(vec,maxScore,score,x,y) if(score==maxScore&&v(x,y)>-1)vec.push_back({x,y});
#define tryReturn() if(vec.size()){return vec[v.rng.rint((int)vec.size())];}vec.clear();

    // Some constants to tweak
    int k = 4;
    int l = 3;
    int m = dnarange(d, 0, l);
    int n = 4;
    int b = dnarange(d, l, k) + 10;

    std::vector<coord_t> vec;

    // Looks forward for good moves...
    int upRightScore = s(1,0,-2) + s(1,1,-2) + s(1,2,-2) + s(5,1,-1);
    int forwardScore = s(1,2,-1) + s(1,2,0) + s(1,2,1) + s(5,1,0);
    int downRightScore = s(1,0,2) + s(1,1,2) + s(1,2,2) + s(5,1,1);
    int maxForwardScore = max3(upRightScore,forwardScore,downRightScore);
    push(vec,maxForwardScore,upRightScore,1,-1);
    push(vec,maxForwardScore,forwardScore,1,0);
    push(vec,maxForwardScore,downRightScore,1,1);
    tryReturn();

    // Looks sideways for good moves...
    int upScore = s(1,-1,-2) + s(1,0,-2) + s(1,1,-2) + s(5,0,-1);
    int downScore = s(1,-1,2) + s(1,0,2) + s(1,1,2) + s(5,0,1);
    int maxSideScore = max2(upScore,downScore);
    push(vec,maxSideScore,upScore,0,-1);
    push(vec,maxSideScore,downScore,0,1);
    tryReturn();

    // If all else fails, move backwards randomly.
    // I have tried considering the scores of backmoves,
    // but it seems worse than just randomly moving backwards. 
    vec.push_back({-1,-1});
    vec.push_back({-1,0});
    vec.push_back({-1,1});
    return vec[v.rng.rint((int)vec.size())];

}

得分:

相当多的1 ...当您看到控制台彼此后退1时,这可能有点令人沮丧。就像一个拥有生活必需品的星球,但没有先进的老鼠文明的迹象...
然后偶有高峰。:)

嗯...显然我很幸运,因为我进行了第一批跑步,获得了300+的几何图形。分数确实确实有很大的波动。但是无论如何,随着模拟器的运行次数增加,它可能会接近≈74。

我的跑步成绩:6 6 53 1 5 101223 89684 17 2 303418 4 85730 24752 1 1 1 3482515 39752 1 59259 47530 13 554321 1 563794 1 1770329 1 57376 1 123870 4 1 1 79092 69931 594057 1 69664 59 1 6 37857 1733138 55616 2 1 51704 1 254006 4 24749 1 117987 49591 220151 26 4292194 23 57616 72 67 1 4 308039 1 1 103 89258 1 286032 1 5 3 1 5 114851 46 143712 5 15 9 80 7425 1 1 7 1 108379 70122 97238 1 1 5 2 23 104794 1 10476 59245 1 204 1 1 12 1 29641 1 314894 18785 13 1 3 1 1 1 1 2 526001 1 1 1 1 27559 29285 3 3 128708 70386 30 2 2 1 208531 331 1 2 1 61 114993 1 15 51997 1 2 1 146191 1 31 4 3 1 161422 207 1 64 1 1 1 68594 145434 87763 150187 169 185518 1 1 1 1 24208 2570 1 1 537 1 1 462284 1 2 55 1 1 1 214365 1 40147 2 213952 1 29 3 1 2144435 5 4502444 72111 1 1 1 1 1 774547


1
在1000场比赛中,我得到74.7的几何平均值,表现不错。
feersum

8

Bishop-Python,初步得分1.901

主教总是沿对角线移动,因此在给定的全途跋涉中无法到达一半的棋盘,但这确实意味着要编码的潜在动作更少,因此基因组的每个位都可以代表一个动作(主教永不退缩)。根据样本前面(右侧)的3x3正方形块确定要指的是哪一位。在给定情况下,最好的举措就是只有一次突变。

该机器人起初学习速度很快,但是在到达终点之前经常碰上顶峰,大概是以下两个问题之一发生的地方:

  • 电路板的两个或更多部分映射到同一位,但需要不同的移动。
  • 某些板不能仅通过对角线移动来通过。

class BishopPlayer(Player):
    def __init__(self):
        Player.__init__(self)
        self.coords = [Coordinate(1,-1),
                       Coordinate(1, 1),
                       ]
        self.inputs = [(x,y) for x in (0,1,2) for y in (-1,0,1)]

    def turn(self):
        # Move away from out of bounds areas
        if self.vision_at(0,-1) == -1:
            return self.coords[1]
        if self.vision_at(0,1) == -1:
            return self.coords[0]

        # Move right, and either up or down based on one bit of the genome
        bit_to_use = sum(self.vision_at(self.inputs[i][0],
                                        self.inputs[i][1]
                                        ) * (16 ** i) for i in range(9)
                         ) % 100
        return self.coords[self.bit_at(bit_to_use)]

尽管有这些限制,主教在极少数情况下还是表现出色,每个标本都在木板上完成了几圈。我曾想过,在给定的一圈中,一个标本只能在棋盘的一半上移动(仅相当于国际象棋棋盘上的黑色方块或白色方块)。但是,正如MartinBüttner指出的那样,传送器可以将标本从黑色正方形移动到白色正方形,反之亦然,因此在大多数板上都不受限制。

(有两对匹配的传送器类型,每对都有0.5的偏移概率,可将样本移动到黑色和白色正方形的另一半。因此,板中只有传送器将样本限制为一个的概率每圈一半的木板只有0.25。)

得分显示,偶尔的胜利穿插在很长一段时间内未能达到终点:

分数:1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 2 1 1 1 1 1 6 1 8 1 10 15 1 1 12544 1 2 1 1 1 1 1 3 7554 1 1 1 1 1


8

红利玩家:几何平均值50.35(5000游戏测试)

该机器人根据DNA的6位片段(例如颜色得分播放器),通过正方形的颜色对正方形进行评分,但是编号系统不同。该机器人的动机是,一个位将得分的值更改为32,而另一位仅将其更改为1,这是相当随意的。它将值n(n + 1)/ 2分配给n个连续的1位。另外,它添加了一种随机化机制,以防止卡住。它将以30分之一的机会随机向前移动。

为了进行比较,在两次1000次游戏测试中,颜色得分玩家得分为30到35。有趣的是,颜色得分玩家的最高游戏分数在3-5百万范围内,而奔跑奖金的最高分数仅为20万。通过更一致地获得非零分数,运行奖金受益于对数平均评分系统。

在C ++控制器上使用6个线程运行5000个游戏大约需要20分钟。

coord_t runbonus(dna_t d, view_t v) {
    int ymax[3], nmax, smax = -1;
    if(!v.rng.rint(30)) {
        int y;
        while(!~v(1, y = v.rng.rint(-1, 1)));
        return {1, y};
    }
    for(int y = -1; y <= 1; y++) {
        if(v(1, y) == OUT_OF_BOUNDS) continue;
        int score = 0;
        int streak = 0;
        for(int i = 0; i < 6; i++) {
            if(d[6*v(1,y) + i])
                score += ++streak;
            else
                streak = 0;
        }
        if(score > smax) {
            smax = score;
            nmax = 0;
        }
        if(score == smax) ymax[nmax++] = y;
    }
    return {1, ymax[v.rng.rint(nmax)]};
}

出于好奇,这5000条曲目测试花了多长时间?我的老鼠需要一个多小时才能完成1000条轨道,所以我必须让计算机整夜运行才能重现您的测试用例。

@kuroineko您的问题的答案已经在我的答案中。
feersum

哎呀,对不起。然后,我将在PC上尝试您的代码,以了解硬件在速度差异中所起的作用。也许尝试使用gcc代替MSVC。我注意到在其他几个计算量大的代码上,性能比MSVC提高了30%。

您的代码在我的i3-2100@3.1GHz上使用4个线程运行了1000多首,运行了20多分钟。分数大约是56。看来这意味着我的PC比您的PC慢5倍,而我的代码在给定的机器上也要慢6倍(但机械上的得分越高,意味着计算时间越长)。由于我买新PC的时间太晚了,是时候进行一些优化了……

8

StarPlayer | C ++ | 得分:162(基于500场比赛)

该玩家尝试使用A *寻找最佳前进方式。它以与ColorScorePlayer相同的方式分配权重,并尝试将其寻路到视图的右边缘。该实现不是我做过的最漂亮的事情,但至少并不太慢。

#include <utility>

#define IDX(a,b) a[VIEW_DIST + b.x][VIEW_DIST + b.y]

std::pair<coord_t,int> planAhead(int weights[N_COLORS], view_t &v, coord_t target) {
    bool open[VIEW_DIST*2+1][VIEW_DIST*2+1] = {false};
    bool closed[VIEW_DIST*2+1][VIEW_DIST*2+1] = {false};
    int f_score[VIEW_DIST*2+1][VIEW_DIST*2+1] = {0};
    int g_score[VIEW_DIST*2+1][VIEW_DIST*2+1] = {0};
    coord_t came_from[VIEW_DIST*2+1][VIEW_DIST*2+1] = {{0,0}};
    open[VIEW_DIST][VIEW_DIST] = true;
    g_score[VIEW_DIST][VIEW_DIST] = v.rng.rint(5);
    f_score[VIEW_DIST][VIEW_DIST] = (abs(target.x) + abs(target.y)) * 10;
    for (;;) {
        coord_t current{VIEW_DIST+1,0};
        for (int x = 0; x < (VIEW_DIST*2+1); x++)
            for (int y = 0; y < (VIEW_DIST*2+1); y++)
                if (open[x][y] && (current.x > VIEW_DIST || f_score[x][y] < IDX(f_score,current)))
                    current = {x - VIEW_DIST, y - VIEW_DIST};
        if (current.x > VIEW_DIST)
            return {{1,0}, 1000000};
        if (current.x == target.x && current.y == target.y)
            break;
        IDX(open,current) = false;
        IDX(closed,current) = true;
        for (int dx = -1; dx <= 1; dx++) for (int dy = -1; dy <= 1; dy++) {
            if (dx == 0 && dy == 0)
                continue;
            coord_t tentative{current.x + dx, current.y + dy};
            if (abs(tentative.x) > VIEW_DIST || abs(tentative.y) > VIEW_DIST)
                continue;
            if (IDX(closed,tentative))
                continue;
            auto color = v(tentative.x, tentative.y);
            if (color == OUT_OF_BOUNDS)
                continue;
            auto tentative_g = IDX(g_score,current) + weights[color];
            if (!IDX(open,tentative) || tentative_g < IDX(g_score,tentative)) {
                IDX(came_from,tentative) = current;
                auto distance = abs(tentative.x - target.x) + abs(tentative.y - target.y);
                IDX(f_score,tentative) = tentative_g + distance * 10;
                IDX(g_score,tentative) = tentative_g;
                IDX(open,tentative) = true;
            }
        }
    }
    auto prev = target, current = target;
    while (current.x != 0 || current.y != 0)
        prev = current, current = IDX(came_from,current);
    return {prev, IDX(g_score,target)};
}

coord_t starPlayer(dna_t d, view_t v) {
    const int chunklen = DNA_BITS / N_COLORS;
    int weights[N_COLORS];
    for (int i = 0; i < N_COLORS; i++)
        weights[i] = dnarange(d, i*chunklen, chunklen);
    std::pair<coord_t,int> choice{{1,0}, 1000000};
    for (int y = -VIEW_DIST; y <= VIEW_DIST; y++) {
        auto plan = planAhead(weights, v, {VIEW_DIST, y});
        if (plan.second < choice.second)
            choice = plan;
    }
    return choice.first;
}

样本分数:

4 92078 1 10 1 1 3 2 2862314 5 24925 1 3 2 126502 1 24 1097182 39 1 1 1 47728 227625 137944 15 1 30061 1 1 1 3171790 19646 10 345866 1 1 1 829756 425 6699 22 8 1 1 6 6 104889 125608 1


1
在1000场比赛中,我得到133.2的高分。
feersum

7

WallGuesser-在1000游戏测试中得分113.266

编码方式

我做了一个非常简单的6位/颜色编码。解码颜色[n]

  • 将基因组中的第n个位相加,总计为96
  • 如果总分> = 4,则说该方块被遮挡了
  • 如果总分<= 4,则其最终得分为其总分的2 ^

通过将一种颜色的位散布到整个基因组中,我增加了将两个亲本的位用于每种颜色的机会。

运动

我使用(我肯定不太高效)基于A *的搜索来寻找成本最低的通往任何右边缘正方形的路径。如果颜色映射到“已阻止”,则搜索将永远不会输入该颜色。如果搜索找不到路径,则假定该老鼠不适合繁殖,并通过向左移动一只老鼠来结束它。

减少不健康大鼠的数量

由于我的基因组有效地猜测了哪些正方形是墙壁或向后的传送者,所以没有猜测(没有颜色映射到被阻止的)的老鼠不太适合。要尝试删除这些老鼠,如果没有颜色将被标记为阻塞,则将每种颜色标记为阻塞,并且老鼠将始终向左移动一只。

去做

目前,行为尚无随机性,因此老鼠很容易被卡住。

#include "./gamelogic.cpp"

#include <algorithm>
#include <set>
#include <map>
#include <climits>

bool operator< (const coord_t &a, const coord_t &b){
    if(a.x != b.x){ return a.x < b.x; }
    else if (a.y != b.y){ return a.y < b.y; }
    else{ return false; }
}

bool operator== (const coord_t &a, const coord_t &b){
    return (a.x == b.x) && (a.y == b.y);
}

int coordDistance(const coord_t &a, const coord_t &b){
    int xDif = abs(a.x - b.x);
    int yDif = abs(a.y - b.y);
    return xDif > yDif ? xDif : yDif;
}

int coordMinSetDistance(const coord_t &a, const std::set<coord_t> &ends){
    int min = INT_MAX;
    for (auto i : ends){
        int cur = coordDistance(a, i);
        if (cur < min){
            min = cur;
        }
    }
    return min;
}


class ColorMap{
public:
    view_t *v;
    int colors[16] = {};
    const int Blocked = -1;

    ColorMap(dna_t &d, view_t *v){
        this->v = v;

        //Decode the genome
        for (int i = 0; i <= (16*6); i++){
            if (d.at(i) == true){
                colors[i % 16]++;
            }
        }

        //Encode the result
        bool guessedWalls = false;
        for (int i = 0; i < 16; i++){
            if (colors[i] >= 4){
                colors[i] = Blocked;
                guessedWalls = true;
            }
            else{
                colors[i] = pow(2, colors[i]);
            }
        }

        if (guessedWalls == false){
            for (auto i : colors){
                i = Blocked;
            }
        }
    }

    int operator() (coord_t pos){
        if (abs(pos.x) > VIEW_DIST || abs(pos.y) > VIEW_DIST){
            return Blocked;
        }

        int value = (*v)(pos.x, pos.y);
        if (value == OUT_OF_BOUNDS){
            return Blocked;
        }
        else{
            return colors[value];
        }
    }

    void print(){
        int lower = -1 * VIEW_DIST;
        int upper = VIEW_DIST;
        for (int y = lower; y <= upper; y++){
            for (int x = lower; x <= upper; x++){
                std::cout << std::setw(3) << this->operator()({ x, y });
            }
            std::cout << std::endl;
        }
    }
};

class node{
public:
    coord_t pos;
    coord_t cameFrom;
    int gScore;
    int minDistance;

    node(coord_t pos, coord_t cameFrom, int gScore, int minDistance){
        this->pos = pos;
        this->cameFrom = cameFrom;
        this->gScore = gScore;
        this->minDistance = minDistance;
    }

    int fScore() const{ return gScore + minDistance; };

    bool operator< (const node &rhs) const{ return fScore() < rhs.fScore(); }
};

class EditablePriorityQueue{
private:
    //This is reversed so smallest are on top
    struct lesser{
        bool operator()(node *a, node *b) const{
            return (*b) < (*a);
        }
    };

    std::vector<node*> queue; // Use heap functions to maintain the priority queue ourself
    std::map<coord_t, node*> members;

public:
    EditablePriorityQueue(){};

    ~EditablePriorityQueue(){
        for (auto &m : members){
            delete m.second;
        }
    }

    bool empty(){ return members.empty(); }

    node *top(){
        auto top = this->queue.front();
        std::pop_heap(queue.begin(), queue.end(), lesser());
        queue.pop_back();
        members.erase(top->pos);
        return top;
    }

    void set(coord_t target, coord_t cameFrom, int gScore, int minDistance){
        auto targetLocation = members.find(target);

        //If the target isn't a member add it
        if (targetLocation == members.end()){
            auto *newNode = new node(target, cameFrom, gScore, minDistance);
            queue.push_back(newNode);
            std::push_heap(queue.begin(), queue.end(), lesser());
            members[target] = newNode;
        }
        //The target must be updated
        else{
            auto currentNode = targetLocation->second;
            if (currentNode->gScore > gScore){
                currentNode->gScore = gScore;
                currentNode->cameFrom = cameFrom;
                std::make_heap(queue.begin(), queue.end()); //More efficient way to do this?
            }
        }
    }
};

std::pair<coord_t, int> pathCost(ColorMap &m, coord_t start, const std::set<coord_t> &ends){
    EditablePriorityQueue openSet;
    std::set<coord_t> closedSet;
    std::map<coord_t, coord_t> cameFrom;

    openSet.set(start, start, 0, coordMinSetDistance(start, ends));
    while (openSet.empty() == false){
        auto current = openSet.top();
        closedSet.insert(current->pos);
        cameFrom[current->pos] = current->cameFrom;

        //Check if we're done
        if (ends.count(current->pos) != 0){
            //Recover the path
            coord_t path = current->pos;
            int finalScore = current->gScore;
            delete current;
            while (!(cameFrom[path] == start)){
                path = cameFrom[path];
            }

            return{ path, finalScore };
        }               

        //Examine current's neighbours
        for (int x = -1; x <= 1; x++) for (int y = -1; y <= 1; y++){
            coord_t neighbour = { current->pos.x + x, current->pos.y + y };

            if (x == 0 && y == 0){ continue; }

            closedSet.count(neighbour);
            if (closedSet.count(neighbour) != 0){ continue; }

            int neighbourScore = m(neighbour);
            if (neighbourScore == m.Blocked){ continue; }

            int tentativeScore = current->gScore + neighbourScore;
            openSet.set(neighbour, current->pos, tentativeScore, coordMinSetDistance(neighbour, ends));

        }
        delete current;
    }

    return{ { -1, 0 }, INT_MAX }; //Try to end it
}

coord_t myPlayer(dna_t d, view_t v) {
    auto ourMap = ColorMap(d, &v);

    std::set<coord_t> edges;
    for (coord_t edge = { VIEW_DIST, -1 * VIEW_DIST }; edge.y <= VIEW_DIST; edge.y++){
        edges.insert(edge);
    }

    //Move to the neighbor closest to a square on the right
    auto result = pathCost(ourMap, { 0, 0 }, edges);
    auto minMove = result.first;

    return minMove;
}

int main() {
    slog << "Geometric mean score: " << runsimulation(myPlayer) << std::endl;
}

嗯,这对我来说并不合算g++ -std=c++11 .\wallguesser.cpp -O2 -o .\wallguesser.exe。我收到很多错误,但第一个错误是.\wallguesser.cpp:47:19: error: 'dna_t' has no member named 'at' if (d.at(i) == true){
Martin Ender

没问题,只需更改at即可[]解决。
feersum'2

7

最出色-几何平均得分:〜922(2K跑步)

我的方法是:

  1. 找出杀死该物种的原因并定义所需的行为(功能性)
  2. 在代码中实现所需的行为(技术)
  3. 给它一个优先事项。它比其他期望的行为重要还是重要?
  4. 通过调整解决方案的参数来优化几何平均得分。

我用相同的50个种子测试了2000多个参数。选择最有前途的组合,并使用250颗相同的种子进行评分,等级最高的组合将用于下一轮测试。因此,我设法创建了一种遗传算法,以根据用户mbomb007的建议为该问题找到最佳的遗传算法

所需的行为:

  1. 该物种应了解哪些颜色是安全的,哪些不好。
  2. 该物种应主要根据前面的3个单元格决定其移动的位置,但是如果没有好的移动可用,则垂直移动或向后移动则应考虑
  3. 该物种还应该寻找超越他周围的8个细胞的并将其用于决策信息中
  4. 该物种应学会识别陷阱
  5. 一些物种错误地认为墙壁是好的,并试图一直向它们移动,因此卡在墙壁的前面。如果他们是当时优胜劣汰分数最高的物种,他们对壁的错误假设的DNA将被复制多次进入新生儿。一段时间后,所有物种都被困在墙前,没有一个达到得分目标。如何制止白痴?

数据存储方式:

我们希望物种学习事物,适应其环境并成为最适者。如果学习内容可以某种方式存储,那么这不可避免地起作用。学习内容将被“存储”在100个DNA位中。这是一种奇怪的存储方式,因为我们无法更改 DNA的价值。因此,我们假设 DNA已经存储了坏运和好运的信息。如果对于某个物种正确的信息存储在其DNA中,他将快速前进并利用其DNA产生许多新物种。

我发现几何平均分数对信息的存储方式很敏感。假设我们读取了100位DNA的前4位,并将其存储在整数变量中。我们可以通过几种方式做到这一点:

  1. 十进制数据存储:通过使用“内置” dnarange功能,例如:4位1011将变为“ 1x2 ^ 3 + 0x2 ^ 2 + 1x2 ^ 1 + 1x2 ^ 0 =15。可能的值(4位):[0,1 ,2、3、4、5、6、7、8、9、10、11、12、13、14、15]
  2. 条纹数据存储:通过使用dnaStreakRange函数(定义如下),例如:4bits 1011将变为1x1 + 0x1 + 1x1+ 1x2 = 4。可能的值(4位):[0,1,2,3,6,10]
int dnaStreakRange(dna_t &d, int start, int chunklen) {
    int score = 0;
    int streak = 0;
    for(int i = 0; i < chunklen; i++) {
        if(d[start + i])
            score += ++streak;
        else
            streak = 0;
    };  
    return score;
}
  1. 比特数据存储:通过使用dnaCountRange函数(定义如下),例如:4bits 1011将变为1x1 + 0x1 + 1x1 + 1x1 = 3。可能的值(4位):[0,1,2,3,4]
int dnaCountRange(dna_t &d, int start, int chunklen) {
    int score = 0;
    for(int i = 0; i < chunklen; i++) {
        if(d[start + i])
            score ++;
    };  
    return score;
}

两种存储方法之间的区别是:

  • 十进制存储方法很容易对 DNA进行一点更改。当比特值从1011更改为0011时,其值从3更改为2,这是一个很小的更改。
  • 十进制存储方法是同构的。每个可能的值都会发生相同的变化。您从4位存储内存块中读取值15的机会是1/16 = 6%。的条纹的存储方法是不均匀的。条纹4位值小于或等于6的机会是(15-3)/ 16 = 81%(除0111、1110、111以外的所有16种组合)。视觉下方显示了分布的形状。如您所见,在蓝色箭头处,4位条纹小于或等于6的几率是81%: 可视化4,5和6位长的二进制数的小数,条纹和位存储类型的分布

确定解决方案的优先级。

当ColorScorePlayer识别出两个得分相同的向前移动时,将做出任意选择。恕我直言,您永远不要使用随机函数v.rng.rint()function。取而代之的是,您应该利用这个机会,将分数相等作为评估二阶效应解的钩子。

一阶效应获得最高优先级。如果达到相等分数,则优先级为2的解决方案为准,依此类推。通过调整解决方案的参数,您可以影响出现相等分数的机会,并以此方式更改优先级1和优先级2解决方案的权重。

实现期望的行为

了解哪些颜色是安全的:

  • 16种颜色中有33%是不良的,因此,当移动的分数低于63/3时,将不允许移动。因此threshold = 63/3=21,63是6位的最高分,而33%= 1/3(可以在上图中查询)。

如果没有好的移动可用,请垂直或向后移动:

  • 当不允许向前移动时,垂直移动将以相同的方式相互比较。如果也不允许垂直移动,则将向后移动排序。这是通过weightMove变量实现的。

看看超越了什么:

  • 当2或3个动作得分相同时,这些动作周围的3x3框将确定(通过x2y2循环)什么是最佳选择(通过mainSubScore变量)。该3x3框中最右边的列处于领先地位。
coord_t adjustedColorPlayer(dna_t d, view_t v) {
    const int chunklen = 6,threshold = 63/3;
    int xBestScore=0, yBestScore=0;
    long bestScore=-1, weightMove, weightMove2, mainScore;
    for(int x = -1; x <= 1; x++) {
        if (x < 0) weightMove = 1000; // moving backward
        if (x== 0) weightMove = 10000; //moving vertical
        if (x > 0) weightMove = 100000; //moving forward
        for(int y = -1; y <= 1; y++) {
            if(v(x, y) == OUT_OF_BOUNDS || (x==0&&y==0) ) continue;
            mainScore = dnarange(d,v(x,y)*chunklen,chunklen);
            if (mainScore<threshold+1) {
                mainScore =  0; //not a suitable move because too low score
            }else{
                mainScore*= weightMove;
                // when equal score, use sub score by examining 5x5 box to rank moves
                for(int x2 = x-1; x2 <= x+1; x2++){     
                    if (x2 < x) weightMove2 = 1; // moving backward
                    if (x2== x) weightMove2 = 10; //moving vertical
                    if (x2 > x) weightMove2 = 100; //moving forward
                    for(int y2 = x-1; y2 <= y+1; y2++){     
                        if(v(x2, y2) != OUT_OF_BOUNDS){
                            long mainSubScore = dnarange(d,v(x2,y2)*chunklen,chunklen);
                            if (mainSubScore>=threshold+1) mainScore+=mainSubScore*weightMove2;
                        }
                    }
                 }
            }
            if(mainScore > bestScore) {
                bestScore = mainScore;              
                xBestScore = x;
                yBestScore = y;
            }
        }
    }
    return{xBestScore,yBestScore};
}

得分:123(2K跑步)

前50个得分(18场比赛仅获得1分):

1 10 1 79947 3 1 11 125 7333287 23701 310869 53744 1 2 2 2 2 1 1 57556 2 688438 60 1 2 2636261 26306 1 125369 1 1 1 61895 27 1 36 1 91100 87636 1 2 47497 53 16 1 11 222384 1 1 1 1

识别陷阱:

当使用bitsum4存储终止任意游戏时,我检查了得分最高的物种的DNA(因此颜色得分的范围为[0,4]):

  • 得分0:向后传送,两面墙壁,安全1x
  • 得分1:向后陷阱(非常无害),向后传送,安全1倍
  • 得分2:陷阱向前(太危险),安全1倍
  • 得分3:向前传送,安全5倍
  • 得分4:向前传送,安全1倍

由此可以得出结论,墙壁和传送带获得正确的分数。无法识别陷阱,因为它们取决于方向和原产地颜色,而得分是根据目的地的颜色进行的。因此,还需要存储有关原色的数据v(0,0)。在理想的世界中,我们希望存储16种颜色x 8个方向x 3位= 384位的信息。

不幸的是,由于只有100位可用,因此我们无法全部使用,因为上述解决方案还需要一些内存。因此,我们将创建4个颜色容器:

  • 0:颜色0-颜色3,
  • 1:颜色4-颜色7
  • 2:颜色8-颜色11
  • 3:颜色12-颜色16

和4个移动方向箱

  • 0:垂直或向后移动,
  • 1:向前移动
  • 2:前进
  • 3:向前走

当十进制分数等于或大于4(100,101,110,111)时,将认为此单元格关联有陷阱,因此,当出现相等分数时,将不会选择此举动。因此,陷阱识别是一种二阶效应,而“寻找超越”将是第三优先解决方案。

int dnaLookup2(dna_t &d, int start, int chunklen, int storageMethod) {
    // Definition of storageMethod: 0=decimal, 1=streak, 2=bitsum
    int score = 0, streak = 0;
    for(int i = start; i < start+chunklen; i++) {
        int value = d[i];
        if (storageMethod==0) {
            score = (score << 1) |value;
        }else{
            if (storageMethod==1){
                if(value) score += ++streak; else streak = 0;
            }else{
                if(value) score ++;         
            }
        }
    };  
    return score;
}

coord_t theTrapFighter(dna_t d, view_t v) {
    // Definition of storageMethod: 0=decimal, 1=streak, 2=bitsum
    const int colorMemStorageMethod = 1, colorMemBlockSize = 3;
    const int trapMemStorageMethod = 0, trapMemBlockSize = 3;
    const int trapMemTopThreshold = 4, nDirBins = 4, nColorBins = 4;

    int xBestScore=0, yBestScore=0;
    long bestScore=-1, weightMove, weightMove2, mainScore;
  for(int x = -1; x <= 1; x++) {
        if (x < 0) weightMove = 1000; // moving backward
        if (x== 0) weightMove = 10000; //moving vertical
        if (x > 0) weightMove = 100000; //moving forward
        for(int y = -1; y <= 1; y++) {          
            int color = v(x, y);
            if(color == OUT_OF_BOUNDS || (x==0&&y==0) ) continue;
            mainScore = dnaLookup2(d,color*colorMemBlockSize,
             colorMemBlockSize,colorMemStorageMethod);
            if (mainScore==0) {
                //not a suitable move because too low score
            }else{
                mainScore*= weightMove;
                //lookup trap likelihood
                int directionBin = 0;
                if (nDirBins==3) directionBin = x>0?y+1:-1;
                if (nDirBins==4) directionBin = x>0?y+2:0;
                // put 16 colors in nColorBins bins
                int colorBin = v(0,0)*nColorBins/N_COLORS; 
                colorBin = colorBin>(nColorBins-1)?(nColorBins-1):colorBin;
                if (directionBin >= 0 &&
                 dnaLookup2(
                   d,
                   colorMemBlockSize*16
                    +trapMemBlockSize*(nColorBins*directionBin+colorBin),
                   trapMemBlockSize,
                   trapMemStorageMethod
                 ) >=trapMemTopThreshold){
                  //suspect a trap therefore no sub score is added                  
                 }else{
                    // when equal score, use sub score by examining 5x5 box to rank moves
                    for(int x2 = x-1; x2 <= x+1; x2++){     
                        if (x2 < x) weightMove2 = 1; // moving backward
                        if (x2== x) weightMove2 = 10; //moving vertical
                        if (x2 > x) weightMove2 = 100; //moving forward
                        for(int y2 = x-1; y2 <= y+1; y2++){     
                            int color2 = v(x2, y2);
                            if(color2 != OUT_OF_BOUNDS){
                                mainScore+=weightMove2 * dnaLookup2(d,color2*colorMemBlockSize,
                                 colorMemBlockSize,colorMemStorageMethod);
                            }
                        }
                    }               
                 }
            }
            if(mainScore > bestScore) {
                bestScore = mainScore;              
                xBestScore = x;
                yBestScore = y;
            }
        }
    }
    return{xBestScore,yBestScore};
}

得分:580(2K次)

前50个得分(13场比赛仅获得1分):

28,044 14,189 1 2,265,670 2,275,942 3 122,769 109,183 401,366 61,643 205,949 47,563 138,680 1 107,199 85,666 31 2 29 1 89,519 22 100,908 14,794 1 3,198,300 21,601 14 3,405,278 1 1 1 2 74,167 1 71,242 97,331,109,080 1 1 102 94

关于白墙的错误假设多次被白痴复制到新生儿中:

一些物种错误地认为墙壁是好的,并试图一直向它们移动,因此卡在墙壁的前面。它们也可能陷入无限的瞬态传送器中。在两种情况下,效果是相同的。

主要的问题是,经过几百次迭代,某些基因变得非常占优势。如果这些是“正确的”基因,您将获得非常高的分数(> 1百万分)。如果这些是错误的,那么您就被困住了,因为您需要多样性才能找到“正确的”基因。

白痴战斗:解决方案1:颜色反转

我尝试的第一个解决方案是努力利用仍然非常多样化的未使用内存的一部分。假设您已将84位分配给彩色内存和陷阱查找内存。其余的16位将非常多样化。我们可以填充2个十进制8变量,它们的值在[0,255]之间,并且是同质的,这意味着每个值都有1/256的机会。变量将称为inInverseinReverse

如果inInverse等于255(机会为1/256),那么我们将反转颜色分数的解释。因此,白痴认为安全的那堵墙是高分的,将获得低分,因此将成为一个坏举动。缺点是,这也会影响“权利”基因,因此我们的得分将不高。此外,该inInverse物种将不得不繁殖,其子代也将获得部分优势DNA。最重要的部分是它带回了多样性。

如果inReverse等于255(机会为1/256),那么我们将颠倒颜色分数的存储位置的顺序。因此,在将颜色0存储在位0-3中之前。现在,颜色15将存储在该位置。与该inInverse方法的不同之处在于,该方法inReverse将撤消到目前为止已完成的工作。我们回到了第一广场。我们创建了一个与游戏开始时具有相似基因的物种(陷阱发现记忆除外)

通过优化,可以测试同时使用inInverse和是否明智inReverse。优化后得出的结论是分数没有增加。问题在于我们拥有更多的基因种群,但这也影响了“正确的DNA”。我们需要另一个解决方案。

白痴之战:解决方案2:哈希码

该物种有15个可能的起始位置,目前如果他从相同的起始位置开始,他将遵循完全相同的路径的可能性太大。如果他是一个热爱墙壁的白痴,他会一遍又一遍地卡在同一堵墙上。如果他幸运地成功到达了遥远的墙,他将以错误的假设开始主导DNA库。我们需要的是他的后代将走一条稍微不同的路径(因为对他而言无论如何都为时已晚),并且不会卡在遥远的墙壁上,而会卡在更近的墙壁上。这可以通过引入哈希码来实现。

一个哈希码应该有目的的唯一标识和标签电路板上的当前位置。目的不是要找出(x,y)的位置,而是要回答我的祖先以前在这个位置上遇到的问题

假设您前面有完整的电路板,并且每5 x 5单元可能的正方形制作一个jpg。您最终将获得(53-5)x(15-5)= 380张图像。让我们给这些图像编号从1到380。我们的哈希码 应被视为这样的ID,不同之处在于它不会从1到330运行,但缺少IDS,例如563、3424、9424、21245等。

unsigned long hashCode=17;
for(int x = -2; x <= 2; x++) {
    for(int y = -2; y <= 2; y++) {
        int color = v(x, y)+2;
        hashCode = hashCode*31+color;
    }
}       

质数1731在那里防止在循环开始时添加的信息消失。稍后将详细介绍如何将我们的哈希码集成到程序的其余部分。

让我们用另一种评分机制代替“看看超越了”的评分机制。当两个或三个单元具有相同的主要分数时,将有50%的机会被选为顶部单元,有50%的机会将被选为底部单元,而有0%的机会将被选为中间单元。机会不是由随机生成器确定的,而是由内存中的位确定的,因为这样可以确保在相同情况下做出相同的选择。

在理想的世界中(我们拥有无限的内存量),我们将为当前情况计算一个唯一的哈希码,例如25881,然后转到内存位置25881并在此处读取,如果我们应该选择顶部或底部的单元格(当存在是相等的分数)。这样,我们将处在完全相同的情况下(例如,当我们第二次旅行董事会并在同一位置开始时)做出相同的决定。由于我们没有无限的内存,因此我们将可用内存大小的模应用于哈希码。当前的哈希码在模运算后的分布是均匀的意义上是好的。

当后代在DNA稍有变化的情况下到达同一块板时,在大多数情况下(> 99%),他将做出完全相同的决定。但是他越走越远,他的祖先就越有机会变得与众不同。因此,他被卡在这堵遥远的墙上的机会很小。尽管他的祖先被卡在附近的同一堵墙上相对较大,但这并不算糟,因为他不会产生太多后代。如果没有哈希码方法,卡在附近和远处的墙上的机会几乎相同

优化

经过优化后,得出的结论是不需要陷阱识别表,每种颜色2位就足够了。存储器100-2x16 = 68位的其余部分用于存储哈希码。似乎哈希码机制可以避免陷阱。

我已经针对15个参数进行了优化。这段代码包含了迄今为止最好的一组调整参数:

int dnaLookup(dna_t &d, int start, int chunklen, int storageMethod,int inInverse) {
    // Definition of storageMethod: 0=decimal, 1=streak, 2=bitsum
    int score = 0;
    int streak = 0;
    for(int i = start; i < start+chunklen; i++) {
        int value = d[i];
        if (inInverse) value = (1-d[i]);            
        if (storageMethod==0) {
            score = (score << 1) |value;
        }else{
            if (storageMethod==1){
                if(value) score += ++streak; else streak = 0;
            }else{
                if(value) score ++;         
            }
        }
    };  
    return score;
}

coord_t theFittest(dna_t d, view_t v) {
    // Definition of storageMethod: 0=decimal, 1=streak, 2=bitsum
    const int colorMemStorageMethod = 2, colorMemBlockSize = 2, colorMemZeroThreshold = 0;
    const int useTrapMem = 0, trapMemStorageMethod = -1, trapMemBlockSize = -1;
    const int trapMemTopThreshold = -1, nDirBins = -1, nColorBins = -1;
    const int reorderMemStorageMethod = -1, reorderMemReverseThreshold = -1;
    const int reorderMemInverseThreshold = -1;
    // Definition of hashPrority: -1: no hash, 0:hash when 'look beyond' scores equal,
    // 1: hash replaces 'look beyond', 2: hash replaces 'trap finder' and 'look beyond'
    // 3: hash replaces everything ('color finder', 'trap finder' and 'look beyond')
    const int hashPrority = 2;
    int inReverse = reorderMemReverseThreshold != -1 && 
     (dnaLookup(d,92,8,reorderMemStorageMethod,0) >= reorderMemReverseThreshold);
    int inInverse = reorderMemInverseThreshold != -1 && 
     (dnaLookup(d,84,8,reorderMemStorageMethod,0) >= reorderMemInverseThreshold);
    int trapMemStart=N_COLORS*colorMemBlockSize;
    unsigned long hashCode=17;
    int moveUp=0;
    if (hashPrority>0){
        for(int x = -2; x <= 2; x++) {
            for(int y = -2; y <= 2; y++) {
                int color = v(x, y)+2;
                hashCode = hashCode*31+color;
            }
        }       
        unsigned long hashMemStart=N_COLORS*colorMemBlockSize;
        if (useTrapMem==1 && hashPrority<=1) hashMemStart+=nDirBins*nColorBins*trapMemBlockSize;
        if (hashPrority==3) hashMemStart=0;
        int hashMemPos = hashCode % (DNA_BITS-hashMemStart);
        moveUp = dnaLookup(d,hashMemStart+hashMemPos,1,0,inInverse);
    }

    int xBestScore=0, yBestScore=0;
    long bestScore=-1, weightMove, weightMove2, mainScore;
    for(int x = -1; x <= 1; x++) {
        if (x < 0) weightMove = 1000; // moving backward
        if (x== 0) weightMove = 10000; //moving vertical
        if (x > 0) weightMove = 100000; //moving forward
        for(int y = -1; y <= 1; y++) {          
            int color = v(x, y);
            if (inReverse) color = 15-v(x, y);
            if(color == OUT_OF_BOUNDS || (x==0&&y==0) ) continue;
            //when MoveUp=1 -> give move with highest y most points (hashScore=highest)
            //when MoveUp=0 -> give move with lowest y most points (hashScore=lowest)
            int hashScore = (y+2)*(2*moveUp-1)+4; 
            mainScore = dnaLookup(
              d,
              color*colorMemBlockSize,
              colorMemBlockSize,
              colorMemStorageMethod,
              inInverse
             );
            if (mainScore<colorMemZeroThreshold+1) {
                mainScore =  0; //not a suitable move because too low score
            }else{
                mainScore*= weightMove;
                //lookup trap likelihood
                int directionBin = 0;
                if (nDirBins==3) directionBin = x>0?y+1:-1;
                if (nDirBins==4) directionBin = x>0?y+2:0;
                // put 16 colors in nColorBins bins
                int colorBin = v(0,0)*nColorBins/N_COLORS; 
                if (inReverse) colorBin = (15-v(0,0))*nColorBins/N_COLORS; 
                colorBin = colorBin>(nColorBins-1)?(nColorBins-1):colorBin;
                if (useTrapMem && directionBin >= 0 &&
                 dnaLookup(
                   d,
                   trapMemStart+trapMemBlockSize*(nColorBins*directionBin+colorBin),
                   trapMemBlockSize,
                   trapMemStorageMethod,
                   0
                 )>=trapMemTopThreshold){
                  //suspect a trap therefore no sub score is added                  
                 }else{
                    if (hashPrority>=1){
                        mainScore+=hashScore;
                    } else{
                        // when equal score, use sub score by examining 5x5 box to rank moves
                        for(int x2 = x-1; x2 <= x+1; x2++){     
                            if (x2 < x) weightMove2 = 1; // moving backward
                            if (x2== x) weightMove2 = 10; //moving vertical
                            if (x2 > x) weightMove2 = 100; //moving forward
                            for(int y2 = x-1; y2 <= y+1; y2++){     
                                int color2 = v(x2, y2);
                                if (inReverse) color2 = 15-v(x2, y2);
                                if(color2 != OUT_OF_BOUNDS){
                                    long mainSubScore = dnaLookup(
                                      d,
                                      color2*colorMemBlockSize,
                                      colorMemBlockSize,
                                      colorMemStorageMethod,
                                      inInverse
                                    );
                                    if (mainSubScore>=colorMemZeroThreshold+1){
                                        mainScore+=mainSubScore*weightMove2;
                                    }
                                }
                            }
                        }
                    }               
                 }
            }
            if (hashPrority==2 || (useTrapMem<=0 && hashPrority>=1)) mainScore+=hashScore*10;
            if (hashPrority==3) mainScore=hashScore*weightMove;         

            if(mainScore > bestScore) {
                bestScore = mainScore;              
                xBestScore = x;
                yBestScore = y;
            }
        }
    }
    return{xBestScore,yBestScore};
}   

得分:922(2K跑步)

前50分(9场比赛仅获得1分):

112,747 3 1 1,876,965 8 57 214,921 218,707 2,512,937 114,389 336,941 1 6,915 2 219,471 74,289 31 116 133,162 1 5 633,066 166,473 515,204 1 86,744 17,360 2 190,697 1 6 122 126,399 399,045 1 4,172,168 1 169,119 4,990,398 77

这是我的第一个C ++程序。我现在和您一样拥有gnome分析的背景。我要感谢组织者,因为我真的很喜欢这项工作。

如果您有任何反馈意见,请在下面发表评论。对长篇文章表示歉意。


我发现您的陷阱分析非常有趣。

您是否尝试了另一个哈希函数,例如将25个颜色值(被视为12.5个16位字)进行异或运算并取模?我不相信素数的全等能提供更好的同质性,但是我不是什么大的数学家。

另外,您是否考虑添加路径算法?不管基因组如何,这似乎都是一个巨大的改进因素,因为它将限制只能沿着更可能导致获胜的路径测试基因组能力的移动。

kuroi,感谢您的反馈。我没有尝试过xoring,因为我不太熟悉c ++中的二进制操作。我假设您的意思是12.5个8位字?您正在使用xoring吗?
Ruut 2015年

您可以查看我的“坚信者”代码,以了解我使用哪种哈希函数。基本上,我会跳过偏离轨道的单元,并将轨道上的颜色视为16位字的高阶和低阶部分。所有这些字都与XOR一起存储在寄存器中,然后将其除以哈希表大小。只要哈希最大值(65535)远大于表大小(<100),该模就具有良好的扩展能力。我在大量随机生成的网格上进行了测试,它似乎具有很好的同质性。

6

探路者,C ++,初步得分35.8504(50发)

彻底检修!我将算法移植到C ++并进行了一些调整,但是分数仍然不是很高,这可能是因为老鼠不断将头撞到墙上。我已经厌倦了尝试改善这一点,所以现在就顺其自然。


int dnarange(dna_t &d, int start, int len) {
    int res = 0;
    for(int i = start; i < start+len; i++) {
        res = (res << 1) | d[i];
    }
    return res;
}

int dnasum(dna_t &d, int start, int len) {
    int res = 0;
    for(int i = start; i < start+len; i++) {
        res += d[i];
    }
    return res;
}

int dnaweight(dna_t &d, int start) {
    return d[start] + d[start+1] + 2*d[start+2] + 2*d[start+3] + 3*d[start+4];
}

int trap_d [16] = {1,0,1,1,0,1,-1,1,-1,0,-1,-1,0,-1,1,-1}; //immutable
int nhood [10] = {1,0,1,1,1,-1,0,1,0,-1}; //immutable

coord_t pathfinder(dna_t d, view_t v) {
  int is_trap[16] = {0};
  int pos_or_weight[16] = {0};
  int u_weight = dnaweight(d, 80);
  for (int i = 0; i < 16; i++) {
    int status = dnarange(d, 5*i, 2);
    if (status == 1) {
      is_trap[i] = 1;
      pos_or_weight[i] = dnarange(d, 5*i + 2, 3);
    } else {
      pos_or_weight[i] = dnaweight(d, 5*i);
    }
  }
  int w_area[7][4] = {0};
  for (int j = 0; j < 7; j++) {
    w_area[j][3] = u_weight;
  }
  for (int i = 0; i < 3; i++) {
    w_area[0][i] = u_weight;
    w_area[6][i] = u_weight;
  }
  int d_coeff = dnaweight(d, 85);
  for (int i = 0; i < 3; i++) {
    for (int j = 1; j < 6; j++) {
      int p_or_w, color = v(i, j-3);
      if (color != OUT_OF_BOUNDS) {
    p_or_w = pos_or_weight[color];
      } else {
    p_or_w = 1000;
      }
      if (color != OUT_OF_BOUNDS && is_trap[color] && i+trap_d[2*p_or_w] >= 0) {
    w_area[j + trap_d[2*p_or_w + 1]][i + trap_d[2*p_or_w]] += d_coeff;
      } else {
    w_area[j][i] += p_or_w;
      }
    }
  }
  for (int i = 3; i >= 0; i--) {
    for (int j = 0; j < 7; j++) {
      int min_w = 1000;
      for (int k = std::max(0, j-1); k <= std::min(6, j+1); k++) {
    min_w = std::min(min_w, w_area[k][i + 1]);
      }
      w_area[j][i] += min_w;
    }
  }
  int speed = dnasum(d, 90, 5);
  w_area[2][0] += 2 + speed;
  w_area[4][0] += 2 + speed;
  int goal = dnaweight(d, 95);
  int min_w = 10000;
  int sec_w = 10000;
  int min_x, min_y, sec_x, sec_y, w;
  for (int i = 0; i < 5; i++) {
    w = w_area[nhood[2*i + 1] + 3][nhood[2*i]];
    if (w < min_w) {
      sec_w = min_w;
      sec_x = min_x;
      sec_y = min_y;
      min_w = w;
      min_x = nhood[2*i];
      min_y = nhood[2*i + 1];
    } else if (w < sec_w) {
      sec_w = w;
      sec_x = nhood[2*i];
      sec_y = nhood[2*i + 1];
    }
  }
  if (min_w > goal) {
    int r = v.rng.rint(5);
    return {nhood[2*r], nhood[2*r+1]};
  } else if (sec_w <= goal && v.rng.rint(100) < 2*speed) {
    return {sec_x, sec_y};
  }
  return {min_x, min_y};
}

说明

总体思路是将每种颜色分类为陷阱,然后将其分配给陷阱,将权重分配给非陷阱,并尝试遵循最小权重路径到达视觉网格的右边界。

在基因组的前80位中,每种颜色均使用5位进行分类abcde。如果为ab = 01,则颜色为陷阱,并cde对其方向进行编码(八种可能性)。如果为ab ≠ 01,则该颜色不是陷阱,其权重为a + b + 2*(c + d + e)

接下来,我们初始化一个3x7的网格,该网格代表大鼠右侧的视野,并填充“未知”颜色。类似于非陷印颜色,位80-84编码未知单元的权重,而位85-89编码陷印的公共权重。我们用权重填充网格,计算最短路径,并在大鼠正上方和正下方的单元格中增加一些额外的权重(在位90-95中进行编码),以防止回避行为。95-99位编码目标权重。如果路径的最小权重低于该最小权重,则大鼠可能会卡在某处,并继续随机移动(但绝不会回溯)。否则,它将遵循最小重量路径。取决于避免回避体重的可能性很小,大鼠改为选择第二至最小体重路径。这是为了防止卡在墙壁上(但现在看来效果不佳)。


在我的计算机上运行您的实现。花了几个小时。平均得分为7.848433940863856分。pastebin.com/d50GcwnK
雅库布,2015年

@Jakube非常感谢!这比我预期的要糟糕得多,但是现在再次查看代码,我看到了一些错误和其他怪异之处。稍后我将尝试将其移植到C ++,以便我自己进行分析。
Zgarb 2015年

5

LookAheadPlayer C ++≈89.904

我最初的想法是寻找与我要寻找的颜色匹配的4位,并使用以下几位作为得分。事实证明这是一个可怕的主意,可能是因为突变。

因此,我想到了防止突变和交叉的方法,这让我想起了我在QR码解码方面所做的工作。在QR码中,数据被分成块和条带化,以避免错误破坏过多的给定数据部分。

因此,像ColorScorePlayer一样,我将DNA切成16个大块,并将其用作给定的分数。但是,分数是条带化的,因此每个分数的各个位是不相邻的。然后,我将当前可能的动作和接下来的潜在动作的得分相加,然后选择要做出的最佳动作。

注意:这是在MinGW上编码/测试的。它不会与优化或多线程一起编译。我没有实际安装Linux或使用Visual Studio方便地使用编译器的地方。明天早上我将很快对其进行测试,但是如果您遇到任何问题,请告诉我。

// get striped color score, 6 bits per color. should be
// resistant to getting erased by a crossover
void mapColorsBitwise(dna_t &d, int* color_array) {
    for (int i=0; i<N_COLORS; i++) {
        int score = 0;
        for (int j=0; j<6; j++) {
            score = (score<<1) | d[ j*N_COLORS + i ];
        }
        color_array[i] = score;
    }
}

// label for the lookup tables
enum direction_lut {
    UP_RIGHT=0, RIGHT, DOWN_RIGHT
};

// movement coord_t's to correspond to a direction
static const coord_t direction_lut[3] = {
    { 1, -1 }, { 1, 0 }, { 1, 1 }
};

// indexes into the arrays to denote what should be summed
// for each direction.
static const int sum_lut[3][6] = {
    { 3, 4, 8, 8, 9, 14 }, { 9, 13, 13, 14, 14, 19 },
    { 14, 18, 18, 19, 23, 24 }
};

coord_t lookAheadPlayer(dna_t d, view_t v) {
    int scoreArray[25] = { 0 };
    int colorScores[N_COLORS] = { };

    // Get color mapping for this iteration
    mapColorsBitwise(d, colorScores);

    for (int y=-2; y<=2; y++) {
        for (int x=0; x<=2; x++) {
            // Get the scores for our whole field of view
            color_t color = v(x,y);
            if (color != OUT_OF_BOUNDS)
                scoreArray[ (x+2)+((y+2)*5) ] += colorScores[color];
        }
    }

    // get the best move by summing all of the array indices for a particular
    // direction
    int best = RIGHT;
    int bestScore = 0;
    for (int dir=UP_RIGHT; dir<=DOWN_RIGHT; dir++) {
        if (v(direction_lut[dir].x, direction_lut[dir].y) == OUT_OF_BOUNDS)
            continue;

        int score = 0;
        for (int i=0; i<6; i++) {
            score += scoreArray[ sum_lut[dir][i] ];
        }

        if (score > bestScore) {
            bestScore = score;
            best = dir;
        }
    }

    return direction_lut[best];
}

5

SlowAndSteady C ++(得分9.7)

我们不能依靠将基因组的大块解释为数字,因为单个位翻转可以根据其位置产生根本不同的影响。这就是为什么我只使用16个6位段并对1s 的数量进行评分的原因。最初111111是好000000是坏,虽然从长远来看(一旦基因组完全进化)没关系(在DNA的初始配置中),大多数片段都有2-4个片段,所以我转而使用9 - (#1 - 3)^2评分,允许第一轮有更多的行动自由和更快的进化。

现在,我仅查看7个最近的邻居,向颜色得分添加方向偏差,并随机向最高方向之一移动。

尽管分数本身不是很高,但是我的小动物到达了终点并且在3/4的情况下分数> 1。

coord_t SlowAndSteadyPlayer(dna_t d, view_t v) {
    const int chunklen = 6;
    int color_scores[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    for(int i=0; i<16; i++){ //count ones
        for(int j=0; j<chunklen; j++){
            color_scores[i] += d[i*chunklen + j];
        }
    }

    int moves[7][2] = {
        {-1,1}, {0,1}, {1,1},
                       {1,0},
        {-1,-1},{1,-1},{-1,-1}
    };
    int movescores[7];
    int smax = -1;
    int nmax = 0;
    int best_moves[7];
    for(int m=0; m<7; m++){ //compute the score for each move
        int temp_color = v(moves[m][0], moves[m][1]);
        if(temp_color == OUT_OF_BOUNDS){
            movescores[m] = 0;
            continue;
        }
        int dir_bias[3] = {1,3,6};
        int temp_score = 9-(color_scores[temp_color]-3)*(color_scores[temp_color]-3) + dir_bias[moves[m][0]+1];
        movescores[m] = temp_score;

        if(temp_score > smax) {
            smax = temp_score;
            nmax = 0;
        }
        if(temp_score == smax) best_moves[nmax++] = m;
    }

    int best_chosen = v.rng.rint(nmax);
    return {moves[best_moves[best_chosen]][0], moves[best_moves[best_chosen]][1]};
}

并在100个木板上打分

Scores: 5 4 13028 1 1 101 2 24 1 21 1 4 2 44 1 1 24 8 2 5 1 13 10 71 2 19528 6 1 69 74587 1 1 3 138 8 4 1 1 17 23 1 2 2 50 7 7 710 6 231 1 4 3 263 4 1 6 7 20 24 11 1 25 1 63 14 1 2 2 1 27 9 7 1 7 31 20 2 17 8 176 3 1 10 13 3 142 1 9 768 64 6837 49 1 9 3 15 32 10 42 8

几何平均分数:9.76557


您是使用标准突变率还是调整后的值来提及一个板的分数?
trichoplax

“我的小动物到了终点线,并且在3/4的情况下得分> 1”我希望评分标准
能给我们带来

5

WeightChooser | C#| 得分:1520游戏中220.8262

根据可能的后续动作(黄色)的平均权重计算可能的下一动作的权重(蓝色)

using ppcggacscontroller;
using System.Linq;
using System;

public class WeightChooser
{
    public static ppcggacscontroller.Program.Coord[] cspcoords = new[] {
            new Program.Coord(1, -1),
            new Program.Coord(1, 0),
            new Program.Coord(1, 1),
        };

    const int dnaBits = 4;

    public static void move(GameLogic.IView v, GameLogic.IGenome g, Random rnd, out int ox, out int oy)
    {
        var gcrds = cspcoords.Where(c => viewVal(v, c) > -1)
            .OrderByDescending(p => getBitsSet(g, viewVal(v, p)))
            .ThenByDescending(gt => weight(v, g, gt));

        Program.Coord nextMove = gcrds.First();
        ox = nextMove.x;
        oy = nextMove.y;
    }

    private static uint getBitsSet(GameLogic.IGenome g, int vVal)
    {
        uint i = g.cutOutInt(dnaBits * vVal, dnaBits);
        i = i - ((i >> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
        return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
    }

    private static int viewVal(GameLogic.IView v, Program.Coord c)
    {
        return v[c.x, c.y];
    }

    private static double weight(GameLogic.IView v, GameLogic.IGenome g, Program.Coord toGo)
    {
        double w = 0;

        int y = (toGo.y + v.yd) - 1;
        int i = 0;
        for (; i <= 2; i++)
        {
            int field = v[toGo.x + 1, (y + i) - v.yd];
            if (field > -1)
                w += getBitsSet(g, field);
        }

        return w / i;
    }
}

Scores: 32, 56103, 1361, 3351446, 33027, 23618, 22481, 1172713, 1, 3, 1, 1, 1, 2 88584, 106357, 1, 1232, 1, 1651280, 16690, 1, 1, 23732, 207554, 53, 69424, 1, 1,  79361, 1, 1, 51813, 229624, 25099, 2, 1, 234239, 362531, 1, 1, 19, 7295, 1, 7, 2, 196672, 1654208, 73453, 1, 23082, 1, 8, 5, 1685018, 4, 20, 1, 1, 1, 1, 1, 144 671, 122309, 10, 94752, 100895, 1, 54787, 54315, 252911, 79277, 1159, 241927, 94 347, 1, 318372, 37793, 1, 1, 1345310, 18934, 169700, 1, 1, 3, 186740, 83018, 121 758, 1, 358, 1935741, 88, 1, 1, 1, 1, 7, 21, 51144, 2, 1, 267638, 1, 1, 3, 1, 1,  1, 1, 674080, 47211, 8879, 7, 222766, 67214, 2, 89, 21038, 178463, 92846, 3, 14 0836, 1, 1, 111927, 1, 92165, 1, 192394, 1, 1, 2563722, 1, 42648, 1, 16, 1, 1, 2 85665, 1, 212653, 1, 4, 20513, 3, 135118, 13161, 2, 57, 78355, 3, 3, 44674, 8, 1 , 226472, 1, 1, 31588, 19619, 1, 2931870, 60814, 1, 1, 33867, 60740, 20558, 1, 1 5, 3, 5, 1, 1, 1, 60737, 450636, 468362, 1, 1, 347193, 91248, 551642, 1, 427215,  1, 57859, 17, 15, 66577, 24192, 1, 63560, 6568, 40279, 68216, 23098, 180732, 1,  1, 3041253, 1, 253488, 60535, 1, 1, 150838, 7361, 72855, 290699, 104644, 1, 763 01, 378, 1, 89220, 1, 262257, 2, 2, 1, 117, 105478, 33, 1, 65210, 1, 117588, 1, 1, 24320, 12, 3714568, 81152, 1, 1, 10125, 2, 1, 22, 1, 45201, 1, 1, 10518, 1, 1 , 1, 1, 34, 210021, 1, 1, 1, 65641, 6, 72, 1, 7, 2, 161578, 1, 1, 38378, 1, 4113 741, 1, 34450, 244212, 127660, 1, 256885, 46, 2, 1, 1, 103532, 1, 503965, 114774 , 52450, 124165, 73476, 50250, 1, 3, 3755352, 24928, 1, 1, 51, 11, 1, 210580, 1,  62375, 1, 1, 92745, 341232, 167675, 86, 242, 293710, 454841, 1, 49840, 4456758,  121378, 145323, 74904, 5048, 25459, 1, 57, 116999, 1, 1, 76074, 111447, 95706, 1, 1, 52631, 166756, 2159474, 161216, 1, 2, 3, 11904, 1, 22050, 6, 1, 1, 1, 41, 48908, 6, 80878, 28125, 28, 160516, 1, 4, 1, 8, 1, 1, 7, 362724, 1, 397193, 1, 2 5, 1, 59926, 3, 74548, 2320284, 470189, 1, 108, 1, 1, 16, 1, 496013, 1, 1, 1, 1,  107758, 1, 284144, 146728, 1, 70769, 94215, 1, 1, 9961, 97300, 7, 1, 76263, 1, 27, 294046, 40, 8, 2, 1, 57796, 2, 79800, 1043488, 470547, 1, 1, 1, 6, 69666, 8,  1, 1, 344011, 205325, 3963186, 1141527, 61598, 446029, 1, 1, 1, 1, 625247, 1877 92, 136391, 1, 72519, 1, 141168, 412, 98491, 103995, 297052, 1, 1, 1, 1, 3, 17, 9, 62899, 5, 47810, 254, 26789, 2, 1, 1, 3, 10361, 19615, 40430, 17288, 3, 71831 , 41374, 1, 91317, 409526, 1, 184305, 1, 192552, 3, 3587674, 39, 13, 134500, 41,  42, 672, 559835, 9, 39004, 51452, 1, 1, 12293, 11544, 265766, 8590, 1, 8632, 1,  1, 61849, 35155, 1, 74798, 72773, 1, 89, 37, 4, 4405882, 1, 99, 44397, 5, 4, 6,  1, 1, 1, 515818, 78383, 20, 127829, 1824801, 157, 1, 1, 268561, 19, 2, 230922, 1, 103, 98146, 5029789, 304324, 1, 5, 60516, 1, 139, 28982, 7, 20755, 187083, 1,  1, 143811, 37697, 1, 1, 269819, 83, 1, 202860, 13793, 16438, 113432, 1, 1, 2, 5 134384, 29, 84135, 39035, 2, 125, 1, 30, 129771, 41982, 13548, 61, 1, 2, 1, 82, 102, 2, 105581, 210399, 291204, 3012324, 1, 84763, 1, 1, 442067, 2, 1, 1, 1, 116 , 1, 3, 3, 56, 208807, 1, 2, 1, 14, 29, 31286, 1, 1, 162358, 28856, 46898, 1, 16 2698, 1, 1, 1, 65, 1, 1, 234566, 6, 1, 1, 128, 124, 2167692, 181946, 29, 1, 1, 1 , 1, 17, 162550, 179588, 4, 226480, 28, 1, 158512, 35084, 1, 26160, 17566, 1, 81 826, 2, 33, 1, 1, 11, 1, 230113, 1, 1, 1, 24405, 17, 1, 2, 1, 162365, 2, 1, 1, 8 5225, 1, 15016, 51509, 1, 5, 1, 93, 13, 59, 24548, 1, 3, 2, 2, 1, 64424, 1, 1, 4 , 1, 1, 1, 2, 267115, 139478, 52653, 96225, 1, 1, 35768, 3, 1, 1, 3280017, 8, 80 014, 43095, 112102, 1, 1, 1, 79594, 5, 1, 1, 4, 455714, 19, 15, 1, 233760, 55850 5, 2, 2, 1, 63672, 1, 3732951, 1, 135858, 134256, 452456, 151573, 79057, 638215,  88820, 1, 1, 76517, 13, 314006, 5, 1, 17704, 1, 79589, 1, 18371, 530793, 59020,  1, 1, 1, 4, 1, 1, 1, 71735, 1, 1, 1, 1, 1, 37894, 1, 2, 24054, 1, 8, 26471, 34,  1, 48033, 5, 3, 1, 25, 101, 1, 1, 5, 1, 1, 1, 97521, 1, 682817, 286486, 5, 1472 4, 1, 7805226, 6, 1, 1, 1, 7, 2, 1, 1, 1, 25, 233330, 1, 20899, 3417337, 92793, 23, 80821, 1, 1, 115948, 264191, 3, 79809, 1, 2, 59531, 2, 1, 1, 28684, 97, 1, 2 69433, 98769, 1, 76608, 138124, 1, 1, 325554, 122567, 1, 1, 3, 689604, 4, 85823,  66911, 138091, 169416, 21430, 1, 2, 486654, 108446, 93072, 1, 67907, 4, 1, 1, 5 2260, 67867, 210496, 25157, 1, 1, 1, 5477, 2, 2, 11907, 106, 48404, 1, 1, 1, 787 11, 190304, 112025, 1, 9313, 143055, 40189, 315537, 157581, 70714, 6, 180600, 38 594, 103658, 59444, 7, 31575, 1, 1, 581388, 370430, 1, 114446, 1, 1, 2, 3968, 1,  1, 1, 1, 1, 4523411, 1, 1, 270442, 1, 59, 235631, 3, 110196, 9, 1, 93724, 1, 22 917, 1, 6, 1, 2350266, 1, 1, 20, 4686858, 31, 1, 240180, 10, 470592, 3, 61051, 1 45372, 2831, 64052, 10, 120652, 255971, 479239, 1, 387659, 1, 1, 1, 378379, 7, 3 3218, 55914, 1, 1, 1667456, 6, 2, 74428, 3, 2, 1, 121582, 121274, 19651, 59899, 1, 11, 406670, 137835, 100269, 2, 164361, 98762, 44311, 25817, 178053, 31576, 1,  8, 2539307, 121430, 1, 41001, 1, 4, 1, 116258, 91101, 1, 126857, 1, 8, 49503, 1 , 489979, 12, 500332, 1, 52, 4, 8786, 4, 4878652, 12354, 27480, 89115, 87560, 11 793, 5, 1, 4702325, 301188, 1, 1, 1, 1, 1, 416520, 49357, 230103, 24497, 1, 3, 2 , 57366, 183021, 1, 1, 1, 1, 1, 2, 2, 2546229, 1, 2, 38665, 1, 6903, 1, 89519, 9 5119, 64879, 1, 1, 160380, 474336, 3107, 1, 7, 29099, 28667, 3, 196933, 35979, 1 2924, 7, 1, 99885, 6, 1, 1, 1, 7, 1, 1, 1, 1, 65727, 1, 1, 1, 1, 2108110, 3, 107 811, 23818, 701905, 1, 156034, 32, 1, 29, 143548, 1, 67665, 4612762, 1, 3, 20, 1 , 1, 9, 28543, 1, 1, 1, 30978, 9, 1, 19504, 79412, 15375, 763265, 1, 352373, 193 045, 1, 4570217, 9, 1, 6, 29180, 90030, 1, 1, 1, 1, 1, 93, 1, 100889, 1, 1, 37, 15, 17, 1, 81184, 1, 2, 272831, 1, 137, 1, 9, 42874, 679183, 1, 350027, 12, 1, 2 , 1, 26408, 1, 11182, 1, 30, 139590, 7, 3, 1, 1, 34729, 1, 2, 1, 1, 50343, 66873 , 3891, 1, 148952, 1, 1, 22322, 104176, 1, 3, 20549, 140266, 37827, 30504, 17, 6 8588, 120195, 1, 123353, 2, 64301, 11, 1, 109867, 4, 1, 1, 1, 28671, 1, 50963, 5 4584, 1, 1, 1, 33, 1, 381918, 1, 265823, 4771840, 155179, 314, 134086, 1, 1, 30,  1, 2, 1102665, 18, 132243, 3861, 1, 1, 208906, 60112, 1, 1, 1, 31273, 551, 3490 0, 2, 43606, 1, 1, 1, 1, 5, 2, 88342, 2, 1, 19, 3, 1, 1, 1, 1, 28507, 1, 491467,  1, 1, 22, 1, 1, 1, 1, 9345, 9, 18, 84343, 1, 2, 1, 18, 36816, 1, 1, 513028, 287 88, 5037383, 721932, 170292, 108942, 539115, 1, 575676, 20, 1, 31698, 99797, 205 21, 380986, 1, 1, 14, 2, 1, 201100, 30, 1, 119484, 1, 1, 1, 1, 2214252, 3, 4, 18 179, 9, 4, 542150, 1, 6, 157, 3182099, 4, 1, 1, 6140, 3339847, 498283, 52523, 1,  1, 1, 1, 1, 202054, 263324, 1, 6, 2, 1, 2, 72357, 12, 5, 66, 4, 7368, 1, 30706,  61936, 3945270, 138991, 1, 68247, 1, 1, 30482, 35326, 1, 1, 9, 1, 148, 1, 46985 , 1, 4325093, 1, 1, 2880384, 65173, 1, 56581, 179178, 372369, 56187, 3, 12, 8, 4 00743, 3, 28658, 1, 1, 9, 1, 4, 2, 34357, 1, 42596, 68840, 2, 62638, 158027, 617 34, 71263, 1, 1, 9, 1, 6830309, 3, 1, 1, 157253, 129837, 9, 5008187, 48499, 5981 3, 1, 40320, 233893, 5, 1383, 7732178, 16, 1, 13, 5686145, 84554, 1, 79442, 1, 1 , 256812, 127818, 31, 226113, 1, 4, 1, 1, 4506163, 1, 4, 1, 40176, 19107, 205, 2 7, 1, 448999, 1, 1, 2750, 62723, 1, 12, 1, 1, 79881, 1, 48, 13, 4, 1, 28765, 1, 33, 291330, 30817, 2, 1, 1, 1, 4170949, 16, 1, 1, 118781, 10473, 520797, 1, 8, 1 , 80215, 1, 21759, 5143209, 79141, 40229, 1, 17403, 71680, 1115694, 1, 1, 1, 10,  1, 77149, 382712, 1, 11, 84891, 47633, 1, 2, 39037, 1, 213148, 1607280, 127674,  1, 333207, 1, 78901, 1, 16203, 87580, 1, 1565571, 537902, 53000, 15, 1, 2, 1, 2 13127, 1, 338634, 2469990, 469479, 9519, 51083, 1, 42082, 33179, 1, 1, 32444, 3,  1, 201642, 99724, 377, 1, 2, 1, 36919, 1, 322707, 2, 164765, 82516, 1, 5274643,  1, 36421, 1, 8, 1, 117856, 1, 1, 493342, 1, 36289, 7, 1, 62, 2, 1, 38533, 1, 68 , 45754, 9, 102015, 312941, 1, 99 
Final score is 220.826222910756

5

行动中的大鼠(不是答案,而是C ++机器人的图形工具)

自从开始挑战以来,我一直很难弄清楚老鼠在赛道上真正面对的是什么。
最后,我入侵了控制器并编写了一个辅助工具,以获取轨道的一些图形表示。
最终,我进行了一些进一步的修改,并添加了可视化模型,以显示给定大鼠DNA的可能路径。

该地图非常混乱,需要一些习惯,但是我发现了解我的机器人的工作原理很有帮助。

这是一个例子:

样本轨道

您可能需要放大才能看到任何内容,因此这里只是前半部分:

半轨(无双关语)

首先,让我们看一下老鼠的路径。每个可能的起始位置都有一条路径(通常为15条,有时会少一些)。通常他们倾向于合并,理想情况下会导致单个胜利位置。

路径由大的直箭头表示。颜色描述了结果:

  • 绿色:获胜
  • 黄色:无限循环
  • 棕色:撞墙
  • 红色:不幸的事故

在该示例中,我们有12个获胜的起始位置,一个导致无限循环,两个导致残酷的死亡(正如图所示被传送到陷阱中)。

路径不连续性是由于隐形传态引起的,您可以跟随相应的弯曲箭头。

现在为彩色符号。它们代表了16种颜色的含义(灰色代表大鼠的视线)。

  • 墙:正方形
  • 传送器:4颗分支星
  • 陷阱检测器:小八角形

空的颜色是...好...是空的。

传送者的箭矢指向目的地。

陷阱检测器还具有指示陷阱的箭头,该箭头标记为红色圆圈。
在9种情况中,一种情况是陷阱与检测器位于同一单元中,在这种情况下,您会在红色圆圈上方看到小的八角形。

在此示例中,浅黄色陷阱就是这种情况。
您还可以看到淡紫色陷阱检测器指向其指示的陷阱。

请注意,有时陷阱的红色圆圈会藏在墙下。两者都是致命的,因此在隐形传送的情况下结果是相同的。
还要注意,陷阱可能位​​于传送器上,在这种情况下,传送器具有优先权(即,老鼠在掉入陷阱中之前被传送了,实际上使陷阱无效了)。

最后,灰色符号代表我的老鼠所见(即它们的基因组属性归于颜色的含义)。

  • 墙:正方形
  • 陷阱检测器:八角形
  • 陷阱:X

基本上,所有位于灰色方块上的细胞都被老鼠视为墙壁。
大X代表被视为陷阱的单元格,相应的八进制表示报告它们的检测器。

在此示例中,两面墙都是这样标识的,浅黄色陷阱也是如此(指示确实是致命的细胞,因此将其表示为墙是正确的)。
淡紫色陷阱检测器已被识别为这种颜色(位于灰色八角形上),但是陷阱位置不正确(您可以看到一些红色圆圈下方没有交叉)。

在4个传送器中,有2个被视为墙壁(青绿色和棕褐色),有2个被视为空单元(红色和淡黄色)。

一些空单元被视为陷阱检测器或壁。仔细观察,您会发现这些“故障检测器”的确禁止进入会使老鼠陷入困境的细胞,因此,即使它们无法匹配真实的颜色,也具有明确的目的。

编码

嗯,这是一团糟,但是效果很好。

从播放器的代码看,我仅添加了一个接口:用于报告给定DNA含义的跟踪函数。在我的情况下,我使用了3种类型(壁,陷阱检测器和空白),但是您基本上可以输出任何与颜色相关的东西(如果您不希望与基因组相关的图形,则什么也不会输出)。

我破解了控制器,生成了一个巨大的字符串,将轨迹和颜色描述与来自所有可能位置的大鼠DNA的“空转”进行了对照。

这意味着只有当漫游器不使用随机值时,结果才会真正有意义。否则,显示的路径将仅代表一种可能的结果。

最后,将所有这些跟踪信息放入一个大文本文件中,然后由生成图形输出的PHP实用程序读取。

在当前版本中,每次达到新的最大适应度后,每只大鼠死亡都拍摄一张快照(这很好地显示了基因组的逐步完善,不需要太多快照),而在游戏结束时拍摄了最后一张快照(显示最成功的DNA)。

如果有人感兴趣,我可以发布代码。

显然,这仅适用于C ++机器人,如果要显示一些特定于基因组的数据(本例为灰色数字),则需要编写跟踪函数可能修改PHP代码。
即使没有特定于DNA的信息,您也可以毫不费力地在给定的地图上看到DNA遵循的路径。

为什么要中间输出?

首先,C ++没有可说的可移植图形库,尤其是在使用MSVC时。即使通常可以使用Win32构建,也常常是事后才想到的,而所需的外部库,程序包和其他类似unix的组件的数量,使得编写快速,简单的图形应用程序成为人身体上无法承受的痛苦。是我的名字。

我考虑使用Qt(关于唯一的环境,它使C ++中的可移植GUI /图形开发成​​为简单甚至令人愉悦的任务,恕我直言-可能是因为它添加了一个消息传递系统à目标C,而C ++却非常缺乏,并且在限制内存方面做得非常出色管理到最低限度),但这似乎对手头的任务来说是一个过大的选择(任何想使用代码的人都必须安装笨拙的SDK-我猜这几乎不值得付出努力)。

即使假设是一个可移植的库,也没有速度要求可言(一秒钟左右的图像生成就足够了),而且由于其众所周知的刚性和固有的混乱性,C ++当然不是最佳的工具。

此外,具有中间文本输出可增加很多灵活性。一旦数据存在,您就可以将其用于其他目的(例如,分析机器人的性能)。

为什么选择PHP?

我发现该语言极其简单和适应性强,非常适合原型制作。我将它作为我的宠物语言来应对不需要极端性能的代码挑战。
虽然这是打高尔夫球的糟糕语言,但是无论如何我从来都不喜欢打高尔夫球。

我想python或Ruby可以用于相同的目的,但是我从来没有机会对它们进行过认真的工作,而且我最近在网站上工作,所以是PHP。

即使您不懂该语言,也可以很轻松地修改代码以适合您的需求。只是不要忘记$变量之前的s,就像旧的Basic日子一样:)。


1
您能否分享您的工具?我在您的答案中看不到代码或链接。
Franky

5

SkyWalker-Python-在50场比赛中得分不到231

因此,请先编写代码,然后再进行一些解释。我希望复制时没有任何问题。

class SkyWalker(Player):
    def __init__(self):
        Player.__init__(self)
        self.coords = [#Coordinate(-1,-1),
                       #Coordinate( 0,-1),
                       Coordinate( 1, 0),
                       Coordinate( 1,-1),
                       #Coordinate(-1, 0),
                       #Coordinate( 0, 0),
                       #Coordinate(-1, 1),
                       #Coordinate( 0, 1),
                       Coordinate( 1, 1)]

        self.n_moves = len(self.coords)

    def visionToMove(self, x, y):
        x = x - 2
        y = y - 2

        return (x, y)

    def trapToMove(self, x, y, offx, offy):
        x = x - 2 + (offx % 3) - 1
        y = y - 2 + (offy % 3) - 1
        return (x, y)

    def isNeighbour(self, x1, y1, x2, y2):
        if (x1 == x2) or (x1+1 == x2) or (x2+1 == x1):
            if (y1 == y2) or (y1+1 == y2) or (y2+1 == y1):
                return True
        return False

    def calcMove(self, donots, never, up):
        forwards = {(1, 0): 0, (1, 1): 0, (1, -1): 0, (0, 1): 10, (0, -1): 10}

        for key in forwards:
            if key in never:
                forwards[key] = 100
            for x in donots:
                if (key[0] == x[0]) and (key[1] == x[1]):
                    forwards[key] = 20

        min_value = min(forwards.itervalues())
        min_keys = [k for k in forwards if forwards[k] == min_value]

        return random.choice(min_keys)

    def turn(self):
        trap1 = self.bit_chunk(0, 4)
        trap1_offsetx = self.bit_chunk(4, 2)
        trap1_offsety = self.bit_chunk(6, 2)
        trap2 = self.bit_chunk(8, 4)
        trap2_offsetx = self.bit_chunk(12, 2)
        trap2_offsety = self.bit_chunk(14, 2)
        wall1 = self.bit_chunk(16, 4)
        wall2 = self.bit_chunk(20, 4)
        tel1 = self.bit_chunk(24, 4)
        tel1_good = self.bit_chunk(28, 3)
        tel2 = self.bit_chunk(31, 4)
        tel2_good = self.bit_chunk(35, 3)
        tel3 = self.bit_chunk(38, 4)
        tel3_good = self.bit_chunk(42, 3)
        tel4 = self.bit_chunk(45, 4)
        tel4_good = self.bit_chunk(49, 3)
        up = self.bit_at(100)

        donots = []
        never = []

        for y in range(0, 5):
            for x in range(0, 5):
                c = self.vision[y][x]
                if (c == -1):
                    never += self.visionToMove(x, y),
                elif (c == trap1):
                    donots += self.trapToMove(x, y, trap1_offsetx, trap1_offsety),
                elif (c == trap2):
                    donots += self.trapToMove(x, y, trap2_offsetx, trap2_offsety),
                elif (c == wall1):
                    donots += self.visionToMove(x, y),
                elif (c == wall2):
                    donots += self.visionToMove(x, y),
                elif (c == tel1):
                    if (tel1_good > 3):
                        donots += self.visionToMove(x, y),
                elif (c == tel2):
                    if (tel2_good > 3):
                        donots += self.visionToMove(x, y),
                elif (c == tel3):
                    if (tel3_good > 3):
                        donots += self.visionToMove(x, y),
                elif (c == tel4):
                    if (tel4_good > 3):
                        donots += self.visionToMove(x, y),

        coord = self.calcMove(donots, never, up)

        return Coordinate(coord[0], coord[1])

一些解释

在我看来,主要区别在于我不会对每种颜色进行编码。相反,我尝试保存重要颜色的数量。我认为这些颜色是陷阱,墙壁和传送器。标本不需要知道好细胞的颜色。因此,我的基因组是按以下方式构造的。

  • 2 x 8位用于陷印,前4位是色号,其他4位是偏移量
  • 2 x 4位的墙壁,只是颜色
  • 传送器为4 x 7位,颜色再次为4位,由3位决定好坏

这总共使用了52位。但是,我只使用3个传送器决策程序的第一位(我检查数字是否大于3)。因此,其他2个可以删除,只剩下44个位。

每次转动时,我都会检查视野中的每个视野是否是一种不好的颜色(+外板-1),然后将其添加到标本不想移动的视野列表中。对于陷印,我添加了该陷印颜色的已保存偏移量上的字段。

根据这些不良字段的列表,可以计算出下一步。首选字段的顺序为:

  1. 向前
  2. 上或下
  3. 向后或向下
  4. 向后

如果类别的两个字段适用,则随机选择一个。

结果

Individual scores: [192, 53116, 5, 1649, 49, 2737, 35, 5836, 3, 10173, 4604, 22456, 21331, 445, 419, 2, 1, 90, 25842, 2, 712, 4, 1, 14, 35159, 13, 5938, 670, 78, 455, 45, 18, 6, 20095, 1784, 2, 11, 307853, 58171, 348, 2, 4, 190, 7, 29392, 15, 1158, 24549, 7409, 1]
On average, your bot got 231.34522696 points

思想

  • 我不知道,如果我幸运地参加了50次比赛,或者我的策略中确实有一些智慧。

  • 我的跑步似乎从未起飞并获得超高分,但他们也往往至少找到目标的几倍

  • 一些小的随机性很好,不要在比赛快结束的某些地方被困在陷阱中

  • 我认为非特殊颜色从不坏。但是,当它们处于陷阱的偏移量时,它们的实例可能很糟糕。因此,如果没有陷阱,墙壁或坏的传送器,则将颜色标记为坏是没有意义的。

  • 城墙是最大的敌人

改进之处

首先,即使我会错过看到黑色方块越来越接近目标的情况,也需要C ++端口来进行更多测试并获得更有意义的结果。

主要问题之一是,如果在大鼠前面有坏细胞(或标本认为不好的细胞),则很容易开始在圆圈中上下移动。在这种情况下,可以通过向前看2步来阻止或减少这种情况,以防止其移至将再次向后移动的区域。

拥有好基因的老鼠通常需要相当长的时间才能达到目标并开始传播其基因。在这些情况下,也许我需要一些策略来增加多样性。

由于难以估计隐形传讯者,也许我应该将人群划分为那些冒险且总是选择优秀的隐形传讯者和更关心的事物,并且只有在没有其他选择的情况下才采用。

我应该以某种方式使用基因组的后半部分。


我也尝试存储颜色,但最后得出结论,它不起作用,因为您会得到双打。例如,如果self.bit_chunk(16, 4)self.bit_chunk(20, 4)都具有两个值,则0010您实际上仅存储了有关两个陷阱之一的信息。
Ruut 2015年

我需要在一行中添加缩进以使其运行-我猜它在复制和粘贴过程中丢失了。我现在也已将其添加到您的代码中。
trichoplax

对于任何人都希望运行此:它运行在Python 2,并且可以在Python 3通过改变单个事件运行itervaluesvalues
trichoplax

我得到以下结果:[6155、133、21、12194、8824、3、3171、112、111425、3026、1303、9130、2680、212、28、753、2923、1、1、4140、107、1256 ,90,11,104,1538,63,917,8,1,709,11,304,212,2,43,5,4,206,8259,75,28,7,1,11,5,1 ,1244、1398、13]几何平均值122.9220309940335
trichoplax

看来我们需要运行50多个游戏才能获得可靠的成绩。
trichoplax'2

3

Python,NeighborsOfNeighbors,分数= 259.84395超过100场比赛

这是ColorScorePlayer的变体。每6位存储一个正方形的质量得分。当机器人进行移动时,它会在3个前向方格中的每一个上得分-对角线向上,向前和对角线向下。得分是正方形的质量加上接下来3个正方形的平均质量的一半。这使机器人在不影响第一个方块的质量的情况下具有前瞻性。该算法类似于LookAheadPlayer,在编写此解决方案之前我没有看到它。

class NeighborsOfNeighbors(Player):
  def __init__(self):
    Player.__init__(self)
    self.coords = [ Coordinate( 1, 0),
                    Coordinate( 1,-1),
                    Coordinate( 1, 1)
                    ]

  def turn(self):
    scores=[self.score(c.x,c.y)+0.5*self.adjacentScore(c.x,c.y) if self.vision_at(c.x,c.y)>-1 else None for c in self.coords ]
    max_score = max(scores)
    return random.choice( [c for s,c in zip(scores,self.coords) if s==max_score] )

  def adjacentScore(self,x,y):
    adjacent = [(x+1,y)]
    if self.vision_at(x,y+1)>-1:
      adjacent+=[(x+1,y+1)]
    if self.vision_at(x,y-1)>-1:
      adjacent+=[(x+1,y-1)]
    adjscores=[self.score(a,b) for a,b in adjacent]
    return sum(adjscores)/float(len(adjscores))

  def score(self,x,y):
    return -1 if self.vision_at(x,y) == -1 else self.bit_chunk(6*self.vision_at(x,y),6)

一行上没有缩进。我猜它在粘贴时迷路了。我已添加它
。– trichoplax

在python 3中运行时,它抱怨在计算max(scores)时比较None。因此,我更改else Noneelse 0上一行来计算您的分数。希望您的逻辑保持不变(除了添加丢失的缩进之外,我在SE上未对您的代码进行任何更改)。
trichoplax

在python 3中运行时,此答案的得分如下:[1、13085、360102、1、73713、1、189、1、1、193613、34、195718、199、8、1、1、60006、66453, 2,2,53,425206,1,4,1,1,16,153556,1,18134,35655,1,4211684,2,1,26451,8,1,1,724635,69242,38469,796553,111340, 1,25,40017,76064,66478,209365,3925393]
trichoplax

428.3750848244933的几何平均值
trichoplax

2

ROUS(异常大小的啮齿动物),Java,得分= 0

这会散布周围环境以决定要去的地方。 由于Java控制器无法正常工作,我对此没有评分。如果它找到一些传送器来帮助它的话,这将变得非常遥远。这往往会消失并偶尔使控制器崩溃。这可能是由于自然环境是“火沼泽”。

import java.awt.*;
import java.util.Map;

public class ROUS extends Player{

    private static final int NUMBER_OF_GENES = 33;
    private static final int GENE_SIZE = 3;
    private static final Point[] coords = new Point[]{
        new Point(-1, -1),
        new Point(-1, 0),
        new Point(-1, 1),
        new Point(0, -1),
        new Point(0, 1),
        new Point(1, -1),
        new Point(1, 0),
        new Point(1, 1)
    };

    public Point takeTurn(String dna, Map<Point, Integer> vision){
        Point[] table = decode(dna);
        int hash = hash(vision);
        return table[hash];
    }

    private int hash(Map<Point, Integer> surroundings) {
        return Math.abs(surroundings.hashCode()) % NUMBER_OF_GENES;
    }

    private Point[] decode(String dna) {
        Point[] result = new Point[NUMBER_OF_GENES];

        for (int i = 0; i < NUMBER_OF_GENES; i++){
            int p = Integer.parseInt(dna.substring(i * GENE_SIZE, (i + 1) * GENE_SIZE), 2);
            int x;
            int y;

            result[i] = coords[p];
        }
        return result;
    }
}

1
Java控制器现在正在工作。
马丁·恩德

3
起初,我以为您是向古老的俄罗斯致敬,但看起来是向罗伯·赖纳(Rob Reiner)致敬。

最低可能的分数是1
trichoplax

@trichoplax ...崩溃了控制器...
TheNumberOne 2015年

哦,我明白了-这样的情况经常发生,以至于您无法达到运行的终点?
trichoplax

2

灰色前瞻(C ++,〜1.35)

这个人的平均表现不佳,但是在极少数情况下,它的表现出色。不幸的是,我们的得分是几何平均分(1.35),而不是最高分(20077)。

该算法仅通过使用4位灰度代码将每种颜色的分数映射到-2到2的某个位置(偏向范围[-1..1]),并计算每个动作的图块及其下一个动作的分数。它还使用2位格雷码来确定图块本身的乘数以及向右移动的偏置因子。(尽管灰色代码实际上对中间代码点交叉没有任何帮助,但是灰色代码不太容易因突变而引起较大的跳跃。)

它也完全没有采取任何措施来专门处理陷阱,而且我怀疑这可能是失败的原因(尽管我没有向控制器添加任何工具来测试该理论)。

对于每个可能的动作,它都确定一个得分,并且在所有得分最高的动作中,它是随机选择的。

coord_t colorTileRanker(dna_t d, view_t v) {
    const int COLOR_OFFSET = 0; // scores for each color (4 bits each)
    const int SELF_MUL_OFFSET = 96; // 2 bits for self-color multiplier
    const int MOVE_MUL_OFFSET = 98; // 2 bits for move-forward multiplier

    static const int gray2[4] = {0, 1, 3, 2};
    static const int gray3[8] = {0, 1, 3, 2, 7, 6, 4, 5};

    // bias factor table
    const int factorTable[4] = {0, 1, 2, 1};

    const int selfMul = factorTable[gray2[dnaRange(d, SELF_MUL_OFFSET, 2)]]*2 + 9;
    const int moveMul = factorTable[gray2[dnaRange(d, MOVE_MUL_OFFSET, 2)]] + 1;

    // scoring table for the color scores
    static const int scoreValue[8] = {0, 1, 2, 3, 4, 3, 2, 1};

    std::vector<coord_t> bestMoves;
    int bestScore = 0;

    for (int x = -1; x <= 1; x++) {
        for (int y = -1; y <= -1; y++) {
            const int color = v(x, y);
            if ((x || y) && (color >= 0)) {
                int score = 0;

                // score for the square itself
                score += selfMul*(scoreValue[gray3[dnaRange(d, COLOR_OFFSET + color*3, 3)]] - 2);

                // score for making forward progress;
                score += moveMul*(x + 1);

                // score for the resulting square's surrounding tiles
                for (int a = -1; a <= 1; a++) {
                    for (int b = -1; b <= 1; b++) {
                        const int color2 = v(x + a, y + b);
                        if (color2 >= 0) {
                            score += scoreValue[gray3[dnaRange(d, COLOR_OFFSET + color2*3, 3)]] - 2;
                        }
                    }
                }

                if (score > bestScore) {
                    bestMoves.clear();
                    bestScore = score;
                }
                if (score >= bestScore) {
                    bestMoves.push_back({x, y});
                }
            }
        }
    }

    if (bestMoves.empty()) {
        return {v.rng.rint(2), v.rng.rint(3) - 1};
    }
    return bestMoves[v.rng.rint(bestMoves.size())];
}

在最近一次跑步中,我得到了成绩:1 1 1 1 1 1 1 1 46 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 20077 1 1 1 2 1 1 1 1 1

我希望我能得到更多的20077s和更少的1s。:)


1
使用格雷码是格雷特的主意!;)
matovitch 2015年

1
格雷码为+1。但是,具有完全突变弹性的基因组会极大地损害多样性。顺便说一句,分数20.000甚至没有达到您可以达到的最高水平。如果某只老鼠进化出从任何可能的起始位置开始追踪的能力,那么它实际上就是不朽的,并会获得巨大的适合度。它的基因组很快占主导地位,从而导致多达近5万只大鼠和数百万人的分数。

2

C ++,TripleScore,得分:100〜400

首先,我的分数在多次运行中差异很大(主要是因为1的数目)。

核心计算5个方向的分数:向上,向下,向前向上,向前和向前向下。首先,计算上下得分,然后将结果与固定值进行比较。如果停留在原处比向上或向下移动更好,则不会选择这些方向(因此必须向前移动)。这是为了防止在两个点之间跳动(向上,向下,向上,向下...)。

现在,对其他3个方向进行了评分:前进,前进和后退。从所有调查的方向中保留得分最高的方向,并随机选择其中1个。

评分方向:TripleScore使用3个子评分来计算动作的得分:

  • 目标颜色的分数(取决于dna,如colorScorePlayer中所示)
  • 前进的分数(取决于dna)
  • 从目的地向前移动的最大分数(乘以存储在dna中的因子)

与其他答案一样,分数很大程度上取决于返回的1分数的数量。

#define CHUNKSIZE 5 //We have 20 values so 5 bits/value
#define MAXVALUE 32 //2^CHUNKSIZE
#define AVGVALUE MAXVALUE/2

#define DNASEGMENT(dna, i) dnarange(dna, i*CHUNKSIZE, CHUNKSIZE)
#define DNA_COLOR 0
#define DNA_FORWARD 16
#define DNA_LOOKAHEAD 17

//Get the score for a specific move
int calcscore(dna_t dna, view_t view, int x, int y, bool final){
  if (view(x,y) == OUT_OF_BOUNDS){
    //We cant go there
    return -MAXVALUE;
  }
  //The score of the color
  int s = DNASEGMENT(dna, DNA_COLOR+view(x,y))-AVGVALUE;
  //The score of going forward
  s += x*DNASEGMENT(dna, DNA_FORWARD);

  //Get the children or not
  if (!final){
    int max=-MAXVALUE;
    int v;
    //Get the maximum score of the children
    for (int i=-1; i<2; ++i){
        v = calcscore(dna, view, x+1, y+i, true);
        if (v>max){
            max=v;
        }
    }
    //Apply dna factor to the childs score
    s += (max * DNASEGMENT(dna, DNA_LOOKAHEAD))/AVGVALUE;
  }
  return s;
}

coord_t TripleScore(dna_t dna, view_t view) {
  int maxscore = -100;
  int score;
  coord_t choices[5]; //Maximum 5 possible movements
  int maxchoices = 0;
  int zeroscore = calcscore(dna, view, 0, 0, false);

  //Go over all possible moves and keep a list of the highest scores
  for (int x=0; x<2; ++x){
    for (int y=-1; y<2; ++y){
        if (x | y){
            score = calcscore(dna, view, x, y, false);
            if (score > maxscore){
                maxscore = score;
                choices[0] = {x, y};
                maxchoices = 1;
            }else if (score == maxscore){
                choices[maxchoices++] = {x, y};
            }
        }
    }
    if (!x && maxscore <= zeroscore){
        //I will NOT bounce!
        maxscore = -100;
    }
  }

  return choices[view.rng.rint(maxchoices)];
}

2

Ruby-ProbabilisticScorePlayer

class ProbabilisticScorePlayer < Player
    Here = Vector2D.new( 0, 0)
    Forward = Vector2D.new( 1, 0)
    Right = Vector2D.new( 0, 1)
    Left = Vector2D.new( 0,-1)

    def vision_at(vec2d)
        v = @vision[vec2d.x+2][vec2d.y+2]
        v==-1?nil:v
    end

    def turn
        coords = [Forward]
        [Here,Forward].each{|x|
            [Here,Right,Left].each{|y|
                c = x+y
                if x!=y && vision_at c > -1
                  coords.push c if bit_at(vision_at c)==1
                  coords.push c if bit_at(vision_at(c+Forward)+16)==1
                  coords.push c if bit_at(vision_at(c+Right)+32)==1
                  coords.push c if bit_at(vision_at(c+Left)+48)==1
                  coords.push c if bit_at(vision_at(c+Forward+Right)+64)==1
                  coords.push c if bit_at(vision_at(c+Forward+Left)+80)==1
                end
            }
        }
        coords.sample(random: @rng)
    end
end

这只高度不确定性的老鼠通过它​​的邻居来计算进入某个空间的概率。基因组中的前16个插槽代表16种颜色。插槽中的1表示可以踩上颜色,0表示不好。接下来的16个在目标前面的空间保持不变,依此类推。

概率方法的主要优点是,几乎不可能长时间被困在墙后面。缺点是您几乎永远不会获得完美的老鼠。


+1独具匠心。你得到什么样的分数?

尚未实际测试过……
MegaTom,2015年

您忘了给出c初始值吗?第一次使用它时似乎没有定义它if
Martin Ender

@MartinBüttner是的,我确实忘记了。我现在将修复它。
MegaTom,2015年

我不太了解Ruby,但是您的代码无法在Ruby2.1.5下运行。coords不是列表,而是使用&&而不是and并忘记了括号,即使修复了所有这些之后,也不会限制RNG值,因此您将得到一个空的方向。这是伪代码,还是要与某种Ruby方言一起运行的代码?

2

Java,RunningStar,得分= 1817.050970291959超过1000场比赛

该机器人通过StarPlayer的技术使用Run-Bonus的颜色编码。

更新:固定的Java控制器。

Scores: 6, 81533, 1648026, 14, 5, 38841, 1, 76023, 115162, 3355130, 65759, 59, 4, 235023, 1, 1, 1, 3, 2, 1, 1, 14, 50, 1, 306429, 68, 3, 35140, 2, 1, 196719, 162703, 1, 1, 50, 78233, 5, 5, 5209, 1, 2, 60237, 1, 14, 19710, 1528620, 79680, 33441, 58, 1, 4, 45, 105227, 11, 4, 40797, 2, 22594, 9, 2192458, 1954, 294950, 2793185, 4, 1, 1, 112900, 30864, 23839, 19330, 134178, 107920, 5, 122894, 1, 1, 2721770, 8, 175694, 25235, 1, 3109568, 4, 11529, 1, 8766, 319753, 5949, 1, 1856027, 19752, 3, 99071, 67, 198153, 18, 332175, 8, 1524511, 1, 159124, 1, 1917181, 2, 1, 10, 276248, 1, 15, 1, 52, 1159005, 43251, 1, 536150, 75864, 509655, 1126347, 250730, 1548383, 17, 194687, 27301, 2, 1, 207930, 621863, 6065, 443547, 1, 6, 1, 1, 1, 1, 556555, 436634, 25394, 2, 61335, 98076, 1, 190958, 2, 18, 67981, 3, 8, 119447, 1, 1, 1, 19, 28803, 23, 33, 60281, 613151, 1, 65, 20341, 799766, 476273, 105018, 357868, 3, 92325, 2062793, 18, 72097, 30229, 1, 1, 3, 610392, 1, 202149, 887122, 56571, 1, 77788, 61580, 4, 72535, 381846, 148682, 26676, 1, 210, 3556343, 212550, 650316, 33491, 180366, 1, 295685, 46255, 43295, 1006367, 63606, 1, 1, 1, 1, 3094617, 21, 10, 3, 1, 1, 14730, 1585801, 102, 2, 410353, 1570, 1, 17423, 1, 1849366, 5, 1, 357670, 1, 1, 1, 1, 89936, 349048, 15, 7, 6, 2, 121654, 1852897, 19, 1, 103275, 1, 1, 771797, 23, 19, 6700, 1, 135844, 2966847, 3, 2356708, 101515, 1, 17, 1, 996641, 22, 16, 657783, 171744, 9604, 1, 1335166, 1739537, 2365309, 1, 3378711, 11332, 3980, 182951, 609339, 8, 10, 1746504, 61895, 386319, 24216, 331130, 12193, 1, 284, 1, 2, 50369, 38, 8, 1, 1238898, 177435, 124552, 22370, 1418184, 20132, 6, 2, 730842, 1, 1341094, 141638, 534983, 1551260, 31508, 96196, 434312, 3012, 715155, 1, 276172, 214255, 1, 208948, 4, 1631942, 512293, 37, 64474, 1342713, 1, 132634, 13, 2, 61876, 1081704, 160301, 2, 488156, 2414109, 1809831, 5, 74904, 6, 11, 5, 1, 79856, 96, 35421, 229858, 238507, 3838897, 18, 44, 1, 1659126, 9, 33708, 12, 1, 758381, 162742, 256046, 3, 15, 142673, 70953, 58559, 6, 2, 1, 984066, 290404, 1072226, 66415, 4465, 924279, 48133, 319765, 519401, 1, 1, 1201037, 418362, 17022, 68, 213072, 37, 1039025, 1, 2, 6, 4, 45769, 1, 5, 1061838, 54614, 21436, 7149, 1, 1, 1, 35950, 2199045, 1, 379742, 3, 2008330, 238692, 181, 7, 140483, 92278, 214409, 5179081, 1, 1, 334436, 2, 107481, 1142028, 1, 31146, 225284, 1, 14533, 4, 3963305, 173084, 102, 1, 4732, 14, 1, 25, 11032, 224336, 2, 131110, 175764, 81, 5630317, 1, 42, 1, 89532, 621825, 2291593, 210421, 8, 44281, 4, 303126, 2895661, 2672876, 3, 436915, 21025, 1, 4, 49227, 1, 39, 3, 1, 103531, 256423, 2, 1600922, 15, 1, 2, 58933, 1114987, 1, 4, 3, 1, 1544880, 285673, 240, 2, 128, 214387, 3, 1327822, 558121, 5, 2718, 4, 1258135, 7, 37418, 2729691, 1, 346813, 385282, 2, 35674, 513070, 13, 1930635, 117343, 1929415, 52822, 203219, 1, 52407, 1, 1, 1, 3, 2, 37121, 175148, 136893, 2510439, 2140016, 437281, 53089, 40647, 37663, 2579170, 83294, 1597164, 206059, 1, 9, 75843, 773677, 50188, 12, 1, 1067679, 105216, 2452993, 1813467, 3279553, 280025, 121774, 62, 5, 113, 182135, 1, 16, 71853, 4, 557139, 37803, 228249, 6, 32420, 8, 410034, 73889, 1, 2, 96706, 48515, 1, 3, 1314561, 137, 966719, 692314, 80040, 85147, 75291, 1, 1, 30, 38119, 182723, 42267, 3836110, 22, 986685, 2, 37, 1, 3, 26, 43389, 2679689, 1, 1, 57365, 1, 2662599, 2, 72055, 1, 141247, 1, 1, 1122312, 1, 1080672, 4, 266211, 1, 34163, 1490610, 256341, 1, 627753, 32110, 1, 42468, 1, 10746, 1, 9, 1, 46, 1714133, 5, 117, 1, 104340, 218338, 151958, 122407, 211637, 223307, 57018, 74768, 582232, 2, 621279, 4, 1, 11, 196094, 1839877, 167117, 8, 42991, 2199269, 124676, 1, 1, 1, 5, 1, 1, 698083, 1, 76361, 1564154, 67345, 1398411, 9, 11, 105726, 1197879, 1, 2, 62740, 39, 2, 397236, 17057, 267647, 13, 57509, 22954, 1, 12, 747361, 4325650, 21425, 2160603, 144738, 1, 204054, 3113425, 6, 3019210, 30, 3359, 1, 89117, 489245, 1, 218068, 1, 1, 14718, 222722, 1, 1, 216041, 72252, 279874, 183, 89224, 170218, 1549362, 2, 1, 953626, 32, 130355, 30460, 121028, 20, 159273, 5, 2, 30, 1, 76215, 1654742, 2326439, 1, 53836, 1, 6, 4, 72327, 9, 285883, 1, 908254, 698872, 47779, 3, 2293485, 265788, 3766, 1, 1, 83151, 36431, 307577, 256891, 29, 1, 1, 1093544, 145213, 5, 2, 581319, 2911699, 1, 213061, 1359700, 2, 1, 343110, 1, 157592, 1708730, 1, 22703, 32075, 1, 1, 87720, 159221, 2313143, 10, 2266815, 2106917, 1345560, 3146014, 4, 551632, 1066905, 550313, 4069794, 1, 1406178, 38981, 1, 3, 1, 3039372, 241545, 35, 63325, 85804, 1365794, 2, 2143204, 48, 1, 99, 3225633, 7, 4074564, 1023899, 3209940, 2054326, 70880, 2, 1, 284192, 1944519, 84682, 2, 867681, 90022, 378115, 1, 15, 602743, 1337444, 131, 1, 229, 161445, 3, 2, 5591616, 195977, 92415, 637936, 142928, 1, 2310569, 923, 1, 230288, 1300519, 398529, 2233, 100261, 4323269, 81362, 37300, 1, 233775, 32277, 434139, 323797, 19214, 782633, 2881473, 1, 1, 9, 337016, 1, 515612, 44637, 17, 1, 25, 67758, 1737819, 16454, 30613, 692963, 62216, 222062, 344596, 3, 33782, 19, 180441, 23552, 20462, 70740, 10298, 109691, 1, 1729427, 33714, 1770930, 1, 1, 1, 1, 290766, 136688, 688231, 3250223, 30703, 1985963, 527128, 3, 226340, 195576, 30, 1, 3, 1, 793085, 5527, 5, 1, 2188429, 1327399, 5, 6192537, 1445186, 2478313, 2, 16892, 3, 1, 1, 15, 12, 1361157, 4, 1241684, 1, 45008, 1, 505095, 4037314, 14, 8, 1, 16740, 69906, 45, 1, 240949, 3975533, 212705, 2617552, 278884, 1, 24966, 958059, 231886, 22929, 4052071, 51259, 67791, 78739, 1, 165787, 67, 518191, 86923, 437, 1271004, 135941, 244766, 1, 1, 1, 1152745, 1, 3, 406365, 3847357, 476636, 135097, 304368, 8, 1578276, 1, 1, 375, 1, 1, 1298206, 1860743, 2, 35311, 834516, 421428, 2, 66629, 1, 309845, 398756, 33, 907277, 384475, 2267460, 1, 269300, 124525, 34399, 93584, 362186, 811260, 426109, 1, 1009323, 109986, 122181, 1, 1, 3626487, 11452, 1092410, 57233, 6, 2009226, 1, 83333, 4, 1338631, 79114, 2140249, 51813, 1118986, 43514, 1529365, 1, 101, 1, 1,
package game.players;

import java.awt.Point;
import java.util.*;

public class RunningStar extends Player{

    @Override
    public Point takeTurn(String genome, Map<Point, Integer> vision) {
        Map<Integer, Integer> squareCosts = decode(genome);
        Path path = astar(vision, squareCosts);
        return path.get(1);
    }

    private Path astar(Map<Point, Integer> vision, Map<Integer, Integer> squareCosts) {
        Set<Path> closed = new HashSet<>();
        PriorityQueue<Path> open = new PriorityQueue<>();
        open.add(new Path(new Point(0, 0), 0));
        while (!open.isEmpty()){
            Path best = open.remove();
            if (best.head().x == 2 || (best.head().x > 0 && (best.head().y == 2 || best.head().y == -2))){
                return best;
            }
            for (Path path : pathsAround(best, vision, squareCosts)){
                if (!closed.contains(path) && !open.contains(path)){
                    open.add(path);
                }
            }
            closed.add(best);
        }

        Path p = new Path(new Point(0,0), 0);
        return p.add(new Point((int)(random.nextDouble() * 3 - 1), (int)(random.nextDouble() * 3 - 1)), 0);
    }

    private List<Path> pathsAround(Path path, Map<Point, Integer> vision, Map<Integer, Integer> costs) {
        Point head = path.head();
        List<Path> results = new ArrayList<>();
        for (int i = -1; i <= 1; i++){
            for (int j = -1; j <= 1; j++){
                if (i == 0 && j == 0){
                    continue;
                }
                Point p = new Point(head.x + i, head.y + j);
                if (!vision.containsKey(p) || vision.get(p) == -1){
                    continue;
                }
                results.add(path.add(p, costs.get(vision.get(p))));
            }
        }
        return results;
    }

    private Map<Integer, Integer> decode(String genome) {
        int chunkLength = genome.length()/16;
        Map<Integer, Integer> costs = new HashMap<>();
        for (int i = 0; i < 16; i++){
            int runSize = 0;
            int cost = 0;
            for (int j = i * chunkLength; j < (i + 1) * chunkLength; j++){
                switch (genome.charAt(j)){
                    case '0':
                        runSize = 0;
                        break;
                    case '1':
                        cost += ++runSize;
                }
            }
            costs.put(i, cost);
        }
        return costs;
    }

    private class Path implements Comparable<Path>{

        Point head;
        Path parent;
        int length;
        int totalCost;

        private Path(){}

        public Path(Point point, int cost) {
            length = 1;
            totalCost = cost;
            head = point;
            parent = null;
        }

        public Point get(int index) {
            if (index >= length || index < 0){
                throw new IllegalArgumentException(index + "");
            }
            if (index == length - 1){
                return head;
            }
            return parent.get(index);
        }

        public Point head() {
            return head;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Path path = (Path) o;

            if (!head.equals(path.head)) return false;

            return true;
        }

        @Override
        public int hashCode() {
            return head.hashCode();
        }

        @Override
        public int compareTo(Path o) {
            return totalCost - o.totalCost;

        }

        public Path add(Point point, int cost) {
            Path p = new Path();
            p.head = point;
            p.totalCost = totalCost + cost;
            p.length = length + 1;
            p.parent = this;
            return p;
        }
    }
}

2

LeapForward,Python 2

并不是特别开创性的,但这是我唯一的尝试。

class LeapForward(Player):
  def __init__(self):
    Player.__init__(self)
    self.coords = [Coordinate( 1, 0),
                   Coordinate( 1,-1),
                   Coordinate( 1, 1)]
    self.n_moves = len(self.coords)

  def turn(self):
    notOKColors = [self.bit_chunk(4*n,4) for n in range(4,8)]
    notOKMap = [Coordinate(x-2,y-2) for x in range(0,5) for y in range(0,5) if self.vision[y][x] not in notOKColors]
    goTo = [c for c in self.coords if c in notOKMap]
    if not goTo:
      goTo = [Coordinate(1,0)]
    return random.choice(goTo)

基本上,它在基因组中编码要避免的四种颜色(每种4位)。然后,它前进到该列表中没有的颜色。如果所有颜色都不好,它仍然会跳到未知的地方。


可能应该将其称为“ RedQueen” :)
plannapus

1

Java-IAmARobotPlayer-得分3.7

我只是为了与我制作的另一个(到目前为止还不太有趣)程序进行比较而创建了这个机器人老鼠。总体上它得分不高,但是如果它得分某个地方,它将吸引很多老鼠。这个想法是,它将只查看前面的三个单元,每个单元的好坏。这给出了一个二进制数。然后它将在其基因组中查找此数字,获取三个连续的位,还将它们转换为一个数字,并采取该数字下存储的操作。因此,当遇到相同情况时,它的行为始终相同。

package game.players;
import java.awt.*;
import java.util.Map;
public class IAmARobotPlayer extends Player{
    private static final Point[] possibleMoves = {new Point(1,-1), new Point(1,0), new Point(1,1), new Point(0,-1), new Point(0,1), new Point(1,-1), new Point(1,0), new Point(1,1)};
    private int isGood(int pos,Map<Point,Integer> vision, char[] genomeChar){
        int value = vision.get(new Point(1,pos));
        if(value ==-1){
            return 0;
        } else {
            return genomeChar[84+value]-'0';
        }
    }

    @Override
    public Point takeTurn(String genome, Map<Point, Integer> vision) {

        char[] genomeChar = genome.toCharArray();
        int situation = 4*isGood(1,vision,genomeChar)+2*isGood(0,vision,genomeChar)+1*isGood(-1,vision,genomeChar);
        int reaction = 4*(genomeChar[3*situation+0]-'0')+2*(genomeChar[3*situation+1]-'0')+1*(genomeChar[3*situation+2]-'0');
        return possibleMoves[reaction];

    }
}

结果:

Individual scores: 1, 1, 332, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47560, 15457, 1, 
Your final score is 3.7100115087136234

1

谨慎标本-C ++-200次跑步时得分约为2030

这将使用Blind Faith编码的DNA的彩色部分(16x4位),而DNA 的其余部分(36位)则完全未使用。

颜色的编码是:

  • 10XX-安全正方形;
  • 11XX-致命方块;和
  • 0000到0111-对于8种陷印正方形。

X表示未使用的位。假设只有16种颜色中的2种会使用其所有位的陷印(并且仅当陷印偏移时,这是9乘8的情况),通常会有64个未使用的位-从理论上讲,影响这些未使用位的任何突变都不会破坏基因组,并且其稳定性优于可以使用这些剩余位的任何奇特的解决方案。

然后,标本使用此计划在以自己为中心的7x7网格内规划安全路线(他们的视野允许5x5加上每边1平方以允许偏移陷阱),优先进行3次移动后向前移动最大距离。

我最初确实开始进行一些检查,以确保标本当前站立的颜色不会致命的事实与基因组相对应,并将任何错误的颜色标记为UNSURE安全正方形(及其相邻的正方形)-但是它增加了重要意义与将这些正方形标记为SAFE并杀死其他一些标本相比,这种复杂性几乎没有收获。如果有时间,我将回到此。

#include <initializer_list>
#include <vector>

enum class D { SAFE, LETHAL,TRAP_N, TRAP_NE, TRAP_E, TRAP_SE, TRAP_S, TRAP_SW, TRAP_W, TRAP_NW, UNSURE };
enum class X { SAFE, LETHAL, UNSURE };

inline void checkLocation( color_t color, D (&dna)[16], D check )
{
    if ( color != OUT_OF_BOUNDS && dna[color] == check )
        dna[color] = D::UNSURE;
}

inline void updateMapLocation( X (&map)[7][7], unsigned int x, unsigned int y, const X& safety ){
    if (        ( safety == X::LETHAL && map[x][y] != X::LETHAL )
            || ( safety == X::UNSURE && map[x][y] == X::SAFE ) )
        map[x][y] = safety;
}

inline unsigned int isSafePath( X (&map)[7][7], coord_t p )
{
    return map[p.x][p.y] == X::SAFE ? 1 : 0;
}
inline unsigned int isSafePath(X (&map)[7][7],coord_t p,coord_t q,coord_t r){
    if ( isSafePath( map,p ) )
        if ( isSafePath( map, q ) )
            return isSafePath( map, r );
    return 0;
}

inline unsigned int isSafeEast( X (&map)[7][7], coord_t p )
{
    if ( !isSafePath( map, p ) )
        return 0;
    if ( p.x == 6 )
        return 1;
    return isSafeEast(map,{p.x+1,p.y-1})
            +isSafeEast(map,{p.x+1,p.y+0})
            +isSafeEast(map,{p.x+1,p.y+1});
}

template<typename T> inline T max(T a,T b){return a>=b?a:b;}
template<typename T, typename... A> inline T max(T a,T b,A... c){return max(max(a,b),c...); }

coord_t cautiousSpecimins( dna_t d, view_t v ) {
    X map[7][7] = { { X::SAFE } };
    D dna[16] = { D::UNSURE };
    for ( color_t i = 0; i < 16; i++ )
    {
        if ( d[4*i] == 1 )
        {
            dna[i] = d[4*i + 1] == 1 ? D::LETHAL : D::SAFE;
        }
        else
        {
            switch ( dnarange( d, 4*i + 1, 3 ) )
            {
                case 0: dna[i] = D::TRAP_N; break;
                case 1: dna[i] = D::TRAP_NE; break;
                case 2: dna[i] = D::TRAP_E; break;
                case 3: dna[i] = D::TRAP_SE; break;
                case 4: dna[i] = D::TRAP_S; break;
                case 5: dna[i] = D::TRAP_SW; break;
                case 6: dna[i] = D::TRAP_W; break;
                case 7: dna[i] = D::TRAP_NW; break;
                default: dna[i] = D::UNSURE; break;
            }
        }
    }
    if ( v(-1, 0) != OUT_OF_BOUNDS )
        checkLocation( v( 0, 0), dna, D::LETHAL );

    if ( v(-1, 0) != OUT_OF_BOUNDS )
        for ( unsigned int y = 0; y < 7; ++ y )
            map[2][y] = X::LETHAL;

    if ( v(-2, 0) != OUT_OF_BOUNDS )
        for ( unsigned int x = 0; x < 2; ++x )
            for ( unsigned int y = 0; y < 7; ++ y )
                map[x][y] = X::LETHAL;

    if ( v( 0, 1) == OUT_OF_BOUNDS )
        for ( unsigned int x = 0; x < 7; ++x )
                map[x][4] = X::LETHAL;

    if ( v( 0, 2) == OUT_OF_BOUNDS )
        for ( unsigned int x = 0; x < 7; ++x )
            for ( unsigned int y = 5; y < 7; ++ y )
                map[x][y] = X::LETHAL;

    if ( v( 0,-1) == OUT_OF_BOUNDS )
        for ( unsigned int x = 0; x < 7; ++x )
                map[x][2] = X::LETHAL;

    if ( v( 0,-2) == OUT_OF_BOUNDS )
        for ( unsigned int x = 0; x < 7; ++x )
            for ( unsigned int y = 0; y < 2; ++ y )
                map[x][y] = X::LETHAL;

    checkLocation( v( 1, 1), dna, D::TRAP_SW );
    checkLocation( v( 1, 0), dna, D::TRAP_W  );
    checkLocation( v( 1,-1), dna, D::TRAP_NW );
    checkLocation( v( 0,-1), dna, D::TRAP_N  );
    checkLocation( v(-1,-1), dna, D::TRAP_NE );
    checkLocation( v(-1, 0), dna, D::TRAP_E  );
    checkLocation( v(-1, 1), dna, D::TRAP_SE );
    checkLocation( v( 0, 1), dna, D::TRAP_S  );

    for ( int x = 1; x <= 5; ++x )
    {
        for ( int y = 1; y <= 5; ++y )
        {
            switch( dna[v(x-3,y-3)] )
            {
                case D::LETHAL : updateMapLocation( map, x+0, y+0, X::LETHAL ); break;
                case D::TRAP_N : updateMapLocation( map, x+0, y+1, X::LETHAL ); break;
                case D::TRAP_NE: updateMapLocation( map, x+1, y+1, X::LETHAL ); break;
                case D::TRAP_E : updateMapLocation( map, x+1, y+0, X::LETHAL ); break;
                case D::TRAP_SE: updateMapLocation( map, x+1, y-1, X::LETHAL ); break;
                case D::TRAP_S : updateMapLocation( map, x+0, y-1, X::LETHAL ); break;
                case D::TRAP_SW: updateMapLocation( map, x-1, y-1, X::LETHAL ); break;
                case D::TRAP_W : updateMapLocation( map, x-1, y+0, X::LETHAL ); break;
                case D::TRAP_NW: updateMapLocation( map, x-1, y+1, X::LETHAL ); break;
//              case D::UNSURE : updateMapLocation( map, x+0, y+0, X::SAFE );
//                               updateMapLocation( map, x+0, y+1, X::UNSURE );
//                               updateMapLocation( map, x+1, y+1, X::UNSURE );
//                               updateMapLocation( map, x+1, y+0, X::UNSURE );
//                               updateMapLocation( map, x+1, y-1, X::UNSURE );
//                               updateMapLocation( map, x+0, y-1, X::UNSURE );
//                               updateMapLocation( map, x-1, y-1, X::UNSURE );
//                               updateMapLocation( map, x-1, y+0, X::UNSURE );
//                               updateMapLocation( map, x-1, y+1, X::UNSURE );
//                               break;
                default        : break;
            }           
        }
    }

    unsigned int north = isSafeEast(map,{4,4});
    unsigned int east  = isSafeEast(map,{4,3});
    unsigned int south = isSafeEast(map,{4,2});
    unsigned int mx    = max( north, east, south );
    unsigned int sz;
    std::vector<coord_t> dir;
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+1,+1} );
        if ( east  == mx ) dir.push_back( {+1,+0} );
        if ( south == mx ) dir.push_back( {+1,-1} );

        return dir[v.rng.rint(dir.size())];
    }


    north = isSafePath(map,{4,4},{5,5},{5,6})
            + isSafePath(map,{4,4},{4,5},{5,6});
    south = isSafePath(map,{4,2},{5,1},{5,0})
            + isSafePath(map,{4,2},{4,1},{5,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+1,+1} );
        if ( south == mx ) dir.push_back( {+1,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = isSafePath(map,{3,4},{4,5},{5,6});
    south = isSafePath(map,{3,2},{4,1},{5,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+0,+1} );
        if ( south == mx ) dir.push_back( {+0,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = 2*isSafePath(map,{4,4},{4,5},{4,6})
            + 1*isSafePath(map,{4,4},{3,5},{4,6});
    south = 2*isSafePath(map,{4,2},{4,1},{4,0})
            + 1*isSafePath(map,{4,2},{3,1},{4,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+1,+1} );
        if ( south == mx ) dir.push_back( {+1,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = isSafePath(map,{3,4},{4,5},{4,6})
            + isSafePath(map,{3,4},{3,5},{4,6});
    south = isSafePath(map,{3,2},{4,1},{4,0})
            + isSafePath(map,{3,2},{3,1},{4,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+0,+1} );
        if ( south == mx ) dir.push_back( {+0,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = isSafePath(map,{2,4},{3,5},{4,6});
    south = isSafePath(map,{2,2},{3,1},{4,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {-1,+1} );
        if ( south == mx ) dir.push_back( {-1,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = isSafePath(map,{3,4},{3,5},{3,6})
            + isSafePath(map,{3,4},{2,5},{3,6});
    south = isSafePath(map,{3,2},{3,1},{3,0})
            + isSafePath(map,{3,2},{2,1},{3,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+0,+1} );
        if ( south == mx ) dir.push_back( {+0,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = isSafePath(map,{2,4},{3,5},{4,6});
    south = isSafePath(map,{2,2},{3,1},{4,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {-1,+1} );
        if ( south == mx ) dir.push_back( {-1,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    return {-1,-1};
}

样本分数:

Scores: 421155 2 129418 71891 90635 1 211 1111987 29745 7 2200750 41793 50500 45 2012072 2 485698 1 110061 1554720 210308 249336 2 1 262110 17 3 19 1719139 23859 45118 3182784 318 2 1 15572 14 2822954 18 11 2 3 15954 1331392 2296280 135015 1 360826 1 692367 4 244775 4814645 3749144 3 1 660000 1 11 3688002 3920202 3428464 123053 1 243520 86 9 6 289576 195966 549120 220918 9 1 43 71046 5213 118177 150678 54639 3 200839 1 3 6 1978584 1514393 119502 1 1 137695 184889 337956 1 1 441405 133902 991 1 4137428 1 1427115 3340977 1 2 1 55559 11 1 94886 30270 1 6 3 69394 264780 6877 47758 128568 1 116672 130539 163747 96253 1 2654354 1 141 58212 1613661 27 9504 1 2474022 843890 1 59 3110814 2353731 150296 313748 2590241 6 5970407 1434171 2 334715 141277 1 56810 2964306 51544 61973 715590 1 106 900384 50948 2 34652 108096 391006 1 2969764 47625 1 24 30481 44 8 1 18 2094036 106461 3080432 75 620651 16 71730 282145 275031 17 1 8 15 121731 18 2 1 1 495868 3252390 6 1 63712 7 3733149 13380 1 1
Geometric mean score: 2030.17

测试期间的最高分数:保存了8,150,817个样品。


现在您做到了……我想保存路径以便以后使用,但是我不能让您谨慎的啮齿类动物不受挑战:)看起来,通过更有效的编码,路径的工作效果更好。您将路径范围扩展到7x7的想法似乎也很有希望。我看看是否可以使用。

我目前正在为此进行2000次跑步...在前900次之后,平均值似乎稳定在600次左右,这与2000年相差甚远。您是否还想将其重新运行,以查看2000年是否只是a幸?
马丁·恩德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.