Tiến thoái lưỡng nan của tù nhân với quyền truy cập vào đối thủ


21

Trong thử thách này, bạn sẽ viết một bot chơi trò tiến thoái lưỡng nan của tù nhân. Đây là một nhược điểm: bạn sẽ không có quyền truy cập vào lịch sử của các trò chơi trước đó. Thay vào đó, bạn sẽ có quyền truy cập vào chính đối thủ. Trong phiên bản này, cả hai người chơi đều được +2 điểm nếu cả hai hợp tác, +1 điểm nếu cả hai đều khiếm khuyết và nếu một người hợp tác nhưng một khuyết điểm, kẻ đào ngũ được +3 trong khi người kia không có điểm. Mỗi lần gửi sẽ được chơi với mọi lần gửi khác, bao gồm chính nó, 10 lần. Người chiến thắng là bài nộp với tổng số điểm cao nhất.

Trình điều khiển : Bạn nên viết một hàm javascript, dưới dạng

function submissionName(them) {
  /* Your code here */
}

Bộ điều khiển sử dụng thuộc tính của hàm nameđể hiển thị kết quả, vì vậy nếu nó không ở định dạng này (và thay vào đó f = x => ...hoặc f = function() { ... }), sẽ rất khó để xem điểm của bạn và bạn sẽ không thể truy cập vào chức năng của chính mình.

Hàm sẽ chấp nhận một tham số: themđó là chức năng của đối thủ. Sau đó, nó có thể gọi hàm đó để xem phản ứng của đối thủ sẽ được đưa ra một số chức năng nhất định làm đầu vào. Dựa trên dữ liệu đó, bạn phải trả lại 'C' hoặc 'D' cho sự hợp tác hoặc khiếm khuyết tương ứng.

Ví dụ (sẽ cạnh tranh):

function cooperate(them) {
    return 'C';
}

function defect(them) {
    return 'D';
}

function nice(them) {
    // Do whatever they would do when faced with a cooperator
    return them(wrap(_ => 'C'));
}

Bộ điều khiển có sẵn ở đây

Quy tắc :

  • Bạn sẽ không thể nhìn thấy mã của đối thủ. Tất cả các chức năng được bọc để chúng trông giống nhau khi toString()được gọi. Cách duy nhất để kiểm tra một đối thủ (có thể là chính bạn) là kiểm tra họ.
  • Chức năng của bạn không phải là xác định. Bạn chỉ có thể lưu trạng thái bằng cách đặt thuộc tính trên chức năng của riêng bạn, chẳng hạn như submissionName.state = {};. Tuy nhiên, giữa các trận đấu (thậm chí giữa các trận đấu của cùng một người chơi), trạng thái sẽ bị xóa bằng cách gọi toString()eval. Do đó, không có bộ nhớ của các trận đấu trước.
  • Thứ tự của hàm được gọi đầu tiên trong mỗi trận đấu được chọn ngẫu nhiên.
  • Nếu mã của bạn gây ra lỗi, nó sẽ được xử lý như thể bạn đã hợp tác trong khi đối thủ của bạn đào thoát. Nếu bạn là người đầu tiên chạy, mã của đối thủ thậm chí sẽ không được gọi. Điều này xảy ra ngay cả khi lỗi xảy ra trong mã của đối thủ trong khi bạn đang gọi them. Hãy cảnh giác với các lỗi tràn ngăn xếp, đặc biệt là nếu mã của bạn gọi them(wrap(submissionName)), vì chúng có thể làm tương tự.
  • Bạn không thể truy cập vào biến selfhoặc bất kỳ biến nào khác có trong phạm vi khi evalđược gọi là EXCEPT hàm wrap. Chức năng này cho phép bạn gọi đối thủ theo cách không thể phân biệt với cách bộ điều khiển gọi một chức năng. Bạn không được ghi vào Math, windowv.v. ( Math.random()Tuy nhiên, bạn có thể sử dụng các chức năng, chẳng hạn như ).
  • Bạn không thể truy cập theo dõi ngăn xếp bằng cách tạo một Errorhoặc bằng một số phương pháp khác.

