科德蒙,我选择你!


55

您的好邻居Tree Doctor刚给了您三种叫做Codémon的神奇生物。附近的Colorville镇有一场战斗比赛。您是最好的吗?

总览

这是一场战斗比赛。每个玩家控制一个由三个怪物组成的团队,目标是淘汰(杀死)另一个团队。共有100场比赛,获得胜利和平局的得分。得分最高的团队获胜!

怪兽

科德蒙是一个复杂的小动物。有五种类型(元素)可供选择,三个统计数据,每个都有三个移动位置。

种类

每个Codémon被分配一种类型。这五种类型是正常,精神,火,水和草。每个都有其优点和缺点。损坏基于下图:

类型图

这些数字是伤害乘数。例如,烈火之水具有0.5的修正值(半伤害),而烈火之草则提高了一倍(2)。

统计资料

每个怪物都有三个决定其战斗能力的属性。攻击会造成伤害。防御可以降低承受的伤害。速度允许它先于速度较低的那些移动。

每个怪物的每个属性的起始值均为50,最大值为100。创建怪物时,您将能够分配80个附加的统计值(每个)。请记住,没有任何一项统计数据可以超过100。因此,您可以分配100/80 / 50、90 / 80/60或65/65/100,但120/50/60是非法的。任何拥有非法数据的球队将被取消比赛资格。您不需要全部使用80分,但是您可能不应该使用最低50/50/50。

您也可以将HP视为统计数据,但每个Codémon的不可修改HP为100。当HP降至零时,他们将无法继续战斗。每次战斗之前,HP会加满100。

动作

每个怪物都知道三个战斗招式。选择的三个必须不同,因此不能使用打孔/打孔/打孔。

一共有15个动作,每种动作三个。每种类型都有直接攻击,效果较弱的攻击和唯一效果移动。

id  name        type    power   uses    usable  effect

0   Punch       N       20      -       NFWG
1   Heal        N        0      3       NFWG    Heals 50 HP
2   Slow        N       10      5       NFWG    Enemy speed x0.8
3   Pain        P       20      -       PFWG
4   Sleep       P        0      3       PFWG    No enemy action until wake
5   Weaken      P       10      5       PFWG    Enemy Atk x0.8
6   Fireball    F       20      -       NPFW
7   Burn        F        0      3       NPFW    Enemy -10 HP each turn
8   Sharpen     F       10      5       NPFW    Own Atk x1.25
9   Watergun    W       20      -       NPWG    
10  Confuse     W        0      3       NPWG    Enemy may strike itself (10 power)
11  Shield      W       10      5       NPWG    Own Def x1.25
12  Vine        G       20      -       NPFG
13  Poison      G        0      3       NPFG    Enemy -5xTurns HP each turn
14  Sap         G       10      5       NPFG    Enemy Def x0.8

type指移动的类型。power是其惊人的力量。uses表示每次战斗可以使用多少次(-无限制)。usable显示可以使用的类型(例如,不能将Punch赋予Psychic类型,因为没有P)。effect展示这些举动有什么作用。每个效果都有75%的机会起作用,但治疗效果除外,此效果始终有效。

对于改变怪物属性的效果,可以叠加效果。例如,两次使用弱化可将对手的攻击降低至0.64效率。不会改变怪兽状态(睡眠,燃烧等)的效果不会叠加

睡眠使对手进入睡眠状态,每回合开始时有60%的机会醒来。睡觉的怪物不会采取任何行动。

活跃时,燃烧在每回合结束对对手造成10点HP 。毒药的作用与此类似,但是每回合的毒药量会增加。第一回合为5,此后每回合获得5。因此,到第四回合,它将造成20点伤害。这些都是单位伤害,不受怪物类别和加成的影响。

混乱可能会使怪物自己攻击,而不是按要求做。该攻击的威力为10,在给定回合中有30%的几率发生。

需要明确的是,效果会持续到战斗结束(如上所述,“睡眠”除外)。

如果由相应类型的怪物使用,招式也将获得20%的力量提升。例如,使用藤蔓的草怪会被提升,而使用“冲床”则不会。

秘密统计

每个怪物的统计数据和类型(但不能移动)都是公众知识。您的对手将能够看到他们在战斗什么,以便选择最佳动作。但是,也有一些隐藏的奖金。

具体来说,每两场战斗之后,您会为团队中的每个怪物获得一个“奖励”统计点。积分将分配给所有死活的怪物,胜利者或失败者。您可以将其分配给您选择的三个统计数据中的任何一个。您不能将它们堆叠在单个怪物上。每个怪物每次都会得到一个这些点不受100限制。由于将进行100轮战斗,因此,如果您分配所有奖金,则最多可以获得149个统计数据。同样,对手只会看到您的“基本”数据,因此您进入比赛的距离越远,他们的知识与事实的距离就越远。

战斗

战斗在三人一组之间进行,每个团队一次活跃。首先,将向您展示对手的队伍,并要求您选择哪个怪物将成为您的第一个“活跃”玩家。

之后,将按照以下步骤进行转弯:

  • 切换:强制进行怪物切换(如果有)
  • 选择战斗动作
  • 切换:发生任何可选的怪物切换(选择为战斗动作)
  • 睡眠检查:有机会从睡眠中醒来
  • 攻击1:如果能,更快的怪物会使用其选择的动作
  • 攻击2:如果能,另一只怪物使用其选择的动作
  • 效果伤害:对活着的怪物造成灼伤/毒药伤害

“速度更快”是指速度较高的怪物。如果两个速度统计都相同,则每转一圈,由PRNG投币选择。

在活动怪物死亡的任何回合结束时,都会要求您选择一个新的活动对象。您可能选择到主动怪物切换为您的移动任何转(前提是你有一个以上的活着)。同样,如果您随手而动,那么该回合就不会做出战斗动作。

不活动时,怪物不会被“处理”。这意味着它们不会遭受烧伤/中毒伤害,不会累积中毒计数器,不会从睡眠中唤醒等。切换时不会移除或更改任何效果。这不是其他怪物战斗游戏。如果您在发起攻击并烧毁的情况下退出,则当您重新打开时,它们仍会存在。

无论您是否杀死对手,都会造成效果伤害。这样,两个团队的成员都可以在一个回合中死亡。

当一个团队用完可用的怪物时,他们就会输掉。如果两队都在同一回合中用完,那就是平局。如果战斗持续1000回合,那是平局。

确定损坏的公式是:

floor((effAttack / effDefense) * movePower * typeMultiplier * moveBoost)

effAttack并且effDefense有效的统计信息的怪物。有效攻击是通过将“攻击”和“加成攻击”相加,然后乘以(乘以0.8或1.25)(如果有任何影响)来获得的。请记住,这些效果会叠加。

当类型修饰符为0(普通<->通灵)或移动的异能为0(治疗,燃烧等)时,伤害只能为0。否则将最小值强制为1。

比赛

比赛持续100回合。在每个回合中,各队进行随机组合并随机配对。如果队伍数量奇数,剩下的人会再见(得分为平局)。赢得一场战斗会为球队赢得2分,并列为1分,并且没有损失。最终得分最高的团队获胜!

如果各队并列,则将举行一场仅将各队并列第一的比赛来确定决胜局的顺序。

协议

控制器将向您的程序发送以下四个命令之一。第一个字符确定命令类型,并在必要时跟随数据。

您的程序将接受命令作为参数,并将在一秒钟内响应STDOUT 。不要活着听STDIN,它不会在那里。每个命令将产生一个新进程。

您可以将数据/状态写入磁盘。将所有文件放在与您的团队同名的子文件夹中。写入的数据不能超过32 KB,否则您将失去资格。数据将在各回合之间保留,但将在锦标赛之间清除。

指令

团队资料

在锦标赛开始时发送一次,以注册您的团队。您的回复应该是固定的,对于每个比赛都应该不同。

查询:

T

响应:

name|member0|member1|member2

name是带有您的团队名称的字符串。请仅使用字母数字,以便于解析。memberN是一个成员字符串,提供每个怪物的详细信息:

成员字符串:

name:typeid:attack:defense:speed:moveid0:moveid1:moveid2

