자바 스크립트 + HTML- 사용해보기
인기 요청에 따라 업데이트
일반적인 행동
이 프로그램은 이제 다소 대화식입니다.
소스 코드는 완전히 매개 변수화되어 있으므로 선호하는 텍스트 편집기로 몇 가지 내부 매개 변수를 조정할 수 있습니다.
포리스트 크기를 변경할 수 있습니다.
나무, 등심, 곰을 3 개의 다른 지점에 놓을 수있는 충분한 공간을 확보하려면 최소 2 개가 필요하며 최대 값은 임의로 100으로 고정됩니다 (평균 컴퓨터 크롤링).
시뮬레이션 속도를 변경할 수도 있습니다.
디스플레이는 20ms마다 업데이트되므로 시간 단계가 클수록 더 나은 애니메이션이 생성됩니다.
이 버튼을 사용하면 시뮬레이션을 중지 / 시작하거나 한 달 또는 1 년 동안 실행할 수 있습니다.
산림 거주자의 움직임이 이제 다소 애니메이션됩니다. 마우 링과 나무 자르기 이벤트도 그려졌습니다.
일부 이벤트 로그도 표시됩니다. 상세 수준을 변경하면 더 많은 메시지를 사용할 수 있지만 "Bob cuts yet another tree"알림이 표시됩니다.
내가 너라면 오히려하지 않겠 어.
놀이터 옆에 자동 스케일 그래픽 세트가 그려집니다.
- 곰과 나무꾼 인구
- 묘목, 성숙한 나무와 노인 나무로 나뉘어 진 총 나무 수
범례에는 각 항목의 현재 수량도 표시됩니다.
시스템 안정성
그래프는 초기 조건이 정상적으로 확장되지 않음을 보여줍니다. 숲이 너무 크면 팬케이크 애호가가 막대 뒤에 놓일 때까지 너무 많은 곰이 등심 인구를 멸종시킵니다. 이것은 노인 나무의 초기 폭발을 일으켜 나무꾼 인구가 회복되는 데 도움이됩니다.
숲이 살아 남기위한 최소 크기 인 것 같습니다. 크기가 10 인 숲은 보통 수백 년 후에 쇠약해질 것입니다. 30보다 큰 크기는 거의 나무로 가득 찬지도를 생성합니다. 15에서 30 사이에서 나무 개체수가 크게 진동하는 것을 볼 수 있습니다.
논쟁의 여지가있는 몇 가지 규칙
원래 게시물의 의견에서 다양한 Biped가 동일한 지점을 차지하지 않는 것으로 보입니다. 이것은 어떻게 팬케이크 아마추어로 돌아 다니는 목에 관한 규칙과 모순됩니다.
어쨌든 나는 그 지침을 따르지 않았습니다. 모든 산림 세포는 여러 종류의 불멸 물 (그리고 정확히 0 또는 1 개의 나무)을 보유 할 수 있습니다. 이것은 등심 효율에 약간의 영향을 미칠 수 있습니다. 나는 그것이 더 큰 나무의 덩어리로 더 쉽게 파고들 수 있다고 생각합니다. 곰에 관해서는, 나는 이것이 큰 차이를 만들 것으로 기대하지 않습니다.
나는 또한 붉은 목 인구가 제로에 도달 할 수 있다는 점에도 불구하고 항상 숲에 적어도 하나의 나무꾼을 두는 것을 선택했습니다. 멸종 위기).
조정
안정성을 달성하기 위해 두 가지 조정 매개 변수를 추가했습니다.
1) 벌목꾼 성장률
충분한 목재가있을 때 고용 된 여분의 나무꾼의 수를 제공하는 공식에 적용된 계수. 원래의 정의로 돌아가려면 1로 설정했지만 약 0.5의 값을 사용하면 숲 (특히 장로 나무)이 더 잘 발달 할 수 있습니다.
2) 곰 제거 기준
동물원에 곰을 보내기 위해 으깬 등심의 최소 백분율을 정의하는 계수. 원래 정의로 돌아가려면 0으로 설정하지만이 과감한 곰 제거는 기본적으로 모집단을 0-1 발진 주기로 제한합니다. 나는 그것을 .15로 설정했다 (즉, 올해 15 % 또는 그 이상의 등심이 헐렁한 경우에만 곰이 제거된다). 이것은 적당한 곰 개체수를 허용하여, 붉은 목이 그 지역을 깨끗하게 닦아 내지 못하지만 숲의 상당 부분을 잘게자를 수있게합니다.
참고로, 시뮬레이션은 멈추지 않습니다 (필요한 400 년이 지난 경우에도). 쉽게 할 수는 있지만 그렇지 않습니다.
코드
코드는 전적으로 단일 HTML 페이지에 포함되어 있습니다.
또한 UTF-8 인코딩되어야 곰 벌목의 적절한 유니 코드 문자를 표시.
유니 코드 장애 시스템 (예 : 우분투)의 경우 다음 줄을 찾으십시오.
jack :{ pic: '🙎', color:'#bc0e11' },
bear :{ pic: '🐻', color:'#422f1e' }},
디스플레이에 쉽게 문자의 그림 문자를 변경 ( #
, *
, 무엇이든)
<!doctype html>
<meta charset=utf-8>
<title>Of jacks and bears</title>
<body onload='init();'>
<style>
#log p { margin-top: 0; margin-bottom: 0; }
</style>
<div id='main'>
</div>
<table>
<tr>
<td><canvas id='forest'></canvas></td>
<td>
<table>
<tr>
<td colspan=2>
<div>Forest size <input type='text' size=10 onchange='create_forest(this.value);'> </div>
<div>Simulation tick <input type='text' size= 5 onchange='set_tick(this.value);' > (ms)</div>
<div>
<input type='button' value='◾' onclick='stop();'>
<input type='button' value='▸' onclick='start();'>
<input type='button' value='1 month' onclick='start(1);'>
<input type='button' value='1 year' onclick='start(12);'>
</div>
</td>
</tr>
<tr>
<td id='log' colspan=2>
</td>
</tr>
<tr>
<td><canvas id='graphs'></canvas></td>
<td id='legend'></td>
</tr>
<tr>
<td align='center'>evolution over 60 years</td>
<td id='counters'></td>
</tr>
</table>
</td>
</tr>
</table>
<script>
// ==================================================================================================
// Global parameters
// ==================================================================================================
var Prm = {
// ------------------------------------
// as defined in the original challenge
// ------------------------------------
// forest size
forest_size: 45, // 2025 cells
// simulation duration
duration: 400*12, // 400 years
// initial populations
populate: { trees: .5, jacks:.1, bears:.02 },
// tree ages
age: { mature:12, elder:120 },
// tree spawning probabilities
spawn: { sapling:0, mature:.1, elder:.2 },
// tree lumber yields
lumber: { mature:1, elder:2 },
// walking distances
distance: { jack:3, bear:5 },
// ------------------------------------
// extra tweaks
// ------------------------------------
// lumberjacks growth rate
// (set to 1 in original contest parameters)
jacks_growth: 1, // .5,
// minimal fraction of lumberjacks mauled to send a bear to the zoo
// (set to 0 in original contest parameters)
mauling_threshold: .15, // 0,
// ------------------------------------
// internal helpers
// ------------------------------------
// offsets to neighbouring cells
neighbours: [
{x:-1, y:-1}, {x: 0, y:-1}, {x: 1, y:-1},
{x:-1, y: 0}, {x: 1, y: 0},
{x:-1, y: 1}, {x: 0, y: 1}, {x: 1, y: 1}],
// ------------------------------------
// goodies
// ------------------------------------
// bear and people names
names:
{ bear: ["Art", "Ursula", "Arthur", "Barney", "Bernard", "Bernie", "Bjorn", "Orson", "Osborn", "Torben", "Bernadette", "Nita", "Uschi"],
jack: ["Bob", "Tom", "Jack", "Fred", "Paul", "Abe", "Roy", "Chuck", "Rob", "Alf", "Tim", "Tex", "Mel", "Chris", "Dave", "Elmer", "Ian", "Kyle", "Leroy", "Matt", "Nick", "Olson", "Sam"] },
// months
month: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
// ------------------------------------
// graphics
// ------------------------------------
// messages verbosity (set to 2 to be flooded, -1 to have no trace at all)
verbosity: 1,
// pixel sizes
icon_size: 100,
canvas_f_size: 600, // forest canvas size
canvas_g_width : 400, // graphs canvas size
canvas_g_height: 200,
// graphical representation
graph: {
soil: { color: '#82641e' },
sapling:{ radius:.1, color:'#52e311', next:'mature'},
mature :{ radius:.3, color:'#48b717', next:'elder' },
elder :{ radius:.5, color:'#8cb717', next:'elder' },
jack :{ pic: '🙎', color:'#2244ff' },
bear :{ pic: '🐻', color:'#422f1e' },
mauling:{ pic: '★', color:'#ff1111' },
cutting:{ pic: '●', color:'#441111' }},
// animation tick
tick:100 // ms
};
// ==================================================================================================
// Utilities
// ==================================================================================================
function int_rand (num)
{
return Math.floor (Math.random() * num);
}
function shuffle (arr)
{
for (
var j, x, i = arr.length;
i;
j = int_rand (i), x = arr[--i], arr[i] = arr[j], arr[j] = x);
}
function pick (arr)
{
return arr[int_rand(arr.length)];
}
function message (str, level)
{
level = level || 0;
if (level <= Prm.verbosity)
{
while (Gg.log.childNodes.length > 10) Gg.log.removeChild(Gg.log.childNodes[0]);
var line = document.createElement ('p');
line.innerHTML = Prm.month[Forest.date%12]+" "+Math.floor(Forest.date/12)+": "+str;
Gg.log.appendChild (line);
}
}
// ==================================================================================================
// Forest
// ==================================================================================================
// --------------------------------------------------------------------------------------------------
// a forest cell
// --------------------------------------------------------------------------------------------------
function cell()
{
this.contents = [];
}
cell.prototype = {
add: function (elt)
{
this.contents.push (elt);
},
remove: function (elt)
{
var i = this.contents.indexOf (elt);
this.contents.splice (i, 1);
},
contains: function (type)
{
for (var i = 0 ; i != this.contents.length ; i++)
{
if (this.contents[i].type == type)
{
return this.contents[i];
}
}
return null;
}
}
// --------------------------------------------------------------------------------------------------
// an entity (tree, jack, bear)
// --------------------------------------------------------------------------------------------------
function entity (x, y, type)
{
this.age = 0;
switch (type)
{
case "jack": this.name = pick (Prm.names.jack); break;
case "bear": this.name = pick (Prm.names.bear); break;
case "tree": this.name = "sapling"; Forest.t.low++; break;
}
this.x = this.old_x = x;
this.y = this.old_y = y;
this.type = type;
}
entity.prototype = {
move: function ()
{
Forest.remove (this);
var n = neighbours (this);
this.x = n[0].x;
this.y = n[0].y;
return Forest.add (this);
}
};
// --------------------------------------------------------------------------------------------------
// a list of entities (trees, jacks, bears)
// --------------------------------------------------------------------------------------------------
function elt_list (type)
{
this.type = type;
this.list = [];
}
elt_list.prototype = {
add: function (x, y)
{
if (x === undefined) x = int_rand (Forest.size);
if (y === undefined) y = int_rand (Forest.size);
var e = new entity (x, y, this.type);
Forest.add (e);
this.list.push (e);
return e;
},
remove: function (elt)
{
var i;
if (elt) // remove a specific element (e.g. a mauled lumberjack)
{
i = this.list.indexOf (elt);
}
else // pick a random element (e.g. a bear punished for the collective pancake rampage)
{
i = int_rand(this.list.length);
elt = this.list[i];
}
this.list.splice (i, 1);
Forest.remove (elt);
if (elt.name == "mature") Forest.t.mid--;
if (elt.name == "elder" ) Forest.t.old--;
return elt;
}
};
// --------------------------------------------------------------------------------------------------
// global forest handling
// --------------------------------------------------------------------------------------------------
function forest (size)
{
// initial parameters
this.size = size;
this.surface = size * size;
this.date = 0;
this.mauling = this.lumber = 0;
this.t = { low:0, mid:0, old:0 };
// initialize cells
this.cells = new Array (size);
for (var i = 0 ; i != size ; i++)
{
this.cells[i] = new Array(size);
for (var j = 0 ; j != size ; j++)
{
this.cells[i][j] = new cell;
}
}
// initialize entities lists
this.trees = new elt_list ("tree");
this.jacks = new elt_list ("jack");
this.bears = new elt_list ("bear");
this.events = [];
}
forest.prototype = {
populate: function ()
{
function fill (num, list)
{
for (var i = 0 ; i < num ; i++)
{
var coords = pick[i_pick++];
list.add (coords.x, coords.y);
}
}
// shuffle forest cells
var pick = new Array (this.surface);
for (var i = 0 ; i != this.surface ; i++)
{
pick[i] = { x:i%this.size, y:Math.floor(i/this.size)};
}
shuffle (pick);
var i_pick = 0;
// populate the lists
fill (Prm.populate.jacks * this.surface, this.jacks);
fill (Prm.populate.bears * this.surface, this.bears);
fill (Prm.populate.trees * this.surface, this.trees);
this.trees.list.forEach (function (elt) { elt.age = Prm.age.mature; });
},
add: function (elt)
{
var cell = this.cells[elt.x][elt.y];
cell.add (elt);
return cell;
},
remove: function (elt)
{
var cell = this.cells[elt.x][elt.y];
cell.remove (elt);
},
evt_mauling: function (jack, bear)
{
message (bear.name+" sniffs a delicious scent of pancake, unfortunately for "+jack.name, 1);
this.jacks.remove (jack);
this.mauling++;
Gg.counter.mauling.innerHTML = this.mauling;
this.register_event ("mauling", jack);
},
evt_cutting: function (jack, tree)
{
if (tree.name == 'sapling') return; // too young to be chopped down
message (jack.name+" cuts a "+tree.name+" tree: lumber "+this.lumber+" (+"+Prm.lumber[tree.name]+")", 2);
this.trees.remove (tree);
this.lumber += Prm.lumber[tree.name];
Gg.counter.cutting.innerHTML = this.lumber;
this.register_event ("cutting", jack);
},
register_event: function (type, position)
{
this.events.push ({ type:type, x:position.x, y:position.y});
},
tick: function()
{
this.date++;
this.events = [];
// monthly updates
this.trees.list.forEach (b_tree);
this.jacks.list.forEach (b_jack);
this.bears.list.forEach (b_bear);
// feed graphics
Gg.graphs.trees.add (this.trees.list.length);
Gg.graphs.jacks.add (this.jacks.list.length);
Gg.graphs.bears.add (this.bears.list.length);
Gg.graphs.sapling.add (this.t.low);
Gg.graphs.mature .add (this.t.mid);
Gg.graphs.elder .add (this.t.old);
// yearly updates
if (!(this.date % 12))
{
// update jacks
if (this.jacks.list.length == 0)
{
message ("An extra lumberjack is hired after a bear rampage");
this.jacks.add ();
}
if (this.lumber >= this.jacks.list.length)
{
var extra_jacks = Math.floor (this.lumber / this.jacks.list.length * Prm.jacks_growth);
message ("A good lumbering year. Lumberjacks +"+extra_jacks, 1);
for (var i = 0 ; i != extra_jacks ; i++) this.jacks.add ();
}
else if (this.jacks.list.length > 1)
{
var fired = this.jacks.remove();
message (fired.name+" has been chopped", 1);
}
// update bears
if (this.mauling > this.jacks.list.length * Prm.mauling_threshold)
{
var bear = this.bears.remove();
message (bear.name+" will now eat pancakes in a zoo", 1);
}
else
{
var bear = this.bears.add();
message (bear.name+" starts a quest for pancakes", 1);
}
// reset counters
this.mauling = this.lumber = 0;
}
}
}
function neighbours (elt)
{
var ofs,x,y;
var list = [];
for (ofs in Prm.neighbours)
{
var o = Prm.neighbours[ofs];
x = elt.x + o.x;
y = elt.y + o.y;
if ( x < 0 || x >= Forest.size
|| y < 0 || y >= Forest.size) continue;
list.push ({x:x, y:y});
}
shuffle (list);
return list;
}
// --------------------------------------------------------------------------------------------------
// entities behaviour
// --------------------------------------------------------------------------------------------------
function b_tree (tree)
{
// update tree age and category
if (tree.age == Prm.age.mature) { tree.name = "mature"; Forest.t.low--; Forest.t.mid++; }
else if (tree.age == Prm.age.elder ) { tree.name = "elder" ; Forest.t.mid--; Forest.t.old++; }
tree.age++;
// see if we can spawn something
if (Math.random() < Prm.spawn[tree.name])
{
var n = neighbours (tree);
for (var i = 0 ; i != n.length ; i++)
{
var coords = n[i];
var cell = Forest.cells[coords.x][coords.y];
if (cell.contains("tree")) continue;
Forest.trees.add (coords.x, coords.y);
break;
}
}
}
function b_jack (jack)
{
jack.old_x = jack.x;
jack.old_y = jack.y;
for (var i = 0 ; i != Prm.distance.jack ; i++)
{
// move
var cell = jack.move ();
// see if we stumbled upon a bear
var bear = cell.contains ("bear");
if (bear)
{
Forest.evt_mauling (jack, bear);
break;
}
// see if we reached an harvestable tree
var tree = cell.contains ("tree");
if (tree)
{
Forest.evt_cutting (jack, tree);
break;
}
}
}
function b_bear (bear)
{
bear.old_x = bear.x;
bear.old_y = bear.y;
for (var i = 0 ; i != Prm.distance.bear ; i++)
{
var cell = bear.move ();
var jack = cell.contains ("jack");
if (jack)
{
Forest.evt_mauling (jack, bear);
break; // one pancake hunt per month is enough
}
}
}
// --------------------------------------------------------------------------------------------------
// Graphics
// --------------------------------------------------------------------------------------------------
function init()
{
function create_counter (desc)
{
var counter = document.createElement ('span');
var item = document.createElement ('p');
item.innerHTML = desc.name+" ";
item.style.color = desc.color;
item.appendChild (counter);
return { item:item, counter:counter };
}
// initialize forest canvas
Gf = { period:20, tick:0 };
Gf.canvas = document.getElementById ('forest');
Gf.canvas.width =
Gf.canvas.height = Prm.canvas_f_size;
Gf.ctx = Gf.canvas.getContext ('2d');
Gf.ctx.textBaseline = 'Top';
// initialize graphs canvas
Gg = { counter:[] };
Gg.canvas = document.getElementById ('graphs');
Gg.canvas.width = Prm.canvas_g_width;
Gg.canvas.height = Prm.canvas_g_height;
Gg.ctx = Gg.canvas.getContext ('2d');
// initialize graphs
Gg.graphs = {
jacks: new graphic({ name:"lumberjacks" , color:Prm.graph.jack.color }),
bears: new graphic({ name:"bears" , color:Prm.graph.bear.color, ref:'jacks' }),
trees: new graphic({ name:"trees" , color:'#0F0' }),
sapling: new graphic({ name:"saplings" , color:Prm.graph.sapling.color, ref:'trees' }),
mature: new graphic({ name:"mature trees", color:Prm.graph.mature .color, ref:'trees' }),
elder: new graphic({ name:"elder trees" , color:Prm.graph.elder .color, ref:'trees' })
};
Gg.legend = document.getElementById ('legend');
for (g in Gg.graphs)
{
var gr = Gg.graphs[g];
var c = create_counter (gr);
gr.counter = c.counter;
Gg.legend.appendChild (c.item);
}
// initialize counters
var counters = document.getElementById ('counters');
var def = [ "mauling", "cutting" ];
var d; for (d in def)
{
var c = create_counter ({ name:def[d], color:Prm.graph[def[d]].color });
counters.appendChild (c.item);
Gg.counter[def[d]] = c.counter;
}
// initialize log
Gg.log = document.getElementById ('log');
// create our forest
create_forest(Prm.forest_size);
start();
}
function create_forest (size)
{
if (size < 2) size = 2;
if (size > 100) size = 100;
Forest = new forest (size);
Prm.icon_size = Prm.canvas_f_size / size;
Gf.ctx.font = 'Bold '+Prm.icon_size+'px Arial';
Forest.populate ();
draw_forest();
var g; for (g in Gg.graphs) Gg.graphs[g].reset();
draw_graphs();
}
function animate()
{
if (Gf.tick % Prm.tick == 0)
{
Forest.tick();
draw_graphs();
}
draw_forest();
Gf.tick+= Gf.period;
if (Gf.tick == Gf.stop_date) stop();
}
function draw_forest ()
{
function draw_dweller (dweller)
{
var type = Prm.graph[dweller.type];
Gf.ctx.fillStyle = type.color;
var x = dweller.x * time_fraction + dweller.old_x * (1 - time_fraction);
var y = dweller.y * time_fraction + dweller.old_y * (1 - time_fraction);
Gf.ctx.fillText (type.pic, x * Prm.icon_size, (y+1) * Prm.icon_size);
}
function draw_event (evt)
{
var gr = Prm.graph[evt.type];
Gf.ctx.fillStyle = gr.color;
Gf.ctx.fillText (gr.pic, evt.x * Prm.icon_size, (evt.y+1) * Prm.icon_size);
}
function draw_tree (tree)
{
// trees grow from one category to the next
var type = Prm.graph[tree.name];
var next = Prm.graph[type.next];
var radius = (type.radius + (next.radius - type.radius) / Prm.age[type.next] * tree.age) * Prm.icon_size;
Gf.ctx.fillStyle = Prm.graph[tree.name].color;
Gf.ctx.beginPath();
Gf.ctx.arc((tree.x+.5) * Prm.icon_size, (tree.y+.5) * Prm.icon_size, radius, 0, 2*Math.PI);
Gf.ctx.fill();
}
// background
Gf.ctx.fillStyle = Prm.graph.soil.color;
Gf.ctx.fillRect (0, 0, Gf.canvas.width, Gf.canvas.height);
// time fraction to animate displacements
var time_fraction = (Gf.tick % Prm.tick) / (Prm.tick-Gf.period);
// entities
Forest.trees.list.forEach (draw_tree);
Forest.jacks.list.forEach (draw_dweller);
Forest.bears.list.forEach (draw_dweller);
Forest.events.forEach (draw_event);
}
// --------------------------------------------------------------------------------------------------
// Graphs
// --------------------------------------------------------------------------------------------------
function graphic (prm)
{
this.name = prm.name || '?';
this.color = prm.color || '#FFF';
this.size = prm.size || 720;
this.ref = prm.ref;
this.values = [];
this.counter = document.getElement
}
graphic.prototype = {
draw: function ()
{
Gg.ctx.strokeStyle = this.color;
Gg.ctx.beginPath();
for (var i = 0 ; i != this.values.length ; i++)
{
var x = (i + this.size - this.values.length) / this.size * Gg.canvas.width;
var y = (1-(this.values[i] - this.min) / this.rng) * Gg.canvas.height;
if (i == 0) Gg.ctx.moveTo (x, y);
else Gg.ctx.lineTo (x, y);
}
Gg.ctx.stroke();
},
add: function (value)
{
// store value
this.values.push (value);
this.counter.innerHTML = value;
// cleanup history
while (this.values.length > this.size) this.values.splice (0,1);
// compute min and max
this.min = Math.min.apply(Math, this.values);
if (this.min > 0) this.min = 0;
this.max = this.ref
? Gg.graphs[this.ref].max
: Math.max.apply(Math, this.values);
this.rng = this.max - this.min;
if (this.rng == 0) this.rng = 1;
},
reset: function()
{
this.values = [];
}
}
function draw_graphs ()
{
function draw_graph (graph)
{
graph.draw();
}
// background
Gg.ctx.fillStyle = '#000';
Gg.ctx.fillRect (0, 0, Gg.canvas.width, Gg.canvas.height);
// graphs
var g; for (g in Gg.graphs)
{
var gr = Gg.graphs[g];
gr.draw();
}
}
// --------------------------------------------------------------------------------------------------
// User interface
// --------------------------------------------------------------------------------------------------
function set_tick(value)
{
value = Math.round (value / Gf.period);
if (value < 2) value = 2;
value *= Gf.period;
Prm.tick = value;
return value;
}
function start (duration)
{
if (Prm.timer) stop();
Gf.stop_date = duration ? Gf.tick + duration*Prm.tick : -1;
Prm.timer = setInterval (animate, Gf.period);
}
function stop ()
{
if (Prm.timer)
{
clearInterval (Prm.timer);
Prm.timer = null;
}
Gf.stop_date = -1;
}
</script>
</body>
다음은?
더 많은 발언은 여전히 환영합니다.
NB : 묘목 / 성숙한 / 장로 나무 수는 여전히 약간 지저분하다는 것을 알고 있습니다.
또한 document.getElementById가 $보다 더 읽기 쉽기 때문에 jQueryism의 부족에 대해 불평 할 필요가 없습니다. 의도적으로 무료 jQuery입니다. 각자 자신에게?
Note that you will never reduce your Lumberjack labor force below 0
등심 섹션 목록 항목 3에서 아마도 곰 섹션에서 언급 한 것과 일치하도록 이것을 1로 변경합니까?