惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
Recent Announcements
Recent Announcements
雷峰网
雷峰网
The GitHub Blog
The GitHub Blog
罗磊的独立博客
月光博客
月光博客
J
Java Code Geeks
A
About on SuperTechFans
Microsoft Security Blog
Microsoft Security Blog
D
Docker
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
F
Fortinet All Blogs
U
Unit 42
C
Check Point Blog
Martin Fowler
Martin Fowler
有赞技术团队
有赞技术团队
博客园 - 叶小钗
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
酷 壳 – CoolShell
酷 壳 – CoolShell
Blog — PlanetScale
Blog — PlanetScale
大猫的无限游戏
大猫的无限游戏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
阮一峰的网络日志
阮一峰的网络日志
MyScale Blog
MyScale Blog

博客园 - 方东信

【far 语言】语言文档目录 【far 语言】注解系统 【far 语言】数组 【far 语言】并发编程(协程) 【far 语言】控制流 【far 语言】异常处理 【far 语言】farcc 构建工具 【far 语言】函数 【far 语言】组合与继承 【far 语言】接口与泛型 【far 语言】List 列表 【far 语言】Map 映射 【far 语言】原生内存与 FFI 【far 语言】字符串 【far 语言】语法总览 【far 语言】类型系统 Java 远程调用类,控制类的办法,老了,记不住了。靠 java opc ua 基于s7 音视频:JavaCV 采集桌面画面并显示的方法 pand3d实现服务端渲染并推流 UI弹窗遮罩屏蔽触发事件的处理 far的数据类型 Windows下Tesseract-OCR的安装与使用 LoRA配置 大模型三阶段训练方法(LLaMa Factory) windows系统下anaconda的安装和使用 trl ppo 【手把手从零实现】Qwen2.5-VL:环境配置/功能实验(图片识别理解、目标检测、文字OCR、文档解析、视频理解)/模型微调(MS-Swift 和 LLaMA-Factory) seata 1.8.0 报错大全 Springboot 报错 java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking
far语言写的回合制战斗逻辑
方东信 · 2025-06-04 · via 博客园 - 方东信



static map skillsConf = ({});


///*实际伤害 = [(攻击方.str + 攻击方.combatExp / 100) * (1 + 攻击方.int / 100)] - (防御方.con / 2)
//
//若 攻击方.dex / 防御方.dex > 随机数(0, 1),则攻击方躲避防御方反击
//若 防御方.dex / 攻击方.dex > 随机数(0, 1),则防御方躲避攻击,实际伤害 = 0*/

static number fight(object me, object victim){

    map kEntire = me.entityData();
    map vEntire = victim.entityData();
    //伤害
    number kdmg = ( kEntire["str"] + kEntire["combatExp"] / 100 ) * (1 + kEntire["int"] / 100) ;
    println(me.query("name")+" 开始伤害是"+kdmg);

    number vDef =  vEntire["con"] / 2;
    kdmg = kdmg - vDef;

    if (randomRange(0,5) < vEntire["dex"] / kEntire["dex"]){
        println("没打中");
    }else{
        vEntire["qi"] -= kdmg;
    }


    println(fmt("%s 气是 %s",victim.query("name"),vEntire["qi"]));

    if( vEntire["qi"] < 1  ){
        string msg = fmt("%s 口吐鲜血,一口气上不来死了。",victim.query("name"));
        tellObject(me,msg);
        println(msg);

        me.removeKiller(victim);
        victim.die();
//
        me.set("pot",me.query("pot")+20);
        tellObject(me,fmt("战斗胜利 修为 + %s",20));


        return 1;
    }

    println(fmt("%s(%s) -> %s(%s)",me.query("name"),kEntire["qi"],victim.query("name"),vEntire["qi"]));


}


