Forked from: ProjectNya's Reversi diff:2916 forked from: Reversi AIを強化しました。(中級者向け) CPUから手を変えるような工夫をいれました。 hamlet forked:0favorite:3lines:4186license : MIT License modified : 2012-05-16 23:25:58 Embed Tweet /** * Copyright hamlet ( http://wonderfl.net/user/hamlet ) * MIT License ( http://www.opensource.org/licenses/mit-license.php ) * Downloaded from: http://wonderfl.net/c/4GIx */ // forked from ProjectNya's Reversi //////////////////////////////////////////////////////////////////////////////// // リバーシ Plus for AS3.0 // ※ProjectNya's ReversiのAI強化版 // // special thanks to ProjectNya // リバーシ for AS3.0 (1) // http://www.project-nya.jp/modules/weblog/details.php?blog_id=1039 // // special thanks to QURAGE // http://qurage.net/labo/fl1/data/reversi.html //////////////////////////////////////////////////////////////////////////////// package { import flash.display.Sprite; import flash.display.Shape; import flash.geom.Matrix; import flash.display.GradientType; import flash.text.TextField; import flash.text.TextFieldType; import flash.text.AntiAliasType; import flash.text.TextFormat; import flash.text.TextFormatAlign; import flash.filters.DropShadowFilter; [SWF(backgroundColor="#FFFFFF", width="465", height="465", frameRate="30")] public class Main extends Sprite { private static var color1:uint = 0x3F68AB; private static var color2:uint = 0x77B2EE; private static var tColor:uint = 0xFFFFFF; private static var sColor:uint = 0x00000; private static var fontType:String = "_ゴシック"; public function Main() { //Wonderfl.capture_delay(10); init(); } private function init():void { draw(465, 465); var game:Game = new Game(); addChild(game); game.x = 42; game.y = 12; } private function draw(w:uint, h:uint):void { var colors:Array = [color1, color2]; var alphas:Array = [1, 1]; var ratios:Array = [0, 255]; var matrix:Matrix = new Matrix(); matrix.createGradientBox(w, h, 1.25*Math.PI, 0, 0); graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix); graphics.drawRect(0, 0, w, h); graphics.endFill(); var tf:TextFormat = new TextFormat(); tf.font = fontType; tf.size = 32; tf.align = TextFormatAlign.LEFT; var title:TextField = new TextField(); addChild(title); title.x = 20; title.y = 2; title.width = 200; title.height = 40; title.type = TextFieldType.DYNAMIC; title.selectable = false; //title.embedFonts = true; //title.antiAliasType = AntiAliasType.ADVANCED; title.defaultTextFormat = tf; title.textColor = tColor; //タイトル修正 (by Hamlet) title.text = "Reversi +"; var shade:DropShadowFilter = new DropShadowFilter(1, 90, sColor, 0.4, 4, 4, 2, 2, false, false); title.filters = [shade]; } } } ////////////////////////////////////////////////// // リバーシ全体を管理するクラス ////////////////////////////////////////////////// import adobe.utils.CustomActions; import flash.display.Sprite; class Game extends Sprite { private static var pieces:uint = 8; private var board:Board; private var score:Score; private var help:Help; public static const INIT:String = "init"; public static const PLAY:String = "play"; public static const PUT:String = "put"; public static const FINISH:String = "finish"; public static const NO_POINT:String = "noPoint"; public static const READY:String = "ready"; public static const RESET:String = "reset"; public static const NO_HELP:String = ""; public static const MOVE:String = "move"; public static const SELECT:String = "select"; public static const PUT_COMPLETE:String = "putComplete"; public static const TURN_COMPLETE:String = "turnComplete"; public function Game() { init(); } private function init():void { board = new Board(); score = new Score(); help = new Help(); addChild(board); board.x = 22; board.y = 88; addChild(score); addChild(help); help.x = 194; help.y = 245; board.init(score, help); } } ////////////////////////////////////////////////// // 盤面を管理するクラス ////////////////////////////////////////////////// import flash.display.Sprite; import flash.display.Shape; import flash.events.Event; import flash.utils.Timer; import flash.events.TimerEvent; import flash.net.navigateToURL; import flash.net.URLRequest; import flash.events.MouseEvent; import flash.utils.escapeMultiByte; class Board extends Sprite { private var mode:String; private var player:uint = 0; private var map:Map; private var score:Score; private var help:Help; private var manager:Manager; private var cursor:Cursor; private static var pieces:uint = 8; private static var bColor:uint = 0x336600; private var pointList:Array; private var pieceList:Array; private static var pid:uint = 0; private var completed:uint = 0; private static var initTime:uint = 500; private static var startTime:uint = 1000; private static var cpuTime:uint = 500; private static var finishTime:uint = 1000; private static var resetTime:uint = 500; private var cpu:Object; private var turns:uint; private var passed1:Boolean = false; private var passed2:Boolean = false; //サウンド private var seready:SoundEffect; private var seput:SoundEffect; private var seturn:SoundEffect; private var sefanfare:SoundEffect; private var seclaps:SoundEffect; private var sefailure:SoundEffect; private var source1:String = "http://www.project-nya.jp/images/flash/reversi/ready.mp3"; private var source2:String = "http://www.project-nya.jp/images/flash/reversi/put.mp3"; private var source3:String = "http://www.project-nya.jp/images/flash/reversi/turn.mp3"; private var source4:String = "http://www.project-nya.jp/images/flash/reversi/fanfare.mp3"; private var source5:String = "http://www.project-nya.jp/images/flash/reversi/claps.mp3"; private var source6:String = "http://www.project-nya.jp/images/flash/reversi/failure.mp3"; //twitter private var twitterBtn:Btn; private static var twitterPath:String = "http://twitter.com/home/?status="; private var msgs:Array = new Array(); private var result:String; private static var tag:String = " http://wonderfl.net/c/vDfO" public function Board() { draw(); seready = new SoundEffect(); seput = new SoundEffect(); seturn = new SoundEffect(); sefanfare = new SoundEffect(); seclaps = new SoundEffect(); sefailure = new SoundEffect(); } public function init(s:Score, h:Help):void { score = s; help = h; seready.load(source1, "ready"); seput.load(source2, "put"); seturn.load(source3, "turn"); sefanfare.load(source4, "fanfare"); seclaps.load(source5, "claps"); sefailure.load(source6, "failure"); reset(null); } //カーソル位置にコマを配置する(キー設定) private function initialize():void { manager = new Manager(this); addChild(manager); manager.addEventListener(Game.READY, readySelect, false, 0, true); manager.addEventListener(Game.MOVE, moveCursor, false, 0, true); manager.addEventListener(Game.SELECT, selectCursor, false, 0, true); manager.addEventListener(Game.RESET, resetSelect, false, 0, true); manager.enable = false; cpu = new Object(); } private function reset(evt:TimerEvent):void { if (evt) evt.target.removeEventListener(TimerEvent.TIMER_COMPLETE, reset); initialize(); map = new Map(); score.init(); mode = Game.INIT; score.showMessage(mode); help.show("ready?"); score.resetTime(); seready.play("ready", 1); manager.help = Game.READY; if (pieceList) clearPieces(); pieceList = new Array(); } private function readySelect(evt:Event):void { manager.help = Game.NO_HELP; var timer:Timer = new Timer(initTime, 1); timer.addEventListener(TimerEvent.TIMER_COMPLETE, start, false, 0, true); timer.start(); help.hide(); } private function start(evt:TimerEvent):void { evt.target.removeEventListener(TimerEvent.TIMER_COMPLETE, start); score.startTime(); //オセロの公式ルールに従い、黒石白石の初期配置を修正。(by Hamlet) putPiece(2, 3, 3); //putPiece(1, 3, 3); putPiece(1, 3, 4); //putPiece(2, 3, 4); putPiece(2, 4, 4); //putPiece(1, 4, 4); putPiece(1, 4, 3); //putPiece(2, 4, 3); } //盤面にコマを配置する private function put(px:uint, py:uint):void { if (map.getPoint(px, py)) { if (map.getHint(px, py)) { switch (player) { case 1 : putPiece(player, px, py); break; case 2 : cpuPiece(player, px, py); var timer:Timer = new Timer(cpuTime, 1); timer.addEventListener(TimerEvent.TIMER_COMPLETE, cpuPut, false, 0, true); timer.start(); break; } } else { score.showMessage(Game.NO_POINT); } } else { score.showMessage(Game.NO_POINT); } } //盤面にコマを配置する(配置可能なマスに) private function putPiece(p:uint, px:uint, py:uint):void { var point:Point = pointList[px+py*pieces]; var xPos:uint = point.x; var yPos:uint = point.y; var id:uint = px+py*pieces; var piece:Piece = new Piece(); addChild(piece); piece.id = id; piece.px = px; piece.py = py; piece.x = xPos; piece.y = yPos; pieceList[id] = piece; piece.addEventListener(Game.PUT_COMPLETE, putComplete, false, 0, true); piece.addEventListener(Game.TURN_COMPLETE, turnComplete, false, 0, true); piece.put(p); score.put(p); map.put(p, px, py); seput.play("put", 1); hideHint(); pid ++; manager.enable = false; } private function cpuPiece(p:uint, px:uint, py:uint):void { cpu = {p: p, px: px, py: py}; } private function cpuPut(evt:TimerEvent):void { evt.target.removeEventListener(TimerEvent.TIMER_COMPLETE, cpuPut); putPiece(cpu.p, cpu.px, cpu.py); } private function clearPieces():void { for (var px:uint = 0; px < pieces; px++) { for (var py:uint = 0; py < pieces; py++) { var piece:Piece = pieceList[px+py*pieces]; if (piece) removeChild(piece); piece = null; } } pid = 0; } //コマ配置後の処理 private function putComplete(evt:Event):void { switch (mode) { case Game.INIT : completed ++; if (completed == 4) { completed = 0; mode = Game.PLAY; score.showMessage(mode); player = 2; var timer:Timer = new Timer(startTime, 1); timer.addEventListener(TimerEvent.TIMER_COMPLETE, prepare, false, 0, true); timer.start(); } break; case Game.PLAY : turn(evt.target.px, evt.target.py); break; } } //反転するコマ情報を取得する private function turn(px:uint, py:uint):void { var list:Array = map.getTurnList(player, px, py); turns = list.length; if (turns > 0) { turnPieces(player, list); seturn.play("turn", 1); } } //コマを反転する private function turnPieces(p:uint, list:Array):void { for (var n:uint = 0; n < list.length; n++) { var tx:uint = list[n].x; var ty:uint = list[n].y; var piece:Piece = pieceList[tx+ty*pieces]; piece.turn(); score.turn(p); map.put(p, tx, ty); } } //コマ反転後の処理 private function turnComplete(evt:Event):void { completed ++; if (completed == turns) { completed = 0; if (pid < pieces*pieces) { prepare(null); } else { finish(); } } } //攻守交代 private function prepare(evt:TimerEvent):void { if (evt) evt.target.removeEventListener(TimerEvent.TIMER_COMPLETE, prepare); player = player%2 + 1; switch (player) { case 1 : score.showMessage(Game.PUT, player, passed2); map.getBestPrio(player); if (showHint()) { if (!cursor) { cursor = new Cursor(); addChild(cursor); setCursor(4, 4); manager.setCursor(4, 4); } manager.enable = true; passed1 = false; } else { passed1 = true; } break; case 2 : score.showMessage(Game.PUT, player, passed1); var best:Object = map.getBestPrio(player); if (!isNaN(best.x) && !isNaN(best.y)) { manager.autoCursor(best.x, best.y); passed2 = false; } else { passed2 = true; } break; } if (passed1 && passed2) { finish(); } else if ((player == 1 && passed1) || (player == 2 && passed2)) { prepare(null); } } private function moveCursor(evt:Event):void { setCursor(evt.target.cx, evt.target.cy); } private function selectCursor(evt:Event):void { put(evt.target.cx, evt.target.cy); } //盤面にカーソルを配置する private function setCursor(cx:uint, cy:uint):void { var point:Point = pointList[cx+cy*pieces]; var xPos:uint = point.x; var yPos:uint = point.y; cursor.x = xPos; cursor.y = yPos; } //ヒントを表示する private function showHint():Boolean { var hint:uint = 0; for (var px:uint = 0; px < pieces; px++) { for (var py:uint = 0; py < pieces; py++) { var point:Point = pointList[px+py*pieces]; if (map.getHint(px, py)) { hint ++; point.hint(); } else { point.init(); } } } if (hint > 0) { return true; } else { return false; } } //ヒントを非表示にする private function hideHint():void { for (var px:uint = 0; px < pieces; px++) { for (var py:uint = 0; py < pieces; py++) { var point:Point = pointList[px+py*pieces]; point.init(); } } } //ゲーム終了の処理 private function finish():void { mode = Game.FINISH; score.showMessage(mode); var timer:Timer = new Timer(finishTime, 1); timer.addEventListener(TimerEvent.TIMER_COMPLETE, showHelp, false, 0, true); timer.start(); score.stopTime(); player = 0; passed1 = false; passed2 = false; } private function showHelp(evt:TimerEvent):void { evt.target.removeEventListener(TimerEvent.TIMER_COMPLETE, showHelp); var scr:Array = score.getScore(); var p1:uint = scr[0]; var p2:uint = scr[1]; //twitter result = String(p1) + ":" + String(p2); if (p1 > p2) { help.show("You win!"); sefanfare.play("fanfare", 1); msgs = ["コンピュータに ", " で勝ったよ!"]; } else if (p1 == p2) { help.show("draw"); seclaps.play("claps", 1); msgs = ["コンピュータと ", " の引き分けでした。"]; } else { help.show("You lose"); sefailure.play("failure", 1); msgs = ["コンピュータに ", " で負けました..."]; } removeChild(cursor); cursor = null; manager.help = Game.RESET; } private function resetSelect(evt:Event):void { manager.help = Game.NO_HELP; var timer:Timer = new Timer(resetTime, 1); timer.addEventListener(TimerEvent.TIMER_COMPLETE, reset, false, 0, true); timer.start(); help.hide(); } private function draw():void { graphics.beginFill(bColor); graphics.drawRect(-2, -2, 340, 340); graphics.endFill(); pointList = new Array(); for (var px:uint = 0; px < pieces; px++) { for (var py:uint = 0; py < pieces; py++) { var point:Point = new Point(); addChild(point); var id:uint = px+py*pieces; point.id = id; pointList[id] = point; point.x = 21 + 42*px; point.y = 21 + 42*py; point.init(); } } for (var cx:uint = 0; cx < 2; cx++) { for (var cy:uint = 0; cy < 2; cy++) { var corner:Shape = new Shape(); addChild(corner); corner.graphics.beginFill(bColor); corner.graphics.drawCircle(0, 0, 4); corner.graphics.endFill(); corner.x = 84 + 168*cx; corner.y = 84 + 168*cy; } } //twitter twitterBtn = new Btn(); addChild(twitterBtn); twitterBtn.x = 365; twitterBtn.y = 350; twitterBtn.init({label: "twitter"}); twitterBtn.addEventListener(MouseEvent.CLICK, twitter, false, 0, true); } //twitter対応 private function twitter(evt:MouseEvent):void { var msg:String = ""; switch (mode) { case Game.INIT : msg = "ゲームを開始します。"; break; case Game.PLAY : msg = "ゲーム中です。"; break; case Game.FINISH : msg = msgs[0] + result + msgs[1]; break; } navigateToURL(new URLRequest(twitterPath + escapeMultiByte(msg + tag)), "_blank"); } } ////////////////////////////////////////////////// // 盤面上のコマの位置を管理するクラス ////////////////////////////////////////////////// class Map { private static var pieces:uint = 8; //空マップ private var aMap:Array; //盤面上のコマ配置マップ private var bMap:Array; //優先度マップ private var pMap:Array; //走査マップ private var cMap:Array; //ヒント表示マップ private var hMap:Array; //独自拡張部分。(by Hamlet) private var Ai:AiManager; public function Map() { init(); } private function init():void { aMap = new Array(); aMap.push([0, 0, 0, 0, 0, 0, 0, 0]); aMap.push([0, 0, 0, 0, 0, 0, 0, 0]); aMap.push([0, 0, 0, 0, 0, 0, 0, 0]); aMap.push([0, 0, 0, 0, 0, 0, 0, 0]); aMap.push([0, 0, 0, 0, 0, 0, 0, 0]); aMap.push([0, 0, 0, 0, 0, 0, 0, 0]); aMap.push([0, 0, 0, 0, 0, 0, 0, 0]); aMap.push([0, 0, 0, 0, 0, 0, 0, 0]); bMap = copyMap(aMap); cMap = copyMap(aMap); pMap = new Array(); pMap.push([7, 0, 5, 6, 6, 5, 0, 7]); pMap.push([0, 0, 2, 3, 3, 2, 0, 0]); pMap.push([5, 2, 5, 4, 4, 5, 2, 5]); pMap.push([6, 3, 4, 4 ,4, 4, 3, 6]); pMap.push([6, 3, 4, 4 ,4, 4, 3, 6]); pMap.push([5, 2, 5, 4, 4, 5, 2, 5]); pMap.push([0, 0, 2, 3, 3, 2, 0, 0]); pMap.push([7, 0, 5, 6, 6, 5, 0, 7]); //独自拡張部分。AIクラスのインスタンス化。(by Hamlet) Ai = new AiManager(); } private function copyMap(list:Array):Array { var map:Array = new Array(); for (var n:uint = 0; n < list.length; n++) { map[n] = list[n].concat(); } return map; } //コマの配置をマップに設定する public function put(p:uint, x:uint, y:uint):void { bMap[y][x] = p; cMap[y][x] = p; for (var cx:int = x-1; cx <= x+1; cx++) { for (var cy:int = y-1; cy <= y+1; cy++) { if (cx >= 0 && cx < pieces && cy >= 0 && cy < pieces) { var player:Object = bMap[cy][cx]; player = (player == 0) ? "*" : player; cMap[cy][cx] = player; } } } } //配置可能なマスかどうかを判定する public function getPoint(x:uint, y:uint):Boolean { if (bMap[y][x] == 0) { return true; } else { return false; } } //走査対象のコマかどうかを判定する private function getCheck(x:uint, y:uint):Boolean { var check:Object = cMap[y][x]; if (check == "*") { return true; } else { return false; } } //ヒント表示するコマかどうかを判定する public function getHint(x:uint, y:uint):Boolean { var hint:Object = hMap[y][x]; if (hint == "*") { return true; } else { return false; } } //評価値の高いマスを取得する({x: 0, y: 0}で返す) public function getBestPrio(p:uint):Object { var px:Number = undefined; var py:Number = undefined; var ev:int = -9999; var best:int = -9999; var bestpos:Array = new Array(35); var bestcnt:int = 0; hMap = copyMap(aMap); for (var x:uint = 0; x < pieces; x++) { for (var y:uint = 0; y < pieces; y++) { if (getCheck(x, y)) { var turns:uint = getTurns(p, x, y); if (turns > 0) { hMap[y][x] = "*"; //独自拡張部分。思考エンジンをコールし評価値を得る。 ev = Ai.Think(bMap, p, x, y); if (best < ev) { //評価値がより大きい場合、bestを更新する。 bestcnt = 0; bestpos[bestcnt++] = y * 8 + x; best = ev; } else if (best == ev) { //bestと同じ評価値の場合、候補のリストに追加する。 bestpos[bestcnt++] = y * 8 + x; } } } } } var index:int = Math.floor (Math.random () * bestcnt) px = bestpos[index] % 8; py = (int)(bestpos[index] / 8); return {x: px, y: py}; } //指定したマスの8方向に対して反転できるコマ数を取得する public function getTurns(p:uint, x:uint, y:uint):uint { var turns:uint = 0; for (var dx:int = -1; dx <= 1; dx++) { for (var dy:int = -1; dy <= 1; dy++) { if (dx == 0 && dy == 0) continue; var px:int = x + dx; var py:int = y + dy; while (px >= 0 && px < pieces && py >= 0 && py < pieces) { var player:uint = bMap[py][px]; if (player == 0) break; if (player == p) { if (dx != 0) { turns += dx*(px - x) - 1; } else { turns += dy*(py - y) - 1; } break; } px += dx; py += dy; } } } return turns; } //反転するコマ情報を取得する public function getTurnList(p:uint, x:uint, y:uint):Array { var list:Array = new Array(); for (var dx:int = -1; dx <= 1; dx++) { for (var dy:int = -1; dy <= 1; dy++) { if (dx == 0 && dy == 0) continue; var px:int = x + dx; var py:int = y + dy; var checking:Boolean = true; while (px >= 0 && px < pieces && py >= 0 && py < pieces) { var player:uint = bMap[py][px]; if (player == 0) break; if (player == p) { if (checking) { px = x + dx; py = y + dy; checking = false; continue; } else { break; } } if (!checking && player != p) { list.push({x: px, y: py}); } px += dx; py += dy; } } } return list; } } ////////////////////////////////////////////////// // コマの動きを管理するクラス ////////////////////////////////////////////////// import flash.display.Sprite; import flash.display.Shape; import flash.events.Event; import flash.utils.Timer; import flash.events.TimerEvent; class Piece extends Sprite { public var id:uint; public var px:uint; public var py:uint; private var piece1:PieceShape; private var piece2:PieceShape; private var scale:Number = 1; private var light:Shape; private var _brightness:Number = 0; public function Piece() { draw(); } public function put(p:uint):void { id = p; var piece:PieceShape = this["piece"+id]; addChild(piece); piece.scaleX = piece.scaleY = scale = 1.6; addEventListener(Event.ENTER_FRAME, putPiece, false, 0, true); } private function putPiece(evt:Event):void { var piece:PieceShape = this["piece"+id]; scale -= 0.1; piece.scaleX = piece.scaleY = scale; if (scale <= 1) { piece.scaleX = piece.scaleY = scale = 1; removeEventListener(Event.ENTER_FRAME, putPiece); dispatchEvent(new Event(Game.PUT_COMPLETE)) } } public function turn():void { var old:PieceShape = this["piece"+id]; removeChild(old); id = id%2 + 1; var piece:PieceShape = this["piece"+id]; addChild(piece); addChild(light); var timer:Timer = new Timer(50, 6); timer.addEventListener(TimerEvent.TIMER, turnPiece, false, 0, true); timer.addEventListener(TimerEvent.TIMER_COMPLETE, motion, false, 0, true); timer.start(); } private function turnPiece(evt:TimerEvent):void { if (evt.target.currentCount == 4) { evt.target.removeEventListener(TimerEvent.TIMER, turnPiece); removeChild(light); } } private function motion(evt:TimerEvent):void { evt.target.removeEventListener(TimerEvent.TIMER_COMPLETE, motion); brightness = 100; addEventListener(Event.ENTER_FRAME, bright, false, 0, true); } private function bright(evt:Event):void { brightness -= 20; if (brightness <= 0) { brightness = 0; removeEventListener(Event.ENTER_FRAME, bright); dispatchEvent(new Event(Game.TURN_COMPLETE)) } } private function draw():void { graphics.beginFill(0x000000); graphics.drawCircle(0, 0, 20); graphics.endFill(); piece1 = new PieceShape(1); piece2 = new PieceShape(2); light = new Shape(); light.graphics.beginFill(0xFFFFFF); light.graphics.drawCircle(0, 0, 20); light.graphics.drawCircle(0, 0, 15); light.graphics.endFill(); } private function get brightness():Number { return _brightness; } private function set brightness(param:Number):void { _brightness = param; ColorManager.brightOffset(this, _brightness); } } ////////////////////////////////////////////////// // コマを描画するクラス ////////////////////////////////////////////////// import flash.display.Shape; import flash.geom.Matrix; import flash.display.GradientType; import flash.display.SpreadMethod; import flash.display.InterpolationMethod; class PieceShape extends Shape { private var type:uint = 1; private static var cList:Array = [[0x888888, 0x000000], [0xFFFFFF, 0xBBBBBB]]; private static var bList:Array = [0x444444, 0xDDDDDD]; public function PieceShape(t:uint) { type = t; draw(); } private function draw():void { var colors:Array = cList[type-1]; var alphas:Array = [1, 1]; var ratios:Array = [0, 255]; var matrix:Matrix = new Matrix(); matrix.createGradientBox(36, 36, 0.25*Math.PI, -18, -18); graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix, SpreadMethod.PAD, InterpolationMethod.RGB, 0); graphics.drawCircle(0, 0, 18); graphics.endFill(); var bColor:uint = bList[type-1]; graphics.beginFill(bColor); graphics.drawCircle(0, 0, 15); graphics.endFill(); } } ////////////////////////////////////////////////// // マスを着色するクラス ////////////////////////////////////////////////// import flash.display.Shape; import flash.geom.ColorTransform; class Point extends Shape { public var id:uint; private static var bColor:uint = 0x66CC00; private static var cColor:uint = 0x66CCFF; private static var bColorTrans:ColorTransform; private static var cColorTrans:ColorTransform; public function Point() { draw(); } public function init():void { transform.colorTransform = bColorTrans; } public function hint():void { transform.colorTransform = cColorTrans; } private function draw():void { graphics.beginFill(0xFFFFFF); graphics.drawRect(-20, -20, 40, 40); graphics.endFill(); bColorTrans = new ColorTransform(0, 0, 0, 1, 0, 0, 0, 0); bColorTrans.color = bColor; cColorTrans = new ColorTransform(0, 0, 0, 1, 0, 0, 0, 0); cColorTrans.color = cColor; } } ////////////////////////////////////////////////// // 得点を管理するクラス ////////////////////////////////////////////////// import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFieldType; import flash.text.AntiAliasType; import flash.text.TextFormat; import flash.text.TextFormatAlign; import flash.filters.DropShadowFilter; class Score extends Sprite { private var pieces1:uint = 0; private var pieces2:uint = 0; private var score1:TextField; private var score2:TextField; private var message:TextField; private var player:Array; private var msgs:Object; private var time:Time; private var txt:TextField; private static var bColor:uint = 0xFFFF00; private static var sColor:uint = 0x000000; private static var b1Color:uint = 0x66CC00; private static var b2Color:uint = 0xFFFFFF; private static var fontType:String = "_ゴシック"; //private static var initMsg:String = "ゲームを初期化しています。"; private static var initMsg:String = "Enterキー・上下左右キーで操作してください。"; private static var playMsg:String = "ゲームを開始します。"; private static var putMsg:String = "の番です。"; private static var passMsg:String = "はパス。"; private static var finishMsg:String = "ゲームは終了しました。"; private static var noPointMsg:String = "そのマスにはコマを置けません。"; public function Score() { draw(); initialize(); } private function initialize():void { msgs = new Object(); msgs[Game.INIT] = initMsg; msgs[Game.PLAY] = playMsg; msgs[Game.PUT] = putMsg; msgs[Game.FINISH] = finishMsg; msgs[Game.NO_POINT] = noPointMsg; player = new Array(); player[1] = "あなた"; player[2] = "コンピュータ"; time = new Time(txt); } public function init():void { pieces1 = 0; pieces2 = 0; showScore(); } public function put(p:uint):void { this["pieces"+p] ++; showScore(); } public function turn(p:uint):void { this["pieces"+p] ++; var r:uint = p%2 + 1; this["pieces"+r] --; showScore(); } private function showScore():void { score1.text = String(pieces1); score2.text = String(pieces2); } public function showMessage(mode:String, p:uint = 0, passed:Boolean = false):void { switch (mode) { case Game.PUT : if (!passed) { message.text = player[p] + msgs[mode]; } else { var r:uint = p%2 + 1; message.text = player[r] + passMsg + player[p] + msgs[mode]; } break; default : message.text = msgs[mode]; break; } } public function getScore():Array { return [pieces1, pieces2]; } public function startTime():void { time.start(); } public function stopTime():void { time.stop(); } public function resetTime():void { time.reset(); } private function draw():void { graphics.beginFill(bColor); graphics.drawRect(20, 56, 340, 24); graphics.endFill(); graphics.beginFill(b1Color); graphics.drawRoundRect(256, 0, 104, 44, 12); graphics.endFill(); graphics.beginFill(b2Color); graphics.drawRoundRect(258, 2, 100, 40, 8); graphics.endFill(); var piece1:PieceShape = new PieceShape(1); addChild(piece1); piece1.x = 288; piece1.y = 29; piece1.width = piece1.height = 24; var piece2:PieceShape = new PieceShape(2); addChild(piece2); piece2.x = 328; piece2.y = 29; piece2.width = piece2.height = 24; var shade:DropShadowFilter = new DropShadowFilter(1, 90, sColor, 0.3, 2, 2, 2, 2, false, false); filters = [shade]; drawText(); } private function drawText():void { var tf:TextFormat = new TextFormat(); tf.font = "_ゴシック"; tf.size = 12; tf.align = TextFormatAlign.LEFT; message = new TextField(); addChild(message); message.x = 30; message.y = 59; message.width = 404; message.height = 21; message.type = TextFieldType.DYNAMIC; message.selectable = false; message.antiAliasType = AntiAliasType.ADVANCED; message.defaultTextFormat = tf; message.textColor = 0x000000; var shade:DropShadowFilter = new DropShadowFilter(1, 90, sColor, 0.4, 2, 2, 2, 2, false, false); var tfn:TextFormat = new TextFormat(); tfn.font = fontType; tfn.size = 12; tfn.align = TextFormatAlign.CENTER; var name1:TextField = new TextField(); addChild(name1); name1.x = 273; name1.y = 1; name1.width = 30; name1.height = 19; name1.type = TextFieldType.DYNAMIC; name1.selectable = false; //name1.embedFonts = true; //name1.antiAliasType = AntiAliasType.ADVANCED; name1.defaultTextFormat = tfn; name1.textColor = 0x000000; name1.text = "You"; name1.filters = [shade]; var name2:TextField = new TextField(); addChild(name2); name2.x = 313; name2.y = 1; name2.width = 30; name2.height = 19; name2.type = TextFieldType.DYNAMIC; name2.selectable = false; //name2.embedFonts = true; //name2.antiAliasType = AntiAliasType.ADVANCED; name2.defaultTextFormat = tfn; name2.textColor = 0x000000; name2.text = "CPU"; name2.filters = [shade]; var tfc:TextFormat = new TextFormat(); tfc.font = fontType; tfc.size = 14; tfc.align = TextFormatAlign.CENTER; score1 = new TextField(); addChild(score1); score1.x = 273; score1.y = 19; score1.width = 30; score1.height = 23; score1.type = TextFieldType.DYNAMIC; score1.selectable = false; //score1.embedFonts = true; //score1.antiAliasType = AntiAliasType.ADVANCED; score1.defaultTextFormat = tfc; score1.textColor = 0xFFFFFF; score1.text = String(0); score2 = new TextField(); addChild(score2); score2.x = 313; score2.y = 19; score2.width = 30; score2.height = 23; score2.type = TextFieldType.DYNAMIC; score2.selectable = false; //score2.embedFonts = true; //score2.antiAliasType = AntiAliasType.ADVANCED; score2.defaultTextFormat = tfc; score2.textColor = 0x000000; score2.text = String(0); var tft:TextFormat = new TextFormat(); tft.font = fontType; tft.size = 16; tft.align = TextFormatAlign.LEFT; var timer:TextField = new TextField(); addChild(timer); timer.x = 140; timer.y = 18; timer.width = 40; timer.height = 21; timer.type = TextFieldType.DYNAMIC; timer.selectable = false; //timer.embedFonts = true; //timer.antiAliasType = AntiAliasType.ADVANCED; timer.defaultTextFormat = tft; timer.textColor = 0xFFFFFF; timer.text = "Time"; txt = new TextField(); addChild(txt); txt.x = 185; txt.y = 18; txt.width = 55; txt.height = 21; txt.type = TextFieldType.DYNAMIC; txt.selectable = false; //txt.embedFonts = true; //txt.antiAliasType = AntiAliasType.ADVANCED; txt.defaultTextFormat = tft; txt.textColor = 0xFFFFFF; txt.text = "00:00"; } } ////////////////////////////////////////////////// // タイマーを管理するクラス ////////////////////////////////////////////////// import flash.display.Sprite; import flash.text.TextField; import flash.utils.getTimer; import flash.utils.Timer; import flash.events.TimerEvent; class Time extends Sprite { private var target:TextField; private var startTime:uint; private var timer:Timer; private var countTime:uint = 30; public function Time(tg:TextField) { target = tg; } public function start():void { startTime = getTimer(); timer = new Timer(countTime); timer.addEventListener(TimerEvent.TIMER, count, false, 0, true); timer.start(); } private function count(evt:TimerEvent):void { var sec:uint = Math.floor((getTimer() - startTime)/1000); var min:String = String(Math.floor(sec/60)); min = (uint(min) < 10) ? "0" + min : min; var msec:String = String(sec%60); msec = (uint(msec) < 10) ? "0" + msec : msec; target.text = min + ":" + msec; } public function stop():void { timer.removeEventListener(TimerEvent.TIMER, count); } public function reset():void { target.text = "00:00"; } } ////////////////////////////////////////////////// // カーソル操作を管理するクラス ////////////////////////////////////////////////// import flash.display.Sprite; import flash.events.Event; import flash.ui.Keyboard; import flash.events.KeyboardEvent; import flash.utils.Timer; import flash.events.TimerEvent; class Manager extends Sprite { private var board:Board; private static var pieces:uint = 8; public var cx:int; public var cy:int; private var tx:uint; private var ty:uint; private var cpu:Object; private static var autoTime:uint = 200; private var helpMode:String = ""; private var keyMode:Boolean = false; public function Manager(b:Board) { board = b; if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true); } private function init(evt:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); cpu = new Object(); stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown, false, 0, true); } //カーソル位置を設定する public function setCursor(x:uint, y:uint):void { cx = x; cy = y; } //キー操作の処理 private function keyDown(evt:KeyboardEvent):void { if (helpMode) { if (evt.keyCode == Keyboard.ENTER) { dispatchEvent(new Event(helpMode)); } } if (keyMode) { switch (evt.keyCode) { case Keyboard.ENTER : dispatchEvent(new Event(Game.SELECT)); break; case Keyboard.LEFT : cx --; break; case Keyboard.UP : cy --; break; case Keyboard.RIGHT : cx ++; break; case Keyboard.DOWN : cy ++; break; } if (cx > pieces - 1) cx = 0; if (cx < 0) cx = pieces - 1; if (cy > pieces - 1) cy = 0; if (cy < 0) cy = pieces - 1; dispatchEvent(new Event(Game.MOVE)); } } //カーソル位置を移動する public function autoCursor(px:uint, py:uint):void { tx = px; ty = py; var timer:Timer = new Timer(autoTime); timer.addEventListener(TimerEvent.TIMER, moveCursor, false, 0, true); timer.start(); } private function moveCursor(evt:TimerEvent):void { var mx:int = uint(tx > cx) - uint(tx < cx); var my:int = uint(ty > cy) - uint(ty < cy); if (mx != 0 || my != 0) { cx += mx; cy += my; dispatchEvent(new Event(Game.MOVE)); if (cx == tx && cy == ty) { evt.target.removeEventListener(TimerEvent.TIMER, moveCursor); dispatchEvent(new Event(Game.SELECT)); } } } public function set enable(param:Boolean):void { keyMode = param; } public function set help(param:String):void { helpMode = param; } } ////////////////////////////////////////////////// // カーソルを描画するクラス ////////////////////////////////////////////////// import flash.display.Sprite; import flash.display.Shape; import flash.utils.Timer; import flash.events.TimerEvent; class Cursor extends Sprite { private var id:uint = 0; private var cursor0:Shape; private var cursor1:Shape; private static var bColor:uint = 0x66CC00; private static var cColor:uint = 0x66CCFF; public function Cursor() { draw(); init(); } private function init():void { var cursor:Shape = this["cursor"+id]; addChild(cursor); var timer:Timer = new Timer(250); timer.addEventListener(TimerEvent.TIMER, change, false, 0, true); timer.start(); } private function change(evt:TimerEvent):void { var old:Shape = this["cursor"+id]; removeChild(old); id = (id+1)%2; var cursor:Shape = this["cursor"+id]; addChild(cursor); } private function draw():void { cursor0 = new Shape(); cursor0.graphics.beginFill(0xFFFFFF); cursor0.graphics.moveTo(-21, -21); cursor0.graphics.lineTo(-21, -6); cursor0.graphics.lineTo(-18, -6); cursor0.graphics.lineTo(-18, -18); cursor0.graphics.lineTo(-6, -18); cursor0.graphics.lineTo(-6, -21); cursor0.graphics.lineTo(-21, -21); cursor0.graphics.moveTo(21, -21); cursor0.graphics.lineTo(21, -6); cursor0.graphics.lineTo(18, -6); cursor0.graphics.lineTo(18, -18); cursor0.graphics.lineTo(6, -18); cursor0.graphics.lineTo(6, -21); cursor0.graphics.lineTo(21, -21); cursor0.graphics.moveTo(-21, 21); cursor0.graphics.lineTo(-21, 6); cursor0.graphics.lineTo(-18, 6); cursor0.graphics.lineTo(-18, 18); cursor0.graphics.lineTo(-6, 18); cursor0.graphics.lineTo(-6, 21); cursor0.graphics.lineTo(-21, 21); cursor0.graphics.moveTo(21, 21); cursor0.graphics.lineTo(21, 6); cursor0.graphics.lineTo(18, 6); cursor0.graphics.lineTo(18, 18); cursor0.graphics.lineTo(6, 18); cursor0.graphics.lineTo(6, 21); cursor0.graphics.lineTo(21, 21); cursor0.graphics.endFill(); cursor1 = new Shape(); cursor1.graphics.beginFill(0xFFFFFF); cursor1.graphics.moveTo(-22, -22); cursor1.graphics.lineTo(-22, -7); cursor1.graphics.lineTo(-19, -7); cursor1.graphics.lineTo(-19, -19); cursor1.graphics.lineTo(-7, -19); cursor1.graphics.lineTo(-7, -22); cursor1.graphics.lineTo(-22, -22); cursor1.graphics.moveTo(22, -22); cursor1.graphics.lineTo(22, -7); cursor1.graphics.lineTo(19, -7); cursor1.graphics.lineTo(19, -19); cursor1.graphics.lineTo(7, -19); cursor1.graphics.lineTo(7, -22); cursor1.graphics.lineTo(22, -22); cursor1.graphics.moveTo(-22, 22); cursor1.graphics.lineTo(-22, 7); cursor1.graphics.lineTo(-19, 7); cursor1.graphics.lineTo(-19, 19); cursor1.graphics.lineTo(-7, 19); cursor1.graphics.lineTo(-7, 22); cursor1.graphics.lineTo(-22, 22); cursor1.graphics.moveTo(22, 22); cursor1.graphics.lineTo(22, 7); cursor1.graphics.lineTo(19, 7); cursor1.graphics.lineTo(19, 19); cursor1.graphics.lineTo(7, 19); cursor1.graphics.lineTo(7, 22); cursor1.graphics.lineTo(22, 22); cursor1.graphics.endFill(); } } ////////////////////////////////////////////////// // ヘルプ表示を管理するクラス ////////////////////////////////////////////////// import flash.display.Sprite; import flash.events.Event; import flash.text.TextField; import flash.text.TextFieldType; import flash.text.AntiAliasType; import flash.text.TextFormat; import flash.text.TextFormatAlign; import flash.filters.GlowFilter; class Help extends Sprite { private var amplitude:Number = 0; private var scale:Number = 1; private static var targetScale:Number = 2; private static var deceleration:Number = 0.5; private static var friction:Number = 0.6; private var txt:TextField; private static var tColor:uint = 0x000000; private static var gColor:uint = 0xFFFFFF; private static var fontType:String = "_ゴシック"; public function Help() { draw(); hide(); } public function hide():void { visible = false; } public function show(help:String):void { txt.text = help; visible = true; amplitude = 0; scale = 1; addEventListener(Event.ENTER_FRAME, elastic, false, 0, true); } private function elastic(evt:Event):void { amplitude += targetScale - scale; scale += amplitude*friction; amplitude *= deceleration; scaleX = scaleY = scale; if (Math.abs(targetScale - scale) < 0.005 && Math.abs(amplitude) < 0.001) { scaleX = scaleY = targetScale; removeEventListener(Event.ENTER_FRAME, elastic); } } private function draw():void { var tf:TextFormat = new TextFormat(); tf.font = fontType; tf.size = 32; tf.align = TextFormatAlign.CENTER; txt = new TextField(); addChild(txt); txt.x = -75; txt.y = -19; txt.width = 150; txt.height = 39; txt.type = TextFieldType.DYNAMIC; txt.selectable = false; //txt.embedFonts = true; //txt.antiAliasType = AntiAliasType.ADVANCED; txt.defaultTextFormat = tf; txt.textColor = tColor; var glow:GlowFilter = new GlowFilter(gColor, 1, 10, 10, 10, 1, false, false); txt.filters = [glow]; } } ////////////////////////////////////////////////// // ColorManagerクラス ////////////////////////////////////////////////// import flash.display.DisplayObject; import flash.geom.ColorTransform; import flash.filters.ColorMatrixFilter; class ColorManager { private static var rs:Number = 0.3086; private static var gs:Number = 0.6094; private static var bs:Number = 0.0820; public function ColorManager() { } public static function brightOffset(target:DisplayObject, param:Number):void { target.transform.colorTransform = getBrightOffset(param); } private static function getBrightOffset(param:Number):ColorTransform { var percent:Number = 1; var offset:Number = param*2.55; var colorTrans:ColorTransform = new ColorTransform(0, 0, 0, 1, 0, 0, 0, 0); colorTrans.redMultiplier = percent; colorTrans.greenMultiplier = percent; colorTrans.blueMultiplier = percent; colorTrans.redOffset = offset; colorTrans.greenOffset = offset; colorTrans.blueOffset = offset; colorTrans.alphaMultiplier = 1; colorTrans.alphaOffset = 0; return colorTrans; } public static function saturation(target:DisplayObject, param:Number):void { target.filters = [getSaturation(param)]; } private static function getSaturation(param:Number):ColorMatrixFilter { var colorMatrix:ColorMatrixFilter = new ColorMatrixFilter(); var p:Number = param*0.01; var r:Number = (1 - p)*rs; var g:Number = (1 - p)*gs; var b:Number = (1 - p)*bs; var matrix:Array = [r + p, g, b, 0, 0, r, g + p, b, 0, 0, r, g, b + p, 0, 0, 0, 0, 0, 1, 0]; colorMatrix.matrix = matrix; return colorMatrix; } } ////////////////////////////////////////////////// // SoundEffectクラス ////////////////////////////////////////////////// import flash.events.EventDispatcher; import flash.events.Event; import flash.events.ProgressEvent; import flash.media.Sound; import flash.media.SoundChannel; import flash.media.SoundTransform; import flash.events.ProgressEvent; import flash.net.URLRequest; class SoundEffect extends EventDispatcher { private static var soundList:Object; private var sound:Sound; private var channel:SoundChannel; private static var initialized:Boolean = false; private var volume:Number; private var looping:Boolean = false; public function SoundEffect() { if (!initialized) initialize(); } private static function initialize():void { initialized = true; soundList = new Object(); } public function init(Snd:Class, id:String):void { var snd:Sound = new Snd(); soundList[id] = snd; } public function load(file:String, id:String):void { var snd:Sound = new Sound(); snd.load(new URLRequest(file)); snd.addEventListener(ProgressEvent.PROGRESS, progress, false, 0, true); snd.addEventListener(Event.COMPLETE, loaded, false, 0, true); soundList[id] = snd; } public function play(id:String, vol:Number, loop:Boolean = false):void { if (channel != null) channel.stop(); sound = soundList[id]; volume = vol; looping = loop; channel = sound.play(); var transform:SoundTransform = channel.soundTransform; transform.volume = volume; channel.soundTransform = transform; if (looping) { channel.addEventListener(Event.SOUND_COMPLETE, complete, false, 0, true); } } public function stop():void { if (channel != null) { channel.stop(); channel.removeEventListener(Event.SOUND_COMPLETE, complete); } } private function progress(evt:ProgressEvent):void { dispatchEvent(evt); } private function loaded(evt:Event):void { dispatchEvent(evt); } private function complete(evt:Event):void { channel.removeEventListener(Event.SOUND_COMPLETE, complete); if (looping) { channel = sound.play(0); channel.addEventListener(Event.SOUND_COMPLETE, complete, false, 0, true); var transform:SoundTransform = channel.soundTransform; transform.volume = volume; channel.soundTransform = transform; } } } ////////////////////////////////////////////////// // Btnクラス ////////////////////////////////////////////////// import flash.display.Sprite; import flash.display.Shape; import flash.text.TextField; import flash.text.TextFieldType; import flash.text.AntiAliasType; import flash.text.TextFormat; import flash.text.TextFormatAlign; import flash.filters.GlowFilter; import flash.events.MouseEvent; class Btn extends Sprite { public var id:uint; private var shade:Shape; private var bottom:Shape; private var light:Shape; private var base:Shape; private var txt:TextField; private var label:String = ""; private static var fontType:String = "_ゴシック"; private var _width:uint = 60; private static var _height:uint = 20; private static var corner:uint = 5; private var type:uint = 1; private static var bColor:uint = 0xFFFFFF; private static var sColor:uint = 0x000000; private static var upColor:uint = 0x666666; private static var overColor:uint = 0x333333; private static var offColor:uint = 0x999999; private static var gColor:uint = 0x0099FF; private var blueGlow:GlowFilter; private var shadeGlow:GlowFilter; private var _clicked:Boolean = false; private var _enabled:Boolean = true; public function Btn() { } public function init(option:Object):void { if (option.id != undefined) id = option.id; if (option.label != undefined) label = option.label; if (option.width != undefined) _width = option.width; if (option.type != undefined) type = option.type; draw(); } private function draw():void { switch (type) { case 1 : bColor = 0xFFFFFF; sColor = 0x000000; upColor = 0x666666; overColor = 0x333333; offColor = 0x999999; break; case 2 : bColor = 0x000000; sColor = 0xFFFFFF; upColor = 0x666666; overColor = 0x999999; offColor = 0x333333; break; } blueGlow = new GlowFilter(gColor, 0.6, 5, 5, 2, 3, false, true); shadeGlow = new GlowFilter(sColor, 0.3, 4, 4, 2, 3, false, true); shade = new Shape(); bottom = new Shape(); light = new Shape(); base = new Shape(); txt = new TextField(); addChild(shade); addChild(bottom); addChild(light); addChild(base); addChild(txt); createBase(shade, _width, _height, corner, sColor); shade.filters = [shadeGlow]; createBase(bottom, _width, _height, corner, sColor, 0.3); createBase(light, _width, _height, corner, gColor); light.filters = [blueGlow]; createBase(base, _width, _height, corner, bColor); txt.x = -_width*0.5; txt.y = -_height*0.5; txt.width = _width; txt.height = _height - 1; txt.type = TextFieldType.DYNAMIC; txt.selectable = false; //txt.embedFonts = true; //txt.antiAliasType = AntiAliasType.ADVANCED; var tf:TextFormat = new TextFormat(); tf.font = fontType; tf.size = 12; tf.align = TextFormatAlign.CENTER; txt.defaultTextFormat = tf; txt.text = label; enabled = true; mouseChildren = false; } private function rollOver(evt:MouseEvent):void { _over(); } private function rollOut(evt:MouseEvent):void { _up(); } private function press(evt:MouseEvent):void { _down(); } private function release(evt:MouseEvent):void { _up(); } private function click(evt:MouseEvent):void { } private function _up():void { txt.y = -_height*0.5; txt.textColor = upColor; base.y = -1; light.visible = false; light.y = -1; } private function _over():void { txt.y = -_height*0.5; txt.textColor = overColor; base.y = -1; light.visible = true; light.y = -1; } private function _down():void { txt.y = -_height*0.5 + 1; txt.textColor = overColor; base.y = 0; light.visible = true; light.y = 0; } private function _off():void { txt.y = -_height*0.5 + 1; txt.textColor = offColor; base.y = 0; light.visible = false; light.y = 0; } public function get clicked():Boolean { return _clicked; } public function set clicked(param:Boolean):void { _clicked = param; enabled = !_clicked; if (_clicked) { _down(); } else { _up(); } } public function get enabled():Boolean { return _enabled; } public function set enabled(param:Boolean):void { _enabled = param; buttonMode = _enabled; mouseEnabled = _enabled; useHandCursor = _enabled; if (_enabled) { _up(); addEventListener(MouseEvent.MOUSE_OVER, rollOver, false, 0, true); addEventListener(MouseEvent.MOUSE_OUT, rollOut, false, 0, true); addEventListener(MouseEvent.MOUSE_DOWN, press, false, 0, true); addEventListener(MouseEvent.MOUSE_UP, release, false, 0, true); addEventListener(MouseEvent.CLICK, click, false, 0, true); } else { _off(); removeEventListener(MouseEvent.MOUSE_OVER, rollOver); removeEventListener(MouseEvent.MOUSE_OUT, rollOut); removeEventListener(MouseEvent.MOUSE_DOWN, press); removeEventListener(MouseEvent.MOUSE_UP, release); removeEventListener(MouseEvent.CLICK, click); } } private function createBase(target:Shape, w:uint, h:uint, c:uint, color:uint, alpha:Number = 1):void { target.graphics.beginFill(color, alpha); target.graphics.drawRoundRect(-w*0.5, -h*0.5, w, h, c*2); target.graphics.endFill(); } } ////////////////////////////////////////////////// // AI用共通const定義 (by Hamlet) ////////////////////////////////////////////////// class AiHeader { //石色定義 public static const BLACK:int = -1; public static const WHITE:int = 1; public static const EMPTY:int = 0; public static const DUMMY:int = 9; //盤面ポジション定義 // A B C D E F G H // 1) 10 11 12 13 14 15 16 17 // 2) 19 20 21 22 23 24 25 26 // 3) 28 29 30 31 32 33 34 35 // 4) 37 38 39 40 41 42 43 44 // 5) 46 47 48 49 50 51 52 53 // 6) 55 56 57 58 59 60 61 62 // 7) 64 65 66 67 68 69 70 71 // 8) 73 74 75 76 77 78 79 80 public static const A1:int = 10; public static const B1:int = 11; public static const C1:int = 12; public static const D1:int = 13; public static const E1:int = 14; public static const F1:int = 15; public static const G1:int = 16; public static const H1:int = 17; public static const A2:int = 19; public static const B2:int = 20; public static const C2:int = 21; public static const D2:int = 22; public static const E2:int = 23; public static const F2:int = 24; public static const G2:int = 25; public static const H2:int = 26; public static const A3:int = 28; public static const B3:int = 29; public static const C3:int = 30; public static const D3:int = 31; public static const E3:int = 32; public static const F3:int = 33; public static const G3:int = 34; public static const H3:int = 35; public static const A4:int = 37; public static const B4:int = 38; public static const C4:int = 39; public static const D4:int = 40; public static const E4:int = 41; public static const F4:int = 42; public static const G4:int = 43; public static const H4:int = 44; public static const A5:int = 46; public static const B5:int = 47; public static const C5:int = 48; public static const D5:int = 49; public static const E5:int = 50; public static const F5:int = 51; public static const G5:int = 52; public static const H5:int = 53; public static const A6:int = 55; public static const B6:int = 56; public static const C6:int = 57; public static const D6:int = 58; public static const E6:int = 59; public static const F6:int = 60; public static const G6:int = 61; public static const H6:int = 62; public static const A7:int = 64; public static const B7:int = 65; public static const C7:int = 66; public static const D7:int = 67; public static const E7:int = 68; public static const F7:int = 69; public static const G7:int = 70; public static const H7:int = 71; public static const A8:int = 73; public static const B8:int = 74; public static const C8:int = 75; public static const D8:int = 76; public static const E8:int = 77; public static const F8:int = 78; public static const G8:int = 79; public static const H8:int = 80; //その他、定数定義 public static const FASTESTFIRST:int = 8; public static const EVALUE_FIRST:int = 3; public static const INFINITY:int = 128; public static const MIDGAME_DEPTH:int = 4; //中盤4手読み public static const ENDGAME_DEPTH:int = 12; //終盤12手読み } ////////////////////////////////////////////////// // 盤面の評価値を算出するクラス (by Hamlet) ////////////////////////////////////////////////// class AiManager extends AiHeader { //CPU思考用・仮想ボード配列 private var ban:AiBoard = new AiBoard(); //CPU思考用・先読み処理 private var Search:SearchEngine = new SearchEngine(); //機能: 指定の場所(x, y)に石を置いた場合の評価値を計算する //備考: 評価値計算ロジックに合わせるため、bMapの2次元盤面データをvtBoard1次元盤面配列に変換する。 public function Think(bMap:Array, p:int , x:int , y:int):int { var nPos:int = 0, nCol:int=EMPTY; var nVal:int = 0, nTurn:int = 0; var nEmpties:int = 0, nDepth:int = MIDGAME_DEPTH; var i:int, j:int; var board:Array = ban.board; var bestmove:Array = [0]; var discdiff:int = 0; var strX:Array = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];//debug用 var strY:Array = ['1', '2', '3', '4', '5', '6', '7', '8'];//debug用 //仮想盤面(vtBoard)に現在の盤面(bMap)の内容をセットする for (i = 0; i < 91; i++) { board[i] = DUMMY; } for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { nPos = (i + 1) * 9 + j + 1; switch (bMap[i][j]) { case 1: if (p == 1) { board[nPos] = BLACK; discdiff++; } else { board[nPos] = WHITE; discdiff--; } break; case 2: if (p == 1) { board[nPos] = WHITE; discdiff--; } else { board[nPos] = BLACK; discdiff++; } break; default: board[nPos] = EMPTY; nEmpties++; } } } //仮想盤面(9*10+1)の座標に変換 nPos = (y + 1) * 9 + x + 1; if (nEmpties > ENDGAME_DEPTH) { //評価関数による評価値算出 if (nDepth >= nEmpties) nDepth = nEmpties - 1; nVal = Search.midGameThink(ban, BLACK, nEmpties, discdiff, nPos, nDepth) & 0xFFFFFFFE; } else { //終盤読み切りによる最終スコア算出 nVal = Search.endGameThink(ban, BLACK, nEmpties, discdiff, nPos); } return nVal; } } ////////////////////////////////////////////////// // 盤面の空所を記録するリスト (by Hamlet) ////////////////////////////////////////////////// class EmptyList { public var square:int; public var pred:EmptyList; public var succ:EmptyList; } ////////////////////////////////////////////////// // AI用盤面管理クラス。高速処理用に別途用意。 (by Hamlet) ////////////////////////////////////////////////// class AiBoard extends AiHeader { public var board:Array = new Array(91); public var flipStack:Array = new Array(1200); public var flipStackP:int = 0; public var emHead:EmptyList = new EmptyList(); public var ems:Array = new Array(60); private const dirMask:Array = [ 0,0,0,0,0,0,0,0,0, 0,81,81,87,87,87,87,22,22, 0,81,81,87,87,87,87,22,22, 0,121,121,255,255,255,255,182,182, 0,121,121,255,255,255,255,182,182, 0,121,121,255,255,255,255,182,182, 0,121,121,255,255,255,255,182,182, 0,41,41,171,171,171,171,162,162, 0,41,41,171,171,171,171,162,162, 0,0,0,0,0,0,0,0,0,0 ]; public function undoFlips( flipCount:int, oppcol:int ):void { if ( (flipCount & 1) != 0 ) { flipCount--; board[flipStack[--flipStackP]] = oppcol; } while ( flipCount > 0 ) { flipCount -= 2; board[flipStack[--flipStackP]] = oppcol; board[flipStack[--flipStackP]] = oppcol; } } public function anyFlips( sqnum:int, color:int ):Boolean { var dir:int = dirMask[sqnum]; if (board[sqnum] != EMPTY) return false; if ( (dir & 128) != 0 ) if ( anyDrctnlFlips( sqnum, -10, color ) > 0) return true; if ( (dir & 64) != 0 ) if ( anyDrctnlFlips( sqnum, 10, color ) > 0) return true; if ( (dir & 32) != 0 ) if ( anyDrctnlFlips( sqnum, -9, color ) > 0) return true; if ( (dir & 16) != 0 ) if ( anyDrctnlFlips( sqnum, 9, color ) > 0) return true; if ( (dir & 8) != 0 ) if ( anyDrctnlFlips( sqnum, -8, color ) > 0) return true; if ( (dir & 4) != 0 ) if ( anyDrctnlFlips( sqnum, 8, color ) > 0) return true; if ( (dir & 2) != 0 ) if ( anyDrctnlFlips( sqnum, -1, color ) > 0) return true; if ( (dir & 1) != 0 ) if ( anyDrctnlFlips( sqnum, 1, color ) > 0) return true; return false; } private function anyDrctnlFlips( sqnum:int, inc:int, color:int ):int { var pos:int = sqnum + inc; var oppcol:int = -color; if( board[pos] == oppcol ){ pos += inc; if( board[pos] == oppcol ){ pos += inc; if( board[pos] == oppcol ){ pos += inc; if( board[pos] == oppcol ){ pos += inc; if( board[pos] == oppcol ){ pos += inc; if( board[pos] == oppcol ){ pos += inc; } } } } } if( board[pos] == color ) return 1; } return 0; } public function countFlips( sqnum:int, color:int ):int { var count:int = 0; var dir:int = dirMask[sqnum]; switch (dir) { case 81: // A1 A2 B1 B2 count += ctDrctnlFlips( sqnum, +1, color ); count += ctDrctnlFlips( sqnum, +10, color ); count += ctDrctnlFlips( sqnum, +9, color ); break; case 22: // G1 G2 H1 H2 count += ctDrctnlFlips( sqnum, -1, color ); count += ctDrctnlFlips( sqnum, +8, color ); count += ctDrctnlFlips( sqnum, +9, color ); break; case 41: // A7 A8 B7 B8 count += ctDrctnlFlips( sqnum, -9, color ); count += ctDrctnlFlips( sqnum, -8, color ); count += ctDrctnlFlips( sqnum, +1, color ); break; case 162:// G7 G8 H7 H8 count += ctDrctnlFlips( sqnum, -9, color ); count += ctDrctnlFlips( sqnum, -10, color ); count += ctDrctnlFlips( sqnum, -1, color ); break; case 87: // C1 C2 D1 D2 E1 E2 F1 F2 count += ctDrctnlFlips( sqnum, -1, color ); count += ctDrctnlFlips( sqnum, +8, color ); count += ctDrctnlFlips( sqnum, +9, color ); count += ctDrctnlFlips( sqnum, +10, color ); count += ctDrctnlFlips( sqnum, +1, color ); break; case 121:// A3 A4 A5 A6 B3 B4 B5 B6 count += ctDrctnlFlips( sqnum, -9, color ); count += ctDrctnlFlips( sqnum, -8, color ); count += ctDrctnlFlips( sqnum, +1, color ); count += ctDrctnlFlips( sqnum, +10, color ); count += ctDrctnlFlips( sqnum, +9, color ); break; case 182:// G3 G4 G5 G6 H3 H4 H5 H6 count += ctDrctnlFlips( sqnum, -9, color ); count += ctDrctnlFlips( sqnum, -10, color ); count += ctDrctnlFlips( sqnum, -1, color ); count += ctDrctnlFlips( sqnum, +8, color ); count += ctDrctnlFlips( sqnum, +9, color ); break; case 171:// C7 C8 D7 D8 E7 E8 F7 F8 count += ctDrctnlFlips( sqnum, -1, color ); count += ctDrctnlFlips( sqnum, -10, color ); count += ctDrctnlFlips( sqnum, -9, color ); count += ctDrctnlFlips( sqnum, -8, color ); count += ctDrctnlFlips( sqnum, +1, color ); break; case 255:// C3 C4 C5 C6 D3 D4 D5 D6 E3 E4 E5 E6 F3 F4 F5 F6 count += ctDrctnlFlips( sqnum, -10, color ); count += ctDrctnlFlips( sqnum, -9, color ); count += ctDrctnlFlips( sqnum, -8, color ); count += ctDrctnlFlips( sqnum, -1, color ); count += ctDrctnlFlips( sqnum, +1, color ); count += ctDrctnlFlips( sqnum, +8, color ); count += ctDrctnlFlips( sqnum, +9, color ); count += ctDrctnlFlips( sqnum, +10, color ); break; } return count; } private function ctDrctnlFlips( sqnum:int, inc:int, color:int ):int { var pos:int = sqnum + inc; var oppcol:int = -color; if( board[pos] == oppcol ){ pos += inc; if( board[pos] == oppcol ){ pos += inc; if( board[pos] == oppcol ){ pos += inc; if( board[pos] == oppcol ){ pos += inc; if( board[pos] == oppcol ){ pos += inc; if( board[pos] == oppcol ){ if( board[pos + inc] == color ) return 6; } else if( board[pos] == color ) return 5; } else if( board[pos] == color ) return 4; } else if( board[pos] == color ) return 3; } else if( board[pos] == color ) return 2; } else if( board[pos] == color ) return 1; } return 0; } public function doFlips( sqnum:int, color:int ):int { var dir:int = dirMask[sqnum]; var OldFlipStackP:int = flipStackP; switch (dir) { case 81: // A1 A2 B1 B2 drctnlFlips( sqnum, +1, color ); drctnlFlips( sqnum, +10, color ); drctnlFlips( sqnum, +9, color ); break; case 22: // G1 G2 H1 H2 drctnlFlips( sqnum, -1, color ); drctnlFlips( sqnum, +8, color ); drctnlFlips( sqnum, +9, color ); break; case 41: // A7 A8 B7 B8 drctnlFlips( sqnum, -9, color ); drctnlFlips( sqnum, -8, color ); drctnlFlips( sqnum, +1, color ); break; case 162: // G7 G8 H7 H8 drctnlFlips( sqnum, -9, color ); drctnlFlips( sqnum, -10, color ); drctnlFlips( sqnum, -1, color ); break; case 87: // C1 C2 D1 D2 E1 E2 F1 F2 drctnlFlips( sqnum, -1, color ); drctnlFlips( sqnum, +8, color ); drctnlFlips( sqnum, +9, color ); drctnlFlips( sqnum, +10, color ); drctnlFlips( sqnum, +1, color ); break; case 121: // A3 A4 A5 A6 B3 B4 B5 B6 drctnlFlips( sqnum, -9, color ); drctnlFlips( sqnum, -8, color ); drctnlFlips( sqnum, +1, color ); drctnlFlips( sqnum, +10, color ); drctnlFlips( sqnum, +9, color ); break; case 182: // G3 G4 G5 G6 H3 H4 H5 H6 drctnlFlips( sqnum, -9, color ); drctnlFlips( sqnum, -10, color ); drctnlFlips( sqnum, -1, color ); drctnlFlips( sqnum, +8, color ); drctnlFlips( sqnum, +9, color ); break; case 171: // C7 C8 D7 D8 E7 E8 F7 F8 drctnlFlips( sqnum, -1, color ); drctnlFlips( sqnum, -10, color ); drctnlFlips( sqnum, -9, color ); drctnlFlips( sqnum, -8, color ); drctnlFlips( sqnum, +1, color ); break; case 255: // C3 C4 C5 C6 D3 D4 D5 D6 E3 E4 E5 E6 F3 F4 F5 F6 drctnlFlips( sqnum, -10, color ); drctnlFlips( sqnum, -9, color ); drctnlFlips( sqnum, -8, color ); drctnlFlips( sqnum, -1, color ); drctnlFlips( sqnum, +1, color ); drctnlFlips( sqnum, +8, color ); drctnlFlips( sqnum, +9, color ); drctnlFlips( sqnum, +10, color ); break; } return flipStackP - OldFlipStackP; } private function drctnlFlips( sqnum:int, inc:int, color:int ):void { var pos:int = sqnum + inc; var sq:int = board[pos]; var oppcol:int = -color; if( sq == oppcol ) { sq = board[pos += inc]; if( sq == oppcol ) { sq = board[pos += inc]; if( sq == oppcol ) { sq = board[pos += inc]; if( sq == oppcol ) { sq = board[pos += inc]; if( sq == oppcol ) { sq = board[pos += inc]; if( sq == oppcol ) { if( board[ pos + inc] != color ) return; board[pos] = color; flipStack[ flipStackP++ ] = pos; } else if (sq != color) return; pos -= inc; board[pos] = color; flipStack[ flipStackP++ ] = pos; } else if (sq != color) return; pos -= inc; board[pos] = color; flipStack[ flipStackP++ ] = pos; } else if (sq != color) return; pos -= inc; board[pos] = color; flipStack[ flipStackP++ ] = pos; } else if (sq != color) return; pos -= inc; board[pos] = color; flipStack[ flipStackP++ ] = pos; } else if (sq != color) return; pos -= inc; board[pos] = color; flipStack[ flipStackP++ ] = pos; } } } ////////////////////////////////////////////////// // 盤面の探索を行うクラス (by Hamlet) // 先読みを実行する探索処理用クラス ////////////////////////////////////////////////// class SearchEngine extends AiHeader { private var evalue:Evaluate; private const worst2best:Array = [ 20, 25, 65, 70, 11, 16, 19, 26, 64, 71, 74, 79, 21, 24, 29, 34, 56, 61, 66, 69, 22, 23, 38, 43, 47, 52, 67, 68, 31, 32, 39, 42, 48, 51, 58, 59, 13, 14, 37, 44, 46, 53, 76, 77, 30, 33, 57, 60, 12, 15, 28, 35, 55, 62, 75, 78, 10, 17, 73, 80 ]; public function SearchEngine() { evalue = new Evaluate(); } //指定の場所に石を打った場合の最終スコアを算出する。 public function endGameThink( ban:AiBoard, color:int, empties:int, discdiff:int, sqnum:int ):int { var oppcol:int = -color; var flipped:int, score:int; var board:Array = ban.board; var square:Array = [0]; flipped = ban.doFlips( sqnum, color ); board[sqnum] = color; score = -endSolve( ban, square, oppcol, empties-1, -discdiff-(flipped*2)-1 ); ban.undoFlips( flipped, oppcol ); board[sqnum] = EMPTY; return score; } //指定の場所に石を打った場合の盤面評価値を算出する。 public function midGameThink( ban:AiBoard, color:int, empties:int, discdiff:int, sqnum:int, depth:int ):int { var oppcol:int = -color; var flipped:int, score:int; var board:Array = ban.board; var square:Array = [0]; flipped = ban.doFlips( sqnum, color ); board[sqnum] = color; score = -midGame( ban, square, oppcol, empties-1, -discdiff-(flipped*2)-1, depth-1 ); ban.undoFlips( flipped, oppcol ); board[sqnum] = EMPTY; return score; } //ゲームの木の探索前の準備処理 (空き場所リストの作成) private function prepareToSolve( ban:AiBoard ):void { var i:int, j:int, sqnum:int; var board:Array = ban.board; var Ems:Array = ban.ems; j = 0; var EmPtr:EmptyList = ban.emHead; for (i = (60-1); i >= 0; i--) { sqnum = worst2best[i]; if ( board[sqnum] == EMPTY ) { Ems[j] = new EmptyList(); EmPtr.succ = Ems[j]; Ems[j].pred = EmPtr; j++; EmPtr = EmPtr.succ; EmPtr.square = sqnum; } } EmPtr.succ = null; } //指定盤面に対する最善手と最終スコアを返す。 private function endSolve ( ban:AiBoard, bestmove:Array, color:int, empties:int, discdiff:int ):int { prepareToSolve(ban); //終盤探索 if ( empties > FASTESTFIRST ) { return fastestFirstEndSolve( ban, bestmove, -64, +64, color, empties, discdiff, 1 ); } else { return alphaBetaEndSolve( ban, bestmove, -64, +64, color, empties, discdiff, 1 ); } } //終盤の「速さ優先」探索を行う。 private function fastestFirstEndSolve( ban:AiBoard, bestmove:Array, alpha:int, beta:int, color:int, empties:int, discdiff:int, prevmove:int ):int { var i:int, j:int; var score:int = -INFINITY; var oppcol:int = -color; var sqnum:int = 0, ev:int; var flipped:int; var moves:int = 0; var best_value:int, best_index:int; var square:Array = [0]; var goodness:Array = new Array(64); var board:Array = ban.board; var em:EmptyList, old_em:EmptyList; var move_ptr:Array = new Array(64); for ( old_em = ban.emHead, em = old_em.succ; em != null; old_em = em, em = em.succ ) { sqnum = em.square; flipped = ban.doFlips( sqnum, color ); if ( flipped > 0) { board[sqnum] = color; old_em.succ = em.succ; goodness[moves] = fastEval( ban, oppcol ); ban.undoFlips( flipped, oppcol ); board[sqnum] = EMPTY; old_em.succ = em; move_ptr[moves] = em; moves++; } } if ( moves != 0 ) { for ( i = 0; i < moves; i++ ) { best_value = goodness[i]; best_index = i; for ( j = i + 1; j < moves; j++ ) { if ( goodness[j] > best_value ) { best_value = goodness[j]; best_index = j; } } em = move_ptr[best_index]; move_ptr[best_index] = move_ptr[i]; goodness[best_index] = goodness[i]; sqnum = em.square; flipped = ban.doFlips( sqnum, color ); board[sqnum] = color; em.pred.succ = em.succ; if ( em.succ != null ) em.succ.pred = em.pred; if ( empties < FASTESTFIRST ) { ev = -alphaBetaEndSolve( ban, square, -beta, -alpha, oppcol, empties-1, -discdiff-(flipped*2)-1, 1); } else { ev = -fastestFirstEndSolve( ban, square, -beta, -alpha, oppcol, empties-1, -discdiff-(flipped*2)-1, 1 ); } ban.undoFlips( flipped, oppcol ); board[sqnum] = EMPTY; em.pred.succ = em; if ( em.succ != null ) em.succ.pred = em; if (ev > score) { score = ev; bestmove[0] = sqnum; if (ev > alpha) { alpha = ev; if (ev >= beta) { return score; } } } } } else { if ( prevmove == 0 ) { if ((discdiff+empties) == 64) return 64; if ((discdiff-empties) == -64) return -64; return discdiff; } else { score = -fastestFirstEndSolve( ban, square, -beta, -alpha, oppcol, empties, -discdiff, 0 ); } } return score; } //ゲームの木の末端処理。最終的な石差を計算する。 private function alphaBetaEndSolve( ban:AiBoard, bestmove:Array, alpha:int, beta:int, color:int, empties:int, discdiff:int, prevmove:int ):int { var score:int = -INFINITY; var oppcol:int = -color; var sqnum:int,flipped:int,ev:int; var square:Array = [0]; var board:Array = ban.board; var em:EmptyList, old_em:EmptyList; for (old_em = ban.emHead, em = old_em.succ; em != null; old_em = em, em = em.succ) { sqnum = em.square; flipped = ban.doFlips( sqnum, color ); if (flipped > 0) { board[sqnum] = color; old_em.succ = em.succ; if (empties == 2) { var flipped1:int; flipped1 = ban.countFlips( ban.emHead.succ.square, oppcol); if (flipped1 > 0) { ev = discdiff + ((flipped-flipped1)*2); } else { flipped1 = ban.countFlips( ban.emHead.succ.square, color); ev = discdiff + (flipped*2); if (flipped1 > 0) { ev += (flipped1+1)*2; } else { ev++; if (ev == 63) ev++; } } } else { ev = -alphaBetaEndSolve( ban, square, -beta, -alpha, oppcol, empties-1, -discdiff-(flipped*2)-1, 1); } ban.undoFlips( flipped, oppcol ); board[sqnum] = EMPTY; old_em.succ = em; if (ev > score) { score = ev; bestmove[0] = sqnum; if (ev > alpha) { alpha = ev; if (ev >= beta) { return score; } } } } } if(score == -INFINITY){ if(prevmove == 0){ if ((discdiff+empties) == 64) return 64; if ((discdiff-empties) == -64) return -64; return discdiff; } else return -alphaBetaEndSolve( ban, square, -beta, -alpha, oppcol, empties, -discdiff, 0); } return score; } //速さ優先探索用関数。相手の着手可能手数が少なくなる手に高い評価を与える。(但し、隅周辺の石の配置により微調整) private function fastEval( ban:AiBoard, oppcol:int ):int { var square:int; var mobility:int = 0; var stability:int = 0; var color:int = -oppcol; var board:Array = ban.board; var em:EmptyList; //相手が打てる場所の数をカウント for ( em = ban.emHead.succ; em != null; em = em.succ ) { square = em.square; if ( ban.anyFlips( square, oppcol ) ) { mobility++; } } //以下、隅周辺の石の配置による微調整 if (board[A1] == color) { stability++; if (board[B1] == color) { stability++; } if (board[A2] == color){ stability++; } } else if (board[A1] == EMPTY) { if (board[B2] == color){ stability--; stability--; } } if (board[A8] == color) { stability++; if (board[B8] == color) { stability++; } if (board[A7] == color) { stability++; } } else if (board[A8] == EMPTY) { if (board[B7] == color){ stability--; stability--; } } if (board[H1] == color) { stability++; if (board[G1] == color) { stability++; } if (board[H2] == color) { stability++; } } else if (board[H1] == EMPTY) { if (board[G2] == color){ stability--; stability--; } } if (board[H8] == color) { stability++; if (board[G8] == color) { stability++; } if (board[H7] == color) { stability++; } } else if (board[H8] == EMPTY) { if (board[G7] == color){ stability--; stability--; } } return stability - ( mobility << 4 ); } //指定盤面に対する中盤の評価値を返す。 private function midGame( ban:AiBoard, bestmove:Array, color:int, empties:int, discdiff:int, depth:int ):int { prepareToSolve(ban); if ( depth > EVALUE_FIRST ) { //ゲームの木の上位ノード処理 return evalFirstMidGame( ban, bestmove, -INFINITY, +INFINITY, color, empties, discdiff, depth, 1 ); } else { //ゲームの木の末端ノード処理 return alphaBetaMidGame( ban, bestmove, -INFINITY, +INFINITY, color, empties, discdiff, depth, 1 ); } } //評価値が高いと予想される手を優先的に探索する中盤処理 private function evalFirstMidGame( ban:AiBoard, bestmove:Array, alpha:int, beta:int, color:int, empties:int, discdiff:int, depth:int, prevmove:int ):int { var i:int, j:int; var score:int = -INFINITY; var oppcol:int = -color; var sqnum:int = 0, ev:int; var flipped:int; var moves:int = 0; var best_value:int, best_index:int; var square:Array = [0]; var goodness:Array = new Array(64); var board:Array = ban.board; var em:EmptyList, old_em:EmptyList; var move_ptr:Array = new Array(64); //優先的に探索するための前準備 for ( old_em = ban.emHead, em = old_em.succ; em != null; old_em = em, em = em.succ ) { sqnum = em.square; flipped = ban.doFlips( sqnum, color ); if ( flipped > 0) { board[sqnum] = color; old_em.succ = em.succ; goodness[moves] = fastEval( ban, oppcol ); ban.undoFlips( flipped, oppcol ); board[sqnum] = EMPTY; old_em.succ = em; move_ptr[moves] = em; moves++; } } //打てる場所すべての評価値を算出する。 if ( moves != 0 ) { for ( i = 0; i < moves; i++ ) { best_value = goodness[i]; best_index = i; for ( j = i + 1; j < moves; j++ ) { if ( goodness[j] > best_value ) { best_value = goodness[j]; best_index = j; } } em = move_ptr[best_index]; move_ptr[best_index] = move_ptr[i]; goodness[best_index] = goodness[i]; sqnum = em.square; flipped = ban.doFlips( sqnum, color ); board[sqnum] = color; em.pred.succ = em.succ; if ( em.succ != null ) em.succ.pred = em.pred; if ( depth <= EVALUE_FIRST ) { ev = -alphaBetaMidGame( ban, square, -beta, -alpha, oppcol, empties-1, -discdiff-(flipped*2)-1, depth-1, 1); } else { ev = -evalFirstMidGame( ban, square, -beta, -alpha, oppcol, empties-1, -discdiff-(flipped*2)-1, depth-1, 1 ); } ban.undoFlips( flipped, oppcol ); board[sqnum] = EMPTY; em.pred.succ = em; if ( em.succ != null ) em.succ.pred = em; if (ev > score) { score = ev; bestmove[0] = sqnum; if (ev > alpha) { alpha = ev; if (ev >= beta) { return score; } } } } } else { if ( prevmove == 0 ) { if (discdiff > 0) return +INFINITY; if (discdiff < 0) return -INFINITY; return 0; } else { score = -evalFirstMidGame( ban, square, -beta, -alpha, oppcol, empties, -discdiff, depth, 0 ); } } return score; } //末端の探索と評価関数のコール処理 private function alphaBetaMidGame( ban:AiBoard, bestmove:Array, alpha:int, beta:int, color:int, empties:int, discdiff:int, depth:int, prevmove:int ):int { if ( depth < 1 ) return evalue.Eval(ban.board, empties, color); //末端のため、評価値を計算して返す。 var score:int = -INFINITY; var oppcol:int = -color; var sqnum:int = 0, ev:int; var flipped:int; var moves:int = 0; var square:Array = [0]; var board:Array = ban.board; var em:EmptyList, old_em:EmptyList; //打てる場所すべての評価値を算出する。 for (old_em = ban.emHead, em = old_em.succ; em!=null; old_em = em, em = em.succ) { sqnum = em.square; flipped = ban.doFlips( sqnum, color ); if (flipped > 0) { board[sqnum] = color; old_em.succ = em.succ; ev = -alphaBetaMidGame( ban, square, -beta, -alpha, oppcol, empties-1, -discdiff-(flipped*2)-1, depth-1, 1); ban.undoFlips( flipped, oppcol ); board[sqnum] = EMPTY; old_em.succ = em; if (ev > score) { score = ev; bestmove[0] = sqnum; if (ev > alpha) { alpha = ev; if (ev >= beta) { return score; } } } } } if(score == -INFINITY){ if(prevmove == 0){ if (discdiff > 0) return +INFINITY; if (discdiff < 0) return -INFINITY; return 0; } else return -alphaBetaMidGame( ban, square, -beta, -alpha, oppcol, empties, -discdiff, depth, 0); } return score; } } ////////////////////////////////////////////////// // 盤面の評価値を算出するクラス ////////////////////////////////////////////////// class Evaluate extends AiHeader { //AIデータアレイ private var Line1:Array; private var Line2:Array; private var Line3:Array; private var Line4:Array; private var Edge8:Array; private var Diag8:Array; private var Diag7:Array; private var Diag6:Array; private var Diag5:Array; private var Diag4:Array; public function Evaluate() { init(); } //機能: 評価値算出用パターンデータの登録。 //戻値: なし。 //備考: 固定値。変動なし。 private function init():void { Line1 = [ +0,+43,-69,-43,+45,-64,+20,+20,-66,-13,-3,-65,-37,+32,-69, +28,+14,-43,+2,+29,-3,-55,+48,-58,+26,+44,-58,-16,+29,-75, -47,+20,-59,+2,+10,-68,-22,-29,-56,-23,+39,-59,+10,+9,-14, +2,+24,-39,-48,+5,-49,+32,+40,-45,+0,+25,-54,-34,+14,-3, +0,-3,-42,-18,-11,-69,-48,+8,-49,+25,+55,-15,-1,+46,-42, -28,+49,-47,+25,+50,-58,-16,+19,-63,-31,+39,-80,+8,-27,-75, -32,-9,-60,-57,+18,-63,+5,+16,-21,-4,+16,-3,-73,+11,-57, +16,+16,-55,-29,+21,-82,-65,-27,-65,-9,+11,-58,-12,-1,-59, -20,+22,-57,+17,-16,-33,-4,+16,-51,-55,+21,-24,+20,+25,-42, +4,+13,-38,-24,+40,-31,+14,-3,-42,-23,-26,-36,-45,+8,-41, +45,+54,-2,+21,+36,-18,-33,+54,-59,+15,+20,-50,-2,+27,-58, -43,+33,-59,+24,+9,-59,-7,-7,-58,-25,+37,-3,+0,-3,+0, +0,+0,-3,-7,-3,-45,+7,+33,-40,-18,+1,-28,-38,+15,-25, +20,-3,-31,-23,-29,-9,-44,+26,-33,+25,+38,+7,+7,+54,-5, -13,+52,-26,+25,+64,-48,+1,+40,-30,-18,+20,-27,+20,+2,-53, -7,+21,-44,-26,+47,-51,+18,+37,-10,+0,+41,-27,-43,+37,-56, +28,+21,-55,-13,+20,-70,-53,+6,-58,+25,-6,-57,-12,-19,-56, -22,+35,-59,-14,-24,-55,-21,-12,-5,-83,+47,-64,+21,+11,-63, -32,+0,-68,-52,+52,-64,-2,-46,-71,-43,-61,-69,-28,+6,-62, +28,-7,-32,+0,+20,-56,-47,+3,-30,+43,+31,-56,-2,+17,-51, -27,+3,-3,+0,-3,-47,-23,-22,-24,-43,-2,-65,+18,+34,-30, -7,+23,-53,-30,+35,-41,+22,+18,-57,-22,-8,-65,-30,+30,-75, +10,-29,-85,-43,-43,-85,-57,+3,-67,+10,+11,-45,+4,+25,-3, -64,+18,-42,+18,+44,-51,-12,+32,-57,-45,-4,-50,+17,+18,-46, -6,+0,-47,-12,+33,-63,-8,-16,-55,-17,-21,-75,-54,-44,-65, +4,-18,-30,+9,-23,-27,-29,+5,-65,-13,-3,-85,-55,-36,-72, -66,+31,+1,+6,+15,+8,+2,+28,-36,-9,+68,-74,-3,+7,-27, -2,+4,-14,-60,-9,-91,-6,-25,-68,-13,-4,-76,-5,+14,-97, -3,-33,-43,-20,+7,-3,-7,-3,-16,-13,-101,-38,-48,-42,-86, -80,-96,-43,+0,-36,-53,-47,-61,-56,-62,-3,-72,-11,+1,-57, -10,+33,+5,-9,+4,-95,+76,+102,-40,-8,-12,-90,-43,+65,+21, -15,+1,+7,-33,+18,-14,-54,+32,-64,+8,-33,-56,-25,+1,-89, -75,+3,-96,-6,+75,-70,-20,-17,-92,-41,+15,-75,+0,-79,-88, -43,+21,-71,-35,+47,-25,+25,-33,-2,-24,-56,-3,+71,-68,-66, +5,+38,-29,-28,-3,-41,-85,-68,-81,+6,-18,-45,-30,-3,-69, -18,+22,-3,+0,-3,+0,+0,+0,-3,-7,-3,+1,+1,+1,+0, +0,+0,-3,-1,-1,-3,+0,-3,-7,-7,-7,-3,-7,-3,-47, -1,+16,-54,-20,-9,-101,+71,-101,-11,-40,-3,-23,-55,+4,-107, -85,+89,-8,+15,-8,-105,-83,-35,-8,+88,+89,-91,-19,-36,-40, -14,+58,-3,-7,-3,-103,-14,+11,-38,-73,-39,-105,-105,-8,-101, +13,-3,-82,-64,-38,+2,-48,+9,-41,+9,+11,-43,-18,+31,-61, -29,+36,-76,+10,+10,-58,-16,-9,-38,-25,+12,-75,+14,+2,-48, -24,+7,-36,-14,+58,-54,+23,+0,-40,-21,+18,-32,-43,+66,-56, -4,+38,-47,-26,+21,-81,-54,+16,-63,-5,-9,-59,-18,-18,-40, -14,+23,-47,+47,-48,-34,-7,-19,+2,-1,+2,-32,+0,-42,-60, -34,+3,-85,-49,+15,-23,+13,-50,-21,-27,-16,-29,-7,+45,-73, +10,+17,+14,-22,+42,-35,-60,+12,-70,+64,+22,-48,-25,-20,-85, -54,+2,-34,+40,+2,-72,-43,-13,-41,-51,+24,-31,+13,-34,-60, -28,+2,-63,-41,+10,-54,+0,+32,-54,-43,-15,-73,-47,-17,-88, +6,-61,-86,-53,-39,-71,-68,+27,-86,+18,-37,-64,-15,-18,-5, -85,-102,-44,+4,+22,-58,-31,+19,-103,-58,+21,-73,+3,-42,-65, -30,-13,-70,-17,+21,-67,+10,-61,-29,-43,-25,-65,-80,-5,+42, +0,+0,-49,-32,+0,-102,-49,-100,-5,-1,-5,-105,-38,-14,-102, -73,-102,-89,-3,-18,-84,-25,+0,-78,-85,-12,-12,-64,+74,-70, -47,-27,-85,-58,+93,-97,-76,-103,-35,-52,-80,-71,-103,-54,-46, +13,-30,-92,-20,+11,-5,-105,+93,-49,-10,+35,-48,-65,+25,-105, -6,-6,-56,-4,-21,-72,-45,-56,-75,-32,-2,-64,+12,-30,-70, -10,-14,-43,-66,-33,+34,-13,+6,-49,-5,+27,-101,-14,+19,-28, +19,-3,-96,-45,-44,-58,-63,-24,-52,+27,-33,-15,+14,+7,-11, -54,-14,-47,-18,+19,-18,-28,-26,-84,-51,+8,-78,-25,-46,-85, -26,-35,-34,-38,+11,-3,+0,-3,+0,+0,+0,-3,-7,-3,-54, -47,+94,-83,-48,+54,+3,-73,+89,-70,+3,-3,-50,-43,-7,-30, -67,-29,-26,+16,+26,-30,-18,+9,+1,-5,+51,-29,+3,+44,-77, -25,-8,-30,-14,+21,-76,+1,+1,-97,-25,-18,-29,-38,-10,-81, +0,+32,-5,-18,+33,+38,-35,+85,-81,-13,-69,-73,-37,+20,-103, -68,+21,-63,-8,-7,-58,-22,-50,-36,-8,+39,-44,-27,-66,-28, -45,-61,-6,+88,-6,-100,-23,+19,-84,-57,-20,-105,-103,-6,-103, -6,-65,+17,-57,-89,-46,-31,-18,-72,+0,-48,-65,-28,-25,-66, -62,-63,-43,-10,+27,-52,-10,-37,-51,-7,+15,-3,+0,-3,-65, -44,-76,-77,-67,+1,-37,-16,+8,-28,-25,+8,-29,-18,+45,-44, -10,+28,-43,-23,-12,-62,-17,+42,-52,+11,+7,-61,-28,-28,-96, -31,+40,-63,-12,-36,-40,-17,-11,-3,-48,-58,-57,-9,+0,-45, -20,+29,-65,-32,-6,-55,+8,-39,-35,-12,-29,-44,+0,+31,-27, +44,+15,+38,+47,+45,-32,-16,+23,+10,+75,+94,+31,+59,+42,+10, +11,+61,-75,-2,+0,-40,-16,-13,-32,-30,+10,+35,+46,+44,+11, +69,+88,+55,+1,+72,+51,+70,+99,+47,+56,+67,+3,+17,+28,+7, +69,-18,+42,+38,+32,+18,+26,+74,-10,+30,-4,-13,+9,+47,+0, -3,+0,-23,+29,+92,-26,+9,+53,-19,-61,-97,+41,+56,+18,-37, -7,+22,+0,-48,+43,+38,+96,+44,+103,+85,+103,+46,+15,+96,+6, +71,+105,+53,+60,+58,+1,+0,+101,+5,+8,+5,+99,+54,+65,+75, -33,+78,-36,+36,+104,+47,+56,+96,+45,-33,+69,-93,+71,-91,+9, +65,+52,-24,-34,+2,+0,+71,+32,-36,+37,+79,+0,+32,+78,-61, +34,+97,+3,+58,+101,+0,+16,+65,-11,+40,+103,+10,+55,+32,-99, -18,+33,+97,+76,+97,-15,+34,+67,-18,+8,+85,-31,+77,-4,+14, +24,+33,+0,-33,+53,+102,+102,+102,+8,+69,+86,+52,-48,+99,+0, +3,+0,-3,-3,-3,+0,-3,+0,-2,+29,+97,+51,+44,+85,+86, -33,+97,+44,+41,-13,-14,+14,+35,-30,-37,+93,+44,+14,+37,-61, -24,-32,-75,-66,+66,+15,+58,+65,+19,+36,+59,+0,-36,+32,-11, +36,+50,+34,+16,+69,-75,-30,+76,+37,+72,+95,-57,+11,+12,+32, -36,+57,-6,+65,+94,+103,+57,+60,+22,-18,+45,+8,+105,+107,+103, +82,+101,+3,+10,+91,+5,+105,+5,+99,+25,+70,+75,+6,+102,+49, +105,+105,+103,+68,+103,+105,+102,+105,-26,+103,+78,+86,+75,+85,+99, +22,+101,+1,+41,+22,+31,+64,+82,+99,+44,+18,+102,-3,+102,+8, +28,+105,+5,+1,+5,+3,+85,+5,+1,+40,+78,+0,+0,+0,+5, +86,+5,+50,+31,+80,+19,+27,+86,+12,+62,+99,-14,+65,+79,+78, +7,+84,+71,+85,+78,+63,+63,+66,+99,+38,+21,-7,+107,+7,+52, +20,+40,+30,+19,+85,+26,+103,-91,+44,+70,+86,+33,+75,+86,-93, +73,+104,+46,+69,+86,+0,+32,+55,+97,+92,+27,+9,+21,+66,+24, -69,+94,+73,+84,-13,+8,+58,+70,+0,-3,+0,+73,+81,-14,+62, +50,+69,-99,+74,+98,+0,+14,+31,+47,+18,+74,-3,+28,+86,-52, +51,+92,-38,+51,+62,-97,-101,+49,+24,+102,+5,-49,+54,+70,+0, -42,+99,+0,+3,+0,+94,+33,+83,-52,+94,+82,+7,+30,+103,+64, +30,+71,-40,+38,+103,+101,+85,-14,+73,+44,+43,-99,+22,+76,-99, +90,+96,+33,+11,+33,-1,+19,+65,-42,+101,+50,-94,+38,+101,+0, +11,+0,-9,+38,+4,+62,+16,+83,-3,+35,-1,+54,+27,+77,+7, +44,+72,-10,+0,+78,+0,+3,+0,+3,+3,+3,+0,-3,+0,+5, +5,+5,+3,+3,+3,+0,+2,+2,+0,+3,+0,-3,-3,-3,+0, -3,+0,+5,+6,+5,+5,+5,+5,+5,+1,+5,+5,+5,+7,+3, +3,+3,+0,+2,+2,+0,+3,+0,+2,+2,+2,+0,+1,+2,+0, +3,+0,+3,+3,+3,+0,-3,+0,-2,-2,+0,-3,-3,-3,-5, -5,-5,+0,+3,+0,-3,-3,-3,+0,-3,+0,-16,+29,-18,+55, +53,+83,-36,-25,+86,-98,+78,+22,+1,+42,+60,+40,-9,+91,+0, +101,+0,-23,+9,+12,-86,-46,+97,-54,-38,+32,+21,+27,+95,+0, -79,+97,-73,+63,+27,-23,+20,+33,-33,-61,+93,+21,+89,+31,-14, -6,+13,-45,-7,+82,-5,+11,+37,+44,+18,+57,-5,-8,-5,-101, +32,+96,-88,-27,+56,-105,-103,-6,-102,+36,+93,+23,-29,-41,-55, +7,-13,+11,+66,+18,+81,+56,+55,+0,-36,+46,+5,+65,+5,+25, +39,+101,+97,-50,+99,+0,+3,+0,-3,-3,-3,+0,-3,+0,-42, -1,+97,-35,+5,+75,+36,-18,+78,-82,+35,+31,-71,+10,+42,-78, -42,+83,+64,-5,+93,-41,-46,+22,-46,-65,+69,-36,+43,+95,-57, +51,+97,+0,-3,+0,-65,+61,+77,-13,+11,+36,-22,-21,+28,+30, +75,+0,+0,+18,+3,+32,-39,+60,-40,+35,+45,+20,+46,+82,+0, -21,+51,+27,+72,+60,+28,+58,+74,-7,+31,+73,-38,+82,+3,-5, +16,+31,+57,-14,+47,-24,-17,+103,+89,+71,+16,-23,+33,+77,+10, +65,+79,+43,+68,+85,-47,+42,+99,-35,+45,+83,+35,+54,+80,+15, +9,+81,+39,+50,+33,-8,+31,+57,+3,+0,+3,+1,+21,+62,+27, +24,+19,-50,-25,+14,+35,+53,+55,+0,+20,+30,+37,-25,+67,+29, +61,+88,+7,+85,+16,+41,+28,+37,+69,+35,+103,+58,+75,+87,-33, +18,+91,+102,+105,+5,+52,+36,+49,+61,+7,+76,-33,+58,+96,+40, +57,+70,+14,+1,+31,+51,+86,+86,-2,+66,+54,-9,+2,+5,-2, +88,+95,+0,+41,+56,+36,+33,+78,-7,+85,+85,+34,+59,+78,-2, -9,+18,-22,+59,+71,-18,+46,+68,-31,+0,+33,+14,+68,+75,-35, +23,+18,-42,+8,+82,-2,+65,+47,+70,+47,+57,+3,+7,+31,+8, +105,+105,+7,+42,+48,-94,-19,+103,+3,+7,+3,+0,+0,+0,+3, +0,+3,-24,+97,+101,+39,+53,+78,+23,-56,+3,+72,+72,+70,-20, +29,+43,-52,-18,+57,+47,-7,+57,-52,-12,+15,-99,-61,+96,+15, +96,+59,+46,+42,+104,+3,+58,+84,-68,+48,+101,-25,+16,+45,-99, +11,+41,+21,+85,+97,+5,+25,+45,+40,-11,+71,-37,+45,+42,+37, +51,+74,+13,-23,+52,+4,+48,+101,+53,+55,+64,-62,-9,+66,-94, +38,+3,+25,+13,-4,-34,+27,+83,+6,+84,+58,+38,+63,+87,+88, -12,+81,+1,+58,+66,+18,+58,+72,-62,-20,+45,+3,+29,+60,+18, +40,+66,-10,-8,+81,-19,+83,+86,-21,+40,+48,+3,+0,+3,-24, +60,+70,+0,+25,+45,-1,+0,-21,+31,+38,+101,-27,+17,+37,+26, -37,+72,-20,+43,+67,+58,+57,+85,+71,+4,+82,+18,+70,+85,+26, +58,+72,-73,+21,+46,+101,+23,+3,+20,+27,+30,+14,-26,+61,-13, +73,+52,+30,+55,+54,+23,-17,+35,+21,+54,+86,+0,+43,+57,-46, -15,+49,-11,+70,+33,+2,+20,+22,-9,+20,+47,-36,+18,+35,-15, +50,+43,-3,+4,+94,-10,+47,+43,-18,+19,+38,-86,-27,+67,-1, +27,+42,-43,-8,-26,-47,-12,+49,-28,+52,+53,+2,+56,+19,-25, -42,-4,-38,+49,+78,+0,+45,+45,+49,+3,+51,-3,+0,-3,-7, +1,+62,-8,+54,+72,-47,+77,+32,+24,+48,+68,-1,-3,+79,+9, +48,+69,-26,+29,+38,-63,+19,+62,-28,+40,+56,-58,+0,+45,-53, -20,+71,-63,+49,+69,+10,+42,+45,-3,-39,+94,-49,+58,+83,-53, +21,+37,-103,+25,+93,-51,+30,+36,-28,+32,+19,-31,+29,+62,-61, +40,-13,-6,+45,+31,+57,-36,+61,-35,+92,+70,-10,+21,-4,+94, +7,-15,-101,+40,-3,-46,-26,-3,-19,-44,+23,+20,+28,+65,+19, +55,+49,-44,+18,+99,+43,+64,+40,+15,+43,+30,-8,-13,+76,-3, +2,+12,-34,+21,-9,-3,-18,+36,-3,+0,-3,+0,+0,+0,-3, -7,-3,+92,+34,+83,+21,-11,+62,-8,-14,-8,+66,+43,-3,+8, -22,+19,+13,-76,+52,-28,+28,+32,+12,+30,+80,+35,-4,+88,+50, +84,+82,-24,+15,+66,-64,-18,+65,+99,+54,+2,-39,-7,-9,-51, -35,+71,-12,+5,+79,+0,+10,+56,-21,+21,+92,-55,+60,+66,-30, -3,+22,-44,-39,+95,-39,+56,+13,-40,-19,-16,-47,-50,+51,-41, +15,-32,-19,+2,+15,-5,-35,-5,-69,+40,+33,-38,-9,+45,-103, -80,-4,-84,-8,+22,-89,-43,-52,-11,-28,+55,-55,+65,+22,+0, +32,+30,-81,-61,+4,+34,+29,+80,-2,+14,+37,+38,-16,+43,-3, +0,-3,-70,-29,+19,-14,-7,+46,-7,+30,+67,-12,-7,+18,-55, -3,+98,-43,-14,+74,-58,-29,-26,+14,-13,+93,+60,+57,-41,-7, -61,-52,-103,-89,+85,-23,+70,+12,+6,+33,+45,-3,-38,+48,-22, +43,+72,-37,-1,+19,-103,-56,-30,-9,+55,+3,-20,+0,-3,-38, -29,+54,-49,+55,+23,+9,+50,+51,-30,-44,-36,-11,+56,+45,+51, +65,+52,-54,+36,+8,-97,+101,+0,-21,+21,+61,-37,-33,+70,+42, +103,+96,+84,+64,+37,+102,+4,-93,+33,+73,+84,+1,+59,+82,+0, +12,+41,-58,+81,+86,-14,+52,+88,-97,+51,+99,-61,+70,+53,-66, +25,+31,+0,-3,+0,-2,+23,+49,-31,+5,-4,-5,-5,-102,+0, +43,+46,-35,+3,+4,-41,-63,+29,+19,+52,+72,-60,+75,+77,-64, +68,-93,-91,+97,+105,+28,+80,+81,+99,+66,+28,+5,+8,+5,-47, +54,+99,-44,-14,+70,-44,+63,+69,+39,+58,+31,-21,+3,+69,-93, +88,+86,+11,+64,+35,-97,+10,+80,+0,+75,+97,+2,+37,+92,+0, +85,+63,-36,+78,+97,+3,+59,+3,+0,-101,+0,+73,+63,+103,-3, +49,+79,-1,-12,+98,+58,+91,+78,+35,+35,+98,-7,+45,+68,+0, +3,+0,+3,+3,+3,+0,-3,+0,+5,+5,+5,+3,+3,+3,+0, +2,+2,+0,+3,+0,-3,-3,-3,+0,-3,+0,-80,+76,+65,-99, +27,+18,+0,-68,+0,+95,+34,+0,-101,+48,+94,+7,-102,+93,-5, -21,-5,-102,+47,-5,-5,-6,+93,-91,+28,+32,+101,+31,+84,+0, -3,+0,+95,+75,+0,+94,+11,+94,-5,+93,-5,+97,+65,+0,+38, +18,+48,+75,-58,+71,-14,+57,+61,+22,+42,+73,+65,+5,+8,+3, +49,+91,+49,+57,+66,+9,+12,+0,-95,+103,+2,+68,+40,-15,+11, +19,+99,+31,+100,+101,+69,+64,+91,+101,+65,+28,-15,+44,+21,+10, +58,+46,-73,+2,+96,-73,+66,+91,+22,+20,+65,+11,+21,+37,-18, +54,+99,-92,+45,+103,+2,-1,+2,+0,+32,+99,+24,+14,+51,-3, -100,-100,+2,+16,+99,-1,+3,+43,+23,+15,+27,+9,+44,+28,+43, +41,+99,+82,-9,+41,-96,+12,+101,-9,+47,+45,-101,+16,+96,-95, +11,+2,-72,+33,+76,-44,+8,+59,+22,+81,+2,+55,+56,+5,+73, +15,+80,+0,+54,+55,-21,+45,+49,+93,-17,+95,+93,+96,+93,-51, +6,+95,+93,+21,+46,+31,+47,+93,-43,+59,+57,-5,+89,+93,+15, +56,+76,-1,+39,+62,+26,+93,+93,-33,+74,+83,-10,+30,+93,-51, +42,+61,-79,+43,-97,-34,+30,+14,-5,-96,-102,+0,-42,+0,+38, +49,-21,-24,+15,-100,-5,-1,-5,-8,+15,-8,-102,+89,+93,-34, +29,+33,-50,+26,+33,+98,-68,+98,+96,+70,+98,-18,+20,+67,-71, +21,+93,+91,+95,-6,-69,+52,-4,-6,-6,+93,+93,-34,+76,+35, +24,+41,-5,-8,-5,-3,+76,-1,-4,-27,+93,-8,-6,-6,+11, +65,+28,-27,-4,-30,-10,-6,+79,-4,+63,+10,+23,+67,+47,+36, +31,+70,-93,+46,+102,+63,+63,+83,+42,+58,+99,+91,+91,+0,-15, +8,+23,-15,-24,+23,+31,+44,+78,+41,+59,+76,+5,+32,+70,-31, +86,+85,+36,+69,+61,-73,+24,+59,+36,+25,+97,+7,+47,+71,+61, -10,+34,+0,+3,+0,+3,+3,+3,+0,-3,+0,+18,+47,+82,+19, +8,+72,-102,-102,+93,+61,+97,+0,-39,-2,+46,+10,+1,+91,-9, +37,+74,+7,+65,+81,+42,+14,+99,+34,+89,+18,+47,+49,+81,-7, +23,+37,+80,+47,+2,+24,+37,+36,+2,+11,+34,+0,+81,+78,+12, +51,+78,+54,+47,+63,-22,+31,+94,+13,+32,+47,-26,+27,+46,+44, +64,+82,+33,+35,+51,+36,+39,+86,-31,+52,+66,-20,+41,+96,-5, +89,+93,-31,+54,+65,-6,+18,+71,-49,-54,+93,-42,-1,+69,+24, +3,+85,-35,+40,+86,+0,+72,+43,+55,+62,+67,-11,-3,+29,+79, +67,+86,+28,+59,+72,+52,+45,+27,+0,+3,+0,+2,+26,+52,+31, -29,+91,+9,+26,+85,+28,+33,+82,+16,+22,+68,-9,+73,+86,+20, +39,+49,-12,+21,+61,-19,+72,-13,-29,+6,+55,-38,-18,+86,+4, +64,+57,+61,+57,+71,+0,+9,+71,+14,+41,+78,+37,+22,+62,+6, -2,+79,+49,+63,+60,+40,+33,+54,+27,+31,+56 ]; Line2 = [ +0,-5,-31,-23,+4,-18,+11,-13,-6,-13,-13,-21,-10,+1,-14, -1,+1,+3,+2,-2,-18,-18,+1,-20,+5,+14,-7,-10,-14,-43, -18,-4,-18,-3,-4,-13,-16,-21,-27,-19,-8,-12,+1,+3,+5, +2,+0,-24,-16,+1,-5,+5,+15,+4,+0,-6,-21,-7,-2,-27, -10,-4,-17,-20,-23,-24,-19,-8,-11,-3,+8,+2,-1,-6,-18, -28,+2,-12,+3,+16,-4,-10,-17,-45,-30,-19,-23,-3,-11,-13, -18,-22,-37,-24,-11,-15,-5,-5,+3,+0,-3,-17,-18,-1,-21, -15,-5,-11,-16,-22,-41,-30,-16,-17,-5,-6,-14,-18,-22,-26, -17,-9,-11,+0,-5,+7,+2,+0,-16,-17,-3,-1,+5,+24,+7, +0,-4,-14,-10,+0,-18,-6,-12,-18,-21,-23,-21,-21,-15,+2, +11,+14,+13,+7,+3,-8,-5,+4,+8,+10,+30,+5,-2,-4,-26, -26,-9,-12,+11,-6,-9,-10,-13,-12,-11,-1,-9,-4,-6,+3, +0,-6,-7,-18,-2,-14,-14,+2,-14,-20,-22,-37,-25,-8,-18, -5,-10,-17,-20,-24,-17,-20,-12,-6,+4,+12,+6,+6,+3,-16, -9,-2,-1,-8,+17,+7,+1,-6,-21,-20,-1,-13,+2,+0,-7, -10,-12,-15,-14,+0,-15,-3,+12,+2,+0,-8,-9,-17,+3,-12, +1,+27,-8,-13,-16,-44,-35,-14,-24,-4,-19,-16,-23,-24,-39, -22,-10,-22,-7,-9,-6,-7,-13,-33,-25,-6,-18,-10,-9,-15, -18,-25,-52,-40,-23,-18,-8,-6,-23,-22,-26,-33,-27,-19,-11, -3,-8,+3,+0,-2,-18,-19,-5,-8,-5,+13,+1,-2,-6,-18, -14,-12,-21,-7,-8,-16,-20,-25,-18,-21,-11,-20,-7,-6,-5, -6,-14,-17,-25,-9,-15,+1,+6,-12,-16,-21,-47,-40,-32,-28, -10,-30,-21,-22,-28,-36,-28,-20,-11,-2,-7,+0,-2,-5,-16, -16,-3,-17,-13,+0,-12,-18,-24,-40,-26,-20,-14,-5,-8,-13, -16,-22,-23,-17,-9,-10,+4,+1,+6,+5,+3,-8,-14,+5,+4, +18,+11,+6,+5,-1,-13,-8,+3,-15,+3,+0,-14,-17,-14,-11, -18,-4,+4,+14,+17,+13,+8,+14,-4,-9,-8,-5,+9,+30,+0, +3,-1,-29,-26,-8,-10,+5,+7,+4,-9,-13,-5,-25,+3,-10, +7,+6,+8,+5,+6,-8,-14,+2,-11,+4,+4,-13,-16,-29,-35, -25,-3,-18,+0,+2,-18,-19,-20,-13,-19,-5,+5,+13,+22,+13, +10,+12,-18,-9,-2,+10,+18,+34,+12,+3,+15,-34,+6,-4,+1, +11,+32,-5,-5,-5,-22,-2,+13,+13,+32,+8,+11,+4,+5,+8, +8,+1,-3,+9,+41,+0,-11,-6,-42,-15,-11,+4,+0,+22,-9, -17,-16,-33,-31,+9,-22,-17,+14,-3,-11,-26,-3,-25,-5,-29, +10,+24,-3,-28,-17,-36,-20,-27,-11,-5,-21,-26,-25,-16,-23, -24,-13,-9,+2,+3,+9,+7,+5,-14,-14,+4,-7,+20,+19,+15, +10,+0,-15,+0,-17,-11,+0,-1,-14,-18,-15,-8,-17,-5,+1, +6,+21,+5,-2,-6,+16,-25,+12,-14,+18,+12,-11,-18,-24,-45, -37,-39,-25,-11,-19,-17,-25,-37,-29,-55,-35,-10,+9,+0,+1, +6,+0,-15,-20,+2,-8,+2,+9,-9,-18,-20,-38,-22,-26,-19, -3,-8,-18,-16,-19,-15,-20,-10,-10,+0,+3,+10,+13,+8,-16, -8,+2,+23,+5,+39,+21,+15,-4,+23,-13,+20,-19,-2,-15,-16, -10,-14,-12,-20,-10,-4,+5,+35,+4,+10,+20,-31,+6,+19,+5, -17,+28,+5,-5,-11,-9,-5,-18,+0,-10,+31,-12,-20,-32,-37, +4,+15,-1,+23,+5,+9,+14,+20,-11,+0,+0,+0,+0,-15,-3, -7,-15,-29,-26,+23,-14,-4,+16,-14,-14,-25,-11,-24,+0,-8, +18,+26,+3,-1,+9,-13,-26,+12,+5,+25,+45,+14,-3,-2,-15, -5,+0,-9,-18,+40,-15,-26,-15,-34,-27,-1,-23,-9,+16,-3, -1,-1,+21,-15,-15,-22,+0,+33,-13,-23,-18,-45,-36,+9,-47, -9,-24,-28,-35,-36,-47,-17,-6,-37,-5,-7,-18,-10,+9,-31, -37,-20,-28,+17,+30,-23,-30,-28,-54,-46,+1,-45,-9,-33,-38, -40,-39,-45,-40,-30,-21,-3,-14,-4,+5,+0,-31,-25,-17,-2, +0,+8,-23,-5,-12,-42,-26,-2,-23,-20,+14,-34,-25,-29,-29, -42,-10,-43,-11,+15,-17,+8,+8,-41,-20,-19,-22,-25,-25,-15, -18,-27,-54,-46,-52,-47,-18,+21,-36,-40,-33,-53,-55,+2,-24, +7,-19,-3,-5,-8,-23,-22,+2,-29,-5,+3,-35,-30,-36,-51, -43,+8,-26,-18,-13,-21,-26,-31,-35,-33,-21,-13,-1,-8,+2, +2,+0,-14,-18,-7,-3,-7,+12,+8,+5,-6,-20,-20,-6,-21, -9,-13,-22,-21,-24,-24,-21,-13,+19,+15,-9,+0,+7,+5,-20, -2,+5,+6,+5,+26,-5,+1,-10,-45,-27,-13,-10,+17,+10,-19, -14,-25,-37,-20,-14,-8,+0,-10,+7,+4,-1,-11,-17,-1,-22, -23,-16,-12,-19,-25,-49,-42,-36,-24,-7,-13,-20,-21,-26,-21, -25,-14,-6,+12,-7,-1,+7,-6,-21,-25,-13,-19,+11,+15,-14, +3,-2,-48,+4,-22,-41,-6,+9,-16,-11,-15,-32,-20,+0,-7, +0,-21,-11,+3,-13,-30,-31,-14,+3,+9,+34,-8,-10,-23,-51, -17,+5,-22,-32,-54,-22,-22,-23,-44,-15,-21,-37,-15,-11,-13, -11,-19,-40,-55,+4,-45,-5,+0,-24,-24,-32,-53,-55,-25,-28, -14,-19,-19,-28,-33,-40,-23,-21,-13,+0,-7,+4,+3,-2,-12, -19,-5,-14,+3,+0,+2,-1,-9,-19,-24,-11,-19,-2,-8,-17, -20,-24,-22,-25,-16,-23,-12,-13,-4,-4,-7,-19,-24,+2,-12, -18,+6,-17,-19,-20,-44,-40,-20,-20,-13,-25,-18,-27,-24,-50, -23,-23,-10,+1,-7,+1,+0,-4,-18,-20,-10,-14,+0,-17,-17, -17,-24,-35,-33,-32,-20,-4,-11,-16,-17,-21,-23,-18,-8,+4, +23,+10,+22,+23,+18,+7,+1,+14,+17,+35,+39,+27,+26,+19,+3, +3,+16,-1,+15,+8,-1,-5,-2,-6,-8,+5,+21,+40,+45,+35, +33,+23,+6,+22,+26,+42,+45,+49,+30,+27,+23,+7,+26,+20,+16, +23,+3,+21,+12,+12,-13,-7,+7,+13,+21,+15,+17,+17,+13,+7, +3,+17,+1,+11,+16,+5,+3,-1,-5,-14,-22,+0,+13,+4,-2, -8,-5,+0,-7,+5,+21,+50,+45,+29,+36,+35,+4,+17,+39,+40, +53,+50,+44,+37,+42,+12,+35,+35,+6,+29,+18,-15,+14,+27,+17, -9,+7,+24,+44,+29,+27,+39,+45,+14,+8,+14,+20,+47,+34,+25, +21,+29,+0,+16,+2,-19,+33,+19,+18,+12,+22,+0,-21,+31,+6, +37,+12,+17,+12,+16,+0,+21,+13,+23,+37,-10,+17,+8,+9,-5, +15,+25,+10,+5,+4,+4,-6,+0,+13,-13,-1,+8,+22,+15,+24, +18,+12,+15,+6,+23,+29,+29,+45,+18,+24,+27,+20,+5,+35,-5, +8,+4,-2,-6,-9,+0,-10,+8,-10,+32,+12,+36,+15,+17,+38, +14,+11,+10,+34,+38,+1,+1,+9,-14,-7,-47,-23,+22,-31,-9, -9,-7,-17,-11,-8,+13,+24,+14,+21,+21,+18,+0,+0,+15,+9, +12,+13,-1,-5,-4,-28,-19,+0,-2,+11,+6,-1,-7,-6,+6, -7,+4,+24,+35,+39,+43,+40,+38,+19,+11,+22,+59,+51,+24,+49, +41,+22,+41,+39,+48,+20,+38,+15,+29,+24,+15,+28,+12,+22,+38, +53,+50,+50,+52,+33,+57,+34,+50,+54,+54,+53,+32,+43,+36,+22, +45,+43,+16,+36,+30,+13,+17,+24,+5,+15,+27,+14,+49,+45,+22, +37,+26,+17,+19,-26,+47,+29,+34,+5,+15,+5,+0,+8,-9,+29, +35,+42,+21,+13,+18,+5,+0,+29,+40,+44,+49,+42,+47,+39,+40, +30,+37,+42,+54,+53,+47,+45,+45,+43,+28,+45,+52,+45,-5,+27, +30,+13,+14,+26,+44,+14,+51,+34,+39,+44,+43,+33,+41,+42,+40, +45,+52,+37,+31,+34,+0,+33,+36,+7,+42,+25,-9,+27,+32,+0, +34,+29,+7,+45,+38,+13,+26,+28,+38,+12,+23,-6,+9,+22,+31, +16,-25,-22,-25,-3,+27,+29,+20,+0,+6,+5,-7,+6,+27,+21, +19,+16,+16,+18,+28,-4,+4,+16,+50,+42,+34,+23,+21,+28,+0, -15,+40,-24,+15,+38,+20,+2,-17,-20,-16,+2,-21,+48,-10,+26, +21,+13,+9,+24,+27,+32,+15,+22,+13,+14,+5,-43,+30,-10,-5, +34,-43,-3,-9,+3,-12,+0,+8,+10,+20,+13,+14,+14,+9,+3, +9,+15,-25,-23,+4,-10,-5,+6,-41,+3,+2,-1,+13,+24,+0, +0,-4,-3,-17,+3,+4,+18,+8,+10,+16,+9,+4,+0,+13,+24, +23,+15,+17,+17,+33,-3,-15,+8,-1,+15,+19,-4,-12,-14,+0, -13,+7,+24,+40,+18,+34,+33,+34,+31,+32,-13,+12,+31,-5,+22, +18,+18,-38,+40,+40,+38,+3,+0,+27,+0,-9,+0,+9,-22,+1, +11,+4,+16,+7,-3,+0,-1,+6,+0,+11,+38,+13,-4,-30,-17, +14,+26,-7,+8,+6,-10,-8,-5,-7,-8,+0,-23,+19,+3,+15, +17,+11,-22,+7,+29,+8,+41,+30,+24,+18,+30,-9,+31,+8,+19, -16,+0,-17,-6,+13,-38,+10,-5,+18,+30,+19,+6,+9,+12,+0, +22,+19,+19,-21,+25,-8,-13,+14,-33,-24,+11,+9,-8,-14,+20, -19,-12,-14,-54,-12,-16,+20,-31,+20,+8,-28,-31,-19,+13,-45, +31,-43,-24,-11,+6,-57,+21,+21,-7,+4,-15,-19,-30,-21,-6, -25,+1,-3,+12,+4,+15,+18,+3,+0,+2,+8,+24,+31,+42,+24, +24,+22,+4,+16,+36,-3,+14,+6,-9,-10,-20,-15,-13,-5,+24, +21,+4,+7,+16,-8,+22,-21,+11,+0,+13,+20,-4,-4,-4,-40, -33,+5,+12,+18,-15,-3,-6,-6,-4,-19,-33,+5,+14,+6,+7, +16,+8,-4,-8,+6,+18,+16,+24,+2,-6,-9,-19,-13,+2,-5, +8,+10,-5,-8,-11,-7,-11,+2,+8,+16,+18,+18,+13,+9,+5, +3,+8,+15,+21,+38,+21,+14,+16,+0,+8,+12,+0,+18,+9,+1, +0,-4,+1,+0,+2,+27,+19,+35,+27,+23,+6,+19,+12,+18,+17, +38,+39,+15,+13,+9,+0,+9,+7,+28,+26,+11,+1,+3,-3,-4, -6,+6,+7,+20,+12,+14,+17,+11,+10,+5,+15,+8,+14,+28,+5, +0,-7,-21,+0,-9,+1,+18,+3,+0,-2,-9,+2,-2,+4,+3, +18,+23,+24,+21,+6,+3,+14,+6,+26,+36,+33,+32,+13,+14,+3, +20,+24,+17,+17,+34,+12,+3,+2,+9,+5,+18,+9,+22,+45,+26, +16,+21,-20,+5,+33,+11,+28,+43,+13,+6,+3,+9,-1,+5,+8, +9,+12,+0,-8,-9,-18,-13,+12,-8,+19,+17,+7,+9,+2,-27, -6,+5,-16,+12,+13,+0,-6,-10,-13,+8,+7,-6,-4,-8,-1, -14,-18,-21,-7,-1,+13,+17,+13,+16,+16,+11,+9,+6,+18,-1, +34,+26,+21,+17,+11,-20,+20,+9,+2,+14,-3,+0,-6,-13,+2, -1,+0,+21,+16,+16,+12,+7,+2,+17,-26,+5,-19,+15,+28,-10, -2,-6,-27,+9,-27,+19,+5,-28,-12,-13,-23,+15,-19,-10,+18, +22,+18,+20,+18,+10,+4,+0,+13,+4,+16,+9,+5,-3,-13,-29, -8,-7,+5,+14,+8,-1,-5,-12,+1,-4,+5,+7,+17,+19,+18, +12,+16,-2,-1,+13,+29,+35,+22,+11,+11,+2,+10,-4,+29,+1, +9,+33,-5,-4,-9,+1,-6,+5,+13,+24,+42,+24,+15,+14,+24, +15,+26,+9,+23,+45,+11,+7,+6,-31,-2,+14,+4,+3,+30,+0, -6,-7,-17,-2,+14,+12,+12,+27,+21,+14,+11,-13,+0,+21,+0, +3,+28,+0,-6,-13,-5,-12,+13,+13,+13,+22,-5,-6,-13,-5, -9,+6,+13,+17,+23,+16,+12,+9,+4,-1,+19,+1,+15,+36,+6, +4,+6,-13,-11,+21,+12,+11,+18,+10,-4,-12,-1,-10,+5,+0, +8,+29,+8,+8,+3,+8,-6,+7,-6,+13,+34,+0,-5,-4,-37, -18,+7,-23,+0,+14,-13,-16,-12,-25,-23,-1,-16,+5,+9,-2, -5,-6,-22,-24,+2,-24,-5,+5,-11,-17,-22,-32,-27,-1,-9, +0,-4,-15,-21,-25,-30,-20,-16,-7,-2,-1,+4,-1,-7,-24, -29,-16,-9,+23,+5,+0,-4,-13,-23,-15,-16,-22,-15,-30,-21, -22,-30,-18,-25,-5,-10,+14,+9,+9,-7,-10,-24,-17,-11,-24, -14,-25,-6,-14,-22,-47,-28,-40,-34,-12,+6,-32,-25,-21,-44, -32,-18,-16,-8,-4,-7,-7,-13,-17,-20,-13,-26,-21,+6,-11, -22,-23,-49,-36,+1,-22,-6,-9,-21,-24,-28,-27,-24,-21,-8, -1,-2,+1,+0,-4,-7,-14,-1,-5,+3,+15,+7,-3,-9,-14, -14,-9,-15,-1,-14,-20,-23,-28,-21,-24,-16,-6,+13,+27,+4, +6,+2,-20,-5,-4,+14,+18,+13,+2,-3,-12,-13,-15,-9,-12, +3,+13,-7,-12,-22,-17,-15,-17,-12,-7,-9,+0,-3,-13,-16, -15,+2,-20,-9,-17,-21,-23,-30,-22,-29,-20,-17,-8,-20,-14, -25,-30,-17,-24,-16,-13,+4,+12,+9,+5,-3,-7,-13,-6,-23, +17,+24,-9,-2,-7,-26,-32,-1,-3,-5,-9,-12,-13,-22,-36, -25,-2,+10,+11,+22,+0,-2,-9,-6,-16,-12,-22,+3,+32,-8, -13,-12,-39,-36,-5,-27,-11,-12,-26,-24,-32,-27,-23,-18,-29, +0,-7,-4,-13,-23,-34,-37,-17,-34,-4,+3,-24,-22,-21,-50, -33,-29,-23,-13,-6,-27,-28,-32,-35,-24,-15,-8,-4,-5,+0, -3,-9,-15,-20,-7,-12,+4,+18,-4,-5,-13,-16,-25,-10,-15, -9,-5,-16,-24,-30,-24,-26,-15,-16,+1,+0,-9,-6,-18,-15, -16,-17,-16,-3,+5,-16,-21,-25,-42,-39,-19,-16,-13,-21,-24, -26,-32,-29,-33,-22,-6,-2,-6,-1,-7,-12,-10,-19,-2,-12, -10,-4,-18,-22,-28,-43,-31,-7,-13,-6,-11,-18,-22,-24,-22, -21,-13,+4,+20,+14,+13,+14,+8,+5,+5,+14,+14,+26,+22,+22, +17,+13,+1,+2,+11,+0,+19,+13,-5,-3,-1,+2,-7,+11,+23, +28,+39,+23,+18,+6,+7,-2,+29,+16,+45,+37,+9,+18,+19,-27, +12,+21,-4,+11,+29,+6,-2,-6,-10,-13,+10,+11,+24,+23,+17, +18,+18,+7,+4,+18,-15,+14,+16,-13,+1,-16,-29,-17,-6,+0, +18,+8,-1,-5,-7,+0,-5,+8,+20,+20,+26,+16,+28,+18,-12, -8,+29,+25,+47,+50,+34,+23,+26,+5,+19,+33,+9,+25,-13,-19, +4,-4,+23,+5,-11,+28,+22,+14,+27,+24,+33,-9,+1,+10,+17, +47,+42,+23,+18,+7,-7,-15,+9,+0,-4,+19,-8,+3,-12,+19, -14,+2,-8,+10,+11,+12,+12,+5,-38,+12,+24,+4,+0,+27,-4, +2,-11,-16,-19,+2,+4,+10,+11,-28,-9,-17,-16,+2,-7,+6, +19,+17,+15,+21,+15,+3,+2,+18,+34,+23,-26,+22,+27,+21,+24, +0,+25,+0,+11,+6,-2,-2,+2,+5,-1,+11,-2,+41,+13,+3, +13,+5,-19,-5,+24,+36,+9,+23,-12,+1,+2,-52,-20,+18,-9, -1,+13,-17,-6,-17,-6,+4,-10,+7,+21,+15,+15,+18,+13,+1, +2,+6,+4,+19,+15,-1,-1,-13,-20,+2,+9,+0,+15,+6,+0, -3,-2,+1,-10,+7,-4,+14,+16,+12,+17,+12,-18,+3,+11,+27, +29,+48,+26,+21,+29,+25,+20,+38,-4,+8,+8,-4,+0,-9,-9, -6,+4,+11,+45,+35,+34,+18,+24,+45,-4,+33,+30,+28,+45,+24, +20,+21,+6,+0,+27,-4,+29,+8,+16,-1,-1,-23,-22,+28,+7, +22,+35,+20,+14,+9,+0,-17,+25,+0,+0,+40,+0,-2,-16,-47, -2,+3,+15,+11,+36,-8,-12,-10,-1,-11,+27,-1,+12,+20,+16, +15,+7,+0,-8,+21,-17,+22,+43,+24,+12,+14,-32,-18,+27,-36, +14,+40,+19,-9,-9,-10,-13,+11,-2,-3,+2,+22,+12,+5,-19, -11,+9,+0,+22,+36,+6,+4,+7,-40,+9,+15,-17,+3,+11,-11, -14,-5,-20,+5,-2,-8,-6,-47,-14,-8,-27,-12,-39,+18,-30, -5,-10,-9,-19,-40,-54,-52,+23,-16,+5,+5,-17,-32,-19,-42, -20,-15,+6,+14,-22,+12,+8,-9,-24,-3,-6,+0,+2,-9,+9, +5,+13,-50,+23,+3,-34,+7,+26,+1,-8,-20,-29,-36,-11,-7, +19,+25,+23,+1,+7,-8,-27,+2,+17,-5,-3,-1,-4,-1,-42, +1,+23,-25,-10,+21,-26,-23,-29,-40,-25,+23,-4,+3,+0,+5, +1,-7,-24,-26,+9,-27,-23,+2,-29,-16,+1,-59,+8,+10,-14, -4,+2,-15,-20,-7,-17,-32,-7,-1,+10,+5,+6,+11,+2,-5, -4,+11,+4,+24,+22,+16,+15,+5,-10,-10,+4,-7,+10,+7,-18, -15,-16,-13,-13,-5,+20,+37,+7,+29,+22,+18,+16,+13,-11,+8, +37,+44,+16,+14,+5,-7,-1,+11,+8,+22,-5,+8,+0,-2,-6, +0,+0,+0,+8,+8,+12,+9,+0,-1,-5,+11,-7,+1,+2,-12, -8,-5,-14,-10,-11,-11,+10,-5,-7,-11,-15,-13,-16,+2,+5, +23,+7,+16,+20,+6,-24,+3,+10,+7,+43,+27,+10,+11,+14,+21, +15,+28,+2,-1,-22,-21,-1,-17,+10,-14,+0,+0,+7,+31,-10, +15,+12,-18,+9,+2,+2,+23,+29,+0,+1,-1,-14,-6,-2,-28, -13,-12,-9,-10,-18,-24,-21,+13,-20,-19,-8,+6,-2,-10,-24, -35,-10,-11,+4,+8,-13,-11,-18,-38,+2,+23,-23,-4,-33,-27, -20,-22,-21,-23,-16,+0,+13,+5,+8,+11,+4,+3,-5,+8,-6, +21,+29,+7,+12,+6,-21,+0,+27,-6,+9,+0,-13,-12,-16,-8, -14,+2,-5,+6,-1,+13,+6,-1,+23,-13,-7,+1,+8,+27,-13, -8,-16,-40,-30,-15,-20,-5,+1,-3,-19,-15,-21,-21,-16,+1, +13,+4,+8,+11,+5,-4,-10,+7,+4,+10,+3,-7,-9,-21,-24, -21,-7,-4,+10,+2,-8,-9,-13,-4,-8,+4 ]; Line3 = [ +0,-1,-10,-6,+0,-7,+2,-5,-3,-5,+1,-7,-6,+0,-5, +1,-3,-3,+0,-2,-10,-11,-7,-4,+0,+0,-3,-4,-2,-8, -7,-5,-5,+0,-2,-4,-5,-3,-7,-8,-4,-5,+3,-2,+1, +2,-1,-14,-10,-6,+0,+5,-2,+3,+0,-3,-3,-2,+0,-6, +2,-1,-13,-9,-8,-11,-10,-6,-5,+1,+6,-3,+0,+0,-6, -5,-3,-5,+0,-8,-3,-4,-9,-8,-8,-9,-12,-2,-2,-10, -7,-5,-12,-10,-10,-7,+1,-4,-3,-1,-5,-14,-11,-9,-6, +1,-3,-12,-6,-9,-8,-10,-12,-6,+0,-5,-5,-5,-7,-9, -7,-6,-2,+4,-4,+3,+2,+0,-10,-10,-6,+8,+5,+3,+1, +1,-2,-6,-5,-7,-4,+2,-4,-6,-9,-10,-9,-9,-8,+6, +8,+4,+4,+3,-4,+1,-6,+0,+3,+9,+2,+3,+0,-2,-7, -6,-8,-2,+0,-4,-5,-4,-7,-6,-8,-7,-3,+1,-3,+0, +0,-2,-10,-9,-7,-2,-6,-5,-11,-9,-13,-13,-17,-12,-4, +1,-2,-8,-10,-9,-8,-11,-8,+2,+4,+2,+1,+3,-1,-1, -3,-1,+4,+7,+3,-2,+0,-3,-1,-2,+2,+0,+8,+2,+0, -4,-11,+3,-6,+2,-2,+0,-2,-7,+0,-7,-6,-6,-3,-3, +1,-2,-8,-5,-3,-18,-10,-12,-4,-2,-19,-11,-9,-10,-17, -12,-9,-5,-2,-6,-4,-3,-8,-12,-13,-8,-7,-1,-5,-8, -7,-6,-19,-12,-11,-9,-4,-5,-12,-9,-12,-11,-12,-8,-4, +1,-5,-3,+0,-4,-13,-12,-8,+1,+3,-2,-3,-2,-3,-5, -7,-5,-7,-1,-7,-9,-10,-10,-12,-12,-9,-6,+0,-4,-3, -3,+0,-2,-10,-5,-5,+0,+0,-12,-5,-13,-26,-12,-11,-14, -7,-2,-11,-9,-3,-14,-11,-12,-6,-1,-6,-2,-2,-7,-14, -12,-9,-2,-1,+0,-5,-5,-8,-15,-12,-11,-6,-2,-7,-6, -6,-9,-11,-7,-7,-2,+2,-2,+2,+2,+0,-8,-11,-7,+2, +2,+4,+3,+0,-7,-1,-4,-4,-3,+0,-1,-9,-10,-10,-10, -11,-8,+12,+6,+13,+3,+4,+13,-9,-5,-5,+12,+6,+4,+8, +0,+1,+5,-10,-9,-10,+0,+9,-1,-3,+9,-3,-10,-15,-2, +0,+1,+3,-1,-2,-10,-12,-7,+5,-10,+2,-11,-10,-15,+1, -13,-15,-3,+0,+0,-9,-12,-9,-9,-12,-9,+10,+9,+4,+18, +7,+21,+13,-5,+4,-15,+13,+8,-5,+2,+14,-10,-10,+9,+9, +1,+8,-5,-6,-1,+1,-10,+10,+10,+4,+18,-6,+2,+3,+9, -6,+9,-7,+3,+6,+8,-2,+4,-20,-11,+5,+0,+0,-31,-4, -6,+17,+8,-5,-9,+2,+2,-3,+0,+0,-9,-1,-11,-5,+16, +0,+10,-1,-5,+3,-12,-12,-1,-5,+0,+2,-7,-10,+0,-10, -7,-4,-2,+2,-2,+0,+1,-2,-9,-12,-7,+1,+4,-3,+0, -2,-1,-3,-3,-7,-4,+0,-2,-8,-9,-11,-8,-11,-8,-15, -4,+5,-7,-8,+6,-24,-11,-18,-3,-5,+2,-13,-11,-10,-7, -14,-14,-8,-1,+10,-17,-13,-6,-26,-22,-18,-1,+1,+0,+1, -2,-8,-7,-11,-6,-9,-4,+5,-6,-11,-18,-8,-17,-17,-2, +0,+0,-10,-12,-18,-7,-12,-7,+4,+3,+5,+6,+1,-6,-1, -4,+1,+21,+13,-5,+10,-1,+3,+21,+7,+9,+7,+4,+8,-4, -5,-8,-3,-6,-1,+3,+6,+16,-10,+1,+9,-13,-10,-6,+4, +8,+9,-5,+0,-7,-5,-5,+27,-1,+0,+11,-6,-2,+0,-15, -11,-20,+4,+4,+6,+2,+6,+0,-8,-3,+2,+7,+0,+4,-2, -2,-8,+7,+0,+11,+5,+10,+14,-8,-7,+5,-5,-6,-1,-5, +1,+0,-19,+0,+1,+1,-10,+2,-8,+0,+14,-9,+0,+8,-14, -5,+4,+3,+5,+13,+8,-6,-1,+6,-9,+0,+2,+3,+3,-19, -1,-4,-9,-11,-5,-11,+0,+13,-9,-6,-2,+3,-12,-3,-19, -3,-28,-9,-10,-21,-27,-16,-7,-6,-3,-21,-5,-9,-15,+7, -14,-12,-16,-8,+2,-17,-8,-14,-24,-10,-10,-8,-6,-14,-5, -12,+8,-13,-11,-14,-5,-3,-7,-2,-3,-1,-14,-13,-11,+1, +0,-1,-1,-5,-19,-13,+0,-10,-8,-4,-6,-19,-17,-17,-16, -18,-13,-8,-8,-7,-12,-7,-18,-13,-12,-21,-7,+0,+17,-8, -7,-3,-14,-10,-25,-18,-13,-20,-11,-12,-15,-23,-19,-17,-9, -6,-10,-2,-5,-9,-17,-17,-14,-10,-13,+0,-7,-10,-13,+3, -13,-17,-9,-2,-5,-8,-12,-15,-12,-9,-9,-3,+1,-5,+0, +1,-2,-13,-11,-9,+3,+6,+1,+1,-1,-7,-7,-6,-6,-7, -1,-8,-11,-9,-12,-12,-12,-11,+7,-1,+0,-5,+2,-9,-2, -10,-3,-6,+3,+8,+9,-1,-6,-3,-9,-2,-10,-2,-8,+11, -6,-11,-4,-12,-17,-4,+0,-4,+1,-1,-5,-11,-11,-8,-6, -4,-10,-17,-10,-17,-17,-18,-26,-5,+0,-3,-13,-12,-13,-12, -12,-10,-1,+0,+3,+10,+0,+0,-1,-10,-6,-4,+8,-9,+10, -1,+7,-15,-11,+11,-7,+4,-2,+2,-8,-10,-2,-12,+3,+5, +0,-1,-2,+0,-14,-11,-5,+5,-21,-3,+4,+7,-6,+3,-31, -16,-2,-20,-4,-25,-19,-12,-12,-14,-13,-12,-9,+1,-15,-16, -8,+8,-17,-22,-10,-22,-6,-5,-9,-10,-3,+1,-19,-11,-14, -6,-2,-17,-11,-10,-20,-13,-11,-4,+0,-6,-1,-1,-6,-13, -12,-10,-2,+3,-6,-1,-3,-12,-8,-6,-15,-7,-2,-7,-9, -11,-14,-13,-12,-10,+3,+0,-2,-5,-4,-2,-5,-7,+1,-14, -1,-7,-5,-8,-10,-19,-11,-18,-10,-9,-5,-11,-12,-17,-14, -13,-9,-5,-1,-5,-3,-4,-10,-13,-12,-10,-6,-3,-5,-7, -7,-14,-20,-9,-14,-7,-2,-5,-8,-7,-11,-11,-8,-6,+8, +11,+10,+14,+11,+11,+0,-2,+3,+14,+12,+17,+17,+9,+10,+1, +5,+7,+5,+7,+7,-3,-4,-2,-1,-5,+0,+21,+20,+20,+9, +11,+18,+13,+4,+6,+25,+13,+26,+11,+7,+6,-5,+0,+18,+12, +10,+9,+5,+2,+5,+4,+3,+4,+8,+12,+7,+13,+8,+8,+4, -2,+1,+0,+5,+13,+4,-2,-1,-13,-7,-8,+6,+9,+9,-2, -5,-4,+0,-6,-1,+17,+14,+20,+8,+14,-2,+17,+13,+5,+18, +23,+22,+14,+12,+10,+11,+16,+5,+3,+26,+9,+1,+4,-22,-1, +0,-1,+27,+14,+32,+31,+17,+7,+34,+18,+13,+31,+27,+34,+15, +7,+14,-4,+3,+17,+8,-8,+26,-9,-2,+9,+0,-1,+14,+8, +4,+2,+21,+6,-4,-7,+5,+9,-11,+15,+33,+5,+6,-3,-18, -7,-10,+6,+3,+16,+18,-4,-17,-4,-2,-7,+8,+13,+7,+15, +12,+12,+0,+1,+2,+14,+16,+13,+24,+11,+12,-5,+6,+13,+6, +8,+6,+5,-3,+1,+0,-4,-1,+14,+2,+2,+6,-3,-24,-27, -3,-9,-23,-6,+27,+10,-3,+11,-22,-21,+16,+3,-1,+2,-8, -6,+6,+1,-15,-5,+10,+12,+10,+10,+9,+8,+5,+0,+4,+4, +3,+18,-8,-4,+2,-7,-10,-12,+8,+10,+10,-4,-6,-4,+1, -5,+0,+20,+20,+17,+9,+15,+18,+8,+4,+11,-23,-3,+35,+18, +8,+23,+1,-5,+24,+6,+8,+17,+17,+3,-4,+7,+1,+14,+9, -1,+22,+27,+19,+32,-21,+8,+33,+4,+24,+4,+31,+8,+4,+23, +14,+28,-9,+12,+1,+31,+3,+9,+18,-9,+19,+14,+17,+13,-1, +13,+5,-5,-3,+8,+28,-7,-24,-13,-2,+20,+0,-1,+0,+8, -1,+16,+17,-2,-12,+13,-6,+7,+21,+19,+26,+21,+26,+11,+22, +4,+10,+32,+14,+4,+31,+8,+27,+28,+9,+16,+18,+7,+29,+14, +2,+12,+22,+8,+5,+12,+31,+34,+23,+18,+23,+34,+6,+25,-1, -3,+33,+4,+10,+12,+0,+13,+29,-27,+20,-5,-13,-2,+16,+4, +4,+11,+2,+3,+27,+10,+7,+31,-27,+2,+7,-11,+5,-11,+6, -8,+21,-23,+17,+30,-11,-5,+5,-10,+0,-25,+5,-7,-6,+9, +8,+13,+0,+5,+2,+4,+2,+1,+13,+13,-24,-15,+3,+12,+0, +4,-4,+4,+3,+10,-3,-5,+21,+5,-10,-1,-11,+15,+33,+9, +1,-24,+6,+10,+20,-11,+14,-11,-17,+0,-19,-28,+2,+20,+9, +10,+27,+2,-5,+30,-11,-5,-1,-3,+7,+18,-18,+6,+10,+0, +5,+1,+3,-21,-22,-25,-3,+11,-1,+0,-26,+0,+1,+11,-2, +0,+0,-1,-5,-1,+7,+13,+7,+16,+14,+13,-3,-1,+0,+19, +17,+17,+13,+14,+13,+0,+8,+11,+3,+7,+5,-4,-4,-7,-5, -8,-3,+19,+17,+9,-8,+12,+18,-6,+8,+16,+30,-7,+29,+22, +10,+23,+27,+13,+2,+3,+1,+18,-9,+2,+20,+7,-2,+7,+7, +11,+6,+11,+10,+9,+0,-2,+1,+6,+8,+10,+1,-1,-10,+5, -6,-6,+4,+10,+7,-9,-7,-7,-4,-7,-3,+3,+5,+9,-6, +2,-30,+3,+9,+1,-2,+13,+1,-30,+6,+16,-6,+11,-3,-19, +24,+18,-12,-4,-3,+27,-8,-25,+10,+11,+26,+25,+6,+17,+0, -31,+27,+25,+9,-5,+9,-5,+8,-34,-28,+24,+6,-9,-6,-31, -19,-17,-34,-25,-14,-2,+2,+2,-10,-1,-28,+6,+10,-8,-9, +13,+27,-12,-2,+11,+21,-20,-16,+0,+9,+7,-32,-2,-32,-13, -5,-24,+9,+13,+9,+15,+13,+12,+0,+0,+3,+22,+14,+16,+16, +14,+9,-4,+14,+14,+6,+9,+7,+2,-2,-3,+0,-3,-1,+3, +1,+16,+15,+1,-2,-3,+2,+3,+12,-1,+5,-4,-2,-6,-22, -14,+15,-12,-13,+7,-2,-5,+6,-17,-2,-7,+9,+13,+10,+7, +10,+9,+3,+0,+4,+6,+1,+11,-8,-5,-1,-8,-5,-12,+5, +8,+9,-4,-7,-6,+0,-5,-1,+9,+8,+11,+11,+6,+8,+4, +0,+5,+11,+8,+18,+13,+5,+9,+2,-6,+6,+8,+10,+13,+0, +0,+1,+4,-2,+2,+13,+17,-2,+20,+12,+16,+32,+21,+2,+21, +5,+11,+24,+4,+13,+10,+1,+19,+15,+7,-30,+6,-1,-23,-18, +0,-1,+9,+13,+12,+16,+8,+8,+9,-2,+6,+5,+8,+2,+8, -1,+1,-17,-1,+0,+6,+9,+12,+0,-4,-5,+2,-6,+0,+7, +11,+18,+16,+11,+16,+2,+13,+6,+7,+11,+32,+15,+10,+25,-2, +9,+28,+14,+17,+18,+20,-4,+23,+8,-9,+6,+17,+19,+7,+27, +11,+21,+31,+3,+13,+10,+9,+23,+21,+3,+14,+13,-4,+19,+7, +4,+17,+0,-7,+3,+9,-14,-8,-2,-11,-24,+28,+5,-7,+9, +6,-6,+10,+6,-24,-7,+0,+7,-31,-18,+27,-12,+1,-2,-6, +0,-12,-5,-2,-3,+6,+9,+8,+18,+9,+8,-2,-2,+2,-3, +19,+5,+10,+13,+21,+3,+0,+20,+3,+8,+9,+0,-2,-4,-5, -5,+1,+24,-2,-4,+2,+0,-7,+12,-9,-9,-5,-8,+31,-2, -2,-5,-14,-15,+6,-3,+5,-28,-20,-8,+5,-1,+8,-19,+4, +11,+8,+10,+6,-4,+4,-8,+2,-4,+4,+10,+7,-5,-13,-17, -9,-15,+3,+9,+9,+0,-7,-4,+3,-10,-2,+9,+7,+10,+12, +5,+9,+8,-7,+5,+12,+7,+23,+28,+12,+9,+25,+3,+15,+12, +6,+13,-7,-2,+0,+8,-7,+5,+6,+9,+10,+11,+8,+25,+12, +14,+15,+28,+17,+27,+25,+3,+6,-6,+8,+10,+20,+1,+16,+7, -3,+1,-5,+7,+19,+9,+17,+12,-8,+11,+21,-1,-1,-2,-15, +2,+12,+0,-3,-17,+13,-19,-20,+8,+11,+9,-8,-3,-8,-4, -12,-1,+0,+5,+6,-5,+12,+13,+4,+1,+9,-22,+8,+4,-4, +3,+6,+17,-7,-5,-6,+13,+23,+2,-2,+1,-10,-6,+3,+10, -7,+14,-12,+8,+14,-9,+4,+22,+6,+9,+12,+0,-1,+6,-4, -2,+9,+7,-8,+8,-21,-3,+4,-15,+3,-8,-17,-9,+11,-14, -3,-5,-22,-10,+1,-14,+5,-19,-25,-9,-1,-31,-3,+17,-10, -8,-6,-24,-13,-11,-11,-10,-10,-3,+1,-1,+1,+3,+1,-16, -15,-4,-3,+1,+20,+0,-3,-17,+15,-8,+10,+0,+0,-10,-10, -13,-29,-24,-17,-6,+7,-10,-3,-16,+2,+7,+30,+3,+6,-6, +9,+21,+4,-2,-1,-31,-14,+17,-13,+5,+11,-15,-6,+10,-14, -3,-14,-1,-1,+2,-20,-1,-13,-13,-18,-10,-26,-10,+11,-28, -9,-1,-18,-13,-17,-5,-3,-1,-13,-8,-22,-17,-14,-9,+0, +3,-2,-1,+2,+1,-7,-10,-8,+5,+2,-4,+20,+3,+0,+18, -8,-1,-4,-1,-7,-10,-10,-17,-10,-12,-9,+5,+16,-22,-10, +4,+23,+10,-1,+1,+28,+5,+12,+14,+3,+1,-10,-1,-19,+1, +0,-3,-28,-11,-13,-21,-10,-2,-4,-1,+1,+0,+0,-4,-11, -11,-7,-1,-2,+21,+8,-8,-29,+1,-17,-4,-2,-3,-3,-16, -10,-21,-13,-14,-11,+11,+5,+5,+6,+3,-23,-15,+9,+10,+26, +12,+9,+16,+3,+1,-9,+0,-2,+2,+7,+20,-2,-7,-13,-6, -11,+1,+0,+2,+9,+0,+7,+3,-25,+17,+23,+15,+19,+16,+12, +1,+4,-23,-21,-7,-25,+6,-17,-27,-10,-1,-31,-12,-11,+0, +5,+6,+10,-4,+5,+8,-6,-8,-4,+10,+30,-11,-5,+10,-27, -15,-11,-7,-3,+6,-20,-3,-2,-9,-17,-11,-4,+1,-4,+0, +3,-5,-15,-9,-10,-7,+2,-12,-1,-1,-8,+0,+5,-11,-8, +0,-7,-18,-9,-21,-15,-13,-12,+9,-10,-17,-6,-1,-12,+6, +0,-2,+17,+19,-25,+5,-3,-11,-21,+8,+1,-11,-18,-32,-16, -12,-2,-8,-10,-20,-7,+0,-4,+1,-3,-4,-16,-18,-10,-7, -6,+0,-12,-7,-22,-9,-15,-25,-8,-2,-6,-11,-9,-14,-14, -11,-11,+3,+7,+3,+8,+6,+5,-5,-7,-4,+5,+9,+11,+5, +6,+5,+0,+1,+0,+0,+2,+0,-3,-6,-8,-8,-9,-7,+10, +14,+5,+7,+9,+6,+0,+4,+3,-1,+8,+10,+10,+5,+9,+11, +2,-6,-2,+5,+1,+12,-1,+10,-6,-6,-1,+2,+5,+2,+2, +4,+2,-4,-7,-4,-2,-5,+1,-8,-6,-4,-8,-11,-8,+0, +3,+3,-6,-8,-10,-6,-10,-6,+7,+10,+6,+11,+14,+2,+12, -5,+3,+22,+18,+33,+13,+12,+15,-9,-6,+13,+13,+8,+16,+3, +0,+1,-3,-3,-2,+16,+20,+13,+25,+4,+13,-6,+9,+5,-3, +19,+25,-7,+7,+22,+27,-5,+7,+0,+0,+27,-7,-3,+23,-8, +5,+1,+4,+10,-9,-1,+2,-9,-3,-18,-9,+3,+1,+20,-20, -3,+6,+9,-21,+16,+2,+10,+3,-15,-5,-2,-12,+1,-2,+3, +7,+1,+8,+7,+6,-6,-7,-4,+10,+8,+8,+0,+6,-2,-4, +2,+3,+0,+4,+1,-3,-7,-7,-6,-8,-7,+4,+7,+9,-2, +0,-6,+19,-5,-9,-24,-3,+7,+6,-7,+1,-18,-12,-28,-13, -9,-8,-14,-8,-8,-3,-10,-2,+4,+7,+4,+4,+4,+2,-3, -6,-3,-5,-7,+1,-12,-9,-10,-6,-14,-10,+0,+3,+4,-8, -9,-10,-5,-10,-5,+8,+6,+7,+7,+2,+6,-6,-4,+0,+7, +10,+24,+26,+6,+15,-3,+9,+20,+5,+9,+11,+4,-7,-1,-4, -6,+3,-4,+22,+5,+4,+7,+28,+9,+9,+13,+28,+16,+16,+14, +4,-5,+11,+4,+13,-3,-16,-3,-10,+2,-2,+11,+11,+6,+5, +6,+13,+1,+2,+20,-6,-7,+3,+0,-7,-4,+15,+0,+10,-28, -10,-1,+2,-5,+14,-5,-5,-11,+0,-15,-1,+8,+14,+18,-17, +5,+19,-12,-9,-6,+16,+7,+28,+6,+5,+10,+11,+27,+13,+24, +3,+2,+5,-8,-19,+23,-2,-5,-9,+21,+17,-15,+3,+19,-25, +5,+7,+0,+11,+29,-6,+0,+9,+1,-3,+24,+3,+7,+24,-10, -12,-7,-31,-2,+4,-13,+6,+16,-28,-3,+6,-30,-14,-28,-28, -4,+20,-28,-9,+17,-4,-25,-2,+1,-12,+15,-21,-11,+1,-25, -18,-17,-3,+2,-8,+7,-1,+0,-22,-15,-8,+0,-1,+0,+3, +0,-20,-13,+11,-1,-10,-1,-6,+3,-12,-4,-14,-26,-14,-13, +4,-10,-26,-4,+27,+2,-1,+16,-16,+8,+30,+22,-5,+17,-32, -10,-2,-22,+15,-16,-7,-11,-11,-18,-11,-19,-6,-3,-12,-5, -8,-15,-19,-17,-10,-7,-21,-26,-12,-12,-17,+23,-17,-2,-5, -2,-12,-11,-11,-25,-14,-14,-12,+1,+5,+0,+7,+6,+2,-9, -8,-7,+6,+9,+14,+1,+7,+5,+3,-1,+3,-4,+1,-3,-4, -8,-9,-10,-11,-8,+9,+9,-1,+0,+5,+6,+2,+10,-2,+13, +6,+5,+17,+5,+3,-2,+0,-5,-4,-2,-25,+2,+2,+1,-8, +3,-6,+0,+4,-1,+4,+3,+1,-7,-8,-7,-5,-4,-1,-9, -6,-6,-14,-13,-14,-2,+2,-1,-9,-9,-12,-8,-10,-8,+3, -3,+4,-9,+6,-1,-3,-15,-1,+13,+8,+19,-7,+5,+19,+11, -20,+6,-4,+15,+7,-24,-7,-2,-14,-17,-6,+0,-5,+14,+0, +2,-8,-10,-9,+1,+9,-2,+11,-10,+0,-8,-12,-7,+4,-16, -10,-14,-17,-9,-11,-27,-12,-9,-9,-7,-5,-5,-6,-19,-19, -18,-2,+4,-3,-1,-6,-10,-14,-9,-17,-19,-10,-12,-7,-13, -12,-20,-21,-9,-19,+0,+4,-1,+4,+4,+0,-9,-9,-6,+3, +5,+7,+3,+5,-1,-9,-1,-1,-3,+2,-3,-6,-8,-11,-8, -10,-8,-3,+1,-7,-11,-2,-3,-3,-4,-2,-8,+5,-6,+0, -4,-10,-21,-14,-17,-7,-10,-24,-7,-8,-11,-17,-11,-19,-1, +3,+0,+0,+2,-2,-7,-7,-5,-8,-4,-1,-9,-6,-9,-20, -9,-12,-3,+2,-1,-9,-7,-11,-8,-6,-6 ]; Line4 = [ +0,-1,-10,-6,+0,-7,+2,-5,-3,-5,+1,-7,-6,+0,-5, +1,-3,-3,+0,-2,-10,-11,-7,-4,+0,+0,-3,-4,-2,-8, -7,-5,-5,+0,-2,-4,-5,-3,-7,-8,-4,-5,+3,-2,+1, +2,-1,-14,-10,-6,+0,+5,-2,+3,+0,-3,-3,-2,+0,-6, +2,-1,-13,-9,-8,-11,-10,-6,-5,+1,+6,-3,+0,+0,-6, -5,-3,-5,+0,-8,-3,-4,-9,-8,-8,-9,-12,-2,-2,-10, -7,-5,-12,-10,-10,-7,+1,-4,-3,-1,-5,-14,-11,-9,-6, +1,-3,-12,-6,-9,-8,-10,-12,-6,+0,-5,-5,-5,-7,-9, -7,-6,-2,+4,-4,+3,+2,+0,-10,-10,-6,+8,+5,+3,+1, +1,-2,-6,-5,-7,-4,+2,-4,-6,-9,-10,-9,-9,-8,+6, +8,+4,+4,+3,-4,+1,-6,+0,+3,+9,+2,+3,+0,-2,-7, -6,-8,-2,+0,-4,-5,-4,-7,-6,-8,-7,-3,+1,-3,+0, +0,-2,-10,-9,-7,-2,-6,-5,-11,-9,-13,-13,-17,-12,-4, +1,-2,-8,-10,-9,-8,-11,-8,+2,+4,+2,+1,+3,-1,-1, -3,-1,+4,+7,+3,-2,+0,-3,-1,-2,+2,+0,+8,+2,+0, -4,-11,+3,-6,+2,-2,+0,-2,-7,+0,-7,-6,-6,-3,-3, +1,-2,-8,-5,-3,-18,-10,-12,-4,-2,-19,-11,-9,-10,-17, -12,-9,-5,-2,-6,-4,-3,-8,-12,-13,-8,-7,-1,-5,-8, -7,-6,-19,-12,-11,-9,-4,-5,-12,-9,-12,-11,-12,-8,-4, +1,-5,-3,+0,-4,-13,-12,-8,+1,+3,-2,-3,-2,-3,-5, -7,-5,-7,-1,-7,-9,-10,-10,-12,-12,-9,-6,+0,-4,-3, -3,+0,-2,-10,-5,-5,+0,+0,-12,-5,-13,-26,-12,-11,-14, -7,-2,-11,-9,-3,-14,-11,-12,-6,-1,-6,-2,-2,-7,-14, -12,-9,-2,-1,+0,-5,-5,-8,-15,-12,-11,-6,-2,-7,-6, -6,-9,-11,-7,-7,-2,+2,-2,+2,+2,+0,-8,-11,-7,+2, +2,+4,+3,+0,-7,-1,-4,-4,-3,+0,-1,-9,-10,-10,-10, -11,-8,+12,+6,+13,+3,+4,+13,-9,-5,-5,+12,+6,+4,+8, +0,+1,+5,-10,-9,-10,+0,+9,-1,-3,+9,-3,-10,-15,-2, +0,+1,+3,-1,-2,-10,-12,-7,+5,-10,+2,-11,-10,-15,+1, -13,-15,-3,+0,+0,-9,-12,-9,-9,-12,-9,+10,+9,+4,+18, +7,+21,+13,-5,+4,-15,+13,+8,-5,+2,+14,-10,-10,+9,+9, +1,+8,-5,-6,-1,+1,-10,+10,+10,+4,+18,-6,+2,+3,+9, -6,+9,-7,+3,+6,+8,-2,+4,-20,-11,+5,+0,+0,-31,-4, -6,+17,+8,-5,-9,+2,+2,-3,+0,+0,-9,-1,-11,-5,+16, +0,+10,-1,-5,+3,-12,-12,-1,-5,+0,+2,-7,-10,+0,-10, -7,-4,-2,+2,-2,+0,+1,-2,-9,-12,-7,+1,+4,-3,+0, -2,-1,-3,-3,-7,-4,+0,-2,-8,-9,-11,-8,-11,-8,-15, -4,+5,-7,-8,+6,-24,-11,-18,-3,-5,+2,-13,-11,-10,-7, -14,-14,-8,-1,+10,-17,-13,-6,-26,-22,-18,-1,+1,+0,+1, -2,-8,-7,-11,-6,-9,-4,+5,-6,-11,-18,-8,-17,-17,-2, +0,+0,-10,-12,-18,-7,-12,-7,+4,+3,+5,+6,+1,-6,-1, -4,+1,+21,+13,-5,+10,-1,+3,+21,+7,+9,+7,+4,+8,-4, -5,-8,-3,-6,-1,+3,+6,+16,-10,+1,+9,-13,-10,-6,+4, +8,+9,-5,+0,-7,-5,-5,+27,-1,+0,+11,-6,-2,+0,-15, -11,-20,+4,+4,+6,+2,+6,+0,-8,-3,+2,+7,+0,+4,-2, -2,-8,+7,+0,+11,+5,+10,+14,-8,-7,+5,-5,-6,-1,-5, +1,+0,-19,+0,+1,+1,-10,+2,-8,+0,+14,-9,+0,+8,-14, -5,+4,+3,+5,+13,+8,-6,-1,+6,-9,+0,+2,+3,+3,-19, -1,-4,-9,-11,-5,-11,+0,+13,-9,-6,-2,+3,-12,-3,-19, -3,-28,-9,-10,-21,-27,-16,-7,-6,-3,-21,-5,-9,-15,+7, -14,-12,-16,-8,+2,-17,-8,-14,-24,-10,-10,-8,-6,-14,-5, -12,+8,-13,-11,-14,-5,-3,-7,-2,-3,-1,-14,-13,-11,+1, +0,-1,-1,-5,-19,-13,+0,-10,-8,-4,-6,-19,-17,-17,-16, -18,-13,-8,-8,-7,-12,-7,-18,-13,-12,-21,-7,+0,+17,-8, -7,-3,-14,-10,-25,-18,-13,-20,-11,-12,-15,-23,-19,-17,-9, -6,-10,-2,-5,-9,-17,-17,-14,-10,-13,+0,-7,-10,-13,+3, -13,-17,-9,-2,-5,-8,-12,-15,-12,-9,-9,-3,+1,-5,+0, +1,-2,-13,-11,-9,+3,+6,+1,+1,-1,-7,-7,-6,-6,-7, -1,-8,-11,-9,-12,-12,-12,-11,+7,-1,+0,-5,+2,-9,-2, -10,-3,-6,+3,+8,+9,-1,-6,-3,-9,-2,-10,-2,-8,+11, -6,-11,-4,-12,-17,-4,+0,-4,+1,-1,-5,-11,-11,-8,-6, -4,-10,-17,-10,-17,-17,-18,-26,-5,+0,-3,-13,-12,-13,-12, -12,-10,-1,+0,+3,+10,+0,+0,-1,-10,-6,-4,+8,-9,+10, -1,+7,-15,-11,+11,-7,+4,-2,+2,-8,-10,-2,-12,+3,+5, +0,-1,-2,+0,-14,-11,-5,+5,-21,-3,+4,+7,-6,+3,-31, -16,-2,-20,-4,-25,-19,-12,-12,-14,-13,-12,-9,+1,-15,-16, -8,+8,-17,-22,-10,-22,-6,-5,-9,-10,-3,+1,-19,-11,-14, -6,-2,-17,-11,-10,-20,-13,-11,-4,+0,-6,-1,-1,-6,-13, -12,-10,-2,+3,-6,-1,-3,-12,-8,-6,-15,-7,-2,-7,-9, -11,-14,-13,-12,-10,+3,+0,-2,-5,-4,-2,-5,-7,+1,-14, -1,-7,-5,-8,-10,-19,-11,-18,-10,-9,-5,-11,-12,-17,-14, -13,-9,-5,-1,-5,-3,-4,-10,-13,-12,-10,-6,-3,-5,-7, -7,-14,-20,-9,-14,-7,-2,-5,-8,-7,-11,-11,-8,-6,+8, +11,+10,+14,+11,+11,+0,-2,+3,+14,+12,+17,+17,+9,+10,+1, +5,+7,+5,+7,+7,-3,-4,-2,-1,-5,+0,+21,+20,+20,+9, +11,+18,+13,+4,+6,+25,+13,+26,+11,+7,+6,-5,+0,+18,+12, +10,+9,+5,+2,+5,+4,+3,+4,+8,+12,+7,+13,+8,+8,+4, -2,+1,+0,+5,+13,+4,-2,-1,-13,-7,-8,+6,+9,+9,-2, -5,-4,+0,-6,-1,+17,+14,+20,+8,+14,-2,+17,+13,+5,+18, +23,+22,+14,+12,+10,+11,+16,+5,+3,+26,+9,+1,+4,-22,-1, +0,-1,+27,+14,+32,+31,+17,+7,+34,+18,+13,+31,+27,+34,+15, +7,+14,-4,+3,+17,+8,-8,+26,-9,-2,+9,+0,-1,+14,+8, +4,+2,+21,+6,-4,-7,+5,+9,-11,+15,+33,+5,+6,-3,-18, -7,-10,+6,+3,+16,+18,-4,-17,-4,-2,-7,+8,+13,+7,+15, +12,+12,+0,+1,+2,+14,+16,+13,+24,+11,+12,-5,+6,+13,+6, +8,+6,+5,-3,+1,+0,-4,-1,+14,+2,+2,+6,-3,-24,-27, -3,-9,-23,-6,+27,+10,-3,+11,-22,-21,+16,+3,-1,+2,-8, -6,+6,+1,-15,-5,+10,+12,+10,+10,+9,+8,+5,+0,+4,+4, +3,+18,-8,-4,+2,-7,-10,-12,+8,+10,+10,-4,-6,-4,+1, -5,+0,+20,+20,+17,+9,+15,+18,+8,+4,+11,-23,-3,+35,+18, +8,+23,+1,-5,+24,+6,+8,+17,+17,+3,-4,+7,+1,+14,+9, -1,+22,+27,+19,+32,-21,+8,+33,+4,+24,+4,+31,+8,+4,+23, +14,+28,-9,+12,+1,+31,+3,+9,+18,-9,+19,+14,+17,+13,-1, +13,+5,-5,-3,+8,+28,-7,-24,-13,-2,+20,+0,-1,+0,+8, -1,+16,+17,-2,-12,+13,-6,+7,+21,+19,+26,+21,+26,+11,+22, +4,+10,+32,+14,+4,+31,+8,+27,+28,+9,+16,+18,+7,+29,+14, +2,+12,+22,+8,+5,+12,+31,+34,+23,+18,+23,+34,+6,+25,-1, -3,+33,+4,+10,+12,+0,+13,+29,-27,+20,-5,-13,-2,+16,+4, +4,+11,+2,+3,+27,+10,+7,+31,-27,+2,+7,-11,+5,-11,+6, -8,+21,-23,+17,+30,-11,-5,+5,-10,+0,-25,+5,-7,-6,+9, +8,+13,+0,+5,+2,+4,+2,+1,+13,+13,-24,-15,+3,+12,+0, +4,-4,+4,+3,+10,-3,-5,+21,+5,-10,-1,-11,+15,+33,+9, +1,-24,+6,+10,+20,-11,+14,-11,-17,+0,-19,-28,+2,+20,+9, +10,+27,+2,-5,+30,-11,-5,-1,-3,+7,+18,-18,+6,+10,+0, +5,+1,+3,-21,-22,-25,-3,+11,-1,+0,-26,+0,+1,+11,-2, +0,+0,-1,-5,-1,+7,+13,+7,+16,+14,+13,-3,-1,+0,+19, +17,+17,+13,+14,+13,+0,+8,+11,+3,+7,+5,-4,-4,-7,-5, -8,-3,+19,+17,+9,-8,+12,+18,-6,+8,+16,+30,-7,+29,+22, +10,+23,+27,+13,+2,+3,+1,+18,-9,+2,+20,+7,-2,+7,+7, +11,+6,+11,+10,+9,+0,-2,+1,+6,+8,+10,+1,-1,-10,+5, -6,-6,+4,+10,+7,-9,-7,-7,-4,-7,-3,+3,+5,+9,-6, +2,-30,+3,+9,+1,-2,+13,+1,-30,+6,+16,-6,+11,-3,-19, +24,+18,-12,-4,-3,+27,-8,-25,+10,+11,+26,+25,+6,+17,+0, -31,+27,+25,+9,-5,+9,-5,+8,-34,-28,+24,+6,-9,-6,-31, -19,-17,-34,-25,-14,-2,+2,+2,-10,-1,-28,+6,+10,-8,-9, +13,+27,-12,-2,+11,+21,-20,-16,+0,+9,+7,-32,-2,-32,-13, -5,-24,+9,+13,+9,+15,+13,+12,+0,+0,+3,+22,+14,+16,+16, +14,+9,-4,+14,+14,+6,+9,+7,+2,-2,-3,+0,-3,-1,+3, +1,+16,+15,+1,-2,-3,+2,+3,+12,-1,+5,-4,-2,-6,-22, -14,+15,-12,-13,+7,-2,-5,+6,-17,-2,-7,+9,+13,+10,+7, +10,+9,+3,+0,+4,+6,+1,+11,-8,-5,-1,-8,-5,-12,+5, +8,+9,-4,-7,-6,+0,-5,-1,+9,+8,+11,+11,+6,+8,+4, +0,+5,+11,+8,+18,+13,+5,+9,+2,-6,+6,+8,+10,+13,+0, +0,+1,+4,-2,+2,+13,+17,-2,+20,+12,+16,+32,+21,+2,+21, +5,+11,+24,+4,+13,+10,+1,+19,+15,+7,-30,+6,-1,-23,-18, +0,-1,+9,+13,+12,+16,+8,+8,+9,-2,+6,+5,+8,+2,+8, -1,+1,-17,-1,+0,+6,+9,+12,+0,-4,-5,+2,-6,+0,+7, +11,+18,+16,+11,+16,+2,+13,+6,+7,+11,+32,+15,+10,+25,-2, +9,+28,+14,+17,+18,+20,-4,+23,+8,-9,+6,+17,+19,+7,+27, +11,+21,+31,+3,+13,+10,+9,+23,+21,+3,+14,+13,-4,+19,+7, +4,+17,+0,-7,+3,+9,-14,-8,-2,-11,-24,+28,+5,-7,+9, +6,-6,+10,+6,-24,-7,+0,+7,-31,-18,+27,-12,+1,-2,-6, +0,-12,-5,-2,-3,+6,+9,+8,+18,+9,+8,-2,-2,+2,-3, +19,+5,+10,+13,+21,+3,+0,+20,+3,+8,+9,+0,-2,-4,-5, -5,+1,+24,-2,-4,+2,+0,-7,+12,-9,-9,-5,-8,+31,-2, -2,-5,-14,-15,+6,-3,+5,-28,-20,-8,+5,-1,+8,-19,+4, +11,+8,+10,+6,-4,+4,-8,+2,-4,+4,+10,+7,-5,-13,-17, -9,-15,+3,+9,+9,+0,-7,-4,+3,-10,-2,+9,+7,+10,+12, +5,+9,+8,-7,+5,+12,+7,+23,+28,+12,+9,+25,+3,+15,+12, +6,+13,-7,-2,+0,+8,-7,+5,+6,+9,+10,+11,+8,+25,+12, +14,+15,+28,+17,+27,+25,+3,+6,-6,+8,+10,+20,+1,+16,+7, -3,+1,-5,+7,+19,+9,+17,+12,-8,+11,+21,-1,-1,-2,-15, +2,+12,+0,-3,-17,+13,-19,-20,+8,+11,+9,-8,-3,-8,-4, -12,-1,+0,+5,+6,-5,+12,+13,+4,+1,+9,-22,+8,+4,-4, +3,+6,+17,-7,-5,-6,+13,+23,+2,-2,+1,-10,-6,+3,+10, -7,+14,-12,+8,+14,-9,+4,+22,+6,+9,+12,+0,-1,+6,-4, -2,+9,+7,-8,+8,-21,-3,+4,-15,+3,-8,-17,-9,+11,-14, -3,-5,-22,-10,+1,-14,+5,-19,-25,-9,-1,-31,-3,+17,-10, -8,-6,-24,-13,-11,-11,-10,-10,-3,+1,-1,+1,+3,+1,-16, -15,-4,-3,+1,+20,+0,-3,-17,+15,-8,+10,+0,+0,-10,-10, -13,-29,-24,-17,-6,+7,-10,-3,-16,+2,+7,+30,+3,+6,-6, +9,+21,+4,-2,-1,-31,-14,+17,-13,+5,+11,-15,-6,+10,-14, -3,-14,-1,-1,+2,-20,-1,-13,-13,-18,-10,-26,-10,+11,-28, -9,-1,-18,-13,-17,-5,-3,-1,-13,-8,-22,-17,-14,-9,+0, +3,-2,-1,+2,+1,-7,-10,-8,+5,+2,-4,+20,+3,+0,+18, -8,-1,-4,-1,-7,-10,-10,-17,-10,-12,-9,+5,+16,-22,-10, +4,+23,+10,-1,+1,+28,+5,+12,+14,+3,+1,-10,-1,-19,+1, +0,-3,-28,-11,-13,-21,-10,-2,-4,-1,+1,+0,+0,-4,-11, -11,-7,-1,-2,+21,+8,-8,-29,+1,-17,-4,-2,-3,-3,-16, -10,-21,-13,-14,-11,+11,+5,+5,+6,+3,-23,-15,+9,+10,+26, +12,+9,+16,+3,+1,-9,+0,-2,+2,+7,+20,-2,-7,-13,-6, -11,+1,+0,+2,+9,+0,+7,+3,-25,+17,+23,+15,+19,+16,+12, +1,+4,-23,-21,-7,-25,+6,-17,-27,-10,-1,-31,-12,-11,+0, +5,+6,+10,-4,+5,+8,-6,-8,-4,+10,+30,-11,-5,+10,-27, -15,-11,-7,-3,+6,-20,-3,-2,-9,-17,-11,-4,+1,-4,+0, +3,-5,-15,-9,-10,-7,+2,-12,-1,-1,-8,+0,+5,-11,-8, +0,-7,-18,-9,-21,-15,-13,-12,+9,-10,-17,-6,-1,-12,+6, +0,-2,+17,+19,-25,+5,-3,-11,-21,+8,+1,-11,-18,-32,-16, -12,-2,-8,-10,-20,-7,+0,-4,+1,-3,-4,-16,-18,-10,-7, -6,+0,-12,-7,-22,-9,-15,-25,-8,-2,-6,-11,-9,-14,-14, -11,-11,+3,+7,+3,+8,+6,+5,-5,-7,-4,+5,+9,+11,+5, +6,+5,+0,+1,+0,+0,+2,+0,-3,-6,-8,-8,-9,-7,+10, +14,+5,+7,+9,+6,+0,+4,+3,-1,+8,+10,+10,+5,+9,+11, +2,-6,-2,+5,+1,+12,-1,+10,-6,-6,-1,+2,+5,+2,+2, +4,+2,-4,-7,-4,-2,-5,+1,-8,-6,-4,-8,-11,-8,+0, +3,+3,-6,-8,-10,-6,-10,-6,+7,+10,+6,+11,+14,+2,+12, -5,+3,+22,+18,+33,+13,+12,+15,-9,-6,+13,+13,+8,+16,+3, +0,+1,-3,-3,-2,+16,+20,+13,+25,+4,+13,-6,+9,+5,-3, +19,+25,-7,+7,+22,+27,-5,+7,+0,+0,+27,-7,-3,+23,-8, +5,+1,+4,+10,-9,-1,+2,-9,-3,-18,-9,+3,+1,+20,-20, -3,+6,+9,-21,+16,+2,+10,+3,-15,-5,-2,-12,+1,-2,+3, +7,+1,+8,+7,+6,-6,-7,-4,+10,+8,+8,+0,+6,-2,-4, +2,+3,+0,+4,+1,-3,-7,-7,-6,-8,-7,+4,+7,+9,-2, +0,-6,+19,-5,-9,-24,-3,+7,+6,-7,+1,-18,-12,-28,-13, -9,-8,-14,-8,-8,-3,-10,-2,+4,+7,+4,+4,+4,+2,-3, -6,-3,-5,-7,+1,-12,-9,-10,-6,-14,-10,+0,+3,+4,-8, -9,-10,-5,-10,-5,+8,+6,+7,+7,+2,+6,-6,-4,+0,+7, +10,+24,+26,+6,+15,-3,+9,+20,+5,+9,+11,+4,-7,-1,-4, -6,+3,-4,+22,+5,+4,+7,+28,+9,+9,+13,+28,+16,+16,+14, +4,-5,+11,+4,+13,-3,-16,-3,-10,+2,-2,+11,+11,+6,+5, +6,+13,+1,+2,+20,-6,-7,+3,+0,-7,-4,+15,+0,+10,-28, -10,-1,+2,-5,+14,-5,-5,-11,+0,-15,-1,+8,+14,+18,-17, +5,+19,-12,-9,-6,+16,+7,+28,+6,+5,+10,+11,+27,+13,+24, +3,+2,+5,-8,-19,+23,-2,-5,-9,+21,+17,-15,+3,+19,-25, +5,+7,+0,+11,+29,-6,+0,+9,+1,-3,+24,+3,+7,+24,-10, -12,-7,-31,-2,+4,-13,+6,+16,-28,-3,+6,-30,-14,-28,-28, -4,+20,-28,-9,+17,-4,-25,-2,+1,-12,+15,-21,-11,+1,-25, -18,-17,-3,+2,-8,+7,-1,+0,-22,-15,-8,+0,-1,+0,+3, +0,-20,-13,+11,-1,-10,-1,-6,+3,-12,-4,-14,-26,-14,-13, +4,-10,-26,-4,+27,+2,-1,+16,-16,+8,+30,+22,-5,+17,-32, -10,-2,-22,+15,-16,-7,-11,-11,-18,-11,-19,-6,-3,-12,-5, -8,-15,-19,-17,-10,-7,-21,-26,-12,-12,-17,+23,-17,-2,-5, -2,-12,-11,-11,-25,-14,-14,-12,+1,+5,+0,+7,+6,+2,-9, -8,-7,+6,+9,+14,+1,+7,+5,+3,-1,+3,-4,+1,-3,-4, -8,-9,-10,-11,-8,+9,+9,-1,+0,+5,+6,+2,+10,-2,+13, +6,+5,+17,+5,+3,-2,+0,-5,-4,-2,-25,+2,+2,+1,-8, +3,-6,+0,+4,-1,+4,+3,+1,-7,-8,-7,-5,-4,-1,-9, -6,-6,-14,-13,-14,-2,+2,-1,-9,-9,-12,-8,-10,-8,+3, -3,+4,-9,+6,-1,-3,-15,-1,+13,+8,+19,-7,+5,+19,+11, -20,+6,-4,+15,+7,-24,-7,-2,-14,-17,-6,+0,-5,+14,+0, +2,-8,-10,-9,+1,+9,-2,+11,-10,+0,-8,-12,-7,+4,-16, -10,-14,-17,-9,-11,-27,-12,-9,-9,-7,-5,-5,-6,-19,-19, -18,-2,+4,-3,-1,-6,-10,-14,-9,-17,-19,-10,-12,-7,-13, -12,-20,-21,-9,-19,+0,+4,-1,+4,+4,+0,-9,-9,-6,+3, +5,+7,+3,+5,-1,-9,-1,-1,-3,+2,-3,-6,-8,-11,-8, -10,-8,-3,+1,-7,-11,-2,-3,-3,-4,-2,-8,+5,-6,+0, -4,-10,-21,-14,-17,-7,-10,-24,-7,-8,-11,-17,-11,-19,-1, +3,+0,+0,+2,-2,-7,-7,-5,-8,-4,-1,-9,-6,-9,-20, -9,-12,-3,+2,-1,-9,-7,-11,-8,-6,-6 ]; Edge8 = [ +0,-9,-1,-14,-12,-8,-38,-45,-31,-64,-60,-11,-54,-28,+46, +57,+22,+66,+61,+16,-28,+24,+10,+0,+0,-11,-2,-12,-24,-10, -21,-24,-7,-17,-42,-15,-30,-27,-26,-49,-40,+25,+51,+25,+39, +27,+5,+15,+17,+2,+11,+13,+2,+28,+7,-2,+10,+3,-5,-17, -26,-34,-9,-54,-49,-27,-25,-48,+21,+50,+9,+45,+51,+10,+3, +28,-8,+10,+10,-4,+16,-2,-15,+0,-11,-15,+1,-32,-3,-20, -44,-42,-2,-27,-25,+26,+25,+16,+53,+50,+21,+2,-6,-2,+4, +7,-16,-2,-10,-26,-6,-13,-24,+6,-13,+7,-33,-51,-34,-18, -35,-32,+11,-21,-1,+40,+0,+21,+19,+27,+7,+8,-4,+18,+14, +0,+2,+4,+11,-2,-4,-68,-15,-13,+0,-13,+5,-39,-13,+1, +40,-3,+9,+0,+24,+8,+38,+11,+1,+9,+2,+0,+0,-1,-10, +3,-10,-5,-1,-1,-31,-6,-5,-21,-34,-18,+4,+54,-4,+42, +0,+63,-12,-58,-15,-3,-1,-9,-11,+0,-16,-16,-20,-17,-1, -23,-31,-23,+0,+24,-19,-18,-21,+28,+84,+27,-9,+0,+30,+20, +13,+5,+30,+0,+12,+18,+0,+5,+7,-4,-7,+33,+0,-61,-18, -11,-47,-26,-41,-52,+32,+0,+12,+59,+0,+18,+21,+12,+1,+21, +0,+1,+9,+0,-5,+7,-7,-12,+18,-7,-40,-2,-4,-41,-14, -48,-34,+42,+0,+26,+49,+0,+22,+24,+34,+5,+4,+0,-17,-16, +0,-21,+7,-9,-25,-5,-19,-11,-29,+64,-32,-2,-2,-24,+7, +10,+11,+33,+69,+33,-19,+29,-7,+24,+9,+15,+20,+15,+12,+0, +7,-3,+4,-69,+13,+12,-63,-24,-18,-65,-18,+13,+43,+17,+22, +26,+31,-2,+16,-8,+16,+18,+14,+4,+15,-2,-8,-7,-9,+2, -18,+12,-27,-32,-18,-28,-20,-16,+7,+15,+13,+19,+51,+13,+23, -18,+6,+2,+31,+0,+0,+5,-17,-18,-18,-17,-1,-17,+16,-33, +6,-35,-13,-42,-20,-7,-48,-27,+0,+0,+0,-6,+0,+0,-10, +4,-52,+0,+0,+0,-42,-84,-54,-56,-64,+47,-84,+0,+0,-48, -28,-66,+12,-76,-20,+0,+0,+0,-22,-56,+20,-14,-25,-36,+0, +0,+0,-20,-74,-14,-21,-19,-58,-62,-56,+0,+1,-70,-21,+3, -38,+18,+0,+0,+0,-17,+0,-6,-25,-33,-49,+0,+0,+0,-29, -84,-30,-35,-77,-68,-62,+0,-84,-15,-84,-20,+10,+66,+28,+84, +0,+0,-84,-84,-84,-4,-3,-23,+0,+0,+0,-32,-72,-75,-18, -84,-84,-84,-84,-84,-44,-69,-76,+24,+28,-9,+0,+84,+0,+5, -38,-22,-18,-32,-31,+0,+0,+0,-28,-21,-15,-31,-13,-61,-15, +27,+9,-10,-15,-21,+28,+84,+0,+0,+0,+0,-84,-42,+84,-22, -70,-50,+0,+0,+0,-23,-15,-47,-28,+46,-84,+51,+0,+0,-16, +37,-63,-13,+0,-56,+84,+0,+0,+84,+0,-84,-24,+0,-1,+0, +0,+0,-58,+0,-66,-84,+0,-84,+0,+0,+0,-40,+0,-32,+17, +0,-16,-84,+0,+0,-28,+0,-84,-13,-42,-10,+0,+0,+0,-47, +0,-63,-13,-84,-22,+0,+0,+0,-1,+0,-18,-18,+0,-54,+0, +0,+0,-84,+0,+84,-43,+13,-37,+0,+0,+0,-84,+0,+0,-75, +0,-36,-84,+0,+0,-84,+0,-52,+43,+51,+16,+0,+0,+0,+49, +67,+12,+8,-17,-16,+0,+0,+0,+4,-7,-8,-42,-84,-53,+44, +84,-84,-21,-25,-54,+13,+42,+23,+0,+0,+0,+21,-32,+10,-3, -56,-3,+0,+0,+0,-9,-30,-9,+12,-18,+8,+16,+60,-63,+7, -40,-21,+41,+7,+54,+0,+0,+0,+61,+84,+5,-14,-5,+3,+0, +0,+0,-15,-70,-35,-6,-84,-32,-20,+0,+0,-26,-62,-63,+30, +58,+59,+0,+0,+0,+45,+43,-17,+0,+0,+0,+0,+0,+0,+4, -3,-13,+63,+56,+84,+28,-57,-28,-12,-62,-57,+4,+0,+31,+0, +0,+0,+48,+24,-10,+0,+0,+0,+0,+0,+0,-28,-49,-22,-58, -59,-59,-78,-68,-55,-22,-52,-24,+44,+0,+84,+0,+0,+0,+73, +58,+63,+0,+0,+0,+0,+0,+0,-28,-56,-45,-49,+47,+23,+63, +68,+2,-33,-44,-55,+61,+0,+29,+0,+0,+0,+40,+56,+36,+0, +0,+0,+0,+0,+0,+1,+18,-26,-71,+0,-84,+84,+0,+36,-14, -52,-62,+47,+0,+37,+0,+0,+0,+56,+28,+16,+0,+0,+0,+0, +0,+0,-20,-49,-21,-84,+0,-84,+0,-84,-80,+11,-47,-34,-74, +0,+0,+0,+0,+0,+58,+0,+33,+0,+0,+0,+0,+0,+0,-43, -26,-37,+0,+0,-84,-84,+67,-84,-45,-84,-74,+22,+0,+84,+0, +0,+0,+0,-84,+0,-7,+0,-29,+0,+0,+0,-56,-84,-59,-49, +0,+84,+0,+0,+0,-60,-84,-53,+6,+0,-21,+0,+0,+0,-12, -84,+1,-5,+0,-10,+0,+0,+0,-26,-43,-31,-8,-74,+9,+28, +0,+0,-7,-49,-1,+22,+0,+0,+0,+0,+0,-34,+0,-84,-25, +0,-43,+0,+0,+0,-27,-4,-31,-24,-28,-68,-14,+0,-60,-19, -84,-21,+38,+0,+84,+0,+0,+0,+64,+0,+15,+0,+0,+0,+0, +0,+0,-3,+0,-12,-45,+0,-84,+0,+0,-79,-6,-59,-41,+36, +0,+41,+0,+0,+0,+36,+0,+6,+0,+0,+0,+0,+0,+0,-1, +0,-18,+29,+0,+12,+28,+0,-10,+6,+11,-25,+57,+0,+0,+0, +0,+0,+80,+0,+22,+0,+0,+0,+0,+0,+0,+1,+0,-30,-44, +0,+0,+42,+0,-28,+1,-39,-43,+38,-47,+32,+34,+0,+64,+55, -8,+41,+8,+33,-4,+17,-25,-24,+2,-9,+1,-36,-84,-48,-63, -84,-45,-41,-14,-41,+16,+18,+13,+24,+0,+39,+36,+2,+32,-5, -4,-6,+1,-36,-10,-9,-16,-7,-15,-8,-20,-39,-57,-32,-13, -42,-13,+57,+45,+56,+74,+0,+67,+67,+11,+51,-8,+50,-9,-8, +51,-25,-18,-14,-17,-32,+84,-34,-46,+84,-43,-35,-51,-37,+5, +54,+8,+27,+84,-41,-20,-47,-19,+0,+0,+0,+0,+0,+0,+0, +0,+0,+20,-45,+24,+17,-84,+35,+24,-60,+18,+14,+28,+12,+34, +84,+32,+0,+0,+29,+0,+0,+0,+0,+0,+0,+0,+0,+0,-3, +51,+4,+58,-84,+45,+4,+9,+3,+6,+57,+5,+47,+84,-18,-10, +84,-4,+29,+57,+35,+49,-84,+37,+30,+22,+6,+10,+51,+14,+77, +0,+62,+0,+64,+5,+28,+1,+2,-4,-72,-25,+84,+0,+63,+0, +0,+0,+0,+0,+0,+0,+0,+0,+65,+0,-20,+0,+0,+0,+84, +0,+72,+54,+67,+41,+78,+84,+84,+84,+0,+84,+0,+0,+0,+0, +0,+0,+0,+0,+0,+39,-36,-8,+84,+0,+0,+74,+0,+0,+54, +61,+48,+34,+0,+19,+77,+84,+52,+28,+0,+19,+0,+0,+0,+0, +0,+0,+60,+84,-1,+84,+84,+0,+75,+0,+33,+12,+0,+3,-28, +0,+64,+31,+84,-25,+0,+0,+0,+0,+0,+0,+0,+0,+0,+53, +0,+11,+0,+0,+0,+0,+0,-72,+20,+84,+20,+18,+0,+44,+45, +0,+34,+0,+0,+0,+0,+0,+0,+0,+0,+0,-17,-45,+3,+84, +0,+0,-28,+0,+0,+14,+63,-6,+28,+0,+76,+28,+84,+10,+2, +84,+41,+0,+0,+0,+84,+0,-60,-7,+84,+27,+0,+0,+0,+35, +0,+30,+51,-12,+38,+45,+84,+70,+56,+28,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+51,+84,-42,-49,+0,-84,-84,+0,+0,+43, +84,+44,+47,+0,+28,+84,+0,+42,+0,+0,+0,+0,+0,+0,+0, +0,+0,+16,+3,-1,+80,+84,+84,+84,+0,+58,+62,+77,+51,+57, +51,+84,+31,+84,+84,+31,-84,+10,+0,+0,+0,+0,+0,+0,+72, +84,+8,+84,+0,+0,+71,+0,+50,+32,+38,+10,+49,-29,+10,+45, -48,-29,+0,+0,+0,+0,+0,+0,+0,+0,+0,+69,-28,+78,-14, -84,-80,+0,-84,-21,+73,+42,+36,+76,+70,+24,+84,+84,+60,+0, +0,+0,+0,+0,+0,+0,+0,+0,+31,+69,+20,+83,+78,+71,+84, +70,+67,+51,+68,+47,+76,+83,+68,+25,+84,+40,+45,+51,+60,+0, +0,+0,+0,+0,+0,+65,+82,+56,+27,+81,+84,+72,+65,+56,+42, +9,+6,+0,+0,-9,+42,+84,+12,+0,+0,+0,+0,+0,+0,+0, +0,+0,+59,+84,+21,+84,+0,-6,+84,+84,-9,+30,+84,-15,+84, +84,+73,+51,+0,+65,+0,+0,+0,+0,+0,+0,+0,+0,+0,+20, +3,-3,+42,+84,+63,+33,+28,+3,+68,+29,+51,+59,+0,+65,+69, +67,+41,+48,+84,+24,+0,+0,+0,+53,+12,+15,+71,+68,+22,+84, +0,+84,+48,+75,+20,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+22,+16,-10,+84, +0,+52,+23,-45,-13,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, -84,+0,+0,+0,+0,+0,+0,-84,+31,+56,+11,+84,+0,+13,+52, +18,+31,+0,+0,+0,+0,+0,+0,+0,+0,+0,+29,-21,-25,+84, +0,+84,-84,+0,+16,+23,+72,-2,-26,+42,-36,+10,-37,+11,+43, +54,+47,+0,+0,+0,+0,+0,+0,+41,+80,+16,+84,+0,+48,+67, -37,+21,+5,+44,+0,-11,+28,-6,+30,+0,+1,+0,+0,+0,+0, +0,+0,+0,+0,+0,+60,+0,+13,+0,+0,+0,+0,+0,+4,+4, +42,+8,+53,+84,+1,+3,-17,+22,+0,+0,+0,+0,+0,+0,+0, +0,+0,+16,-54,-12,+0,+0,+0,+14,+61,+5,+3,+68,-5,+11, +70,+22,+5,+64,+22,+14,+15,-5,+0,+0,+0,+84,-42,-21,+8, +56,+14,+0,+0,+72,-2,+81,+15,+33,+75,+33,+0,+84,+28,-47, +0,-25,+0,+0,+0,+0,+0,+0,+0,+0,+0,+19,+58,+15,+12, +84,-3,-11,+10,-22,+25,-84,+28,+74,+84,-43,+25,+84,+9,+0, +0,+0,+0,+0,+0,+0,+0,+0,+11,+27,+26,+22,+49,+6,-1, +34,+13,+53,+66,+54,+65,+84,+16,+0,+0,+36,+52,-10,+53,+16, +34,+37,-8,-84,+24,+34,+69,+25,+34,+84,+8,+10,+49,+6,+34, +28,-1,-17,+19,+84,+0,-56,+24,+0,+0,+0,+0,+0,+0,+0, +0,+0,+19,+8,+12,+4,-73,-38,+42,-36,-16,+49,+43,+22,+76, +71,+68,+14,+48,+20,+0,+0,+0,+0,+0,+0,+0,+0,+0,+44, +65,+15,+59,-42,+30,+42,+0,+19,+68,+70,+54,+67,+71,+71,+80, +84,+41,+61,+61,+43,+37,+0,+47,+47,+0,-13,+52,+59,+53,+58, -59,+25,+61,+16,+39,+18,+74,+18,+84,-84,-74,-72,+0,-7,+0, +0,+0,+0,+0,+0,+0,+0,+0,+19,+4,+10,-7,+0,+5,-32, +28,-5,+37,+60,+32,+18,+84,-58,-63,+0,+32,+0,+0,+0,+0, +0,+0,+0,+0,+0,+17,+29,+16,+32,+0,+35,-2,+51,+16,+83, +71,+45,+74,+56,+67,+38,+28,+41,+54,+38,+68,+78,+0,+65,+30, +36,+49,+24,+50,-7,+54,+0,+52,+19,+80,+1,+6,-17,-9,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+35, +32,+10,+15,+14,+21,+19,+42,-24,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+23,+26,+12,+51, +10,+49,+28,+15,+37,+42,+73,+54,+60,+84,+45,+45,-24,+45,+59, +55,+48,+51,+28,+3,+31,+27,-15,+44,+52,+30,+53,+41,+49,+40, +10,+39,+26,+43,-4,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+36,+73,+27,+47,+10,-5,+38,+18,-6,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+47,+55,+29,+62,+39,+44,+49,+29,+22,+64,+81,+36,+46, +46,+8,+43,+19,+18,+58,+46,+42,+42,+28,+6,+38,-7,+6,+53, +67,+42,+58,+42,+34,+48,+30,+16,+15,-21,+3,+0,+0,+0,+37, -18,+21,+0,+0,+0,+0,+0,+0,+0,+0,+0,+41,+60,+34,+25, +49,+12,+14,+12,+6,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+0,+0,+0,+18,+60,+20,+24,+23,+32,+44, +47,+21,+54,+84,+53,-34,+3,+2,+71,+78,+33,+44,+53,+24,+43, +8,+23,+17,+23,+4,+47,+19,+43,+51,+41,+34,+47,+51,+37,+11, -5,+5,+0,+0,+0,+10,+26,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+5,+17,-14,-7,+0,-35,+26,+52,+8,+0,+0,+0,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+10, +13,+5,+38,+0,+67,+16,+59,+23,+24,-28,+42,+84,+0,+56,-15, +84,+57,+45,+21,+60,+45,+0,+46,-3,+25,+6,+18,+40,-4,+22, +84,+36,+7,+45,+25,+27,+0,-8,+0,+0,+0,+24,-84,-26,+0, +0,+0,+0,+0,+0,+0,+0,+0,+25,+84,+28,+84,+0,+5,-4, -5,-19,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+26,+0,+10,+84,+0,+6,+21,-5,-5,+84, +0,-12,+84,+0,-42,-8,-38,-12,+72,+0,+32,+34,+0,+28,+36, -6,-8,+23,+42,-3,+32,-34,+29,+5,+0,-5,+40,-11,+26,+0, +0,+0,-12,-84,-11,+0,+0,+0,+0,+0,+0,+0,+0,+0,-3, +29,-2,+25,+60,+12,-11,+36,-20,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+10,+0,+23,+23, +52,+27,+12,-34,-5,+60,+21,+67,+78,+64,+51,+4,+51,-1,+53, +66,+60,+35,+63,+13,+9,+51,+6,+2,+69,+11,+18,+2,+19,-7, +2,-21,-2,-5,-28,+0,+0,+0,+7,+0,+6,+0,+0,+0,+0, +0,+0,+0,+0,+0,-13,-15,+1,+72,+0,+0,+22,+0,+6,+47, +60,+34,+0,+0,+0,+59,+0,+68,+0,+0,+0,+0,+0,+0,+0, +0,+0,+19,+0,+8,-26,+0,+42,-4,+65,+1,+41,+84,+55,+0, +0,+0,+53,+0,+52,+48,+84,+60,+0,+0,+0,+42,-84,+41,+40, +76,+39,+56,+0,+0,+41,+45,+38,+23,+25,-15,+0,+0,+0,+11, -44,+24,+0,+0,+0,+0,+0,+0,+0,+0,+0,+29,+78,+2,+84, +84,+84,+22,-17,+18,+83,+84,+84,+0,+0,+0,+72,+84,+48,+0, +0,+0,+0,+0,+0,+0,+0,+0,+54,+84,+22,+0,-84,+84,+52, +45,+40,+64,-11,+64,+0,+0,+0,+70,+31,+14,+50,+72,+70,+0, +0,+0,+54,+55,+68,+63,+77,+24,+75,+84,+84,+66,+53,+48,+4, +9,-33,+0,+0,+0,-11,+0,-84,+0,+0,+0,+0,+0,+0,+0, +0,+0,-22,-63,-9,+0,+0,+0,+23,+0,-21,+48,+0,+28,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+28, +62,+36,+0,+0,+0,+61,+0,+23,+20,+0,+64,+0,+0,+0,+0, +0,-58,+53,+0,+44,+0,+0,+0,+0,+0,+0,+54,+84,+21,+84, +0,+0,+72,+0,+44,+12,+60,+59,+0,+0,+0,+16,+84,+1,+0, +0,+0,+0,+0,+0,+0,+0,+0,+24,-28,-13,+0,+0,+0,+3, -21,-31,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+19,+84,+29,+0,+0,+0,+32,+51,+52,+62, +84,+14,+0,+0,+0,+12,+70,+84,+32,+79,+18,+0,+0,+0,+53, +59,+48,+71,+56,+81,+84,+0,+28,+51,+51,+30,+5,+0,-20,+0, +0,+0,+42,-51,-31,+0,+0,+0,+0,+0,+0,+0,+0,+0,+27, +84,+15,+0,+0,+0,+0,-15,-18,+0,+0,+0,+0,+0,+0,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+21,+0,+28,+0, +0,+0,+46,+49,+33,+46,+0,+47,+0,+0,+0,+73,+63,+36,+0, +0,+0,+0,+0,+0,+40,+37,+19,+66,+81,+49,+52,+55,+31,+60, +57,+44,+82,+0,-7,+0,+0,+0,+44,+0,+21,+0,+0,+0,+0, +0,+0,+0,+0,+0,+23,+0,-35,+0,+0,+0,-8,-13,-24,+0, +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, +0,+0,+77,+0,+84,+0,+0,+0,+52,-34,+18,+84,+0,+0,+0, +0,+0,+18,+0,+31,+0,+0,+0,+0,+0,+0,+56,+0,+43,+84, +0,+28,+84,+0,+47,+44,+70,+22,+14,+20,+30,+69,+0,+84,+6, +0,+45,-10,+84,+84,+0,+0,+0,+39,-84,+19,+13,+51,+3,+0, -84,-56,-11,+49,+12,+15,+53,+73,+0,+0,+84,+21,+0,+65,+46, +0,+54,+0,+0,+0,+0,+67,+5,+20,+49,+48,+66,+0,-58,+35, +84,+24,+36,+24,-11,+84,+0,+84,+14,+84,-7,+31,+0,+23,+0, +0,+0,+12,+34,+32,+38,+81,+44,+84,+84,+14,+54,+64,+52,+40, -11,+6,+84,-22,+36,+42,+3,-5,+14,+33,+13,+0,+0,+0,+64, +84,-11,+13,+6,+3,-84,-46,-31,+23,+29,+6,+66,+18,+29,+84, -8,-19,+49,+73,+26,+46,+36,+40,+0,+0,+0,+57,+34,+19,+56, +52,+30,+84,+75,+84,+17,+35,+41,+59,+73,+33,+84,+77,+84,+65, +40,+27,+77,+81,+25,+0,+0,+0,+50,+21,+18,+79,+82,+42,+84, +84,+80,+71,+74,+39,+10,-11,+8,+42,-76,+0,+33,-18,+19,+28, +28,+25,+20,+0,+32,+15,+54,+17,+23,+25,+19,+3,-84,-7,+22, +20,+10,+34,+62,+48,+28,+84,+74,+59,+25,+48,+33,-10,+33,+34, +80,+19,+21,+40,+8,+15,+45,+17,+47,+55,+48,+29,+40,+35,+50, +68,+51,+84,+17,+68,+55,+42,+57,+47,+79,+49,+62,+0,+45,+27, +45,+31,+57,+75,+57,+58,+84,+68,+71,+63,+66 ]; Diag8 = [ +0,+0,-10,-8,-8,-10,+0,-10,-8,-8,-8,-10,-16,-8,-10, +0,-10,+0,+0,+0,-10,-21,-10,+0,+0,+2,-8,-8,-8,-18, -16,-16,-10,+0,-10,-16,-16,-16,-10,-16,-8,-10,+0,-10,+0, +0,+0,-10,-21,-10,+8,+8,+8,+0,+0,+0,-10,-8,-8,-10, +0,-10,-21,-21,-21,-10,-21,-10,+0,+8,+2,+0,+0,+0,+2, -8,+2,+0,+0,+2,-8,-8,-8,-18,-16,-16,-18,-8,-18,-16, -16,-16,-18,-24,-16,-10,+0,-10,+0,+0,+0,-10,-21,-10,-8, -8,-5,-16,-16,-16,-26,-24,-24,-10,+0,-10,-16,-16,-16,-10, -16,-8,-10,+0,-10,+0,+0,+0,-10,-21,-10,+8,+8,+8,+0, +0,+0,-10,-8,-8,-10,+0,-10,-21,-21,-21,-10,-21,-10,+8, +16,+8,+8,+8,+8,+8,-2,+8,+8,+8,+10,+0,+0,+0,-10, -8,-8,-10,+0,-10,-8,-8,-8,-10,-16,-8,-10,+0,-10,+0, +0,+0,-10,-21,-10,-13,-13,-10,-21,-21,-21,-29,-29,-29,-10, +0,-10,-21,-21,-21,-10,-21,-10,+0,+8,+2,+8,+8,+8,+2, -8,+2,+8,+8,+10,+0,+0,+0,-10,-8,-8,+2,+13,+2,-8, -8,-8,+2,-8,+2,+0,+8,+2,+0,+0,+0,+2,-8,+2,+0, +0,+2,-8,-8,-8,-18,-16,-16,-18,-8,-18,-16,-16,-16,-18, -24,-16,-18,-8,-18,-8,-8,-8,-18,-29,-18,-8,-8,-5,-16, -16,-16,-26,-24,-24,-18,-8,-18,-24,-24,-24,-18,-24,-16,-10, +0,-10,+0,+0,+0,-10,-21,-10,+8,+8,+8,+0,+0,+0,-10, -8,-8,-10,+0,-10,-21,-21,-21,-10,-21,-10,-8,+0,-5,-8, -8,-8,-5,-16,-5,-8,-8,-5,-16,-16,-16,-26,-24,-24,-26, -16,-26,-24,-24,-24,-26,-32,-24,-10,+0,-10,+0,+0,+0,-10, -21,-10,-8,-8,-5,-16,-16,-16,-26,-24,-24,-10,+0,-10,-16, -16,-16,-10,-16,-8,-10,+0,-10,+0,+0,+0,-10,-21,-10,+8, +8,+8,+0,+0,+0,-10,-8,-8,-10,+0,-10,-21,-21,-21,-10, -21,-10,+8,+16,+8,+8,+8,+8,+8,-2,+8,+8,+8,+10,+0, +0,+0,-10,-8,-8,-10,+0,-10,-8,-8,-8,-10,-16,-8,-10, +0,-10,+0,+0,+0,-10,-21,-10,-13,-13,-10,-21,-21,-21,-29, -29,-29,-10,+0,-10,-21,-21,-21,-10,-21,-10,+8,+16,+8,+16, +16,+16,+8,-2,+8,+16,+16,+18,+8,+8,+8,-2,+0,+0,+8, +18,+8,-2,-2,-2,+8,-2,+8,+8,+16,+10,+8,+8,+8,+10, +0,+10,+8,+8,+10,+0,+0,+0,-10,-8,-8,-10,+0,-10,-8, -8,-8,-10,-16,-8,-10,+0,-10,+0,+0,+0,-10,-21,-10,+0, +0,+2,-8,-8,-8,-18,-16,-16,-10,+0,-10,-16,-16,-16,-10, -16,-8,-10,+0,-10,+0,+0,+0,-10,-21,-10,+8,+8,+8,+0, +0,+0,-10,-8,-8,-10,+0,-10,-21,-21,-21,-10,-21,-10,-13, -5,-10,-13,-13,-13,-10,-21,-10,-13,-13,-10,-21,-21,-21,-31, -29,-29,-29,-18,-29,-29,-29,-29,-29,-37,-29,-10,+0,-10,+0, +0,+0,-10,-21,-10,-13,-13,-10,-21,-21,-21,-29,-29,-29,-10, +0,-10,-21,-21,-21,-10,-21,-10,+0,+8,+2,+8,+8,+8,+2, -8,+2,+16,+16,+18,+8,+8,+8,-2,+0,+0,+2,+13,+2,-8, -8,-8,+2,-8,+2,+8,+16,+10,+8,+8,+8,+10,+0,+10,+8, +8,+10,+0,+0,+0,-10,-8,-8,-10,+0,-10,-8,-8,-8,-10, -16,-8,+2,+13,+2,+13,+13,+13,+2,-8,+2,+0,+0,+2,-8, -8,-8,-16,-16,-16,+2,+13,+2,-8,-8,-8,+2,-8,+2,+0, +8,+2,+8,+8,+8,+2,-8,+2,+8,+8,+10,+0,+0,+0,-10, -8,-8,+2,+13,+2,-8,-8,-8,+2,-8,+2,+0,+8,+2,+0, +0,+0,+2,-8,+2,+0,+0,+2,-8,-8,-8,-18,-16,-16,-18, -8,-18,-16,-16,-16,-18,-24,-16,-18,-8,-18,-8,-8,-8,-18, -29,-18,-8,-8,-5,-16,-16,-16,-26,-24,-24,-18,-8,-18,-24, -24,-24,-18,-24,-16,-18,-8,-18,-8,-8,-8,-18,-29,-18,+0, +0,+0,-8,-8,-8,-18,-16,-16,-18,-8,-18,-29,-29,-29,-18, -29,-18,-8,+0,-5,-8,-8,-8,-5,-16,-5,-8,-8,-5,-16, -16,-16,-26,-24,-24,-26,-16,-26,-24,-24,-24,-26,-32,-24,-18, -8,-18,-8,-8,-8,-18,-29,-18,-16,-16,-13,-24,-24,-24,-34, -32,-32,-18,-8,-18,-24,-24,-24,-18,-24,-16,-10,+0,-10,+0, +0,+0,-10,-21,-10,+8,+8,+8,+0,+0,+0,-10,-8,-8,-10, +0,-10,-21,-21,-21,-10,-21,-10,+8,+16,+8,+8,+8,+8,+8, -2,+8,+8,+8,+10,+0,+0,+0,-10,-8,-8,-10,+0,-10,-8, -8,-8,-10,-16,-8,-10,+0,-10,+0,+0,+0,-10,-21,-10,-13, -13,-10,-21,-21,-21,-29,-29,-29,-10,+0,-10,-21,-21,-21,-10, -21,-10,-8,+0,-5,+0,+0,+0,-5,-16,-5,+0,+0,+2,-8, -8,-8,-18,-16,-16,-5,+5,-5,-16,-16,-16,-5,-16,-5,-8, +0,-5,-8,-8,-8,-5,-16,-5,-8,-8,-5,-16,-16,-16,-26, -24,-24,-26,-16,-26,-24,-24,-24,-26,-32,-24,-26,-16,-26,-16, -16,-16,-26,-37,-26,-16,-16,-13,-24,-24,-24,-34,-32,-32,-26, -16,-26,-32,-32,-32,-26,-32,-24,-10,+0,-10,+0,+0,+0,-10, -21,-10,+8,+8,+8,+0,+0,+0,-10,-8,-8,-10,+0,-10,-21, -21,-21,-10,-21,-10,-8,+0,-5,-8,-8,-8,-5,-16,-5,-8, -8,-5,-16,-16,-16,-26,-24,-24,-26,-16,-26,-24,-24,-24,-26, -32,-24,-10,+0,-10,+0,+0,+0,-10,-21,-10,-8,-8,-5,-16, -16,-16,-26,-24,-24,-10,+0,-10,-16,-16,-16,-10,-16,-8,+0, +10,+0,+10,+10,+10,+0,-10,+0,+18,+18,+18,+10,+10,+10,+0, +2,+2,+0,+10,+0,-10,-10,-10,+0,-10,+0,+18,+26,+18,+18, +18,+18,+18,+8,+18,+18,+18,+21,+10,+10,+10,+0,+2,+2,+0, +10,+0,+2,+2,+2,+0,-5,+2,+0,+10,+0,+10,+10,+10,+0, -10,+0,-2,-2,+0,-10,-10,-10,-18,-18,-18,+0,+10,+0,-10, -10,-10,+0,-10,+0,+18,+26,+18,+26,+26,+26,+18,+8,+18,+26, +26,+29,+18,+18,+18,+8,+10,+10,+18,+29,+18,+8,+8,+8,+18, +8,+18,+18,+26,+21,+18,+18,+18,+21,+10,+21,+18,+18,+21,+10, +10,+10,+0,+2,+2,+0,+10,+0,+2,+2,+2,+0,-5,+2,+0, +10,+0,+10,+10,+10,+0,-10,+0,+10,+10,+13,+2,+2,+2,-8, -5,-5,+0,+10,+0,-5,-5,-5,+0,-5,+2,+0,+10,+0,+10, +10,+10,+0,-10,+0,+18,+18,+18,+10,+10,+10,+0,+2,+2,+0, +10,+0,-10,-10,-10,+0,-10,+0,-2,+5,+0,-2,-2,-2,+0, -10,+0,-2,-2,+0,-10,-10,-10,-21,-18,-18,-18,-8,-18,-18, -18,-18,-18,-26,-18,+0,+10,+0,+10,+10,+10,+0,-10,+0,-2, -2,+0,-10,-10,-10,-18,-18,-18,+0,+10,+0,-10,-10,-10,+0, -10,+0,+18,+26,+18,+26,+26,+26,+18,+8,+18,+34,+34,+37,+26, +26,+26,+16,+18,+18,+18,+29,+18,+8,+8,+8,+18,+8,+18,+26, +34,+29,+26,+26,+26,+29,+18,+29,+26,+26,+29,+18,+18,+18,+8, +10,+10,+8,+18,+8,+10,+10,+10,+8,+2,+10,+18,+29,+18,+29, +29,+29,+18,+8,+18,+16,+16,+18,+8,+8,+8,+0,+0,+0,+18, +29,+18,+8,+8,+8,+18,+8,+18,+18,+26,+21,+26,+26,+26,+21, +10,+21,+26,+26,+29,+18,+18,+18,+8,+10,+10,+21,+31,+21,+10, +10,+10,+21,+10,+21,+18,+26,+21,+18,+18,+18,+21,+10,+21,+18, +18,+21,+10,+10,+10,+0,+2,+2,+0,+10,+0,+2,+2,+2,+0, -5,+2,+0,+10,+0,+10,+10,+10,+0,-10,+0,+10,+10,+13,+2, +2,+2,-8,-5,-5,+0,+10,+0,-5,-5,-5,+0,-5,+2,+0, +10,+0,+10,+10,+10,+0,-10,+0,+18,+18,+18,+10,+10,+10,+0, +2,+2,+0,+10,+0,-10,-10,-10,+0,-10,+0,+10,+18,+13,+10, +10,+10,+13,+2,+13,+10,+10,+13,+2,+2,+2,-8,-5,-5,-8, +2,-8,-5,-5,-5,-8,-13,-5,+0,+10,+0,+10,+10,+10,+0, -10,+0,+2,+2,+5,-5,-5,-5,-16,-13,-13,+0,+10,+0,-5, -5,-5,+0,-5,+2,+0,+10,+0,+10,+10,+10,+0,-10,+0,+18, +18,+18,+10,+10,+10,+0,+2,+2,+0,+10,+0,-10,-10,-10,+0, -10,+0,+18,+26,+18,+18,+18,+18,+18,+8,+18,+18,+18,+21,+10, +10,+10,+0,+2,+2,+0,+10,+0,+2,+2,+2,+0,-5,+2,+0, +10,+0,+10,+10,+10,+0,-10,+0,-2,-2,+0,-10,-10,-10,-18, -18,-18,+0,+10,+0,-10,-10,-10,+0,-10,+0,-2,+5,+0,+5, +5,+5,+0,-10,+0,+5,+5,+8,-2,-2,-2,-13,-10,-10,+0, +10,+0,-10,-10,-10,+0,-10,+0,-2,+5,+0,-2,-2,-2,+0, -10,+0,-2,-2,+0,-10,-10,-10,-21,-18,-18,-21,-10,-21,-18, -18,-18,-21,-26,-18,-18,-8,-18,-8,-8,-8,-18,-29,-18,-10, -10,-8,-18,-18,-18,-29,-26,-26,-18,-8,-18,-26,-26,-26,-18, -26,-18,+0,+10,+0,+10,+10,+10,+0,-10,+0,+18,+18,+18,+10, +10,+10,+0,+2,+2,+0,+10,+0,-10,-10,-10,+0,-10,+0,-2, +5,+0,-2,-2,-2,+0,-10,+0,-2,-2,+0,-10,-10,-10,-21, -18,-18,-18,-8,-18,-18,-18,-18,-18,-26,-18,+0,+10,+0,+10, +10,+10,+0,-10,+0,-2,-2,+0,-10,-10,-10,-18,-18,-18,+0, +10,+0,-10,-10,-10,+0,-10,+0,+8,+16,+10,+16,+16,+16,+10, +0,+10,+24,+24,+26,+16,+16,+16,+5,+8,+8,+10,+21,+10,+0, +0,+0,+10,+0,+10,+24,+32,+26,+24,+24,+24,+26,+16,+26,+24, +24,+26,+16,+16,+16,+5,+8,+8,+5,+16,+5,+8,+8,+8,+5, +0,+8,+10,+21,+10,+21,+21,+21,+10,+0,+10,+8,+8,+10,+0, +0,+0,-8,-8,-8,+10,+21,+10,+0,+0,+0,+10,+0,+10,+16, +24,+18,+24,+24,+24,+18,+8,+18,+24,+24,+26,+16,+16,+16,+5, +8,+8,+18,+29,+18,+8,+8,+8,+18,+8,+18,+16,+24,+18,+16, +16,+16,+18,+8,+18,+16,+16,+18,+8,+8,+8,-2,+0,+0,-2, +8,-2,+0,+0,+0,-2,-8,+0,-2,+8,-2,+8,+8,+8,-2, -13,-2,+8,+8,+10,+0,+0,+0,-10,-8,-8,-2,+8,-2,-8, -8,-8,-2,-8,+0,+10,+21,+10,+21,+21,+21,+10,+0,+10,+29, +29,+29,+21,+21,+21,+10,+13,+13,+10,+21,+10,+0,+0,+0,+10, +0,+10,+8,+16,+10,+8,+8,+8,+10,+0,+10,+8,+8,+10,+0, +0,+0,-10,-8,-8,-8,+2,-8,-8,-8,-8,-8,-16,-8,+10, +21,+10,+21,+21,+21,+10,+0,+10,+8,+8,+10,+0,+0,+0,-8, -8,-8,+10,+21,+10,+0,+0,+0,+10,+0,+10,+8,+16,+10,+16, +16,+16,+10,+0,+10,+24,+24,+26,+16,+16,+16,+5,+8,+8,+10, +21,+10,+0,+0,+0,+10,+0,+10,+16,+24,+18,+16,+16,+16,+18, +8,+18,+16,+16,+18,+8,+8,+8,-2,+0,+0,-2,+8,-2,+0, +0,+0,-2,-8,+0,+10,+21,+10,+21,+21,+21,+10,+0,+10,+8, +8,+10,+0,+0,+0,-8,-8,-8,+10,+21,+10,+0,+0,+0,+10, +0,+10,+8,+16,+10,+16,+16,+16,+10,+0,+10,+16,+16,+18,+8, +8,+8,-2,+0,+0,+10,+21,+10,+0,+0,+0,+10,+0,+10,+8, +16,+10,+8,+8,+8,+10,+0,+10,+8,+8,+10,+0,+0,+0,-10, -8,-8,-10,+0,-10,-8,-8,-8,-10,-16,-8,-10,+0,-10,+0, +0,+0,-10,-21,-10,+0,+0,+2,-8,-8,-8,-18,-16,-16,-10, +0,-10,-16,-16,-16,-10,-16,-8,-10,+0,-10,+0,+0,+0,-10, -21,-10,+8,+8,+8,+0,+0,+0,-10,-8,-8,-10,+0,-10,-21, -21,-21,-10,-21,-10,+0,+8,+2,+0,+0,+0,+2,-8,+2,+0, +0,+2,-8,-8,-8,-18,-16,-16,-18,-8,-18,-16,-16,-16,-18, -24,-16,-10,+0,-10,+0,+0,+0,-10,-21,-10,-8,-8,-5,-16, -16,-16,-26,-24,-24,-10,+0,-10,-16,-16,-16,-10,-16,-8,-10, +0,-10,+0,+0,+0,-10,-21,-10,+8,+8,+8,+0,+0,+0,-10, -8,-8,-10,+0,-10,-21,-21,-21,-10,-21,-10,+8,+16,+8,+8, +8,+8,+8,-2,+8,+8,+8,+10,+0,+0,+0,-10,-8,-8,-10, +0,-10,-8,-8,-8,-10,-16,-8,-10,+0,-10,+0,+0,+0,-10, -21,-10,-13,-13,-10,-21,-21,-21,-29,-29,-29,-10,+0,-10,-21, -21,-21,-10,-21,-10,+0,+8,+2,+8,+8,+8,+2,-8,+2,+8, +8,+10,+0,+0,+0,-10,-8,-8,+2,+13,+2,-8,-8,-8,+2, -8,+2,+0,+8,+2,+0,+0,+0,+2,-8,+2,+0,+0,+2,-8, -8,-8,-18,-16,-16,-18,-8,-18,-16,-16,-16,-18,-24,-16,-18, -8,-18,-8,-8,-8,-18,-29,-18,-8,-8,-5,-16,-16,-16,-26, -24,-24,-18,-8,-18,-24,-24,-24,-18,-24,-16,-10,+0,-10,+0, +0,+0,-10,-21,-10,+8,+8,+8,+0,+0,+0,-10,-8,-8,-10, +0,-10,-21,-21,-21,-10,-21,-10,-8,+0,-5,-8,-8,-8,-5, -16,-5,-8,-8,-5,-16,-16,-16,-26,-24,-24,-26,-16,-26,-24, -24,-24,-26,-32,-24,-10,+0,-10,+0,+0,+0,-10,-21,-10,-8, -8,-5,-16,-16,-16,-26,-24,-24,-10,+0,-10,-16,-16,-16,-10, -16,-8,+0,+10,+0,+10,+10,+10,+0,-10,+0,+18,+18,+18,+10, +10,+10,+0,+2,+2,+0,+10,+0,-10,-10,-10,+0,-10,+0,+18, +26,+18,+18,+18,+18,+18,+8,+18,+18,+18,+21,+10,+10,+10,+0, +2,+2,+0,+10,+0,+2,+2,+2,+0,-5,+2,+0,+10,+0,+10, +10,+10,+0,-10,+0,-2,-2,+0,-10,-10,-10,-18,-18,-18,+0, +10,+0,-10,-10,-10,+0,-10,+0,+18,+26,+18,+26,+26,+26,+18, +8,+18,+26,+26,+29,+18,+18,+18,+8,+10,+10,+18,+29,+18,+8, +8,+8,+18,+8,+18,+18,+26,+21,+18,+18,+18,+21,+10,+21,+18, +18,+21,+10,+10,+10,+0,+2,+2,+0,+10,+0,+2,+2,+2,+0, -5,+2,+0,+10,+0,+10,+10,+10,+0,-10,+0,+10,+10,+13,+2, +2,+2,-8,-5,-5,+0,+10,+0,-5,-5,-5,+0,-5,+2,+0, +10,+0,+10,+10,+10,+0,-10,+0,+18,+18,+18,+10,+10,+10,+0, +2,+2,+0,+10,+0,-10,-10,-10,+0,-10,+0,-2,+5,+0,-2, -2,-2,+0,-10,+0,-2,-2,+0,-10,-10,-10,-21,-18,-18,-18, -8,-18,-18,-18,-18,-18,-26,-18,+0,+10,+0,+10,+10,+10,+0, -10,+0,-2,-2,+0,-10,-10,-10,-18,-18,-18,+0,+10,+0,-10, -10,-10,+0,-10,+0,+0,+8,+2,+8,+8,+8,+2,-8,+2,+16, +16,+18,+8,+8,+8,-2,+0,+0,+2,+13,+2,-8,-8,-8,+2, -8,+2,+8,+16,+10,+8,+8,+8,+10,+0,+10,+8,+8,+10,+0, +0,+0,-10,-8,-8,-10,+0,-10,-8,-8,-8,-10,-16,-8,+2, +13,+2,+13,+13,+13,+2,-8,+2,+0,+0,+2,-8,-8,-8,-16, -16,-16,+2,+13,+2,-8,-8,-8,+2,-8,+2,+0,+8,+2,+8, +8,+8,+2,-8,+2,+8,+8,+10,+0,+0,+0,-10,-8,-8,+2, +13,+2,-8,-8,-8,+2,-8,+2,+0,+8,+2,+0,+0,+0,+2, -8,+2,+0,+0,+2,-8,-8,-8,-18,-16,-16,-18,-8,-18,-16, -16,-16,-18,-24,-16,-18,-8,-18,-8,-8,-8,-18,-29,-18,-8, -8,-5,-16,-16,-16,-26,-24,-24,-18,-8,-18,-24,-24,-24,-18, -24,-16,-18,-8,-18,-8,-8,-8,-18,-29,-18,+0,+0,+0,-8, -8,-8,-18,-16,-16,-18,-8,-18,-29,-29,-29,-18,-29,-18,-8, +0,-5,-8,-8,-8,-5,-16,-5,-8,-8,-5,-16,-16,-16,-26, -24,-24,-26,-16,-26,-24,-24,-24,-26,-32,-24,-18,-8,-18,-8, -8,-8,-18,-29,-18,-16,-16,-13,-24,-24,-24,-34,-32,-32,-18, -8,-18,-24,-24,-24,-18,-24,-16,+0,+10,+0,+10,+10,+10,+0, -10,+0,+18,+18,+18,+10,+10,+10,+0,+2,+2,+0,+10,+0,-10, -10,-10,+0,-10,+0,+18,+26,+18,+18,+18,+18,+18,+8,+18,+18, +18,+21,+10,+10,+10,+0,+2,+2,+0,+10,+0,+2,+2,+2,+0, -5,+2,+0,+10,+0,+10,+10,+10,+0,-10,+0,-2,-2,+0,-10, -10,-10,-18,-18,-18,+0,+10,+0,-10,-10,-10,+0,-10,+0,+0, +8,+2,+8,+8,+8,+2,-8,+2,+8,+8,+10,+0,+0,+0,-10, -8,-8,+2,+13,+2,-8,-8,-8,+2,-8,+2,+0,+8,+2,+0, +0,+0,+2,-8,+2,+0,+0,+2,-8,-8,-8,-18,-16,-16,-18, -8,-18,-16,-16,-16,-18,-24,-16,-18,-8,-18,-8,-8,-8,-18, -29,-18,-8,-8,-5,-16,-16,-16,-26,-24,-24,-18,-8,-18,-24, -24,-24,-18,-24,-16,+0,+10,+0,+10,+10,+10,+0,-10,+0,+18, +18,+18,+10,+10,+10,+0,+2,+2,+0,+10,+0,-10,-10,-10,+0, -10,+0,+0,+8,+2,+0,+0,+0,+2,-8,+2,+0,+0,+2,-8, -8,-8,-18,-16,-16,-18,-8,-18,-16,-16,-16,-18,-24,-16,+0, +10,+0,+10,+10,+10,+0,-10,+0,+0,+0,+2,-8,-8,-8,-18, -16,-16,+0,+10,+0,-8,-8,-8,+0,-8,+0 ]; Diag7 = [ +0,+0,-9,-6,-6,-9,+0,-9,-6,-6,-6,-9,-12,-6,-10,+0,-10, -1,+0,-1,-12,-19,-10,-3,+0,-3,-12,-7,-1,-18,-15,-14, -10,-1,-9,-13,-12,-13,-10,-13,-7,-10,+0,-10,+0,+0,-1, -12,-19,-11,+3,+8,+5,-3,+0,-4,-8,-9,-6,-10,+0,-9, -18,-19,-21,-11,-19,-10,+0,+6,+3,+0,+0,+0,+3,-6,+3, +0,+0,+3,-6,-6,-6,-15,-12,-12,-15,-6,-15,-12,-12,-12, -15,-17,-12,-10,+0,-10,+0,+0,-1,-12,-19,-11,-6,-6,-6, -13,-12,-13,-25,-21,-24,-10,-1,-10,-13,-13,-14,-11,-13,-7, -9,+0,-9,+1,+1,+0,-11,-20,-11,+15,+8,+10,-5,+1,-2, -5,-7,-3,-9,+0,-8,-19,-19,-20,-11,-20,-10,+6,+12,+6, +6,+6,+6,+6,-3,+6,+6,+6,+9,+0,+0,+0,-9,-6,-6, -9,+0,-9,-6,-6,-6,-9,-12,-6,-9,+1,-9,+0,+0,+0, -11,-19,-11,-11,-13,-16,-17,-19,-13,-32,-26,-18,-8,+0,-8, -20,-19,-20,-10,-19,-10,+1,+8,+1,+5,+6,+2,+4,-7,+3, -3,+10,+17,+4,+0,+0,+0,-8,+3,+5,+13,+6,+0,-9,-10, +3,-7,+5,+0,+6,+3,+0,+0,+0,+3,-6,+3,+0,+0,+3, -6,-6,-6,-15,-12,-12,-15,-6,-15,-12,-12,-12,-15,-17,-12, -18,-7,-17,-10,-8,-11,-20,-26,-17,-6,-10,-3,-20,-15,-20, -20,-22,-9,-18,-8,-17,-23,-21,-23,-18,-21,-14,-10,+0,-10, +0,+0,-1,-12,-20,-12,+4,+7,+5,-4,+0,-4,-15,-7,-3, -10,-1,-9,-19,-19,-20,-11,-20,-11,-6,+0,-3,-6,-6,-6, -3,-12,-3,-6,-6,-3,-12,-12,-12,-20,-17,-17,-20,-12,-20, -17,-17,-17,-20,-23,-17,-10,+0,-10,-1,+0,+0,-12,-19,-11, -11,-8,-12,-19,-13,-12,-28,-21,-15,-9,+0,-9,-14,-13,-12, -11,-14,-7,+1,+11,+3,+13,+11,+13,+0,-9,+0,+17,+18,+20, +17,+10,+11,-2,+1,+6,+2,+10,+3,-9,-10,-10,+0,-10,+0, +15,+20,+15,+15,+15,+15,+15,+6,+15,+15,+15,+17,+9,+9,+9, +0,+3,+3,+0,+9,+0,+3,+3,+3,+0,-3,+3,+2,+11,+2, +12,+11,+12,-1,-9,+0,+3,-3,+4,-2,-10,-10,-23,-17,-6, +2,+11,+3,-9,-10,-10,+0,-10,+1,+20,+28,+20,+29,+25,+12, +23,+10,+19,+20,+20,+23,+15,+18,+15,+6,+17,+17,+21,+32,+16, +6,+5,+6,+23,+5,+22,+15,+20,+17,+15,+15,+15,+17,+9,+17, +15,+15,+17,+9,+9,+9,+0,+3,+3,+0,+9,+0,+3,+3,+3, +0,-3,+3,-7,+15,+4,+9,+8,+9,+9,-16,-9,+9,+0,+12, +3,-3,+3,-6,-3,+6,+0,+5,-2,-3,-6,-3,+2,-12,+0, +2,+12,+3,+12,+12,+14,+0,-8,+0,+23,+20,+16,+9,+12,+6, -9,+6,+2,+2,+11,+3,-10,-9,-9,+1,-9,+1,-3,+3,+0, -3,-3,-3,+0,-9,+0,-3,-3,+0,-9,-9,-9,-17,-15,-15, -15,-6,-15,-15,-15,-15,-15,-20,-15,+2,+12,+3,+11,+12,+14, +0,-8,+1,-9,-4,-2,-3,-9,-15,-23,-17,-23,+2,+11,+3, -11,-10,-8,+0,-9,+1,+6,+14,+13,+18,+13,+20,+11,+0,+9, +17,+23,+12,+20,+13,+12,+3,+2,+8,+11,+20,+14,+9,-1,+4, +9,-1,+9,+12,+17,+15,+12,+12,+12,+15,+6,+15,+12,+12,+15, +6,+6,+6,-3,+0,+0,-3,+6,-3,+0,+0,+0,-3,-6,+0, +10,+19,+12,+15,+18,+26,+10,+0,+10,+6,+0,+9,-9,-1,+0, -6,-11,-6,+11,+19,+14,-9,-1,+2,+9,+0,+11,+11,+19,+11, +12,+13,+12,+3,-2,+12,+12,+20,+15,+6,+12,+6,-3,+0,+0, +15,+17,+6,+9,-4,+0,+2,-4,+6,+6,+12,+9,+6,+6,+6, +9,+0,+9,+6,+6,+9,+0,+0,+0,-9,-6,-6,-9,+0,-9, -6,-6,-6,-9,-12,-6,-12,+4,-10,+0,+3,+0,-9,-13,-3, +0,-4,+3,-6,-1,-6,-15,-20,-12,-11,+5,-15,-20,-13,-12, -17,-12,-8,-9,+1,-10,-1,+0,+4,-11,-20,-13,+6,+10,+6, +0,+1,+0,-9,-10,-6,-7,+0,-9,-15,-21,-17,-12,-20,-10, +0,+6,+3,+0,+0,+0,+3,-6,+3,+0,+0,+3,-6,-6,-6, -15,-12,-12,-15,-6,-15,-12,-12,-12,-15,-17,-12,-10,+0,-10, +1,+0,+2,-12,-20,-10,-15,-5,-3,-12,-13,-12,-29,-23,-17, -11,-1,-8,-18,-14,-20,-13,-12,-6,-1,+9,+0,+11,+10,+9, -2,-11,-2,+20,+18,+19,+11,+10,+12,+0,+3,+8,+0,+8,+0, -11,-11,-13,-2,-12,-2,+15,+20,+15,+15,+15,+15,+15,+6,+15, +15,+15,+17,+9,+9,+9,+0,+3,+3,+0,+9,+0,+3,+3,+3, +0,-3,+3,-1,+10,+0,+7,+10,+10,-2,-11,-2,-10,-5,-9, -15,-10,-3,-21,-17,-15,+0,+9,+1,-11,-11,-10,-2,-11,-2, +4,+11,+6,+15,+6,+8,+9,-3,+8,+6,+6,+17,+0,+3,+0, -9,+3,-6,+10,+11,+2,-6,-6,-6,-3,-3,+4,+0,+6,+3, +0,+0,+0,+3,-6,+3,+0,+0,+3,-6,-6,-6,-15,-12,-12, -15,-6,-15,-12,-12,-12,-15,-17,-12,-11,-4,-6,-6,-3,-6, -23,-18,-15,-6,+3,+6,-12,-14,-12,-20,-9,-17,-20,-15,-23, -17,-24,-17,-17,-15,-18,+0,+10,+0,+10,+10,+9,-2,-10,-2, +11,+18,+22,+12,+10,+6,+7,+5,+4,+1,+9,+1,-10,-10,-10, -2,-11,-2,+0,+6,+3,+0,+0,+0,+3,-6,+3,+0,+0,+3, -6,-6,-6,-15,-12,-12,-15,-6,-15,-12,-12,-12,-15,-17,-12, +0,+10,+1,+9,+10,+11,-2,-10,-2,-4,-1,+0,-11,-7,-8, -20,-14,-18,+1,+9,+1,-6,-7,-6,-1,-7,-1 ]; Diag6 = [ +0,+0,-7,-5,-5,-7,+0,-7,-5,-5,-5, -7,-10,-5,-7,+0,-7,+0,+0,+0,-7,-15,-7,+0,+0,+2, -5,-5,-5,-12,-10,-10,-7,+0,-7,-10,-10,-10,-7,-10,-5, -7,+0,-7,+0,+0,+0,-7,-15,-7,+5,+5,+5,+0,+0,+0, -7,-5,-5,-7,+0,-7,-15,-15,-15,-7,-15,-7,+0,+5,+2, +0,+0,+0,+2,-5,+2,+0,+0,+2,-5,-5,-5,-12,-10,-10, -12,-5,-12,-10,-10,-10,-12,-15,-10,-7,+0,-7,+0,+0,+0, -7,-15,-7,-5,-5,-3,-10,-10,-10,-18,-15,-15,-7,+0,-7, -10,-10,-10,-7,-10,-5,+0,+7,+0,+7,+7,+7,+0,-7,+0, +12,+12,+12,+7,+7,+7,+0,+2,+2,+0,+7,+0,-7,-7,-7, +0,-7,+0,+12,+18,+12,+12,+12,+12,+12,+5,+12,+12,+12,+15, +7,+7,+7,+0,+2,+2,+0,+7,+0,+2,+2,+2,+0,-3,+2, +0,+7,+0,+7,+7,+7,+0,-7,+0,-2,-2,+0,-7,-7,-7, -12,-12,-12,+0,+7,+0,-7,-7,-7,+0,-7,+0,+5,+10,+7, +10,+10,+10,+7,+0,+7,+10,+10,+12,+5,+5,+5,-2,+0,+0, +7,+15,+7,+0,+0,+0,+7,+0,+7,+5,+10,+7,+5,+5,+5, +7,+0,+7,+5,+5,+7,+0,+0,+0,-7,-5,-5,-7,+0,-7, -5,-5,-5,-7,-10,-5,-7,+0,-7,+0,+0,+0,-7,-15,-7, +0,+0,+2,-5,-5,-5,-12,-10,-10,-7,+0,-7,-10,-10,-10, -7,-10,-5,+0,+7,+0,+7,+7,+7,+0,-7,+0,+12,+12,+12, +7,+7,+7,+0,+2,+2,+0,+7,+0,-7,-7,-7,+0,-7,+0, +0,+5,+2,+0,+0,+0,+2,-5,+2,+0,+0,+2,-5,-5,-5, -12,-10,-10,-12,-5,-12,-10,-10,-10,-12,-15,-10,+0,+7,+0, +7,+7,+7,+0,-7,+0,+0,+0,+2,-5,-5,-5,-12,-10,-10, +0,+7,+0,-5,-5,-5,+0,-5,+0 ]; Diag5 = [ +0,+0,-5,-4,-4,-5,+0,-5,-4,-4,-4,-5,-7,-4, -5,+0,-5,+0,+0,+0,-5,-11,-5,+0,+0,+2,-4,-4,-4, -9,-7,-7,-5,+0,-5,-7,-7,-7,-5,-7,-4,+0,+5,+0, +5,+5,+5,+0,-5,+0,+9,+9,+9,+5,+5,+5,+0,+2,+2, +0,+5,+0,-5,-5,-5,+0,-5,+0,+4,+7,+5,+4,+4,+4, +5,+0,+5,+4,+4,+5,+0,+0,+0,-5,-4,-4,-5,+0,-5, -4,-4,-4,-5,-7,-4,+0,+5,+0,+5,+5,+5,+0,-5,+0, +0,+0,+2,-4,-4,-4,-9,-7,-7,+0,+5,+0,-4,-4,-4, +0,-4,+0 ]; Diag4 = [ +0,+0,-4,-3,-3, -3,+0,-3,-2,-3,-3,-5,-5,-3,+1,+5,+1,+4,+4,+3, +0,-3,+0,+2,+2,+3,+0,+0,-1,-4,-3,-3,+0,+3,+0, -2,-3,-3,-1,-3,-1 ]; } //機能: 与えられた盤面の評価値を算出する。 //備考: 白番で有利で+のデータ。黒番の時は、値を反転する。 public function Eval(board:Array, empties:int, color:int):int { var Idx:int, Val:int, Val1:int, Val2:int, Val3:int, Val4:int; var Val5:int, Val6:int, Val7:int, Val8:int, Val9:int, Val0:int; //Line1 Val1 = 0; Idx = ((((((board[A1]*3+board[B1])*3+board[C1]) *3+board[D1])*3+board[E1])*3+board[F1]) *3+board[G1])*3+board[H1]; if (Idx < 0) Val1 -= Line1[-Idx]; else Val1 += Line1[Idx]; Idx = ((((((board[A8]*3+board[B8])*3+board[C8]) *3+board[D8])*3+board[E8])*3+board[F8]) *3+board[G8])*3+board[H8]; if (Idx < 0) Val1 -= Line1[-Idx]; else Val1 += Line1[Idx]; Idx = ((((((board[A1]*3+board[A2])*3+board[A3]) *3+board[A4])*3+board[A5])*3+board[A6]) *3+board[A7])*3+board[A8]; if (Idx < 0) Val1 -= Line1[-Idx]; else Val1 += Line1[Idx]; Idx = ((((((board[H1]*3+board[H2])*3+board[H3]) *3+board[H4])*3+board[H5])*3+board[H6]) *3+board[H7])*3+board[H8]; if (Idx < 0) Val1 -= Line1[-Idx]; else Val1 += Line1[Idx]; //Line2 Val2 = 0; Idx = ((((((board[A2]*3+board[B2])*3+board[C2]) *3+board[D2])*3+board[E2])*3+board[F2]) *3+board[G2])*3+board[H2]; if (Idx < 0) Val2 -= Line2[-Idx]; else Val2 += Line2[Idx]; Idx = ((((((board[A7]*3+board[B7])*3+board[C7]) *3+board[D7])*3+board[E7])*3+board[F7]) *3+board[G7])*3+board[H7]; if (Idx < 0) Val2 -= Line2[-Idx]; else Val2 += Line2[Idx]; Idx = ((((((board[B1]*3+board[B2])*3+board[B3]) *3+board[B4])*3+board[B5])*3+board[B6]) *3+board[B7])*3+board[B8]; if (Idx < 0) Val2 -= Line2[-Idx]; else Val2 += Line2[Idx]; Idx = ((((((board[G1]*3+board[G2])*3+board[G3]) *3+board[G4])*3+board[G5])*3+board[G6]) *3+board[G7])*3+board[G8]; if (Idx < 0) Val2 -= Line2[-Idx]; else Val2 += Line2[Idx]; //Line3 Val3 = 0; Idx = ((((((board[A3]*3+board[B3])*3+board[C3]) *3+board[D3])*3+board[E3])*3+board[F3]) *3+board[G3])*3+board[H3]; if (Idx < 0) Val3 -= Line3[-Idx]; else Val3 += Line3[Idx]; Idx = ((((((board[A6]*3+board[B6])*3+board[C6]) *3+board[D6])*3+board[E6])*3+board[F6]) *3+board[G6])*3+board[H6]; if (Idx < 0) Val3 -= Line3[-Idx]; else Val3 += Line3[Idx]; Idx = ((((((board[C1]*3+board[C2])*3+board[C3]) *3+board[C4])*3+board[C5])*3+board[C6]) *3+board[C7])*3+board[C8]; if (Idx < 0) Val3 -= Line3[-Idx]; else Val3 += Line3[Idx]; Idx = ((((((board[F1]*3+board[F2])*3+board[F3]) *3+board[F4])*3+board[F5])*3+board[F6]) *3+board[F7])*3+board[F8]; if (Idx < 0) Val3 -= Line3[-Idx]; else Val3 += Line3[Idx]; //Line4 Val4 = 0; Idx = ((((((board[A4]*3+board[B4])*3+board[C4]) *3+board[D4])*3+board[E4])*3+board[F4]) *3+board[G4])*3+board[H4]; if (Idx < 0) Val4 -= Line4[-Idx]; else Val4 += Line4[Idx]; Idx = ((((((board[A5]*3+board[B5])*3+board[C5]) *3+board[D5])*3+board[E5])*3+board[F5]) *3+board[G5])*3+board[H5]; if (Idx < 0) Val4 -= Line4[-Idx]; else Val4 += Line4[Idx]; Idx = ((((((board[D1]*3+board[D2])*3+board[D3]) *3+board[D4])*3+board[D5])*3+board[D6]) *3+board[D7])*3+board[D8]; if (Idx < 0) Val4 -= Line4[-Idx]; else Val4 += Line4[Idx]; Idx = ((((((board[E1]*3+board[E2])*3+board[E3]) *3+board[E4])*3+board[E5])*3+board[E6]) *3+board[E7])*3+board[E8]; if (Idx < 0) Val4 -= Line4[-Idx]; else Val4 += Line4[Idx]; //Diag4 Val5 = 0; Idx = ((board[A4]*3+board[B3])*3+board[C2]) *3+board[D1]; if (Idx < 0) Val5 -= Diag4[-Idx]; else Val5 += Diag4[Idx]; Idx = ((board[E1]*3+board[F2])*3+board[G3]) *3+board[H4]; if (Idx < 0) Val5 -= Diag4[-Idx]; else Val5 += Diag4[Idx]; Idx = ((board[A5]*3+board[B6])*3+board[C7]) *3+board[D8]; if (Idx < 0) Val5 -= Diag4[-Idx]; else Val5 += Diag4[Idx]; Idx = ((board[E8]*3+board[F7])*3+board[G6]) *3+board[H5]; if (Idx < 0) Val5 -= Diag4[-Idx]; else Val5 += Diag4[Idx]; //Diag5 Val6 = 0; Idx = (((board[A5]*3+board[B4])*3+board[C3]) *3+board[D2])*3+board[E1]; if (Idx < 0) Val6 -= Diag5[-Idx]; else Val6 += Diag5[Idx]; Idx = (((board[D1]*3+board[E2])*3+board[F3]) *3+board[G4])*3+board[H5]; if (Idx < 0) Val6 -= Diag5[-Idx]; else Val6 += Diag5[Idx]; Idx = (((board[A4]*3+board[B5])*3+board[C6]) *3+board[D7])*3+board[E8]; if (Idx < 0) Val6 -= Diag5[-Idx]; else Val6 += Diag5[Idx]; Idx = (((board[D8]*3+board[E7])*3+board[F6]) *3+board[G5])*3+board[H4]; if (Idx < 0) Val6 -= Diag5[-Idx]; else Val6 += Diag5[Idx]; //Diag6 Val7 = 0; Idx = ((((board[A6]*3+board[B5])*3+board[C4]) *3+board[D3])*3+board[E2])*3+board[F1]; if (Idx < 0) Val7 -= Diag6[-Idx]; else Val7 += Diag6[Idx]; Idx = ((((board[C1]*3+board[D2])*3+board[E3]) *3+board[F4])*3+board[G5])*3+board[H6]; if (Idx < 0) Val7 -= Diag6[-Idx]; else Val7 += Diag6[Idx]; Idx = ((((board[A3]*3+board[B4])*3+board[C5]) *3+board[D6])*3+board[E7])*3+board[F8]; if (Idx < 0) Val7 -= Diag6[-Idx]; else Val7 += Diag6[Idx]; Idx = ((((board[C8]*3+board[D7])*3+board[E6]) *3+board[F5])*3+board[G4])*3+board[H3]; if (Idx < 0) Val7 -= Diag6[-Idx]; else Val7 += Diag6[Idx]; //Diag7 Val8= 0; Idx = (((((board[A7]*3+board[B6])*3+board[C5]) *3+board[D4])*3+board[E3])*3+board[F2]) *3+board[G1]; if (Idx < 0) Val8 -= Diag7[-Idx]; else Val8 += Diag7[Idx]; Idx = (((((board[B1]*3+board[C2])*3+board[D3]) *3+board[E4])*3+board[F5])*3+board[G6]) *3+board[H7]; if (Idx < 0) Val8 -= Diag7[-Idx]; else Val8 += Diag7[Idx]; Idx = (((((board[A2]*3+board[B3])*3+board[C4]) *3+board[D5])*3+board[E6])*3+board[F7]) *3+board[G8]; if (Idx < 0) Val8 -= Diag7[-Idx]; else Val8 += Diag7[Idx]; Idx = (((((board[B8]*3+board[C7])*3+board[D6]) *3+board[E5])*3+board[F4])*3+board[G3]) *3+board[H2]; if (Idx < 0) Val8 -= Diag7[-Idx]; else Val8 += Diag7[Idx]; //Diag8 Val9 = 0; Idx = ((((((board[A1]*3+board[B2])*3+board[C3]) *3+board[D4])*3+board[E5])*3+board[F6]) *3+board[G7])*3+board[H8]; if (Idx < 0) Val9 -= Diag8[-Idx]; else Val9 += Diag8[Idx]; Idx = ((((((board[A8]*3+board[B7])*3+board[C6]) *3+board[D5])*3+board[E4])*3+board[F3]) *3+board[G2])*3+board[H1]; if (Idx < 0) Val9 -= Diag8[-Idx]; else Val9 += Diag8[Idx]; //Edge8 Val0 = 0; Idx = ((((((board[A1]*3+board[B1])*3+board[C1]) *3+board[D1])*3+board[A2])*3+board[B2]) *3+board[C2])*3+board[D2]; if (Idx < 0) Val0 -= Edge8[-Idx]; else Val0 += Edge8[Idx]; Idx = ((((((board[A1]*3+board[A2])*3+board[A3]) *3+board[A4])*3+board[B1])*3+board[B2]) *3+board[B3])*3+board[B4]; if (Idx < 0) Val0 -= Edge8[-Idx]; else Val0 += Edge8[Idx]; Idx = ((((((board[H1]*3+board[G1])*3+board[F1]) *3+board[E1])*3+board[H2])*3+board[G2]) *3+board[F2])*3+board[E2]; if (Idx < 0) Val0 -= Edge8[-Idx]; else Val0 += Edge8[Idx]; Idx = ((((((board[H1]*3+board[H2])*3+board[H3]) *3+board[H4])*3+board[G1])*3+board[G2]) *3+board[G3])*3+board[G4]; if (Idx < 0) Val0 -= Edge8[-Idx]; else Val0 += Edge8[Idx]; Idx = ((((((board[A8]*3+board[B8])*3+board[C8]) *3+board[D8])*3+board[A7])*3+board[B7]) *3+board[C7])*3+board[D7]; if (Idx < 0) Val0 -= Edge8[-Idx]; else Val0 += Edge8[Idx]; Idx = ((((((board[A8]*3+board[A7])*3+board[A6]) *3+board[A5])*3+board[B8])*3+board[B7]) *3+board[B6])*3+board[B5]; if (Idx < 0) Val0 -= Edge8[-Idx]; else Val0 += Edge8[Idx]; Idx = ((((((board[H8]*3+board[G8])*3+board[F8]) *3+board[E8])*3+board[H7])*3+board[G7]) *3+board[F7])*3+board[E7]; if (Idx < 0) Val0 -= Edge8[-Idx]; else Val0 += Edge8[Idx]; Idx = ((((((board[H8]*3+board[H7])*3+board[H6]) *3+board[H5])*3+board[G8])*3+board[G7]) *3+board[G6])*3+board[G5]; if (Idx < 0) Val0 -= Edge8[-Idx]; else Val0 += Edge8[Idx]; //空きマスの数によって、隅周辺の評価値を調整する。 Val = 0; if (board[A1] == BLACK) Val -= empties*2; if (board[A1] == EMPTY && board[B2] == BLACK) Val += empties*2; if (board[A1] == WHITE) Val += empties*2; if (board[A1] == EMPTY && board[B2] == WHITE) Val -= empties*2; if (board[H1] == BLACK) Val -= empties*2; if (board[H1] == EMPTY && board[G2] == BLACK) Val += empties*2; if (board[H1] == WHITE) Val += empties*2; if (board[H1] == EMPTY && board[G2] == WHITE) Val -= empties*2; if (board[A8] == BLACK) Val -= empties*2; if (board[A8] == EMPTY && board[B7] == BLACK) Val += empties*2; if (board[A8] == WHITE) Val += empties*2; if (board[A8] == EMPTY && board[B7] == WHITE) Val -= empties*2; if (board[H8] == BLACK) Val -= empties*2; if (board[H8] == EMPTY && board[G7] == BLACK) Val += empties*2; if (board[H8] == WHITE) Val += empties*2; if (board[H8] == EMPTY && board[G7] == WHITE) Val -= empties*2; //評価値を石差の近似値に変換する。 var ev:int = (int)((Val1 + Val2 + Val3 + Val4 + Val5 + Val6 + Val7 + Val8 + Val9 + Val0 + Val) / 10); if (ev > 50) ev = 50 + (int)((ev-50) / 10); //評価値を戻す return (color == BLACK ? -ev : ev); } } Code Fullscreen Preview Fullscreen ProjectNya Mingchoi merrycat : game game color alpha Keyboard.F7 Keyboard.F2 Keyboard.F5 Keyboard.F6 Keyboard.F4 Keyboard.F8 Keyboard.F3 dispatchEvent Shape Keyboard.F1 addEventListener Timer MouseEvent.SOUND_COMPLETE transform Object undefined GlowFilter String