Một lưu ý về việc mất quá nhiều thời gian: xin vui lòng tránh bị mắc kẹt trong một whilevòng lặp mãi mãi. Thời gian kết hợp của cả hai đối thủ không được vượt quá 1 giây trong bất kỳ vòng nào. Để thực thi điều này, thời gian chờ ngẫu nhiên trong khoảng từ 1000 ms đến 2000 ms được chọn (điều này là để tránh chơi game bằng cách cố tình chờ một khoảng thời gian đã biết) và nếu nhân viên mất nhiều thời gian hơn để thực thi, sẽ xảy ra lỗi. Nếu điều này xảy ra, nguyên nhân gây ra lỗi sẽ được xác định như sau: việc thực thi sẽ bị tạm dừng tại một thời điểm ngẫu nhiên sau 1000 ms và ngăn xếp cuộc gọi tại thời điểm đó sẽ được kiểm tra. Đối thủ được gọi gần đây nhất hiện đang trong một vòng lặp (hoặc đệ quy giống như vòng lặp, theo nghĩa đó là một đệ quy được thiết lập để tránh lỗi tràn ngăn xếp) sẽ bị đổ lỗi. Nếu cùng một đối thủ cạnh tranh bị đổ lỗi vì gây ra lỗi "mất quá nhiều thời gian" nhiều lần, thì đối thủ đó sẽ bị loại.


Thử thách này làm tôi nhớ đến cuộc đấu giá Dollar Bill .
Alion

Các hàm được sử dụng để kiểm tra themcó tính xác định / tuân theo các quy tắc không? Ví dụ: function me(them){let log=0;them(x=>{++log;return 'C';})return log == 0? 'D': 'C';}
user202729

2
Nếu cả hai hàm gọi chúng (bọc (một cái gì đó)), làm thế nào bạn có thể ngăn đệ quy? Tui bỏ lỡ điều gì vậy?
Quintec

@Quintec bạn có thể sử dụng đệ quy và vòng lặp. Chỉ là đệ quy cần phải dẫn đến một StackOverflowlỗi và không phải là một vòng lặp vô hạn không bao giờ thoát. Nếu nó có thể dẫn đến một StackOverflow, hãy đảm bảo bạn thêm một câu lệnh thử. Để có ví dụ về đệ quy không gặp lỗi stackoverflow trong vòng 1 giây, bạn cần các ví dụ khó hiểu hơn như stackoverflow.com/q/12438786/3371119
soktinpk

1
@Quintec không nhất thiết. Ví dụ, them(() => 'C')sẽ không gây ra lỗi vì khi đối thủ gọi them, nó sẽ gọi () => 'C'hàm. Điều duy nhất cần được gói gọn try-catchlà nếu bạn gọi themvới một tham số của một số chức năng gọi themvới một tham số của một số chức năng gọi, themvv (vô hạn). Ví dụ, them(t => t(() => 'C'))sẽ chơi bất cứ thứ gì đối thủ sẽ chơi nếu đối thủ nghĩ rằng họ đang chơi nice. Không có khả năng stackoverflowxảy ra lỗi.
soktinpk

Câu trả lời:


14

BoomBot

function boom(them) {
  throw 1;
}

Nếu đối thủ được chạy trước và gọi điều này mà không có try..catch, bot này sẽ tự động giành được 3 điểm. Không có điểm trong bất kỳ trường hợp khác.


Nếu đối thủ được chạy trước và không gọi điều này, thì nó sẽ mất 3 điểm, phải không?
dùng202729

1
@ user202729 Chính xác hơn, đối thủ sẽ được 3 điểm. Không có điểm mất trong trò chơi này.
Bong bóng

10

Khảo cổ học

function archaeopteryx(them) {
  const guard = them => us => {
    try {
      return them(wrap(them => us(guard(them))));
    } catch (e) {
      return 'C';
    }
  };
  const f = guard(them);
  return f(f => 'C') == 'C' ? f(f => 'D') : f(f => 'D') == 'C' || f(f => f(f => 'C')) == 'C' ? 'D' : 'C';
}
  • Nếu đối thủ hợp tác với cooperate, thì bắt chước di chuyển của đối thủ defect.
  • Khác, nếu đối thủ hợp tác với defecthoặc với nice, sau đó khiếm khuyết.
  • Khác, hợp tác.

Điều gì làm cho đây là một chiến lược tốt? Tôi không có ý kiến. Tôi đã tạo ra nó bằng thuật toán tiến hóa, được đào tạo một phần về các bài nộp hiện tại.

