å
容
è»ãèããããšãã§ãããã©ããã®åé¡ã¯ãæœæ°ŽèŠãèªè¡ã§ãããã©ããã®åé¡ãšåããããé©åã§ãã
Edsger Dijkstraãã³ã³ãã¥ãŒãã£ã³ã°ãµã€ãšã³ã¹ãžã®è
åšãããžã§ã¯ãã®ç« ã§ã¯ãçè«ãæããã®ããããããã°ã©ã ã«ã€ããŠäžç·ã«åãçµã¿ãŸãã çè«ã¯ããã°ã©ãã³ã°ã®æè²ã«äžå¯æ¬ ã§ãããéèŠãªããã°ã©ã ãèªãã§çè§£ããå¿
èŠããããŸãã
ç§ãã¡ã®ãããžã§ã¯ãã¯ãç§»åããŠçåã®ããã«æŠãçãç©ãçæ¯ããå°ããªäžçã§ããä»®æ³ãšã³ã·ã¹ãã ã®æ§ç¯ã§ãã
å®çŸ©
ã¿ã¹ã¯ãå®è¡å¯èœã«ããããã«ãäžçã®æŠå¿µã倧å¹
ã«ç°¡çŽ åããŸãã ã€ãŸããäžçã¯2次å
ã®ã°ãªããã«ãªããåãšã³ãã£ãã£ã1ã€ã®ã»ã«ãå æããŸãã åã¿ãŒã³ã§ãã¯ãªãŒãã£ãŒã¯äœããã®ã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãã
ãããã£ãŠãæéãšã¹ããŒã¹ãåºå®ãµã€ãºã®åäœã«åå²ããŸããã€ãŸããã¹ããŒã¹ã®ã»ã«ãšæéã®åãã§ãã ãã¡ãããããã¯å€§éæã§ããããªè¿äŒŒã§ãã ããããç§ãã¡ã®ã·ãã¥ã¬ãŒã·ã§ã³ã¯ãé¢çœããªããŠé¢çœããªããã°ãªããªãã®ã§ãèªç±ã«ãã³ãŒããŒãã«ãããããŸãã
ãã©ã³ã®å©ããåããŠäžçãå®çŸ©ããããšãã§ããŸã-ã»ã«ããšã«1æåã䜿çšããŠäžçã°ãªãããã¬ã€ã¢ãŠãããæååã®é
åã
var plan = ["############################", "# # # o ##", "# #", "# ##### #", "## # # ## #", "### ## # #", "# ### # #", "# #### #", "# ## o #", "# o # o ### #", "# # #", "############################"];
èšå·ãïŒãã¯å£ãšç³ãæå³ãããoãã¯çç©ã§ãã ã¹ããŒã¹ã¯ç©ºã®ã¹ããŒã¹ã§ãã
èšç»ã䜿çšããŠãäžçã®ãªããžã§ã¯ããäœæã§ããŸãã 圌ã¯äžçã®èŠæš¡ãšå
容ãç£èŠããŠããŸãã ããã«ã¯ãäžçãåºåã©ã€ã³ïŒãããåºã«ããŠãããã©ââã³ãªã©ïŒã«å€æããtoStringã¡ãœããããããå
éšã§äœãèµ·ãã£ãŠãããã芳å¯ã§ããŸãã ã¯ãŒã«ãã®ãªããžã§ã¯ãã«ã¯ã¿ãŒã³ã¡ãœãããããããã¹ãŠã®ã¯ãªãŒãã£ãŒã1ã€ã®åããè¡ããã¢ã¯ã·ã§ã³ã«åŸã£ãŠã¯ãŒã«ãã®ç¶æ
ãæŽæ°ã§ããŸãã
ã¹ããŒã¹ãæã
äžçãã¢ããªã³ã°ããã°ãªããã«ã¯å¹
ãšé«ãããããŸãã ã»ã«ã¯ãxããã³y座æšã«ãã£ãŠå®çŸ©ãããŸãã ãããã®åº§æšãã¢ã衚ãã«ã¯ãåçŽãªVectorã¿ã€ãïŒåã®ç« ã®æŒç¿ããïŒã䜿çšããŸãã
function Vector(x, y) { this.x = x; this.y = y; } Vector.prototype.plus = function(other) { return new Vector(this.x + other.x, this.y + other.y); };
次ã«ãã°ãªããèªäœãã·ãã¥ã¬ãŒããããªããžã§ã¯ãã¿ã€ããå¿
èŠã§ãã ã°ãªããã¯äžçã®äžéšã§ãããäžçãªããžã§ã¯ããè€éã«ããªãããã«ãããããå¥ã®ãªããžã§ã¯ãïŒäžçãªããžã§ã¯ãã®ããããã£ã«ãªããŸãïŒãäœæããŸãã äžçã¯äžçã«é¢é£ãããã®ãèªèº«ã§ããŒãããã°ãªããã¯ã°ãªããã«é¢é£ãããã®ãããŒãããªããã°ãªããŸããã
å€ã®ã°ãªãããä¿åããããã®ããã€ãã®ãªãã·ã§ã³ããããŸãã æååé
åã®é
åã䜿çšããããããã£ãžã®2段éã¢ã¯ã»ã¹ã䜿çšã§ããŸãã
var grid = [["top left", "top middle", "top right"], ["bottom left", "bottom middle", "bottom right"]]; console.log(grid[1][2]);
ãŸãã¯ãå¹
Ãé«ãã®ãµã€ãºã®1ã€ã®é
åã䜿çšããŠãèŠçŽ ïŒxãyïŒãäœçœ®x +ïŒyÃwidthïŒã«ãããšå€æã§ããŸãã
var grid = ["top left", "top middle", "top right", "bottom left", "bottom middle", "bottom right"]; console.log(grid[2 + (1 * 3)]);
ã¢ã¯ã»ã¹ã¯ã¡ãã·ã¥ãªããžã§ã¯ãã®ã¡ãœããã«ã©ããããããããå€éšã³ãŒãã¯ã©ã¡ãã®ã¢ãããŒããéžæãããããæ°ã«ããŸããã ã¢ã¬ã€ãäœæããæ¹ãç°¡åãªã®ã§ã2çªç®ãéžæããŸããã 1ã€ã®æ°å€ãåŒæ°ãšããŠArrayã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºããšãæå®ãããé·ãã®æ°ãã空ã®é
åãäœæãããŸãã
次ã®ã³ãŒãã¯ãã¡ã€ã³ã¡ãœããã§ã°ãªãããªããžã§ã¯ãã宣èšããŸãã
function Grid(width, height) { this.space = new Array(width * height); this.width = width; this.height = height; } Grid.prototype.isInside = function(vector) { return vector.x >= 0 && vector.x < this.width && vector.y >= 0 && vector.y < this.height; }; Grid.prototype.get = function(vector) { return this.space[vector.x + this.width * vector.y]; }; Grid.prototype.set = function(vector, value) { this.space[vector.x + this.width * vector.y] = value; };
åºç€è©ŠéšïŒ
var grid = new Grid(5, 5); console.log(grid.get(new Vector(1, 1)));
ã¯ãªãŒãã£ãŒããã°ã©ãã³ã°ã€ã³ã¿ãŒãã§ã€ã¹
ã¯ãŒã«ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒãåãäžããåã«ãããã«çæ¯ããã¯ãªãŒãã£ãŒã®ãªããžã§ã¯ããæ±ºå®ããå¿
èŠããããŸãã ç§ã¯ãäžçã¯çãç©ã«åœŒããäœããããã®ããå°ãããšè¿°ã¹ãã ããã¯æ¬¡ã®ããã«æ©èœããŸãããã¹ãŠã®ã¯ãªãŒãã£ãŒãªããžã§ã¯ãã«ã¯ãåŒã³åºããããšãã«ã¢ã¯ã·ã§ã³ãè¿ãactã¡ãœããããããŸãã ã¢ã¯ã·ã§ã³-ã¿ã€ãããããã£ã®ãªããžã§ã¯ããã¯ãªãŒãã£ãŒãå®è¡ãããã¢ã¯ã·ã§ã³ã®ã¿ã€ããããšãã°ãç§»åããæå®ããŸãã ã¢ã¯ã·ã§ã³ã«ã¯ãç§»åæ¹åãªã©ã®è¿œå æ
å ±ãå«ãŸããå ŽåããããŸãã
ã¯ãªãŒãã£ãŒã¯ã²ã©ãè¿èŠçŒçã§ãããçãç©ã®ããé£ã«ãã现èããèŠããŸããã ããããããã¯ã¢ã¯ã·ã§ã³ãéžæãããšãã«åœ¹ç«ã¡ãŸãã actã¡ãœãããåŒã³åºããããšããã¥ãŒãªããžã§ã¯ããäžããããã¯ãªãŒãã£ãŒãåšå²ã®ãšãªã¢ãæ¢çŽ¢ã§ããããã«ãªããŸãã 8ã€ã®é£æ¥ããã»ã«ãã³ã³ãã¹æ¹åãšåŒã³ãŸãããnãã¯åããneãã¯åæ±ãªã©ã§ãã æ¹åã®ååãã座æšãªãã»ããã«å€æããããã«äœ¿çšããããªããžã§ã¯ãã¯æ¬¡ã®ãšããã§ãã
var directions = { "n": new Vector( 0, -1), "ne": new Vector( 1, -1), "e": new Vector( 1, 0), "se": new Vector( 1, 1), "s": new Vector( 0, 1), "sw": new Vector(-1, 1), "w": new Vector(-1, 0), "nw": new Vector(-1, -1) };
ãã¥ãŒãªããžã§ã¯ãã«ã¯ãæ¹åãååŸããŠæåãè¿ãlookã¡ãœããããããŸããããšãã°ãå£ãããå Žåã¯ãïŒããäœããªãå Žåã¯ã¹ããŒã¹ã§ãã ãã®ãªããžã§ã¯ãã¯ã䟿å©ãªfindããã³findAllã¡ãœãããæäŸããŸãã ã©ã¡ãããåŒæ°ãšããŠãããäžã®ãã®ã衚ãæåã®1ã€ãåããŸãã æåã¯ããã®ã¢ã€ãã ãã¯ãªãŒãã£ãŒã®é£ã§èŠã€ããæ¹åãè¿ããŸãããã®ãããªã¢ã€ãã ãè¿ãã«ãªãå Žåã¯nullãè¿ããŸãã 2çªç®ã¯ããã®ãããªãªããžã§ã¯ããèŠã€ãã£ããã¹ãŠã®å¯èœãªæ¹åãå«ãé
åãè¿ããŸãã ããšãã°ãå£ã®å·ŠåŽïŒè¥¿åŽïŒã®ã¯ãªãŒãã£ãŒã¯ãåŒæ° "ïŒ"ãæå®ããŠfindAllãåŒã³åºããšã["ne"ã "e"ã "se"]ãåãåããŸãã
ããã¯ãé害ç©ã«è¡çªããŠã©ã³ãã ãªæ¹åã«è·³ãè¿ããŸã§æ©ãã ãã®åçŽãªãã çç©ã§ãã
function randomElement(array) { return array[Math.floor(Math.random() * array.length)]; } function BouncingCritter() { this.direction = randomElement(Object.keys(directions)); }; BouncingCritter.prototype.act = function(view) { if (view.look(this.direction) != " ") this.direction = view.find(" ") || "s"; return {type: "move", direction: this.direction}; };
ãã«ããŒé¢æ°randomElementã¯ãMath.randomãšå°ãã®ç®è¡æŒç®ã䜿çšããŠã©ã³ãã é
åèŠçŽ ãéžæããã©ã³ãã ã€ã³ããã¯ã¹ãååŸããŸãã ã©ã³ãã æ§ã¯ã·ãã¥ã¬ãŒã·ã§ã³ã§åœ¹ç«ã€ãããåŒãç¶ãã©ã³ãã æ§ã䜿çšããŸãã
BouncingCritterã³ã³ã¹ãã©ã¯ã¿ãŒã¯Object.keysãåŒã³åºããŸãã åã®ç« ã§ãã®é¢æ°ãèŠãŸãã-ãªããžã§ã¯ãã®ãã¹ãŠã®ããããã£åãå«ãé
åãè¿ããŸãã ããã§ã圌女ã¯åã«æå®ããã«ãŒããªããžã§ã¯ããããã¹ãŠã®ã«ãŒãåãååŸããŸãã
æ§é ã|| actã¡ãœããã®ãsãã¯ãã¯ãªãŒãã£ãŒã空ãã¹ããŒã¹ã®ãªãé
ã«éãŸã£ãŠããå Žåã«this.directionãnullã«ãªããªãããã«ããããã«å¿
èŠã§ããããšãã°ãä»ã®ã¯ãªãŒãã£ãŒã«å²ãŸããŠããŸãã
ã¯ãŒã«ããªããžã§ã¯ã
ããã§ãã¯ãŒã«ããªããžã§ã¯ãWorldã«é²ãããšãã§ããŸãã ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ããã©ã³ïŒäžçã®ã°ãªããã衚ãæååã®é
åïŒãšå¡äŸãªããžã§ã¯ããåãå
¥ããŸãã ããã¯ãåãããã·ã³ãã«ã®æå³ãå ±åãããªããžã§ã¯ãã§ãã nullïŒç©ºã®ã¹ããŒã¹ã衚ãïŒãåç
§ããã¹ããŒã¹ãé€ããŠãåæåã®ã³ã³ã¹ãã©ã¯ã¿ãŒããããŸãã
function elementFromChar(legend, ch) { if (ch == " ") return null; var element = new legend[ch](); element.originChar = ch; return element; } function World(map, legend) { var grid = new Grid(map[0].length, map.length); this.grid = grid; this.legend = legend; map.forEach(function(line, y) { for (var x = 0; x < line.length; x++) grid.set(new Vector(x, y), elementFromChar(legend, line[x])); }); }
elementFromCharã§ã¯ãæåã«ç®çã®åã®ã€ã³ã¹ã¿ã³ã¹ãäœæããã·ã³ãã«ã³ã³ã¹ãã©ã¯ã¿ãŒãèŠã€ããŠãããã«æ°ãããã®ãé©çšããŸãã æ¬¡ã«ãoriginCharããããã£ã远å ããŠãèŠçŽ ãæåã«äœæãããã·ã³ãã«ãç°¡åã«èŠã€ããããããã«ããŸãã
ã¯ãŒã«ãtoStringã¡ãœãããäœæããã«ã¯ããã®originCharããããã£ãå¿
èŠã§ãã ãã®ã¡ãœããã¯ãäžçã®çŸåšã®ç¶æ
ããæååãšããŠããããäœæããã°ãªããã®ã»ã«ã«2次å
ã®ãµã€ã¯ã«ãæž¡ããŸãã
function charFromElement(element) { if (element == null) return " "; else return element.originChar; } World.prototype.toString = function() { var output = ""; for (var y = 0; y < this.grid.height; y++) { for (var x = 0; x < this.grid.width; x++) { var element = this.grid.get(new Vector(x, y)); output += charFromElement(element); } output += "\n"; } return output; };
å£å£ã¯åçŽãªãªããžã§ã¯ãã§ãã ã¹ããŒã¹ãå æããããã«äœ¿çšãããactã¡ãœããã¯ãããŸããã
function Wall() {}
Worldãªããžã§ã¯ãã確èªããç« ã®æåã§æå®ãããã©ã³ã䜿çšããŠã€ã³ã¹ã¿ã³ã¹ãäœæãããã®toStringã¡ãœãããåŒã³åºããšããã®ãã©ã³ã«éåžžã«äŒŒãè¡ãåŸãããŸãã
var world = new World(plan, {"#": Wall, "o": BouncingCritter}); console.log(world.toString());
ãããšãã®ç¯å²
Worldã³ã³ã¹ãã©ã¯ã¿ãŒã«ã¯forEachã®åŒã³åºãããããŸãã forEachã«æž¡ããã颿°å
ã§ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒã®ã¹ã³ãŒãå
ã«çŽæ¥ããªãããšã«æ³šæããŠãã ããã å颿°åŒã³åºãã¯ç¬èªã®åå空éãååŸããããããã®å
éšã®ããã¯ã颿°ã®å€éšãåç
§ããäœæããããªããžã§ã¯ããåç
§ããªããªããŸãã äžè¬ã«ã颿°ãã¡ãœãããšããŠåŒã³åºãããªãå Žåãããã¯ã°ããŒãã«ãªããžã§ã¯ããåç
§ããŸãã
ãããã£ãŠãã«ãŒãå
ããã°ãªããã«ã¢ã¯ã»ã¹ããããã«this.gridãèšè¿°ããããšã¯ã§ããŸããã 代ããã«ãå€éšé¢æ°ã¯ãå
éšé¢æ°ãã°ãªããã«ã¢ã¯ã»ã¹ããããã®ããŒã«ã«ã°ãªãã倿°ãäœæããŸãã
ããã¯JavaScriptãã¶ã€ã³ã®å€±æã§ãã 幞ããªããšã«ã次ã®ããŒãžã§ã³ã«ã¯ãã®åé¡ã®è§£æ±ºçããããŸãã ãããŸã§ã®éãåé¿çããããŸãã éåžžæžã
var self = this
ãã®åŸã圌ãã¯èªå·±å€æ°ãæäœããŸãã
å¥ã®è§£æ±ºçã¯bindã¡ãœããã䜿çšããããšã§ããããã«ãããç¹å®ã®thisãªããžã§ã¯ãã«ãã€ã³ãã§ããŸãã
var test = { prop: 10, addPropTo: function(array) { return array.map(function(elt) { return this.prop + elt; }.bind(this)); } }; console.log(test.addPropTo([5]));
mapã«æž¡ããã颿°ã¯åŒã³åºããã€ã³ãã£ã³ã°ã®çµæã§ããããããã®thisã¯bindã«æž¡ãããæåã®åŒæ°ãã€ãŸãå€éšé¢æ°ïŒãã¹ããªããžã§ã¯ããå«ãïŒã®this倿°ã«ãã€ã³ããããŸãã
forEachãmapãªã©ãé
åã®æšæºçãªé«æ¬¡ã¡ãœããã®ã»ãšãã©ã¯ããªãã·ã§ã³ã®2çªç®ã®åŒæ°ãåãå
¥ããŸããããã¯ãååŸ©é¢æ°ãåŒã³åºããšãã«ãããæž¡ãããã«ã䜿çšã§ããŸãã åã®äŸãå°ãç°¡åã«æžãããšãã§ããŸãã
var test = { prop: 10, addPropTo: function(array) { return array.map(function(elt) { return this.prop + elt; }, this);
ããã¯ããã®ãããªã³ã³ããã¹ããã©ã¡ãŒã¿ãæã€é«é颿°ã§ã®ã¿æ©èœããŸãã ããã§ãªãå Žåã¯ãåè¿°ã®ä»ã®ã¢ãããŒãã䜿çšããå¿
èŠããããŸãã
ç¬èªã®é«é颿°ã§ã¯ãcallã¡ãœããã䜿çšããŠåŒæ°ãšããŠæž¡ããã颿°ãåŒã³åºãã³ã³ããã¹ããã©ã¡ãŒã¿ãŒãµããŒããæå¹ã«ã§ããŸãã ããšãã°ãnullãŸãã¯æªå®çŸ©ã§ã¯ãªãåã©ãã£ã¹èŠçŽ ã«å¯ŸããŠç¹å®ã®é¢æ°ãåŒã³åºãGridã¿ã€ãã®forEachã¡ãœããã¯æ¬¡ã®ãšããã§ãã
Grid.prototype.forEach = function(f, context) { for (var y = 0; y < this.height; y++) { for (var x = 0; x < this.width; x++) { var value = this.space[x + y * this.width]; if (value != null) f.call(context, value, new Vector(x, y)); } } };
äžçãèããã
次ã®ã¹ãããã¯ãã¯ãªãŒãã£ãŒãè¡åã§ããããã«ããã¯ãŒã«ããªããžã§ã¯ãã®ã¿ãŒã³ã¡ãœããïŒã¹ãããïŒãäœæããããšã§ãã forEachã¡ãœããã§ã°ãªãããèµ°æ»ããactã¡ãœãããæã€ãªããžã§ã¯ããæ¢ããŸãã ãªããžã§ã¯ããèŠã€ãã£ãããturnã¯ãã®ã¡ãœãããåŒã³åºããŠãã¢ã¯ã·ã§ã³ãªããžã§ã¯ããååŸããæå¹ãªå Žåã¯ãã®ã¢ã¯ã·ã§ã³ãçæããŸãã ãããŸã§ã®ãšããããç§»åãã¢ã¯ã·ã§ã³ã®ã¿ãçè§£ããŠããŸãã
èããããåé¡ã1ã€ãããŸãã ã©ããèŠããŸããïŒ äžŠã¹æ¿ãããšãã«ã¯ãªãŒãã£ãŒãç§»åã§ããããã«ãããšããŸã åŠçãããŠããªãã»ã«ã«ç§»åã§ããã¿ãŒã³ããã®ã»ã«ã«éãããšãã«åã³ç§»åã§ããããã«ãªããŸãã ãããã£ãŠããã§ã«äžæ©é²ãã ã¯ãªãŒãã£ãŒã®é
åãä¿åããåééãããšãã«ããããç¡èŠããå¿
èŠããããŸãã
World.prototype.turn = function() { var acted = []; this.grid.forEach(function(critter, vector) { if (critter.act && acted.indexOf(critter) == -1) { acted.push(critter); this.letAct(critter, vector); } }, this); };
forEachã¡ãœããã®2çªç®ã®ãã©ã¡ãŒã¿ãŒã¯ãå
éšé¢æ°ã®æ£ããthis倿°ã«ã¢ã¯ã»ã¹ããããã«äœ¿çšãããŸãã letActã¡ãœããã«ã¯ãã¯ãªãŒãã£ãŒã®ç§»åãèš±å¯ããããžãã¯ãå«ãŸããŠããŸãã
World.prototype.letAct = function(critter, vector) { var action = critter.act(new View(this, vector)); if (action && action.type == "move") { var dest = this.checkDestination(action, vector); if (dest && this.grid.get(dest) == null) { this.grid.set(vector, null); this.grid.set(dest, critter); } } }; World.prototype.checkDestination = function(action, vector) { if (directions.hasOwnProperty(action.direction)) { var dest = vector.plus(directions[action.direction]); if (this.grid.isInside(dest)) return dest; } };
ãŸããã¯ãªãŒãã£ãŒã«ã¢ã¯ã·ã§ã³ãèŠæ±ããã ãã§ãã¯ãŒã«ããšãã®ã¯ãªãŒãã£ãŒã®ã¯ãŒã«ãå
ã®çŸåšäœçœ®ãç¥ããã¥ãŒãªããžã§ã¯ããæž¡ããŸãïŒããã«ãã¥ãŒãèšå®ããŸãïŒã actã¡ãœããã¯ã¢ã¯ã·ã§ã³ãè¿ããŸãã
ã¢ã¯ã·ã§ã³ã®ã¿ã€ãããç§»åãã§ã¯ãªãå Žåãç¡èŠãããŸãã ãç§»åãããæå¹ãªæ¹åãåç
§ããæ¹åããããã£ãããããã®æ¹åã®ã»ã«ã空ïŒnullïŒã§ããå Žåãã¯ãªãŒãã£ãŒãåã«nullã§ãã£ãã»ã«ãå²ãåœãŠãã¯ãªãŒãã£ãŒãå®å
ã»ã«ã«ä¿åããŸãã
letActã¯ç¡å¹ãªå
¥åãç¡èŠããããšã«æ³šæããŠãã ããã ããã©ã«ãã§ã¯ãæ¹åãæå¹ã§ããããšããã¿ã€ãããããã£ãæå³ããªããšã¯æ³å®ããŠããŸããã ãã®çš®ã®é²åŸ¡çãªããã°ã©ãã³ã°ã¯ãç¶æ³ã«ãã£ãŠã¯çã«ããªã£ãŠããŸãã ããã¯äž»ã«ãå¶åŸ¡ããŠããªããœãŒã¹ïŒãŠãŒã¶ãŒå
¥åãŸãã¯ãã¡ã€ã«ã®èªã¿åãïŒããã®å
¥åããã§ãã¯ããããã«è¡ãããŸããããµãã·ã¹ãã ãçžäºã«åé¢ããã®ã«ã圹ç«ã¡ãŸãã ç§ãã¡ã®å Žåããã®ç®çã¯ãã¯ãªãŒãã£ãŒãäžæ£ç¢ºã«ããã°ã©ã ãããå¯èœæ§ãããããšãèæ
®ããããšã§ãã 圌ãã®æå³ãçã«ããªã£ãŠãããã©ããããã§ãã¯ããå¿
èŠã¯ãããŸããã 圌ãã¯åã«è¡åã®å¯èœæ§ãèŠæ±ããäžçèªäœããããèš±å¯ãããã©ãããæ±ºå®ããŸãã
ãããã®2ã€ã®ã¡ãœããã¯ãã¯ãŒã«ããªããžã§ã¯ãã®å€éšã€ã³ã¿ãŒãã§ã€ã¹ã«å±ããŠããŸããã ãããã¯å
éšå®è£
ã®äžéšã§ãã äžéšã®èšèªã¯ãç¹å®ã®ã¡ãœãããšããããã£ãããã©ã€ããŒããã«å®£èšãããªããžã§ã¯ãã®å€éšã§äœ¿çšããããšãããšãšã©ãŒãã¹ããŒããæ¹æ³ãæäŸããŸãã JavaScriptã§ã¯ãããæäŸãããªãããããªããžã§ã¯ãã®ã€ã³ã¿ãŒãã§ã€ã¹ã®äžéšãå ±åããã«ã¯ãä»ã®ã¡ãœããã«äŸåããå¿
èŠããããŸãã ããšãã°ãã¢ã³ããŒã¹ã³ã¢ïŒ_ïŒãªã©ã®å
éšåã®ç¹å¥ãªãã¬ãã£ãã¯ã¹ã䜿çšããŠãããããã£ã®åœåã¹ããŒã ã䜿çšããŠå
éšãšå€éšãåºå¥ãããšåœ¹ç«ã€å ŽåããããŸãã ããã«ãããã€ã³ã¿ãŒãã§ã€ã¹ã®äžéšã§ã¯ãªãããããã£ã®å¶çºçãªäœ¿çšã®èå¥ã容æã«ãªããŸãã
äžè¶³ããŠããéšåã§ããViewãšå
¥åãããšã次ã®ããã«ãªããŸãã
function View(world, vector) { this.world = world; this.vector = vector; } View.prototype.look = function(dir) { var target = this.vector.plus(directions[dir]); if (this.world.grid.isInside(target)) return charFromElement(this.world.grid.get(target)); else return "#"; }; View.prototype.findAll = function(ch) { var found = []; for (var dir in directions) if (this.look(dir) == ch) found.push(dir); return found; }; View.prototype.find = function(ch) { var found = this.findAll(ch); if (found.length == 0) return null; return randomElement(found); };
lookã¡ãœããã¯ãèŠãããšããŠãã座æšãèšç®ããŸãã ããããã°ãªããå
ã«ããå Žåãããã«ããèŠçŽ ã«å¯Ÿå¿ããã·ã³ãã«ãååŸããŸãã ã°ãªããã®å€åŽã®åº§æšã«ã€ããŠã¯ãå£ã®ãµããããŠãã ãã-åšå²ã®å£ã®ãªãäžçãèšå®ãããšãã¯ãªãŒãã£ãŒã¯ç«¯ããåºãããªããªããŸãã
åã
ã¯ãŒã«ããªããžã§ã¯ãã®ã³ããŒãäœæããŸããã å¿
èŠãªãã¹ãŠã®ã¡ãœãããæºåã§ããã®ã§ããããåããããšãã§ããã¯ãã§ãã
for (var i = 0; i < 5; i++) { world.turn(); console.log(world.toString()); }
å°å³ã®5ã€ã®ã³ããŒã衚瀺ããã ãã§ã¯ãäžçã芳å¯ããã®ã«ããŸã䟿å©ãªæ¹æ³ã§ã¯ãããŸããã ãããã£ãŠãæ¬ã®ãµã³ãããã¯ã¹ïŒãŸãã¯
ããŠã³ããŒãçšã®ãã¡ã€ã« ïŒã«ã¯éæ³ã®é¢æ°animateWorldããããã¹ããããæŒããŸã§ç»é¢äžã«äžçãã¢ãã¡ãŒã·ã§ã³ãšããŠè¡šç€ºããæ¯ç§3ã¹ããããå®è¡ããŸãã
animateWorld(world);
animateWorldã®å®è£
ã¯è¬ã®ãŸãŸã§ãããJavaScriptã®ãã©ãŠã¶ãžã®çµ±åã«ã€ããŠèª¬æããŠããæ¬ã®ä»¥äžã®ç« ãèªãã åŸãããã»ã©ç¥ç§çã«ã¯ãªããŸããã
ããå€ãã®çåœäœ
äžçã§èµ·ãã£ãŠããè峿·±ãç¶æ³ã®1ã€ã¯ã2ã€ã®ã¯ãªãŒãã£ãŒãäºãã«è·³ãè¿ã£ããšãã«èµ·ãããŸãã å¥ã®è峿·±ã圢ã®ããåããæãã€ãããšãã§ããŸããïŒ
å£ã«æ²¿ã£ãŠåãçãç©ãæãã€ããŸããã å·ŠæïŒè¶³ãè§Šæãªã©ïŒãå£ã«ä¿æããå£ã«æ²¿ã£ãŠç§»åããŸãã çµå±ã®ãšãããããã¯ããã°ã©ã ããã®ãããã»ã©ç°¡åã§ã¯ãããŸããã
空éå
ã®æ¹åã䜿çšããŠèšç®ããå¿
èŠããããŸãã æ¹åã¯äžé£ã®ç·ã§äžãããããããçžå¯Ÿæ¹åãèšç®ããã«ã¯ç¬èªã®dirPlusæäœãèšå®ããå¿
èŠããããŸãã dirPlusïŒãnãã1ïŒã¯ãæèšåãã«45床åãæå³ãããneãã«ãªããŸãã dirPlusïŒ "s"ã-2ïŒã¯ãåããæ±ãžã®åæèšåãã®å転ãæå³ããŸãã
var directionNames = Object.keys(directions); function dirPlus(dir, n) { var index = directionNames.indexOf(dir); return directionNames[(index + n + 8) % 8]; } function WallFollower() { this.dir = "s"; } WallFollower.prototype.act = function(view) { var start = this.dir; if (view.look(dirPlus(this.dir, -3)) != " ") start = this.dir = dirPlus(this.dir, -2); while (view.look(this.dir) != " ") { this.dir = dirPlus(this.dir, 1); if (this.dir == start) break; } return {type: "move", direction: this.dir}; };
actã¡ãœããã¯ã空ã®ã»ã«ãèŠã€ãããŸã§ãå·ŠåŽããæèšåãã«ã¯ãªãŒãã£ãŒã®ç°å¢ã®ã¿ãã¹ãã£ã³ããŸãã æ¬¡ã«ããã®ã»ã«ã«åãã£ãŠç§»åããŸãã
ç¶æ³ãè€éã«ããŠããã®ã¯ãã¯ãªãŒãã£ãŒã空ãã¹ããŒã¹ã®å£ããé ãé¢ããŠããå¯èœæ§ãããããšã§ããã€ãŸããå¥ã®ã¯ãªãŒãã£ãŒããã€ãã¹ããããæåã«ããã«ããããšã§ãã èšèŒãããã¢ã«ãŽãªãºã ãé¢ãããšãäžå¹žãªã¯ãªãŒãã£ãŒã¯æ¯ã¿ãŒã³å·Šã«æ²ãããåãæãããã«èµ°ããŸãã
ãã®ãããã¯ãªãŒãã£ãŒãé害ç©ãééããçŽåŸã«ã¹ãã£ã³ãéå§ããå¿
èŠãããå Žåã¯ãå¥ã®ãã§ãã¯ãè¡ãããŸãã ã€ãŸããèé¢ãšå·ŠåŽã®ã¹ããŒã¹ã空ã§ãªãå Žåã§ãã ãã以å€ã®å Žåã¯ãå
ã«ã¹ãã£ã³ãéå§ããããã空ãã¹ããŒã¹ã§ã¯çŽé²ããŸãã
æåŸã«ãthis.dirã®äžèŽããã§ãã¯ãããµã€ã¯ã«ã®åããã»ãŒãžã§éå§ããŸããããã«ãããã¯ãªãŒãã£ãŒãå£ãä»ã®ã¯ãªãŒãã£ãŒã®åŸãããè¡ãå Žæããªãã空ã®ã»ã«ãèŠã€ãããªãå Žåã«ããµã€ã¯ã«ã«å
¥ããªãããã«ããŸãã
ãã®å°ããªäžçã¯ãå£ã«æ²¿ã£ãŠåãçç©ã瀺ããŠããŸãã
animateWorld(new World( ["############", "# # #", "# ~ ~ #", "# ## #", "# ## o####", "# #", "############"], {"#": Wall, "~": WallFollower, "o": BouncingCritter} ));
ããå€ãã®çæŽ»ç¶æ³
ç§ãã¡ã®å°ããªäžçã§ã®ç掻ãããé¢çœãããããã«ãé£ç©ãšçæ®ã®æŠå¿µã远å ããŸãã ããããã®çãç©ã«ã¯ãšãã«ã®ãŒããããè¡åãå®è¡ããããšæžå°ããé£ã¹ç©ãé£ã¹ããšå¢å ããŸãã ã¯ãªãŒãã£ãŒãååãªãšãã«ã®ãŒãæã£ãŠããå Žåãããã¯å¢æ®ããŠåãã¿ã€ãã®æ°ããã¯ãªãŒãã£ãŒãäœæã§ããŸãã èšç®ãç°¡çŽ åããããã«ãç§ãã¡ã®çãç©ã¯èªåã§åçããŸãã
çãç©ããã åããŠãäºããé£ã¹ããšãäžçã¯ããã«ãšã³ããããŒã®å¢å ã«å±ãããšãã«ã®ãŒã¯ããã§çµãããç æŒ ã«å€ãããŸãã ãã®çµäºïŒãŸãã¯é
å»¶ïŒãé²ãããã«ãæ€ç©ã远å ããŸãã 圌ãã¯åããŸããã 圌ãã¯åã«å
åæã«åŸäºããæé·ïŒãšãã«ã®ãŒãçæïŒãã墿®ããŸãã
ãããæ©èœããããã«ã¯ãç°ãªãletActã¡ãœãããæã€äžçãå¿
èŠã§ãã ã¯ãŒã«ããããã¿ã€ãã¡ãœããã眮ãæããããšãã§ããŸãããç§ã¯å£ã®äžãæ©ãçç©ã®ã·ãã¥ã¬ãŒã·ã§ã³ã«æ
£ããŠããããããç Žå£ããããããŸããã
1ã€ã®è§£æ±ºçã¯ãç¶æ¿ã䜿çšããããšã§ãã æ°ãããããã¿ã€ãLifelikeWorldãäœæããŠããŸãããã®ãããã¿ã€ãã®ãããã¿ã€ãã¯Worldãããã¿ã€ãã«åºã¥ããŠããŸãããletActã¡ãœããããªãŒããŒã©ã€ãããŸãã æ°ããletActã¯ãã¢ã¯ã·ã§ã³ãã³ãããããäœæ¥ãactionTypesãªããžã§ã¯ãã«æ ŒçŽãããŠããããŸããŸãªé¢æ°ã«è»¢éããŸãã
function LifelikeWorld(map, legend) { World.call(this, map, legend); } LifelikeWorld.prototype = Object.create(World.prototype); var actionTypes = Object.create(null); LifelikeWorld.prototype.letAct = function(critter, vector) { var action = critter.act(new View(this, vector)); var handled = action && action.type in actionTypes && actionTypes[action.type].call(this, critter, vector, action); if (!handled) { critter.energy -= 0.2; if (critter.energy <= 0) this.grid.set(vector, null); } };
æ°ããletActã¡ãœããã¯ãå°ãªããšãããã€ãã®ã¢ã¯ã·ã§ã³ãæž¡ããããã©ããããã§ãã¯ãããããåŠçãã颿°ããããã©ãããæåŸã«ãã®é¢æ°ãtrueãè¿ããã¢ã¯ã·ã§ã³ãæ£åžžã«å®äºããããšã瀺ããŸãã ãããä»ããŠé¢æ°ãã¯ãŒã«ããªããžã§ã¯ãã«ã¢ã¯ã»ã¹ã§ããããã«ããããã®åŒã³åºãã®äœ¿çšã«æ³šæããŠãã ããã
äœããã®çç±ã§ã¢ã¯ã·ã§ã³ãæ©èœããªãå Žåãã¯ãªãŒãã£ãŒã®ããã©ã«ãã®ã¢ã¯ã·ã§ã³ã¯åŸ
æ©ã§ãã 圌ã¯ãšãã«ã®ãŒã®0.2åäœã倱ãããšãã«ã®ãŒã¬ãã«ã0æªæºã«äžãããšãåœŒã¯æ»ã«ãã°ãªããããæ¶ããŸãã
ã¢ã¯ã·ã§ã³ãã³ãã©ãŒ
æãåçŽãªã¢ã¯ã·ã§ã³ã¯æé·ã§ãããæ€ç©ã¯ããã䜿çšããŸãã ã¿ã€ã{typeïŒ "grow"}ã®ã¢ã¯ã·ã§ã³ãªããžã§ã¯ããè¿ããããšã次ã®ãã³ãã©ãŒã¡ãœãããåŒã³åºãããŸãã
actionTypes.grow = function(critter) { critter.energy += 0.5; return true; };
æé·ã¯åžžã«æåããæ€ç©ã®ãšãã«ã®ãŒã¬ãã«ã«ååã®åäœã远å ããŸããåãã¯ãã£ãšè€éã§ãã actionTypes.move = function(critter, vector, action) { var dest = this.checkDestination(action, vector); if (dest == null || critter.energy <= 1 || this.grid.get(dest) != null) return false; critter.energy -= 1; this.grid.set(vector, null); this.grid.set(dest, critter); return true; };
ãã®ã¢ã¯ã·ã§ã³ã¯æåã«ã以åã«å®£èšãããcheckDestinationã¡ãœããã䜿çšããŠãã¢ã¯ã·ã§ã³ãæå¹ãªæ¹åãæäŸãããã©ããããã§ãã¯ããŸããããã§ãªãå ŽåããŸãã¯ãã®æ¹åã§é åã空ã§ãªãå ŽåããŸãã¯ã¯ãªãŒãã£ãŒã«ãšãã«ã®ãŒãäžè¶³ããŠããå Žå-moveã¯falseãè¿ããã¢ã¯ã·ã§ã³ãå®è¡ãããªãã£ãããšã瀺ããŸããããã§ãªããã°ã圌ã¯ã¯ãªãŒãã£ãŒãåããããšãã«ã®ãŒãåŒããŸããåãã«å ããŠãã¯ãªãŒãã£ãŒã¯é£ã¹ãããšãã§ããŸãã actionTypes.eat = function(critter, vector, action) { var dest = this.checkDestination(action, vector); var atDest = dest != null && this.grid.get(dest); if (!atDest || atDest.energy == null) return false; critter.energy += atDest.energy; this.grid.set(dest, null); return true; };
å¥ã®ã¯ãªãŒãã£ãŒãé£ã¹ãã«ã¯ãæå¹ãªæåæ§ã»ã«ã®æºåãå¿
èŠã§ãããã®å Žåãã»ã«ã«ã¯ãšãã«ã®ãŒã®ãããã®ãããšãã°çãç©ãå«ãŸããŠããå¿
èŠããããŸãïŒå£ã§ã¯ãªããé£ã¹ãããŸããïŒãããã確èªããããšãé£ã¹ã人ã®ãšãã«ã®ãŒã¯é£ã¹ã人ã«è¡ããç ç²è
ã¯ã°ãªããããåãé€ãããŸããæåŸã«ãã¯ãªãŒãã£ãŒã®å¢æ®ãèš±å¯ããŸãã actionTypes.reproduce = function(critter, vector, action) { var baby = elementFromChar(this.legend, critter.originChar); var dest = this.checkDestination(action, vector); if (dest == null || critter.energy <= 2 * baby.energy || this.grid.get(dest) != null) return false; critter.energy -= 2 * baby.energy; this.grid.set(dest, baby); return true; };
åçã¯ãæ°çå
ã®2åã®ãšãã«ã®ãŒãæ¶è²»ããŸãããããã£ãŠãå
ã®ã¯ãªãŒãã£ãŒã§elementFromCharã䜿çšããŠä»®æ³ã®åå«ãäœæããŸããåå«ãã§ãããããã®ãšãã«ã®ãŒã¬ãã«ã調ã¹ã芪ãåºç£ããã®ã«ååãªãšãã«ã®ãŒãæã£ãŠãããã©ããã確èªã§ããŸããæå¹ãªæ¹åã»ã«ãå¿
èŠã§ãããã¹ãŠãæ£åžžã§ããå Žåãåå«ã¯ã°ãªããäžã«é
眮ããïŒãããŠä»®æ³çã§ã¯ãªããªããŸãïŒããšãã«ã®ãŒãç¡é§ã«ãªããŸããäžçã«äœã
ããã§ãæ¬ç©ã«äŒŒãã¯ãªãŒãã£ãŒãã·ãã¥ã¬ãŒãããããã®åºç€ãã§ããŸãããå€ããã®ããæ°ããäžçã«çãç©ãå
¥ããããšã¯ã§ããŸããããããã¯ãšãã«ã®ãŒç¹æ§ãæããªããããæ»ã¬ã ãã§ããæ°ãããã®ãäœããŸãããããŸããæ€ç©ãæžããŸããããã¯å®éãããªãåçŽãªçåœã§ãã function Plant() { this.energy = 3 + Math.random() * 4; } Plant.prototype.act = function(context) { if (this.energy > 15) { var space = context.find(" "); if (space) return {type: "reproduce", direction: space}; } if (this.energy < 20) return {type: "grow"}; };
æ€ç©ã¯ã3ã7ã®ã©ã³ãã ãªãšãã«ã®ãŒã¬ãã«ã§éå§ãããããäžåºŠã«ãã¹ãŠãå¢å ããããšã¯ãããŸãããæ€ç©ã15ã®ãšãã«ã®ãŒã«éãããšãè¿ãã«ç©ºã®ã»ã«ããããŸã-ããã¯ããã«å¢æ®ããŸãã墿®ã§ããªãå Žåã¯ããšãã«ã®ãŒ20ã«éãããŸã§åçŽã«æé·ããŸããæ¬¡ã«ãæ€ç©ãé£ã¹ã人ãå®çŸ©ããŸãã function PlantEater() { this.energy = 20; } PlantEater.prototype.act = function(context) { var space = context.find(" "); if (this.energy > 60 && space) return {type: "reproduce", direction: space}; var plant = context.find("*"); if (plant) return {type: "eat", direction: plant}; if (space) return {type: "move", direction: space}; };
æ€ç©ã®å Žåãèšå·*-ã¯ãªãŒãã£ãŒãé£ç©ãæ¢ããŠæ¢ãèšå·ã䜿çšããŸããåœãå¹ã蟌ã
ãããŠä»ãç§ãã¡ã¯æ°ããäžçã«ååãªèŠçŽ ãæã£ãŠããŸããæ¬¡ã®ããããèé£åç©ã®çŸ€ããèããã®è°·ãšããŠæ³åããŠãã ãããèé£åç©ã®çŸ€ããæŸç§ãããããã€ãã®å²©ã暪ããããç·è±ããªæ€çãå²ããŸãã var valley = new LifelikeWorld( ["############################", "##### ######", "## *** **##", "# *##** ** O *##", "# *** O ##** *#", "# O ##*** #", "# ##** #", "# O #* #", "#* #** O #", "#*** ##** O **#", "##**** ###*** *###", "############################"], {"#": Wall, "O": PlantEater, "*": Plant} );
ã»ãšãã©ã®å Žåãæ€ç©ã¯å¢æ®ããŠæé·ããŸããããã®åŸãè±å¯ãªé£ç©ãèé£åç©ã®ççºçãªæé·ã«ã€ãªãããã»ãšãã©ãã¹ãŠã®æ€çãé£ã¹å°œããã飢fromããã®å€§éçµ¶æ»
ã«ã€ãªãããŸããæã«ã¯ãçæ
ç³»ãå埩ããæ°ãããµã€ã¯ã«ãå§ãŸããŸããä»ã®å Žåã«ã¯ãäžéšã®çš®ãæ»ã«ãŸããèé£åç©ãªãã空éå
šäœãæ€ç©ã§æºããããŠããŸããæ€ç©-æ®ãã®çãç©ã空è
¹ã§æ»ã¬ãšãè°·ã¯ç¡äººã®èãå°ã«å€ãããŸãããããèªç¶ã®æ®é
·ã...æŒç¿
人工ãã«
ç§ãã¡ã®äžçã®äœæ°ãæ°åã§æ»ã¬ãšããããã¯æ²ããã§ããããã«å¯ŸåŠããããã«ãããã¹ããŒããªæ€ç©ãé£ã¹ã人ãäœæããããšãã§ããŸããèé£åç©ã«ã¯ããã€ãã®æãããªåé¡ããããŸãã第äžã«ã圌ãã¯è²ªæ¬²ã§ã-圌ãã¯ãã¹ãŠã®æ€ç©ãå®å
šã«ç Žå£ãããŸã§ãèŠã€ãããã¹ãŠã®æ€ç©ãé£ã¹ãŸããæ¬¡ã«ããããã®ã©ã³ãã ãªåãïŒview.findã¡ãœãããã©ã³ãã ãªæ¹åãè¿ãããšãæãåºããŠãã ããïŒã¯ãéå¹ççã«ã¶ãã¶ãããè¿ãã«æ€ç©ããªããã°é£¢ãã§æ»ã«ãŸãããããŠæåŸã«ã圌ãã¯ããŸãã«ãéã墿®ãããããè±å¯ãã飢hungãžã®ãµã€ã¯ã«ãããŸãã«ãéãããŸãã1ã€ä»¥äžã®åé¡ã«å¯ŸåŠããããšããæ°ããã¿ã€ãã®ã¯ãªãŒãã£ãŒãäœæãããããè°·ã®äžçã®å€ãPlantEaterã¿ã€ãã«çœ®ãæããŸãããããã«åŸã£ãŠãã ãããå¿
èŠãªèª¿æŽãè¡ããŸãã
æé£è
æ·±å»ãªçæ
ç³»ã§ã¯ãé£ç©é£éã¯1ã€ã®ãªã³ã¯ãããé·ããªããŸããèé£åç©ãé£ã¹ãŠçãæ®ãå¥ã®çãç©ãæžããŸãããµã€ã¯ã«ãç°ãªãã¬ãã«ã§çºçãããšãå®å®æ§ãéæããã®ãããã«é£ãããªãããšãããããŸãããšã³ã·ã¹ãã ããã°ããã¹ã ãŒãºã«å®è¡ã§ããããã«ããæŠç¥ãèŠã€ããŠãã ãããäžçãæ¡å€§ãããšããã«åœ¹ç«ã¡ãŸãããããªããšãå°åã®äººå£ççºãäººå£æžå°ã«ãã£ãŠäººå£ãå®å
šã«ç Žå£ãããå¯èœæ§ã¯äœããªããæé£è
ã®å°æ°ã®éå£ãæ¯ããããšãã§ããæ¯èŒç倧ããªç²ç©ã®éå£ã®äœå°ããããŸãã