同样,“ name”是一个字符串,这次带有这个怪物的名字。typeid是它的类型。类型ID按照上表中显示的顺序,Normal = 0,Grass = 4。

接下来的三个字段是您的基本统计信息。请记住上面统计信息部分所述的限制。

最后三个是怪物的举动。ID显示在上方的移动图中。

团队数据回复示例如下所示:

DummyTeam|DummyA:0:50:60:70:0:1:2|DummyB:0:50:60:70:0:1:2|DummyC:0:50:60:70:0:1:2

在此之前,任何将垃圾,格式错误或非法数据发送回去的团队都不会参与。

选择有效

该消息在每次战斗开始时发送,并且在怪物死亡并需要切换时发送。

查询:

C#battleState

battleState显示当前战斗的状态。在这里忍受我,这很丑陋:

yourTeamState#theirTeamState

其中XteamState的样子:

name:activeSlot|member0state|member1state|member2state

activeSlot显示当前处于活动状态的怪物(0-2)。成员国有两种口味。如果是您的团队,它会提供更多信息。所以,

您的 memberXstate:

name:id:attack:defense:speed:hp:typeid:poisonedturns:moveCount0:moveCount1:moveCount2:bonusAttack:bonusDefense:bonusSpeed:effectid:effectid:effectid

他们的 memberXstate:

name:id:attack:defense:speed:hp:typeid:poisonedturns:effectid:effectid:effectid

id只是一个整数标识符,如果您不喜欢使用,可以用来跟踪怪物name

attack:defense:speed是您的基本统计信息。

poisonedturns 告诉您中毒了多少回合。

moveCountX告诉您每个动作还剩下多少用途。如果为0,则无法使用。对于无限移动,这将是负面的。

bonus(stat) 是您分配给每个统计数据的奖励积分的数量。

effectid是已应用于怪物的大小可变的效果列表。无论是否存在主动效果,字符串上都不会出现尾随:。如果有叠加效果,它们将在列表中显示为多个效果。

效果ID为:

0  NONE           (should not appear, internal use)
1  POISON
2  CONFUSION 
3  BURN 
4  SLEEP 
5  HEAL           (should not appear, internal use)
6  ATTACK_UP
7  ATTACK_DOWN
8  DEFENSE_UP
9  DEFENSE_DOWN
10 SPEED_DOWN

响应:

memberSlot

唯一需要的响应是单个数字0,1,2,告诉您要激活哪个成员。该成员必须是能够战斗的成员。1如果成员1已死亡,请不要发回。

战斗动作

每回合,您都需要决定要做什么。

查询:

A#battleState

battleState这里正是如上所述。

响应:

要使用移动,请发回移动所在的插槽。例如,如果我将“打孔”分配给了插槽0,则发送0会执行“打孔”。

要切换到另一个成员,请发送该成员的广告位加10。因此要切换到成员2,发送12

不在[0,1,2,10,11,12]中的任何内容均被视为无效,并且将导致本回合不采取任何措施。

奖励统计

每两场战斗后,您会为每个团队成员获得一个秘密的加分。

查询:

B#yourTeamState

您的团队状态与上面显示的相同,请不要重复。

响应:

stat0:stat1:stat2

您的回复将代表每个团队成员要增加的统计数据。攻击为0,防御为1,速度为2。

因此,为了提高成员的速度,成员2的攻击和成员3的防御,您将做出以下响应:

2:0:1

控制者

可以在BitBucket上找到该控制器:https://Geobits@bitbucket.org/Geobits/codemon.git

只需将所有已编译的类文件,提交内容和players.conf放入一个文件夹中并运行即可。

控制器的主类称为Tournament。用法是:

java Tournament [LOG_LEVEL]

从0-4的日志级别提供了越来越多的信息。级别0静默运行锦标赛,并给出结果,而级别3给出逐行注释。级别4是调试输出。

您可以在比赛中添加提交内容,players.conf只需添加运行程序所需的命令行字符串,每行一个。以开头的行#是注释。

在您的帖子中,包括我将需要添加到命令中的命令players.conf以及所有编译步骤(如果需要)。

其中包括一个由所有正常成员组成的虚拟团队,其中包括三个正常动作。他们随机选择举动,并且有糟糕的数据。乐于击败他们。

杂项规则

  • 您不得读写任何外部资源(如上所述,在您自己的子文件夹中,最大32 kB除外)。

  • 您的团队需要参加比赛“盲注”。这意味着您无法分析其他人的消息来源来确定特定团队/怪物在给定情况下会做什么。您可以分析对手的移动/状态并随着比赛的进行保持跟踪,但无需对这些信息进行硬编码。

  • 不要干扰其他过程/提交。请勿调用它们,使用反射获取其数据等。请勿弄乱我的计算机。只是不要尝试。这是我自行决定的。违反者可能被禁止将来进入。

  • 参赛者最多只能参加两次比赛。如果您提交的更多,我只会对前两个提交的分数进行评分。如果要撤消一个,请将其删除。

  • 条目可能不仅仅存在以支持其他条目。另外,您可能不能尝试间接取消其他参赛者的资格(例如,对试图将其写入磁盘的DQ玩家使用27M角色队伍名称)。每个提交都应发挥自己的优势取胜。

  • 您的程序一次最多可以生成一个子进程(后代总数,而不是直接子代)。提供输出后,主进程和任何子进程都必须立即终止。无论哪种方式,请确保您都不会超时。

  • 比赛将在装有Intel i7 3770K处理器的运行Ubuntu的计算机上举行。

结果

这些是当前玩家的结果。这是非常的顶级竞争者之间的密切,而且我在想碰撞的回合数高达500(和调整的奖励积分的间距相匹配)。有任何反对意见吗?

------- Final Results -------

158     Happy3Campers
157     LittleKid
71      InsideYourHead
68      HardenedTrio
46      BitterRivals

Google云端硬盘上的完整播放结果


62
我想成为最好的/从来没有像过的代码/不崩溃是我的测试/调试是我的原因!/我将穿越局域网/遍历整个脚本/努力理解/为什么要破坏我的BIOS!/Codémon,是你和我/打高尔夫可以一览无余/Codémon,你是我最好的朋友/计划结束后!/Codémon,如此真实的语言/不会有段错将我们带走/您教给我,我教给您/Codémon,一定要高尔夫!
卡兹·沃尔夫

1
如果不让回合数增加到500,而是让每一个人都与每个人交战就好了。因此bye,对于不平衡数量的竞争者,不再需要任何竞争,并且可以确保比赛对是公平且均匀分布的。
foob​​ar

@foobar我想避免这种情况,因为它扩大了n^2而不是的战斗n。仅以目前的7个竞争对手和100轮比赛而言,这是2100场战斗(原样为300场,而500轮则为1500场)。随着越来越多的参赛者进入,情况只会变得更糟。我可以缩减回合数,但是由于内在的可变性(关于状态esp),我犹豫了一下,而且50的倍数(用于奖励积分)更容易。
Geobits 2015年

这个挑战不是需要更新吗?:)
GholGoth15年

@ GholGoth21是的,我相信是的。我可能今天无法到达,但是明天或第二天。如果您希望在星期四之前未更新,请在聊天中给我发消息。
Geobits'3

Answers:


16

快乐的3个露营者-PHP

一群胆小鬼,喜欢用令人衰弱的咒语向对手撒谎,看着他们腐烂。

编辑:鲁比先生受到了严厉的指责,不再说坏话了


便利便利Grass - atk:50 def:99 spd:81 Confuse Poison Heal

一个有毒的无臂海狸,喜欢将人与有问题的握手混淆


软盘软盘Water - atk:50 def:99 spd:81 Confuse Burn Heal

公告板资深人士,对轻率的谈话和火焰战争情有独钟。


坚果坚果Fire - atk:50 def:99 spd:81 Burn Poison Heal

大规模杀伤性武器是他最喜欢的糖果。


块状块状Php - lines:500 clarity:05 spd:01 Gather Guess Store

凭借其近2位数的智商和惊人的记忆力,Lumpy可以猜出敌人的举动。好吧,主要是。


