• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

C++ TTEntry类代码示例

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

本文整理汇总了C++中TTEntry的典型用法代码示例。如果您正苦于以下问题:C++ TTEntry类的具体用法?C++ TTEntry怎么用?C++ TTEntry使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。



在下文中一共展示了TTEntry类的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。

示例1: ASSERT_LV3

  void RootMove::insert_pv_in_tt(Position& pos) {

    StateInfo state[MAX_PLY], *st = state;
    bool ttHit;

    // 細かいことだがpvのtailから前方に向かって置換表に書き込んでいくほうが、
    // pvの前のほうがエントリーの価値が高いので上書きされてしまう場合にわずかに得ではある。
    // ただ、現実的にはほとんど起こりえないので気にしないことにする。
    
    for (Move m : pv)
    {
      // 銀の不成の指し手をcounter moveとして登録して、この位置に角が来ると
      // 角の不成の指し手を生成することになるからLEGALではなくLEGAL_ALLで判定しないといけない。
      ASSERT_LV3(MoveList<LEGAL_ALL>(pos).contains(m));
      TTEntry* tte = TT.probe(pos.state()->key(), ttHit);

      // 正しいエントリーは書き換えない。
      if (!ttHit || tte->move() != m)
        tte->save(pos.state()->key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE,
          m, 
#ifndef NO_EVAL_IN_TT         
          VALUE_NONE,
#endif
          TT.generation());

      pos.do_move(m, *st++);
    }

    for (size_t i = pv.size(); i > 0; )
      pos.undo_move(pv[--i]);
  }
开发者ID:AaronWilliamHawkins,项目名称:YaneuraOu,代码行数:31,代码来源:shogi.cpp


示例2: extract_ponder_from_tt

  bool RootMove::extract_ponder_from_tt(Position& pos,Move ponder_candidate)
  {
    StateInfo st;
    bool ttHit;

//    ASSERT_LV3(pv.size() == 1);

    // 詰みの局面が"ponderhit"で返ってくることがあるので、ここでのpv[0] == MOVE_RESIGNであることがありうる。
    if (!is_ok(pv[0]))
      return false;

    pos.check_info_update();
    pos.do_move(pv[0], st, pos.gives_check(pv[0]));
    TTEntry* tte = TT.probe(pos.state()->key(), ttHit);
    Move m;
    if (ttHit)
    {
      m = tte->move(); // SMP safeにするためlocal copy
      if (MoveList<LEGAL_ALL>(pos).contains(m))
        goto FOUND;
    }
    // 置換表にもなかったので以前のiteration時のpv[1]をほじくり返す。
    m = ponder_candidate;
    if (MoveList<LEGAL_ALL>(pos).contains(m))
      goto FOUND;

    pos.undo_move(pv[0]);
    return false;
  FOUND:;
    pos.undo_move(pv[0]);
    pv.push_back(m);
//    std::cout << m << std::endl;
    return true;
  }
开发者ID:AaronWilliamHawkins,项目名称:YaneuraOu,代码行数:34,代码来源:shogi.cpp


示例3: pos

void
TranspositionTable::extractPVMoves(const Position& rootPos, const Move& mFirst, std::vector<Move>& pv) {
    Position pos(rootPos);
    Move m(mFirst);
    UndoInfo ui;
    std::vector<U64> hashHistory;
    while (true) {
        pv.push_back(m);
        pos.makeMove(m, ui);
        if (contains(hashHistory, pos.zobristHash()))
            break;
        hashHistory.push_back(pos.zobristHash());
        TTEntry ent;
        ent.clear();
        probe(pos.historyHash(), ent);
        if (ent.getType() == TType::T_EMPTY)
            break;
        ent.getMove(m);
        MoveList moves;
        MoveGen::pseudoLegalMoves(pos, moves);
        MoveGen::removeIllegal(pos, moves);
        bool contains = false;
        for (int mi = 0; mi < moves.size; mi++)
            if (moves[mi].equals(m)) {
                contains = true;
                break;
            }
        if  (!contains)
            break;
    }
}
开发者ID:raimarHD,项目名称:lcec,代码行数:31,代码来源:transpositionTable.cpp