//获取物理站位的名称
static string posDesc(number posId){
    string desc;
    if( posId==1 ){
        desc="左(后上)";
    }else if(posId==2){
        desc="左(后中)";
    }else if(posId==3){
        desc="左(后下)";
    }else if(posId==4){
        desc="左(前上)";
     }else if(posId==5){
         desc="左(前中)";
     }else if(posId==6){
         desc="左(前下)";
     }else if(posId==7){
          desc="右(前上)";
      }else if(posId==8){
          desc="右(前中)";
      }else if(posId==9){
          desc="右(前下)";
       }else if(posId==10){
           desc="右(后上)";
       }else if(posId==11){
           desc="右(后中)";
       }else if(posId==12){
           desc="右(后下)";
       }else{
            desc="位置数据错误!";
       }
       return desc;
}

static number getPosOf(number vPosId,map target){
    foreach(e in target){
        println(e);
    }
}
//计算伤害
static number calcDamage(map killer,map buf,number baseDamage){

 if(  buf["resultType"] > 1){//调整比例
    if( buf["refChangeType"]==1 && buf["refTarget"]==1){//增加模式
        baseDamage += baseDamage * buf["refChangeVal"];
    }
  }

  if(  sizeof(killer["effs"]) > 0 ){
    foreach( e in killer["effs"]){
        if( e["type"] == "减伤" && e["duration"] > 0){
            println(fmt("减伤 %s",baseDamage * e["refChangeVal"]));
            baseDamage-= baseDamage * e["refChangeVal"];
        }
    }
  }

  return baseDamage;
}