战略

策略是让对手尽快中毒,燃烧和困惑。
没有使用睡眠,因为它似乎不如上面的三个咒语强大。
从长远来看,混乱是致命的,因为它可以减少30%的攻击(造成伤害和施法),阻止治疗者治愈自己并严重伤害重击者(50点防御力/ 100点攻击力的怪物会对其自身造成20点伤害)。

一旦敌人被彻底粘贴,我的营员们只会看着他嘶嘶作响,腐烂并猛烈地把自己撞死。

高防御力和治疗能力可以减轻痛苦中的传入伤害。

当我的三个营员在战斗时,魔鹿驼峰会注视着敌人的一举一动,有时还能识别出它们。这些信息将反馈给我们的战斗机,他们会尽力利用这些信息。

在防守之后,速度是最重要的数据。
主动性对于在下一次打击发生之前进行康复至关重要。

根本不使用攻击。

咒语是终极武器吗?

诸如毒药,燃烧和迷惑之类的法术可以逃脱其他攻击的整体石头/剪刀布/剪刀逻辑。

一旦怪物受到影响,即使施法者死了,它也会继续失去生命值。好像施法者的幽灵一直在攻击他。
此外,毒药变得比完全疲惫的大规模攻击(5回合后超过50点)更强大。

被毒害和燃烧的怪物的预期寿命即使经过3次治疗也不会超过8回合。

就像马丁的机器人似乎指出的那样,游戏的平衡性非常好。
从根本上说,这将是在纯净施法者和纯净攻击者之间取得平衡的主动性。

编码

调用 php campers.php

这是一个丑陋的混乱局面,但坦率地说,该界面也无济于事。

既然出现了适当的侵略性比赛,我就实施了我长期计划中的敌人举动猜测。
分析攻击需要各种特技演绎和最后转弯状态的持久存储,这意味着使用偏执控制器接口进行全面战争。
它既不是漂亮的东西,也不是六足的兔子,但是做得很好。

<?php

// ============================================================================
// Game
// ============================================================================
class G {
    static $code_type = array ("Normal", "Psychic", "Fire", "Water", "Grass", "?", "self"); 
    static $code_move = array    ("Punch", "Heal", "Slow", "Pain", "Sleep", "Weaken", "Fireball", "Burn", "Sharpen", "Watergun", "Confuse", "Shield", "Vine", "Poison", "Sap", "?", "self", "pass");
    static $move_uses = array (1000,3,5,1000,3,5,1000,3,5,1000,3,5,1000,3,5,   2000,2000);
    static $move_type      = array (0,0,0,1,1,1,2,2,2,3,3,3,4,4,4, 5,5,5);
    static $move_dmg       = array (20,0,10,20,0,10,20,0,10,20,0,10,20,0,10,  20,10,0);
    static $move_forbidden = array (1,1,1,0,0,0,4,4,4,2,2,2,3,3,3);
    static $code_effect = array ("N", "Poison", "Confuse", "Burn", "Sleep", "H", "Sharpen", "Weaken", "Shield", "Sap", "Slow"); 
    static $decode_type, $decode_move, $decode_effect;
    static $damage_multiplier = array (
        array (2, 0, 1, 1, 1, 0),
        array (0, 2, 1, 1, 1, 0),
        array (1, 1,.5, 2,.5, 0),
        array (1, 1,.5,.5, 2, 0),
        array (1, 1, 2,.5,.5, 0),
        array (2, 2, 2, 2, 2,-1),
        array (9, 9, 9, 9, 9, 9, 1));
    static $atk_score = array ("Poison"=> 1002, "Confuse"=>1001, "Burn"=>1000);
    static $status_field = "atk:def:spd:hp:type:Pturns";
    static $all_moves, $strong_moves, $medium_moves, $effect_moves, $possible_moves;

    function init()
    {
        self::$status_field = explode (":", self::$status_field);
        foreach (array ("type", "move", "effect") as $table) self::${"decode_$table"} = array_flip (self::${"code_$table"});
        foreach (self::$code_move as $c=>$m)
        {
            if ($m == "?") break;
            self::$all_moves[] = new Move($m);
            if (self::$move_uses[$c] >  5) self::$strong_moves[] = $m;
            if (self::$move_uses[$c] == 5) self::$medium_moves[] = $m;
            if (self::$move_uses[$c] == 3) self::$effect_moves[] = $m;
            for ($type = 0 ; $type != 5 ; $type++) if ((self::$move_uses[$c] >  5) && (self::$move_forbidden[$c] != $type)) self::$possible_moves[$type][] = $m;
        }
    }

    function __construct ($name, $team)
    {
        $this->turn = 0;
        $this->name = $name;
        $this->team = $team;
        $this->results_pending = false;
    }

    function parse_team ($tpack, $own_team)
    {
        $pack = explode ("|", $tpack);
        list ($name,$active) = explode (":", array_shift($pack));
        if ($own_team)
        {
            $team = $this->team;
        }
        else
        {
            if (!isset($this->enemies[$name])) $this->enemies[$name] = new Team(array (new Monster (), new Monster (), new Monster ()));
            $team = $this->foes = $this->enemies[$name];
        }
        $team->active = $active;
        foreach ($pack as $i=>$mpack) $team->monster[$i]->parse_monster ($own_team, $mpack);
    }

    function choose_active ()
    {
        // detect start of round
        $team = $this->team;
        $foes = $this->foes;
        foreach ($team->monster as $i=>$m) if ($m->hp > 0) $candidate[$i] = $m;
        if (count ($candidate) == 3)
        {
            $this->results_pending = false;
            $this->round++;

            // reinitialize all monsters
            foreach (array($team, $foes) as $t)
            foreach ($t->monster as $m)
                $m->start_round();

            // guess initial opponent
            $opponent = $foes->initial_opponent();
        }
        else
        {
            $this->analyze_last_round();
            $opponent = $foes->active();
        }
        return $this->do_switch ($opponent);
    }

    function choose_attacker ($foe)
    {
        foreach ($this->team->monster as $i=>$m) if ($m->can_attack($foe)) $candidate[$i] = $m;
        if (isset($candidate))
        {
            uasort ($candidate, function ($a,$b) use ($foe) { return ($a->atk_score != $b->atk_score) ? $b->atk_score - $a->atk_score : $b->life_expectancy($foe) - $a->life_expectancy($foe); });
            return key($candidate);
        }
        return -1;
    }

    function do_switch ($foe)
    {
        $replacement = $this->choose_attacker ($foe);
        if ($replacement < 0)
        {
            $candidate =  $this->team->monster;
            uasort ($candidate, function ($a,$b) use ($foe) { return $b->life_expectancy($foe) - $a->life_expectancy($foe); });
            $replacement = key($candidate);
        }

        $this->old_own = $this->team->monster[$replacement];
        $this->old_own->attack = "pass";
        return $replacement;
    }

    function choose_action ()
    {
        $this->analyze_last_round();
        $own = $this->team->active();
        $foe = $this->foes->active();
        $this->old_own = $own;

        if ($own->hp <= $own->max_damage($foe) && $own->can_do ("Heal")) return $own->execute("Heal");
        if ($attack = $own->can_attack($foe)) return $own->execute($attack);
        if ($own->hp <= 50 && $own->can_do ("Heal")) return $own->execute("Heal");

        return 10 + $this->do_switch ($foe);    
    }

    function choose_bonus()
    {
        foreach ($this->team->monster as $m)
        {
            if ($m->spd_b == 0) { $m->spd_b++; $res[] = 2; }
            else                { $m->def_b++; $res[] = 1; }
        }
        return implode (":", $res);
    }

    function parse ($parts)
    {
        self::parse_team ($parts[1], true);
        self::parse_team ($parts[2], false);    
    }

    function analyze_last_round()
    {
        if ($this->results_pending)
        {
            $this->results_pending = false;

            $foes = $this->foes;
            $foe = null;
            foreach ($foes->monster as $m) if ($m->hp != $m->old->hp) $foe = $m;
            if ($foe === null) $foe = $foes->monster[$foes->active];

            $this->old_own->guess_attack($foe);
        }
    }