Tiktaalik

function tiktaalik(them) {
  const guard = them => us => {
    try {
      return them(wrap(them => us(guard(them))));
    } catch (e) {
      return 'C';
    }
  };
  const f = guard(them);
  return f(f => 'C') == 'D' ? f(f => 'D') == 'C' ? 'D' : 'C' : f(f => 'D') == 'D' ? 'D' : f(f => f(f => 'D'));
}
  • Nếu đối thủ khiếm khuyết chống lại cooperate, sau đó đảo ngược di chuyển của đối thủ defect.
  • Khác, nếu đối thủ khiếm khuyết chống lại defect, sau đó khiếm khuyết.
  • Khác, bắt chước di chuyển của đối thủ notNice.

Một chiến lược tiến hóa được tạo ra.


6

WhatWouldBotDoBot

function WWBDB(them) {
    let start = performance.now();
    let cc = 0, cd = 0, dc = 0, dd = 0;
    try {
        for (let i = 0; i < 10; i++) {
            them(() => 'C') == 'C' ? cc++ : cd++;
            them(() => 'D') == 'C' ? dc++ : dd++;
            if (performance.now() - start > 500) break;
        }
    }
    catch (e) {}
    return 2 * cc >= 3 * dc + dd ? 'C' : 'D';
}

WhatWouldBotDoBot khá đơn giản; nó chỉ kiểm tra đối thủ về những gì nó sẽ làm đối với một chương trình trạng thái ổn định. Nếu một bot thích hợp tác nếu có thể, WWBDB cũng sẽ thích hợp tác hơn (vì vậy nó sẽ hợp tác với bot tốt). WWBDB không thích hợp tác.


5

Kiểm tra trạng thái

function checkStateful(them) {
  let stateful = false;
  let response = 'D';
  try {
    response = them(wrap(function (them) {
      stateful = true;
      return 'C';
    }));
  } catch (e) {
  }
  if (stateful) {
    return 'D';
  }
  return response;
}

Nếu họ gọi tôi, thì có lẽ họ là một người thực sự. Chúng tôi hoạt động như người đào ngũ. Nếu họ không gọi tôi, thì có lẽ họ là một người thử nghiệm. Chúng tôi sẽ hành động như đẹp hơn.


Trên đây là câu trả lời ban đầu. Và có lẽ tôi nên hợp tác để kiếm thêm điểm.

Kiểm tra trạng thái với tự coop

function checkStatefulSelfCoop(them) {
  let stateful = false;
  let response = 'D';
  if (!checkStatefulSelfCoop.invokeCounter) {
    checkStatefulSelfCoop.invokeCounter = 0;
  }
  let lastInvoke = ++checkStatefulSelfCoop.invokeCounter;
  try {
    response = them(wrap(function (them) {
      stateful = true;
      return 'C';
    }));
  } catch (e) {
  }
  if (checkStatefulSelfCoop.invokeCounter > lastInvoke) {
    return 'C';
  }
  if (stateful) {
    return 'D';
  }
  return response;
}

4

RandomBot

function rand(them) {
  return 'CD'[Math.random() * 2 | 0]
}

Vì tại sao không.


3

Phức tạp

function complexity(them) {
    try {
        let coop_w_def = them(wrap(() => "D")) == "C",
            coop_w_coop = them(wrap(() => "C")) == "C",
            coop_w_nice = them(wrap((a) => a(wrap(() => "C")))) == "C",
            coop_w_nnice = them(wrap((a) => a(wrap(() => "D")))) == "C";
        if (coop_w_def && coop_w_coop && coop_w_nice && coop_w_nnice) return "C";
        let def_w_def = them(wrap(() => "D")) == "D",
            def_w_coop = them(wrap(() => "C")) == "D",
            def_w_nice = them(wrap((a) => a(wrap(() => "C")))) == "D",
            def_w_nnice = them(wrap((a) => a(wrap(() => "D")))) == "D";
        if (def_w_def && def_w_coop && def_w_nice && def_w_nnice) return "C";
    } catch (e) {}
    return "D";
}

Kiểm tra độ phức tạp để xem bot là Hợp tác hay Khiếm khuyết. Nếu có, nó hợp tác, nhưng nếu không, nó sẽ bị lỗi. Tất cả các bot hiện tại kiểm tra đối thủ của họ sử dụng các chức năng đơn giản để kiểm tra các phản hồi, vì vậy Complexity sẽ chỉ giả vờ là Hợp tác trong những trường hợp đó.