示例4:

void
TranspositionTable::clear() {
    hashMask = table.size() - 1;
    tbGen.reset();
    notUsedCnt = 0;
    TTEntry ent;
    ent.clear();
    for (size_t i = 0; i < table.size(); i++)
        ent.store(table[i]);
}
开发者ID:raimarHD,项目名称:lcec,代码行数:10,代码来源:transpositionTable.cpp


示例5: rateMoves

void MoveOrdering::rateMoves(std::vector<Move>& moveList, std::shared_ptr<Board> board, const unsigned int ply, const bool isSEE)
{
    TTEntry* ttEntry = globalTT.probeTT(board->key, 0); // returns non nullpr if key exists and depth is greater
    Move hashMove = Move();

    if(ttEntry)
    {
        hashMove = ttEntry->getBestmove();

    }

	for(Move& move : moveList)
	{
		unsigned int score=0;

        if(move==hashMove)
        {
           score += 100000;
        } 


		if(move.isPromotion())
		{
			score += Eval::pieceTypeToValue(move.getPromotedPieceType())-Piece::PAWN_VALUE;
		}

		if(move.isCapture())
		{
            if(isSEE)
            {
                score += board->seeCapture(move, Utils::getOppositeColor(board->getColorToPlay()));
            }
            else
            {
                // MVV/LVA
                score += Eval::pieceTypeToValue(move.getCapturedPieceType())-move.getPieceType();
            }
		}

        if (move == myKiller1[ply])
        {
            score += KILLER1_BONUS;
        }

        if (move == myKiller2[ply])
        {
            score += KILLER2_BONUS;
        }

		move.setMoveRating(score);
	}
}
开发者ID:RomainGoussault,项目名称:Deepov,代码行数:52,代码来源:MoveOrdering.cpp


示例6: if

// Transposition Table look up + alpha/beta update
TTLookupValue AlphaBeta::TTlookup(const GameState & state, AlphaBetaScore & alpha, AlphaBetaScore & beta, const size_t & depth)
{
	TTEntry * entry = _TT->lookupScan(state.calculateHash(0), state.calculateHash(1));
	if (entry && (entry->getDepth() == depth)) 
	{
		// get the value and type of the entry
		AlphaBetaScore TTvalue = entry->getScore();
		
		// set alpha and beta depending on the type of entry in the TT
		if (entry->getType() == TTEntry::LOWER)
		{
			if (TTvalue > alpha) 
			{
				alpha = TTvalue;
			}
		}
		else if (entry->getType() == TTEntry::UPPER) 
		{
			if (TTvalue < beta)
			{
				beta  = TTvalue;
			}
		} 
		else
		{
			printf("LOL\n");
			alpha = TTvalue;
			beta = TTvalue;
		}
		
		if (alpha >= beta) 
		{
			// this will be a cut
			_results.ttcuts++;
			return TTLookupValue(true, true, entry);
		}
		else
		{
			// found but no cut
			_results.ttFoundNoCut++;
			return TTLookupValue(true, false, entry);
		}
	}
	else if (entry)
	{
		_results.ttFoundLessDepth++;
		return TTLookupValue(true, false, entry);
	}

	return TTLookupValue(false, false, entry);
}
开发者ID:welwa,项目名称:ualbertabot,代码行数:52,代码来源:AlphaBeta.cpp


示例7: while