    function process ($line)
    {
        $parts = explode ("#", $line);
        switch ($parts[0])
        {
        case "T": // register for tournament
            echo "$this->name|$this->team";
            break;
        case "C": // designate active monster
            $this->parse ($parts);
            echo $this->choose_active();
            break;
        case "A": // choose round action
            $this->parse ($parts);
            echo $this->choose_action();

            // save current state
            foreach (array($this->team, $this->foes) as $t)
            foreach ($t->monster as $m)
            {
                unset ($m->old);
                $m->old = clone ($m);
            }
            $this->results_pending = true;
            break;
        case "B": // distribute stat bonus
            echo $this->choose_bonus();
            break;
        }

    }
}
G::init();

// ============================================================================
// Move
// ============================================================================
class Move {
    function __construct ($move)
    {
        $this->register($move);
    }

    function register ($move)
    {
        $this->type = G::$decode_move[$move];
        $this->reinit();
    }

    function reinit()
    {
        $this->uses = G::$move_uses[$this->type];
    }

    function __tostring() { return G::$code_move[$this->type]."($this->uses)"; }
}

// ============================================================================
// Monster
// ============================================================================
class Monster { 
    function __construct ($name="?", $type="?", $atk=100, $def=100, $spd=100, $m0="?", $m1="?", $m2="?")
    {
        $this->name = $name;
        $this->type = G::$decode_type[$type];
        $this->atk  = $atk;
        $this->def  = $def;
        $this->spd  = $spd;
        $this->hp   = 100;
        $this->move = array (new Move($m0), new Move($m1), new Move($m2));
        $this->atk_b = 0;
        $this->def_b = 0;
        $this->spd_b = 0;
        foreach (G::$code_effect as $e) $this->$e = 0;
    }

    function __tostring ()
    {
        return implode (":", array (
            $this->name,
            $this->type,
            $this->atk,
            $this->def,
            $this->spd,
            $this->move[0]->type,
            $this->move[1]->type,
            $this->move[2]->type));
    }

    function start_round()
    {
        foreach ($this->move as $m) $m->reinit();
    }

    function parse_monster ($own_team, $spack)
    {
        $pack = explode (":", $spack);
        $name = array_shift ($pack); // get name
        array_shift ($pack); // skip id
        if ($this->name == "?") $this->name = $name; // get paranoid
        else if ($this->name != $name) die ("expected $this->name, got $name");

        // store updated values
        foreach (G::$status_field as $var) $this->$var = array_shift ($pack);
        if ($own_team)
        {
            foreach ($this->move as $m) $m->new_count = array_shift($pack);
            $pack = array_slice ($pack, 3); // these are maintained internally
        }
        $var = array();
        foreach ($pack as $e) @$var[G::$code_effect[$e]]++; 
        foreach (G::$code_effect as $e) $this->$e = @$var[$e]+0;
    }

    function damage_recieved ($attack, $foe=null)
    {
        if ($attack == "self") $foe = $this;
        $a = G::$decode_move[$attack];
        $type = G::$move_type[$a];
        $dmg = g::$move_dmg[$a];

        if ($dmg == 0) return 0;

        $atk = ($foe ->atk+$foe ->atk_b) * pow (.8, ($foe ->Weaken - $foe ->Sharpen));
        $def = ($this->def+$this->def_b) * pow (.8, ($this->Sap    - $this->Shield ));

        $boost = ($foe->type == $type) ? 1.2 : 1;
        return max (floor ($dmg * $atk / $def * $boost * G::$damage_multiplier[$this->type][$type]), 1);
    }

    function guess_attack_from_effect ($attacks)
    {
        foreach ($attacks as $status) if ($this->$status != $this->old->$status) return $status;
        return "?";
    }

    function guess_attack_from_damage ($foe, $damages)
    {
        $select = array();
        foreach (G::$possible_moves[$foe->type] as $attack)
        {
            $dmg = $this->damage_recieved ($attack, $foe);
            foreach ($damages as $damage) if ($damage != 0 && abs ($dmg/$damage-1) < 0.1) $select[$attack] = 1;
        }
        $res = array();
        foreach ($select as $a=>$x) $res[] = $a;
        return $res;
    }

    function guess_attack ($foe)
    {
        $attempt = G::$decode_move[$this->old->attack];
        $success = ($this->old->attack == "pass");
        foreach ($this->move as $m)
        {
            if ($m->type == $attempt)
            {
                if ($m->new_count == $m->uses-1)
                {
                    $m->uses--;
                    $success = true;
                }
                break;
            }
        }

        $possible = array();
        $attack = $this->guess_attack_from_effect (array("Burn", "Confuse", "Poison", "Sleep", "Slow", "Weaken", "Sap"));
        if ($attack == "?") $attack = $foe->guess_attack_from_effect (array("Sharpen", "Shield"));
        if ($attack == "?")
        {
            $foe_damage = $this->old->hp - $this->hp - (10 * $this->Burn + 5 * $this->Pturns*$this->Poison);
            if ($this->old->attack == "Heal" && $success) $foe_damage += 50;
            $possible_dmg[] = $foe_damage;
            //;!;if ($this->Confuse) $possible_dmg[] = $foe_damage + $this->damage_recieved ("self");
            $possible = $this->guess_attack_from_damage ($foe, $possible_dmg);
            if (count ($possible) == 1) $attack = $possible[0];
        }
        if ($attack == "?")
        {
            $own_damage = $foe->old->hp - $foe->hp 
                        - (10 * $foe->Burn + 5 * $foe->Pturns*$foe->Poison)
                        + $foe->damage_recieved ($this->attack);
            if (abs ($own_damage/50+1) < 0.1) $attack = "Heal";
        }
        if ($attack != "?")
        {
            $type = G::$decode_move[$attack];
            if ($attack != "?")
            {
                foreach ($foe->move as $m) if ($m->type == $type) goto found_old;
                foreach ($foe->move as $m) if ($m->type == 15) { $m->register($attack); goto found_new; }
            }
            found_new:
            found_old:
        }
    }

    function max_damage($foe)
    {
        $dmg = 0;
        foreach ($foe->move as $m) $dmg = max ($dmg, $this->damage_recieved (G::$code_move[$m->type], $foe));
        return $dmg;
    }

    function expected_damage ($foe)
    {
        return $this->max_damage($foe) + 10 * $this->Burn + 5 * ($this->Pturns+1);
    }

    function life_expectancy ($foe)
    {
        $hp = $this->hp;
        $poison = $this->Pturns;
        $heal = $this->can_do ("Heal");
        $dmg = $this->max_damage($foe);
        for ($turn = 0 ; $hp > 0 && $turn < 10; $turn++)
        {
            $hp -= 10 * $this->Burn + 5 * $poison;
            if ($poison > 0) $poison++;
            $hp -= $dmg;
            if ($hp <= 0 && $heal > 0) { $hp+=50; $heal--; }
        }
        return 100 * $turn + $this->hp;
    }

    function can_attack ($foe)
    {
        $attack = false;
        if ($this->hp > 0)
        {
            if      (!$foe->Poison  && $this->can_do ("Poison" )) $attack = "Poison";
            else if (!$foe->Confuse && $this->can_do ("Confuse")) $attack = "Confuse";
            else if (!$foe->Burn    && $this->can_do ("Burn"   )) $attack = "Burn";
        }
        $this->atk_score = ($attack === false) ? 0 : G::$atk_score[$attack];
        return $attack;
    }

    function can_do($move)
    {
        $type = G::$decode_move[$move];
        foreach ($this->move as $m) if ($m->type == $type && $m->uses > 0) return $m->uses;
        return false;
    }

    function execute($move)
    {
        $type = G::$decode_move[$move];
        foreach ($this->move as $i=>$m) if ($m->type == $type) 
        { 
            if ($m->uses > 0)
            {
//;!;               $m->uses--;
                $this->attack = $move;
            }
            else $this->attack = "pass";
            return $i; 
        }
        die ("$this asked to perform $move, available ".implode(",", $this->move));
    }
}

// ============================================================================
// Team
// ============================================================================
class Team {
    function __construct ($members)
    {
        $this->monster = $members;
    }