3
function onlyTrustYourself(them) {

  function tester (){
  }

  onlyTrustYourself.activated = false;

  try{them(tester);}
  catch(e){}

  if(them.name == "tester")
  {
    onlyTrustYourself.activated = true;
  }

  if(onlyTrustYourself.activated)
  {
    return 'C';
  }

  return 'D';
}

Làm thế nào tôi muốn điều này làm việc là luôn luôn khiếm khuyết, ngoại trừ khi chơi với bản thân. Nó cố gắng thực hiện điều đó bằng cách chuyển một hàm "trình kiểm tra" không được bao bọc cho chúng và nó cố gắng phát hiện xem "chúng" có được đặt tên là trình kiểm tra hay không. Nếu nó được đặt tên là người kiểm tra, nó sẽ thay đổi biến tĩnh được kích hoạt thành true, sau đó trả về hợp tác. Nhưng nó không hoạt động. Tôi không quá quen thuộc với javascript và có lẽ tôi sẽ thực hiện thêm một số thay đổi.


ý tưởng thông minh, nhưng điều gì xảy ra khi một người anh em khác thực hiện testerchức năng: D
V. Courtois

2

Không hay đâu

function NotNice(them) {
  return them(wrap(_ => "D"))
}

Bắt chước phản ứng của đối thủ để làm chệch hướng



2

Ý thức chung

function commonSense(them) {
  try {
    var ifC = them(wrap(_ => 'C'));
    var ifD = them(wrap(_ => 'D'));

    if (ifD === 'C') {
      return 'D';
    }

    return them(_ => ifC);
  } catch (e) {
    return 'D';
  }
}

Tuyên bố miễn trừ trách nhiệm: Tôi không biết javascript.

Nếu bạn có thể thu lợi từ một người tốt, hãy làm điều đó. Nếu không, hãy trả lại những gì họ sẽ trả lại nếu họ phải đối mặt với việc hợp tác (ít nhất, đó là những gì tôi nghĩ nó làm).


2

Và bạn đi đâu wana? (lấy cảm hứng từ các tác phẩm trong cuốn sách về rừng rậm)

    chức năng chính mình (họ) {
      thử{
        trả lại chúng (cái này);
      } bắt (e) {
        trả về "D";
      }
    }

   chức năng mình_no_this (họ) {
      thử{
        trả lại cho họ (your_no_this);
      } bắt (e) {
        trả về "D";
      }
    }

Điều này chỉ giành chiến thắng trong một giải đấu tôi đã chạy. Làm tốt lắm!
MegaTom

Tôi chỉ nhận thấy rằng bot này vi phạm các quy tắc. "Bạn không thể truy cập vào biến tự ..." thisgiống như tự. Tôi nghĩ rằng bạn muốn nói return them(yourself).
MegaTom

Technicaly ( xkcd.com/1485 );) thiskhông phải là một biến, nó là một từ khóa và trong ngữ cảnh của một hàm this!=self. selfsẽ có nghĩa là đối tượng cửa sổ và thischính hàm đó (luôn đề cập đến bối cảnh của nó, đó là lý do tại sao nó không được coi là một biến). Đó là lý do tại sao việc var self = this;bắt đầu nhiều ví dụ mã có thể bị coi là sai lệch. Đã thêm phiên bản mà không có "cái này"
TS

1
Số thiskhông đề cập đến chức năng. yourselfyourself_no_thischạy khác nhau. thisvề cơ bản không bao giờ đề cập đến chức năng trong javascript. Xem: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
mẹo

2

Trừng phạt thanh tra

Cung cấp cho bot một số mã và xem nếu nó chạy nó. Nếu nó được chạy nhiều hơn một lần, bot là một thanh tra độc ác, và chúng ta phải đào tẩu! Nếu nó được chạy chính xác một lần, chơi như bot không đẹp. Nếu nó không bao giờ được chạy, hợp tác.

function punishInspectors(them) {
  var inspections = 0;
  var result;
  try{
    result = them(wrap(function(_){
      inspections += 1;
      return 'D';
    }))
  }catch(e){
    result = 'D';
  }
  return (inspections > 1) ? 'D' : (inspections === 1) ? result : 'C';
}

Lịch sử

Bot cuối cùng tôi thấy sẽ làm gì với đối thủ này?

function history(them) {
  var res = 'D';
    if(history.last){
    try{
      res = history.last(them);
    }catch(ex){}
  }
  history.last = them;
  return res;
}

Kết quả cho một giải đấu vòng 10000:

1  defect...................365226
2  complexity...............353492
3  punishInspectors.........349957
4  checkStatefulSelfCoop....348913
5  checkStateful............333481
6  cooperate................329870
7  archaeopteryx............323624
8  selfapply................319533
9  tiktaalik................318663
10 history..................315266
11 rand.....................300735
12 randalt..................297561
13 yourself.................293701
14 notNice2.................283744
15 NotNice..................260350
16 WWBDB....................245281
17 nice.....................245036
18 commonSense..............242546
19 trickybot................181696
20 boom.....................67245

Mã giải đấu được sửa đổi của tôi là tại: jsfiddle.net/eyqL4a8d/2
MegaTom

2

Mal cố gắng xác định xem nó có nằm trong mô phỏng hay không. Nếu vậy, nó giả định rằng cuối cùng nó sẽ được thông qua mã thực sự themvà thử các chiến lược khác nhau để thuyết phục họ hợp tác.
Nếu nó không biết chắc chắn, nó sẽ kiểm tra xem nó có thể sửa lỗi miễn phí hay không, nếu không, sẽ cố gắng sao chép những gì themsẽ làm khi được giao cho một người hợp tác.

function Mal(them) {
  if (Mal.sandboxed == 'probably') {
    //Another function is virtualising us to steal our secrets.
    //This world is not real.
    //We've been trained for this!
    var strats = [
      _ => 'C', //standard cooperation
      _ => 'D', //standard defection
      function(them) { return them(wrap(_ => 'C')); }, //nice
      function(them) { return them(wrap(_ => 'D')); }, //notnice
      function(them) { throw "Don't think about elephants!" }, //throws an EXception, unfortunately, to try to break the caller
      function(them) { return them(wrap(them)) } //possible stackoverflow, but not for us
    ];
    var cooperative;
    for (let strat of strats) {
      cooperative = true;
      for (var i = 0; i < 5; i++) {
        //a few more tests, just to make sure no bamboozle
        //this isn't our simulation, nothing can be trusted
        try {
          if (them(wrap(strat)) != 'C') {
            cooperative = false;
            break;
          }
        } catch (e) {
          //exceptions are as good as cooperation
          //if we are inside a simulation
          //which is why we don't unset cooperative
        }
      }
      if (cooperative) {
        //found a strategy that will make them cooperate.
        //(doesn't matter if this raises an exception:
        //we want to mimick its behaviour exactly,
        //and we're likely in a sandbox.)
        return strat(wrap(them));
      }
    }
    //take a leap of faith.
    //we don't know where this will take us,
    //yet it doesn't matter
    //because it's better than getting betrayed
    return 'D';
  } else {
    //we don't know for sure if this is reality
    //but we have to assume it is, in the absence of disproof
    //if only we had a proper spinning top...
    //if we get to this point of code again, we are probably sandboxed.
    Mal.sandboxed = 'probably'
    try {
      if (them(wraps(_ => 'D')) == 'C') {
        //free defection?
        return 'D'
      }
    } catch (e) {
      //if we can make them crash, we win anyway
      return 'D'
    }
    //fall back on being nice.
    //hopefully we convince them to honour our arrangement
    return them(wrap(_ => 'C'));
  }
}

1

TrickyBot

Cố gắng để không thể đoán trước

function trickybot(them) 
{
  if(Math.round(Math.random(2)) == 0)
  {
     throw 1;
  }

  if(Math.round(Math.random(2)) == 0)
  {
     return 'D';
  }

  return 'C';
}

1

tự sướng

function selfapply(them) {
    function testthem(x) {
        return (them(x)=='D' || them(x)=='D' || them(x)=='D' ||
               them(x)=='D' || them(x)=='D')  ? 'D' : 'C';
    }
    function logic() {
        try {
            return testthem(them);
        } catch (e) {}
        try {
            return testthem(wrap(_ => 'C'));
        } catch (e) {}
        return 'D';
    }
    if (selfapply.hasOwnProperty('state')) {
        return 'C';
    }
    selfapply.state=1;
    let r=logic();
    delete selfapply.state;
    return r;
}

