WoW用のシンプルなボットの作成、プログラミングルート(続き)

これは、World of Warcraftゲーム用の単純なボットの作成に関する記事の2番目の部分です。 最初の部分はここにあります 。 今日は

  1. AutoItで Recorderのキーと座標を記述する
  2. ボットに対するPlayerの指示を書く
  3. 数学2D 、コサイン定理なしでデカルト座標系をナビゲートする方法
  4. センサーが不十分なロボット制御
  5. ボットへの対策






レコーダー



私たちのタスク:ピクセルの色の読み取り、キーストロークの決定、一時停止機能を備えたバックグラウンド作業、アプリケーションへのクリックの送信。 ここでは、AutoItが最適です。 Cで同じことを書くには ハンドル、デバイス、フック、Windowsイベントに悩まされます...さらに、これらのアクションのそれぞれについて、ヘルプを読み、方法を見つけ、構造、タイプ、Cookieを決定する必要があります。



スクリプトの編集とクイック起動には、 SciTE-Liteを使用しました。これには、強調表示、CodeFolding、オートコンプリート、Intellisense、SyntaxCheckが含まれます。 組み込みの言語ヘルプは無料です。 標準チップ。



ホットキー


デスクトップで動作し、 それを制御できる各スクリプトでは、いくつかのホットキーハンドラを使用することをお勧めします



$paused = false HotKeySet("{F11}", "Pause") HotKeySet("{F10}", "Kill") Func Pause() $Paused = NOT $Paused While $Paused Sleep(100) WEnd EndFunc Func Kill() FileClose($hfile) Exit EndFunc
      
      





そうしないと、システムを制御できずにオブザーバー状態に陥る危険があります。 審判の日



ハンドラーをF12やその他のボタンに掛けることはできません。 しばらくの間、なぜ呼び出されなかったのか理解できませんでした。



座標を取得する


アドオンでは、ピクセルの色成分に浮動小数点数を入れますが、それらはバイト全体の形で送られてくることを思い出してください。



 #include <Color.au3> Opt("PixelCoordMode", 2) ;          Opt("MouseCoordMode", 2) ;          $WinName = "World of Warcraft" $hwnd = WinGetHandle($WinName) Func GetPitch() $pixel2 = _ColorGetRGB(PixelGetColor(10, 0, $hwnd)); Return ($pixel2[2]/255.0-0.5)*4 EndFunc Func GetPos() $pixel1 = _ColorGetRGB(PixelGetColor(0, 0, $hwnd)); $pixel2 = _ColorGetRGB(PixelGetColor(10, 0, $hwnd)); $result[3] = [ ($pixel1[0]+$pixel1[1]/255.0)/255*100, ($pixel2[0]+$pixel2[1]/255.0)/255*100, $pixel1[2]*7.0/255 ] return $result EndFunc
      
      





データを読み取った後、それらを使用して逆変換を実行します。 関数は配列を返し、配列はプログラマーにとって完全に透過的な変数に書き込まれます。



キーロギング


AutoItの作者は、マルウェアを作成するためにサイバー犯罪者がこのようなシンプルで強力な言語を使用することを望んでいないことをどこかで読みました。 したがって、彼はすべてのキーのキーストロークハンドラーを一度に作成する機能を削除し、少なくともキーロガーがリベットしないようにしました。



なんて言えますか。 AutoItはマルウェアの作成に非常に積極的に使用されており、次のように必要なキーを押す傍受を行います。



 local $keys = StringSplit("` [ ] 1 2 3 4 5 6 7 8 9 0 !1 !2 !3 !4 !5 !6 !7 !8 !9 !0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +f {SPACE} {TAB} {ESC} {PAUSE} {DELETE} {BACKSPACE}", " ", 2) for $i = 0 to UBound($keys)-1 HotKeySet($keys[$i], "OnHotKey") Next Func OnHotKey() ;ToolTip(@HotKeyPressed) HotKeySet(@HotKeyPressed) Send(@HotKeyPressed) HotKeySet(@HotKeyPressed, "OnHotKey") Switch @HotKeyPressed Case "[" FileWriteLine($hfile, "mouse left " & MouseGetPos(0) & " " & MouseGetPos(1)) Case "]" FileWriteLine($hfile, "mouse right " & MouseGetPos(0) & " " & MouseGetPos(1)) Case "{PAUSE}" FileWriteLine($hfile, "pause 1000") Case "{BACKSPACE}" FileWriteLine($hfile, StringFormat("pitch %.2f", GetPitch())) Case Else FileWriteLine($hfile, "key " & @HotKeyPressed) EndSwitch EndFunc
      
      





したがって、ファイルに保存するためにキーに名前を付ける独自のシステムを考案する必要はありません。AutoITで採用されているものを使用してください



他の何かをインターセプトする必要がある場合(そしてゲーム中に押すものと使用するスペルを事前に知っている場合)、それらを最初に長いリストに追加します。



キーストロークをインターセプトした後、それをアプリケーションにさらに送信する必要があります。そのため、ハンドラーを一時的に削除します



 HotKeySet(@HotKeyPressed) Send(@HotKeyPressed) HotKeySet(@HotKeyPressed, "OnHotKey")
      
      





このアプローチはヘルプで推奨されていますが、実際には、 Altなどとの組み合わせをクリックすると、明らかにバグが多くなります。 私は理解していませんでしたが、そのような組み合わせの使用を避けました。



マウスロギング


AutoItには、マウスクリックをインターセプトするための通常の方法がありません。 使用例が記載されたサードパーティのモジュールがあります 。 または、 SetWindowsHookEx(WH_MOUSE_LL)をハングさせることができます。 AutoItで WinAPIコールバック関数を使用する便利な例 こちらです。 ただし、次の2つの理由でこのアプローチを使用しませんでした。

  1. キャラクターの動きは、ログに記録する必要のない多数のマウスクリックに関連付けられています。 さらに、ランダムなクリックが可能です。 ハエをカツレツから分離するためのロジックを記述する必要があります。
  2. フックを使用すると、「特別なサービス」の注目を集める可能性が高くなります。 これについては、「ボットに対抗する」セクションで詳しく説明します。


したがって、既にお気付きのように、「 [ 」および「 ] 」ボタンを使用し、必要に応じてそれらを押しただけです。 主なことは、それらをクリックすることを忘れないことです。



座標記録


もちろん、 レコーダーはバックグラウンドでキャラクターの動きを記録する必要があります



 $hfile = FileOpen("output.txt", 1) $prev = "" While true WinWaitActive($hwnd) local $pos = GetPos() $command = StringFormat("move %.3f %.3f %.3f", $pos[0], $pos[1], $pos[2]); if $pos[0] + $pos[1] > 0 And $command <> $prev Then FileWriteLine($hfile, $command) EndIf $prev = $command Sleep(100) WEnd
      
      





なぜ頻繁に(1秒に10回)座標を記録するのかと尋ねることができますか? 事実、私たちのルートには障害物があります:箱、角、戸口、街灯柱、 熊手です。 そして、キャラクターは単に彼らに「磁化」します。 どこかを通り過ぎて、彼が立ち往生した場合、彼は間違いなくそれを行います。 長い間直線で走っていたとしても、動きの方位角は完璧に設定されていなかったので、額に壁を当てて長時間走っていた可能性があります。

完全なレコーダーソースコード
 #include <Color.au3> Global $WinName = "World of Warcraft" Opt("PixelCoordMode", 2) ;          Opt("MouseCoordMode", 2) ;          $paused = false HotKeySet("{F11}", "Pause") HotKeySet("{F10}", "Kill") local $keys = StringSplit("` [ ] 1 2 3 4 5 6 7 8 9 0 !1 !2 !3 !4 !5 !6 !7 !8 !9 !0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +f {SPACE} {TAB} {ESC} {PAUSE} {DELETE} {BACKSPACE}", " ", 2) for $i = 0 to UBound($keys)-1 HotKeySet($keys[$i], "OnHotKey") Next $hwnd = WinGetHandle($WinName) $hfile = FileOpen("output.txt", 1) $prev = "" While true WinWaitActive($hwnd) local $pos = GetPos() $command = StringFormat("move %.3f %.3f %.3f", $pos[0], $pos[1], $pos[2]); if $pos[0] + $pos[1] > 0 And $command <> $prev Then FileWriteLine($hfile, $command) EndIf $prev = $command Sleep(100) WEnd Func Pause() $Paused = NOT $Paused While $Paused Sleep(100) WEnd EndFunc Func Kill() FileClose($hfile) Exit EndFunc Func GetPitch() $pixel2 = _ColorGetRGB(PixelGetColor(10, 0, $hwnd)); Return ($pixel2[2]/255.0-0.5)*4 EndFunc Func GetPos() $pixel1 = _ColorGetRGB(PixelGetColor(0, 0, $hwnd)); $pixel2 = _ColorGetRGB(PixelGetColor(10, 0, $hwnd)); local $result[3] = [ ($pixel1[0]+$pixel1[1]/255.0)/255*100, ($pixel2[0]+$pixel2[1]/255.0)/255*100, $pixel1[2]*7.0/255 ] return $result EndFunc Func OnHotKey() ;ToolTip(@HotKeyPressed) HotKeySet(@HotKeyPressed) Send(@HotKeyPressed) HotKeySet(@HotKeyPressed, "OnHotKey") Switch @HotKeyPressed Case "[" FileWriteLine($hfile, "mouse left " & MouseGetPos(0) & " " & MouseGetPos(1)) Case "]" FileWriteLine($hfile, "mouse right " & MouseGetPos(0) & " " & MouseGetPos(1)) Case "{PAUSE}" FileWriteLine($hfile, "pause 1000") Case "{BACKSPACE}" FileWriteLine($hfile, StringFormat("pitch %.2f", GetPitch())) Case Else FileWriteLine($hfile, "key " & @HotKeyPressed) EndSwitch EndFunc
      
      









Au3record


AutoIt3 \ Extras \ Au3Record \ Au3Record.exeはSciTE4AutoIt3に付属しており、デスクトップでアクションを記録し、 AutoItスクリプトとしてすぐに作成できます。 考えずに一連のマシンアクションを何度も実行する必要がある場合(たとえば、多数のコンピューターにソフトウェアまたはパッチをインストールする場合)、このツールをご覧ください。



プレイヤー



前の章で説明したRecorderの作業の結果は、次の形式のコマンドセットであることに注意してください。



 マウス左1892 1021
一時停止10000
ピッチ-0.89
マウス右942 498
一時停止10000
移動83.72 50.03 0.604
キー `
一時停止1000
キー{SPACE}
ピッチ-0.1
移動83.777 50.207 1.235
移動83.777 50.207 2.114
移動83.777 50.207 2.827
移動83.777 50.207 2.855
移動83.754 50.327 2.855 


一見、それらを「失う」ことは難しいことではないようですが、このプロセスを詳しく見てみましょう。



パンとチルト


ボタンを押して回転および傾斜させると、約30度の精度が得られますが、これはタスクでは受け入れられません。 したがって、このために2番目の機会を使用します:右ボタンを押したままマウスを移動します。 アルゴリズムは次のとおりです。

  1. マウスの右ボタンを押したままにする
  2. ゲーム自体は、画面の中央にカーソルを置き、そこに保持します。 これにより、ユーザーは、画面の端にカーソルを置いて最後に休まないようになります。
  3. カーソルを特定のピクセル数だけ左右に移動します
  4. キャラクターの方向は左または右にシフトします。 さらに、カーソルを速く動かすほど、キャラクターは速く回転します


現在と必須の2つの角度がある場合、どの方向がより収益性が高いかを判断するのはどのように簡単ですか?



正の場合は、角度の違いを右に見ることができます。 ただし、現在の角度は30度、必要な角度は330度です。 違いはマイナスですが、私たちは気にしません。 また、角度は負の値にすることができます。 これらすべての条件を書き出す必要がないように、単に角度の差のサインを使用して、そのサインのみを調べます。



$ wantおよび$ current変数には(x、y、azimuth)が含まれます



 Func Turn($want) while true $current = GetPos() $sin = sin($current[2] - $want[2]) ;ToolTip(StringFormat("(%.2f,%.2f,%.2f) to (%.2f,%.2f,%.2f)", $current[0], $current[1], $sin, $want[0], $want[1], $want[2])) if abs($sin) < 0.05 then return MouseMove(MouseGetPos(0)+50*$sin, MouseGetPos(1), 1) wend EndFunc
      
      





サインにより、回転速度を調整することもできます。 角度が小さいほど、カーソルはより正確に動き、より正確に回転します。 逆もまた然りで、大きな角度ではより速く回転したい。



水平線への傾きを変更する機能は完全に類似しており、カーソルを垂直に移動する必要があるだけです。



上記のコード例では、不正なボットの動作につながる可能性のある論理エラーがあります。 私は好奇心の強い読者にそれを自分で見つけるように勧めます。



ムーブメント


次の要件がトラフィックに適用されます

  1. 位置決め精度が低い。 あなたが望む場所に正確に到達することはできません
  2. 方向転換せずに移動する必要があります。 利用可能な動きのうち、前方への走行、後方への後退、および横行のみがあります(旋回せずに横向きの動き)
  3. 動きは、停止またはけいれんなしで連続的でなければなりません
  4. できるだけ少ないリターンと方向の変更。 キャラクターが少し走ってから後退し、再び走った場合など、モニターを見るのは不快です




前方か後方か?


数学が好きではない、または高校を長い間卒業していない場合は、理解を損なうことなくこのセクションをスキップできます。 しかし、ここでは特に複雑なことはありません。 キャラクターを(a x 、a y )の上に立って、角度を見てみましょう そして、彼は(b x 、b yに入る必要があります、彼は前方または後方に走りますか? まず、タスクをわずかに言い換えます。キャラクターを(0、0)に立って、 、しかし(d x 、d y )で彼を必要とします。



問題を真正面から解決する場合、ベクトル間の角度の余弦を計算する必要があります。 正の場合、角度は鋭く、前方に進みます。 負の場合-愚か、あなたは後退する必要があります。 コサインはコサイン定理によって計算できます



ただし、このためには、各ベクトルの長さを計算し、根を抽出する必要があり、非常に面倒です。



スカラー積公式もあります



ご存知のように、デカルト座標系では次の式で計算できます



したがって、スカラー積を計算してその符号を調べた後、前方に実行するか後方に実行するかを決定できます。 そして、私たちの場合、次の式で計算します 。 さらに、この同じスカラー積は、 幾何学的定義 (あるベクトルの別のベクトルへの投影に2番目のベクトルの長さを掛けたもの)に応じて正確にどれだけ前進または後退する必要があるかを示しています。

画像



左か右か


同様に、ビューベクトル間の角度のサイン そしてターゲットへの方向(d x 、d yはどちらの側に行くかを決定します。 正の場合、目標は右手にあり、その逆も同様です。 ここで、 ベクトル積は、より正確には、式によってデカルト座標で計算された擬似スカラー積に役立ちます。



繰り返しますが、この数値の大きさによって、必要なサイドステップの数が決まります。



実装


推論をプログラムします



 Func ScalarMult($a, $b, $x, $y) return $a*$x + $b*$y EndFunc Func VectorMult($a, $b, $x, $y) return $a*$y - $b*$x EndFunc Func GetDirection($x, $y, $wx, $wy, $angle) $dx = $x - $wx $dy = $y - $wy local $result[2] = [ ScalarMult(-sin($angle), -cos($angle), $dx, $dy), VectorMult(-sin($angle), -cos($angle), $dx, $dy) ] Return $result EndFunc
      
      





プログラム内でサインとコサインが入れ替わり、反対の符号でとられていることを混同しないでください。 WoWでは、方位角は北から反時計回りにカウントされます。 これらの詳細は、実際のプログラムで単純に「試す」ことができます。 そして、それが逆になった場合、標識で遊んでください。



GetDirection()関数は、次の2つの値の配列を返します:どれだけ前進/後退するか、どれだけ横に移動するか。



これはひねりです!


一部の読者は次のように叫ぶかもしれません。「なぜ、これらの正弦-余弦による乗算は、座標系の通常の回転にすぎない、



説明した

画像

なぜ私たちの頭をだますか。」



確かに、しかし、マトリックスがそのようなものである理由を説明することは私にとってより難しいでしょう。



やめて


これで実行ボタンを押す準備ができました



 Func Move($want) while true StartMoving() local $pos = GetPos() local $dir = GetDirection($pos[0], $pos[1], $want[0], $want[1], $pos[2]) ;ToolTip(StringFormat("(%.2f,%.2f,%.2f) to (%.2f,%.2f, %.2f): (%.2f,%.2f)", $pos[0], $pos[1], $pos[2], $want[0], $want[1], $want[2], $dir[0], $dir[1])) if abs($dir[0]) < 0.1 And abs($dir[1]) < 0.1 then ExitLoop if abs($dir[0]) >= abs($dir[1]) Then Send("{a up}{d up}") if $dir[0] <=0 Then Send("{w down}{s up}") ; forward Else Send("{s down}{w up}") ; backward EndIf Else Send("{s up}") if $dir[1] < 0 Then Send("{d down}{a up}") ; right Else Send("{a down}{d up}") ; left EndIf EndIf wend Send("{s up}{a up}{d up}") EndFunc
      
      





私たちは最も遠くに行く方向に進んでおり、私たちがほとんどそこにいるときにパスを終了することに注意してください。 これにより、キャラクターがちらつきません。 転送ボタンは、宛先に到達してもリリースされません。 したがって、必要な角度で比較的迅速に旋回する必要があります。



コマンドファイルの再生を担当するコードは、興味深いものではありません。必要に応じて、自分で慣れることができます。

プレーヤーの完全なソースコード
 #include <Color.au3> Global $WinName = "World of Warcraft" Opt("PixelCoordMode", 2) ;          Opt("MouseCoordMode", 2) ;          $paused = false $moving = false HotKeySet("{F11}", "Pause") HotKeySet("{F10}", "Kill") ;WinActivate($WinName) $hwnd = WinGetHandle($WinName) WinWaitActive($hwnd) PlayFile("outdoor.txt", 0) PlayFile("indoor.txt", 0) PlayFile("outdoor.txt", 0) PlayFile("indoor.txt", 0) PlayFile("outdoor.txt", 0) PlayFile("indoor.txt", 0) PlayFile("outdoor.txt", 0) PlayFile("indoor.txt", 0) PlayFile("outdoor.txt", 0) PlayFile("indoor.txt", 0) Func PlayLine($line) local $command = StringSplit($line, " ", 2) ;ToolTip(StringFormat("%s %s %s", $command[0], $command[1], $command[2])) Switch $command[0] Case "move" local $want[3] = [ number($command[1]), number($command[2]), number($command[3]) ] Move($want) Turn($want) Case "pause" StopMoving() Sleep($command[1]) Case "key" If $command[1] = "{SPACE}" Then Send("{SPACE down}") Sleep(300) Send("{SPACE up}") Else StopMoving() if UBound($command) > 2 Then Send($command[1] & " " & $command[2]) Else Send($command[1]) EndIf Sleep(1500) EndIf Case "mouse" StopMoving() MouseClick($command[1], $command[2], $command[3]) Sleep(500) Case "pitch" SetPitch($command[1]) EndSwitch EndFunc Func PlayFile($filename, $skip = 0) $hfile = FileOpen($filename, 0) For $i = 1 to $skip $line = FileReadLine($hfile) Next while True $line = FileReadLine($hfile) if @error = -1 Then ExitLoop PlayLine($line) wend FileClose($hfile) StopMoving() EndFunc Func Sign($x) if ($x < 0) then return -1 else return 1 EndIf EndFunc Func ScalarMult($a, $b, $x, $y) return $a*$x + $b*$y EndFunc Func VectorMult($a, $b, $x, $y) return $a*$y - $b*$x EndFunc Func StartMoving() if $moving then return $moving = true; WinWaitActive($hwnd) MouseMove(@DesktopWidth/2, @DesktopHeight/2, 0) MouseDown("right") Sleep(300) EndFunc Func StopMoving() $moving = false Send("{w up}{s up}{a up}{d up}") MouseUp("right") Sleep(300) EndFunc Func GetPitch() StartMoving() $pixel2 = _ColorGetRGB(PixelGetColor(10, 0, $hwnd)); Return ($pixel2[2]/255.0-0.5)*4 EndFunc Func GetPos() StartMoving() $pixel1 = _ColorGetRGB(PixelGetColor(0, 0, $hwnd)); $pixel2 = _ColorGetRGB(PixelGetColor(10, 0, $hwnd)); local $result[3] = [ ($pixel1[0]+$pixel1[1]/255.0)/255*100, ($pixel2[0]+$pixel2[1]/255.0)/255*100, $pixel1[2]*7.0/255 ] return $result EndFunc Func GetDirection($x, $y, $wx, $wy, $angle) $dx = $x - $wx $dy = $y - $wy local $result[2] = [ ScalarMult(-sin($angle), -cos($angle), $dx, $dy), VectorMult(-sin($angle), -cos($angle), $dx, $dy) ] Return $result EndFunc Func Move($want) while true local $pos = GetPos() local $dir = GetDirection($pos[0], $pos[1], $want[0], $want[1], $pos[2]) ToolTip(StringFormat("(%.2f,%.2f,%.2f) to (%.2f,%.2f, %.2f): (%.2f,%.2f)", $pos[0], $pos[1], $pos[2], $want[0], $want[1], $want[2], $dir[0], $dir[1])) if abs($dir[0]) < 0.1 And abs($dir[1]) < 0.1 then ExitLoop if abs($dir[0]) >= abs($dir[1]) Then Send("{a up}{d up}") if $dir[0] <=0 Then Send("{w down}{s up}") ; forward Else Send("{s down}{w up}") ; backward EndIf Else Send("{s up}") if $dir[1] < 0 Then Send("{d down}{a up}") ; right Else Send("{a down}{d up}") ; left EndIf EndIf wend Send("{s up}{a up}{d up}") EndFunc Func Turn($want) while true local $current = GetPos() $sin = sin($current[2] - $want[2]) ;ToolTip(StringFormat("(%.2f,%.2f,%.2f) to (%.2f,%.2f,%.2f)", $current[0], $current[1], $sin, $want[0], $want[1], $want[2])) if abs($sin) < 0.05 then return MouseMove(MouseGetPos(0)+50*$sin, MouseGetPos(1), 1) wend EndFunc Func SetPitch($want) while true $current = GetPitch() $sin = sin($current - $want) ;ToolTip(StringFormat("pitch %.2f to %.2f: %.2f", $current, $want, $sin)) if abs($sin) < 0.05 then return MouseMove(MouseGetPos(0), MouseGetPos(1)+50*$sin, 1) wend EndFunc Func Pause() $paused = not $paused if $paused then StopMoving() While $Paused Sleep(1000) WEnd EndFunc Func Kill() StopMoving() Exit EndFunc
      
      







管理(ro)ボット





それがすべてのようです。 ルートに沿って実行し、座標、キーストローク、クリックを書き留め、再生を有効にします。 しかし、そこにありました。 これが最も難しい部分の始まりです。



Mobはダンジョンに住んでいます。Mobはキャラクターの生活に脅威を与えませんが、気絶させ、「沈黙」を投げ、殺したいときに脇に逃げ、思いついた瞬間に容赦なく駆けつけます。完全に異なる暴徒をターゲットに持ち込みます。 ターゲットが背中の後ろを走る場合もあれば、一撃で死ぬ場合もありますが、3回生きるはずです。 一般に、それらの混oticとした振る舞いは私たちのルートにランダム性の顕著な要素を導入し、その結果、キャラクターは最初に誰かを殺すことができなかったという理由だけで、ルートの最後のロックされたドアにいる可能性があります。



はい、ゲーム内のマクロを作成して目的のMobをターゲットにし、それによっていくつかの問題を取り除くことができましたが、ボットを可能な限り汎用的にしたかったのです。



格子ドア。 開くにはそれらをクリックする必要があります。 そして、それらは格子であるため、誤って穴に優しくクリックすることができます。 そしてキャラクターは、さらに走ろうとして額をドアにぶつけます。



したがって、ルートを記録したら、ノートブックで開いてデバッグします。 あなたはキャラクターを観察し、問題や起こりうる問題の場合、ルートに「松葉杖を運転」します:忠実度のために追加の呪文を挿入し(突然暴徒が生き残ります)、歩きたいという願望に関係なく、暴徒が正確に見えて到達するポイントに到達します。 あなたはルートを変えるので、あなたは確かにこの不運な箱につまずかないことはありません。 10レース後、そこで突然すべてのクモを殺した方が、後の10分の1で突然の呪文でリベンジできるようになるよりも良いという結論に達しました。 しかし、キャラクターがすでに自分で走っているときは、自分の足で走るのではなく、ただ見たいだけです。



ローバーを起動したり、ロボット掃除機をプログラムしたり、真っ暗闇の中でアパートを歩き回ったり、ロボットにサッカーを教えることの気持ちを実感しました。 余裕を持ってすべてを確実に行う必要があります。 火星では、穴がいたるところにあり、突出した岩や洞窟もあります。 アパートでは、どこでもワイヤーとスリッパがロボット掃除機に直面します。また、遊びたい猫もいます。 真っ暗闇では、角、椅子の足、さらには床に落ちたナイフもあります。 タッチするだけ!



私は認めます、私は最後の部分で述べられた最小限のプログラムだけを実行しました。 ボットはまだ1%の確率でタスクを完了しない場合があります。 ですから、あなたは夜に彼をコントロールすることなく離れることができません、彼は立ち往生します。



ボットに対抗する





MMORPGゲームから遠く離れた人々は、「なぜボットに煩わされるのですか? 結局のところ、自動化はどこでも歓迎されています。 全員が同じを支払う場合、機会は等しくなければなりません。 それ以外の場合、侵害された部分は気分を害し、再生を停止します。 たとえば、ゲームでマクロを使用できる場合、プログラマーはそれらを理解するべきではありません。 したがって、ゲーム開発者は、ライセンス契約とモニターのレベルでの自動化の使用を禁止しています。



私はよくBlizzard (これはWoWの開発者)の監視が不十分であり、ボットはどこにでもあるという感嘆に会いました。 まず、私はそうは思わない。彼らのシェアは誇張されていると思う。 そして次に、開発者の兵器庫にあるものについて議論しましょう。 ボットを認識するだけでなく、裏付けとなる事実をどのように持つか。 実際、疑惑に基づいて、プレーヤーを禁止することは無礼です。



, - ( ) . , «» , : , , ( ), , — . , , , , «».



Blizzard Warden . :

  1. - , -
  2. , ,


, - Wine . Blizzard .



, , :

  1. , ,
  2. -


ban-wave .

AutoIt , , «» . Blizzard , , .



おわりに



:

  1. ,


, , . 20 ( 5 ). , , . . , , , - .



, , . がんばって。




All Articles