void
TranspositionTable::printStats(int rootDepth) const {
    int unused = 0;
    int thisGen = 0;
    std::vector<int> depHist;
    for (size_t i = 0; i < table.size(); i++) {
        TTEntry ent;
        ent.load(table[i]);
        if (ent.getType() == TType::T_EMPTY) {
            unused++;
        } else {
            if (ent.getGeneration() == generation)
                thisGen++;
            int d = ent.getDepth();
            while ((int)depHist.size() <= d)
                depHist.push_back(0);
            depHist[d]++;
        }
    }
    double w = 100.0 / table.size();
    std::stringstream ss;
    ss.precision(2);
    ss << std::fixed << "hstat: d:" << rootDepth << " size:" << table.size()
       << " unused:" << unused << " (" << (unused*w) << "%)"
       << " thisGen:" << thisGen << " (" << (thisGen*w) << "%)" << std::endl;
    cout << ss.str();
    for (size_t i = 0; i < depHist.size(); i++) {
        int c = depHist[i];
        if (c > 0) {
            std::stringstream ss;
            ss.precision(2);
            ss << std::setw(4) << i
               << ' ' << std::setw(8) << c
               << " " << std::setw(6) << std::fixed << (c*w);
            std::cout << "hstat:" << ss.str() << std::endl;
        }
    }
}
开发者ID:raimarHD,项目名称:lcec,代码行数:38,代码来源:transpositionTable.cpp


示例8: type

// Transposition Table save 
void AlphaBeta::TTsave(	GameState & state, const AlphaBetaScore & value, const AlphaBetaScore & alpha, const AlphaBetaScore & beta, const size_t & depth, 
						const IDType & firstPlayer, const AlphaBetaMove & bestFirstMove, const AlphaBetaMove & bestSecondMove) 
{
	// IF THE DEPTH OF THE ENTRY IS BIGGER THAN CURRENT DEPTH, DO NOTHING
	TTEntry * entry = _TT->lookupScan(state.calculateHash(0), state.calculateHash(1));
	bool valid = entry && entry->isValid();
	size_t edepth = entry ? entry->getDepth() : 0;

	_results.ttSaveAttempts++;
	
	if (valid && (edepth > depth)) 
	{
		return;
	}
	
	int type(TTEntry::NONE);

	if      (value <= alpha) type = TTEntry::UPPER;
	else if (value >= beta)  type = TTEntry::LOWER;
	else                     type = TTEntry::ACCURATE;

	// SAVE A NEW ENTRY IN THE TRANSPOSITION TABLE
	_TT->save(state.calculateHash(0), state.calculateHash(1), value, depth, type, firstPlayer, bestFirstMove, bestSecondMove);
}
开发者ID:welwa,项目名称:ualbertabot,代码行数:25,代码来源:AlphaBeta.cpp


示例9: checkTime

