地方游戏,绥江-丢,状态机设计

术语解释:

叫牌:

挖到或者前面的玩家出牌,轮到自己对这个牌发表意见。�� 包括:放弃、吃、筷、对、水、丢

要牌:

当前轮到的牌,自己叫牌优先级最高,可以将牌与自己手中的牌与底牌匹配,吞掉(吃、筷、对、水、丢)

等牌:

其他玩家在对牌做处理,要么是在要牌(等他打出新的牌),要么是在等待这个玩家叫牌。

摸牌:

上一张牌已经确定了没有人叫牌,轮到自己从底牌中拿起新的一张牌。

丢牌:

逻辑

角色与规则定义:

  • 两边是另外两个玩家,玩家轮流摸牌,摸到牌依次叫牌,叫牌后根据优先级最高的人判断给谁优先处理。

  • 每一个玩家摸到牌之后,其他玩家自动弹出对或者吃的提示。由玩家确定要选择哪种,
    特殊点:选择丢牌,则让玩家选出手中用来丢牌的另外两张牌,合法的逻辑就可以让该玩家丢牌,并结束游戏。

  • 要牌的玩家,如果不是丢牌,则需要打出一张新的牌。

  • 叫牌后的牌,分派牌的优先级规则是:吃 < 块 < 块水 < 硬对(或者块水,2张硬牌)< 丢(结束游戏)。

  • 限定要牌的时间为15秒(暂定),限定听牌的时间为20秒(暂定)。

洗牌规则:

  • 模拟短牌在桌面上的洗牌方式。
    对半开+使用随机数(小于10)再分配半的数量,
    得到:数组A + 数组B,在A、B之间随机获得其中一方的最前面一张牌(根据奇偶性质),并移动到新的数组C中,直到AB数组都移除。重复此过程3次即可。

打牌规则:

  • 分为:ABCD三个角色玩家,由系统分配玩家(1234)角色,角色和玩家之间的对应关系为A头家,BC陪玩,D闲家。

  • 发牌以类似区块链的规则处理,底牌直接以每次10张发送给玩家,少于3张时,再次发送10张,直到底牌发完。
    这样每个玩家都有3到13张底牌,可以在摸牌的时候不会因为网络慢而不能立刻看到摸起来的牌。

  • 头家打牌之后,轮次发放牌。发牌之后从摸牌家起轮询是否要牌。

tnA, tnB, tnC: turnA, turnB, turnC
1、挖牌后:
logic A,叫牌:
tnA是否喊牌,然后轮询其他玩家是否拦截。
tnB喊牌,tnC决定是否拦截。
tnC家决定是否要牌,轮询结束。

任意一家轮询过程中给丢牌了,都结束游戏,并且不再轮询后续玩家。

logic B,要拍:
若没有人叫牌,玩家轮流的角色变更。开始新的一轮叫牌。
有人叫牌,
需要前面的玩家再次叫牌,原本优先级低(并且不是叫吃、筷)的玩家是否要丢。
则根据谁的优先级高,分派牌给对应的玩家。
2、头家出牌:排除丢牌的逻辑,B是否要牌,C是否拦截。
B不要牌,C是否要牌。

A的牌,C不能吃。

除了摸牌并有人丢牌,其他情况都是挨个轮询对这个牌的决定,上家要牌后,下家要牌的规则需要比上一家高。
轮询完成后才实行实际的分配,指定玩家得以放牌。

放牌的玩家的下家开始重复逻辑2,如果没有人要牌,重复逻辑1。

伪代码:

服务器对客户端的要牌规则的优先级是:

logic_diu = [](){
    if X 丢了{ 则直接结束, return true}
    return false;
}

logic_hard_couple = [](surplus_players){ 
    if logic_diu(B) { return true; }
    if  logic_diu (C) {return true;}
        
    do it on this player;
    return true;
}
logic_shui_with2xcard = [](surplus_players){
    if logic_hard_couple(B, C) {
        return false;
    }else{
        do it; return true;
    }   
}

logic_kuai_with1xcard = [](surplus_players){
    if logic_shui_with2xcard(B, C) {
        return false;
    }else{
        do it; return true;
    }   
}

任何一种喊法都是可以放弃不要牌的,但是喊吃不能丢,喊筷不能吃和硬对,
func on_player_x_turn(current, surplus){
    status  = ask_player_status(current);
    if status == logic_diu {
                return true;
    }else if status == logic_hard_couple {  // A 硬(无听用)对牌 或者硬水牌(只带一个听用)
        return true;
    }else if status == logic_shui_with2xcard {  //A 水牌+带2个听用
        return true;
    }else if status == logic_kuai_with1xcard {  //筷牌
        return true;    
    }else if status == logic_chi{  
        return true;
    }else{  //status == logic_ignore
        return on_player_x_turn(surplus->next, surplus-1);
    }   
}

客户端配合逻辑:
客户端玩家要牌,需要收到服务器的轮询结论后,才能知道自己的牌是不是可以成功的获得喊出来的机会。
最终的拦截玩家获得放牌的机会,如果获得放牌机会的玩家放弃机会,则把放牌机会留给后面一家。


func call_in_desktop_card(c, others){
  bool did_other_called = false
  int call_priority = 0
  
  others.foreach{
    if ($0.did_call_this_card){
      did_other_called = true;
      call_priority = max($0.call_priority, call_priority)
    }
  }
  higher_logic_call(c, call_priority);
}

while(no_one_did_diu){
  card = waite_to_new_card();  //
  if card.is_from_outside {
    if card.is_from_desktop{
      bool diu = call_in_desktop_card();  //
      if (diu){
        no_one_did_diu = false;
        break;
      }
    }else{  //is from other users
      call_in_other_users_none_desktop_card(card);
    }
  }else{  //is from my turn, got it from desktop
    bool diu = call_in_desktop_card();
    if(diu){
      no_one_did_diu = false;
      break;
    }
  }
}

你可能感兴趣的:(地方游戏,绥江-丢,状态机设计)