static number rdKill(map killer,map kSkillData,map kBuf, map victim,number currRound,string* combatMessage){


    //伤害
    number kdmg = ( killer["str"] + killer["combatExp"] / 100 ) * (1 + killer["int"] / 100) ;
//    println(killer["name"]+" 开始伤害是"+kdmg);

    number vDef =  victim["con"] / 2;
    kdmg = kdmg - vDef;
    number rand = randomRange(0,5);
    number dexRate = victim["dex"] / killer["dex"];


    var attackSk = killer["skills"]["attack"];

    if( !this::skillsConf ){
        println("skillConf没有数据啊!");
        return 1;
    }
    map skillData = kSkillData;
        //大当家(200/200, 能量:50/50)<左(前下)> 使出 十八摸(抓手)(消耗20能量) 攻击 李阿婆(200/200, 能量:50/50)<右(前上)>
      //→ 攻击命中!造成20.52点伤害(25攻-4.48防),附加迟缓(Buf 0,闪避-20%,持续2回合)
     // → 大当家能量剩余:30/50


    map buf = kBuf;//skillData["bufs"][random(sizeof(skillData["bufs"]))];
    map carryEffect = ({});
    //恢复类效果的值
    number recoverVal;

    object kOb = killer["teamLeader"];
    object vOb = victim["teamLeader"];
    string skName = skillData["name"];
    string skBufName = buf["name"];
    string kPosDesc = this::posDesc(killer["pPos"]);
    string vPosDesc = this::posDesc(victim["pPos"]);
    string* kmsg;
//    string batMsg1 = fmt("%s(%s)<%s> 使出 %s(%s) 攻击 %s(%s)<%s> ",killer["name"],killer["qi"],kPosDesc,  skillData["name"],buf["name"],victim["name"],victim["qi"],vPosDesc);

    //[回合N] 大当家(气血:200/200 | 能量:50/50)<左(前下)> 释放技能「十八摸·抓手」(消耗能量20)
    string kStr =  fmt("[回合%s] %s(气:%s/%s | 能:%s/%s)<%s>",currRound,killer["name"],killer["qi"],killer["maxQi"],killer["neili"],killer["maxNeili"],kPosDesc);
    string vStr = fmt(" -> 目标: %s(气:%s/%s | 能:%s/%s)<%s>\n",victim["name"],victim["qi"],victim["maxQi"],victim["neili"],victim["maxNeili"],vPosDesc);
    string btMsg="";

    string kTitle = fmt("%s(气 %s/%s 能 %s/%s)<%s>",killer["name"],killer["qi"],killer["maxQi"],killer["neili"],killer["maxNeili"],kPosDesc);
    string vTitle = fmt("%s(气 %s/%s 能 %s/%s)<%s>",victim["name"],victim["qi"],victim["maxQi"],victim["neili"],victim["maxNeili"],vPosDesc);
    string actType;
    string skillMsg;
    string batMsg;
    string effMsg="";

// [回合1] 大当家(气血:200/200 | 能量:50/50)<左(前下)> 释放技能「十八摸·抓手」(消耗能量20)
//   → 目标:李阿婆(气血:200/200 | 能量:50/50)<右(前上)>
//   → 计算:攻击强度25 - 目标防御4.48 = 基础伤害20.52
//   → 结果:命中!造成**20.52点伤害**(气血剩余:**179.48/200**)
//   → 附加效果:迟缓(Buf ID:0 | 闪避-20% | 持续2回合)
//   → 执行者状态:能量剩余**30/50**
//
//// [回合2] 李阿婆(气血:179.48/200 | 能量:50/50)<右(前上)> 普通攻击 大当家(气血:200/200 | 能量:30/50)<左(前下)>
//   → 计算:攻击强度15 - 目标防御8 = 基础伤害7
//   → 结果:未命中!(受迟缓影响,闪避+20%)
//   → 执行者状态:能量无消耗 **50/50**
//
//// [回合3] 大当家(气血:200/200 | 能量:30/50)<左(前下)> 释放技能「十八摸·锁喉」(消耗能量30)
//   → 目标:李阿婆(气血:179.48/200 | 能量:50/50)<右(前上)>
//   → 计算:攻击强度30(暴击!×1.2)- 目标防御4.48 = 基础伤害31.52
//   → 结果:暴击命中!造成**31.52点伤害**(气血剩余:179.48 - 31.52 = **147.96/200**)
//   → 附加效果:流血(每回合损失5%气血,持续3回合)
//   → 执行者状态:能量剩余30 - 30 = **0/50**(下一回合无法释放技能)

    number hitTrue = 0;
    //执行前的能量
    number befNeili = killer["neili"];
    skillMsg = fmt("使出 %s(%s)",skName,skBufName);
    if( buf["type"]=="物理攻击" ){
        kdmg = calcDamage(killer,buf,kdmg);

        actType = "攻击";
        if (rand < dexRate){
            batMsg = fmt("但没打中%s",victim["name"]);

            btMsg+=fmt(" -> 结果:未命中 原因 %s < %s\n",rand,dexRate);

        }else{

             hitTrue = 1;

             btMsg+=fmt(" -> 结果:命中 造成 %s 点伤害,目标气血剩余 %s - %s =",kdmg,victim["qi"],kdmg);

             victim["qi"] -= kdmg;

             btMsg+=fmt(" %s\n",victim["qi"]);

            //会不会给对方贴上buf?
            if( has( buf,"afterEffect") && has(buf["afterEffect"],"effs") && sizeof(buf["afterEffect"]["effs"]) > 0 ){
                foreach( e in buf["afterEffect"]["effs"] ){
                    if( !canSetBuf(victim,e) ) continue;

                    e["duration"] = e["cycle"];
                    effMsg+=fmt(" %s 持续%s回合、",e["name"],e["cycle"]);

                    if( !victim["effs"] ){
                        victim["effs"] = ([]);
                        victim["effs"]+=e;
                    }else{
                         victim["effs"]+=e;
                    }
                }
            }
            batMsg = fmt("造成 %s 点伤害。",kdmg);
            if( effMsg ){
                btMsg+=fmt(" -> 附加效果:%s\n",effMsg);
                batMsg+= "还附加了Buf "+effMsg;
            }
        }
    }
    else if( buf["type"] == "治疗"){

//        var aef = buf["afterEffect"]["bufs"][0];
        carryEffect["triggerOdds"]      = buf["triggerOdds"];
        carryEffect["refChangeVal"]     = buf["refChangeVal"];
        carryEffect["resultType"]       = buf["resultType"];
        carryEffect["refTarget"]        = buf["refTarget"];
        carryEffect["refChangeType"]    = buf["refChangeType"];
        carryEffect["costNeili"]        = buf["costNeili"];

        if( buf["resultType"] > 1 && buf["refChangeType"]==1 ){//增加模式
            if(  carryEffect["refTarget"]==4  ){
                recoverVal = victim["maxQi"] * buf["refChangeVal"];
            }
        }
        number costNeili = killer["maxNeili"] * buf["costNeili"] ;

        actType = "治疗";
//        println( fmt(" 当前内里 %s ,消耗内力  %s ->内里减去 结果 %s",killer["neili"],costNeili,killer["neili"] - costNeili) );

        if(  killer["neili"] - costNeili > 1 ){
            killer["neili"] -= costNeili;
            victim["qi"]+=recoverVal;

            btMsg+=fmt(" -> 结果:命中 恢复 %s 点气,目标气剩余 %s\n",recoverVal,victim["qi"]);

            batMsg = fmt("%s 恢复了 %s 点气血",victim["name"],recoverVal);
        }else{
            btMsg+=" -> 结果:未命中\n"
            batMsg = "结果能量不足!";
        }
//        println( fmt("能量消耗 %s ,当前能量 %s",costNeili,killer["neili"]) );



        //预防超量恢复
        if( victim["qi"] > victim["maxQi"] ){
            victim["qi"] = victim["maxQi"];
        }

    }else{

    }


    btMsg+=fmt(" -> 执行者状态 : 能量 %s - %s = %s",befNeili, befNeili - killer["neili"] ,befNeili - (befNeili - killer["neili"]));



    batMsg = fmt( "%s %s %s %s %s", kTitle, skillMsg, actType,vTitle,batMsg );

    kStr+=fmt("使出 %s(%s) -> %s\n",skName,skBufName,actType);


      println(kStr+vStr+btMsg);

        combatMessage+=batMsg;
//       if( kOb.query("isUser")  ){
//
//           kmsg = kOb.query("combatMessage");
//           kmsg+= batMsg;
//       }
//
//       if(vOb.query("isUser") ){
//            kmsg = vOb.query("combatMessage");
//           kmsg+= batMsg;
//       }





       if( victim["qi"] < 1  ){
            combatMessage+=fmt("%s(%s) 口吐鲜血,一口气上不来死了。",victim["name"],victim["qi"]);
//             if( kOb.query("isUser")  ){
//                   kOb.add("combat/reward/pot",20);
//                   combatMessage+=fmt("%s(%s) 口吐鲜血,一口气上不来死了。",victim["name"],victim["qi"]);
//             }
           return 1;
       }




//    println(fmt("%s(%s) -> %s(%s)",killer["name"],killer["qi"],victim["name"],victim["qi"]));



}

//是否能给目标设置Buf
static number canSetBuf(map victim,map buf){

    if( victim["effs"] && sizeof( victim["effs"] ) > 0 ){
        foreach(e in victim["effs"]){
            if( buf["type"]==e["type"] ) return 0;
        }
    }
    return 1;
}

static map* crRound(object k, object v){

    //回合唯一ID

    k.set("combatMessage",([]));
    v.set("combatMessage",([]));

    k.set("rGame/skills/attack","100001");
    k.set("rGame/skills/defense","100002");

     v.set("rGame/skills/attack","100003");
     v.set("rGame/skills/defense","100004");
     map sk1 = ({
        "rGame":({
            "skills":({
                "attack":"100003"
            })
        })

     });

          map sk2 = ({
             "rGame":({
                 "skills":({
                     "attack":"100002"
                 })
             })

          });

//     println("技能显示");
//     println(sk1["rGame"]["skills"]);




    map* que = ([
        ({
             "teamId":k.id(),
             "teamLeader":k,
             "name":k.query("name"),
             "qi":k.query("qi"),
             "maxQi":k.query("maxQi"),
             "neili":k.query("neili"),
             "maxNeili":k.query("maxNeili"),
             "str":k.query("str"),
             "int":k.query("int"),
             "dex":k.query("dex"),
             "combatExp":k.query("combatExp"),
             "skills":k.query("rGame/skills"),
             "con":k.query("con"),
             //虚拟站位 玩家vs玩家时  玩家始终在右边 6格
             "vPos":1,
             //物理站位
             "pPos":6

        }),
         ({
                     "teamId":k.id(),
                      "teamLeader":k,
                     "name":"老色鬼",
                     "qi":100,
                     "maxQi":100,
                      "neili":100,
                      "maxNeili":100,
                      "str":15,
                      "int":15,
                      "dex":15,
                      "combatExp":0,
                       "skills":sk1["rGame"]["skills"],
                      "con":15,
                       "vPos":4,
                       //物理站位
                       "pPos":5

          }),
         ({
             "teamId":v.id(),
              "teamLeader":v,
             "name":v.query("name"),
             "qi":v.query("qi"),
             "maxQi":v.query("maxQi"),
              "neili":v.query("neili"),
              "maxNeili":v.query("maxNeili"),
              "str":v.query("str"),
              "int":v.query("int"),
              "dex":v.query("dex"),
              "combatExp":v.query("combatExp"),
               "skills":v.query("rGame/skills"),
              "con":v.query("con"),
               "vPos":1,
               //物理站位
               "pPos":7
        }),

         ({
                     "teamId":v.id(),
                      "teamLeader":v,
                     "name":"赵灵儿",
                     "qi":100,
                     "maxQi":100,
                      "neili":100,
                      "maxNeili":100,
                      "str":15,
                      "int":15,
                      "dex":15,
                      "combatExp":0,
                       "skills":sk2["rGame"]["skills"],
                      "con":15,
                       "vPos":5,
                       //物理站位
                       "pPos":11
                })

    ]);

    return que;


}