// 基本思考ルーチン::depthMax手読み
int AI::think(LightField &self, LightField &enemy, int depth, int timeLimit)
{
	if (calls_count++ > 1000)
	{
		checkTime();
		calls_count = 0;
	}

	// rootからの手数
	int ply = depth_max_ - depth;

#ifdef HASH
	TTEntry *tte;

	// 同一局面が発生するのは2手目以降しかありえない。
	if (ply > 0)
	{
		bool tt_hit = TT.probe<true>(&self, nullptr, tte);

		// 局面が登録されていた
		if (tt_hit)
		{
			assert(tte->depth() >= 0);

			// 局面表に登録されている局面が、現在の局面の残り深さ以上
			if (tte->depth() >= depth)
			{
				best_[depth] = tte->move();

				// 局面表のスコアは信用できるのでそのまま返す
				return tte->score();
			}
		}
	}
#endif

	if (depth <= DEPTH_ZERO)
		return evalate(self, enemy, depth, timeLimit);
	else
	{	
		int score;
		int max = -SCORE_INFINITE - 1;
		int movenum;
		int con_prev[3];
		self.saveConnect(con_prev);
		Move move[22];// おける場所は最大で22種類なので

		// 置く場所なし == 負け
		if ((movenum = self.generateMoves(move)) == 0)
			return -SCORE_INFINITE;
		
		self.nextPlus();

#if defined(DEBUG)
		LightField f = self;// debug
#endif
		for (int i = 0; i < movenum; i++)
		{
			// generateMovesでもとめた場所においてみる
			self.doMove<true>(move[i]);
			assert(self.key() == self.keyInit());

			// 設置にかかる時間を計算
			// 落下にかかる時間は、13 - 設置位置のyの小さいほう ちぎりなら、余計に時間がかかる
			int takeTime = (13 - std::min(toY(move[i].csq()), toY(move[i].psq()))) * FALLTIME + (move[i].isTigiri() ? TAKETIME_INCLUDETIGIRI : TAKETIME);

			if (self.flag(VANISH))// 消えるなら
			{
				score = evalVanish(self, enemy, depth, timeLimit) - takeTime;
				self.clearFlag(VANISH);
			}
			else// 消えないとき
			{
				if (timeLimit < takeTime)
				{
					// 致死量振るときに発火できなければ負け。
					if (enemy.scoreMax() >= 30 * RATE || enemy.scoreMax() >= self.deadLine() * RATE) 
						score = -SCORE_INFINITE;
					else 
						score = think(self, enemy, depth - ONE_PLY, timeLimit - takeTime) - takeTime;
				}
				else
					score = think(self, enemy, depth - ONE_PLY, timeLimit - takeTime) - takeTime;
			}

			self.undoMove(move[i], con_prev);

			if (stop)
				return SCORE_ZERO;

			if (max < score)
			{
				max = score;
				best_[depth] = move[i];// もっとも評価の高い手を選ぶ
			}

#if defined DEBUG
			assert(self == f); // debug::きちんともとの局面に戻せているか
#endif
//.........这里部分代码省略.........
开发者ID:TukamotoRyuzo,项目名称:tukapuyo,代码行数:101,代码来源:AI.cpp


示例10: search

  Value search(Position& pos, Value alpha, Value beta, Depth depth)
  {
    ASSERT_LV3(alpha < beta);

    // -----------------------
    //     nodeの種類
    // -----------------------

    // root nodeであるか
    const bool RootNode = NT == Root;

    // PV nodeであるか(root nodeはPV nodeに含まれる)
    const bool PvNode = NT == PV || NT == Root;

    // -----------------------
    //     変数宣言
    // -----------------------

    // 現在のnodeのrootからの手数。これカウンターが必要。
    // nanoだとこのカウンター持ってないので適当にごまかす。
    const int ply_from_root = (pos.this_thread()->rootDepth - depth / ONE_PLY) + 1;

    // -----------------------
    //   置換表のprobe
    // -----------------------

    auto key = pos.state()->key();

    bool ttHit;    // 置換表がhitしたか
    TTEntry* tte = TT.probe(key, ttHit);

    // 置換表上のスコア
    // 置換表にhitしなければVALUE_NONE
    Value ttValue = ttHit ? value_from_tt(tte->value(), ply_from_root) : VALUE_NONE;

    auto thisThread = pos.this_thread();

    // 置換表の指し手
    // 置換表にhitしなければMOVE_NONE

    // RootNodeであるなら、指し手は現在注目している1手だけであるから、それが置換表にあったものとして指し手を進める。
    Move ttMove = RootNode ? thisThread->rootMoves[thisThread->PVIdx].pv[0]
      :  ttHit ? tte->move() : MOVE_NONE;

    // 置換表の値による枝刈り
    
    if (!PvNode        // PV nodeでは置換表の指し手では枝刈りしない(PV nodeはごくわずかしかないので..)
      && ttHit         // 置換表の指し手がhitして
      && tte->depth() >= depth   // 置換表に登録されている探索深さのほうが深くて
      && ttValue != VALUE_NONE   // (VALUE_NONEだとすると他スレッドからTTEntryが読みだす直前に破壊された可能性がある)
      && (ttValue >= beta ? (tte->bound() & BOUND_LOWER)
                          : (tte->bound() & BOUND_UPPER))
      // ttValueが下界(真の評価値はこれより大きい)もしくはジャストな値で、かつttValue >= beta超えならbeta cutされる
      // ttValueが上界(真の評価値はこれより小さい)だが、tte->depth()のほうがdepthより深いということは、
      // 今回の探索よりたくさん探索した結果のはずなので、今回よりは枝刈りが甘いはずだから、その値を信頼して
      // このままこの値でreturnして良い。
      )
    {
      return ttValue;
    }

    // -----------------------
    // 1手ずつ指し手を試す
    // -----------------------

    pos.check_info_update();
    MovePicker mp(pos,ttMove);

    Value value;
    Move move;

    StateInfo si;

    // この局面でdo_move()された合法手の数
    int moveCount = 0;
    Move bestMove = MOVE_NONE;

    while (move = mp.nextMove())
    {
      // root nodeでは、rootMoves()の集合に含まれていない指し手は探索をスキップする。
      if (RootNode && !std::count(thisThread->rootMoves.begin() + thisThread->PVIdx,
        thisThread->rootMoves.end(), move))
        continue;

      // legal()のチェック。root nodeだとlegal()だとわかっているのでこのチェックは不要。
      if (!RootNode && !pos.legal(move))
        continue;

      // -----------------------
      //      1手進める
      // -----------------------

      pos.do_move(move, si, pos.gives_check(move));

      // do_moveした指し手の数のインクリメント
      ++moveCount;

      // -----------------------
      // 再帰的にsearchを呼び出す
      // -----------------------
//.........这里部分代码省略.........
开发者ID:mchem,项目名称:YaneuraOu,代码行数:101,代码来源:nano_search.cpp


示例11: firstEntry

void TranspositionTable::store(const Key posKey, const Score score, const Bound bound, Depth depth,
  Move move, const Score evalScore)
{
#ifdef OUTPUT_TRANSPOSITION_EXPIRATION_RATE
  ++numberOfSaves;
#endif

  TTEntry* tte = firstEntry(posKey);
  TTEntry* replace = tte;
  const u32 posKeyHigh32 = posKey >> 32;

  if (depth < Depth0) {
    depth = Depth0;
  }

  for (int i = 0; i < ClusterSize; ++i, ++tte) {
    // 置換表が空か、keyが同じな古い情報が入っているとき
    if (!tte->key() || tte->key() == posKeyHigh32) {
      // move が無いなら、とりあえず古い情報でも良いので、他の指し手を保存する。
      if (move.isNone()) {
        move = tte->move();
      }

      tte->save(depth, score, move, posKeyHigh32,
        bound, this->generation(), evalScore);
      return;
    }

    int c = (replace->generation() == this->generation() ? 2 : 0);
    c += (tte->generation() == this->generation() || tte->type() == BoundExact ? -2 : 0);
    c += (tte->depth() < replace->depth() ? 1 : 0);

    if (0 < c) {
      replace = tte;
    }
  }

#ifdef OUTPUT_TRANSPOSITION_EXPIRATION_RATE
  if (replace->key() != 0 && replace->key() != posKeyHigh32) {
    ++numberOfCacheExpirations;
  }
#endif

  replace->save(depth, score, move, posKeyHigh32,
    bound, this->generation(), evalScore);
}
开发者ID:aoshimanoa,项目名称:apery,代码行数:46,代码来源:tt.cpp


示例12: checkTime

Score AI::search(Score alpha, Score beta, LightField& self, LightField& enemy, int depth, int my_remain_time)
{
	if (calls_count++ > 100)
	{
		checkTime();
		calls_count = 0;
	}

	node_searched++;
	const bool rootnode = NT == ROOT;

	assert(alpha >= -SCORE_INFINITE && alpha < beta && beta <= SCORE_INFINITE);

	// ルートからの手数
	int ply = depth_max_ - depth;

	// 局面表を見る
	Move tt_move, best_move;
	Score tt_score;
	TTEntry* tte;
	const Key key = self.key() ^ enemy.key();
	const bool tt_hit = TT.probe<false>(&self, &enemy, tte);

	if (stop)
		return SCORE_ZERO;

	// 局面表の指し手
	tt_move = tt_hit ? tte->move() :
		rootnode ? root_moves[0].pv[0] : Move::moveNone();

	// 置換表上のスコア
	tt_score = tt_hit ? tte->score() : SCORE_NONE;

	// 置換表のスコアが信用に足るならそのまま返す。
	// 条件)
	// root nodeではない
	// 置換表にエントリーがあった
	// 置換表のエントリーのdepthが今回の残り探索depth以上である
	// 置換表のエントリーのスコアがSCORE_NONEではない。(置換表のアクセス競合のときにのみこの値になりうる)
	// 置換表のスコアのboundがBOUND_EXACTなら信用に足るので置換表の指し手をそのまま返す
	// non PV nodeであれば置換表の値がbetaを超えているならBOUND_LOWER(真の値はこれより上なのでこのときbeta cutできる)であるか、
	// betaを超えていないのであれば、BOUND_UPPER(真の値はこれより下なのでこのときbeta cutが起きないことが確定)である。

	if (!rootnode
		&& tt_hit
		&& tte->depth() >= depth
		&& (depth == 0
			|| (tte->bound() == BOUND_EXACT
				|| (tte->bound() & BOUND_LOWER && tt_score >= beta))))
	{
		best_[depth] = tte->move();

		assert(tte->move().isNone() || tte->move().isLegal(self));

		// 局面表のスコアは信用できるのでそのまま返す
		return tt_score;
	}

	// 最大探索深さまでいったら、その局面の点数を返す
	if (depth <= DEPTH_ZERO)
	{
		Score s = evaluateEX(self, enemy, depth, my_remain_time);

		// せっかく評価関数を呼び出したので局面表に登録しておく。
		tte->save(key, 0, s, 0, BOUND_NONE, TT.generation(), self.player(), my_remain_time, self.ojama() - enemy.ojama());
		return s;
	}

	Move move[23];
	int move_max = 0;
	Move *pmove = move;

	if (!tt_move.isNone())
	{
		if (tt_move.isLegalAbout(self))
		{
			// 置換表にある手を手のバッファの先頭に入れる。
			*pmove++ = tt_move;
			move_max++;
		}
	}

	if ((move_max += self.generateMoves(pmove)) == 0)
	{
		// 置く場所なし == 負け
		return SCORE_MATED;
	}

	Score score, max = -SCORE_INFINITE;

	// お邪魔ぷよが降る場合はenemyのojamaを減らしているので、
	// このmoveを調べ終わった後元に戻さなければならない
	int enemy_ojama_prev = enemy.ojama();
	Flag enemy_flag = enemy.flag();
	self.nextPlus();

	// TODO:ムーブオーダリングしたい

	// 手がある間、すべての手を試す
	for (int i = 0; i < move_max; i++)
//.........这里部分代码省略.........
开发者ID:TukamotoRyuzo,项目名称:tukapuyo,代码行数:101,代码来源:AI_PolytecFesta2015.cpp


示例13: getIndex

void
TranspositionTable::insert(U64 key, const Move& sm, int type, int ply, int depth, int evalScore) {
    if (depth < 0) depth = 0;
    size_t idx0 = getIndex(key);
    U64 key2 = getStoredKey(key);
    TTEntry ent0, ent1;
    ent0.load(table[idx0]);
    size_t idx = idx0;
    TTEntry* ent = &ent0;
    if (ent0.getKey() != key2) {
        size_t idx1 = idx0 ^ 1;
        ent1.load(table[idx1]);
        idx = idx1;
        ent = &ent1;
        if (ent1.getKey() != key2)
            if (ent1.betterThan(ent0, generation)) {
                idx = idx0;
                ent = &ent0;
            }
    }
    bool doStore = true;
    if ((ent->getKey() == key2) && (ent->getDepth() > depth) && (ent->getType() == type)) {
        if (type == TType::T_EXACT)
            doStore = false;
        else if ((type == TType::T_GE) && (sm.score() <= ent->getScore(ply)))
            doStore = false;
        else if ((type == TType::T_LE) && (sm.score() >= ent->getScore(ply)))
            doStore = false;
    }
    if (doStore) {
        if ((ent->getKey() != key2) || (sm.from() != sm.to()))
            ent->setMove(sm);
        ent->setKey(key2);
        ent->setScore(sm.score(), ply);
        ent->setDepth(depth);
        ent->setGeneration((S8)generation);
        ent->setType(type);
        ent->setEvalScore(evalScore);
        ent->store(table[idx]);
    }
}
开发者ID:raimarHD,项目名称:lcec,代码行数:41,代码来源:transpositionTable.cpp



注:本文中的TTEntry类示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C++ TTObject类代码示例发布时间:2022-05-31
下一篇:
C++ TTAudioSignalPtr类代码示例发布时间:2022-05-31
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap