private string CalcMinShantenPai(int mypositionId, List<Tehai> tehais, List<Kawa> kawas, Field field) { var syu = new int[MJUtil.LENGTH_SYU_ALL]; foreach (var p in tehais[mypositionId].tehai) { syu[p.PaiNumber]++; } var resultDict = new Dictionary<int, int>(); foreach (var paiId in syu.Select((value, index) => new { value, index })) { if (paiId.value == 0) { continue; } syu[paiId.index]--; resultDict.Add(paiId.index, shantenCalclator.CalcShantenWithFuro(syu, tehais[mypositionId].furos.Count)); syu[paiId.index]++; } var bestShanten = resultDict.OrderBy(e => e.Value).First().Value; var bestNumber = resultDict.Where(e => e.Value == bestShanten).OrderBy( e => Guid.NewGuid() ).First().Key; var paiString = tehais[mypositionId].tehai.Where(e => e.PaiNumber == bestNumber).First().PaiString; return paiString; }
public void ThinkOnFuroDahai(int mypositionId, string pai, List<Tehai> tehais, List<Kawa> kawas, Field field, List<InfoForResult> ifrs, Yama yama) { var myTehai = tehais[mypositionId]; var dahaiPaiString = CalcMinShantenPai(mypositionId, tehais, kawas, field,yama); SendDahai(new MJsonMessageDahai(mypositionId, dahaiPaiString, dahaiPaiString == pai)); }
public bool CanHora(Tehai tehai, InfoForResult ifr, Field field, int dapaiActor, int playerId, string pai) { if (dapaiActor == playerId) { return CanHoraIntsumo( tehai, ifr, field, dapaiActor, playerId, pai); } else { return CanHoraInRon(tehai, ifr, field, dapaiActor, playerId, pai); } }
public static Field ChangeOnRyukyoku(Field fld, List<bool> tenpais) { var IsOyaChange = tenpais[fld.OyaPlayerId] == false ; var nextKyokuId = IsOyaChange ? fld.KyokuId % SAME_WIND_KYOKU_NUM + 1: fld.KyokuId; var nextHonba = fld.Honba + 1; var nextkyotaku = fld.Kyotaku; var nextOyaPlayerId = IsOyaChange ? getNextOyaPlayerId(fld.OyaPlayerId) : fld.OyaPlayerId; var nextBakaze = (nextKyokuId == 1 && IsOyaChange) ? getNextBakaze(fld.Bakaze) : fld.Bakaze; return new Field(nextKyokuId, nextHonba, nextkyotaku, nextOyaPlayerId, nextBakaze.PaiString); }
public static Field ChangeOnHora(Field fld, int horaActor) { var IsOyaChange = horaActor != fld.OyaPlayerId; var nextKyokuId = IsOyaChange ? fld.KyokuId % SAME_WIND_KYOKU_NUM + 1 : fld.KyokuId; var nextHonba = IsOyaChange ? 0 : fld.Honba++; var nextkyotaku = 0; var nextOyaPlayerId = IsOyaChange ? getNextOyaPlayerId(fld.OyaPlayerId) : fld.OyaPlayerId; var nextBakaze = (nextKyokuId == 1 && IsOyaChange) ? getNextBakaze(fld.Bakaze) : fld.Bakaze; return new Field(nextKyokuId, nextHonba, nextkyotaku, nextOyaPlayerId, nextBakaze.PaiString); }
private bool CanHoraIntsumo(Tehai tehai, InfoForResult ifr, Field field, int dapaiActor, int playerId, string pai) { if( tehai.GetShanten() == -1 ) { var horaResult = ResultCalclator.CalcHoraResult(tehai, ifr, field, pai); if (horaResult.yakuResult.HasYakuExcludeDora) { return true; } } return false; }
public void ThinkOnMyTsumo(int mypositionId, string tsumopai, List<Tehai> tehais, List<Kawa> kawas, Field field, List<InfoForResult> ifrs, Yama yama) { var myTehai = tehais[mypositionId]; if (myTehai.IsHora()) { var result = CalcHora(mypositionId, tsumopai); if (result.yakuResult.HasYakuExcludeDora) { if (DisplayHora) { Debug.WriteLine("on tsumo"); Debug.WriteLine(myTehai.ToString()); result.yakuResult.yakus.ForEach(e => Debug.Write(e[0] + ",")); Debug.WriteLine(""); Debug.WriteLine("--------------------------------------------------------------------------------"); } SendHora(new MJsonMessageHora(mypositionId, mypositionId, tsumopai)); CalcHora(mypositionId, tsumopai); return; } } if (ifrs[mypositionId].IsReach) { SendDahai(new MJsonMessageDahai(mypositionId, tsumopai, true)); return; } var dahaiPaiString = CalcMinShantenPai(mypositionId, tehais, kawas, field,yama); if (CanReach(tehais[mypositionId],ifrs[mypositionId],yama)) { MessagebufferForReach = new MJsonMessageDahai(mypositionId,dahaiPaiString, dahaiPaiString == tsumopai); SendReach(new MJsonMessageReach(mypositionId)); return; } SendDahai(new MJsonMessageDahai(mypositionId, dahaiPaiString, dahaiPaiString == tsumopai)); }
private string CalcMinShantenPai(int mypositionId, List<Tehai> tehais, List<Kawa> kawas, Field field, Yama yama) { int fordebug = -1; int[] fordebug2 = new int[0]; try { var restNum = Enumerable.Repeat(4, MJUtil.LENGTH_SYU_ALL).ToArray(); tehais[mypositionId].tehai.ForEach(pai => restNum[pai.PaiNumber]--); tehais.ForEach(player => player.furos.ForEach(furo => furo.consumed.ForEach(pai => restNum[pai.PaiNumber]--))); kawas.ForEach(player => player.discards.ForEach(pai => restNum[pai.PaiNumber]--)); yama.GetDoraMarkerStrings().ForEach(paiStr => restNum[PaiConverter.STRING_TO_ID[paiStr]]--); var kokushiShanten = shantenCalclator.CalcKokushiShanten(tehais[mypositionId].tehaiString); if (kokushiShanten > 3) { shantenCalclator.SetUseKokushi(false); } var chitoitsuShanten = shantenCalclator.CalcChitoitsuShanten(tehais[mypositionId].tehaiString); if (chitoitsuShanten <= 1) { shantenCalclator.SetUseChitoitsu(true); } else { shantenCalclator.SetUseChitoitsu(false); } var nowShanten = shantenCalclator.CalcShanten(tehais[mypositionId]); var validateMap = new Dictionary<int, int>(); var dahaiCandidate = tehais[mypositionId].tehai; foreach (var pai in dahaiCandidate) { if (validateMap.ContainsKey(pai.PaiNumber)) { continue; } var tehaiIds = tehais[mypositionId].tehai.Select(e => e.PaiNumber).ToList(); var furoCount = tehais[mypositionId].furos.Count; tehaiIds.Remove(pai.PaiNumber); var validPai = 0; var syuArray = Enumerable.Repeat(0, MJUtil.LENGTH_SYU_ALL).ToArray(); tehaiIds.ForEach(e => syuArray[e]++); for (int i = 0; i < MJUtil.LENGTH_SYU_ALL; i++) { if (restNum[i] <= 0) { continue; } fordebug = i; fordebug2 = syuArray; syuArray[i]++; var tempShanten = shantenCalclator.CalcShantenWithFuro(syuArray, furoCount); if (tempShanten < nowShanten) { validPai += restNum[i]; } syuArray[i]--; } validateMap.Add(pai.PaiNumber, validPai); } shantenCalclator.SetUseKokushi(true); shantenCalclator.SetUseChitoitsu(true); var bestValidNumber = validateMap.OrderByDescending(e => e.Value).First().Value; var dahaiCandidateMap = validateMap.Where(e => e.Value == bestValidNumber); var bestNumber = -1;// temp value if (dahaiCandidateMap.Any(e => e.Key >= MJUtil.LENGTH_SYU_ONE_NUMBERS * 3)) { bestNumber = dahaiCandidateMap.Last().Key; } else if (dahaiCandidateMap.Any(e => e.Key % 9 == 0 || e.Key % 9 == 8)) { bestNumber = dahaiCandidateMap.Where(e => e.Key % 9 == 0 || e.Key % 9 == 8).Last().Key; } else if (dahaiCandidateMap.Any(e => e.Key % 9 == 1 || e.Key % 9 == 7)) { bestNumber = dahaiCandidateMap.Where(e => e.Key % 9 == 1 || e.Key % 9 == 7).Last().Key; } else if (dahaiCandidateMap.Any(e => e.Key % 9 == 2 || e.Key % 9 == 6)) { bestNumber = dahaiCandidateMap.Where(e => e.Key % 9 == 2 || e.Key % 9 == 6).Last().Key; } else if (dahaiCandidateMap.Any(e => e.Key % 9 == 3 || e.Key % 9 == 5)) { bestNumber = dahaiCandidateMap.Where(e => e.Key % 9 == 3 || e.Key % 9 == 5).Last().Key; } else { bestNumber = dahaiCandidateMap.Last().Key; } var paiString = tehais[mypositionId].tehai.Where(e => e.PaiNumber == bestNumber).First().PaiString; var tehaiString = tehais[mypositionId].ToString(); return paiString; } catch (Exception e) { Debug.WriteLine(e); Debug.WriteLine(fordebug); fordebug2.ToList().ForEach(v => Debug.Write(v+",")); return ""; } }
public void ThinkOnOtherPlayerDoroped(int mypositionId, int dapaiActor, string pai, List<Tehai> tehais, List<Kawa> kawas, Field field, List<InfoForResult> ifrs, Yama yama) { if (shantenCalclator.CalcShanten(tehais[mypositionId], pai) != MJUtil.SHANTEN_HORA) { SendNone(new MJsonMessageNone()); return; } // check my furiten var myTehai = tehais[mypositionId]; var myKawa = kawas[mypositionId]; var isFuritenByMyKawa = myKawa.discards.Any(discard => myTehai.GetShanten(discard.PaiString) == MJUtil.SHANTEN_HORA); if(isFuritenByMyKawa) { SendNone(new MJsonMessageNone()); return; } // check yaku var tempSave = ifrs[mypositionId].LastAddedPai; ifrs[mypositionId].LastAddedPai = new Pai(pai); var result = CalcHora(dapaiActor, pai); if (result.yakuResult.HasYakuExcludeDora) { if (DisplayHora) { Debug.WriteLine("on other player doroped"); Debug.WriteLine(myTehai.ToString()); result.yakuResult.yakus.ForEach(e => Debug.Write(e[0] + ",")); Debug.WriteLine(""); Debug.WriteLine("--------------------------------------------------------------------------------"); } SendHora(new MJsonMessageHora(mypositionId, dapaiActor, pai)); return; } ifrs[mypositionId].LastAddedPai = tempSave; SendNone(new MJsonMessageNone()); }
public void ReplaceKyokuInfoForTest(MJsonMessageStartKyoku msg) { var haipais = msg.tehais; var field = new Field(msg.kyoku, msg.honba, msg.kyotaku, msg.oya, msg.bakaze); gameModel.field = field; gameModel.tehais = haipais.Select(e => new Tehai(e)).ToList(); gameContext.ChangeState(msg); gameModel.SetCurrentActor(msg.oya); gameModel.infoForResultList = new List<InfoForResult>() { new InfoForResult(field.KyokuId, 0, field.OyaPlayerId), new InfoForResult(field.KyokuId, 1, field.OyaPlayerId), new InfoForResult(field.KyokuId, 2, field.OyaPlayerId), new InfoForResult(field.KyokuId, 3, field.OyaPlayerId) }; }
public void Unit_HoraResultTest() { //親40符3翻 ダブ東 ツモ 7800点 { var expected = 7800; var tehai = new Tehai(new List<string>() { "1m", "2m", "3m", "4p", "5p", "6p", "7p", "7p", "7p", "9p", "9p", "E", "E", "E" }); var gameId = 1; var playerPosition = 0; var lastAddedPai = "E"; var ifr = new InfoForResult(gameId, playerPosition); ifr.IsTsumo = true; ifr.IsFured = false; ifr.IsMenzen = true; ifr.UseYamaPaiNum = 5; ifr.SetLastAddedPai(lastAddedPai); var fd = new Field(); var result = ResultCalclator.CalcHoraResult(tehai, ifr, fd, lastAddedPai); Assert.AreEqual(expected, result.pointResult.HoraPlayerIncome); } //親50符2翻 ツモ 三暗刻 { var expected = 9600; var tehai = new Tehai(new List<string>() { "1m", "1m", "1m", "2p", "2p", "2p", "4p", "5p", "5p", "5p", "6p", "E", "E", "5p" }); var gameId = 1; var playerPosition = 0; var lastAddedPai = "5p"; var ifr = new InfoForResult(gameId, playerPosition); ifr.IsTsumo = true; ifr.IsFured = false; ifr.IsMenzen = true; ifr.UseYamaPaiNum = 5; ifr.SetLastAddedPai(lastAddedPai); var fd = new Field(); var result = ResultCalclator.CalcHoraResult(tehai, ifr, fd, lastAddedPai); Assert.AreEqual(expected, result.pointResult.HoraPlayerIncome); } //子20符2翻 タンピン { var expected = 2000; var tehai = new Tehai(new List<string>() { "2m", "3m", "4m", "2p", "3p", "4p", "4p", "5p", "6p", "4s", "5s", "8s", "8s" }); var gameId = 1; var playerPosition = 1; var lastAddedPai = "6s"; var ifr = new InfoForResult(gameId, playerPosition); ifr.IsTsumo = false; ifr.IsFured = false; ifr.IsMenzen = true; ifr.UseYamaPaiNum = 5; var fd = new Field(); ifr.SetLastAddedPai(lastAddedPai); var result = ResultCalclator.CalcHoraResult(tehai, ifr, fd, lastAddedPai); Assert.AreEqual(expected, result.pointResult.HoraPlayerIncome); } //子20符3翻 タンヤオ三食一盃口 { var expected = 8000; var tehai = new Tehai(new List<string>() { "2m", "3m", "4m", "2p", "3p", "4p", "2p", "4p", "5s", "5s", "2s", "3s", "4s" }); var gameId = 1; var playerPosition = 1; var lastAddedPai = "3p"; var ifr = new InfoForResult(gameId, playerPosition); ifr.IsTsumo = false; ifr.IsFured = false; ifr.IsMenzen = true; ifr.UseYamaPaiNum = 5; var fd = new Field(); ifr.SetLastAddedPai(lastAddedPai); var result = ResultCalclator.CalcHoraResult(tehai, ifr, fd, lastAddedPai); Assert.AreEqual(expected, result.pointResult.HoraPlayerIncome); } //子40符1翻 自摸 { var expected = 1500; var tehai = new Tehai(new List<string>() { "1m", "2m", "3m", "3m", "4m", "5m", "1p", "1p", "1p", "2s", "3s", "4s", "5s", "5s" }); var gameId = 1; var playerPosition = 1; var lastAddedPai = "3m"; var ifr = new InfoForResult(gameId, playerPosition); ifr.IsTsumo = true; ifr.IsFured = false; ifr.IsMenzen = true; ifr.UseYamaPaiNum = 5; var fd = new Field(); ifr.SetLastAddedPai(lastAddedPai); var result = ResultCalclator.CalcHoraResult(tehai, ifr, fd, lastAddedPai); Assert.AreEqual(expected, result.pointResult.HoraPlayerIncome); } //子50符2翻 ロン { var expected = 3200; var tehai = new Tehai(new List<string>() { "1m", "1m", "1m", "2m", "2m", "2m", "1p", "1p", "1p", "2p", "3p", "4s", "4s" }); var gameId = 1; var playerPosition = 1; var lastAddedPai = "1p"; var ifr = new InfoForResult(gameId, playerPosition); ifr.IsTsumo = false; ifr.IsFured = false; ifr.IsMenzen = true; ifr.UseYamaPaiNum = 5; var fd = new Field(); ifr.SetLastAddedPai(lastAddedPai); var result = ResultCalclator.CalcHoraResult(tehai, ifr, fd, lastAddedPai); Assert.AreEqual(expected, result.pointResult.HoraPlayerIncome); } }
public void Unit_HoraResultTestUseHoraPatternExamples() { using (StreamReader sr = new StreamReader(@"../../HoraPatternOutputSmall.txt", Encoding.GetEncoding("shift_jis"))) { var lineNumber = 0; while (true) { string line = sr.ReadLine(); if (line == null) break; lineNumber++; var obj = JsonConvert.DeserializeObject<MJsonMessageHora_Extend>(line); int expected = obj.hora_points; var gameId = obj.kyoku; var playerPosition = obj.actor; var lastAddedPai = obj.pai; var stubOyaId = 0;// replaced after var ifr = new InfoForResult(gameId, playerPosition, stubOyaId, obj.bakaze); ifr.IsTsumo = obj.actor == obj.target; var ankantsuCount = obj.hora_furos.Count(e => e[0] == "ankantsu"); ifr.IsMenzen = obj.hora_furos.Count - ankantsuCount == 0; ifr.IsFured = !ifr.IsMenzen; ifr.UseYamaPaiNum = 5; ifr.SetLastAddedPai(lastAddedPai); ifr.IsIppatsu = yakuContains(obj, "ippatsu"); ifr.IsReach = yakuContains(obj, "reach"); ifr.IsDoubleReach = yakuContains(obj, "double_reach"); ifr.IsHaitei = yakuContains(obj, "haiteiraoyue"); ifr.IsHoutei = yakuContains(obj, "hoteiraoyui"); ifr.IsRinshan = yakuContains(obj, "rinshankaiho"); ifr.IsChankan = yakuContains(obj, "chankan"); ifr.IsOya = (obj.kyoku - 1 - obj.actor + Constants.PLAYER_NUM) % Constants.PLAYER_NUM == 0; foreach (var doraMarker in obj.dora_markers) { ifr.RegisterDoraMarker(doraMarker); } ifr.RegisterUraDoraMarker(obj.uradora_markers); var fd = new Field(obj.kyoku, 0, 0, 0,obj.bakaze); var tehai = new Tehai(obj.hora_tehais); foreach (var furo in obj.hora_furos) { // ankan don't contains furo.furopai if (MJUtil.TARTSU_TYPE_STRING_ENUM_MAP[furo[0]] == MJUtil.TartsuType.ANKANTSU) { var f = new Furo(furo[0], Pai.UNKNOWN_PAI_STRING, furo.GetRange(1, furo.Count - 1)); tehai.furos.Add(f); } else { var f = new Furo(furo[0], furo[1], furo.GetRange(2, furo.Count - 2)); tehai.furos.Add(f); } } if (ifr.IsTsumo) { tehai.tehai.Add(new Pai(lastAddedPai)); } var result = ResultCalclator.CalcHoraResult(tehai, ifr, fd, lastAddedPai); var myPointResult = result.pointResult.HoraPlayerIncome; if (myPointResult != expected) { Debug.WriteLine(lineNumber + ", acc = " + expected + " --> " + myPointResult + " tehais:" + string.Join(",", tehai.GetTehaiStringList().ToList())); foreach (var yaku in result.yakuResult.yakus) { Debug.WriteLine("accual yaku {0}, han {1}",yaku[0],yaku[1]); } result = ResultCalclator.CalcHoraResult(tehai, ifr, fd, lastAddedPai); } Assert.AreEqual(expected, myPointResult); } } }
public void StartKyoku(string bakaze, int kyoku, int honba, int kyotaku, int oya, string doraMarker, List<List<string>> tehais) { field = new Field(kyoku, honba, kyotaku, oya, bakaze); CurrentActor = oya; infoForResultList = new List<InfoForResult>() { new InfoForResult(field.KyokuId, 0, oya, bakaze), new InfoForResult(field.KyokuId, 1, oya, bakaze), new InfoForResult(field.KyokuId, 2, oya, bakaze), new InfoForResult(field.KyokuId, 3, oya, bakaze) }; this.tehais = new List<Tehai> { new Tehai(tehais[0]), new Tehai(tehais[1]), new Tehai(tehais[2]), new Tehai(tehais[3]) }; // Don't use this haipai and this operation is for restYamaNum count yama = new Yama(); yama.MakeHaipai(); kawas = new List<Kawa> { new Kawa(), new Kawa(), new Kawa(), new Kawa() }; }
public void SetScene(int rest_tsumo_num, List<string> dora_markers, List<List<string>> kawas, List<List<bool>> is_reached_kawapai, List<int> scores, int kyoku, int honba, int kyotaku, string bakaze, int oya, List<List<string>> tehais, List<List<List<string>>> furos, int actor, int mypositionid) { Init(); yama.SetScene(rest_tsumo_num, dora_markers, tehais, furos, kawas); for (int i = 0; i < Constants.PLAYER_NUM; i++) { this.kawas[i].SetScene(kawas[i], is_reached_kawapai[i]); } for (int i = 0; i < Constants.PLAYER_NUM; i++) { this.tehais[i].SetScene(tehais[i], furos[i]); } field = new Field(kyoku, honba, kyotaku, oya, bakaze); this.scores = scores; myPositionId = mypositionid; CurrentActor = actor; infoForResultList = new List<InfoForResult>() { new InfoForResult(field.KyokuId, 0, field.OyaPlayerId), new InfoForResult(field.KyokuId, 1, field.OyaPlayerId), new InfoForResult(field.KyokuId, 2, field.OyaPlayerId), new InfoForResult(field.KyokuId, 3, field.OyaPlayerId) }; foreach (var doraMarker in dora_markers) { infoForResultList.ForEach(e => e.RegisterDoraMarker(doraMarker)); } for (int i = 0; i < Constants.PLAYER_NUM; i++) { infoForResultList[i].SetLastAddedPai(tehais[i].Last()); } // configure reach flag // SetReachFlag must be configred after configure yama. var isReach = is_reached_kawapai.Select(e => e.Contains(true)).ToList(); for (int i = 0; i < Constants.PLAYER_NUM; i++) { if (isReach[i]) { SetReachFlag(i); } } }
public void Init() { yama = new Yama(); kawas = new List<Kawa> { new Kawa(), new Kawa(), new Kawa(), new Kawa() }; tehais = new List<Tehai> { new Tehai(), new Tehai(), new Tehai(), new Tehai() }; field = new Field(); infoForResultList = new List<InfoForResult>() { new InfoForResult(), new InfoForResult(), new InfoForResult(), new InfoForResult() }; scores = new List<int> { 25000, 25000, 25000, 25000 }; CurrentActor = 0; }
public void ThinkOnOtherPlayerDoroped(int mypositionId, int dapaiActor, string pai, List<Tehai> tehais, List<Kawa> kawas, Field field, List<InfoForResult> ifrs, Yama yama) { SendNone(new MJsonMessageNone()); }