// writePump pumps messages from the hub to the websocket connection. func (c *connection) writePump() { ticker := time.NewTicker(pingPeriod) defer func() { ticker.Stop() c.ws.Close() }() for { select { case threadToResponse, ok := <-c.send: if !ok { c.write(websocket.CloseMessage, []byte{}) return } if err := c.ws.WriteJSON(threadToResponse); err != nil { l.Output( logrus.Fields{ l.ErrMsg: l.ErrToStr(err), l.TraceMsg: l.TraceToStr(l.Trace()), "Thread": l.Sprintf(threadToResponse), }, "can not write JSON", l.Debug, ) return } case <-ticker.C: if err := c.write(websocket.PingMessage, []byte{}); err != nil { l.PutErr(err, l.Trace(), l.E_R_PingMsg, websocket.PingMessage) return } } } }
// readPump pumps messages from the websocket connection to the hub. func (c *connection) readPump() { defer func() { H.Unregister <- c c.ws.Close() }() c.ws.SetReadLimit(maxMessageSize) c.ws.SetReadDeadline(time.Now().Add(pongWait)) c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil }) for { err := c.ws.ReadJSON(&thread) if err != nil { if thread == nil { break } l.Output( logrus.Fields{ l.ErrMsg: l.ErrToStr(err), l.TraceMsg: l.TraceToStr(l.Trace()), "Thread": l.Sprintf(thread), }, "can not read JSON or Closed Websocket", l.Debug, ) break } if newThread, err = m.UpdateExistingTimeLine(thread); err != nil { l.PutErr(err, l.Trace(), l.E_R_Upsert, thread) } H.Broadcast <- newThread } }
func PostApplyScoreData(teamName string, ApplyScore *PostApplyScore) (*Status, error) { l.PutInfo(l.I_M_PostPage, teamName, ApplyScore) //更新情報をGlobal変数に格納する defer SetPlayerCol(ApplyScore.UserIds) AUserIdInTheTeam := teams[teamName].UserIds[0] if players[AUserIdInTheTeam].Apply != 0 { l.Output( logrus.Fields{ "User Apply": l.Sprintf(players[AUserIdInTheTeam].Apply), }, "Apply score is already registered", l.Debug, ) return &Status{"already registered"}, nil } for playerIndex, userId := range ApplyScore.UserIds { findQuery := bson.M{"userid": userId} setQuery := bson.M{"$set": bson.M{"apply": ApplyScore.Apply[playerIndex]}} if err = UpdateMongoData("player", findQuery, setQuery); err != nil { l.PutErr(err, l.Trace(), l.E_M_Update, ApplyScore.Apply[playerIndex]) return &Status{"failed"}, err } } return &Status{"success"}, nil }
func UpsertNewTimeLine(thread *Thread) error { l.PutInfo(l.I_M_PostPage, thread, nil) //更新情報をGlobal変数に格納する defer SetAllThreadCol() defaultColor := "#c0c0c0" if len(thread.ThreadId) != 0 { l.PutErr(nil, l.Trace(), l.E_WrongData, thread) return errors.New("thread id exists") } db, session := mongoConn() threadCol := db.C("thread") defer session.Close() thread.ThreadId = make20lengthHashString() thread.CreatedAt = time.Now().Format(c.DatetimeFormat) thread.ColorCode = defaultColor if err = threadCol.Insert(thread); err != nil { l.PutErr(err, l.Trace(), l.E_M_Insert, thread) return err } ThreadChan <- thread return nil }
func RegisterFieldColData(date string, fieldCols []FieldCol) (*Status, error) { l.PutInfo(l.I_M_RegisterCol, date, fieldCols) defer SetAllFieldCol() db, session := mongoConn() fieldC := db.C("field") defer session.Close() var createCnt, updateCnt int for _, fieldCol := range fieldCols { if fieldCol.Hole > 18 || fieldCol.Hole < 0 { l.PutErr(nil, l.Trace(), l.E_WrongData, fieldCol.Hole) return &Status{"this is not hole number"}, err } fieldCol.Ignore = false fieldCol.Date = date findQuery := bson.M{"hole": fieldCol.Hole} change, err := fieldC.Upsert(findQuery, fieldCol) if err != nil { l.PutErr(err, l.Trace(), l.E_M_Upsert, fieldCol.Hole) return &Status{"can not upsert"}, err } if change.Updated == 0 { createCnt += 1 } else { updateCnt += 1 } } return &Status{"success"}, nil }
func RegisterThreadImg(r *RequestTakePictureStatus) (*RequestTakePictureStatus, error) { l.PutInfo(l.I_M_RegisterCol, r, nil) defer SetPlayerCol([]string{r.UserId}) if len(r.ThreadId) == 0 { return nil, errors.New("there is not thread id") } if len(r.PhotoUrl) == 0 { return nil, errors.New("there is not pthoto url ") } threadFindQuery := bson.M{"threadid": r.ThreadId} threadSetQuery := bson.M{"$set": bson.M{"imgurl": r.PhotoUrl}} if err = UpdateMongoData("thread", threadFindQuery, threadSetQuery); err != nil { l.PutErr(err, l.Trace(), l.E_M_Update, r.PhotoUrl) return &RequestTakePictureStatus{Status: "failed"}, err } var photoKey string if r.Positive { photoKey = "positivephotourl" } else { photoKey = "negativephotourl" } playerFindQuery := bson.M{"userid": r.UserId} playerSetQuery := bson.M{"$set": bson.M{photoKey: r.PhotoUrl}} if err = UpdateMongoData("player", playerFindQuery, playerSetQuery); err != nil { l.PutErr(err, l.Trace(), l.E_M_Update, r.PhotoUrl) return &RequestTakePictureStatus{Status: "failed"}, err } SetAllThreadCol() thread := &Thread{ ThreadId: r.ThreadId, UserId: threads[r.ThreadId].UserId, UserName: threads[r.ThreadId].UserName, Msg: threads[r.ThreadId].Msg, ImgUrl: threads[r.ThreadId].ImgUrl, ColorCode: threads[r.ThreadId].ColorCode, Positive: threads[r.ThreadId].Positive, CreatedAt: threads[r.ThreadId].CreatedAt, } ThreadChan <- thread requestTakePictureStatus, err := RequestTakePicture(r.TeamUserIds) if err != nil { return nil, err } if len(requestTakePictureStatus.ThreadId) != 0 { return requestTakePictureStatus, nil } return &RequestTakePictureStatus{Status: "success"}, nil }
func (player TMainPlayer) GetJosekiMove(ban *TBan, all_moves *map[int]*TMove) *TMove { logger := GetLogger() current_sfen := ban.ToSFEN(false) // 現在の局面に定跡が登録されているか確認する fix_move, fix_move_exists := player.Joseki.FixOpening[*(ban.Tesuu)+1] var fix_move_string string = "" if fix_move_exists { fix_move_string = fix_move.GetUSIMoveString() logger.Trace("[MainPlayer] fix_move_string is: " + fix_move_string) } else { sfen_joseki_move, exists := player.Joseki.SFENMap[current_sfen] if exists { fix_move_string = sfen_joseki_move.GetUSIMoveString() logger.Trace("[MainPlayer] sfen_joseki_move_string is: " + fix_move_string) } } // 定跡手が存在する場合、(念のため)手があることを確認して返す if fix_move_string != "" { for key, move := range *all_moves { move_string := move.GetUSIMoveString() if fix_move_string == move_string { return (*all_moves)[key] } else { continue } } } return nil }
func RegisterTeamColData(date string, teamCols []TeamCol) (*Status, error) { l.PutInfo(l.I_M_RegisterCol, date, teamCols) defer SetAllPlayerCol() defer SetAllTeamCol() db, session := mongoConn() playerC := db.C("player") teamC := db.C("team") defer session.Close() var OneBeforebyteOfA byte = 64 alphabet := make([]byte, 1) alphabet[0] = OneBeforebyteOfA totalHoleNum := 18 for _, teamCol := range teamCols { if len(teamCol.UserIds) == 0 { l.PutErr(nil, l.Trace(), l.E_Nil, teamCol) return &Status{"this team do not have user id"}, nil } alphabet[0] += 1 teamCol.Name = string(alphabet) teamCol.Defined = false teamCol.Date = date if err := teamC.Insert(teamCol); err != nil { l.PutErr(err, l.Trace(), l.E_M_Insert, teamCol) return &Status{"can not insert"}, err } for _, userId := range teamCol.UserIds { scores := []bson.M{} for holeNum := 1; holeNum <= totalHoleNum; holeNum++ { score := bson.M{ "hole": holeNum, "putt": 0, "total": 0, } scores = append(scores, score) } player := PlayerCol{ UserId: userId, Score: scores, Date: date, } if err := playerC.Insert(player); err != nil { l.PutErr(err, l.Trace(), l.E_M_Insert, player) return &Status{"can not insert"}, err } } } return &Status{"success"}, nil }
func PostScoreEntrySheetPageData(teamName string, holeString string, teamScore *PostTeamScore) (*RequestTakePictureStatus, error) { l.PutInfo(l.I_M_PostPage, teamName, teamScore) userIds := teams[teamName].UserIds //更新情報をGlobal変数に格納する defer SetPlayerCol(userIds) if len(holeString) == 0 { l.PutErr(nil, l.Trace(), l.E_Nil, teamName) return &RequestTakePictureStatus{Status: "failed"}, errors.New("hole is not string") } holeNum, _ := strconv.Atoi(holeString) holeIndex := holeNum - 1 holeIndexString := strconv.Itoa(holeIndex) if teamScore.Excnt != excnt[teamName][holeNum] { return &RequestTakePictureStatus{Status: "other updated"}, nil } else { excnt[teamName][holeNum]++ } for playerIndex, userId := range teamScore.UserIds { total, putt := teamScore.Total[playerIndex], teamScore.Putt[playerIndex] findQuery := bson.M{"userid": userId} setQuery := bson.M{ "$set": bson.M{ "score." + holeIndexString + ".total": total, "score." + holeIndexString + ".putt": putt, }, } if err = UpdateMongoData("player", findQuery, setQuery); err != nil { l.PutErr(err, l.Trace(), l.E_M_Update, userId) return &RequestTakePictureStatus{Status: "failed update score"}, err } } // Thread登録 if err := RegisterThreadOfScore(holeString, teamScore); err != nil { l.PutErr(err, l.Trace(), l.E_M_RegisterThread, teamScore) return nil, err } // チーム内に写真リクエストがあるか確認する requestTakePictureStatus, err := RequestTakePicture(userIds) if err != nil { l.PutErr(err, l.Trace(), l.E_M_SearchPhotoTask, userIds) return nil, err } return requestTakePictureStatus, nil }
func (ban TBan) DoMove(from TPosition, to TPosition, promote bool) { logger := GetLogger() // fromにある駒を取得 from_masu := ban.AllMasu[from] from_koma := ban.AllKoma[from_masu.KomaId] if from_koma == nil { // 盤と手、どちらかがおかしい logger.Trace("ERROR!! no Koma exists at: " + s(from)) return } // fromにある手を取得 moves := ban.AllMoves[from_koma.Id] var move *TMove = nil for _, value := range moves.Map { if value.ToPosition == to { move = value break } } if move == nil { // 盤と手、どちらかがおかしい logger.Trace("ERROR!! Koma at: " + s(from) + ",no Move exists to: " + s(to)) return } else { if move.ToId == 0 { // 相手の駒を取る手ではない } else { // 相手の駒を取る capture_koma := ban.AllKoma[move.ToId] if capture_koma.Position != to { logger.Trace("ERROR!! capture_koma id " + s(move.ToId) + " is at: " + s(capture_koma.Position)) } else { ban.CaptureKoma(move.ToId) } } } // fromにある駒をいったん盤から取り除く ban.RemoveKoma(from_masu.KomaId) // 取り除いた駒をtoに置く from_koma.Position = to // 駒が成る場合 if promote { from_koma.Promoted = true } ban.PutKoma(from_koma) }
func GetScoreEntrySheetPageData(teamName string, holeString string) (*ScoreEntrySheet, error) { l.PutInfo(l.I_M_GetPage, teamName, holeString) if len(holeString) == 0 { l.PutErr(nil, l.Trace(), l.E_Nil, teamName) return nil, errors.New("hole string is nil") } holeNum, _ := strconv.Atoi(holeString) holeIndex := holeNum - 1 field := fields[holeNum] userIds := teams[teamName].UserIds member := make([]string, len(userIds)) total := make([]int, len(userIds)) putt := make([]int, len(userIds)) for i, userId := range userIds { member[i] = users[userId].Name total[i] = players[userId].Score[holeIndex]["total"].(int) putt[i] = players[userId].Score[holeIndex]["putt"].(int) } scoreEntrySheet := ScoreEntrySheet{ Team: teamName, Hole: holeNum, Member: member, UserIds: userIds, Par: field.Par, Yard: field.Yard, Total: total, Putt: putt, Excnt: excnt[teamName][holeNum], } return &scoreEntrySheet, nil }
func make20lengthHashString() string { b := make([]byte, 32) if _, err := io.ReadFull(rand.Reader, b); err != nil { l.PutErr(err, l.Trace(), l.E_MakeHash, rand.Reader) } longHash := strings.TrimRight(base32.StdEncoding.EncodeToString(b), "=") return string([]rune(longHash)[:20]) }
// serveWs handles websocket requests from the peer. func ServeWs(w http.ResponseWriter, r *http.Request) { ws, err := upgrader.Upgrade(w, r, nil) if err != nil { l.PutErr(err, l.Trace(), l.E_R_Upgrader, nil) return } c := &connection{send: make(chan *m.Thread, 256), ws: ws} H.Register <- c go c.writePump() c.readPump() }
func (ban *TBan) CheckEmptyMasu() { logger := GetLogger() empty_masu := make([]TPosition, 81) fu_drop_sente := make([]byte, 0) fu_drop_gote := make([]byte, 0) var x, y byte = 1, 1 for x <= 9 { fu_sente := false fu_gote := false y = 1 for y <= 9 { pos := Bytes2TPosition(x, y) // logger.Trace("CheckEmptyMasu pos: " + s(pos)) masu := ban.AllMasu[pos] if masu.KomaId == 0 { // 空いたマスを保存 empty_masu = append(empty_masu, pos) // logger.Trace("CheckEmptyMasu append. pos: " + s(pos)) } else { koma := ban.AllKoma[masu.KomaId] if koma.Position != pos { // ありえないが、バグとしてありえるので予め logger.Trace("CheckEmptyMasu Ghost Koma Id: " + s(koma.Id)) masu.KomaId = 0 empty_masu = append(empty_masu, pos) } else { // その列の歩の有無をチェック if koma.Kind == Fu { if koma.IsSente { fu_sente = true } else { fu_gote = true } } } } y++ } if !fu_sente { fu_drop_sente = append(fu_drop_sente, x) } if !fu_gote { fu_drop_gote = append(fu_drop_gote, x) } x++ } // 独自のstructに値を保存するには、レシーバをアドレス表記にする必要がある。 ban.EmptyMasu = empty_masu ban.FuDropSente = fu_drop_sente ban.FuDropGote = fu_drop_gote // logger.Trace("CheckEmptyMasu ok: " + s(empty_masu)) }
func SetAllUserCol() { db, session := mongoConn() col := db.C("user") defer session.Close() usersCol := []UserCol{} if err = col.Find(nil).All(&usersCol); err != nil { l.PutErr(err, l.Trace(), l.E_M_FindEntireCol, nil) } for _, userCol := range usersCol { users[userCol.UserId] = userCol } }
func SetAllThreadCol() { db, session := mongoConn() col := db.C("thread") defer session.Close() threadsCol := []ThreadCol{} if err = col.Find(nil).All(&threadsCol); err != nil { l.PutErr(err, l.Trace(), l.E_M_FindEntireCol, nil) } for _, threadCol := range threadsCol { threads[threadCol.ThreadId] = threadCol } }
func SetAllPlayerCol() { db, session := mongoConn() col := db.C("player") defer session.Close() playersCol := []PlayerCol{} if err = col.Find(nil).All(&playersCol); err != nil { l.PutErr(err, l.Trace(), l.E_M_FindEntireCol, nil) } for _, playerCol := range playersCol { players[playerCol.UserId] = playerCol } }
func SetAllTeamCol() { db, session := mongoConn() col := db.C("team") defer session.Close() teamsCol := []TeamCol{} if err = col.Find(nil).All(&teamsCol); err != nil { l.PutErr(err, l.Trace(), l.E_M_FindEntireCol, nil) } for _, teamCol := range teamsCol { teams[teamCol.Name] = teamCol } }
func SetAllFieldCol() { db, session := mongoConn() col := db.C("field") defer session.Close() fieldsCol := []FieldCol{} if err = col.Find(nil).All(&fieldsCol); err != nil { l.PutErr(err, l.Trace(), l.E_M_FindEntireCol, nil) } for _, fieldCol := range fieldsCol { fields[fieldCol.Hole] = fieldCol } }
func SetThreadCol(threadId string) { db, session := mongoConn() col := db.C("thread") defer session.Close() threadCol := ThreadCol{} findQuery := bson.M{"threadid": threadId} if err = col.Find(findQuery).One(&threadCol); err != nil { l.PutErr(err, l.Trace(), l.E_M_FindCol, findQuery) } threads[threadId] = threadCol }
func SetFieldCol(hole int) { db, session := mongoConn() col := db.C("field") defer session.Close() fieldCol := FieldCol{} findQuery := bson.M{"hole": hole} if err = col.Find(findQuery).One(&fieldCol); err != nil { l.PutErr(err, l.Trace(), l.E_M_FindCol, findQuery) } fields[hole] = fieldCol }
func SetTeamCol(teamName string) { db, session := mongoConn() col := db.C("team") defer session.Close() teamCol := TeamCol{} findQuery := bson.M{"name": teamName} if err = col.Find(findQuery).One(&teamCol); err != nil { l.PutErr(err, l.Trace(), l.E_M_FindCol, findQuery) } teams[teamName] = teamCol }
func RegisterUserColData(userCols []UserCol) (*Status, error) { l.PutInfo(l.I_M_RegisterCol, userCols, nil) defer SetAllUserCol() db, session := mongoConn() col := db.C("user") defer session.Close() var createCnt, updateCnt int for _, userCol := range userCols { if len(userCol.Name) == 0 { l.PutErr(nil, l.Trace(), l.E_Nil, userCol.Name) return &Status{"this user do not have name"}, nil } if len(userCol.UserId) == 0 { userCol.UserId = make20lengthHashString() } if len(userCol.CreatedAt) == 0 { userCol.CreatedAt = time.Now().Format(c.DatetimeFormat) } findQuery := bson.M{"userid": userCol.UserId} change, err := col.Upsert(findQuery, userCol) if err != nil { l.PutErr(err, l.Trace(), l.E_M_Upsert, userCol.UserId) return &Status{"can not upsert"}, err } if change.Updated == 0 { createCnt += 1 } else { updateCnt += 1 } } return &Status{"success"}, nil }
func (player TMainPlayer) Search(ban *TBan, ms int) (string, int) { logger := GetLogger() teban := *(ban.Teban) logger.Trace("[MainPlayer] ban.Tesuu: " + s(*(ban.Tesuu)) + ", teban: " + s(teban)) all_moves := MakeAllMoves(ban) moves_count := len(all_moves) logger.Trace("[MainPlayer] moves: " + s(moves_count)) if moves_count == 0 { return "resign", 0 } joseki_move := player.GetJosekiMove(ban, &all_moves) if joseki_move != nil { return joseki_move.GetUSIMoveString(), 0 } // magic number width := 999 depth := 4 if ms < 300000 { depth = 3 } if ms < 120000 { depth = 2 } if ms < 60000 { // magic number depth = 0 } move, score := player.GetMainBestMove(ban, &all_moves, width, depth, true) return move.GetUSIMoveString(), score }
func (ban TBan) FindMochiKoma(teban TTeban, kind TKind) *TKoma { teban_koma_map := ban.GetTebanKoma(teban) var found *TKoma = nil for _, koma := range *teban_koma_map { if koma.Kind == kind && koma.Position == Mochigoma { found = koma break } } if found == nil { logger := GetLogger() logger.Trace("ERROR!! koma to drop is not found.") } return found }
func PostScoreViewSheetPageData(teamName string, definedTeam *PostDefinedTeam) (*Status, error) { l.PutInfo(l.I_M_PostPage, teamName, definedTeam) //更新情報をGlobal変数に格納する defer SetTeamCol(teamName) findQuery := bson.M{"name": teamName} setQuery := bson.M{"$set": bson.M{"defined": true}} if err = UpdateMongoData("team", findQuery, setQuery); err != nil { l.PutErr(err, l.Trace(), l.E_M_Update, teamName) return &Status{"failed"}, err } return &Status{"success"}, nil }
func UpdateMongoData(collection string, findQuery bson.M, updateQuery bson.M) error { db, session := mongoConn() c := db.C(collection) defer session.Close() if err = c.Update(findQuery, updateQuery); err != nil { l.PutErr(err, l.Trace(), l.E_M_Update, map[string]bson.M{ "findQuery": findQuery, "updateQuery": updateQuery, }, ) return err } return nil }
func SetPlayerCol(userIds []string) { db, session := mongoConn() col := db.C("player") defer session.Close() for _, userId := range userIds { playerCol := PlayerCol{} findQuery := bson.M{"userid": userId} if err = col.Find(findQuery).One(&playerCol); err != nil { l.PutErr(err, l.Trace(), l.E_M_FindCol, findQuery) } players[userId] = playerCol } }
func (player TMainPlayer) GetMainBestMove(ban *TBan, all_moves *map[int]*TMove, width int, depth int, is_disp bool) (*TMove, int) { logger := GetLogger() teban := *(ban.Teban) current_sfen := ban.ToSFEN(false) score_channel := player.GetScore(current_sfen, teban, all_moves, is_disp) oute_map := make(map[int]int) better_moves_map := make(map[int]int) if depth == 0 { // 緊急避難ロジック return (*all_moves)[0], 28 } if width == 999 { width = len(*all_moves) / 2 } if width > 32 { width = 32 } if width == 0 { width = 1 } // logger.Trace("------start------") // ゴルーチンの結果待ち for i := 0; i < len(*all_moves); i++ { result := <-score_channel // "key_of_all_moves:score:Oute(if oute)" result_arr := strings.Split(result, ":") key, _ := strconv.Atoi(result_arr[0]) score, _ := strconv.Atoi(result_arr[1]) sfen := result_arr[2] player.Cache[sfen] = score if len(result_arr) == 4 { // 王手フラグあり。候補手とする oute_map[key] = score } else { // 上位width件だけ候補手とする PutToMap(&better_moves_map, key, score, width) } } // 王手を候補手に追加 for k, s := range oute_map { better_moves_map[k] = s } // /2にして幅を広くしても、時間を浪費して自滅する。 next_width := width / 4 // 最低幅を4にすると、重すぎ。2でどうか?2でも重い。 if next_width < 1 { next_width = 1 } next_depth := depth - 1 current_move_key := 0 current_score := 0 if depth >= 2 { // depthが2以上なら、絞り込んだ結果を元に、相手の手番でdepth-1手先まで読む。 current_min := 99999 // logger.Trace("depth: " + s(depth)) // logger.Trace("moves: " + s(len(better_moves_map))) for key, score := range better_moves_map { new_ban := FromSFEN(current_sfen) move := (*all_moves)[key] move_string := move.GetUSIMoveString() need_sente_move := true need_gote_move := true if teban { // need_gote_move = true } else { // need_sente_move = false } new_ban.ApplyMove(move_string, true, need_sente_move, need_gote_move) // ここのApplyMove後では、相手側の手だけあれば。 // 王手なら、利きも必要になる。ただ、現在王手かどうかの判定に利きを使っているので、現状は利きと相手側の手だけで。 next_moves := MakeAllMoves(new_ban) if len(next_moves) == 0 { // 手がないので詰み。下のは読んだ先で詰みがある場合? current_move_key = key current_score = 99999 logger.Trace("[BestMove3] tsumi: " + move_string) break } next_best_move, count := player.GetMainBestMove(new_ban, &next_moves, next_width, next_depth, false) if next_best_move == nil { // 手がないのはつまり詰み。 current_move_key = key current_score = -99999 logger.Trace("[BestMove3] tsumi: " + move_string) break } next_best_move_string := next_best_move.GetUSIMoveString() if is_disp { Resp("info time 0 depth 1 nodes 1 score cp "+ToDisplayScore(count, teban)+" pv "+move_string+" "+next_best_move_string, logger) } if current_min > count { current_min = count current_move_key = key current_score = score } else { if current_min == count { if current_score < score { current_move_key = key current_score = score } } } } } else { // depthが1なら、上位width件の中で最高の評価値の手を返す max := -99999 for key, score := range better_moves_map { if score > max { max = score current_move_key = key current_score = score } } } // logger.Trace("[BestMove3] score: " + s(current_score)) selected_move := (*all_moves)[current_move_key] // logger.Trace("------ end ------") return selected_move, current_score }
func main() { // 独自のLoggerを使用 InitLogger() logger := GetLogger() defer logger.Close() // master ban var master *TBan var tesuu int = 0 //player := NewPlayer("Slide") //player := NewPlayer("Random") player := NewPlayer("Main") // 将棋所とのやりとり // TODO:いつでも返答すべきコマンドは常時listenするイメージで。GoRoutineとChannelを使えばよさげ scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { text := scanner.Text() logger.Req(text) switch text { // エンジン登録時は、usiとquitのみ入力される。 case "usi": respUSI(logger) case "quit": // TODO 終了前処理 os.Exit(0) case "setoption name USI_Ponder value true": // TODO 設定を保存する case "setoption name USI_Hash value 256": // TODO 設定を保存する case "isready": master = CreateInitialState() tesuu = 0 Resp("readyok", logger) case "usinewgame": // TODO: モードを切り替えるべきか。 case "gameover": // TODO: 対局待ち状態に戻る。 default: if s.HasPrefix(text, "position") { logger.Trace(text) split_text := s.Split(text, " ") // 通常の対局 // position startpos moves 7g7f 8b7b 2g2f is_sfen := false if split_text[1] == "sfen" { is_sfen = true // 局面編集からの検討だとこのように // position sfen lnsgkgsnl/1r5b1/1pppppppp/p8/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1 moves 2g2f sfen_index := s.Index(text, "sfen") moves_index := s.Index(text, "moves") var sfen_str string if moves_index == -1 { sfen_str = text[sfen_index:] } else { sfen_str = text[sfen_index : moves_index-1] } master = FromSFEN(sfen_str) } if is_sfen { // こちらのルートはどうすればいいのか不明。デッドコピーとしておく。 for index, value := range split_text { if index < 7 { continue } // 何度も一手ずつ反映する必要はないので、スキップしている。 if index-7 < tesuu { continue } logger.Trace("to apply: " + value) master.ApplyMove(value, true, true, true) logger.Trace(master.Display()) tesuu++ } // resp("info string "+text, logger) } else { for index, value := range split_text { if index < 3 { continue } // 何度も一手ずつ反映する必要はないので、スキップしている。 if index-3 < tesuu { continue } logger.Trace("to apply: " + value) master.ApplyMove(value, true, true, true) logger.Trace(master.Display()) logger.Trace(master.ToSFEN(true)) tesuu++ } } } else if s.HasPrefix(text, "go") { split_text := s.Split(text, " ") btime := split_text[2] wtime := split_text[4] teban := *(master.Teban) var ms int = 0 if teban { ms, _ = strconv.Atoi(btime) } else { ms, _ = strconv.Atoi(wtime) } bestmove, score := player.Search(master, ms) if len(bestmove) < 6 { master.ApplyMove(bestmove, true, true, true) logger.Trace(master.Display()) logger.Trace(master.ToSFEN(true)) tesuu++ } Resp(("info time 0 depth 1 nodes 1 score cp " + ToDisplayScore(score, teban) + " pv " + bestmove), logger) bestmove_str := "bestmove " + bestmove Resp(bestmove_str, logger) } } } }