//prev 上一回合数据
static map* nextRound(map *prev){
    //回合唯一ID
    map* nQue = ([]);
    foreach(k in prev){
          k["haveBeenAttack"]=0;
         if( k["qi"] > 0){
           nQue+=k;
         }
    }
    return nQue;
}

//获取对手阵营数据
static map* getEnemyLists(map killer,map* que){
    map* enemys  = ([]);
    foreach(e in que){
        if( e["teamId"]!=killer["teamId"] && e["qi"] > 0 ){
            enemys+=e;
        }
    }
    return enemys;
}
//获取我方成员数据
static map* getAllieLists(map killer,map* que){
    map* enemys  = ([]);
    foreach(e in que){
        if( e["teamId"]==killer["teamId"] && e["qi"] > 0 ){
            enemys+=e;
        }
    }
    return enemys;
}



//我方或者地方的前排
static map* getFront(map* enemys){
    map* enemyLists = ([]);
    foreach( e in enemys ){
        if( e["vPos"] > 0  && e["vPos"] < 4  ){
            enemyLists+=e;
        }
    }
    return enemyLists;
}

//我方或者地方的后排
static map* getBack(map* enemys){
    map* enemyLists = ([]);
    foreach( e in enemys ){
        if( e["vPos"] > 3  && e["vPos"] < 7  ){
            enemyLists+=e;
        }
    }
    return enemyLists;
}


static map getSkiData(map killer){
 //提取出技能
     var attackSk = killer["skills"]["attack"];
    if( !this::skillsConf ){
        println("skillConf没有数据啊!");
        return 1;
    }
    map skillData = this::skillsConf[attackSk];
    if( !skillData ){
        println(attackSk+" 没有找到技能文件");
    }
    return skillData;
}


//从对手集合中随机获取一个对手
static number getEnemyOfRandom(map* enemyQue){
    map enemy = enemyQue[ random(sizeof(enemyQue)-1)  ];
    return enemy;
}

static number selectEnemy(map killer,map* que,number currRound,string* combatMessage){

    map sk = getSkiData(killer);

    map buf = sk["bufs"][random(sizeof(sk["bufs"]))];
    var enemyLists = ([]);
     //1我方前排 2我方后排 3我方所有 4我自己(使用技能的人) 5敌方前排 6敌方后排 7敌方所有 8上一次攻击 9相同占位
    var emys ;

//    if( sizeof(emys) < 1 ) return 3;
    if( buf["findDomain"] == 5 ){//技能要求选择敌方前排
        emys = getEnemyLists(killer,que);
        enemyLists = getFront( emys );
    }else if(buf["findDomain"] == 1){//我方前排
        emys = getAllieLists(killer,que);
        enemyLists = getFront( emys );
    }else{
        emys = getEnemyLists(killer,que);
    }

//    if( killer["name"]=="大当家" ){
//        println(emys);
//        println(enemyLists);
//    }


    //    //对面都没人了...
    if( sizeof(emys) < 1 ) return 3;

    if( !enemyLists || sizeof(enemyLists) < 1 ) enemyLists+= emys[random(sizeof(emys)-1)];


    foreach(kv in enemyLists){
        this::rdKill(killer,sk,buf,kv,currRound,combatMessage);
        return 1;
    }
}



static number getReming(string id,map* que){
    number n=0;
    foreach( k in que ){
        if( k["teamId"]==id ) n++;
    }
    return n;
}


//每个回合 执行buf
static number evalBufs(map k){
    number n = sizeof(k["effs"]);
    if( n > 0 ){
//        for(number i=0;i < sizeof(k["effs"]);i++  ){
//            map e = k["effs"][i];
//            if( k["effs"][i]["duration"] > 0 ){
//                string s = fmt("%s 有 %s buf 剩余%s",k["name"],k["effs"][i]["type"],k["effs"][i]["duration"]);
//                println(s);
//                k["effs"][i]["duration"]--;
//            }
//        }

        foreach( e in k["effs"] ){
            e["duration"]--;
        }

        //过滤掉不需要的
        k["effs"] = filterArray( k["effs"],(e)->{
            return e["duration"] > 0 ;
        } );

//        println(k["effs"]);


    }

    return 1;

}

//能量恢复
static number recoverNeli(map *que){
    foreach(k in que){
        if( k["qi"] < 1 ) continue;

        if(  k["neili"] < k["maxNeili"] ){
             number recoverVal = k["maxNeili"] * 0.02;
             k["neili"]+=recoverVal;
        }

        if( k["neili"] > k["maxNeili"] ){
            println(fmt("当前能量 %s 最大能量 %s",k["neili"],k["maxNeili"]));
            k["neili"] = k["maxNeili"];
        }

    }
}

static number roundFight(object me, object victim){

    map kEntire = me.entityData();
    map vEntire = victim.entityData();

    //构建回合制调度器 交替回合制 所有人出手完成 算一回合

    //获取第n回合 战斗序列
    map* que =  this::crRound(me,victim);

    //如果是PVP 则是两个玩家
    object player = findPlayerObj(que);

    //提取队列分组ID
    string a1Id = me.id();
    string a2Id = victim.id();

    string* combatMessage = ([]);
    number rounCount = 1;
//    for(; sizeof(que) > 1 ;){
    for(  ;; ){
        foreach(k in que){
            if( k["qi"] < 1 ) continue;
             //是否有buf
            evalBufs(k);
            selectEnemy(k,que,rounCount,combatMessage);
        }
        //恢复能量
        recoverNeli(que);

        rounCount++;
        que = nextRound( que );
        if( getReming(a1Id,que) < 1 || getReming(a2Id,que) < 1  ) break;

    }

    println(combatMessage);
    //把战斗记录挂载玩家身上
    player.set("combatMessage",combatMessage);
    println( fmt("%s 回合后 剩下的队伍%s",rounCount,toJsonStr(que)) );

}


static object findPlayerObj(map* que){
    foreach( e in que ){
        if( e["teamLeader"].query("isUser") ){
            return e["teamLeader"];
        }
    }
    return 0;
}



static number testCron(string param){
    println("被计划调用咯"+param);
}

Rust编程语言群 1036955113
java新手自学群 626070845
java/springboot/hadoop/JVM 群 4915800
Hadoop/mongodb(搭建/开发/运维)Q群481975850
GOLang Q1群:6848027
GOLang Q2群:450509103
GOLang Q3群:436173132
GOLang Q4群:141984758
GOLang Q5群:215535604
C/C++/QT群 1414577
单片机嵌入式/电子电路入门群群 306312845
MUD/LIB/交流群 391486684
Electron/koa/Nodejs/express 214737701
大前端群vue/js/ts 165150391
操作系统研发群:15375777
汇编/辅助/破解新手群:755783453
大数据 elasticsearch 群 481975850
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。