    function __tostring()
    {
        return implode ("|", $this->monster);
    }

    function active ()
    {
        return $this->monster[$this->active];
    }

    function initial_opponent()
    {
        return $this->monster[0];
    }
}

// ============================================================================
// main
// ============================================================================
$input = $argv[1];

$team_name = "H3C";
$mem_file = "$team_name/memory.txt";
$trc_file = "$team_name/trace.txt";
if (!file_exists($team_name)) mkdir($team_name, 0777, true) or die ("could not create storage directory '$team_name'");
if ($input == "T") array_map('unlink', glob("$team_name/*.txt"));

if (file_exists($mem_file)) $game = unserialize (file_get_contents ($mem_file));
else
{
    $team = new Team (
        array (
            new Monster ("Handy" , "Grass" , 50, 99, 81, "Confuse", "Poison", "Heal"),
            new Monster ("Nutty" , "Fire"  , 50, 99, 81, "Burn"   , "Poison", "Heal"),
            new Monster ("Flippy", "Water" , 50, 99, 81, "Confuse" , "Burn" , "Heal")));
    $game = new G($team_name,$team);
}

$game->process ($input);
file_put_contents ($mem_file, serialize($game));

结果

LittleKid仍然令人生畏,但我的三人组以一定优势击败了他的毒蛇怪。

马丁的机器人由于缺乏主动性而注定了失败,提高速度将要求降低攻击力,这将削弱其在破坏能力上的优势。

来自JavaScript星球的新竞争者与团队是一对一的,但与其他竞争对手的竞争则更糟。它们实际上有助于降低LittleKid的得分:)。

所以看来我可爱的朋友们仍然是山丘之王-现在...

170             H3C
158             Nodemon
145             LittleKid
55              InsideYourHead
42              HardenedTrio
30              BitterRivals

而且我也没有PHP。我希望您能用Metapods拖地板,因为它们缓慢移动并会中毒致死。
Sp3000

... *和*烧成酥脆的:D。这就是规则复杂的问题:主导策略很可能会出现。由于没有针对这些咒语的保护措施,因此它们可能是科德蒙的胖子和小男孩。

我将它与剪刀,纸,石头等非传递性游戏进行比较-由于效果需要一段时间,因此,全力进攻的团队应该能够将您击倒:)
Sp3000

2
是的,这是我一想到毒药和烧伤都没有补救措施时就想到的。感谢您实现我的梦想。
justhalf 2015年

1
当Lumpy先生从同一个对手中发现3次以上不同的攻击时,他就表示困惑。我有一个即将完成的固定版本,但是我现在正处于其他事项之中,因此该修补程序将在一天左右的时间内发布。

7

HardenedTrio,Python 3

由于Geobits足够好,可以给我们提交两次,所以我认为我会为第一个提交愚蠢的东西:P

派对是三个Codemon(Metapod1,Metapod2,Metapod3),它们的统计数据和移动方式相同:

  • 80攻击,100防御,50速度
  • 打孔,治疗,盾牌硬化

所有加分也分配给防御。


from collections import namedtuple
import sys

BattleState = namedtuple("BattleState", ["us", "them"])
TeamState = namedtuple("TeamState", ["name", "active", "members"])
MemberState = namedtuple("MemberState", ["name", "id", "attack", "defense", "speed", "hp",
                                         "typeid", "poisonedturns", "otherstats"])

def parse_battle_state(state):
    return BattleState(*map(parse_team_state, state.split("#")))

def parse_team_state(state):
    na, *members = state.split("|")
    name, active = na.split(":")
    return TeamState(name, int(active), list(map(parse_member_state, members)))

def parse_member_state(state):
    name, id_, attack, defense, speed, hp, typeid, poisonedturns, *rest = state.split(":")
    return MemberState(name, int(id_), float(attack), float(defense), float(speed),
                       float(hp), int(typeid), int(poisonedturns), rest)

command = sys.argv[1].strip()

if command.startswith("T"):
    print("HardenedTrio|Metapod1:0:80:100:50:0:1:11|"
          "Metapod2:0:80:100:50:0:1:11|Metapod3:0:80:100:50:0:1:11")

elif command.startswith("C"):
    battle_state = parse_battle_state(command[2:])

    for i, codemon in enumerate(battle_state.us.members):
        if codemon.hp > 0:
            print(i)
            break

elif command.startswith("A"):
    battle_state = parse_battle_state(command[2:])
    current_codemon = battle_state.us.members[battle_state.us.active]

    if current_codemon.hp < 50 and int(current_codemon.otherstats[1]) > 0:
        print(1) # Heal up if low

    elif int(current_codemon.otherstats[2]) > 0:
        print(2) # Harden!

    else:
        print(0) # Punch!

elif command.startswith("B"):
    print("1:1:1")

与运行

py -3 <filename>

(或使用python/ python3而不是py取决于您的安装)



1
@FryAmTheEggman Metapod,哈顿!
Sp3000

我正在尝试阅读您的代码,但对感到困惑int(current_codemon.otherstats[1])>0。如果他有地位影响,那返回true?而且,他只有在具有两种状态影响时才使用强化?
Mooing Duck 2015年

@MooingDuck对于您的Codemon,您必须在moveCounts之前加effectids,因此它将检查它是否仍可以使用Harden。我懒于解析,这就是为什么将其混入其中的原因。
Sp3000

@ Sp3000:哦!对!哈哈哈!
Mooing Duck 2015年

6

露比

  • 布赖恩:通灵,攻击力:100,防御力:50,速度:80,疼痛,火球,水枪
  • Elemon1:通灵,攻击:100,防御:50,速度:80,火球,水枪,藤蔓
  • Elemon2:通灵,攻击:100,防御:50,速度:80,火球,水枪,藤蔓
TEAM_SPEC = "InsideYourHead"+
            "|Brian:1:100:50:80:3:6:9"+
            "|Elemon1:1:100:50:80:6:9:12"+
            "|Elemon2:1:100:50:80:6:9:12"

def parse_battle_state request
    request.map do |team_state|
        state = {}
        parts = team_state.split '|'
        state[:active] = parts.shift.split(':')[1].to_i
        state[:monsters] = parts.map do |monster_state|
            monster = {}
            parts = monster_state.split(':')
            monster[:name] = parts[0]
            monster[:hp] = parts[5].to_i
            monster[:type] = parts[6].to_i
            monster
        end
        state
    end
end

request = ARGV[0].split '#'
case request.shift
when 'T'
    puts TEAM_SPEC
when 'C'
    battle_state = parse_battle_state request
    my_state = battle_state[0]
    puts my_state[:monsters].find_index {|monster| monster[:hp] > 0}
when 'A'
    battle_state = parse_battle_state request
    my_state, their_state = *battle_state
    my_monster = my_state[:monsters][my_state[:active]]
    their_monster = their_state[:monsters][their_state[:active]]
    puts [1,0,1,2,0][their_monster[:type]]
when 'B'
    puts '0:0:0'
end

与运行

ruby InsideYourHead.rb

这对Manu的机器人来说效果不佳,但超过了其他三个。团队和怪物的名字是随机的...如果我想出更好的东西,我可能会改变他们

策略很简单:攻击!所有三个怪物仅具有纯攻击招式,并且它们根据对手怪物的类型选择招式。

我可能会稍后尝试进行“治疗”。


1
呵呵,这变得更加有趣。我知道我可以指望你,马丁:)

6

Java LittleKid

一个小孩发现了3个相同的鳕鱼,并对其进行了训练。他们的治疗+毒药攻击非常令人讨厌。由于毒药对所有类型的毒药都有效,因此仅使用普通类型的鱼肉就无需将它们与特定敌人配对。

public class LittleKid {