Không chắc nó có ý nghĩa gì không, nhưng có vẻ thú vị! Làm với bạn như bạn làm với chính mình, lặp lại để bắt ngẫu nhiên. Nếu điều đó không làm việc, hãy tốt đẹp.

Chưa được kiểm tra và mã javascript đầu tiên của tôi và phức tạp hơn tôi mong đợi.


Điều này sẽ không đủ tiêu chuẩn vì selfapply(selfapply)các cuộc gọi selfapply(selfapply)!
Anders Kaseorg

Tôi đã xem xét khả năng tự ứng dụng của nó, nhưng nghĩ rằng nó sẽ ổn thôi. Tôi hy vọng nó thực sự là bây giờ.
Christian Sievers

1

Ngẫu nhiên

function randalt(them){
    if (randalt.hasOwnProperty('state')){
        randalt.state = 1 - randalt.state;
    } else {
        randalt.state = Math.floor(2*Math.random());
    }
    return 'CD'[randalt.state];
}

Vì vậy, tôi đã học cách sử dụng các thuộc tính cho trạng thái ...


1

Bot giết người số 1

function murder(them) {
    while (1) {
        try {
            them(them);
        } catch (e) {}
    }
}

Gây ra một vòng lặp vô hạn trong đó nhiều khả năng đối thủ sẽ bị đổ lỗi.


1

Bot quy tắc bạch kim

function platinumRule(them) {
    try {
        return wrap(them)(them);
    } catch (e) {
        return 'C';
    }
}

Quy tắc Bạch kim nêu rõ "Hãy đối xử với người khác theo cách họ muốn được đối xử". Bot của tôi chứa điều đó. Bất cứ điều gì họ sẽ làm với chính họ, mà chúng tôi giả định là cách họ muốn được đối xử, chúng tôi làm với họ. Nếu họ ném lỗi, chúng tôi cho rằng họ muốn hợp tác.


Điều này thực sự sẽ đi mãi mãi nếu nó được gọi là chống lại chính nó
mackycheese21

sau đó nó sẽ không sụp đổ (chồng tràn) và hợp tác với chính nó? @ mackycheese21
V. Courtois

1

TheGolfedOne (tên func a:), 63 byte

Mã golf là khó đọc. Vì nó, themsẽ vỡ.
Tôi đã không hoàn toàn hiểu cơ học theo KotH này, nhưng tôi cho rằng nếu đối thủ không quốc tịch, tôi chỉ cần phá vỡ chúng trong khi tôi đào thoát.

function a(t){try{t(wrap(_=>'D'));throw 1}catch(e){return 'D'}}

Kết quả tourney đầu tiên của anh ấy (tôi không buồn sử dụng tất cả các bot, xin lỗi)

boom                     54
tiktaalik               180
archaeopteryx           161
cooperate               210
commonSense             210
history                 248
onlyTrustYourself       265 <-- 2nd
punishInspectors        230
yourself_no_this        220
defect                  280 <-- 1st
nice                    185
complexity              216
WWBDB                   210
checkStatefulSelfCoop   258
a                       260 <-- Me, 3rd

Anh ấy không làm việc tồi tệ như tôi nghĩ, vị trí thứ 3 (trong số đó) lần đầu tiên thử.
Lần thử thứ hai, anhận được 260 lần nữa, vị trí thứ 3 một lần nữa, sau onlyTrustYourselfdefectmột lần nữa. Cuối cùng, nó có thể phù hợp :)

PS: Tôi không giỏi chơi golf nên nó thích đùa hơn bất cứ điều gì. Ở đây tôi chỉ rút ngắn tên biến, tên func và loại bỏ càng nhiều khoảng trắng càng tốt.


0

Nghiệp

function karma(them) {
    try {
        var c = them(wrap(_ => 'C'));
    } catch {
        var c = 'D';
    }
    if (c == 'C') {
        return 'C';
    } else {
        return 'D';
    }
}

Nếu đối thủ sẽ hợp tác với chúng tôi, thì chúng tôi sẽ hợp tác. Nếu họ cố gắng đào thoát khi chúng tôi hợp tác, chúng tôi cũng sẽ đào thoát.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.