回合流程

PM登场流程(主机)

  1. foreach,构造实例,检查幻影
  2. Sendout
  3. Tiles排序
  4. foreach,如果Action == Debut,治愈之愿
  5. foreach,踩钉子
  6. 如果还活着
    1. foreach 未登场,尝试发动紧张感和道具,清除未登场标记
    2. foreach 未登场,尝试发动其他登场发动特性和道具,清除未登场标记
    3. foreach 未登场,尝试发动花之礼物,气象台待测,道具,清除未登场标记
    4. 特别的,对于之前得到紧张感特性的精灵,虽然会因为其他精灵登场而发动紧张感特性,但不会有得到的气球的提示

UseMove流程(主机)

  1. http://pbo.codeplex.com/wikipage?title=AttackAction&referringTitle=Documentation
  2. http://pbo.codeplex.com/wikipage?title=StatusMove&referringTitle=Documentation 

主循环(主机,灰色部分单独编码不在循环中):

  1. <BeginTurn>检查所有在场pm,对于没有行动任务的(Done)
    1. 标记为等待输入(WaitingForInput)
    2. 将玩家添加到输入列表中 
    3. 如果输入列表不为空,InputFinished指向第2步
    4. 对于每个输入列表中的玩家,依次RequireInput,暂停循环等待数据包
    5. 当有ActionInput时,必须是TurnInput,验证该Input,可以覆盖已有的Input,如果该玩家的所有pm都已Input,InputSucceed
    6. 如果Input验证不通过,发送客户端InputFail
    7. 若所有玩家都InputSucceed,通知事件InputFinished,否则继续等待数据包
  2. <Sort>ActivePokemons排序
    1. 随机打乱所有在场pm顺序
    2. 调用Sort,Sort所需要的比较函数见附录
  3. <Prepare>foreach,对于WillUseMove的pm,调用SelectedMove.Prepare(追击订阅Withdraw事件),这并不意味着该Move可以Execute
  4. <Action>foreach(此foreach可能被RequireInput中断,考虑让InputFinished的委托执行登场流程后再次指向此步)
    1. 如果Action!=WillXXX(死亡/追击已经行动了/自由落体)则跳过
    2. 如果是Switch执行交换,Withdraw触发事件(追击),进入PM登场流程(必定只有一头pm)
    3. 如果是UseMove,进入UseMove流程
  5. <EndTurn>EndTurn
    1. 根据回合末计算前时点的速度顺序进行Tiles排序(考虑麻痹、欺骗空间、能力等级等因素)
    2. 对于附录中的回合末顺序的每个大项,依照排序结果,按速度由高到低的顺序按每个小项逐步计算。
    3. 如果发生精灵倒下,判断比赛是否结束。如果双方在同一大项中先后倒下致使没有精灵可用,判定为平局。
    4. 重复步骤2~3,完成EndTurn的计算。
    5. 如果场上有EmptyTile,且该Tile的责任玩家有可以交换出的pm,(第0回合每个玩家依次同时送出前PokemonPerPlayer个精灵,跳到第6步进入pm登场流程)InputFinished指向第6步,RequireInput,否则跳到第8步
    6. 对于SendoutInput,其中所有的Sendout必须没有重复的Position或SendoutId,且均CanSendout,InputSucceed,否则InputFail(ActionInput也用委托实现好了...)
    7.  进入pm登场流程,所有PM登场完毕后,依速度顺序分别执行治愈之愿/新月之舞、钉子以及登场时发动的特性的计算。
    8. 回第5步检查
    9. foreach,缓慢启动及其他与回合有关的状态变化
  6. NextTurn,依然从第一步开始(可以用BeginInvoke避免尾递归,但即使尾递归也不会暴栈,因为有RequireInput中断)

 客户端(包含模拟端,用颜色标出):

  1. 如果收到LeapTurn信息,则提取Turn中的初始化信息,显示游戏界面
    *对于玩家,LeapTurn必为第0回合;对于观战者则可以是任意回合;
  2. foreach(Turn.GameEvents)
    1. 更新战报
    2. 更新Outward
    3. 更新SimGame
  3. 此时再处理上一次收到的AdditionalInfo,用队列先进先出
  4. 如果收到RequireInput
    1. 通过SimGame,判别是RequireTurnInput/RequireSendoutInput
    2. 如果是TurnInput,则获取ActivePokemons*,给所有ActivePokemons一个ActionInput
    3. 如果是SendoutInput,则获取EmptyPositions*,只要还有活着不在场的pm,必须按Positions优先级填入EmptyPositions
    4. 使用ActionInput推送输入
  5. 如果收到InputSucceed,清除RequireInput信息,进入等待模式
  6. 如果收到InputFail,根据RequireInput信息,重新输入

//以下是pm比较方法伪码,注意Sort是降序的
int ComparePokemons(tileA,tileB) //正数A>B 负数A<B 0A==B
{
  if (Tile排序) goto SPEED;
  a = tileA.Pokemon;
  b = tileB.Pokemon;
  if (b==null)
    if (a == null) return 0;
    else return 1;
  if (a == null) return -1;

  if (a.Action == Switch && b.Action==Switch) goto SPEED;
  if (a.Action == Switch) return 1;
  if (b.Action == Switch) return -1;
  if (a.Move.Priority != b.Move.Priority) //检查恶作剧之心
    return a.Move.Priority-b.Move.Priority;
  if (ItemValueA!=ItemValueB)//1=先制爪/先制果发动 0=无道具 -1=后攻尾/满腹香炉发动
    return(ItemValueA-ItemValueB)
  if (a.Ablity==Stall && b.Ability!=Stall) return -1;
  if (b.Ablity==Stall && a.Ability!=Stall) return 1;

SPEED:
  if (TrickRoom) return tileB.Speed - tileA.Speed; //tileX.Speed为当前Pokemon.Speed或上一个Pokemon.Speed(如果濒死/蜻蜓返已收回)
  else return tileA.Speed - tileB.Speed;
}

 


 

回合末顺序
        1.0 天气信息
        2.0沙暴伤害,冰雹伤害,接雨盆,干燥肌肤,寒冰躯体
        3.0 预知未来,破灭之愿
        4.0 许愿
        5.0 火海[火之誓+草之誓]伤害        5.1 蜕皮、湿润身躯、治愈之心        5.2 剩饭、黑色淤泥
        6.0 液体圈
        7.0 扎根
        8.0 寄生种子
        9.0 中毒、剧毒、烧伤、毒疗        9.1 恶梦(技能)
        10.0 鬼系诅咒
        11.0 暂时性束缚技能
        12.0 挑拨结束
        13.0 鼓掌结束
        14.0 残废/诅咒身躯造成的残废结束
        15.0 电磁浮游状态消失
        16.0 念动力状态消失
        17.0 回复封印状态消失
        18.0 扣押状态消失
        19.0 哈欠发动
        20.0 灭亡歌倒计时
        21.0 反射盾消失        21.1 光之壁消失        21.2 神秘守护消失        21.3 白雾消失        21.4 顺风消失        21.5 祈祷消失        21.6 组合技效果消失
        22.0 重力消失
        23.0 欺骗空间消失
        24.0 神奇空间消失
        25.0 魔法空间消失
        26.0 吵闹提示信息
        26.1 加速、恶梦(特性)、收获、心意不定        26.2 毒珠、火珠、附针发动        26.3 拾取特性发动
        27.0 达摩模式特性达摩狒狒转变形态

Last edited Oct 1, 2012 at 5:46 PM by Snowy, version 19

Comments

Snowy Nov 5, 2012 at 2:11 PM 
即使速度最快依然可以发动先制爪
有充足的理由相信回合末上场前只排序一次 测试方法祈雨+轻快剩饭 雨停的那一回合速度慢的轻快依然先发动剩饭

Snowy Oct 22, 2012 at 8:07 AM 
先制之爪的战报在交换前 不过奇怪的是一次全场速度最快的pm带了先制爪死活不发动 不知是否rp问题

Snowy Mar 3, 2012 at 2:50 PM 
@LostKanon 那就按我们后来讨论的改一下吧 你是Editor嘛~

LostKanon Feb 29, 2012 at 6:05 AM 
我想了一下,觉得GameEnd在回合末判定不太合适

Snowy Feb 28, 2012 at 1:37 AM 
事实上就不该InputFail嘛~ 所谓的InputFail判断在模拟端才有意义 TCP的数据包送过来InputFail了视为客户端被修改直接T掉才对