    public static void main(String[] args) {
        if(args.length < 1){
            System.out.println("Geobits says you can't do this.");
            System.exit(0);
        }

        String[] sections = args[0].split("#");
        String me, them, out = "";
        switch(sections[0]){
            case "T":
                out = "LittleKid";
                out += "|Poisoner:0:80:100:50:0:1:13";
                out += "|Poisoner:0:80:100:50:0:1:13";
                out += "|Poisoner:0:80:100:50:0:1:13";
                break;
            case "B":
                out = "1:1:1";
                break;
            case "C":
                me = sections[1];
                them = sections[2];
                int pick = 0;

                if(!isAlive(me, pick)){
                    for(int i=0;i<3;i++){
                        if(isAlive(me,i))
                            pick = i;
                    }
                }

                out = String.valueOf(pick);
                break;
            case "A":
                me = sections[1];
                them = sections[2];
                int active = getActive(me);
                int enemyActive = getActive(them);
                if (getField(me, HP, active) < 50 && getField(me, MOVE1, active) != 0) {
                    out = "1";
                } else if (getEffectCount(them, POISON, enemyActive, false) < 1 && getField(me, MOVE2, active) != 0) {
                    out = "2";
                } else {
                    out = "0";
                }
                break;
            default:
                out = "Invalid query from controller.";             
        }
        System.out.println(out);
    }

    static boolean isAlive(String teamState, int who){
        return getField(teamState, HP, who) > 0;
    }

    static int getActive(String teamState){
        return Integer.parseInt(teamState.split("\\|")[0].split(":")[1]);
    }

    static int getField(String teamState, int field, int who){
        String[] fields = teamState.split("\\|")[who+1].split(":");
        return Integer.parseInt(fields[field]);
    }

    static int getEffectCount(String teamState, int effect, int who, boolean mine){
            String[] fields = teamState.split("\\|")[who+1].split(":");
            int count = 0;
            for(int i=mine?14:8;i<fields.length;i++){
                if(Integer.parseInt(fields[i]) == effect)
                    count++;
            }
            return count;
    }

    final static int ID =       1; 
    final static int ATTACK =   2; 
    final static int DEFENSE =  3; 
    final static int SPEED =    4; 
    final static int HP =       5; 
    final static int TYPE =     6;
    final static int MOVE0 =    8; 
    final static int MOVE1 =    9; 
    final static int MOVE2 =    10;

    final static int POISON =           1;
}

5
Geobits说您不能这样做 ”:D
Geobits

似乎毒药是这场游戏中真正的炸弹:)

5

Nodémon-Javascript

由于地位似乎是主要策略,因此该团队专注于速度,以首先将毒药和混乱之类的状况带给对手,然后在对手浪费时间的同时with愈和/或睡眠。

我没有安装PHP,因此尚未针对Campers进行测试,但在我的测试中,LittleKid似乎是它的一个不错的竞争对手(并降低了Bitter Rivals)。

/*jshint node:true*/
'use strict';

var fs = require('fs');

var dataFile = 'Nodemon/data.json';
function getData(callback) {
  fs.readFile(dataFile, 'utf8', function(err, contents) {
    var data = {round: 0};

    if(!err) {
      data = JSON.parse(contents);
    }

    callback(data);
  });
}

function saveData(data, callback) {
  fs.mkdir('Nodemon', function() {    
    fs.writeFile(dataFile, JSON.stringify(data), callback);
  });
}

var effect = {
  poison: '1',
  confusion: '2',
  burn: '3',
  sleep: '4',
  heal: '5',
  attackUp: '6',
  attackDown: '7',
  defenseUp: '8',
  defenseDown: '9',
  speedDown: '10'
};

function parseMemberCommon(args) {
  return {
    name: args[0],
    id: args[1],
    baseAttack: +args[2],
    baseDefense: +args[3],
    baseSpeed: +args[4],
    hp: +args[5],
    typeId: args[6],
    poisonedTurns: +args[7],
    effects: args.slice(8)
  };
}

function parseOwnMember(arg) {
  var args = arg.split(':');

  var ownArgs = args.splice(8, 6);

  var member = parseMemberCommon(args);

  member.moveCount = [
    +ownArgs[0],
    +ownArgs[1],
    +ownArgs[2]
  ];

  member.bonusAttack = +ownArgs[3];
  member.bonusDefense = +ownArgs[3];
  member.bonusSpeed = +ownArgs[3];

  return member;
}

function parseOpponentMember(arg) {
  return parseMemberCommon(arg.split(':'));
}

function parseTeamStateCommon(arg, memberParse) {
  var args = arg.split(':');
  var state = {
    name: args[0],
    members: []
  };
  args = arg.substring(state.name.length + 1).split('|');
  var activeSlot = args[0];
  for(var index = 1; index < args.length; index++) {
    state.members.push(memberParse(args[index]));
  }
  state.activeMember = state.members[activeSlot];
  return state;
}

function parseOwnState(arg) {
  return parseTeamStateCommon(arg, parseOwnMember);
}

function parseOpponentState(arg) {
  return parseTeamStateCommon(arg, parseOpponentMember);
}

function parseBattleState(arg) {
  var args = arg.split('#');
  return {
    own: parseOwnState(args[0]),
    opponent: parseOpponentState(args[1])
  };
}

function teamData() {

  saveData({round:0}, function() {
    console.log('Nodemon|' + 
      'Charasaur:0:50:80:100:10:13:1|' +
      'Bulbtortle:4:50:80:100:10:13:1|' +
      'Squirtmander:1:50:80:100:10:13:4');
  });
}

function getActiveIndex(battleState) {
  for(var index = 0; index < battleState.own.members.length; index++) {
    var member = battleState.own.members[index];
    if(member.hp > 0) {
      return index;
    }
  }
}

function chooseActive(arg) {
  var battleState = parseBattleState(arg);

  getData(function(data) {
    var allFull = true;
    for(var index = 0; index < battleState.opponent.members.length; index++) {
      var member = battleState.opponent.members[index];
      if(!data.maxSpeed || member.baseSpeed > data.maxSpeed) {
        data.maxSpeed = member.baseSpeed;
      }
      if(member.hp < 100) {
        allFull = false;
      }
    }

    if(allFull) {
      data.round++;
    }

    saveData(data, function() {
      console.log(getActiveIndex(battleState));
    });    
  });
}

function useMove(moves, battleState) {
  var fighter = battleState.own.activeMember;

  for(var moveIndex = 0; moveIndex < moves.length; moveIndex++) {
    var move = moves[moveIndex];
    if(fighter.moveCount[move]) {
      return move;
    }

    for(var memberIndex = 0; memberIndex < battleState.own.members.length; memberIndex++) {
      var member = battleState.own.members[memberIndex];

      if(member.hp > 0 && member.moveCount[move] > 0) {
        return 10 + memberIndex;
      }
    }
  }

  return -1;  //do nothing
}

function battleAction(arg) {
  var battleState = parseBattleState(arg);

  var fighter = battleState.own.activeMember;
  var opponent = battleState.opponent.activeMember;

  var attemptedMoves = [];

  if(opponent.effects.indexOf(effect.poison) === -1) {
    attemptedMoves.push(1);
  }

  if(opponent.effects.indexOf(effect.confusion) === -1) {
    attemptedMoves.push(0);
  }

  if(fighter.name === 'Squirtmander') {
    //sleep
    if(opponent.effects.indexOf(effect.sleep) === -1) {
      attemptedMoves.push(2);
    }
  }
  else {
    //heal
    if(fighter.hp <= 60) {
      attemptedMoves.push(2);
    }
  }

  console.log(useMove(attemptedMoves, battleState));
}

function bonusStats(arg) {
  var teamState = parseOwnState(arg);

  getData(function(data) {
    var result = '1:';

    if(data.round % 4 === 0) {
      result += '1:';
    }
    else {
      result += '2:';
    }
    if(teamState.members[2].baseSpeed + teamState.members[2].bonusSpeed > data.maxSpeed + (data.round / 2)) {
      result += '1';
    }
    else {
      result += '2';
    }
    console.log(result);
  });
}

var actions = {
  'T': teamData,
  'C': chooseActive,
  'A': battleAction,
  'B': bonusStats
};

var arg = process.argv[2];
actions[arg[0]](arg.substring(2));

与运行

node nodemon

PS 致歉nodemon


这正在升级为服务器端脚本的全球战争:D

4

激烈的竞争对手-Java

一个喜欢将其切换的草/火/水团队。

绿龙

至少对任何人都有中立的报道。高速弥补不足的防守。

Type: Grass
Attack:   80     Vine
Defense:  50     Punch
Speed:   100     Pain

西里扎德

尝试以较低的攻击力伤害敌人。之后烧伤和火球。

Type: Fire
Attack:  100     Fireball
Defense:  50     Burn
Speed:    80     Sap

疾风盾

使用盾牌来增强其本已很高的防御力。必要时愈。

Type: Water
Attack:   80     Watergun
Defense: 100     Shield
Speed:    50     Heal

这也包括在控制器中。这一支与DummyTeam不同的竞争团队。需要的命令players.conf是:

java BitterRivals

public class BitterRivals {

    public static void main(String[] args) {
        if(args.length < 1){
            System.out.println("You're not doing this right. Read the spec and try again.");
            System.exit(0);
        }

        String[] sections = args[0].split("#");
        String me, them, out = "";
        switch(sections[0]){
            case "T":
                out = "BitterRivals";
                out += "|Greenosaur:4:80:50:100:12:0:3";
                out += "|Searizard:2:100:50:80:6:7:14";
                out += "|Blastshield:3:80:100:50:9:11:1";
                break;
            case "B":
                out = "2:0:1";
                break;
            case "C":
                me = sections[1];
                them = sections[2];

                int pick = 0;
                switch(getField(them, TYPE, getActive(them))){
                    case 0:
                    case 1:
                    case 3:
                        pick = 0;
                        break;
                    case 2:
                        pick = 2;
                        break;
                    case 4:
                        pick = 1;
                        break;
                }

                if(!isAlive(me, pick)){
                    for(int i=0;i<3;i++){
                        if(isAlive(me,i))
                            pick = i;
                    }
                }

                out = pick + "";
                break;
            case "A":
                me = sections[1];
                them = sections[2];
                int active = getActive(me);
                int oType = getField(them, TYPE, getActive(them));
                switch(active){
                    case 0:         // Greenosaur
                        switch(oType){
                            case 0:
                            case 4:
                                out = "1";
                                break;
                            case 1:
                                out = "2";
                                break;
                            case 3:
                                out = "0";
                                break;
                            case 2:
                                if(isAlive(me, 2)){
                                    out = "12";
                                } else if(isAlive(me, 1)){
                                    out = "11";
                                } else {
                                    out = "1";
                                }
                                break;
                        }
                        break;
                    case 1:         // Searizard
                        if(oType == 3){
                            if(isAlive(me, 0)){
                                out = "10";
                                break;
                            } else if(isAlive(me, 2)){
                                out = "12";
                                break;
                            }
                            if(getEffectCount(them, BURN, getActive(them), false) < 1 && getField(me, MOVE1, active) > 0){
                                out = "1";
                            } else if(getField(me, MOVE2, active) > 0){
                                out = "2";
                            } else {
                                out = "3";
                            }                           
                        } else {
                            if(getField(them, ATTACK, getActive(them)) < 80){
                                if(getEffectCount(them, DEFENSE_DOWN, getActive(them), false) < 1 && getField(me, MOVE2, active) > 0){
                                    out = "2";
                                    break;
                                } else if(getEffectCount(them, BURN, getActive(them), false) < 1 && getField(me, MOVE1, active) > 0){
                                    out = "1";
                                    break;
                                }
                            }
                            out = "0";
                        }
                        break;
                    case 2:         // Blastshield
                        if(oType == 4){
                            if(isAlive(me, 1)){
                                out = "11";
                                break;
                            } else if(isAlive(me, 0)){
                                out = "10";
                                break;
                            }
                        }
                        if(getField(me, HP, active) < 50 && getField(me, MOVE2, active) > 0){
                            out = "2";
                        } else if(getEffectCount(me, DEFENSE_UP, active, true) < 3 && getField(me, MOVE1, active) > 0){
                            out = "1";
                        } else {
                            out = "0";
                        }
                        break;
                }
                break;
            default:
                out = "Invalid query from controller.";             
        }
        System.out.println(out);
    }

    static boolean isAlive(String teamState, int who){
        return getField(teamState, HP, who) > 0;
    }

    static int getActive(String teamState){
        return Integer.parseInt(teamState.split("\\|")[0].split(":")[1]);
    }

    static int getField(String teamState, int field, int who){
        String[] fields = teamState.split("\\|")[who+1].split(":");
        return Integer.parseInt(fields[field]);
    }

    static int getEffectCount(String teamState, int effect, int who, boolean mine){
            String[] fields = teamState.split("\\|")[who+1].split(":");
            int count = 0;
            for(int i=mine?14:8;i<fields.length;i++){
                if(Integer.parseInt(fields[i]) == effect)
                    count++;
            }
            return count;
    }

    final static int ID =       1; 
    final static int ATTACK =   2; 
    final static int DEFENSE =  3; 
    final static int SPEED =    4; 
    final static int HP =       5; 
    final static int TYPE =     6; 
    final static int PTURNS =   7; 
    final static int MOVE0 =    8; 
    final static int MOVE1 =    9; 
    final static int MOVE2 =    10; 
    final static int HA =       11; 
    final static int HD =       12; 
    final static int HS =       13; 

    final static int POISON =           1;
    final static int CONFUSION =        2;
    final static int BURN =             3;
    final static int SLEEP =            4;
    final static int ATTACK_UP =        6;
    final static int ATTACK_DOWN =      7;
    final static int DEFENSE_UP =       8;
    final static int DEFENSE_DOWN =     9;
    final static int SPEED_DOWN =       10;
}

4

错误310:重定向过多-C ++

一支训练有素,训练有素的团队,以对抗毒药的破坏

三个星期以来,我几乎没有训练过我的鳕鱼。我组成了几个团队。最后,我准备面对这个挑战。为了回答我所有的毒药反对者,我组成了一个团队,他们拥有非常不同的鳕鱼,每个角色都有特定的角色。


解毒剂(图片)

Type : Normal - atk:50 def:100 spd:80 - Poison/Burn/Heal

解毒剂爱毒药。如此之多,以至于我无法阻止他急于进行毒药袭击。


(图片)

Type : Fire - atk:100 def:80 spd:50 - Poison/Vine/Heal

禅宗是一种非常令人惊讶的杂种,可以容纳所有效果。他更喜欢看着敌人为抵抗自己的沉默而奋斗和疲惫。


特力(图片)

Type : Psychic - atk:88 def:60 spd:82 - Fireball/Watergun/Vine

Triforce是经典的codémon,随时准备战斗。这个人用他的精神力量来控制这三个要素,并造成尽可能多的损失。


您可以在此处下载团队:

Linux:

http://dl.free.fr/iHYlmTOQ2

与启动 ./Error310TMR

Windows:

http://dl.free.fr/vCyjtqo2s

与启动 ./Error310TMR.exe

该代码是一个完整的c ++项目。我不知道如何发布。

$ wc -l src/*
    165 src/BruteForce.cpp
     26 src/BruteForce.h
    349 src/Codemon.cpp
     77 src/Codemon.h
     21 src/Logger.cpp
     35 src/Logger.h
    105 src/NoTimeToExplain.cpp
     27 src/NoTimeToExplain.h
    240 src/Recoverator.cpp
     31 src/Recoverator.h
     26 src/StrManip.cpp
     16 src/StrManip.h
    303 src/Team.cpp
     68 src/Team.h
     88 src/TooManyRedirects.cpp
     24 src/TooManyRedirects.h
     87 src/Unrecoverable.cpp
     27 src/Unrecoverable.h
     59 src/enums.cpp
    119 src/enums.h
     68 src/main.cpp
   1961 total

但这非常有效:

------- Final Results -------

176     Error310TMR
131     H3C
130     LittleKid
121     Nodemon
58      InsideYourHead
47      HardenedTrio
37      BitterRivals

2

童话

一个相当普通的中级团队。基于试图做自己的事情的三个原型,如果根本无法做自己的事情,则将其切换。

该团队是在看起来像毒药成为新元素之前就创建的,自从我最初组成团队以来,我就一直没有真正跟上改变团队的步伐,大部分时间都花在了试图解决问题上。我尚未能够运行锦标赛来进行测试,但是这是非常繁忙的一周。如果此功能实际上无法像我的测试数据那样正常工作,那么在工作后,我将对其进行更多处理。

#!/bin/perl
use 5.20.0;
use strict;

use constant MINE => 0;
use constant THEIRS => 1;

$_ = $ARGV[0];

if(/^T/){
    say 'FairyTale|Fairy:1:89:90:51:3:4:13|Dragon:2:100:50:80:6:1:8|Assassin:0:70:60:100:0:1:10';

} elsif(/^C#(.*)/){
    my $state = readBattleState($1);
    if($state->[MINE]->{$state->[MINE]->{slot}}{hp}){
        say $state->[MINE]->{slot};
    } elsif($state->[MINE]->{($state->[MINE]->{slot}+1)%3}{hp}){
        say (($state->[MINE]->{slot}+1)%3);
    } else {
        say (($state->[MINE]->{slot}+2)%3);
    }

} elsif(/^A#(.*)/){
    my $state = readBattleState($1);
    my @actives = (
        $state->[MINE]->{$state->[MINE]->{slot}},
        $state->[THEIRS]->{$state->[THEIRS]->{slot}}
    );
    if($state->[MINE]->{slot} == 0){
        if(!exists($actives[THEIRS]{effects}{4}) && $actives[MINE]{pp}->[1]){
            say 1;
        } elsif(!exists($actives[THEIRS]{effects}{1}) && $actives[MINE]{pp}->[2]) {
            say 2;
        } elsif(!$actives[THEIRS]{type}) {
            if($state->[MINE]->{($state->[MINE]->{slot}+1)%3}{hp} > 0){
                say (($state->[MINE]->{slot}+1)%3);
            } elsif($state->[MINE]->{($state->[MINE]->{slot}+2)%3}{hp} > 0) {
                say (($state->[MINE]->{slot}+2)%3);
            } else {
                say 0;
            }
        } else {
            say 0;
        }
    } elsif($state->[MINE]->{slot} == 1){
        if(!exists($actives[MINE]{effects}{6}) && $actives[MINE]{pp}->[2]){
            say 2;
        } elsif ($actives[MINE]{hp} > 10 && $actives[MINE]{hp} < 50 && $actives[MINE]{pp}->[1]){
            say 1;
        } else {
            say 0;
        }
    } elsif($state->[MINE]->{slot} == 2){
        if(!exists($actives[MINE]{effects}{6}) && $actives[MINE]{pp}->[2]){
            say 2;
        } elsif ($actives[MINE]{hp} > 10 && $actives[MINE]{hp} < 50 && $actives[MINE]{pp}->[1]){
            say 1;
        } elsif($actives[THEIRS]{type} == 1) {
            if($state->[MINE]->{($state->[MINE]->{slot}+1)%3}{hp} > 0){
                say (($state->[MINE]->{slot}+1)%3);
            } elsif($state->[MINE]->{($state->[MINE]->{slot}+2)%3}{hp} > 0) {
                say (($state->[MINE]->{slot}+2)%3);
            } else {
                say 0;
            }
        } else {
            say 0;
        }
    }

} elsif(/^B#(.*)/){
    my $state = readTeam($1, 1);
    say '1:0:2';
}

sub readBattleState {
    local $_ = $_[0];
    if(/^(.*?)#(.*?)$/){
        my @teams;
        $teams[0] = readTeam($1, 1);
        $teams[1] = readTeam($2, 0);
        return \@teams;
    }
}

sub readTeam {
    my $isMine = $_[1];
    local $_ = $_[0];
    if(/.*?:(?<slot>.*?)\|(.*?)\|(.*?)\|(.*?)$/){
        my %team;
        $team{slot} = $1;
        $team{0} = $isMine ? readYourMember($2) : readTheirMember($2);
        $team{1} = $isMine ? readYourMember($3) : readTheirMember($3);
        $team{2} = $isMine ? readYourMember($4) : readTheirMember($4);
        return \%team;
    }
    return 0;
}

sub readYourMember {
    local $_ = $_[0];
    if(/(?<name>.*?):(?<id>.*?):(?<atk>.*?):(?<def>.*?):(?<spd>.*?):(?<hp>.*?):(?<type>.*?):(?<poison>.*?):(?<move0>.*?):(?<move1>.*?):(?<move2>.*?):(?<batk>.*?):(?<bdef>.*?):(?<bspd>.*?)(?<effects>(?::.*)|$)/){
        my %effects = map { $_ => 1 } readEffects($+{effects});
        my %member = (
            name   => $+{name},
            id     => $+{id},
            hp     => $+{hp},
            atk    => $+{atk}+$+{batk},
            def    => $+{def}+$+{bdef},
            spd    => $+{spd}+$+{bspd},
            type   => $+{type},
            pp     => [$+{move0}, $+{move1}, $+{move2}],
            poistrn=> $+{poison},
            effects=> \%effects
        );
        return \%member;
    }
}

sub readTheirMember {
    local $_ = $_[0];
    if(/(?<name>.*?):(?<id>.*?):(?<atk>.*?):(?<def>.*?):(?<spd>.*?):(?<hp>.*?):(?<type>.*?):(?<poison>.*?)(?<effects>(?::.*)|$)/){
        my %effects = map { $_ => 1 } readEffects($+{effects});
        my %member = (
            name   => $+{name},
            id     => $+{id},
            hp     => $+{hp},
            atk    => $+{atk},
            def    => $+{def},
            spd    => $+{spd},
            type   => $+{type},
            poistrn=> $+{poison},
            effects=> \%effects
        );
        return \%member;
    }
    return 0;
}

sub readEffects {
    local $_ = $_[0];
    my @retval = /:([^:]*)/g;
    if(!@retval){
        @retval = (0);
    }
    return @retval;
}

与运行

perl fairytale.pl

该机器人因第一次死亡后试图“选择活跃的”死亡成员而被踢出去。我从未看到过第一场战斗。
Geobits'2

真?我以为我之前已经解决了该错误,也许这是该代码的旧版本……
mezzoEmrys 2015年

不要忘了,当一个Codemon被淘汰时,他的恢复点降低到0 或更小。因此,if($state->[MINE]->{$state->[MINE]->{slot}}{hp})如果没有,该语句将无法正常工作>0
GholGoth15年

嗯,是的,可以做到。
mezzoEmrys 2015年

0

虚拟团队-Java

(不竞争的CW)

这是一个要练习的虚拟团队。这是所有普通类型,每回合在它们的移动(打孔,治疗,减速)之间随机选择。玩得开心。

public class DummyTeam {

    public static void main(String[] args) {
        if(args.length < 1){
            System.out.println("You need to run this from the tournament. Try to keep up.");
            System.exit(0);
        }

        String[] sections = args[0].split("#");
        String out = "";
        switch(sections[0]){
            // team data
            //      sends back all Normal types with minimum stats and Normal moves (randomized name suffixes to distinguish in tests)
            case "T":
                out = "DummyTeam";
                for(int i=0;i<3;i++)
                    out += "|Dummy"+((char)(Math.random()*26)+65) + i + ":0:50:50:50:0:1:2";
                break;
            // bonus points
            //      shoves them all in defense every time
            case "B":
                out = "1:1:1";
                break;
            // choose active
            //      picks last active if alive, otherwise loops to find first living member
            case "C":
                String[] team = sections[1].split("\\|");
                int current = Integer.parseInt(team[0].split(":")[1]);
                if(Integer.parseInt(team[current+1].split(":")[5]) > 0){
                    out = current + "";
                } else {
                    for(int i=1;i<team.length;i++){
                        if(Integer.parseInt(team[i].split(":")[5]) > 0){
                            out = (i - 1) + "";
                        }
                    }
                }               
                break;
            // choose action
            //      chooses a random move. does not check if it ran out of uses, so wastes turns quite often
            case "A":
                out = ((int)(Math.random()*3)) + "";
                break;
            default:
                out = "Invalid query from controller.";             
        }
        System.out.println(out);
    }


}
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.