Compare Revisions
Swap
Showing 22 commits
Merge Ancestor: c62400235fb9
22 silverwing b86ed9567583
6 days ago
21 silverwing 5985b0a31815
6 days ago
20 silverwing fe8693a3e7d5
6 days ago
19 silverwing 93cfddc9484c
6 days ago
18 silverwing 1332d630308f
6 days ago
17 silverwing f2f018459fb7
6 days ago
16 silverwing 0c055c1e38c1
6 days ago
15 silverwing a3357855c7d3
7 days ago
14 silverwing 9cf402fecdaf
8 days ago
13 silverwing 79074f9e816e
8 days ago
12 silverwing b1f91fd22b0b
9 days ago
11 silverwing 7da04978fd8a
2 months ago
10 silverwing f64fd360962a
2 months ago
9 silverwing 6e2e4d683a57
2 months ago
8 silverwing 3c6baa05ef09
3 months ago
7 silverwing 0ac34928cadb
3 months ago
6 silverwing e0ab59b58fc1
3 months ago
5 silverwing b16a671170b8
3 months ago
4 silverwing 6318c07fd328
3 months ago
3 silverwing 009ae74f1983
3 months ago
2 silverwing c2e2cb3a6e5d
3 months ago
1 silverwing 3dcee4fa8059
4 months ago
38 files changed with 12298 insertions and 10250 deletions:
computer_parts.lua
Show inline comments
 
function motherboard(cpu, ram, slots, status, src)
 
	local name = cpu .. '-' .. ram .. '-I' .. tostring(slots) .. 'SB';
 
	
 
	return obj {
 
		nam = name:lower();
 
		status = status;
 
		name = name;
 
		cpu = cpu;
 
		ram = ram;
 
		slots = slots;
 
		ptype = 'motherboard';
 
		part = true;
 
		disp = translate("parts_locale", 'motherboard_title', {model=name});
 
		dsc = function(s)
 
  local name = cpu .. '-' .. ram .. '-I' .. tostring(slots) .. 'SB';
 
  
 
  return obj {
 
    nam = name:lower();
 
    status = status;
 
    name = name;
 
    cpu = cpu;
 
    ram = ram;
 
    slots = slots;
 
    ptype = 'motherboard';
 
    part = true;
 
    disp = translate("parts_locale", 'motherboard_title', {model=name});
 
    dsc = function(s)
 
      return '{' .. translate_now("parts_locale", 'motherboard_title', {model=name}) .. '}^'
 
    end;
 
		inv = translate("parts_locale", 'motherboard_inv_from_' .. src, {model=name});
 
		tak = translate("parts_locale", 'motherboard_tak', {model=name});
 
	};
 
    inv = translate("parts_locale", 'motherboard_inv_from_' .. src, {model=name});
 
    tak = translate("parts_locale", 'motherboard_tak', {model=name});
 
  };
 
end;
 

	
 
function cpu(slot, speed, status, src, name_postfix)
 
	local name;
 
	if slot == 'CAX' then
 
		name = 'CPU' .. tostring(speed * 10) .. '-CAX-' .. tostring(speed) .. 'MHz';
 
	elseif slot == 'CVX' then
 
		name = 'MCPU' .. tostring(speed * 10) .. '-CVX-' .. tostring(speed) .. 'MHz';
 
	elseif slot == 'CRX' then
 
		name = 'RCPU' .. tostring(speed * 10) .. '-CRX-' .. tostring(speed) .. 'MHz';
 
	elseif slot == 'CXX' then
 
		name = 'XCPU' .. tostring(speed) .. '-CXX-' .. tostring(speed) .. 'MHz';
 
	end;
 
	
 
	if not name_postfix then
 
		name_postfix = '';
 
	end;
 
	
 
	return obj {
 
		nam = name:lower() .. name_postfix;
 
		status = status;
 
		name = name;
 
		slot = slot;
 
		disp = translate("parts_locale", 'cpu_title', {model=name});
 
		speed = speed;
 
		status = status;
 
		ptype = 'cpu';
 
		part = true;
 
		dsc = function(s)
 
  local name;
 
  if slot == 'CAX' then
 
    name = 'CPU' .. tostring(speed * 10) .. '-CAX-' .. tostring(speed) .. 'MHz';
 
  elseif slot == 'CVX' then
 
    name = 'MCPU' .. tostring(speed * 10) .. '-CVX-' .. tostring(speed) .. 'MHz';
 
  elseif slot == 'CRX' then
 
    name = 'RCPU' .. tostring(speed * 10) .. '-CRX-' .. tostring(speed) .. 'MHz';
 
  elseif slot == 'CXX' then
 
    name = 'XCPU' .. tostring(speed) .. '-CXX-' .. tostring(speed) .. 'MHz';
 
  end;
 
  
 
  if not name_postfix then
 
    name_postfix = '';
 
  end;
 
  
 
  return obj {
 
    nam = name:lower() .. name_postfix;
 
    status = status;
 
    name = name;
 
    slot = slot;
 
    disp = translate("parts_locale", 'cpu_title', {model=name});
 
    speed = speed;
 
    status = status;
 
    ptype = 'cpu';
 
    part = true;
 
    dsc = function(s)
 
      return '{' .. translate_now("parts_locale", 'cpu_title', {model=name}) .. '}^'
 
    end;
 
		inv = translate("parts_locale", 'cpu_inv_from_' .. src, {model=name});
 
		tak = translate("parts_locale", 'cpu_tak', {model=name});
 
	};
 
    inv = translate("parts_locale", 'cpu_inv_from_' .. src, {model=name});
 
    tak = translate("parts_locale", 'cpu_tak', {model=name});
 
  };
 
end;
 

	
 
function ram(slot, size, status, dsc, name_postfix)
 
	local name;
 
	if slot == 'RKT' then
 
		name = 'RKT-M' .. tostring(size * 10) .. '-' ..tostring(size) .. 'MB';
 
	else
 
		name = slot .. '-M' .. tostring(size) .. '-' ..tostring(size) .. 'MB';
 
	end;
 
	
 
	if not name_postfix then
 
		name_postfix = '';
 
	end;
 
	
 
	return obj {
 
		nam = name:lower() .. name_postfix;
 
		status = status;
 
		name = name;
 
		slot = slot;
 
		ptype = 'ram';
 
		disp = translate("parts_locale", 'ram_title', {model=name});
 
		status = status;
 
		size = size;
 
		part = true;
 
		dsc = function(s)
 
  local name;
 
  if slot == 'RKT' then
 
    name = 'RKT-M' .. tostring(size * 10) .. '-' ..tostring(size) .. 'MB';
 
  else
 
    name = slot .. '-M' .. tostring(size) .. '-' ..tostring(size) .. 'MB';
 
  end;
 
  
 
  if not name_postfix then
 
    name_postfix = '';
 
  end;
 
  
 
  return obj {
 
    nam = name:lower() .. name_postfix;
 
    status = status;
 
    name = name;
 
    slot = slot;
 
    ptype = 'ram';
 
    disp = translate("parts_locale", 'ram_title', {model=name});
 
    status = status;
 
    size = size;
 
    part = true;
 
    dsc = function(s)
 
      return '{' .. translate_now("parts_locale", 'ram_title', {model=name}) .. '}^'
 
    end;
 
		inv = translate("parts_locale", 'ram_inv_from_' .. dsc, {model=name});
 
		tak = translate("parts_locale", 'ram_tak', {model=name});
 
	};
 
    inv = translate("parts_locale", 'ram_inv_from_' .. dsc, {model=name});
 
    tak = translate("parts_locale", 'ram_tak', {model=name});
 
  };
 
end;
 

	
 
motherboard('CVX', 'RST', 3, true, 'computer');
 
@@ -116,193 +116,193 @@ ram('RDT', 32, true, 'box'); -- type 3
 
ram('RDT', 64, false, 'box'); -- type 4
 

	
 
obj {
 
	nam = 'tva-rx1';
 
	status = true;
 
	name = 'TVA-RX1';
 
	ptype = 'video';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'tva-rx1';
 
  status = true;
 
  name = 'TVA-RX1';
 
  ptype = 'video';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 1;
 
	disp = translate("parts_locale", 'videocard_title', {model='TVA-RX1'});
 
  disp = translate("parts_locale", 'videocard_title', {model='TVA-RX1'});
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'videocard_title', {model='TVA-RX1'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'videocard_inv_from_computer', {model='TVA-RX1'});
 
  inv = translate("parts_locale", 'videocard_inv_from_computer', {model='TVA-RX1'});
 
  tak = translate("parts_locale", 'videocard_tak', {model='TVA-RX1'});
 
}
 

	
 
obj {
 
	nam = 'tva-rx2';
 
	status = true;
 
	ptype = 'video';
 
	name = 'TVA-RX2';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'tva-rx2';
 
  status = true;
 
  ptype = 'video';
 
  name = 'TVA-RX2';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 1;
 
	disp = translate("parts_locale", 'videocard_title', {model='TVA-RX2'});
 
	dsc = function(s)
 
  disp = translate("parts_locale", 'videocard_title', {model='TVA-RX2'});
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'videocard_title', {model='TVA-RX2'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'videocard_inv_from_box', {model='TVA-RX2'});
 
	tak = translate("parts_locale", 'videocard_tak', {model='TVA-RX2'});
 
  inv = translate("parts_locale", 'videocard_inv_from_box', {model='TVA-RX2'});
 
  tak = translate("parts_locale", 'videocard_tak', {model='TVA-RX2'});
 
}
 

	
 
obj {
 
	nam = 'gva-rx2';
 
	status = false;
 
	ptype = 'video';
 
	name = 'GVA-RX2';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'gva-rx2';
 
  status = false;
 
  ptype = 'video';
 
  name = 'GVA-RX2';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 2;
 
	disp = translate("parts_locale", 'videocard_title', {model='GVA-RX2'});
 
	dsc = function(s)
 
  disp = translate("parts_locale", 'videocard_title', {model='GVA-RX2'});
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'videocard_title', {model='GVA-RX2'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'videocard_inv_from_box', {model='GVA-RX2'});
 
	tak = translate("parts_locale", 'videocard_tak', {model='GVA-RX2'});
 
  inv = translate("parts_locale", 'videocard_inv_from_box', {model='GVA-RX2'});
 
  tak = translate("parts_locale", 'videocard_tak', {model='GVA-RX2'});
 
}
 

	
 
obj {
 
	nam = 'gva-rx4';
 
	status = true;
 
	name = 'GVA-RX4';
 
	ptype = 'video';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'gva-rx4';
 
  status = true;
 
  name = 'GVA-RX4';
 
  ptype = 'video';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 2;
 
	disp = translate("parts_locale", 'videocard_title', {model='GVA-RX4'});
 
	dsc = function(s)
 
  disp = translate("parts_locale", 'videocard_title', {model='GVA-RX4'});
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'videocard_title', {model='GVA-RX4'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'videocard_inv_from_box', {model='GVA-RX4'});
 
	tak = translate("parts_locale", 'videocard_tak', {model='GVA-RX4'});
 
  inv = translate("parts_locale", 'videocard_inv_from_box', {model='GVA-RX4'});
 
  tak = translate("parts_locale", 'videocard_tak', {model='GVA-RX4'});
 
}
 

	
 
obj {
 
	nam = 'fna-100-10mbs_1';
 
	status = true;
 
	name = 'FNA-100-10Mb/s';
 
	ptype = 'network';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'fna-100-10mbs_1';
 
  status = true;
 
  name = 'FNA-100-10Mb/s';
 
  ptype = 'network';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 3;
 
	disp = translate("parts_locale", 'network_adapter_title', {model='FNA-100-10Mb/s'});
 
	dsc = function(s)
 
  disp = translate("parts_locale", 'network_adapter_title', {model='FNA-100-10Mb/s'});
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'network_adapter_title', {model='FNA-100-10Mb/s'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'network_adapter_inv_from_computer', {model='FNA-100-10Mb/s'});
 
  inv = translate("parts_locale", 'network_adapter_inv_from_computer', {model='FNA-100-10Mb/s'});
 
  tak = translate("parts_locale", 'network_adapter_tak', {model='FNA-100-10Mb/s'});
 
}
 

	
 
obj {
 
	nam = 'fna-200-20mbs';
 
	status = false;
 
	name = 'FNA-200-20Mb/s';
 
	ptype = 'network';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'fna-200-20mbs';
 
  status = false;
 
  name = 'FNA-200-20Mb/s';
 
  ptype = 'network';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 3;
 
	disp = translate("parts_locale", 'network_adapter_title', {model='FNA-200-20Mb/s'});
 
	dsc = function(s)
 
  disp = translate("parts_locale", 'network_adapter_title', {model='FNA-200-20Mb/s'});
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'network_adapter_title', {model='FNA-200-20Mb/s'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'network_adapter_inv_from_box', {model='FNA-200-20Mb/s'});
 
  inv = translate("parts_locale", 'network_adapter_inv_from_box', {model='FNA-200-20Mb/s'});
 
  tak = translate("parts_locale", 'network_adapter_tak', {model='FNA-200-20Mb/s'});
 
}
 

	
 
obj {
 
	nam = 'fna-100-10mbs_2';
 
	status = true;
 
	name = 'FNA-100-10Mb/s';
 
	ptype = 'network';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'fna-100-10mbs_2';
 
  status = true;
 
  name = 'FNA-100-10Mb/s';
 
  ptype = 'network';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 3;
 
	disp = translate("parts_locale", 'network_adapter_title', {model='FNA-100-10Mb/s'});
 
	dsc = function(s)
 
  disp = translate("parts_locale", 'network_adapter_title', {model='FNA-100-10Mb/s'});
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'network_adapter_title', {model='FNA-100-10Mb/s'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'network_adapter_inv_from_box', {model='FNA-100-10Mb/s'});
 
  inv = translate("parts_locale", 'network_adapter_inv_from_box', {model='FNA-100-10Mb/s'});
 
  tak = translate("parts_locale", 'network_adapter_tak', {model='FNA-100-10Mb/s'});
 
}
 

	
 
obj {
 
	nam = 'fna-50-5mbs';
 
	status = true;
 
	name = 'FNA-50-5Mb/s';
 
	ptype = 'network';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'fna-50-5mbs';
 
  status = true;
 
  name = 'FNA-50-5Mb/s';
 
  ptype = 'network';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 3;
 
	disp = translate("parts_locale", 'network_adapter_title', {model='FNA-50-5Mb/s'});
 
	dsc = function(s)
 
  disp = translate("parts_locale", 'network_adapter_title', {model='FNA-50-5Mb/s'});
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'network_adapter_title', {model='FNA-50-5Mb/s'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'network_adapter_inv_from_box', {model='FNA-50-5Mb/s'});
 
  inv = translate("parts_locale", 'network_adapter_inv_from_box', {model='FNA-50-5Mb/s'});
 
  tak = translate("parts_locale", 'network_adapter_tak', {model='FNA-50-5Mb/s'});
 
}
 

	
 
obj {
 
	nam = 'kbc-s';
 
	status = true;
 
	name = 'KBC-S';
 
	ptype = 'keyboard';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'kbc-s';
 
  status = true;
 
  name = 'KBC-S';
 
  ptype = 'keyboard';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 4;
 
  disp = translate("parts_locale", 'keyboard_controller_title', {model='KBC-S'});
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'keyboard_controller_title', {model='KBC-S'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'keyboard_controller_inv_from_computer', {model='KBC-S'});
 
  inv = translate("parts_locale", 'keyboard_controller_inv_from_computer', {model='KBC-S'});
 
  tak = translate("parts_locale", 'keyboard_controller_tak', {model='KBC-S'});
 
}
 

	
 
obj {
 
	nam = 'kbc-s_2';
 
	status = false;
 
	name = 'KBC-S';
 
	ptype = 'keyboard';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'kbc-s_2';
 
  status = false;
 
  name = 'KBC-S';
 
  ptype = 'keyboard';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 4;
 
  disp = translate("parts_locale", 'keyboard_controller_title', {model='KBC-S'});
 
	dsc = function(s)
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'keyboard_controller_title', {model='KBC-S'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'keyboard_controller_inv_from_box', {model='KBC-S'});
 
  inv = translate("parts_locale", 'keyboard_controller_inv_from_box', {model='KBC-S'});
 
  tak = translate("parts_locale", 'keyboard_controller_tak', {model='KBC-S'});
 
}
 

	
 
obj {
 
	nam = 'kbc-r';
 
	status = false;
 
	name = 'KBC-R';
 
	ptype = 'keyboard';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'kbc-r';
 
  status = false;
 
  name = 'KBC-R';
 
  ptype = 'keyboard';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 4;
 
  disp = translate("parts_locale", 'keyboard_controller_title', {model='KBC-R'});
 
	dsc = function(s)
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'keyboard_controller_title', {model='KBC-R'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'keyboard_controller_inv_from_box', {model='KBC-R'});
 
  inv = translate("parts_locale", 'keyboard_controller_inv_from_box', {model='KBC-R'});
 
  tak = translate("parts_locale", 'keyboard_controller_tak', {model='KBC-R'});
 
}
 

	
 
obj {
 
	nam = 'kbc-p';
 
	status = true;
 
	name = 'KBC-P';
 
	ptype = 'keyboard';
 
	slot = 'ISB';
 
	part = true;
 
  nam = 'kbc-p';
 
  status = true;
 
  name = 'KBC-P';
 
  ptype = 'keyboard';
 
  slot = 'ISB';
 
  part = true;
 
  visual = 4;
 
  disp = translate("parts_locale", 'keyboard_controller_title', {model='KBC-P'});
 
	dsc = function(s)
 
  dsc = function(s)
 
    return '{' .. translate_now("parts_locale", 'keyboard_controller_title', {model='KBC-P'}) .. '}^';
 
  end;
 
	inv = translate("parts_locale", 'keyboard_controller_inv_from_box', {model='KBC-P'});
 
  inv = translate("parts_locale", 'keyboard_controller_inv_from_box', {model='KBC-P'});
 
  tak = translate("parts_locale", 'keyboard_controller_tak', {model='KBC-P'});
 
}
ending.lua
Show inline comments
 
global {
 
	solarscale_stays = false
 
  solarscale_stays = false
 
}
 

	
 
function make_tbg_slice(scale, theme)
 
	local src = pixels.new('images/' .. theme .. '_theme/text_bg.png'):scale(scale);
 
	local tbg, tbg_slice
 
	local frw, frh, fdx, fdy
 
	if theme == 'main' or theme == 'bwm' then
 
		tbg, tbg_slice = dire_slice_9(src, {
 
			x = 9 * scale,
 
			y = 6 * scale,
 
			w = 96 * scale,
 
			h = 96 * scale
 
		});
 
	else
 
		tbg, tbg_slice = dire_slice_9(src, {
 
			x = 6 * scale,
 
			y = 6 * scale,
 
			w = 128 * scale,
 
			h = 128 * scale
 
		});
 
	end;
 
	
 
	return tbg, tbg_slice;
 
  local src = pixels.new('images/' .. theme .. '_theme/text_bg.png'):scale(scale);
 
  local tbg, tbg_slice
 
  local frw, frh, fdx, fdy
 
  if theme == 'main' or theme == 'bwm' then
 
    tbg, tbg_slice = dire_slice_9(src, {
 
      x = 9 * scale,
 
      y = 6 * scale,
 
      w = 96 * scale,
 
      h = 96 * scale
 
    });
 
  else
 
    tbg, tbg_slice = dire_slice_9(src, {
 
      x = 6 * scale,
 
      y = 6 * scale,
 
      w = 128 * scale,
 
      h = 128 * scale
 
    });
 
  end;
 
  
 
  return tbg, tbg_slice;
 
end;
 

	
 
function make_ending_frame(scale, theme, tbg, tbg_slice)
 
	local fdx, fdy, frw, frh;
 
	
 
	if theme == 'main' or theme == 'bwm'  then
 
		frw = 978 * scale;
 
		frh = 612 * scale;
 
		fdx = 9 * scale;
 
		fdy = 6 * scale;
 
	else
 
		frw = 970 * scale;
 
		frh = 610 * scale;
 
		fdx = 5 * scale;
 
		fdy = 5 * scale;
 
	end;
 
	
 
	local bgframe = pixels.new(frw, frh);
 
	dire_draw_9(tbg, bgframe, {x = 0; y = 0; w = frw; h = frh}, {parts=tbg_slice});
 
	return bgframe, fdx, fdy, frw, frh;
 
  local fdx, fdy, frw, frh;
 
  
 
  if theme == 'main' or theme == 'bwm'  then
 
    frw = 978 * scale;
 
    frh = 612 * scale;
 
    fdx = 9 * scale;
 
    fdy = 6 * scale;
 
  else
 
    frw = 970 * scale;
 
    frh = 610 * scale;
 
    fdx = 5 * scale;
 
    fdy = 5 * scale;
 
  end;
 
  
 
  local bgframe = pixels.new(frw, frh);
 
  dire_draw_9(tbg, bgframe, {x = 0; y = 0; w = frw; h = frh}, {parts=tbg_slice});
 
  return bgframe, fdx, fdy, frw, frh;
 
end;
 

	
 
function show_ending(theme, image, position, hide_textbg)
 
@@ -50,15 +50,18 @@ function show_ending(theme, image, posit
 
    position: nil or 0 -- center, 1 -- bottom-left
 
  ]]
 
  --frames, process, delay, frame_nr
 
  if instead.tiny then
 
    return
 
  end;
 
  
 
	local scale = diretheme.get_scale();
 
	
 
  local scale = diretheme.get_scale();
 
  
 
  local unscaled_sw, unscaled_sh = diretheme.get_scaled_screen();
 
  
 
  local unscaled_w = 960;
 
  local unscaled_h = 600;
 
  
 
	local ox = math.floor((unscaled_sw - unscaled_w) / 2);
 
  local ox = math.floor((unscaled_sw - unscaled_w) / 2);
 
  local oy = math.floor((unscaled_sh - unscaled_h) / 2);
 

	
 
  if position == 1 then
 
@@ -72,7 +75,7 @@ function show_ending(theme, image, posit
 
  
 
  if hide_textbg then
 
    D {'textbg'};
 
  else
 
  elseif unscaled_sw ~= 640 or unscaled_sh ~= 480 then
 
    local sw, sh = diretheme.get_screen();
 
    local tx = 24 * scale;
 
    local tw = sw - tx - 24 * scale;
 
@@ -134,41 +137,37 @@ room {
 
  {
 
    state = 0;
 
  };
 
	nam = 'ending_left';
 
	nofollow = true;
 
	theme = 'ending_outside';
 
	disp = translate("ending_locale", 'game_end');
 
	noinv = true;
 
	notitle = true;
 
  nam = 'ending_left';
 
  nofollow = true;
 
  theme = 'ending_outside';
 
  disp = translate("ending_locale", 'game_end');
 
  noinv = true;
 
  notitle = true;
 
  nosave = true;
 
  noautosave = true;
 
	themeInit = function(s)
 
  themeInit = function(s)
 
    local scale = diretheme.get_scale();
 
    local width, height = diretheme.get_scaled_screen();
 
    local dx = math.floor((width - 960) / 2);
 
    local dy = math.floor((height - 600) / 2);
 
    
 
		show_ending('main', 'images/endings/tower_left_bg.png');
 
		timer:set(25);
 
    show_ending('main', 'images/endings/tower_left_bg.png');
 
    timer:set(25);
 
    
 
    local animheight = 600 * scale;
 
    if width == 640 and height == 480 then
 
      animheight=360 * scale;
 
    end;
 
    
 
    animation_set({
 
      {type="delay", delay=2000};
 
      {
 
          type="image", 
 
          image=get_sprite('images/endings/tower_left_bg.png'),
 
          x = dx * scale,
 
          y = dy * scale,
 
          w = 960 * scale,
 
          h = 600 * scale,
 
          background = true
 
        };
 
      {
 
          type="anim",
 
          image=get_sprite('images/endings/tower_left_frames.png'),
 
          x = dx * scale,
 
          y = dy * scale,
 
          w = 960 * scale, 
 
          h = 600 * scale, 
 
          h = animheight, 
 
          frames=6,
 
          delay=500,
 
          frame_data = {
 
@@ -181,19 +180,19 @@ room {
 
          };
 
        };
 
    }, true);
 
	end;
 
	onenter = function(s)
 
		s.state = s.state + 1;
 
		if s.state == 1 then
 
			p(translate_now("ending_locale", 'left_state_1'));
 
			return false;
 
		elseif s.state == 2 then
 
			p(translate_now("ending_locale", 'left_state_2'));
 
			return false;
 
		elseif s.state == 3 then
 
			p(translate_now("ending_locale", 'left_state_3'));
 
			return false;
 
		end;
 
  end;
 
  onenter = function(s)
 
    s.state = s.state + 1;
 
    if s.state == 1 then
 
      p(translate_now("ending_locale", 'left_state_1'));
 
      return false;
 
    elseif s.state == 2 then
 
      p(translate_now("ending_locale", 'left_state_2'));
 
      return false;
 
    elseif s.state == 3 then
 
      p(translate_now("ending_locale", 'left_state_3'));
 
      return false;
 
    end;
 
    
 
    if irradiated then
 
      snd.music('sound/bgm_ending_forest_irradiated.ogg');
 
@@ -202,19 +201,19 @@ room {
 
    end;
 
    
 
    enableSmoke('images/endings/tower_left_bg.png');
 
	end;
 
  end;
 
  onexit = function(s)
 
    fading.enabled = false;
 
  end;
 
	dsc = function(s)
 
		p(translate_now("ending_locale", 'left_part_1'));
 
		if solarscale_with_me then
 
			p(translate_now("ending_locale", 'left_part_1_solarscale'));
 
		end;
 
	end;
 
  dsc = function(s)
 
    p(translate_now("ending_locale", 'left_part_1'));
 
    if solarscale_with_me then
 
      p(translate_now("ending_locale", 'left_part_1_solarscale'));
 
    end;
 
  end;
 
  way = {
 
		path {translate("common_locale", 'continue'), 'ending_left_2'};
 
	};
 
    path {translate("common_locale", 'continue'), 'ending_left_2'};
 
  };
 
}
 

	
 
room {
 
@@ -229,9 +228,9 @@ room {
 
      return 'ending_outside';
 
    end;
 
  end;
 
	disp = translate("ending_locale", 'game_end');
 
	noinv = true;
 
	notitle = true;
 
  disp = translate("ending_locale", 'game_end');
 
  noinv = true;
 
  notitle = true;
 
  themeInit = function(s)
 
    if irradiated then
 
      show_ending('bwm', 'images/endings/tower_left_closed_bw.png');
 
@@ -240,16 +239,16 @@ room {
 
    end;
 
    
 
    animation_set(false);
 
	end;
 
	dsc = function(s)
 
		pn(translate_now("ending_locale", 'left_part_2'));
 
		if solarscale_with_me then
 
			pn(translate_now("ending_locale", 'solarscale_lost'));
 
		end;
 
  end;
 
  dsc = function(s)
 
    pn(translate_now("ending_locale", 'left_part_2'));
 
    if solarscale_with_me then
 
      pn(translate_now("ending_locale", 'solarscale_lost'));
 
    end;
 
    if irradiated then
 
      p(translate_now("ending_locale", 'irradiated'));
 
    end;
 
	end;
 
  end;
 
  way = {
 
    path {translate("common_locale", 'continue'), function(s)
 
        if irradiated then
 
@@ -267,19 +266,19 @@ 2. Destroying the tower
 
]]
 

	
 
room {
 
	nam = 'ending_formatted';
 
	disp = translate("ending_locale", 'game_end');
 
	theme = 'ending_outside';
 
	nofollow = true;
 
	noinv = true;
 
	notitle = true;
 
	theme = 'ending_outside';
 
  nam = 'ending_formatted';
 
  disp = translate("ending_locale", 'game_end');
 
  theme = 'ending_outside';
 
  nofollow = true;
 
  noinv = true;
 
  notitle = true;
 
  theme = 'ending_outside';
 
  nosave = true;
 
  noautosave = true;
 
	themeInit = function(s)
 
		show_ending('main', 'images/endings/tower_ruin.png');
 
  themeInit = function(s)
 
    show_ending('main', 'images/endings/tower_ruin.png');
 
    timer:set(25);
 
	end;
 
  end;
 
  onenter = function(s)
 
    if irradiated then
 
      snd.music('sound/bgm_ending_forest_irradiated.ogg');
 
@@ -290,16 +289,16 @@ room {
 
  onexit = function(s)
 
    fading.enabled = false;
 
  end;
 
	dsc = function(s)
 
		if solarscale_with_me then
 
			p(translate_now("ending_locale", 'formatted_solarscale'));
 
		else
 
			p(translate_now("ending_locale", 'formatted_alone'));
 
		end;
 
	end;
 
  dsc = function(s)
 
    if solarscale_with_me then
 
      p(translate_now("ending_locale", 'formatted_solarscale'));
 
    else
 
      p(translate_now("ending_locale", 'formatted_alone'));
 
    end;
 
  end;
 
  way = {
 
		path {translate("common_locale", 'continue'), 'ending_formatted_2'};
 
	};
 
    path {translate("common_locale", 'continue'), 'ending_formatted_2'};
 
  };
 
}
 

	
 
room {
 
@@ -314,25 +313,25 @@ room {
 
  end;
 
  nosave = true;
 
  noautosave = true;
 
	disp = translate("ending_locale", 'game_end');
 
	noinv = true;
 
	notitle = true;
 
  disp = translate("ending_locale", 'game_end');
 
  noinv = true;
 
  notitle = true;
 
  themeInit = function(s)
 
    if irradiated then
 
      return show_ending('bwm', 'images/endings/tower_ruin_bw.png');
 
    else
 
      return show_ending('main', 'images/endings/tower_ruin.png');
 
    end;
 
	end;
 
	dsc = function(s)
 
		pn(translate_now("ending_locale", 'formatted_2'));
 
		if solarscale_with_me then
 
			pn(translate_now("ending_locale", 'solarscale_lost'));
 
		end;
 
  end;
 
  dsc = function(s)
 
    pn(translate_now("ending_locale", 'formatted_2'));
 
    if solarscale_with_me then
 
      pn(translate_now("ending_locale", 'solarscale_lost'));
 
    end;
 
    if irradiated then
 
      p(translate_now("ending_locale", 'irradiated'));
 
    end;
 
	end;
 
  end;
 
  way = {
 
    path {translate("common_locale", 'continue'), function(s)
 
        if irradiated then
 
@@ -372,7 +371,7 @@ ending_room {
 
      dy = height - 600;
 
    end;
 
    
 
		show_ending('main', 'images/endings/crater_edge/tower_solarscale.png', 1);
 
    show_ending('main', 'images/endings/crater_edge/tower_solarscale.png', 1);
 
    animation_set({
 
        {type="delay", delay=2000};
 
        {
 
@@ -387,28 +386,28 @@ ending_room {
 
        };
 
    }, true);
 
    timer:set(25);
 
	end;
 
  end;
 
  onexit = function(s)
 
    fading.enabled = false;
 
  end;
 
  way = {
 
		path {translate("common_locale", 'continue'), 'ending_solarscale_flies_away'};
 
	};
 
    path {translate("common_locale", 'continue'), 'ending_solarscale_flies_away'};
 
  };
 
}
 

	
 
room {
 
	nam = 'ending_solarscale_pre';
 
	theme = 'tower';
 
	disp = translate("tower_locale", 'tower_level_4_room_2_disp');
 
  nam = 'ending_solarscale_pre';
 
  theme = 'tower';
 
  disp = translate("tower_locale", 'tower_level_4_room_2_disp');
 
  nofollow = true;
 
	noinv = true;
 
  noinv = true;
 
  nosave = true;
 
  noautosave = true;
 
  pic = 'images/tower_level_4_room_2_light.png';
 
  dsc = translate("ending_locale", 'ending_solarscale_pre');
 
	way = {
 
		path {translate("common_locale", 'continue'), 'ending_solarscale_dlg'};
 
	};
 
  way = {
 
    path {translate("common_locale", 'continue'), 'ending_solarscale_dlg'};
 
  };
 
}
 

	
 
local solarscale_convince = function(s)
 
@@ -426,23 +425,23 @@ end;
 

	
 
dlg {
 
  weight = 0;
 
	nam = 'ending_solarscale_dlg';
 
	nofollow = true;
 
	theme = 'tower';
 
	noinv = true;
 
	disp = translate("solarscale_locale", 'disp');
 
  nam = 'ending_solarscale_dlg';
 
  nofollow = true;
 
  theme = 'tower';
 
  noinv = true;
 
  disp = translate("solarscale_locale", 'disp');
 
  nosave = true;
 
  noautosave = true;
 
  pic = 'images/tower_level_4_room_2_light.png;images/characters/solarscale_tower_dusk.png';
 
	enter = translate("ending_locale", 'true_solarscale_dlg_enter');
 
	phr = {
 
		{translate("ending_locale", "true_solarscale_dlg_1"), function(s)
 
			walk('ending_solarscale_leaving_hold');
 
		end};
 
		{translate("ending_locale", "true_solarscale_dlg_2"), translate("ending_locale", "true_solarscale_dlg_2_response"), next='#convince'};
 
		{translate("ending_locale", "true_solarscale_dlg_end"), function(s)
 
			walk('ending_solarscale_leaving_farewell');
 
		end};
 
  enter = translate("ending_locale", 'true_solarscale_dlg_enter');
 
  phr = {
 
    {translate("ending_locale", "true_solarscale_dlg_1"), function(s)
 
      walk('ending_solarscale_leaving_hold');
 
    end};
 
    {translate("ending_locale", "true_solarscale_dlg_2"), translate("ending_locale", "true_solarscale_dlg_2_response"), next='#convince'};
 
    {translate("ending_locale", "true_solarscale_dlg_end"), function(s)
 
      walk('ending_solarscale_leaving_farewell');
 
    end};
 
    {false, '#convince', 
 
      {translate("ending_locale", "true_solarscale_dlg_1"), function(s)
 
        walk('ending_solarscale_leaving_hold');
 
@@ -457,13 +456,13 @@ dlg {
 
      {cond=function(s) return solarscale_helps < 2 end; translate("ending_locale", "true_solarscale_dlg_7"), solarscale_convince};
 
      {cond=function(s) return solarscale_glade_visited end; translate("ending_locale", "true_solarscale_dlg_8"), solarscale_convince};
 
    };
 
	};
 
  };
 
}
 

	
 
room {
 
  nam = 'ending_solarscale_stays';
 
  nofollow = true;
 
	theme = 'tower';
 
  theme = 'tower';
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
@@ -471,20 +470,20 @@ room {
 
  pic = 'images/tower_level_4_room_2_light.png;images/characters/solarscale_tower_dusk.png';
 
  decor = translate("ending_locale", "true_solarscale_convince_level_4");
 
  way = {
 
		path {translate("common_locale", 'continue'), 'ending_solarscale_stays_part_2'};
 
	};
 
    path {translate("common_locale", 'continue'), 'ending_solarscale_stays_part_2'};
 
  };
 
};
 

	
 
room {
 
	nam = 'ending_solarscale_stays_part_2';
 
	notitle = true;
 
	nofollow = true;
 
	theme = 'ending_outside';
 
	noinv = true;
 
	disp = translate("ending_locale", 'game_end');
 
  nam = 'ending_solarscale_stays_part_2';
 
  notitle = true;
 
  nofollow = true;
 
  theme = 'ending_outside';
 
  noinv = true;
 
  disp = translate("ending_locale", 'game_end');
 
  nosave = true;
 
  noautosave = true;
 
	dsc = translate("ending_locale", 'true_solarscale_stays');
 
  dsc = translate("ending_locale", 'true_solarscale_stays');
 
  onenter = function(s)
 
    solarscale_stays = true;
 
    enableSmoke('images/endings/crater_edge/crater_edge.png', 1);
 
@@ -503,7 +502,7 @@ room {
 
      dy = height - 600;
 
    end;
 
    
 
		show_ending('main', 'images/endings/crater_edge/crater_edge.png', 1);
 
    show_ending('main', 'images/endings/crater_edge/crater_edge.png', 1);
 
    animation_set({
 
        {type="delay", delay=2000};
 
        {
 
@@ -519,34 +518,34 @@ room {
 
    }, true);
 
  
 
    timer:set(25);
 
	end;
 
  end;
 
  onexit = function(s)
 
    fading.enabled = false;
 
  end;
 
	way = {
 
		path {translate("common_locale", 'continue'), 'ending_welcome'};
 
	};
 
  way = {
 
    path {translate("common_locale", 'continue'), 'ending_welcome'};
 
  };
 
};
 

	
 
room {
 
  nam = 'ending_solarscale_leaving_farewell';
 
  nofollow = true;
 
	theme = 'tower';
 
  theme = 'tower';
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
  disp = translate("tower_locale", 'tower_level_4_room_2_disp');
 
  pic = 'images/tower_level_4_room_2_light.png';
 
  decor =  translate("ending_locale", "true_solarscale_dlg_end_response");
 
  decor = translate("ending_locale", "true_solarscale_dlg_end_response");
 
  way = {
 
		path {translate("common_locale", 'continue'), 'ending_solarscale_leaving_part_2'};
 
	};
 
    path {translate("common_locale", 'continue'), 'ending_solarscale_leaving_part_2'};
 
  };
 
};
 

	
 
room {
 
  nam = 'ending_solarscale_leaving_hold';
 
  nofollow = true;
 
	theme = 'tower';
 
  theme = 'tower';
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
@@ -554,16 +553,16 @@ room {
 
  disp = translate("tower_locale", 'tower_level_4_room_2_disp');
 
  decor =  translate("ending_locale", "true_solarscale_dlg_1_response");
 
  way = {
 
		path {translate("common_locale", 'continue'), 'ending_solarscale_leaving_part_2'};
 
	};
 
    path {translate("common_locale", 'continue'), 'ending_solarscale_leaving_part_2'};
 
  };
 
};
 

	
 
room {
 
	nam = 'ending_solarscale_leaving_part_2';
 
	notitle = true;
 
	nofollow = true;
 
	noinv = true;
 
	disp = translate("ending_locale", 'game_end');
 
  nam = 'ending_solarscale_leaving_part_2';
 
  notitle = true;
 
  nofollow = true;
 
  noinv = true;
 
  disp = translate("ending_locale", 'game_end');
 
  theme = 'ending_outside';
 
  nosave = true;
 
  noautosave = true;
 
@@ -576,7 +575,12 @@ room {
 
    local dx = math.floor((width - 960) / 2);
 
    local dy = math.floor((height - 600) / 2);
 
    
 
		show_ending('main', 'images/endings/tower_left_bg.png');
 
    local animheight = 600 * scale;
 
    if width == 640 and height == 480 then
 
      animheight=360 * scale;
 
    end;
 
    
 
    show_ending('main', 'images/endings/tower_left_bg.png');
 
    animation_set({
 
        {type="delay", delay=2000};
 
        {
 
@@ -585,7 +589,7 @@ room {
 
          x = dx * scale,
 
          y = dy * scale,
 
          w = 960 * scale,
 
          h = 600 * scale,
 
          h = animheight,
 
          background = true
 
        };
 
        {
 
@@ -594,7 +598,7 @@ room {
 
          x = dx * scale,
 
          y = dy * scale,
 
          w = 960 * scale,
 
          h = 600 * scale,
 
          h = animheight,
 
          frames = 15,
 
          delay = 100,
 
          background = true,
 
@@ -622,9 +626,10 @@ room {
 
          x = dx * scale,
 
          y = dy * scale,
 
          w = 960 * scale, 
 
          h = 600 * scale, 
 
          h = animheight,
 
          frames=6,
 
          delay=500,
 
          background = true,
 
          frame_data = {
 
            {};
 
            {x=0, y=318, w=51, h=16,  dx=444, dy=246};
 
@@ -643,16 +648,16 @@ room {
 
  end;
 
  pic = 'images/tower_level_4_room_2_light.png';
 
  decor = translate("ending_locale", 'true_solarscale_leaving');
 
	way = {
 
		path {translate("common_locale", 'continue'), 'ending_dissolving_tower_solarscale_alt'};
 
	};
 
  way = {
 
    path {translate("common_locale", 'continue'), 'ending_dissolving_tower_solarscale_alt'};
 
  };
 
}
 

	
 
room {
 
  nam = 'ending_dissolving_tower_solarscale_alt';
 
  notitle = true;
 
	nofollow = true;
 
	theme = 'ending_outside';
 
  nofollow = true;
 
  theme = 'ending_outside';
 
  noinv = true;
 
  notitle = true;
 
  nosave = true;
 
@@ -672,7 +677,7 @@ room {
 
      dy = height - 600;
 
    end;
 
    
 
		show_ending('main', 'images/endings/crater_edge/tower_solarscale.png', 1);
 
    show_ending('main', 'images/endings/crater_edge/tower_solarscale.png', 1);
 
    animation_set({
 
        {type="delay", delay=2000};
 
        {
 
@@ -687,18 +692,18 @@ room {
 
        };
 
    }, true);
 
    timer:set(25);
 
	end;
 
  end;
 
  dsc = translate("ending_locale", 'ending_dissolving_tower_solarscale_alt');
 
  way = {
 
		path {translate("common_locale", 'continue'), 'ending_solarscale_flies_away'};
 
	};
 
    path {translate("common_locale", 'continue'), 'ending_solarscale_flies_away'};
 
  };
 
};
 

	
 
room {
 
  nam = 'ending_solarscale_flies_away';
 
  notitle = true;
 
	nofollow = true;
 
	theme = 'ending_outside';
 
  nofollow = true;
 
  theme = 'ending_outside';
 
  noinv = true;
 
  notitle = true;
 
  nosave = true;
 
@@ -718,7 +723,12 @@ room {
 
      dy = height - 600;
 
    end;
 
    
 
		show_ending('main', 'images/endings/crater_edge/solarscale.png', 1);
 
    local animheight = 600;
 
    if width == 640 and height == 480 then
 
      animheight = 420;
 
    end;
 
    
 
    show_ending('main', 'images/endings/crater_edge/solarscale.png', 1);
 
    animation_set({
 
        {type="delay", delay=2000};
 
        {
 
@@ -727,7 +737,7 @@ room {
 
          x = dx * scale,
 
          y = dy * scale,
 
          w = 960 * scale,
 
          h = 600 * scale,
 
          h = animheight * scale,
 
          background = true
 
        };
 
        {
 
@@ -736,7 +746,7 @@ room {
 
          x = dx * scale,
 
          y = dy * scale,
 
          w = 960 * scale,
 
          h = 600 * scale,
 
          h = animheight * scale,
 
          frames = 28,
 
          delay = 125,
 
          background = true,
 
@@ -773,19 +783,62 @@ room {
 
          };
 
        };
 
    }, true);
 
	end;
 
  end;
 
  dsc = translate("ending_locale", 'true_solarscale_outside_part_2');
 
  way = {
 
		path {translate("common_locale", 'continue'), 'ending_welcome'};
 
	};
 
    path {translate("common_locale", 'continue'), 'ending_welcome'};
 
  };
 
}
 

	
 
local function bayer(size)
 
  if size == 1 then
 
    return {
 
      {0}
 
    };
 
  end;
 
  
 
  local u = bayer(size / 2);
 
  local v = 4;
 
  local h = size / 2;
 
  local m = {};
 
  
 
  for j = 1, h do
 
    m[j] = {};
 
    for i = 1, h do
 
      m[j][i] = u[j][i] * v;
 
    end;
 
  end;
 
  
 
  for j = h + 1, size do
 
    m[j] = {};
 
    for i = 1, h do
 
      m[j][i] = u[j - h][i] * v + 3;
 
    end;
 
  end;
 
  
 
  for j = 1, h do
 
    for i = h + 1, size  do
 
      m[j][i] = u[j][i - h] * v + 2;
 
    end;
 
  end;
 
  
 
  for j = h + 1, size do
 
    for i = h + 1, size do
 
      m[j][i] = u[j - h][i - h] * v + 1;
 
    end;
 
  end;
 
  
 
  return m;
 
end;
 

	
 
ending_room {
 
  nam = 'ending_welcome';
 
  theme = 'ending_inside';
 
  themeInit = function(s)
 
    if instead.tiny then
 
      return;
 
    end;
 
    local scale = diretheme.get_scale();
 
    local uwidth, uheight = diretheme.get_screen();
 
    local width, height = diretheme.get_scaled_screen();
 
    local pic_dx = math.floor((width - 960) / 2);
 
    local pic_dy = math.floor((height - 600) / 2);
 
@@ -810,48 +863,130 @@ ending_room {
 
      src = sprite.new('images/endings/pre_space_1.png');
 
      dst = sprite.new('images/endings/pre_space_2.png');
 
    end;
 
    
 
    if width == 640 and height == 480 then
 
      height = 300;
 
    end;
 
    
 
    if pic_dx < 0 or pic_dy < 0 then
 
      local src2 = sprite.new(width, height);
 
      src:copy(-pic_dx, -pic_dy, width, height, src2, 0, 0);
 
      src = src2;
 
    end;
 
    
 
    newsrc = sprite.new(width, height);
 
    src:copy(-pic_dx, -pic_dy, width, height, newsrc, 0, 0);
 
    
 
    -- A tiny performance test: painting 1 - 512 lines, doubling every time. If any of the operations takes more than 10ms -- switch to lo-perf mode
 
    local passed = true;
 
    local test = 1;
 
    while passed and test <= 512 do
 
      local t = instead.ticks();
 
      local tdst = sprite.new(width, test);
 
      tdst:draw(-pic_dx, 0, width, test, newsrc, 0, 0, 1);
 
      if instead.ticks() - t > 10 then
 
        passed = false;
 
      end;
 
      test = test * 2;
 
    end;
 
    
 
    src:copy(0, 0, width, height, newsrc, 0, 0);
 
    
 
    local alpha = 1;
 
    local part = 0;
 
    local partcount = 10;
 
    local partheight = math.floor(600 / partcount);
 
    local partheight;
 
    local parts = {};
 
    local dalpha = 1;
 
    local alternative = false;
 
    local delta = 25;
 
    
 
    -- Now calculate animation speed
 
    -- Expected duration is 125 ms before shifting alpha by 1
 
    if passed then
 
      -- Test passed, can paint the whole sprite in one part
 
      partcount = 1;
 
      partheight = height;
 
    else
 
      -- test failed; Calculate, how fast painting can be done
 
      test = math.max(test / 4, 1); -- Rows in one frame
 
      partcount = math.ceil(height / test);
 
      dalpha = math.floor(partcount / 5);
 
      alpha = dalpha;
 
      partheight = math.floor(height / partcount);
 
    end;  
 
    
 
    for i = 1, partcount do
 
      parts[i] = sprite.new(width, partheight);
 
      dst:copy(-pic_dx, (i - 1) * partheight, width, partheight, parts[i], 0, 0);
 
    end;    
 
    
 
    local process = function(s)
 
      src:copy(-pic_dx, part * partheight, width, partheight, newsrc, 0, pic_dy + part * partheight);
 
    if partcount > 25 then
 
      -- test completely failed; Use alternative animation
 
      alternative = true;
 
      alpha = 1;
 
      delta = 125;
 
    else
 
      for i = 1, partcount do
 
        parts[i] = sprite.new(width, partheight);
 
        dst:copy(-pic_dx, (i - 1) * partheight - pic_dy, width, partheight, parts[i], 0, 0);
 
      end;
 
      dst = nil;
 
    end;
 
        
 
    local process;
 
    if alternative then
 
      local map = {};
 
      local m = bayer(16);
 
      for j = 1, 16 do
 
        for i = 1, 16 do
 
          map[i + j * 16 - 16] = m[j][i];
 
        end;
 
      end;      
 
      
 
      if alpha < 255 then
 
        dst:draw(-pic_dx, part * partheight, width, partheight, newsrc, 0, pic_dy + part * partheight, alpha);
 
      else
 
        dst:copy(-pic_dx, part * partheight, width, partheight, newsrc, 0, pic_dy + part * partheight);
 
      end;
 
      dst = dst:scale(scale, scale, false);
 
      
 
      part = part + 1
 
      if part >= partcount then
 
        part = 0
 
        alpha = alpha + 2
 
        if alpha > 255 then
 
          s.process = nil
 
          -- TODO End
 
      process = function(s)
 
        local i = map[alpha];
 
        while i < height do
 
          if scale == 1 then
 
            dst:copy(-pic_dx, i - pic_dy, width, 1, s.sprite, 0, i);
 
          else
 
            dst:copy(-pic_dy, i * scale - pic_dy, width * scale, scale, s.sprite, 0, i * scale);
 
          end;
 
          i = i + 256;
 
        end;
 
        
 
        if scale ~= 1 then
 
          s.sprite = newsrc:scale(scale, scale, false);
 
        alpha = alpha + 1;
 
        if alpha == 257 then
 
          s.process = nil
 
        end;
 
      end;
 
    else
 
      process = function(s)
 
        src:copy(0, part * partheight, width, partheight, newsrc, 0, part * partheight);
 
        
 
        if alpha < 255 then
 
          parts[part + 1]:draw(newsrc, 0, part * partheight, alpha);
 
        else
 
          newsrc:copy(s.sprite, 0, 0);
 
          parts[part + 1]:copy(newsrc, 0, part * partheight);
 
        end;
 
        
 
        return false;
 
        part = part + 1
 
        if part >= partcount then
 
          if alpha > 255 then
 
            s.process = nil
 
            -- TODO End
 
          end;
 
          
 
          part = 0
 
          alpha = alpha + dalpha;
 
          
 
          if scale ~= 1 then
 
            s.sprite = newsrc:scale(scale, scale, false);
 
          elseif partcount > 1 then
 
            newsrc:copy(s.sprite, 0, 0);
 
          end;
 
          
 
          return false;
 
        end;
 
        
 
        return true;
 
      end;
 
      
 
      return true;
 
    end;
 

	
 
    if solarscale_stays then
 
@@ -862,37 +997,47 @@ ending_room {
 
    local spr
 
    if scale ~= 1 then
 
      spr = newsrc:scale(scale, scale, false);
 
    elseif partcount == 1 then
 
      spr = newsrc;
 
    else
 
      spr = newsrc:dup();
 
    end;
 
      
 
    animation_set({
 
      {type="image", image=spr, x=dx * scale, y=dy * scale, w=width * scale, h=height * scale, process=process, delay=25, background=true};
 
      {type="image", image=spr, x=dx * scale, y=dy * scale, w=width * scale, h=height * scale, process=process, delay=125, background=true};
 
    });
 
    spr = nil;  -- remove reference
 
    timer:set(25);
 
	end;
 
  end;
 
  dsc = translate("ending_locale", 'ending_welcome');
 
  way = {
 
		path {translate("common_locale", 'continue'), function(s)
 
    path {translate("common_locale", 'continue'), function(s)
 
        if solarscale_stays then
 
          return 'ending_solarscale_flight';
 
        else
 
          return 'ending_space_1';
 
        end;
 
    end};
 
	};
 
  };
 
};
 

	
 
ending_room {
 
  nam = 'ending_solarscale_flight';
 
  theme = 'ending_inside';
 
  themeInit = function(s)
 
    if instead.tiny then
 
      return;
 
    end;
 
    local scale = diretheme.get_scale();
 
    local width, height = diretheme.get_scaled_screen();
 
    local dx = math.floor((width - 960) / 2);
 
    local dy = math.floor((height - 600) / 2);
 
    
 
    local animheight = 600 * scale;
 
    if width == 640 and height == 480 then
 
      animheight=360 * scale;
 
    end;
 
    
 
    show_ending('tower', 'images/endings/solarscale/solarscale_first.png');
 
    animation_set({
 
        {type="delay", delay=2000};
 
@@ -902,7 +1047,7 @@ ending_room {
 
          x = dx * scale,
 
          y = dy * scale,
 
          w = 960 * scale,
 
          h = 600 * scale,
 
          h = animheight,
 
          background = true
 
        },
 
        {
 
@@ -911,7 +1056,7 @@ ending_room {
 
          x = dx * scale,
 
          y = dy * scale,
 
          w = 960 * scale,
 
          h = 600 * scale,
 
          h = animheight,
 
          frames = 70,
 
          delay={
 
            150, 150, 150, 150, 150,
 
@@ -1007,32 +1152,35 @@ ending_room {
 
  end;
 
  dsc = translate("ending_locale", 'ending_solarscale_flight');
 
  way = {
 
		path {translate("common_locale", 'continue'), 'ending_space_1'};
 
	};
 
    path {translate("common_locale", 'continue'), 'ending_space_1'};
 
  };
 
}
 

	
 
ending_room {
 
  nam = 'ending_space_1';
 
  theme = 'ending_inside';
 
  themeInit = function(s)
 
    if instead.tiny then
 
      return;
 
    end;
 
    if solarscale_stays then
 
      show_ending('tower', 'images/endings/solarscale/solarscale_first.png');
 
    else
 
      show_ending('tower', 'images/endings/space.png');
 
    end;
 
    animation_set(false);
 
	end;
 
  end;
 
  dsc = function(s)
 
		if solarscale_stays then
 
			pr(translate_now("ending_locale", 'true_step_1_solarscale'));
 
    if solarscale_stays then
 
      pr(translate_now("ending_locale", 'true_step_1_solarscale'));
 
    else
 
      pr(translate_now("ending_locale", 'true_step_1_alone'));
 
		end;
 
    end;
 
    pn();
 
    pr(translate_now("ending_locale", 'true_step_1'));
 
	end;
 
  end;
 
  way = {
 
		path {translate("common_locale", 'continue'), function(s)
 
    path {translate("common_locale", 'continue'), function(s)
 
      if irradiated then
 
        return 'ending_space_2_irradiated';
 
      else
 
@@ -1043,23 +1191,26 @@ ending_room {
 
};
 

	
 
room {
 
	nam = 'ending_space_2';
 
	disp = translate("ending_locale", 'game_end');
 
	noinv = true;
 
	notitle = true;
 
	nofollow = true;
 
  nam = 'ending_space_2';
 
  disp = translate("ending_locale", 'game_end');
 
  noinv = true;
 
  notitle = true;
 
  nofollow = true;
 
  nosave = true;
 
  noautosave = true;
 
	theme = 'ending_inside';
 
  theme = 'ending_inside';
 
  themeInit = function(s)
 
		if solarscale_stays then
 
    if instead.tiny then
 
      return;
 
    end;
 
    if solarscale_stays then
 
      show_ending('tower', 'images/endings/solarscale/solarscale_first.png');
 
    else
 
      show_ending('tower', 'images/endings/space.png');
 
    end;
 
    timer:set(25);
 
	end;
 
	dsc = function(s)
 
  end;
 
  dsc = function(s)
 
    if solarscale_stays then
 
      return translate_now("ending_locale", 'true_step_2_solarscale');
 
    else
 
@@ -1079,18 +1230,18 @@ room {
 
};
 

	
 
room {
 
	nam = 'ending_space_2_irradiated';
 
	disp = translate("ending_locale", 'game_end');
 
	noinv = true;
 
	notitle = true;
 
	nofollow = true;
 
  nam = 'ending_space_2_irradiated';
 
  disp = translate("ending_locale", 'game_end');
 
  noinv = true;
 
  notitle = true;
 
  nofollow = true;
 
  nosave = true;
 
  noautosave = true;
 
	theme = 'ending_inside_bw';
 
  theme = 'ending_inside_bw';
 
  themeInit = function(s)
 
		show_ending('bwt', 'images/endings/space_bw.png');
 
	end;
 
	dsc = translate("ending_locale", 'true_step_2_irradiated');
 
    show_ending('bwt', 'images/endings/space_bw.png');
 
  end;
 
  dsc = translate("ending_locale", 'true_step_2_irradiated');
 
  way = {
 
    path {translate("common_locale", 'continue'), function(s)
 
        _'ending_credits'.etype = 'bwm';
 
@@ -1099,15 +1250,33 @@ room {
 
  };
 
};
 

	
 
function credits_text(centered) 
 
  local closed_beta_participants = 'arbtttrn6, De@th K!d, Fehatt, Lesha Pak, Łukasz Sawicki, Niko Flang, Oleg Bosh, Terracon, Андрей Лобанов';
 
  local tab = '<tab>';
 
  if centered then
 
    tab = '';
 
  end;
 
  return translate_now("menu_locale", 'credits_author') .. ': Khaelenmore Thaal^' ..
 
      translate_now("menu_locale", 'credits_art') .. ': Sabra Naikomy^' ..
 
      translate_now("menu_locale", 'credits_music') .. ': Khaelenmore Thaal^' ..
 
      translate_now("menu_locale", 'credits_engine') .. ': INSTEAD ' .. translate_now("menu_locale", 'credits_engine_author') .. ' {$link https://github.com/instead-hub/instead/}^' ..
 
      translate_now("menu_locale", 'credits_sounds') .. ': {$link https://freesound.org/} CC-0^' ..
 
      translate_now("menu_locale", 'credits_fonts') .. ': VileR {$link https://int10h.org/oldschool-pc-fonts/} CC-BY-SA 4.0^^' ..
 
      translate_now("menu_locale", 'credits_closed_beta') .. ': ' .. closed_beta_participants.. '^^'..
 
      translate_now("menu_locale", "credits_translation") .. ':^' ..
 
      tab .. 'Esperanto: arbtttrn6' .. '^^' ..
 
      translate_now("menu_locale", 'credits_thanks');
 
end;
 

	
 
room {
 
	nam = 'ending_credits';
 
	disp = translate("ending_locale", 'thank_you_for_playing');
 
	noinv = true;
 
	nofollow = true;
 
  nam = 'ending_credits';
 
  disp = translate("ending_locale", 'thank_you_for_playing');
 
  noinv = true;
 
  nofollow = true;
 
  nosave = true;
 
  noautosave = true;
 
  etype = false; -- main, mbw, left, leftbw, format, formatbw
 
	theme = function(s)
 
  theme = function(s)
 
    if s.etype == 'main' or s.etype == 'main_solarscale' then
 
      return 'credits_inside';
 
    elseif s.etype == 'bwm' then
 
@@ -1138,26 +1307,19 @@ room {
 
    else
 
      error('Unexpected ending');
 
    end;
 
		timer:set(25);
 
    timer:set(25);
 
    
 
    if s.etype == 'main' and not irradiated then
 
      prefs.completed = true;
 
    end;
 
    fmt.para = false;
 
	end;  
 
  end;  
 
  themeDispose = function(s)
 
    fmt.para = true;
 
  end;
 
	decor = function(s)
 
		return translate_now("menu_locale", 'credits_author') .. ': Khaelenmore Thaal^' ..
 
			translate_now("menu_locale", 'credits_art') .. ': Sabra Naikomy^' ..
 
			translate_now("menu_locale", 'credits_music') .. ': Khaelenmore Thaal^' ..
 
			translate_now("menu_locale", 'credits_engine') .. ': INSTEAD ' .. translate_now("menu_locale", 'credits_engine_author') .. ' {$link https://github.com/instead-hub/instead/}^' ..
 
			translate_now("menu_locale", 'credits_sounds') .. ': {$link https://freesound.org/} CC-0^' ..
 
			translate_now("menu_locale", 'credits_fonts') .. ': VileR {$link https://int10h.org/oldschool-pc-fonts/} CC-BY-SA 4.0^^' ..
 
      translate_now("menu_locale", 'credits_closed_beta') .. ': ' .. closed_beta_participants.. '^^'..
 
			translate_now("menu_locale", 'credits_thanks');
 
	end;
 
  decor = function(s)
 
    return credits_text(true);
 
  end;
 
  way = {
 
    path {translate("ending_locale", 'show_menu'), 'reset'};
 
  };
forest.lua
Show inline comments
 
global {
 
	raspberry_pie_status = 0;
 
	seen_ring_librarian = false;
 
	seen_ring_box = false;
 
	power_on = false;
 
	irradiated = false;
 
	rods_raised = false;
 
	rods_enriched = false;
 
	candles_solved = false;
 
	solarscale_with_me = false;
 
  raspberry_pie_status = 0;
 
  seen_ring_librarian = false;
 
  seen_ring_box = false;
 
  power_on = false;
 
  irradiated = false;
 
  rods_raised = false;
 
  rods_enriched = false;
 
  candles_solved = false;
 
  solarscale_with_me = false;
 

	
 
	solarscale_helps = 2;
 
	solarscale_glade_visited = false;
 
	pc_status = false;
 
	village_visited = false;
 
	candle_taken = false;
 
  solarscale_helps = 2;
 
  solarscale_glade_visited = false;
 
  pc_status = false;
 
  village_visited = false;
 
  candle_taken = false;
 
  tower_seen = false;
 
  tower_accept_level = 0; --0 -- no contanct, 1 -- level 3 reached, 2 -- level 4 completed, 3 -- complete acceptance
 
  tea_answer_1 = 0; --0 -- not spoken or not correct, 1 -- correct, 2 -- don't know
 
@@ -36,23 +36,23 @@ global {
 
}
 

	
 
obj {
 
	nam = 'raspberry_pie';
 
	disp = translate("forest_locale", 'raspberry_pie');
 
	inv = translate("forest_locale", 'raspberry_pie_inv');
 
  nam = 'raspberry_pie';
 
  disp = translate("forest_locale", 'raspberry_pie');
 
  inv = translate("forest_locale", 'raspberry_pie_inv');
 
}
 

	
 
obj {
 
	nam = 'flower';
 
	disp =translate("forest_locale", 'flower');
 
	inv = translate("forest_locale", 'flower_inv');
 
  nam = 'flower';
 
  disp =translate("forest_locale", 'flower');
 
  inv = translate("forest_locale", 'flower_inv');
 
}
 

	
 
obj {
 
	nam = 'lock';
 
	disp = translate("forest_locale", 'lock');
 
	disp2 = translate("forest_locale", 'lock_disp2');
 
	disp3 = translate("forest_locale", 'lock_disp3');
 
	inv = translate("forest_locale", 'lock_inv');
 
  nam = 'lock';
 
  disp = translate("forest_locale", 'lock');
 
  disp2 = translate("forest_locale", 'lock_disp2');
 
  disp3 = translate("forest_locale", 'lock_disp3');
 
  inv = translate("forest_locale", 'lock_inv');
 
}
 

	
 
obj {
 
@@ -74,1029 +74,1029 @@ obj {
 
}
 

	
 
room {
 
	nam = 'above_forest';
 
	pic = 'images/above_forest.png';
 
	disp = translate("forest_locale", 'above_forest');
 
	theme = 'main';
 
	decor = function(s)
 
		p(translate_now("forest_locale", 'above_forest_decor'));
 
		if not village_visited then
 
			p(translate_now("forest_locale", 'above_forest_decor_village'));
 
		end;
 
	end;
 
	enter = function(s)
 
  nam = 'above_forest';
 
  pic = 'images/above_forest.png';
 
  disp = translate("forest_locale", 'above_forest');
 
  theme = 'main';
 
  decor = function(s)
 
    p(translate_now("forest_locale", 'above_forest_decor'));
 
    if not village_visited then
 
      p(translate_now("forest_locale", 'above_forest_decor_village'));
 
    end;
 
  end;
 
  enter = function(s)
 
    if not have('old_map') then
 
      take('old_map');
 
    end;
 
		if here():from()^'intro_start' or here():from()^'intro_settings' or here():from()^'intro_info' then
 
			stop_menu();
 
		end;
 
		if here():from()^'forest_glade' then
 
			pr(translate_now("forest_locale", 'above_forest_enter'));
 
		end;
 
		snd.music('sound/bgm_forest.ogg');
 
	end;
 
	way = {
 
		 path {"#down", translate("forest_locale", 'transition_land'), 'forest_glade'}:disable();
 
		 path {"#north", translate("forest_locale", 'transition_north_along_road'), 'above_near_village'};
 
	}
 
    if here():from()^'intro_start' or here():from()^'intro_settings' or here():from()^'intro_info' then
 
      stop_menu();
 
    end;
 
    if here():from()^'forest_glade' then
 
      pr(translate_now("forest_locale", 'above_forest_enter'));
 
    end;
 
    snd.music('sound/bgm_forest.ogg');
 
  end;
 
  way = {
 
     path {"#down", translate("forest_locale", 'transition_land'), 'forest_glade'}:disable();
 
     path {"#north", translate("forest_locale", 'transition_north_along_road'), 'above_near_village'};
 
  }
 
}:with {
 
	obj {
 
		nam = '#thicket';
 
		act = translate("forest_locale", 'above_forest_thicket_act');
 
	};
 
	obj {
 
		nam = '#road';
 
		act = function(s)
 
			p(translate_now("forest_locale", 'above_forest_road_act'));
 
  obj {
 
    nam = '#thicket';
 
    act = translate("forest_locale", 'above_forest_thicket_act');
 
  };
 
  obj {
 
    nam = '#road';
 
    act = function(s)
 
      p(translate_now("forest_locale", 'above_forest_road_act'));
 

	
 
			if not village_visited then
 
				p(translate_now("forest_locale", 'above_forest_road_act_village'));
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#powerlines';
 
		act = translate("forest_locale", 'above_forest_powerlines_act');
 
	};
 
	obj {
 
		nam = '#glade';
 
		act = function(s)
 
			p(translate_now("forest_locale", 'above_forest_glade_act'));
 
			if _'#down':disabled() then
 
				_'#down':enable();
 
				p(translate_now("forest_locale", 'above_forest_glade_act_first'));
 
			end;
 
		end;
 
	};
 
	'mountains';
 
	'wind';
 
	'sun';
 
	'clouds';
 
      if not village_visited then
 
        p(translate_now("forest_locale", 'above_forest_road_act_village'));
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#powerlines';
 
    act = translate("forest_locale", 'above_forest_powerlines_act');
 
  };
 
  obj {
 
    nam = '#glade';
 
    act = function(s)
 
      p(translate_now("forest_locale", 'above_forest_glade_act'));
 
      if _'#down':disabled() then
 
        _'#down':enable();
 
        p(translate_now("forest_locale", 'above_forest_glade_act_first'));
 
      end;
 
    end;
 
  };
 
  'mountains';
 
  'wind';
 
  'sun';
 
  'clouds';
 
}
 

	
 
room {
 
	nam = 'forest_glade';
 
	pic = function(s)
 
		if lookup('#flowers', 'forest_glade').state == 1 then
 
			return 'images/forest_glade.png';
 
		else
 
			return 'images/forest_glade.png;images/forest_glade_flower.png@269,201';
 
		end;
 
	end;
 
	disp = translate("forest_locale", 'forest_glade');
 
	theme = 'main';
 
	onenter = translate("forest_locale", 'forest_glade_enter');
 
	decor = translate("forest_locale", 'forest_glade_decor');
 
	way = {
 
		path {'#up', translate("forest_locale", 'transition_fly'), 'above_forest'};
 
	}
 
  nam = 'forest_glade';
 
  pic = function(s)
 
    if lookup('#flowers', 'forest_glade').state == 1 then
 
      return 'images/forest_glade.png';
 
    else
 
      return 'images/forest_glade.png;images/forest_glade_flower.png@269,201';
 
    end;
 
  end;
 
  disp = translate("forest_locale", 'forest_glade');
 
  theme = 'main';
 
  onenter = translate("forest_locale", 'forest_glade_enter');
 
  decor = translate("forest_locale", 'forest_glade_decor');
 
  way = {
 
    path {'#up', translate("forest_locale", 'transition_fly'), 'above_forest'};
 
  }
 
}: with {
 
	obj {
 
		nam = '#thicket';
 
		act = translate("forest_locale", 'forest_glade_thicket');
 
	};
 
	obj {
 
		nam = '#birds';
 
		act = translate("forest_locale", 'forest_glade_birds');
 
	};
 
	obj {
 
		nam = '#grass';
 
		act = function(s)
 
			_'#flowers':enable();
 
			return translate_now("forest_locale", 'forest_glade_grass');
 
		end;
 
	};
 
	obj {
 
		state = 0;
 
		nam = '#flowers';
 
		act = function(s)
 
			if s.state == 0 then
 
				take('flower');
 
				s.state = 1;
 
				return translate_now("forest_locale", 'forest_glade_flowers_first');
 
			else
 
				return translate_now("forest_locale", 'forest_glade_flowers');
 
			end;
 
		end;
 
	}:disable();
 
  obj {
 
    nam = '#thicket';
 
    act = translate("forest_locale", 'forest_glade_thicket');
 
  };
 
  obj {
 
    nam = '#birds';
 
    act = translate("forest_locale", 'forest_glade_birds');
 
  };
 
  obj {
 
    nam = '#grass';
 
    act = function(s)
 
      _'#flowers':enable();
 
      return translate_now("forest_locale", 'forest_glade_grass');
 
    end;
 
  };
 
  obj {
 
    state = 0;
 
    nam = '#flowers';
 
    act = function(s)
 
      if s.state == 0 then
 
        take('flower');
 
        s.state = 1;
 
        return translate_now("forest_locale", 'forest_glade_flowers_first');
 
      else
 
        return translate_now("forest_locale", 'forest_glade_flowers');
 
      end;
 
    end;
 
  }:disable();
 
}
 

	
 
room {
 
	nam = 'above_near_village';
 
	disp = translate("forest_locale", 'near_village');
 
	pic = 'images/above_near_village.png';
 
	theme = 'main';
 
	onenter = function(s)
 
		if here()^'near_village' then
 
			return translate_now("forest_locale", 'above_near_village_enter');
 
		end;
 
	end;
 
	decor = translate("forest_locale", 'above_near_village_decor');
 
	way = {
 
		path {"#south", translate("forest_locale", 'transition_south_along_road'), 'above_forest'};
 
		path {"#down", translate("forest_locale", 'transition_land'), 'near_village'};
 
		path {"#north", translate("forest_locale", 'transition_north_to_the_village'), 'above_village'};
 
	}
 
  nam = 'above_near_village';
 
  disp = translate("forest_locale", 'near_village');
 
  pic = 'images/above_near_village.png';
 
  theme = 'main';
 
  onenter = function(s)
 
    if here()^'near_village' then
 
      return translate_now("forest_locale", 'above_near_village_enter');
 
    end;
 
  end;
 
  decor = translate("forest_locale", 'above_near_village_decor');
 
  way = {
 
    path {"#south", translate("forest_locale", 'transition_south_along_road'), 'above_forest'};
 
    path {"#down", translate("forest_locale", 'transition_land'), 'near_village'};
 
    path {"#north", translate("forest_locale", 'transition_north_to_the_village'), 'above_village'};
 
  }
 
}: with {
 
	obj {
 
		nam = '#road';
 
		act = translate("forest_locale", 'above_near_village_road');
 
	};
 
	obj {
 
		nam = '#thicket';
 
		act = translate("forest_locale", 'above_near_village_thicket');
 
	};
 
	obj {
 
		nam = '#village';
 
		act = function(s)
 
			p(translate_now("forest_locale", 'above_near_village_village'));
 
			if not village_visited then
 
				village_visited = true;
 
				p(translate_now("forest_locale", 'village_unvisited'));
 
			end;
 
		end;
 
	};
 
	'mountains';
 
	'wind';
 
	'sun';
 
	'clouds';
 
  obj {
 
    nam = '#road';
 
    act = translate("forest_locale", 'above_near_village_road');
 
  };
 
  obj {
 
    nam = '#thicket';
 
    act = translate("forest_locale", 'above_near_village_thicket');
 
  };
 
  obj {
 
    nam = '#village';
 
    act = function(s)
 
      p(translate_now("forest_locale", 'above_near_village_village'));
 
      if not village_visited then
 
        village_visited = true;
 
        p(translate_now("forest_locale", 'village_unvisited'));
 
      end;
 
    end;
 
  };
 
  'mountains';
 
  'wind';
 
  'sun';
 
  'clouds';
 
};
 

	
 
room {
 
	nam = 'above_village';
 
	pic = 'images/above_village.png';
 
	disp = translate("forest_locale", 'above_village');
 
	theme = 'main';
 
	decor = translate("forest_locale", 'above_village_decor');
 
	way = {
 
		path {"#south", translate("forest_locale", 'transition_south_along_road'), 'above_near_village'};
 
		path {"#down", translate("forest_locale", 'transition_land'), 'village_no_way'};
 
		path {"fly_west_from_village", translate("forest_locale", 'transition_west'), 'above_west'}:disable();
 
	}
 
  nam = 'above_village';
 
  pic = 'images/above_village.png';
 
  disp = translate("forest_locale", 'above_village');
 
  theme = 'main';
 
  decor = translate("forest_locale", 'above_village_decor');
 
  way = {
 
    path {"#south", translate("forest_locale", 'transition_south_along_road'), 'above_near_village'};
 
    path {"#down", translate("forest_locale", 'transition_land'), 'village_no_way'};
 
    path {"fly_west_from_village", translate("forest_locale", 'transition_west'), 'above_west'}:disable();
 
  }
 
}: with {
 
	obj {
 
		nam = '#thicket';
 
		act = translate("forest_locale", 'above_village_thicket');
 
	};
 
	obj {
 
		nam = '#road';
 
		act = translate("forest_locale", 'above_village_road');
 
	};
 
	obj {
 
		nam = '#village';
 
		act = function(s)
 
			p(translate_now("forest_locale", 'above_village_village'));
 
			if not village_visited then
 
				village_visited = true;
 
				p(translate_now("forest_locale", 'village_unvisited'));
 
			end;
 
		end;
 
	};
 
	'mountains';
 
	'wind';
 
	'sun';
 
	'clouds';
 
  obj {
 
    nam = '#thicket';
 
    act = translate("forest_locale", 'above_village_thicket');
 
  };
 
  obj {
 
    nam = '#road';
 
    act = translate("forest_locale", 'above_village_road');
 
  };
 
  obj {
 
    nam = '#village';
 
    act = function(s)
 
      p(translate_now("forest_locale", 'above_village_village'));
 
      if not village_visited then
 
        village_visited = true;
 
        p(translate_now("forest_locale", 'village_unvisited'));
 
      end;
 
    end;
 
  };
 
  'mountains';
 
  'wind';
 
  'sun';
 
  'clouds';
 
};
 

	
 
obj {
 
	nam = 'sun';
 
	act = translate("forest_locale", 'sun');
 
  nam = 'sun';
 
  act = translate("forest_locale", 'sun');
 
};
 

	
 
obj {
 
	nam = 'sun_transformed';
 
	act = translate("forest_locale", 'sun_transformed');
 
  nam = 'sun_transformed';
 
  act = translate("forest_locale", 'sun_transformed');
 
};
 

	
 
obj {
 
	nam = 'clouds';
 
	act = translate("forest_locale", 'clouds');
 
  nam = 'clouds';
 
  act = translate("forest_locale", 'clouds');
 
};
 

	
 
obj {
 
	nam = 'wind';
 
	act = translate("forest_locale", 'wind');
 
  nam = 'wind';
 
  act = translate("forest_locale", 'wind');
 
};
 

	
 
obj {
 
	nam = 'mountains';
 
	act = translate("forest_locale", 'mountains');
 
  nam = 'mountains';
 
  act = translate("forest_locale", 'mountains');
 
};
 

	
 
room {
 
	nam = 'above_west';
 
	disp = translate("forest_locale", 'above_west');
 
	pic = 'images/above_west.png';
 
	theme = 'main';
 
	decor = translate("forest_locale", 'above_west_decor');
 
	way = {
 
		path {"#east", translate("forest_locale", 'transition_east_to_the_village'), 'above_village'};
 
		path {"#west", translate("forest_locale", 'transition_west_to_the_crater'), 'above_crater'}:disable();
 
	}
 
  nam = 'above_west';
 
  disp = translate("forest_locale", 'above_west');
 
  pic = 'images/above_west.png';
 
  theme = 'main';
 
  decor = translate("forest_locale", 'above_west_decor');
 
  way = {
 
    path {"#east", translate("forest_locale", 'transition_east_to_the_village'), 'above_village'};
 
    path {"#west", translate("forest_locale", 'transition_west_to_the_crater'), 'above_crater'}:disable();
 
  }
 
}: with {
 
	obj {
 
		nam = '#village';
 
		act = translate("forest_locale", 'above_west_village');
 
	};
 
	obj {
 
		nam = '#mountains';
 
		act = translate("forest_locale", 'above_west_mountains');
 
	};
 
	obj {
 
		nam = '#mountaintops';
 
		act = translate("forest_locale", 'above_west_mountaintops');
 
	};
 
	obj {
 
		nam = '#mountainslopes';
 
		act = translate("forest_locale", 'above_west_mountainslopes');
 
	};
 
	obj {
 
		nam = '#crater';
 
		act = function(s)
 
			_'#west':enable();
 
			return translate_now("forest_locale", 'above_west_crater');
 
		end;
 
	};
 
	'clouds';
 
	'sun';
 
  obj {
 
    nam = '#village';
 
    act = translate("forest_locale", 'above_west_village');
 
  };
 
  obj {
 
    nam = '#mountains';
 
    act = translate("forest_locale", 'above_west_mountains');
 
  };
 
  obj {
 
    nam = '#mountaintops';
 
    act = translate("forest_locale", 'above_west_mountaintops');
 
  };
 
  obj {
 
    nam = '#mountainslopes';
 
    act = translate("forest_locale", 'above_west_mountainslopes');
 
  };
 
  obj {
 
    nam = '#crater';
 
    act = function(s)
 
      _'#west':enable();
 
      return translate_now("forest_locale", 'above_west_crater');
 
    end;
 
  };
 
  'clouds';
 
  'sun';
 
}
 

	
 
room {
 
	nam = 'above_crater';
 
	pic = 'images/above_crater.png';
 
	theme = 'main';
 
	onenter = function(s)
 
		if here()^'inside_crater_glade' then
 
			p(translate_now("forest_locale", 'above_crater_enter'));
 
		end;
 
	end;
 
	disp = translate("forest_locale", 'above_crater');
 
	decor = translate("forest_locale", 'above_crater_decor');
 
	way = {
 
		path {"#east", translate("forest_locale", 'transition_east'), 'above_west'};
 
		path {"#down", translate("forest_locale", 'transition_land'), 'inside_crater_glade'}:disable();
 
	}
 
  nam = 'above_crater';
 
  pic = 'images/above_crater.png';
 
  theme = 'main';
 
  onenter = function(s)
 
    if here()^'inside_crater_glade' then
 
      p(translate_now("forest_locale", 'above_crater_enter'));
 
    end;
 
  end;
 
  disp = translate("forest_locale", 'above_crater');
 
  decor = translate("forest_locale", 'above_crater_decor');
 
  way = {
 
    path {"#east", translate("forest_locale", 'transition_east'), 'above_west'};
 
    path {"#down", translate("forest_locale", 'transition_land'), 'inside_crater_glade'}:disable();
 
  }
 
}: with {
 
	obj {
 
		nam = '#crater';
 
		act = translate("forest_locale", 'above_crater_crater');
 
	};
 
	obj {
 
		nam = '#tower';
 
		act = translate("forest_locale", 'above_crater_tower');
 
	};
 
	obj {
 
		nam = '#trees';
 
		act = translate("forest_locale", 'above_crater_trees');
 
	};
 
	obj {
 
		nam = '#glade';
 
		act = function(s)
 
			_'#down':enable();
 
			return translate_now("forest_locale", 'above_crater_glade');
 
		end;
 
	};
 
	'wind';
 
	'sun';
 
	'clouds';
 
  obj {
 
    nam = '#crater';
 
    act = translate("forest_locale", 'above_crater_crater');
 
  };
 
  obj {
 
    nam = '#tower';
 
    act = translate("forest_locale", 'above_crater_tower');
 
  };
 
  obj {
 
    nam = '#trees';
 
    act = translate("forest_locale", 'above_crater_trees');
 
  };
 
  obj {
 
    nam = '#glade';
 
    act = function(s)
 
      _'#down':enable();
 
      return translate_now("forest_locale", 'above_crater_glade');
 
    end;
 
  };
 
  'wind';
 
  'sun';
 
  'clouds';
 
}
 

	
 
room {
 
	nam = 'village_no_way';
 
	onenter = function(s)
 
		if solarscale_with_me then
 
			p(translate_now("forest_locale", 'village_no_way_solarscale'));
 
		else
 
			p(translate_now("forest_locale", 'village_no_way_alone'));
 
		end;
 
		return false;
 
	end;
 
  nam = 'village_no_way';
 
  onenter = function(s)
 
    if solarscale_with_me then
 
      p(translate_now("forest_locale", 'village_no_way_solarscale'));
 
    else
 
      p(translate_now("forest_locale", 'village_no_way_alone'));
 
    end;
 
    return false;
 
  end;
 
}
 

	
 
room {
 
	nam = 'near_village';
 
	disp = translate("forest_locale", 'near_village');
 
	pic = 'images/near_village.png';
 
	theme = 'main';
 
	onenter = function(s)
 
		if here()^'above_near_village' then
 
			p(translate_now("forest_locale", 'near_village_enter'));
 
		end;
 
	end;
 
	decor = translate("forest_locale", 'near_village_decor');
 
	way = {
 
		path {"#up", translate("forest_locale", 'transition_fly'), 'above_near_village'};
 
		path {"#north", translate("forest_locale", 'transition_north_to_the_village'), 'village_south'};
 
	}
 
  nam = 'near_village';
 
  disp = translate("forest_locale", 'near_village');
 
  pic = 'images/near_village.png';
 
  theme = 'main';
 
  onenter = function(s)
 
    if here()^'above_near_village' then
 
      p(translate_now("forest_locale", 'near_village_enter'));
 
    end;
 
  end;
 
  decor = translate("forest_locale", 'near_village_decor');
 
  way = {
 
    path {"#up", translate("forest_locale", 'transition_fly'), 'above_near_village'};
 
    path {"#north", translate("forest_locale", 'transition_north_to_the_village'), 'village_south'};
 
  }
 
}: with {
 
	obj {
 
		nam = '#road';
 
		act = translate("forest_locale", 'near_village_road');
 
	};
 
	obj {
 
		nam = '#forest';
 
		act = translate("forest_locale", 'near_village_forest');
 
	};
 
	obj {
 
		nam = '#village';
 
		act = function(s)
 
			p(translate_now("forest_locale", 'near_village_village'));
 
			if not village_visited then
 
				village_visited = true;
 
				p(translate_now("forest_locale", 'village_unvisited'));
 
			end;
 
		end;
 
	};
 
	'sun_transformed';
 
	'clouds';
 
  obj {
 
    nam = '#road';
 
    act = translate("forest_locale", 'near_village_road');
 
  };
 
  obj {
 
    nam = '#forest';
 
    act = translate("forest_locale", 'near_village_forest');
 
  };
 
  obj {
 
    nam = '#village';
 
    act = function(s)
 
      p(translate_now("forest_locale", 'near_village_village'));
 
      if not village_visited then
 
        village_visited = true;
 
        p(translate_now("forest_locale", 'village_unvisited'));
 
      end;
 
    end;
 
  };
 
  'sun_transformed';
 
  'clouds';
 
}
 

	
 
room {
 
	nam = 'village_south';
 
	disp = translate("forest_locale", 'village_south');
 
	pic='images/village_south.png';
 
	theme = 'main';
 
	enter = function(s)
 
		if not village_visited then
 
			village_visited = true;
 
			p(translate_now("forest_locale", 'village_unvisited'));
 
		end;
 
	end;
 
	nofollow = function(s)
 
		if here():from()^'near_village' then
 
			return translate_now("solarscale_locale", 'follow_refuse') .. ' ' ..translate_now("solarscale_locale", 'follow_refuse_village');
 
		else
 
			return true;
 
		end;
 
	end;
 
	decor = translate("forest_locale", 'village_south_decor');
 
	way = {
 
		path {'#south', translate("forest_locale", 'transition_south_to_the_forest'), 'near_village'};
 
		path {'#in', translate("forest_locale", 'transition_inside_hut'), 'foresters_hut'};
 
		path {'#north', translate("forest_locale", 'transition_north_to_the_townhall'), 'village_center'};
 
	};
 
  nam = 'village_south';
 
  disp = translate("forest_locale", 'village_south');
 
  pic='images/village_south.png';
 
  theme = 'main';
 
  enter = function(s)
 
    if not village_visited then
 
      village_visited = true;
 
      p(translate_now("forest_locale", 'village_unvisited'));
 
    end;
 
  end;
 
  nofollow = function(s)
 
    if here():from()^'near_village' then
 
      return translate_now("solarscale_locale", 'follow_refuse') .. ' ' ..translate_now("solarscale_locale", 'follow_refuse_village');
 
    else
 
      return true;
 
    end;
 
  end;
 
  decor = translate("forest_locale", 'village_south_decor');
 
  way = {
 
    path {'#south', translate("forest_locale", 'transition_south_to_the_forest'), 'near_village'};
 
    path {'#in', translate("forest_locale", 'transition_inside_hut'), 'foresters_hut'};
 
    path {'#north', translate("forest_locale", 'transition_north_to_the_townhall'), 'village_center'};
 
  };
 
}:with {
 
	obj {
 
		nam = '#road';
 
		act = translate("forest_locale", 'village_south_road');
 
	};
 
	obj {
 
		nam = '#village';
 
		act = translate("forest_locale", 'village_south_village');
 
	};
 
	obj {
 
		nam = '#foresters_car';
 
		act = translate("forest_locale", 'village_south_car');
 
	};
 
	obj {
 
		nam = '#foresters_hut_out';
 
		act = translate("forest_locale", 'village_south_hut');
 
	};
 
	'sun_transformed';
 
	'clouds';
 
  obj {
 
    nam = '#road';
 
    act = translate("forest_locale", 'village_south_road');
 
  };
 
  obj {
 
    nam = '#village';
 
    act = translate("forest_locale", 'village_south_village');
 
  };
 
  obj {
 
    nam = '#foresters_car';
 
    act = translate("forest_locale", 'village_south_car');
 
  };
 
  obj {
 
    nam = '#foresters_hut_out';
 
    act = translate("forest_locale", 'village_south_hut');
 
  };
 
  'sun_transformed';
 
  'clouds';
 
}
 

	
 
room {
 
	state = 0;
 
	nam = 'foresters_hut';
 
	pic = function(s)
 
		if _'rope':where() == here() then
 
			return 'images/foresters_hut.png;images/foresters_hut_rope.png@8,160';
 
		else
 
			return 'images/foresters_hut.png';
 
		end;
 
	end;
 
	theme = 'main';
 
	nofollow = true;
 
	disp = translate("forest_locale", 'foresters_hut');
 
	enter = function(s)
 
		if s.state == 0 then
 
			s.state = 1;
 
			return translate_now("forest_locale", 'foresters_hut_enter');
 
		end;
 
	end;
 
	decor = translate("forest_locale", 'foresters_hut_decor');
 
	way = {
 
		path {'#out', translate("forest_locale", 'transition_out'), 'village_south'};
 
	}
 
  state = 0;
 
  nam = 'foresters_hut';
 
  pic = function(s)
 
    if _'rope':where() == here() then
 
      return 'images/foresters_hut.png;images/foresters_hut_rope.png@8,160';
 
    else
 
      return 'images/foresters_hut.png';
 
    end;
 
  end;
 
  theme = 'main';
 
  nofollow = true;
 
  disp = translate("forest_locale", 'foresters_hut');
 
  enter = function(s)
 
    if s.state == 0 then
 
      s.state = 1;
 
      return translate_now("forest_locale", 'foresters_hut_enter');
 
    end;
 
  end;
 
  decor = translate("forest_locale", 'foresters_hut_decor');
 
  way = {
 
    path {'#out', translate("forest_locale", 'transition_out'), 'village_south'};
 
  }
 
}:with {
 
	obj {
 
		nam = '#sofa';
 
		act = translate("forest_locale", 'foresters_hut_sofa');
 
	};
 
	obj {
 
		nam = '#cupboard';
 
		act = translate("forest_locale", 'foresters_hut_cupboard');
 
	};
 
	obj {
 
		nam = '#table';
 
		act = translate("forest_locale", 'foresters_hut_table');
 
	};
 
	obj {
 
		nam = '#chairs';
 
		act = translate("forest_locale", 'foresters_hut_chairs');
 
	};
 
	obj {
 
		nam = '#radio';
 
		act = translate("forest_locale", 'foresters_hut_radio');
 
	};
 
	obj {
 
		bought = false;
 
		nam = 'forester';
 
		dsc = translate("forest_locale", 'foresters_hut_forester');
 
		act = function(s)
 
			walkin('forester_dlg');
 
		end;
 
		used = function(s, o)
 
			if o^'raspberry_pie' then
 
				return translate_now("forest_locale", 'foresters_hut_forester_pie');
 
			else
 
				return translate_now("forest_locale", 'foresters_hut_not_interested');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = 'rope';
 
		disp = translate("forest_locale", 'foresters_hut_rope_disp');
 
		dsc = translate("forest_locale", 'foresters_hut_rope');
 
		act = function(s)
 
			if _('forester').bought then
 
				p(translate_now("forest_locale", 'foresters_hut_rope_taken'));
 
				take('rope')
 
			else
 
				p(translate_now("forest_locale", 'foresters_hut_rope_not_taken'));
 
			end;
 
		end;
 
		inv = translate("forest_locale", 'foresters_hut_rope_inv');
 
	};
 
  obj {
 
    nam = '#sofa';
 
    act = translate("forest_locale", 'foresters_hut_sofa');
 
  };
 
  obj {
 
    nam = '#cupboard';
 
    act = translate("forest_locale", 'foresters_hut_cupboard');
 
  };
 
  obj {
 
    nam = '#table';
 
    act = translate("forest_locale", 'foresters_hut_table');
 
  };
 
  obj {
 
    nam = '#chairs';
 
    act = translate("forest_locale", 'foresters_hut_chairs');
 
  };
 
  obj {
 
    nam = '#radio';
 
    act = translate("forest_locale", 'foresters_hut_radio');
 
  };
 
  obj {
 
    bought = false;
 
    nam = 'forester';
 
    dsc = translate("forest_locale", 'foresters_hut_forester');
 
    act = function(s)
 
      walkin('forester_dlg');
 
    end;
 
    used = function(s, o)
 
      if o^'raspberry_pie' then
 
        return translate_now("forest_locale", 'foresters_hut_forester_pie');
 
      else
 
        return translate_now("forest_locale", 'foresters_hut_not_interested');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = 'rope';
 
    disp = translate("forest_locale", 'foresters_hut_rope_disp');
 
    dsc = translate("forest_locale", 'foresters_hut_rope');
 
    act = function(s)
 
      if _('forester').bought then
 
        p(translate_now("forest_locale", 'foresters_hut_rope_taken'));
 
        take('rope')
 
      else
 
        p(translate_now("forest_locale", 'foresters_hut_rope_not_taken'));
 
      end;
 
    end;
 
    inv = translate("forest_locale", 'foresters_hut_rope_inv');
 
  };
 
}
 

	
 
dlg {
 
	nam = 'forester_dlg';
 
	disp = translate("forest_locale", 'forester_dlg_disp');
 
	theme = 'main';
 
	pic = 'images/characters/forester.png';
 
	enter = translate("forest_locale", 'forester_dlg_enter');
 
	phr = {
 
		{translate("forest_locale", 'common_dlg_greet'), translate("forest_locale", 'forester_dlg_greet_response'),
 
			{translate("forest_locale", 'common_dlg_places'), translate("forest_locale", 'forester_dlg_places_response')};
 
		},
 
		{cond=function(s) return where('rope') and where('rope')^'foresters_hut' and not _('forester').bought end, translate("forest_locale", 'forester_dlg_rope'), function(s)
 
			p(translate_now("forest_locale", 'forester_dlg_rope_response'));
 
			raspberry_pie_status = 1;
 
		end},
 
		{cond=function(s) return have 'raspberry_pie' end, translate("forest_locale", 'forester_dlg_pie'), function(s)
 
			remove('raspberry_pie', pl);
 
			p(translate_now("forest_locale", 'forester_dlg_pie_response'));
 
			raspberry_pie_status = 2;
 
			_('forester').bought = 1;
 
		end},
 
		{true, translate("forest_locale", 'common_dlg_bye'), function(s)
 
			p(translate_now("forest_locale", 'forester_dlg_farewell_response'));
 
			walkout();
 
		end}
 
	}
 
  nam = 'forester_dlg';
 
  disp = translate("forest_locale", 'forester_dlg_disp');
 
  theme = 'main';
 
  pic = 'images/characters/forester.png';
 
  enter = translate("forest_locale", 'forester_dlg_enter');
 
  phr = {
 
    {translate("forest_locale", 'common_dlg_greet'), translate("forest_locale", 'forester_dlg_greet_response'),
 
      {translate("forest_locale", 'common_dlg_places'), translate("forest_locale", 'forester_dlg_places_response')};
 
    },
 
    {cond=function(s) return where('rope') and where('rope')^'foresters_hut' and not _('forester').bought end, translate("forest_locale", 'forester_dlg_rope'), function(s)
 
      p(translate_now("forest_locale", 'forester_dlg_rope_response'));
 
      raspberry_pie_status = 1;
 
    end},
 
    {cond=function(s) return have 'raspberry_pie' end, translate("forest_locale", 'forester_dlg_pie'), function(s)
 
      remove('raspberry_pie', pl);
 
      p(translate_now("forest_locale", 'forester_dlg_pie_response'));
 
      raspberry_pie_status = 2;
 
      _('forester').bought = 1;
 
    end},
 
    {true, translate("forest_locale", 'common_dlg_bye'), function(s)
 
      p(translate_now("forest_locale", 'forester_dlg_farewell_response'));
 
      walkout();
 
    end}
 
  }
 
}
 

	
 
room {
 
	nam = 'village_center';
 
	nofollow = true;
 
	pic = 'images/village_center.png';
 
	theme = 'main';
 
	disp = translate("forest_locale", 'village_center');
 
	decor = function(s)
 
  nam = 'village_center';
 
  nofollow = true;
 
  pic = 'images/village_center.png';
 
  theme = 'main';
 
  disp = translate("forest_locale", 'village_center');
 
  decor = function(s)
 
    p(translate_now("forest_locale", 'village_center_decor'));
 
    p(translate_now("forest_locale", 'village_all_decor'));
 
  end;
 
	way = {
 
		 path {translate("forest_locale", 'transition_south_to_hut'), 'village_south'};
 
		 path {'#down', translate("forest_locale", 'transition_inside_well'), 'inside_well'}:disable();
 
		 path {translate("forest_locale", 'transition_inside_town_hall'), 'townhall'};
 
		 path {translate("forest_locale", 'transition_inside_tavern'), 'tavern'};
 
		 path {translate("forest_locale", 'transition_north_to_library'), 'village_north'};
 
	};
 
  way = {
 
     path {translate("forest_locale", 'transition_south_to_hut'), 'village_south'};
 
     path {'#down', translate("forest_locale", 'transition_inside_well'), 'inside_well'}:disable();
 
     path {translate("forest_locale", 'transition_inside_town_hall'), 'townhall'};
 
     path {translate("forest_locale", 'transition_inside_tavern'), 'tavern'};
 
     path {translate("forest_locale", 'transition_north_to_library'), 'village_north'};
 
  };
 
}: with {
 
	obj {
 
		nam = '#townhall';
 
		act = translate("forest_locale", 'village_center_townhall');
 
	};
 
	obj {
 
		nam = '#music';
 
		act = translate("forest_locale", 'village_center_music');
 
	};
 
	obj {
 
		nam = '#tavern';
 
		act = translate("forest_locale", 'village_center_tavern');
 
	};
 
	obj {
 
		nam = '#library';
 
		act = translate("forest_locale", 'village_center_library');
 
  obj {
 
    nam = '#townhall';
 
    act = translate("forest_locale", 'village_center_townhall');
 
  };
 
  obj {
 
    nam = '#music';
 
    act = translate("forest_locale", 'village_center_music');
 
  };
 
  obj {
 
    nam = '#tavern';
 
    act = translate("forest_locale", 'village_center_tavern');
 
  };
 
  obj {
 
    nam = '#library';
 
    act = translate("forest_locale", 'village_center_library');
 

	
 
	};
 
	obj {
 
		known = false;
 
		nam = 'village_well';
 
		dsc = function(s)
 
  };
 
  obj {
 
    known = false;
 
    nam = 'village_well';
 
    dsc = function(s)
 
      p(translate_now("forest_locale", 'village_well_dsc'));
 
			if _('inside_well').state then
 
				p(translate_now("forest_locale", 'village_well_dsc_rope'));
 
			end;
 
		end;
 
		act = function(s)
 
			if s.known then
 
				_'#down':enable();
 
				p(translate_now("forest_locale", 'village_well_act_key'));
 
			else
 
				p(translate_now("forest_locale", 'village_well_act'));
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'rope' then
 
      if _('inside_well').state then
 
        p(translate_now("forest_locale", 'village_well_dsc_rope'));
 
      end;
 
    end;
 
    act = function(s)
 
      if s.known then
 
        _'#down':enable();
 
        p(translate_now("forest_locale", 'village_well_act_key'));
 
      else
 
        p(translate_now("forest_locale", 'village_well_act'));
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'rope' then
 
        _'#down':enable();
 
				_('inside_well').state = true;
 
				remove('rope', pl);
 
				p(translate_now("forest_locale", 'village_well_used'));
 
			else
 
				return false;
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = 'maid';
 
		dsc = function(s)
 
        _('inside_well').state = true;
 
        remove('rope', pl);
 
        p(translate_now("forest_locale", 'village_well_used'));
 
      else
 
        return false;
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = 'maid';
 
    dsc = function(s)
 
      p(translate_now("forest_locale", 'village_maid_dsc'));
 
			if _('maid_dlg').flower then
 
				p(translate_now("forest_locale", 'village_maid_flower'));
 
			end;
 
		end;
 
		act = function(s)
 
			if _('maid_dlg').flower and (raspberry_pie_status == 0 or raspberry_pie_status == 2) then
 
				return translate_now("forest_locale", 'maid_dlg_enter') .. ' ' .. translate_now("forest_locale", 'village_maid_act_no_dlg');
 
			else
 
				walkin('maid_dlg');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'flower' then
 
				return translate_now("forest_locale", 'village_maid_used_flower');
 
			else
 
				return translate_now("forest_locale", 'village_maid_used_other');
 
			end;
 
		end;
 
	};
 
	'sun_transformed';
 
	'clouds';
 
      if _('maid_dlg').flower then
 
        p(translate_now("forest_locale", 'village_maid_flower'));
 
      end;
 
    end;
 
    act = function(s)
 
      if _('maid_dlg').flower and (raspberry_pie_status == 0 or raspberry_pie_status == 2) then
 
        return translate_now("forest_locale", 'maid_dlg_enter') .. ' ' .. translate_now("forest_locale", 'village_maid_act_no_dlg');
 
      else
 
        walkin('maid_dlg');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'flower' then
 
        return translate_now("forest_locale", 'village_maid_used_flower');
 
      else
 
        return translate_now("forest_locale", 'village_maid_used_other');
 
      end;
 
    end;
 
  };
 
  'sun_transformed';
 
  'clouds';
 
}
 

	
 
dlg {
 
	nam = 'maid_dlg';
 
	disp = translate("forest_locale", 'maid_dlg');
 
	theme = 'main';
 
	pic = function(s)
 
		if s.flower then
 
			return 'images/characters/maid_glad.png';
 
		else
 
			return 'images/characters/maid_sad.png';
 
		end;
 
	end;
 
	flower = false;
 
	pie = false;
 
	work_asked = false;
 
	pie_asked = false;
 
	enter = function(s)
 
  nam = 'maid_dlg';
 
  disp = translate("forest_locale", 'maid_dlg');
 
  theme = 'main';
 
  pic = function(s)
 
    if s.flower then
 
      return 'images/characters/maid_glad.png';
 
    else
 
      return 'images/characters/maid_sad.png';
 
    end;
 
  end;
 
  flower = false;
 
  pie = false;
 
  work_asked = false;
 
  pie_asked = false;
 
  enter = function(s)
 
    p(translate_now("forest_locale", 'maid_dlg_enter'));
 
		if _('maid_dlg').flower then
 
			p(translate_now("forest_locale", 'maid_dlg_enter_with_flower'));
 
    if _('maid_dlg').flower then
 
      p(translate_now("forest_locale", 'maid_dlg_enter_with_flower'));
 
      p(translate_now("forest_locale", 'village_maid_flower'));
 
		else
 
			p(translate_now("forest_locale", 'maid_dlg_enter_no_flower'));
 
		end;
 
	end;
 
	phr = {
 
		{cond=function(s) return not _('maid_dlg').flower end, translate("forest_locale", 'common_dlg_greet'), translate("forest_locale", 'maid_dlg_greet_response'),
 
			{translate("forest_locale", 'common_dlg_places'), translate("forest_locale", 'maid_dlg_places_response'),
 
				{translate("forest_locale", 'maid_dlg_places_like'), translate("forest_locale", 'maid_dlg_places_like_response'), only=true,
 
					{
 
						cond=function(s) return have 'flower' end,
 
						translate("forest_locale", 'maid_dlg_flower'),
 
						function(s)
 
							_('maid_dlg').flower = 1;
 
							remove('flower', pl);
 
							p(translate_now("forest_locale", 'maid_dlg_flower_response'));
 
						end
 
					};
 
					{
 
						translate("common_locale", 'dlg_keep_silent'),
 
						translate("forest_locale", 'maid_dlg_silent_response')
 
					}
 
				};
 
			};
 
		};
 
		{cond=function(s) return not _('maid_dlg').work_asked end, translate("forest_locale", 'maid_dlg_tavern'), function(s)
 
			_('maid_dlg').work_asked = true;
 
			return translate_now("forest_locale", 'maid_dlg_tavern_response');
 
		end};
 
		{
 
			cond=function(s) return _('maid_dlg').pie_asked and have 'flower' end,
 
			translate("forest_locale", 'maid_dlg_flower'),
 
			function(s)
 
				_('maid_dlg').flower = 1;
 
				remove('flower', pl);
 
				raspberry_pie_status = 2;
 
				take 'raspberry_pie'
 
				p(translate_now("forest_locale", 'maid_dlg_pie_response'));
 
			end
 
		};
 
		{
 
			cond=function(s) return _('maid_dlg').work_asked and not _('maid_dlg').pie_asked and _('maid_dlg').flower and raspberry_pie_status == 1; end;
 
			translate("forest_locale", 'maid_dlg_pie'),
 
			function(s)
 
				raspberry_pie_status = 2;
 
				take 'raspberry_pie'
 
				p(translate_now("forest_locale", 'maid_dlg_pie_response'));
 
			end;
 
		};
 
		{
 
			cond=function(s) return _('maid_dlg').work_asked and not _('maid_dlg').pie_asked and not _('maid_dlg').flower and raspberry_pie_status == 1; end;
 
			translate("forest_locale", 'maid_dlg_pie'),
 
			translate("forest_locale", 'maid_dlg_pie_fail_response'), only=true,
 
			{
 
				translate("forest_locale", 'maid_dlg_no_money'), function(s)
 
					_('maid_dlg').pie_asked = 1;
 
					p(translate_now("forest_locale", 'maid_dlg_no_money_response'));
 
				end, only=true,
 
				{
 
					cond=function(s) return have 'flower' end,
 
					translate("forest_locale", 'maid_dlg_flower'),
 
					function(s)
 
						_('maid_dlg').flower = 1;
 
						remove('flower', pl);
 
						raspberry_pie_status = 2;
 
						take('raspberry_pie');
 
						p(translate_now("forest_locale", 'maid_dlg_pie_response'));
 
					end
 
				};
 
    else
 
      p(translate_now("forest_locale", 'maid_dlg_enter_no_flower'));
 
    end;
 
  end;
 
  phr = {
 
    {cond=function(s) return not _('maid_dlg').flower end, translate("forest_locale", 'common_dlg_greet'), translate("forest_locale", 'maid_dlg_greet_response'),
 
      {translate("forest_locale", 'common_dlg_places'), translate("forest_locale", 'maid_dlg_places_response'),
 
        {translate("forest_locale", 'maid_dlg_places_like'), translate("forest_locale", 'maid_dlg_places_like_response'), only=true,
 
          {
 
            cond=function(s) return have 'flower' end,
 
            translate("forest_locale", 'maid_dlg_flower'),
 
            function(s)
 
              _('maid_dlg').flower = 1;
 
              remove('flower', pl);
 
              p(translate_now("forest_locale", 'maid_dlg_flower_response'));
 
            end
 
          };
 
          {
 
            translate("common_locale", 'dlg_keep_silent'),
 
            translate("forest_locale", 'maid_dlg_silent_response')
 
          }
 
        };
 
      };
 
    };
 
    {cond=function(s) return not _('maid_dlg').work_asked end, translate("forest_locale", 'maid_dlg_tavern'), function(s)
 
      _('maid_dlg').work_asked = true;
 
      return translate_now("forest_locale", 'maid_dlg_tavern_response');
 
    end};
 
    {
 
      cond=function(s) return _('maid_dlg').pie_asked and have 'flower' end,
 
      translate("forest_locale", 'maid_dlg_flower'),
 
      function(s)
 
        _('maid_dlg').flower = 1;
 
        remove('flower', pl);
 
        raspberry_pie_status = 2;
 
        take 'raspberry_pie'
 
        p(translate_now("forest_locale", 'maid_dlg_pie_response'));
 
      end
 
    };
 
    {
 
      cond=function(s) return _('maid_dlg').work_asked and not _('maid_dlg').pie_asked and _('maid_dlg').flower and raspberry_pie_status == 1; end;
 
      translate("forest_locale", 'maid_dlg_pie'),
 
      function(s)
 
        raspberry_pie_status = 2;
 
        take 'raspberry_pie'
 
        p(translate_now("forest_locale", 'maid_dlg_pie_response'));
 
      end;
 
    };
 
    {
 
      cond=function(s) return _('maid_dlg').work_asked and not _('maid_dlg').pie_asked and not _('maid_dlg').flower and raspberry_pie_status == 1; end;
 
      translate("forest_locale", 'maid_dlg_pie'),
 
      translate("forest_locale", 'maid_dlg_pie_fail_response'), only=true,
 
      {
 
        translate("forest_locale", 'maid_dlg_no_money'), function(s)
 
          _('maid_dlg').pie_asked = 1;
 
          p(translate_now("forest_locale", 'maid_dlg_no_money_response'));
 
        end, only=true,
 
        {
 
          cond=function(s) return have 'flower' end,
 
          translate("forest_locale", 'maid_dlg_flower'),
 
          function(s)
 
            _('maid_dlg').flower = 1;
 
            remove('flower', pl);
 
            raspberry_pie_status = 2;
 
            take('raspberry_pie');
 
            p(translate_now("forest_locale", 'maid_dlg_pie_response'));
 
          end
 
        };
 
        {translate("forest_locale", 'maid_dlg_flower_agree'), translate("forest_locale", 'maid_dlg_flower_agree_response')};
 
				{translate("forest_locale", 'maid_dlg_flower_think'), translate("forest_locale", 'maid_dlg_flower_think_response')};
 
			},
 
			{
 
				translate("forest_locale", 'maid_dlg_pie_ask'), translate("forest_locale", 'maid_dlg_pie_ask_response')
 
			}
 
		};
 
		{
 
			translate("forest_locale", 'maid_dlg_bye'), function(s)
 
			p(translate_now("forest_locale", 'maid_dlg_bye_response'));
 
			walkout();
 
		end
 
		}
 
	}
 
        {translate("forest_locale", 'maid_dlg_flower_think'), translate("forest_locale", 'maid_dlg_flower_think_response')};
 
      },
 
      {
 
        translate("forest_locale", 'maid_dlg_pie_ask'), translate("forest_locale", 'maid_dlg_pie_ask_response')
 
      }
 
    };
 
    {
 
      translate("forest_locale", 'maid_dlg_bye'), function(s)
 
      p(translate_now("forest_locale", 'maid_dlg_bye_response'));
 
      walkout();
 
    end
 
    }
 
  }
 
}
 

	
 
room {
 
	nam = 'tavern';
 
	pic = function(s)
 
		if raspberry_pie_status == 2 then
 
			return 'images/tavern.png';
 
		else
 
			return 'images/tavern.png;images/tavern_pie.png@181,124';
 
		end;
 
	end;
 
	disp = translate("forest_locale", 'tavern');
 
	theme = 'main';
 
	nofollow = true;
 
	decor = translate("forest_locale", 'tavern_decor');
 
	way = {
 
		path {'#outside', translate("forest_locale", 'transition_out'), 'village_center'};
 
	};
 
  nam = 'tavern';
 
  pic = function(s)
 
    if raspberry_pie_status == 2 then
 
      return 'images/tavern.png';
 
    else
 
      return 'images/tavern.png;images/tavern_pie.png@181,124';
 
    end;
 
  end;
 
  disp = translate("forest_locale", 'tavern');
 
  theme = 'main';
 
  nofollow = true;
 
  decor = translate("forest_locale", 'tavern_decor');
 
  way = {
 
    path {'#outside', translate("forest_locale", 'transition_out'), 'village_center'};
 
  };
 
}: with {
 
	obj {
 
		nam = '#windows';
 
		act = translate("forest_locale", 'tavern_windows');
 
	};
 
	obj {
 
		nam = '#tables';
 
		act = translate("forest_locale", 'tavern_tables');
 
	};
 
	obj {
 
		nam = '#walls';
 
		act = translate("forest_locale", 'tavern_walls');
 
	};
 
	obj {
 
		nam = '#lights';
 
		act = translate("forest_locale", 'tavern_lights');
 
	};
 
	obj {
 
		nam = '#fireplace';
 
		act = translate("forest_locale", 'tavern_fireplace');
 
	};
 
	obj {
 
		nam = '#cauldron';
 
		act = translate("forest_locale", 'tavern_cauldron');
 
	};
 
	obj {
 
		nam = 'tavernkeeper';
 
		dsc = translate("forest_locale", 'tavern_keeper');
 
		act = function(s)
 
			walkin 'tavernkeeper_dlg'
 
		end;
 
	}
 
  obj {
 
    nam = '#windows';
 
    act = translate("forest_locale", 'tavern_windows');
 
  };
 
  obj {
 
    nam = '#tables';
 
    act = translate("forest_locale", 'tavern_tables');
 
  };
 
  obj {
 
    nam = '#walls';
 
    act = translate("forest_locale", 'tavern_walls');
 
  };
 
  obj {
 
    nam = '#lights';
 
    act = translate("forest_locale", 'tavern_lights');
 
  };
 
  obj {
 
    nam = '#fireplace';
 
    act = translate("forest_locale", 'tavern_fireplace');
 
  };
 
  obj {
 
    nam = '#cauldron';
 
    act = translate("forest_locale", 'tavern_cauldron');
 
  };
 
  obj {
 
    nam = 'tavernkeeper';
 
    dsc = translate("forest_locale", 'tavern_keeper');
 
    act = function(s)
 
      walkin 'tavernkeeper_dlg'
 
    end;
 
  }
 
}
 

	
 
dlg {
 
	nam = 'tavernkeeper_dlg';
 
	noinv = true;
 
	title = translate("forest_locale", 'tavernkeeper_dlg');
 
	pic = 'images/characters/tavernkeeper.png';
 
	theme = 'main';
 
	enter = translate("forest_locale", 'tavernkeeper_dlg_enter');
 
	phr = {
 
		{translate("forest_locale", 'common_dlg_greet'), translate("forest_locale", 'tavernkeeper_dlg_greet_response'),
 
			{translate("forest_locale", 'tavernkeeper_dlg_money'), translate("forest_locale", 'tavernkeeper_dlg_money_response')};
 
			{translate("forest_locale", 'common_dlg_places'), translate("forest_locale", 'tavernkeeper_dlg_places_response')};
 
		};
 
		{cond=function(s) return raspberry_pie_status == 1; end, translate("forest_locale", 'tavernkeeper_dlg_pie'), translate("forest_locale", 'tavernkeeper_dlg_pie_response'),
 
			{translate("forest_locale", 'tavernkeeper_dlg_pie_2'), translate("forest_locale", 'tavernkeeper_dlg_pie_response_2')}
 
		};
 
		{true, translate("forest_locale", 'common_dlg_bye'), function(s)
 
			p(translate_now("forest_locale", 'tavernkeeper_dlg_bye_response'));
 
			walkout();
 
		end};
 
	};
 
  nam = 'tavernkeeper_dlg';
 
  noinv = true;
 
  title = translate("forest_locale", 'tavernkeeper_dlg');
 
  pic = 'images/characters/tavernkeeper.png';
 
  theme = 'main';
 
  enter = translate("forest_locale", 'tavernkeeper_dlg_enter');
 
  phr = {
 
    {translate("forest_locale", 'common_dlg_greet'), translate("forest_locale", 'tavernkeeper_dlg_greet_response'),
 
      {translate("forest_locale", 'tavernkeeper_dlg_money'), translate("forest_locale", 'tavernkeeper_dlg_money_response')};
 
      {translate("forest_locale", 'common_dlg_places'), translate("forest_locale", 'tavernkeeper_dlg_places_response')};
 
    };
 
    {cond=function(s) return raspberry_pie_status == 1; end, translate("forest_locale", 'tavernkeeper_dlg_pie'), translate("forest_locale", 'tavernkeeper_dlg_pie_response'),
 
      {translate("forest_locale", 'tavernkeeper_dlg_pie_2'), translate("forest_locale", 'tavernkeeper_dlg_pie_response_2')}
 
    };
 
    {true, translate("forest_locale", 'common_dlg_bye'), function(s)
 
      p(translate_now("forest_locale", 'tavernkeeper_dlg_bye_response'));
 
      walkout();
 
    end};
 
  };
 
}
 

	
 
room {
 
	nam = 'townhall';
 
	pic='images/townhall.png';
 
	theme = 'main';
 
	title = translate("forest_locale", 'townhall');
 
	nofollow = true;
 
	decor = translate("forest_locale", 'townhall_decor');
 
	onexit = function(s)
 
		if have 'oil' then
 
			p(translate_now("forest_locale", 'townhall_onexit'));
 
			return false;
 
		end;
 
	end;
 
	way = {
 
		path {'#out', translate("forest_locale", 'transition_out'), 'village_center'};
 
	};
 
  nam = 'townhall';
 
  pic='images/townhall.png';
 
  theme = 'main';
 
  title = translate("forest_locale", 'townhall');
 
  nofollow = true;
 
  decor = translate("forest_locale", 'townhall_decor');
 
  onexit = function(s)
 
    if have 'oil' then
 
      p(translate_now("forest_locale", 'townhall_onexit'));
 
      return false;
 
    end;
 
  end;
 
  way = {
 
    path {'#out', translate("forest_locale", 'transition_out'), 'village_center'};
 
  };
 
}: with {
 
	obj {
 
		nam = '#ceiling';
 
		act = translate("forest_locale", 'townhall_ceiling');
 
	};
 
	obj {
 
		nam = '#chandelier';
 
		act = translate("forest_locale", 'townhall_chandelier');
 
	};
 
	obj {
 
		nam = '#curtains';
 
		act = translate("forest_locale", 'townhall_curtains');
 
	};
 
	obj {
 
		nam = '#table';
 
		act = translate("forest_locale", 'townhall_table');
 
	};
 
	obj {
 
		nam = '#chairs';
 
		act = translate("forest_locale", 'townhall_chairs');
 
	};
 
	obj {
 
		nam = '#head';
 
		act = translate("forest_locale", 'townhall_head');
 
	};
 
	obj {
 
		flask = true;
 
		nam = 'cabinet';
 
		dsc = translate("forest_locale", 'townhall_cabinet');
 
		act = function(s)
 
			if s.flask then
 
				return translate_now("forest_locale", 'townhall_cabinet_act_oil');
 
			else
 
				return translate_now("forest_locale", 'townhall_cabinet_act');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o == _('oil') then
 
				s.flask = true;
 
				remove(o, pl);
 
				put(o, 'townhall');
 
				return translate_now("forest_locale", 'townhall_cabinet_used_oil');
 
			end;
 
		end;
 
	}:with {
 
		obj {
 
			nam = 'records';
 
			act = translate("forest_locale", 'townhall_cabinet_records');
 
		};
 
		obj {
 
			nam = 'parts';
 
			act = translate("forest_locale", 'townhall_cabinet_parts');
 
		};
 
		obj {
 
			nam = 'oil';
 
			disp = translate("forest_locale", 'townhall_cabinet_oil');
 
			tak = function(s)
 
				_('cabinet').flask = false;
 
				return translate_now("forest_locale", 'townhall_cabinet_oil_tak');
 
			end;
 
			inv = translate("forest_locale", 'townhall_cabinet_oil_inv');
 
		};
 
		obj {
 
			nam = 'record_player';
 
			act = translate("forest_locale", 'townhall_cabinet_record_player');
 
		};
 
	};
 
  obj {
 
    nam = '#ceiling';
 
    act = translate("forest_locale", 'townhall_ceiling');
 
  };
 
  obj {
 
    nam = '#chandelier';
 
    act = translate("forest_locale", 'townhall_chandelier');
 
  };
 
  obj {
 
    nam = '#curtains';
 
    act = translate("forest_locale", 'townhall_curtains');
 
  };
 
  obj {
 
    nam = '#table';
 
    act = translate("forest_locale", 'townhall_table');
 
  };
 
  obj {
 
    nam = '#chairs';
 
    act = translate("forest_locale", 'townhall_chairs');
 
  };
 
  obj {
 
    nam = '#head';
 
    act = translate("forest_locale", 'townhall_head');
 
  };
 
  obj {
 
    flask = true;
 
    nam = 'cabinet';
 
    dsc = translate("forest_locale", 'townhall_cabinet');
 
    act = function(s)
 
      if s.flask then
 
        return translate_now("forest_locale", 'townhall_cabinet_act_oil');
 
      else
 
        return translate_now("forest_locale", 'townhall_cabinet_act');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o == _('oil') then
 
        s.flask = true;
 
        remove(o, pl);
 
        put(o, 'townhall');
 
        return translate_now("forest_locale", 'townhall_cabinet_used_oil');
 
      end;
 
    end;
 
  }:with {
 
    obj {
 
      nam = 'records';
 
      act = translate("forest_locale", 'townhall_cabinet_records');
 
    };
 
    obj {
 
      nam = 'parts';
 
      act = translate("forest_locale", 'townhall_cabinet_parts');
 
    };
 
    obj {
 
      nam = 'oil';
 
      disp = translate("forest_locale", 'townhall_cabinet_oil');
 
      tak = function(s)
 
        _('cabinet').flask = false;
 
        return translate_now("forest_locale", 'townhall_cabinet_oil_tak');
 
      end;
 
      inv = translate("forest_locale", 'townhall_cabinet_oil_inv');
 
    };
 
    obj {
 
      nam = 'record_player';
 
      act = translate("forest_locale", 'townhall_cabinet_record_player');
 
    };
 
  };
 
}
 

	
 
room {
 
	state = false;
 
	nofollow = true;
 
	nam = 'inside_well';
 
	theme = 'tower';
 
	pic = 'images/oldwell.png';
 
	disp = translate("forest_locale", 'inside_well');
 
	onenter = function(s)
 
		if not s.state then
 
			p(translate_now("forest_locale", 'inside_well_enter'));
 
			return false;
 
		end;
 
	end;
 
	decor = translate("forest_locale", 'inside_well_decor');
 
	way = {
 
		path {translate("forest_locale", 'transition_up'), 'village_center'};
 
	}
 
  state = false;
 
  nofollow = true;
 
  nam = 'inside_well';
 
  theme = 'tower';
 
  pic = 'images/oldwell.png';
 
  disp = translate("forest_locale", 'inside_well');
 
  onenter = function(s)
 
    if not s.state then
 
      p(translate_now("forest_locale", 'inside_well_enter'));
 
      return false;
 
    end;
 
  end;
 
  decor = translate("forest_locale", 'inside_well_decor');
 
  way = {
 
    path {translate("forest_locale", 'transition_up'), 'village_center'};
 
  }
 
}:with {
 
	obj {
 
		nam = 'loose_rock';
 
		dsc = translate("forest_locale", 'inside_well_loose_rock');
 
		act = function(s)
 
			p(translate_now("forest_locale", 'inside_well_loose_rock_act'));
 
			take('hidden_key');
 
			s:disable();
 
		end;
 
	}
 
  obj {
 
    nam = 'loose_rock';
 
    dsc = translate("forest_locale", 'inside_well_loose_rock');
 
    act = function(s)
 
      p(translate_now("forest_locale", 'inside_well_loose_rock_act'));
 
      take('hidden_key');
 
      s:disable();
 
    end;
 
  }
 
}
 

	
 
obj {
 
	nam = 'hidden_key';
 
	disp = translate("forest_locale", 'hidden_key_disp');
 
	disp2 = translate("forest_locale", 'hidden_key_disp2');
 
	disp3 = translate("forest_locale", 'hidden_key_disp3');
 
	inv = translate("forest_locale", 'hidden_key_inv');
 
  nam = 'hidden_key';
 
  disp = translate("forest_locale", 'hidden_key_disp');
 
  disp2 = translate("forest_locale", 'hidden_key_disp2');
 
  disp3 = translate("forest_locale", 'hidden_key_disp3');
 
  inv = translate("forest_locale", 'hidden_key_inv');
 
}
 

	
 
room {
 
	nam = 'village_north';
 
	pic = 'images/village_north.png';
 
	disp = translate("forest_locale", 'village_north');
 
	theme = 'main';
 
	nofollow = true;
 
	decor = function(s)
 
  nam = 'village_north';
 
  pic = 'images/village_north.png';
 
  disp = translate("forest_locale", 'village_north');
 
  theme = 'main';
 
  nofollow = true;
 
  decor = function(s)
 
      p(translate_now("forest_locale", 'village_north_decor'));
 
      p(translate_now("forest_locale", 'village_all_decor'));
 
  end;
 
	way = {
 
		path {'#south', translate("forest_locale", 'transition_south_to_town_hall'), 'village_center'};
 
		path {'#in', translate("forest_locale", 'transition_inside_library'), 'library'};
 
	};
 
  way = {
 
    path {'#south', translate("forest_locale", 'transition_south_to_town_hall'), 'village_center'};
 
    path {'#in', translate("forest_locale", 'transition_inside_library'), 'library'};
 
  };
 
}: with {
 
	obj {
 
		nam = '#village';
 
		act = translate("forest_locale", 'village_north_village');
 
	};
 
	obj {
 
		nam = '#road';
 
		act = translate("forest_locale", 'village_north_road');
 
	};
 
	obj {
 
		nam = '#forest';
 
		act = translate("forest_locale", 'village_north_forest');
 
	};
 
	obj {
 
		nam = '#library';
 
		act = translate("forest_locale", 'village_north_library');
 
	};
 
	obj {
 
		nam = '#mountains';
 
		act = translate("forest_locale", 'village_north_mountains');
 
	};
 
	'sun_transformed';
 
	'clouds';
 
  obj {
 
    nam = '#village';
 
    act = translate("forest_locale", 'village_north_village');
 
  };
 
  obj {
 
    nam = '#road';
 
    act = translate("forest_locale", 'village_north_road');
 
  };
 
  obj {
 
    nam = '#forest';
 
    act = translate("forest_locale", 'village_north_forest');
 
  };
 
  obj {
 
    nam = '#library';
 
    act = translate("forest_locale", 'village_north_library');
 
  };
 
  obj {
 
    nam = '#mountains';
 
    act = translate("forest_locale", 'village_north_mountains');
 
  };
 
  'sun_transformed';
 
  'clouds';
 
}
 

	
 
room {
 
	nam = 'library';
 
	pic = 'images/library.png';
 
	disp = translate("forest_locale", 'library');
 
	theme = 'main';
 
	nofollow = true;
 
	decor = translate("forest_locale", 'library_decor');
 
	way = {
 
		path {'#out', translate("forest_locale", 'transition_out'), 'village_north'};
 
		path {'library_hidden_path', translate("forest_locale", 'transition_to_hidden_room'), 'library_hidden_room'}:disable();
 
	};
 
  nam = 'library';
 
  pic = 'images/library.png';
 
  disp = translate("forest_locale", 'library');
 
  theme = 'main';
 
  nofollow = true;
 
  decor = translate("forest_locale", 'library_decor');
 
  way = {
 
    path {'#out', translate("forest_locale", 'transition_out'), 'village_north'};
 
    path {'library_hidden_path', translate("forest_locale", 'transition_to_hidden_room'), 'library_hidden_room'}:disable();
 
  };
 
}:with {
 
	obj {
 
		nam = 'librarian';
 
		dsc = translate("forest_locale", 'library_librarian');
 
		act = function(s)
 
			walkin 'librarian_dlg'
 
		end;
 
		used = function(s, o)
 
			if o^'box' then
 
				return translate_now("forest_locale", 'library_librarian_used_box');
 
			else
 
				return translate_now("forest_locale", 'library_librarian_used_other');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#tables';
 
		act = translate("forest_locale", 'library_tables');
 
	};
 
	obj {
 
		nam = '#chairs';
 
		act = translate("forest_locale", 'library_chairs');
 
	};
 
	obj {
 
		nam = '#lamps';
 
		act = translate("forest_locale", 'library_lamps');
 
	};
 
	obj {
 
		nam = '#windows';
 
		act = translate("forest_locale", 'library_windows');
 
	};
 
	obj {
 
		state = 0;
 
		nam = 'library_shelves';
 
		act = function(s)
 
			if s.state == 0 then
 
				p(translate_now("forest_locale", 'library_shelves_act_first'));
 
			else
 
				p(translate_now("forest_locale", 'library_shelves_act'));
 
			end;
 
		end;
 
	},
 
	obj {
 
		nam = 'library_the_shelf';
 
		act = function(s)
 
			if	_'library_shelves'.state == 0 then
 
				p(translate_now("forest_locale", 'library_the_shelf_act', {word=library_word}));
 
			end;
 
			_'library_shelves'.state = 1;
 
			walkin('library_shelf_puzzle');
 
		end;
 
	};
 
	obj {
 
		nam = '#library_notice';
 
		act = function(s)
 
			walkin('library_notice_inside')
 
		end;
 
	}
 
  obj {
 
    nam = 'librarian';
 
    dsc = translate("forest_locale", 'library_librarian');
 
    act = function(s)
 
      walkin 'librarian_dlg'
 
    end;
 
    used = function(s, o)
 
      if o^'box' then
 
        return translate_now("forest_locale", 'library_librarian_used_box');
 
      else
 
        return translate_now("forest_locale", 'library_librarian_used_other');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#tables';
 
    act = translate("forest_locale", 'library_tables');
 
  };
 
  obj {
 
    nam = '#chairs';
 
    act = translate("forest_locale", 'library_chairs');
 
  };
 
  obj {
 
    nam = '#lamps';
 
    act = translate("forest_locale", 'library_lamps');
 
  };
 
  obj {
 
    nam = '#windows';
 
    act = translate("forest_locale", 'library_windows');
 
  };
 
  obj {
 
    state = 0;
 
    nam = 'library_shelves';
 
    act = function(s)
 
      if s.state == 0 then
 
        p(translate_now("forest_locale", 'library_shelves_act_first'));
 
      else
 
        p(translate_now("forest_locale", 'library_shelves_act'));
 
      end;
 
    end;
 
  },
 
  obj {
 
    nam = 'library_the_shelf';
 
    act = function(s)
 
      if  _'library_shelves'.state == 0 then
 
        p(translate_now("forest_locale", 'library_the_shelf_act', {word=library_word}));
 
      end;
 
      _'library_shelves'.state = 1;
 
      walkin('library_shelf_puzzle');
 
    end;
 
  };
 
  obj {
 
    nam = '#library_notice';
 
    act = function(s)
 
      walkin('library_notice_inside')
 
    end;
 
  }
 
}
 

	
 
room {
 
	nam = 'library_notice_inside';
 
	pic = 'images/library.png';
 
	disp = translate("forest_locale", 'library');
 
	theme = 'main';
 
  nam = 'library_notice_inside';
 
  pic = 'images/library.png';
 
  disp = translate("forest_locale", 'library');
 
  theme = 'main';
 
  nofollow = true;
 
	decor = translate("forest_locale", 'library_notice_inside_decor');
 
	way = {
 
		path {translate("common_locale", 'back'), 'library'};
 
	};
 
  decor = translate("forest_locale", 'library_notice_inside_decor');
 
  way = {
 
    path {translate("common_locale", 'back'), 'library'};
 
  };
 
}
 

	
 
dlg {
 
	ring = 0;
 
	nam = 'librarian_dlg';
 
	pic = 'images/characters/librarian.png';
 
	theme = 'main';
 
	noinv = true;
 
	title = translate("forest_locale", 'librarian_dlg');
 
	enter = function(s)
 
		seen_ring_librarian = true;
 
		return translate_now("forest_locale", 'librarian_dlg_enter');
 
	end;
 
	phr = {
 
		{translate("forest_locale", 'common_dlg_greet'), translate("forest_locale", 'librarian_dlg_greet_response'),
 
			{translate("forest_locale", 'common_dlg_places'), translate("forest_locale", 'librarian_dlg_places_response'),
 
				{translate("forest_locale", 'librarian_dlg_library'), translate("forest_locale", 'librarian_dlg_library_response')};
 
  ring = 0;
 
  nam = 'librarian_dlg';
 
  pic = 'images/characters/librarian.png';
 
  theme = 'main';
 
  noinv = true;
 
  title = translate("forest_locale", 'librarian_dlg');
 
  enter = function(s)
 
    seen_ring_librarian = true;
 
    return translate_now("forest_locale", 'librarian_dlg_enter');
 
  end;
 
  phr = {
 
    {translate("forest_locale", 'common_dlg_greet'), translate("forest_locale", 'librarian_dlg_greet_response'),
 
      {translate("forest_locale", 'common_dlg_places'), translate("forest_locale", 'librarian_dlg_places_response'),
 
        {translate("forest_locale", 'librarian_dlg_library'), translate("forest_locale", 'librarian_dlg_library_response')};
 
        {translate("forest_locale", 'librarian_dlg_library_old'), translate("forest_locale", 'librarian_dlg_library_old_response')};
 
			},
 
			{translate("forest_locale", 'librarian_dlg_ring'), translate("forest_locale", 'librarian_dlg_ring_response')}
 
		},
 
		{cond=function(s) return seen_ring_box; end, translate("forest_locale", 'librarian_dlg_ring_look'), function(s)
 
			_('village_well').known = 1;
 
			return translate_now("forest_locale", 'librarian_dlg_ring_look_response');
 
		end};
 
		{true, translate("forest_locale", 'common_dlg_bye'), function(s)
 
			p(translate_now("forest_locale", 'librarian_dlg_bye_response'));
 
			walkout();
 
		end}
 
	}
 
      },
 
      {translate("forest_locale", 'librarian_dlg_ring'), translate("forest_locale", 'librarian_dlg_ring_response')}
 
    },
 
    {cond=function(s) return seen_ring_box; end, translate("forest_locale", 'librarian_dlg_ring_look'), function(s)
 
      _('village_well').known = 1;
 
      return translate_now("forest_locale", 'librarian_dlg_ring_look_response');
 
    end};
 
    {true, translate("forest_locale", 'common_dlg_bye'), function(s)
 
      p(translate_now("forest_locale", 'librarian_dlg_bye_response'));
 
      walkout();
 
    end}
 
  }
 
}
 

	
 
function book(number) 
 
@@ -1124,16 +1124,16 @@ function book(number)
 
        _'shelf'.obj:add(o, idx);
 
        p(translate_now("forest_locale", 'library_shelf_puzzle_used_book'));
 
        if #t == 9 then
 
					for i = 1, 9 do
 
						if library_book_map[t[i].book] ~= i then
 
							return;
 
						end;
 
					end;
 
					p(translate_now("forest_locale", 'library_shelf_puzzle_used_book_success'));
 
					disable 'library_shelves'
 
					enable 'library_hidden_path'
 
					walkout()
 
				end;
 
          for i = 1, 9 do
 
            if library_book_map[t[i].book] ~= i then
 
              return;
 
            end;
 
          end;
 
          p(translate_now("forest_locale", 'library_shelf_puzzle_used_book_success'));
 
          disable 'library_shelves'
 
          enable 'library_hidden_path'
 
          walkout()
 
        end;
 
      else
 
        return false;
 
      end;
 
@@ -1142,264 +1142,264 @@ function book(number)
 
end;
 

	
 
room {
 
	nam = 'library_shelf_puzzle';
 
	nofollow = true;
 
	disp = translate("forest_locale", 'library');
 
	theme = 'main';
 
  nam = 'library_shelf_puzzle';
 
  nofollow = true;
 
  disp = translate("forest_locale", 'library');
 
  theme = 'main';
 
  onexit = function(s)
 
    if have('book_1') or have('book_2') or have('book_3') or have('book_4') or have('book_5') or have('book_6') or have('book_7') or have('book_8')or have('book_9') then
 
      p(translate_now("forest_locale", 'leave_books_message'));
 
      return false;
 
    end;
 
  end;
 
	pic = function(s)
 
		local pic = 'images/library/library_bg_' .. library_word.. '.png';
 
		for index, book in ipairs(_'shelf'.obj) do
 
			pic = pic .. ';images/library/library_book' .. tostring(book.book) .. '.png@' .. tostring(35 * index - 33) .. ',63';
 
		end;
 
		return pic;
 
	end;
 
	way = {
 
		path {'#back', translate("forest_locale", 'transition_away_from_bookstand'), 'library'};
 
	};
 
  pic = function(s)
 
    local pic = 'images/library/library_bg_' .. library_word.. '.png';
 
    for index, book in ipairs(_'shelf'.obj) do
 
      pic = pic .. ';images/library/library_book' .. tostring(book.book) .. '.png@' .. tostring(35 * index - 33) .. ',63';
 
    end;
 
    return pic;
 
  end;
 
  way = {
 
    path {'#back', translate("forest_locale", 'transition_away_from_bookstand'), 'library'};
 
  };
 
}:with {
 
	obj {
 
		nam = 'shelf';
 
		dsc = function(s)
 
			local count = #s.obj;
 
			if count > 1 then
 
				p(translate_now("forest_locale", 'library_shelf_puzzle_shelf_multiple'));
 
			elseif count == 1 then
 
				p(translate_now("forest_locale", 'library_shelf_puzzle_shelf_single'));
 
			else
 
				p(translate_now("forest_locale", 'library_shelf_puzzle_shelf_none'));
 
			end;
 
		end;
 
		act = function(s)
 
  obj {
 
    nam = 'shelf';
 
    dsc = function(s)
 
      local count = #s.obj;
 
      if count > 1 then
 
        p(translate_now("forest_locale", 'library_shelf_puzzle_shelf_multiple'));
 
      elseif count == 1 then
 
        p(translate_now("forest_locale", 'library_shelf_puzzle_shelf_single'));
 
      else
 
        p(translate_now("forest_locale", 'library_shelf_puzzle_shelf_none'));
 
      end;
 
    end;
 
    act = function(s)
 
      return translate_now("forest_locale", 'library_shelf_puzzle_shelf_act', {word=library_word});
 
    end;
 
		used = function(s, o)		
 
			if o.book then
 
				remove(o, pl);
 
				_'shelf'.obj:add(o);
 
				p(translate_now("forest_locale", 'library_shelf_puzzle_used_book'));
 
    used = function(s, o)    
 
      if o.book then
 
        remove(o, pl);
 
        _'shelf'.obj:add(o);
 
        p(translate_now("forest_locale", 'library_shelf_puzzle_used_book'));
 

	
 
				if #s.obj == 9 then
 
					for i = 1, 9 do
 
						if library_book_map[s.obj[i].book] ~= i then
 
							return;
 
						end;
 
					end;
 
					p(translate_now("forest_locale", 'library_shelf_puzzle_used_book_success'));
 
					disable 'library_shelves'
 
					enable 'library_hidden_path'
 
					walkout()
 
				end;
 
			else
 
				return false;
 
			end;
 
		end;
 
	}:with {
 
		book(1),
 
		book(2),
 
		book(3),
 
		book(4),
 
		book(5),
 
		book(6),
 
		book(7),
 
		book(8),
 
		book(9),
 
	}
 
        if #s.obj == 9 then
 
          for i = 1, 9 do
 
            if library_book_map[s.obj[i].book] ~= i then
 
              return;
 
            end;
 
          end;
 
          p(translate_now("forest_locale", 'library_shelf_puzzle_used_book_success'));
 
          disable 'library_shelves'
 
          enable 'library_hidden_path'
 
          walkout()
 
        end;
 
      else
 
        return false;
 
      end;
 
    end;
 
  }:with {
 
    book(1),
 
    book(2),
 
    book(3),
 
    book(4),
 
    book(5),
 
    book(6),
 
    book(7),
 
    book(8),
 
    book(9),
 
  }
 
}
 

	
 
room {
 
	nam = 'library_hidden_room';
 
	pic = function(s)
 
  nam = 'library_hidden_room';
 
  pic = function(s)
 
    if where('box')^here() then
 
      return 'images/library_hidden_room_box.png';
 
    else
 
      return 'images/library_hidden_room.png';
 
    end;
 
  end;
 
	disp = translate("forest_locale", 'library_hidden_room');
 
	theme = 'main';
 
	nofollow = true;
 
	decor = translate("forest_locale", 'library_hidden_room_decor');
 
	way = {
 
		path {translate("forest_locale", 'transition_to_main_hall'), 'library'};
 
	};
 
  disp = translate("forest_locale", 'library_hidden_room');
 
  theme = 'main';
 
  nofollow = true;
 
  decor = translate("forest_locale", 'library_hidden_room_decor');
 
  way = {
 
    path {translate("forest_locale", 'transition_to_main_hall'), 'library'};
 
  };
 
}:with {
 
	obj {
 
		nam = '#table';
 
		act = translate("forest_locale", 'library_hidden_room_table');
 
	};
 
	obj {
 
		oiled = false;
 
		opened = false;
 
		lock_taken = false;
 
		nam = 'box';
 
		disp = translate("forest_locale", 'box_disp');
 
		disp2 = translate("forest_locale", 'box_disp2');
 
		disp3 = translate("forest_locale", 'box_disp3');
 
		dsc = translate("forest_locale", 'box_dsc');
 
		tak = translate("forest_locale", 'box_tak');
 
		inv = function(s)
 
			seen_ring_box = true;
 
			if s.lock_taken then
 
				p(translate_now("forest_locale", 'box_inv_without_lock'));
 
			elseif s.opened then
 
				s.lock_taken = true;
 
				p(translate_now("forest_locale", 'box_inv_take_lock'));
 
				take('lock');
 
				remove('box', pl);
 
			else
 
  obj {
 
    nam = '#table';
 
    act = translate("forest_locale", 'library_hidden_room_table');
 
  };
 
  obj {
 
    oiled = false;
 
    opened = false;
 
    lock_taken = false;
 
    nam = 'box';
 
    disp = translate("forest_locale", 'box_disp');
 
    disp2 = translate("forest_locale", 'box_disp2');
 
    disp3 = translate("forest_locale", 'box_disp3');
 
    dsc = translate("forest_locale", 'box_dsc');
 
    tak = translate("forest_locale", 'box_tak');
 
    inv = function(s)
 
      seen_ring_box = true;
 
      if s.lock_taken then
 
        p(translate_now("forest_locale", 'box_inv_without_lock'));
 
      elseif s.opened then
 
        s.lock_taken = true;
 
        p(translate_now("forest_locale", 'box_inv_take_lock'));
 
        take('lock');
 
        remove('box', pl);
 
      else
 
        p(translate_now("forest_locale", 'box_inv'));
 
        if seen_ring_librarian then
 
          p(translate_now("forest_locale", 'box_inv_known'));
 
        end;
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'hidden_key' then
 
				if s.oiled then
 
					s.opened = true;
 
					take('map');
 
					p(translate_now("forest_locale", 'box_used_key_success'));
 
				else
 
					p(translate_now("forest_locale", 'box_used_key_failed'));
 
				end;
 
			elseif o^'oil' then
 
				if not s.oiled then
 
					s.oiled = true;
 
					p(translate_now("forest_locale", 'box_used_key_oil'));
 
				else
 
					p(translate_now("forest_locale", 'box_used_key_oil2'));
 
				end;
 
			end;
 
		end;
 
	}
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'hidden_key' then
 
        if s.oiled then
 
          s.opened = true;
 
          take('map');
 
          p(translate_now("forest_locale", 'box_used_key_success'));
 
        else
 
          p(translate_now("forest_locale", 'box_used_key_failed'));
 
        end;
 
      elseif o^'oil' then
 
        if not s.oiled then
 
          s.oiled = true;
 
          p(translate_now("forest_locale", 'box_used_key_oil'));
 
        else
 
          p(translate_now("forest_locale", 'box_used_key_oil2'));
 
        end;
 
      end;
 
    end;
 
  }
 
}
 

	
 
obj {
 
	nam = 'map';
 
	disp = translate("forest_locale", 'map_disp');
 
	disp2 = translate("forest_locale", 'map_disp2');
 
	disp3 = translate("forest_locale", 'map_disp3');
 
	inv = function(s)
 
		p(translate_now("forest_locale", 'map_inv'));
 
		_('fly_west_from_village'):enable();
 
	end;
 
  nam = 'map';
 
  disp = translate("forest_locale", 'map_disp');
 
  disp2 = translate("forest_locale", 'map_disp2');
 
  disp3 = translate("forest_locale", 'map_disp3');
 
  inv = function(s)
 
    p(translate_now("forest_locale", 'map_inv'));
 
    _('fly_west_from_village'):enable();
 
  end;
 
}
 

	
 
room {
 
	nam = 'inside_crater_glade';
 
	pic = 'images/inside_crater_glade.png';
 
	disp = translate("forest_locale", 'inside_crater_glade');
 
	theme = 'main';
 
	onenter = function(s)
 
		if here()^'above_crater' then
 
			p(translate_now("forest_locale", 'inside_crater_glade_on_enter'));
 
		end;
 
	end;
 
	decor = translate("forest_locale", 'inside_crater_glade_decor');
 
	way = {
 
		path {translate("forest_locale", 'transition_fly'), "above_crater"};
 
		path {translate("forest_locale", 'transition_along_the_path'), "inside_crater_path"};
 
	}
 
  nam = 'inside_crater_glade';
 
  pic = 'images/inside_crater_glade.png';
 
  disp = translate("forest_locale", 'inside_crater_glade');
 
  theme = 'main';
 
  onenter = function(s)
 
    if here()^'above_crater' then
 
      p(translate_now("forest_locale", 'inside_crater_glade_on_enter'));
 
    end;
 
  end;
 
  decor = translate("forest_locale", 'inside_crater_glade_decor');
 
  way = {
 
    path {translate("forest_locale", 'transition_fly'), "above_crater"};
 
    path {translate("forest_locale", 'transition_along_the_path'), "inside_crater_path"};
 
  }
 
}: with {
 
	obj {
 
		nam = '#forest';
 
		act = translate("forest_locale", 'inside_crater_glade_forest');
 
	};
 
	obj {
 
		nam = '#oak';
 
		act = translate("forest_locale", 'inside_crater_glade_oak');
 
	};
 
	obj {
 
		nam = '#grass';
 
		act = translate("forest_locale", 'inside_crater_glade_grass');
 
	};
 
	obj {
 
		nam = '#path';
 
		act = translate("forest_locale", 'inside_crater_glade_path');
 
	};
 
	obj {
 
		nam = '#tower';
 
		act = translate("forest_locale", 'inside_crater_glade_tower');
 
	};
 
	obj {
 
		nam = '#crater';
 
		act = translate("forest_locale", 'inside_crater_glade_crater');
 
	};
 
  obj {
 
    nam = '#forest';
 
    act = translate("forest_locale", 'inside_crater_glade_forest');
 
  };
 
  obj {
 
    nam = '#oak';
 
    act = translate("forest_locale", 'inside_crater_glade_oak');
 
  };
 
  obj {
 
    nam = '#grass';
 
    act = translate("forest_locale", 'inside_crater_glade_grass');
 
  };
 
  obj {
 
    nam = '#path';
 
    act = translate("forest_locale", 'inside_crater_glade_path');
 
  };
 
  obj {
 
    nam = '#tower';
 
    act = translate("forest_locale", 'inside_crater_glade_tower');
 
  };
 
  obj {
 
    nam = '#crater';
 
    act = translate("forest_locale", 'inside_crater_glade_crater');
 
  };
 
}
 

	
 
room {
 
	nam = 'inside_crater_path';
 
	pic = function(s)
 
		local p = 'images/inside_crater_path.png';
 
		if here()^where('solarscale') then
 
			p = p .. ';images/characters/solarscale_on_rock.png';
 
		end;
 
		return p;
 
	end;
 
	disp = translate("forest_locale", 'inside_crater_path');
 
	theme = 'main';
 
	decor = translate("forest_locale", 'inside_crater_path_decor');
 
	exit = function(s, t)
 
		if t^'crater_near_tower' and seen('solarscale', s) then
 
			remove('solarscale', where('solarscale'));
 
			p(translate_now("forest_locale", 'inside_crater_path_exit'));
 
		end;
 
	end;
 
	way = {
 
		path {translate("forest_locale", 'transition_to_glade'), "inside_crater_glade"};
 
		path {translate("forest_locale", 'transition_to_tower'), "crater_near_tower"};
 
	};
 
  nam = 'inside_crater_path';
 
  pic = function(s)
 
    local p = 'images/inside_crater_path.png';
 
    if here()^where('solarscale') then
 
      p = p .. ';images/characters/solarscale_on_rock.png';
 
    end;
 
    return p;
 
  end;
 
  disp = translate("forest_locale", 'inside_crater_path');
 
  theme = 'main';
 
  decor = translate("forest_locale", 'inside_crater_path_decor');
 
  exit = function(s, t)
 
    if t^'crater_near_tower' and seen('solarscale', s) then
 
      remove('solarscale', where('solarscale'));
 
      p(translate_now("forest_locale", 'inside_crater_path_exit'));
 
    end;
 
  end;
 
  way = {
 
    path {translate("forest_locale", 'transition_to_glade'), "inside_crater_glade"};
 
    path {translate("forest_locale", 'transition_to_tower'), "crater_near_tower"};
 
  };
 
}: with {
 
	obj {
 
		nam = '#grass';
 
		act = translate("forest_locale", 'inside_crater_path_grass');
 
	};
 
	obj {
 
		nam = '#crater';
 
		act = translate("forest_locale", 'inside_crater_path_crater')
 
	};
 
	obj {
 
		nam = '#trees';
 
		act = translate("forest_locale", 'inside_crater_path_trees')
 
	};
 
	obj {
 
		nam = '#tower';
 
		act = translate("forest_locale", 'inside_crater_path_tower')
 
	};
 
	obj {
 
		nam = '#stump';
 
		dsc = function(s)
 
			if seen('solarscale', here()) then
 
				p(translate_now("forest_locale", 'inside_crater_path_stump_with_solarscale'));
 
			else
 
				p(translate_now("forest_locale", 'inside_crater_path_stump'));
 
			end;
 
		end;
 
		act = translate("forest_locale", 'inside_crater_path_stump_act');
 
	};
 
	obj {
 
		nam = 'solarscale';
 
		act = function(s)
 
			walkin('solarscale_dlg');
 
		end;
 
	}
 
  obj {
 
    nam = '#grass';
 
    act = translate("forest_locale", 'inside_crater_path_grass');
 
  };
 
  obj {
 
    nam = '#crater';
 
    act = translate("forest_locale", 'inside_crater_path_crater')
 
  };
 
  obj {
 
    nam = '#trees';
 
    act = translate("forest_locale", 'inside_crater_path_trees')
 
  };
 
  obj {
 
    nam = '#tower';
 
    act = translate("forest_locale", 'inside_crater_path_tower')
 
  };
 
  obj {
 
    nam = '#stump';
 
    dsc = function(s)
 
      if seen('solarscale', here()) then
 
        p(translate_now("forest_locale", 'inside_crater_path_stump_with_solarscale'));
 
      else
 
        p(translate_now("forest_locale", 'inside_crater_path_stump'));
 
      end;
 
    end;
 
    act = translate("forest_locale", 'inside_crater_path_stump_act');
 
  };
 
  obj {
 
    nam = 'solarscale';
 
    act = function(s)
 
      walkin('solarscale_dlg');
 
    end;
 
  }
 
}
 

	
 
dlg {
 
	nam = 'solarscale_dlg';
 
	disp = translate("solarscale_locale", 'disp');
 
	theme = 'main';
 
	pic = 'images/inside_crater_path.png;images/characters/solarscale.png';
 
	enter = translate("solarscale_locale", 'first_dlg_enter');
 
  nam = 'solarscale_dlg';
 
  disp = translate("solarscale_locale", 'disp');
 
  theme = 'main';
 
  pic = 'images/inside_crater_path.png;images/characters/solarscale.png';
 
  enter = translate("solarscale_locale", 'first_dlg_enter');
 
  convince = 0;
 
  open_q45 = false;
 
	phr = {
 
  phr = {
 
    {only=true, '#q1', translate("solarscale_locale", 'first_dlg_dragon'), translate("solarscale_locale", 'first_dlg_dragon_response'),
 
      {translate("solarscale_locale", 'first_dlg_dragon_admit'), function(s) 
 
        _('solarscale_dlg').convince = _('solarscale_dlg').convince + 1;
 
@@ -1481,41 +1481,41 @@ dlg {
 
          return translate_now("solarscale_locale", 'first_dlg_tower_bye_thanks');
 
        end;
 
    end, function(s)
 
			walkout();
 
			remove('solarscale', where('solarscale'));
 
			return translate_now("solarscale_locale", 'first_dlg_tower_bye_response');
 
		end};
 
      walkout();
 
      remove('solarscale', where('solarscale'));
 
      return translate_now("solarscale_locale", 'first_dlg_tower_bye_response');
 
    end};
 
  }
 
}
 

	
 
room {
 
	nam = 'crater_near_tower';
 
	pic = 'images/crater_near_tower.png';
 
	disp = translate("forest_locale", 'crater_near_tower');
 
	theme = 'main';
 
	decor = translate("forest_locale", 'crater_near_tower_decor');
 
  nam = 'crater_near_tower';
 
  pic = 'images/crater_near_tower.png';
 
  disp = translate("forest_locale", 'crater_near_tower');
 
  theme = 'main';
 
  decor = translate("forest_locale", 'crater_near_tower_decor');
 
  enter = function(s)
 
    tower_seen = true;
 
  end;
 
	way = {
 
		path {translate("forest_locale", 'transition_along_the_path'), "inside_crater_path"};
 
		path {translate("forest_locale", 'transition_inside_tower'), "tower_level_1"};
 
	};
 
  way = {
 
    path {translate("forest_locale", 'transition_along_the_path'), "inside_crater_path"};
 
    path {translate("forest_locale", 'transition_inside_tower'), "tower_level_1"};
 
  };
 
}:with {
 
	obj {
 
		nam = '#tower';
 
		act = translate("forest_locale", 'crater_near_tower_tower');
 
	};
 
	obj {
 
		nam = '#grass';
 
		act = translate("forest_locale", 'crater_near_tower_grass');
 
	};
 
	obj {
 
		nam = '#trees';
 
		act = translate("forest_locale", 'crater_near_tower_trees');
 
	};
 
	obj {
 
		nam = '#sun';
 
		act = translate("forest_locale", 'crater_near_tower_sun');
 
	};
 
  obj {
 
    nam = '#tower';
 
    act = translate("forest_locale", 'crater_near_tower_tower');
 
  };
 
  obj {
 
    nam = '#grass';
 
    act = translate("forest_locale", 'crater_near_tower_grass');
 
  };
 
  obj {
 
    nam = '#trees';
 
    act = translate("forest_locale", 'crater_near_tower_trees');
 
  };
 
  obj {
 
    nam = '#sun';
 
    act = translate("forest_locale", 'crater_near_tower_sun');
 
  };
 
}
game_theme.lua
Show inline comments
 
new file 100644
 
if instead.tiny then
 
  -- Stub the theme if instead.tiny is present
 
  function set_theme(t) end;
 
  return;
 
end;
 

	
 
function set_theme(t)  
 
  -- resetting defaults
 
  fmt.para = true;
 
  std.scene_delim = '^^';
 
  theme.set('snd.click', 'sound/click.wav');
 
  
 
  D {'settings_open'};
 

	
 
  local tname, tcolor_text, tcolor_link, tcolor_alink;
 

	
 
  local width, height = diretheme.get_screen();
 
  
 
  -- 640x480 is the base size
 
  local scale = get_graphic_scale();
 
  local max_scale_x = math.floor(width / 640);
 
  local max_scale_y = math.floor(height / 480);
 
  -- Fail-safe for too small screen
 
  if max_scale_x < 1 then max_scale_x = 1; end;
 
  if max_scale_y < 1 then max_scale_y = 1; end;
 
    
 
  local max_scale = math.min(max_scale_x, max_scale_y);
 
  
 
  if scale > max_scale then
 
    scale = max_scale;
 
    prefs.graphic_scale = false;
 
  end;
 
  
 
  local cursor_scale = get_cursor_scale();
 
  if cursor_scale > 2 * max_scale then
 
    cursor_scale = 2 * max_scale;
 
  end;
 
  
 
  local font_scale = get_font_scale() / 100;
 
  if font_scale > 2 * scale then
 
    font_scale = scale;
 
    prefs.font_scale = font_scale * 100
 
  end;
 
  
 
  local inv_scale = get_inventory_font_scale() / 100;
 
  
 
  local text_align = 'justify';
 
  if prefs.text_alignment == 2 then
 
    text_align = 'left';
 
  end;
 
  
 
  local hpadding, vpadding = 0, 0;
 
  if prefs.text_padding == 2 then
 
    hpadding, vpadding = 24, 12;
 
  end;
 
  
 
  local interval = '1.0';
 
  if prefs.text_interval == 2 then
 
    interval = '1.5';
 
  end;
 
  
 
  local canvas = diretheme.set_canvas({rmax = 2, rmin = 1});
 
  diretheme.set_scale(scale);
 

	
 
  local scaled_width, scaled_height = diretheme.get_scaled_screen();
 

	
 
  current_theme = t;
 
  local tvariant = 0;
 
  if t:match("_bw$") then
 
    t = t:gsub("_bw$", "");
 
    tvariant = 1;
 
  end;
 
  
 
  -- Most text area settings are per-theme
 
  local text_area = {};
 
  
 
  -- Hide inventory by default
 
  local inventory = {
 
    rect = {
 
      lx = width + 1,
 
      y = 0,
 
      wmax = 1,
 
      wmin = 1,
 
      ty = 2,
 
      by = 2,
 
      ax = 1
 
    }
 
  };
 
  
 
  -- And image
 
  local image_area = {
 
    rect = {
 
      lx = width + 1,
 
      ax = 1,
 
      wmax = 584,
 
      hmax = 258,
 
      wmin = 584,
 
      hmin = 258
 
    };
 
    bg = {};
 
    mode = 'float';
 
  };
 
  
 
  -- Preset colors
 
  local theme_directory = nil;
 
  local text_color, link_color, alink_color;
 
  local inv_color, inv_link, inv_alink;
 
  if t == 'terminal' or t == 'black' then
 
    diretheme.set_canvas({
 
      lx = 0, ty = 0, rx = 0, by = 0
 
    });
 
    text_color = '#D0FFFF';
 
    link_color = '#ABDECE';
 
    alink_color = '#9BCEBE';  
 
    theme_directory = 'images/tower_theme';
 
    
 
    text_area.text = {
 
      font = 'fonts/vga.ttf',
 
      color = text_color,
 
      link = link_color,
 
      alink = alink_color,
 
      size = 16
 
    };
 
  else
 
    canvas = diretheme.set_canvas({
 
      lx = 0, ty = 0, rx = 0, by = 0, rmin = 1.2, rmax = 1.8
 
    });
 
    
 
    if t == 'menu' or t == 'main' or t == 'ending_outside' or t == 'credits_outside' then
 
      inv_color = '#403426';
 
      inv_link = '#403426';
 
      inv_alink = '#61503A';
 
      
 
      if tvariant == 0 then
 
        text_color = '#000504';
 
        link_color = '#80382A';
 
        alink_color = '#80605D';
 
        theme_directory = 'images/main_theme';
 
      else
 
        text_color = '#040404';
 
        link_color = '#434343';
 
        alink_color = '#585858';
 
        theme_directory = 'images/bwm_theme';
 
      end;
 
      
 
      text_area.uppos = {ax=1, x = 12, y = 0, ay=-1};
 
      text_area.downpos = {ax=1, x = 12, y = 0, ay=1};
 
      text_area.bg = {
 
        image = theme_directory .. '/text_bg.png',
 
        options = {
 
          mode = 6,
 
          drawmethod = 2,
 
          slice = {
 
            x = 9,
 
            y = 6,
 
            w = 96,
 
            h = 96
 
          },
 
          scale = true
 
        }
 
      };
 
    elseif t == 'tower' or t == 'ending_inside' or t == 'credits_inside' then
 
      inv_color = '#6b9e8e';
 
      inv_link = '#9bcebe';
 
      inv_alink = '#Bbeede';
 
      
 
      if tvariant == 0 then
 
        text_color = '#93DDCD';
 
        link_color = '#E0F0EA';
 
        alink_color = '#FFFFFF';
 
        theme_directory = 'images/tower_theme';
 
      else
 
        text_color = '#ADADAD';
 
        link_color = '#CDCDCD';
 
        alink_color = '#BDBDBD';
 
        theme_directory = 'images/bwt_theme';
 
      end;
 
      
 
      text_area.uppos = {ax=1, x = 16, y = 0, ay=-1};
 
      text_area.downpos = {ax=1, x = 16, y = 0, ay=1};
 
      text_area.bg = {
 
        image = theme_directory .. '/text_bg.png',
 
        options = {
 
          mode = 6,
 
          drawmethod = 2,
 
          slice = {
 
            x = 6,
 
            y = 6,
 
            w = 128,
 
            h = 128
 
          },
 
          scale = true
 
        }
 
      };
 
    end;
 
    
 
    if t == 'ending_inside' or t == 'ending_outside' then
 
      canvas = diretheme.set_canvas({
 
        lx = 0, ty = 0, rx = 0, by = 0
 
      });
 
    end;
 
  
 
    text_area.align = text_align;
 
    text_area.height = interval;
 
    text_area.scaleui = true;
 
    text_area.up = theme_directory .. '/arrow_up.png';
 
    text_area.down = theme_directory .. '/arrow_down.png';
 
    text_area.text = {
 
      font = 'fonts/{sans,sans-b,sans-i,sans-bi}.ttf',
 
      color = text_color,
 
      link = link_color,
 
      alink = alink_color,
 
      size = math.floor(16 * font_scale),
 
      noscale = true
 
    };
 
    
 
    inventory.up = theme_directory .. '/arrow_up.png';
 
    inventory.down = theme_directory .. '/arrow_down.png';
 
    inventory.uppos = {ax=1, x = 8, y = 0, ay=-1};
 
    inventory.downpos = {ax=1, x = 8, y = 0, ay=1};
 
    inventory.text = {
 
      color = inv_color,
 
      link = inv_link,
 
      alink = inv_alink,
 
      size = math.floor(16 * inv_scale),
 
      noscale = true
 
    };
 
    inventory.height = interval;
 
  end;
 
  
 
  if t == 'main' or t == 'tower' then
 
    std.scene_delim = '^' .. fmt.c(fmt.img(theme_directory .. '/line_separator.png')) .. '^'
 
  end;
 
  
 
 -- And menu, but need theme_directory to have proper button image
 
  local menu = {
 
    button = {
 
      image = theme_directory ..'/menu.png';
 
      options = {
 
        mode = 1,
 
        scale = true
 
      }
 
    };
 
    buttonrect = {
 
      x = width + 1,
 
      y = 0,
 
      w = 50,
 
      h = 16
 
    };
 
    text = {
 
      size = math.floor(15 * font_scale),
 
      noscale = true
 
    },
 
    height = interval,
 
    scaleui = true;
 
  };
 
  
 
  local cursor, active_cursor = 'images/cursor.png', 'images/cursor_active.png';
 
  if tvariant == 1 then
 
    cursor, active_cursor = 'images/cursor_bw.png', 'images/cursor_active_bw.png'
 
  end;
 
  
 
  diretheme.set_cursor({
 
    x = 2,
 
    y = 2,
 
    normal = cursor,
 
    active = active_cursor,
 
    scale = true;
 
    scalefactor = cursor_scale;
 
  });
 
  
 
  if t == 'menu' then
 
    diretheme.set_background('#89C6AE', 255, 'images/main_theme/background.png', {mode=2, scale=true});
 
    local padding_delta = -10;
 
    if height < 520 * scale then
 
      padding_delta = -95;
 
    end;
 
    
 
    text_area.rect = {
 
      ty = padding_delta + vpadding,
 
      wmax = 538 - hpadding * 2,
 
      hmax = 322 - vpadding * 2,
 
      ay = 0
 
    };
 
    text_area.text = text_area.text;
 
    text_area.uppos = {ax=1, x = 15, y = 65, ay=-1};
 
    text_area.downpos = {ax=1, x = 15, y = -20, ay=1};
 
    text_area.contentrect = {wf=prefs.text_width / 100};
 
    text_area.bg = '';
 
  elseif t == 'main' then
 
    diretheme.set_background('#89C6AE', 255, 'images/main_theme/background.png', {mode=2, scale = true});
 
    
 
    local image_bg = 'images/main_theme/picture_bg.png';
 
    if canvas.w < 800 * scale then
 
      image_bg = 'images/main_theme/picture_bg_small.png';
 
    end;
 
    
 
    image_area.leftof = 'inv';
 
    image_area.topof = 'text';
 
    image_area.rect = {
 
      ax = 0,
 
      wmax = 584,
 
      hmax = 265,
 
      wmin = 584,
 
      hmin = 265
 
    };
 
    image_area.contentrect = {
 
      ax = 0,
 
      ay = -1,
 
      ty = 11,
 
      wmin = 320,
 
      hmin = 240,
 
      wmax = 320,
 
      hmax = 240
 
    };
 
    image_area.bg = {
 
      image = image_bg,
 
      options = {
 
        mode = 1,
 
        scale = true
 
      }
 
    };
 
    
 
    text_area.leftof = 'inv';
 
    text_area.rect = {
 
      lx = 7,
 
      ty = 266,
 
      rx = 8,
 
      by = 2,
 
      ax = 1,
 
      ay = 1
 
    };
 
    text_area.contentrect = {
 
      lx = 21 + hpadding,
 
      rx = 21 + hpadding,
 
      ty = 14 + vpadding,
 
      by = 14 + vpadding,
 
      wf=prefs.text_width / 100
 
    };
 
    
 
    inventory.rect = {
 
      rx = 2,
 
      y = 2,
 
      wmax = 208,
 
      wmin = 208,
 
      ty = 2,
 
      by = 2,
 
      ax = 1
 
    };
 
    inventory.contentrect = {
 
      lx = 25,
 
      rx = 25,
 
      ty = 40,
 
      by = 40
 
    };
 
    inventory.bg = {
 
      image = function(tpx, rect)
 
        local top = pixels.new('images/main_theme/inv_top.png'):scale(scale, scale, false);
 
        local mid = pixels.new('images/main_theme/inv_mid.png'):scale(scale, scale, false);
 
        local bottom = pixels.new('images/main_theme/inv_bottom.png'):scale(scale, scale, false);
 
        
 
        dire_draw_tile(mid, tpx, { x=rect.x + 11 * scale, y=rect.y + 10 * scale, w=rect.w - 22 * scale, h = rect.h - 20 * scale}, {});
 
        dire_draw_center(top, tpx, {x=rect.x, y=rect.y, w=208 * scale, h=60 * scale});
 
        dire_draw_center(bottom, tpx, {x=rect.x, y=rect.y + rect.h - 60 * scale, w=208 * scale, h=60 * scale});
 
      end,
 
      options = {scale = true}
 
    };
 

	
 
    menu.buttonrect = {
 
      wmin = 50,
 
      wmax = 50,
 
      hmin = 16,
 
      hmax = 16,
 
      by = 12,
 
      ay = 1,
 
      rx = 81,
 
      ax = 1
 
    };
 

	
 
    D {
 
      'settings_open', 
 
      'raw', 
 
      x=canvas.x + canvas.w - 33 * scale, 
 
      y=canvas.y + canvas.h - 30 * scale, 
 
      xc=0,
 
      yc=0,
 
      w=24 * scale,
 
      h=22 * scale,
 
      click=true,
 
    };
 
  elseif t == 'tower' then
 
    diretheme.set_background('#181E37', 255, 'images/tower_theme/background.png', {mode=2, scale=true});
 
    
 
    local image_bg = 'images/tower_theme/picture_bg.png';
 
    if canvas.w < 800 * scale then
 
      image_bg = 'images/tower_theme/picture_bg_small.png';
 
    end;
 
    
 
    image_area.leftof='inv';
 
    image_area.topof='text';
 
    image_area.rect = {
 
      ax = 0,
 
      maxw = 584,
 
      maxh = 258,
 
      minw = 584,
 
      minh = 258
 
    };
 
    image_area.contentrect = {
 
      ax = 0,
 
      ay = -1,
 
      ty = 12,
 
      wmin = 320,
 
      hmin = 240,
 
      wmax = 320,
 
      hmax = 240
 
    };
 
    image_area.bg = {
 
      image = image_bg,
 
      options = {
 
        mode = 1,
 
        scale = true
 
      }
 
    };
 
    
 
    text_area.leftof = 'inv';
 
    text_area.rect = {
 
      lx = 7,
 
      ty = 266,
 
      rx = 8,
 
      by = 2,
 
      ax = 1,
 
      ay = 1
 
    };
 
    text_area.contentrect = {
 
      lx = 21 + hpadding,
 
      rx = 21 + hpadding,
 
      ty = 14 + vpadding,
 
      by = 14 + vpadding,
 
      wf = prefs.text_width / 100
 
    };
 
  
 
    inventory.rect = {
 
      rx = 2,
 
      y = 2,
 
      wmax = 208,
 
      wmin = 208,
 
      ty = 2,
 
      by = 2,
 
      ax = 1
 
    };
 
    inventory.contentrect = {
 
      lx = 12,
 
      rx = 16,
 
      ty = 10,
 
      by = 40
 
    };
 
    inventory.bg = {
 
      image = function(tpx, rect)
 
        local bg = pixels.new('images/tower_theme/inv_bg.png'):scale(scale, scale, false);
 
        local icon = pixels.new('images/tower_theme/settings.png'):scale(scale, scale, false);
 
        
 
        local tbg, tbg_slice = dire_slice_9(bg, {
 
          x = 7 * scale,
 
          y = 11 * scale,
 
          w = 194 * scale,
 
          h = 38 * scale
 
        })
 
        
 
        dire_draw_9(tbg, tpx, rect, {parts=tbg_slice});
 
        
 
        dire_draw_center(icon, tpx, {x = rect.x + rect.w - 33 * scale, y = rect.y + rect.h - 35 * scale, w = 24 * scale, h = 22 * scale});
 
      end
 
    };
 
    
 
    menu.buttonrect = {
 
      wmin = 50,
 
      wmax = 50,
 
      hmin = 16,
 
      hmax = 16,
 
      by = 20,
 
      ay = 1,
 
      rx = 81,
 
      ax = 1
 
    };
 
    
 
    D {
 
      'settings_open', 
 
      'raw',
 
      x=canvas.x + canvas.w - 35 * scale, 
 
      y=canvas.y + canvas.h - 37 * scale,
 
      xc=0,
 
      yc=0,
 
      w=24 * scale,
 
      h=22 * scale,
 
      click=true
 
    };
 
  elseif t == 'terminal' then
 
    theme.set('snd.click', '');
 
    
 
    local upshift = 0;
 
    if height / scale < 540 then
 
      upshift = 19;
 
    end;
 
    
 
    local px = pixels.new(scaled_width, scaled_height);
 
    local tiles_src = pixels.new('images/terminal/table_tiles.png');
 
    local backdrop_src = pixels.new('images/terminal/backdrop.png');
 
    
 
    local tabletop = scaled_height - 422 - upshift
 
    if tabletop < 335 - upshift then
 
      tabletop = 335 - upshift;
 
    end;
 
    
 
    dire_draw_tile(tiles_src, px, {
 
      w = scaled_width,
 
      h = 422,
 
      x = 0,
 
      y = tabletop
 
    }, {xoffset = -1, yoffxet = -1});
 

	
 
    dire_draw_tile(backdrop_src, px, {
 
      w = scaled_width,
 
      h = tabletop,
 
      x = 0,
 
      y = 0
 
    }, {xoffset = -1, yoffset = -2});
 
    
 
    diretheme.set_background('#181E37', 255, px, {mode=5});
 
    
 
    local ty
 
    if here().ticks ~= nil and here().ticks < 128 and here().graphical then
 
      ty = 72
 
    else
 
      ty = 2
 
    end;    
 

	
 
    text_area.rect = {
 
      ty = 0 - upshift,
 
      by = 189,
 
      wmin = 808,
 
      hmin = 568,
 
      wmax = 808,
 
      hmax = 568,
 
      ax = 0,
 
      ay = 1
 
    };
 
    text_area.contentrect = {
 
      wmax = 569,
 
      hmax = 390,
 
      ty = ty,
 
      ax = 0,
 
      ay = -2,
 
      dx = -16
 
    };
 
    text_area.bg = {
 
      image = 'images/terminal/bg_text.png',
 
      options = {
 
        mode = 1,
 
        scale = true
 
      }
 
    };
 
  elseif t == 'ending_outside' then
 
    diretheme.set_background('#89C6AE', 255, theme_directory .. '/background.png', {mode=2, scale=true});
 
    
 
    if scaled_width == 640 and scaled_height == 480 then
 
      text_area.rect = {
 
        lx = 0,
 
        rx = 0,
 
        wmax = 640,
 
        hmax = 180,
 
        by = 0,
 
        ay = 1
 
      };
 
    else
 
      text_area.rect = {
 
        lx = 24,
 
        rx = 24,
 
        wmax = 600,
 
        hmax = 160,
 
        by = 24,
 
        ay = 1
 
      };
 
    end;
 
    
 
    text_area.contentrect = {
 
      lx = 18 + hpadding,
 
      rx = 18 + hpadding,
 
      ty = 14 + vpadding,
 
      by = 14 + vpadding,
 
      wf = prefs.text_width / 100
 
    };
 
  elseif t == 'ending_inside' then
 
    diretheme.set_background('#181E37', 255, theme_directory .. '/background.png', {mode=2});
 
    
 
     if scaled_width == 640 and scaled_height == 480 then
 
      text_area.rect = {
 
        lx = 0,
 
        rx = 0,
 
        wmax = 640,
 
        hmax = 180,
 
        by = 0,
 
        ay = 1
 
      };
 
    else
 
      text_area.rect = {
 
        lx = 24,
 
        rx = 24,
 
        wmax = 600,
 
        hmax = 160,
 
        by = 24,
 
        ay = 1
 
      };
 
    end;
 
    
 
    text_area.contentrect = {
 
      lx = 18 + hpadding,
 
      rx = 18 + hpadding,
 
      ty = 14 + vpadding,
 
      by = 14 + vpadding,
 
      wf = prefs.text_width / 100
 
    };
 
  elseif t == 'credits_outside' or t == 'credits_inside' then
 
    -- text scaled on top of picture
 
    text_area.rect = {
 
      wmax = 960,
 
      hmax = 600
 
    };
 
    text_area.bg = {};
 
    text_area.align = 'center';
 
    text_area.content_rect = {
 
      wf = prefs.text_width / 100
 
    };
 
  elseif t == 'black' then    
 
    fmt.para = false;
 
    diretheme.set_background('#000000', 255);
 
    
 
    text_area.rect = {
 
      wmax = 600,
 
      hmax = 400,
 
      ax = 0,
 
      ay = 0
 
    };
 
    text_area.align = 'center';
 
  end;
 
  
 
  diretheme.set_image_area(image_area, true);
 
  diretheme.set_text_area(text_area, true);
 
  diretheme.set_inventory_area(inventory, true);
 
  
 
  diretheme.set_menu(menu, true);
 
end;
 
\ No newline at end of file
images/terminal/keyboard_shift.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
images/title/about.eo.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
images/title/back.eo.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
images/title/load.eo.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
images/title/quit.eo.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
images/title/save.eo.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
images/title/settings.eo.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
images/title/start.eo.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
images/title/tutorial.eo.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
lib/decor.lua
Show inline comments
 
@@ -7,102 +7,102 @@ local pauseticks = nil;
 
local deltaticks = nil;
 

	
 
local function utf_ff(b, pos)
 
	if type(b) ~= 'string' or b:len() == 0 then
 
		return 0
 
	end
 
	local utf8 = (std.game.codepage == 'UTF-8' or std.game.codepage == 'utf-8')
 
	if not utf8 then return 1 end
 
	local i = pos or 1
 
	local l = 0
 
	if b:byte(i) < 0x80 then
 
		return 1
 
	end
 
	i = i + 1
 
	l = l + 1
 
	while b:byte(i) >= 0x80 and b:byte(i) <= 0xbf do
 
		i = i + 1
 
		l = l + 1
 
		if i > b:len() then
 
			break
 
		end
 
	end
 
	return l
 
  if type(b) ~= 'string' or b:len() == 0 then
 
    return 0
 
  end
 
  local utf8 = (std.game.codepage == 'UTF-8' or std.game.codepage == 'utf-8')
 
  if not utf8 then return 1 end
 
  local i = pos or 1
 
  local l = 0
 
  if b:byte(i) < 0x80 then
 
    return 1
 
  end
 
  i = i + 1
 
  l = l + 1
 
  while b:byte(i) >= 0x80 and b:byte(i) <= 0xbf do
 
    i = i + 1
 
    l = l + 1
 
    if i > b:len() then
 
      break
 
    end
 
  end
 
  return l
 
end
 

	
 
local cache = {
 
}
 

	
 
function cache:new(max, ttl)
 
	local c = {
 
		cache = {};
 
		list = {};
 
		ttl = ttl or 4;
 
		max = max or 16;
 
	}
 
	self.__index = self
 
	return std.setmt(c, self)
 
  local c = {
 
    cache = {};
 
    list = {};
 
    ttl = ttl or 4;
 
    max = max or 16;
 
  }
 
  self.__index = self
 
  return std.setmt(c, self)
 
end
 

	
 
function cache:add(name, value)
 
	local v = self.cache[name]
 
	if v then
 
		v.value = value
 
		v.use = v.use + 1
 
		return v.value
 
	end
 
	v = { name = name, value = value, use = 1 }
 
	self.cache[name] = v
 
	table.insert(self.list, 1, v)
 
	return v.value
 
  local v = self.cache[name]
 
  if v then
 
    v.value = value
 
    v.use = v.use + 1
 
    return v.value
 
  end
 
  v = { name = name, value = value, use = 1 }
 
  self.cache[name] = v
 
  table.insert(self.list, 1, v)
 
  return v.value
 
end
 

	
 
function cache:get(name)
 
	local v = self.cache[name]
 
	if not v then
 
		return
 
	end
 
	v.use = v.use + 1
 
	return v.value
 
  local v = self.cache[name]
 
  if not v then
 
    return
 
  end
 
  v.use = v.use + 1
 
  return v.value
 
end
 

	
 
function cache:clear()
 
	local nr = #self.list
 
	local list = {}
 
	if nr <= self.max then
 
		return
 
	end
 
	local todel = nr - self.max
 
	for k, v in ipairs(self.list) do
 
		if v.use == 0 and todel > 0 then
 
			v.ttl = v.ttl - 1
 
			if v.ttl <= 0 then
 
				self.cache[v.name] = nil
 
				if DEBUG then
 
					dprint("cache purge: "..v.name)
 
				end
 
				todel = todel - 1
 
			else
 
				table.insert(list, v)
 
			end
 
		else
 
			table.insert(list, v)
 
		end
 
	end
 
	self.list = list
 
  local nr = #self.list
 
  local list = {}
 
  if nr <= self.max then
 
    return
 
  end
 
  local todel = nr - self.max
 
  for k, v in ipairs(self.list) do
 
    if v.use == 0 and todel > 0 then
 
      v.ttl = v.ttl - 1
 
      if v.ttl <= 0 then
 
        self.cache[v.name] = nil
 
        if DEBUG then
 
          dprint("cache purge: "..v.name)
 
        end
 
        todel = todel - 1
 
      else
 
        table.insert(list, v)
 
      end
 
    else
 
      table.insert(list, v)
 
    end
 
  end
 
  self.list = list
 
end
 

	
 
function cache:put(name)
 
	local v = self.cache[name]
 
	if not v then
 
		return
 
	end
 
	v.use = v.use - 1
 
	if v.use <= 0 then v.use = 0; v.ttl = self.ttl; end
 
	return v.value
 
  local v = self.cache[name]
 
  if not v then
 
    return
 
  end
 
  v.use = v.use - 1
 
  if v.use <= 0 then v.use = 0; v.ttl = self.ttl; end
 
  return v.value
 
end
 

	
 
local img = {
 
	cache = cache:new();
 
  cache = cache:new();
 
}
 

	
 
function img:update(v)
 
@@ -187,7 +187,7 @@ function img:delete(v)
 
end
 

	
 
function img:clear()
 
	self.cache:clear()
 
  self.cache:clear()
 
end
 

	
 

	
 
@@ -196,100 +196,102 @@ function img:render(v)
 
    return
 
  end;
 

	
 
	if v.background then
 
		if v.frames and v.fw and v.fh then
 
			v.sprite:copy(v.fx, v.fy, v.fw, v.fh, sprite.scr(), v.dx - v.xc, v.dy - v.yc)
 
		else
 
			v.sprite:copy(sprite.scr(), v.x - v.xc, v.y - v.yc)
 
		end
 
		return
 
	end
 
	if v.render and type(v.render) == 'function' then
 
		v.render(v)
 
		return
 
	end
 
	if v.fx and v.fy and v.w and v.h then
 
		v.sprite:draw(v.fx, v.fy, v.fw, v.fh, sprite.scr(), v.dx - v.xc, v.dy - v.yc, v.alpha)
 
	else
 
		v.sprite:draw(sprite.scr(), v.x - v.xc, v.y - v.yc, v.alpha)
 
	end
 
  if v.background then
 
    if v.frames and v.fw and v.fh then
 
      v.sprite:copy(v.fx, v.fy, v.fw, v.fh, sprite.scr(), v.dx - v.xc, v.dy - v.yc)
 
    elseif v.w and v.h then
 
      v.sprite:copy(0, 0, v.w, v.h, sprite.scr(), v.x - v.xc, v.y - v.yc)
 
    else
 
      v.sprite:copy(sprite.scr(), v.x - v.xc, v.y - v.yc)
 
    end
 
    return
 
  end
 
  if v.render and type(v.render) == 'function' then
 
    v.render(v)
 
    return
 
  end
 
  if v.fx and v.fy and v.w and v.h then
 
    v.sprite:draw(v.fx, v.fy, v.fw, v.fh, sprite.scr(), v.dx - v.xc, v.dy - v.yc, v.alpha)
 
  else
 
    v.sprite:draw(sprite.scr(), v.x - v.xc, v.y - v.yc, v.alpha)
 
  end
 
end
 

	
 
function img:new_spr(v, s)
 
	v.xc = v.xc or 0
 
	v.yc = v.yc or 0
 
	v.x = v.x or 0
 
	v.y = v.y or 0
 
	v.sprite = s
 
	if not s then
 
		return v
 
	end
 
	local w, h = s:size()
 
	if v.w then w = v.w end
 
	if v.h then h = v.h end
 
	if v.xc == true then
 
		v.xc = math.floor(w / 2)
 
	end
 
	if v.yc == true then
 
		v.yc = math.floor(h / 2)
 
	end
 
	v.w, v.h = w, h
 
	return v
 
  v.xc = v.xc or 0
 
  v.yc = v.yc or 0
 
  v.x = v.x or 0
 
  v.y = v.y or 0
 
  v.sprite = s
 
  if not s then
 
    return v
 
  end
 
  local w, h = s:size()
 
  if v.w then w = v.w end
 
  if v.h then h = v.h end
 
  if v.xc == true then
 
    v.xc = math.floor(w / 2)
 
  end
 
  if v.yc == true then
 
    v.yc = math.floor(h / 2)
 
  end
 
  v.w, v.h = w, h
 
  return v
 
end
 

	
 
function img:new(v)
 
	local fname = v[3]
 
	local spr
 
	if type(fname) == 'function' then
 
		if not std.functions[fname] then
 
			std.err("Non declared function", 2)
 
		end
 
		local s = fname(v)
 
		if not s then
 
			std.err("Can not construct sprite", 2)
 
		end
 
		spr = self:new_spr(v, s)
 
	elseif type(fname) == 'userdata' then
 
		spr = self:new_spr(v, fname)
 
	else
 
		if type(fname) ~= 'string' then
 
			std.err("Wrong filename in image");
 
		end;
 
	
 
		local s = self.cache:get(fname)
 
		if not s then
 
			local sp = sprite.new(fname)
 
			if not sp then
 
				std.err("Can not load sprite: "..fname, 2)
 
			end
 
			s = self.cache:add(fname, sp)
 
		end
 
		self.cache:put(fname)
 
		spr = self:new_spr(v, s)
 
	end;
 
	
 
  local fname = v[3]
 
  local spr
 
  if type(fname) == 'function' then
 
    if not std.functions[fname] then
 
      std.err("Non declared function", 2)
 
    end
 
    local s = fname(v)
 
    if not s then
 
      std.err("Can not construct sprite", 2)
 
    end
 
    spr = self:new_spr(v, s)
 
  elseif type(fname) == 'userdata' then
 
    spr = self:new_spr(v, fname)
 
  else
 
    if type(fname) ~= 'string' then
 
      std.err("Wrong filename in image");
 
    end;
 
  
 
    local s = self.cache:get(fname)
 
    if not s then
 
      local sp = sprite.new(fname)
 
      if not sp then
 
        std.err("Can not load sprite: "..fname, 2)
 
      end
 
      s = self.cache:add(fname, sp)
 
    end
 
    self.cache:put(fname)
 
    spr = self:new_spr(v, s)
 
  end;
 
  
 
  if spr.frame_data then
 
    spr._frame_cache = spr.frame_data;
 
  elseif spr.frames and spr.w and spr.h then
 
		local w, h = spr.sprite:size()
 
		local framesx = math.floor(w / spr.w)
 
		local framesy = math.floor(h / spr.h)
 
		
 
		spr._frame_cache = {}
 
		for i = 0, spr.frames - 1 do
 
			local xi = math.floor(i % framesx);
 
			local yi = math.floor(i / framesx);
 
			table.insert(spr._frame_cache, {
 
				x = xi * spr.w,
 
				y = yi * spr.h,
 
    local w, h = spr.sprite:size()
 
    local framesx = math.floor(w / spr.w)
 
    local framesy = math.floor(h / spr.h)
 
    
 
    spr._frame_cache = {}
 
    for i = 0, spr.frames - 1 do
 
      local xi = math.floor(i % framesx);
 
      local yi = math.floor(i / framesx);
 
      table.insert(spr._frame_cache, {
 
        x = xi * spr.w,
 
        y = yi * spr.h,
 
        w = spr.w,
 
        h = spr.h,
 
        dx = 0,
 
        dy = 0
 
			});
 
		end;
 
	end;
 
	
 
      });
 
    end;
 
  end;
 
  
 
  v.dx = v.x or 0;
 
  v.dy = v.y or 0;
 
  v.fw = v.w or nil;
 
@@ -297,7 +299,7 @@ function img:new(v)
 
  v.fx = 0;
 
  v.fy = 0;
 
  
 
	return spr
 
  return spr
 
end
 

	
 
local raw = {
 
@@ -315,20 +317,20 @@ end
 
function raw:clear()
 
end
 
function raw:render(v)
 
	if type(v.render) == 'function' then
 
		v.render(v)
 
	end
 
  if type(v.render) == 'function' then
 
    v.render(v)
 
  end
 
end
 
function raw:new(v)
 
	if type(v[3]) == 'function' then
 
		v[3](v)
 
		return v
 
	end
 
	return v
 
  if type(v[3]) == 'function' then
 
    v[3](v)
 
    return v
 
  end
 
  return v
 
end
 

	
 
local fnt = {
 
	cache = cache:new();
 
  cache = cache:new();
 
}
 

	
 
function fnt:update(v)
 
@@ -339,53 +341,53 @@ function fnt:update(v)
 
end;
 

	
 
function fnt:key(name, size)
 
	return name .. std.tostr(size)
 
  return name .. std.tostr(size)
 
end
 

	
 
function fnt:clear()
 
	self.cache:clear()
 
	for k, v in ipairs(self.cache.list) do
 
		v.value.cache:clear()
 
	end
 
  self.cache:clear()
 
  for k, v in ipairs(self.cache.list) do
 
    v.value.cache:clear()
 
  end
 
end
 

	
 
function fnt:_get(name, size)
 
	local f = self.cache:get(self:key(name, size))
 
	if not f then
 
		local fnt = sprite.fnt(name, size)
 
		if not fnt then
 
			std.err("Can not load font", 2)
 
		end
 
		f = { fnt = fnt, cache = cache:new(256, 16) }
 
		self.cache:add(self:key(name, size), f)
 
	end
 
	return f
 
  local f = self.cache:get(self:key(name, size))
 
  if not f then
 
    local fnt = sprite.fnt(name, size)
 
    if not fnt then
 
      std.err("Can not load font", 2)
 
    end
 
    f = { fnt = fnt, cache = cache:new(256, 16) }
 
    self.cache:add(self:key(name, size), f)
 
  end
 
  return f
 
end
 

	
 
function fnt:get(name, size)
 
	return self:_get(name, size).fnt
 
  return self:_get(name, size).fnt
 
end
 

	
 
function fnt:text_key(text, color, style)
 
	local key = std.tostr(color)..'#'..std.tostr(style or "")..'#'..tostring(text)
 
	return key
 
  local key = std.tostr(color)..'#'..std.tostr(style or "")..'#'..tostring(text)
 
  return key
 
end
 

	
 
function fnt:text(name, size, text, color, style)
 
	local fn = self:_get(name, size);
 
	local key = self:text_key(text, color, style)
 
	local sp = fn.cache:get(key)
 
	if not sp then
 
		sp = fn.fnt:text(text, color, style)
 
		fn.cache:add(key, sp)
 
	end
 
	fn.cache:put(key)
 
	self:put(name, size)
 
	return sp
 
  local fn = self:_get(name, size);
 
  local key = self:text_key(text, color, style)
 
  local sp = fn.cache:get(key)
 
  if not sp then
 
    sp = fn.fnt:text(text, color, style)
 
    fn.cache:add(key, sp)
 
  end
 
  fn.cache:put(key)
 
  self:put(name, size)
 
  return sp
 
end
 

	
 
function fnt:put(name, size)
 
	self.cache:put(self:key(name, size))
 
  self.cache:put(self:key(name, size))
 
end
 

	
 
local txt_mt = {
 
@@ -404,173 +406,173 @@ function txt_mt:update()
 
end;
 

	
 
function txt_mt:pages()
 
	return #self.__pages
 
  return #self.__pages
 
end
 

	
 
function txt_mt:page(nr)
 
	if nr == nil then
 
		return self.page_nr
 
	end
 
	if nr > self:pages() then
 
		return false
 
	end
 
	if nr < 1 then
 
		return false
 
	end
 
	if self.typewriter then
 
		self.finished = false
 
	end
 
	txt:make_page(self, nr)
 
	return true
 
  if nr == nil then
 
    return self.page_nr
 
  end
 
  if nr > self:pages() then
 
    return false
 
  end
 
  if nr < 1 then
 
    return false
 
  end
 
  if self.typewriter then
 
    self.finished = false
 
  end
 
  txt:make_page(self, nr)
 
  return true
 
end
 

	
 
function txt_mt:next_page()
 
	if self.typewriter and self.started then
 
		self.typewriter = false
 
		txt:make_page(self, self.page_nr or 1)
 
		self.typewriter = true
 
		self.started = false
 
		self.finished = true
 
		return
 
	end
 
	return self:page((self.page_nr or 1) + 1)
 
  if self.typewriter and self.started then
 
    self.typewriter = false
 
    txt:make_page(self, self.page_nr or 1)
 
    self.typewriter = true
 
    self.started = false
 
    self.finished = true
 
    return
 
  end
 
  return self:page((self.page_nr or 1) + 1)
 
end
 

	
 
local function make_align(l, width, t)
 
	if t == 'left' then
 
		return
 
	end
 
	if t == 'center' then
 
		local delta = math.floor((width - l.w) / 2)
 
		for _, v in ipairs(l) do
 
			v.x = v.x + delta
 
		end
 
		return
 
	end
 
	if t == 'right' then
 
		local delta = math.floor(width - l.w)
 
		for _, v in ipairs(l) do
 
			v.x = v.x + delta
 
		end
 
		return
 
	end
 
	if t == 'justify' then
 
		local n = 0
 
		for _, v in ipairs(l) do
 
			if not v.unbreak then
 
				n = n + 1
 
			end
 
		end
 
		n = n - 1
 
		if n == 0 then
 
			return
 
		end
 
		local delta = math.floor((width - l.w) / n)
 
		local ldelta = (width - l.w) % n
 
		local xx = 0
 
		for k, v in ipairs(l) do
 
			if k > 1 then
 
				if not v.unbreak then
 
					if k == 2 then
 
						xx = xx + ldelta
 
					end
 
					xx = xx + delta
 
				end
 
				v.x = v.x + xx
 
			end
 
		end
 
		return
 
	end
 
  if t == 'left' then
 
    return
 
  end
 
  if t == 'center' then
 
    local delta = math.floor((width - l.w) / 2)
 
    for _, v in ipairs(l) do
 
      v.x = v.x + delta
 
    end
 
    return
 
  end
 
  if t == 'right' then
 
    local delta = math.floor(width - l.w)
 
    for _, v in ipairs(l) do
 
      v.x = v.x + delta
 
    end
 
    return
 
  end
 
  if t == 'justify' then
 
    local n = 0
 
    for _, v in ipairs(l) do
 
      if not v.unbreak then
 
        n = n + 1
 
      end
 
    end
 
    n = n - 1
 
    if n == 0 then
 
      return
 
    end
 
    local delta = math.floor((width - l.w) / n)
 
    local ldelta = (width - l.w) % n
 
    local xx = 0
 
    for k, v in ipairs(l) do
 
      if k > 1 then
 
        if not v.unbreak then
 
          if k == 2 then
 
            xx = xx + ldelta
 
          end
 
          xx = xx + delta
 
        end
 
        v.x = v.x + xx
 
      end
 
    end
 
    return
 
  end
 
end
 

	
 
local function parse_xref(str)
 
	str = str:gsub("^{", ""):gsub("}$", "")
 
	local h = str:find("|", 1, true)
 
	if not h then
 
		return false, str
 
	end
 
	local l = str:sub(h + 1)
 
	h = str:sub(1, h - 1)
 
	return h, l
 
  str = str:gsub("^{", ""):gsub("}$", "")
 
  local h = str:find("|", 1, true)
 
  if not h then
 
    return false, str
 
  end
 
  local l = str:sub(h + 1)
 
  h = str:sub(1, h - 1)
 
  return h, l
 
end
 

	
 
local function preparse_links(text, links)
 
	local links = {}
 
	local link_id = 0
 
  local links = {}
 
  local link_id = 0
 

	
 
	local s = std.for_each_xref(text,
 
					function(str)
 
						local h, l = parse_xref(str)
 
						if not h then
 
							std.err("Wrong xref: "..str, 2)
 
						end
 
						local o = ""
 
						link_id = link_id + 1
 
						for w in l:gmatch("[^ \t]+") do
 
							if o ~= '' then o = o ..' ' end
 
							table.insert(links, {h, w, link_id})
 
							o = o .. "\3".. std.tostr(#links)  .."\4"
 
						end
 
						return o
 
	end)
 
	s = s:gsub('\\?'..'[{}]', { ['\\{'] = '{', ['\\}'] = '}' })
 
	return s, links
 
  local s = std.for_each_xref(text,
 
          function(str)
 
            local h, l = parse_xref(str)
 
            if not h then
 
              std.err("Wrong xref: "..str, 2)
 
            end
 
            local o = ""
 
            link_id = link_id + 1
 
            for w in l:gmatch("[^ \t]+") do
 
              if o ~= '' then o = o ..' ' end
 
              table.insert(links, {h, w, link_id})
 
              o = o .. "\3".. std.tostr(#links)  .."\4"
 
            end
 
            return o
 
  end)
 
  s = s:gsub('\\?'..'[{}]', { ['\\{'] = '{', ['\\}'] = '}' })
 
  return s, links
 
end
 

	
 
function txt:make_page(v, nr)
 
	local page = nr or v.page_nr or 1
 
	local lines = v.__lines
 
	local spr = v.sprite
 
	local size = v.size or std.tonum(theme.get 'win.fnt.size')
 
	local color = v.color or theme.get('win.col.fg')
 
	local link_color = v.color_link or theme.get('win.col.link')
 
	local alink_color = v.color_alink or theme.get('win.col.alink')
 
	local font = v.font or theme.get('win.fnt.name')
 
	v.page_nr = page
 
	if v.w == 0 or v.h == 0 then
 
		return
 
	end
 
	if not v.__spr_blank then
 
		v.__spr_blank = sprite.new(v.w, v.h)
 
	end
 
	local lnr = v.__pages[page]
 
	v.__spr_blank:copy(v.sprite)
 
	if #lines == 0 then return end
 
	local off = lines[lnr].y
 
	v.__offset = off
 
	for _ = lnr, #lines do
 
		local l = lines[_]
 
		if l.y + l.h - off > v.h or l.pgbrk then
 
			break
 
		end
 
		for _, w in ipairs(l) do
 
			if not w.spr and w.w > 0 then
 
				w.spr = fnt:text(font, size, w.txt,
 
						 w.id and link_color or color, w.style)
 
			end
 
			if w.id then -- link
 
				if not w.link then
 
					w.link = fnt:text(font, size, w.txt, alink_color, w.style)
 
				end
 
			else
 
				w.link = nil
 
			end
 
			if w.spr then
 
				w.spr:copy(v.sprite, w.x, w.y - off)
 
			end
 
		end
 
	end
 
	if v.typewriter then
 
		v.step = 0; -- typewriter effect
 
		if not v.__spr_blank then
 
			v.__spr_blank = sprite.new(v.w, v.h)
 
		end
 
		if not v.finished then
 
			v.started = true
 
			v.finished = false
 
			v.__spr_blank:copy(v.sprite)
 
		end
 
	end
 
  local page = nr or v.page_nr or 1
 
  local lines = v.__lines
 
  local spr = v.sprite
 
  local size = v.size or std.tonum(theme.get 'win.fnt.size')
 
  local color = v.color or theme.get('win.col.fg')
 
  local link_color = v.color_link or theme.get('win.col.link')
 
  local alink_color = v.color_alink or theme.get('win.col.alink')
 
  local font = v.font or theme.get('win.fnt.name')
 
  v.page_nr = page
 
  if v.w == 0 or v.h == 0 then
 
    return
 
  end
 
  if not v.__spr_blank then
 
    v.__spr_blank = sprite.new(v.w, v.h)
 
  end
 
  local lnr = v.__pages[page]
 
  v.__spr_blank:copy(v.sprite)
 
  if #lines == 0 then return end
 
  local off = lines[lnr].y
 
  v.__offset = off
 
  for _ = lnr, #lines do
 
    local l = lines[_]
 
    if l.y + l.h - off > v.h or l.pgbrk then
 
      break
 
    end
 
    for _, w in ipairs(l) do
 
      if not w.spr and w.w > 0 then
 
        w.spr = fnt:text(font, size, w.txt,
 
             w.id and link_color or color, w.style)
 
      end
 
      if w.id then -- link
 
        if not w.link then
 
          w.link = fnt:text(font, size, w.txt, alink_color, w.style)
 
        end
 
      else
 
        w.link = nil
 
      end
 
      if w.spr then
 
        w.spr:copy(v.sprite, w.x, w.y - off)
 
      end
 
    end
 
  end
 
  if v.typewriter then
 
    v.step = 0; -- typewriter effect
 
    if not v.__spr_blank then
 
      v.__spr_blank = sprite.new(v.w, v.h)
 
    end
 
    if not v.finished then
 
      v.started = true
 
      v.finished = false
 
      v.__spr_blank:copy(v.sprite)
 
    end
 
  end
 
end
 

	
 
function simple_txt:update(v)
 
@@ -585,23 +587,23 @@ function simple_txt:update(v)
 
end;
 

	
 
function simple_txt:new(v)
 
	local lines = v[3];
 
  local lines = v[3];
 

	
 
	v.style = v.style or 0;
 
	v.font = v.font or theme.get('win.fnt.name');
 
	v.size = v.size or std.tonum(theme.get 'win.fnt.size');
 
	
 
	v.fnt = fnt:get(v.font, v.size);	
 
	v.sprite = sprite.new(v.w, v.h);
 
	
 
	v.bgcolor = v.bgcolor or '#000000'
 
	
 
	v.sprite:fill(v.bgcolor);
 
	
 
	v.lh = v.fnt:height();
 
  v.style = v.style or 0;
 
  v.font = v.font or theme.get('win.fnt.name');
 
  v.size = v.size or std.tonum(theme.get 'win.fnt.size');
 
  
 
  v.fnt = fnt:get(v.font, v.size);  
 
  v.sprite = sprite.new(v.w, v.h);
 
  
 
  v.bgcolor = v.bgcolor or '#000000'
 
  
 
  v.sprite:fill(v.bgcolor);
 
  
 
  v.lh = v.fnt:height();
 
  v.lc = math.floor(v.h / v.lh);
 
	
 
	v.repaint = {0, v.lc}
 
  
 
  v.repaint = {0, v.lc}
 
  
 
  v.dx = v.x or 0;
 
  v.dy = v.y or 0;
 
@@ -609,14 +611,14 @@ function simple_txt:new(v)
 
  v.fh = v.h or nil;
 
  v.fx = 0;
 
  v.fy = 0;
 
	
 
	v = img:new_spr(v, v.sprite);
 
	v.drop_line = simple_txt_drop_line;
 
	v.drop_all = simple_txt_drop_all;
 
	v.insert_line = simple_txt_insert_line;
 
	v.replace_line = simple_txt_replace_line;
 
  
 
  v = img:new_spr(v, v.sprite);
 
  v.drop_line = simple_txt_drop_line;
 
  v.drop_all = simple_txt_drop_all;
 
  v.insert_line = simple_txt_insert_line;
 
  v.replace_line = simple_txt_replace_line;
 
  v.setrepaint = simple_txt_set_repaint;
 
	return v;
 
  return v;
 
end;
 

	
 
function simple_txt_set_repaint(v, top, bottom)
 
@@ -650,7 +652,7 @@ function simple_txt:render(v)
 
    v.repaint = nil;
 
  end;
 
  
 
	return img:render(v)
 
  return img:render(v)
 
end;
 

	
 
function simple_txt:delete(v)
 
@@ -658,468 +660,468 @@ function simple_txt:delete(v)
 
end;
 

	
 
function simple_txt_drop_all(v)
 
	v[3] = {};
 
	v.cy = 0;
 
  v[3] = {};
 
  v.cy = 0;
 
  v:setrepaint(1, v.lc);
 
end;
 

	
 
function simple_txt_drop_line(v)
 
	table.remove(v[3], 1);
 
	v:setrepaint(1, v.lc);
 
  table.remove(v[3], 1);
 
  v:setrepaint(1, v.lc);
 
end;
 

	
 
function simple_txt_insert_line(v, l)
 
	while #v[3] == v.lc do
 
		v:drop_line(v);
 
	end;
 
	table.insert(v[3], l);
 
  while #v[3] == v.lc do
 
    v:drop_line(v);
 
  end;
 
  table.insert(v[3], l);
 
  v:setrepaint(#v[3], #v[3]);
 
end;
 

	
 
function simple_txt_replace_line(v, l)
 
	if #v[3] < 1 then
 
		simple_txt_insert_line(v, l);
 
		return;
 
	end;
 
	v[3][#v[3]] = l
 
	
 
	v:setrepaint(#v[3], #v[3]);
 
  if #v[3] < 1 then
 
    simple_txt_insert_line(v, l);
 
    return;
 
  end;
 
  v[3][#v[3]] = l
 
  
 
  v:setrepaint(#v[3], #v[3]);
 
end;
 

	
 
function txt:new(v)
 
	local text = v[3]
 
	if type(text) == 'function' then
 
		if not std.functions[text] then
 
			std.err("Non declared function", 2)
 
		end
 
		text = text(v)
 
	end
 
	if type(text) ~= 'string' then
 
		std.err("Wrong text in txt decorator")
 
	end
 
  local text = v[3]
 
  if type(text) == 'function' then
 
    if not std.functions[text] then
 
      std.err("Non declared function", 2)
 
    end
 
    text = text(v)
 
  end
 
  if type(text) ~= 'string' then
 
    std.err("Wrong text in txt decorator")
 
  end
 

	
 
	local align = v.align or 'left'
 
	local style = v.style or 0
 
	local font = v.font or theme.get('win.fnt.name')
 
	local intvl = v.interval or std.tonum(theme.get 'win.fnt.height')
 
	local size = v.size or std.tonum(theme.get 'win.fnt.size')
 
  local align = v.align or 'left'
 
  local style = v.style or 0
 
  local font = v.font or theme.get('win.fnt.name')
 
  local intvl = v.interval or std.tonum(theme.get 'win.fnt.height')
 
  local size = v.size or std.tonum(theme.get 'win.fnt.size')
 

	
 
	local x, y = 0, 0
 
	v.fnt = fnt:get(font, size)
 
	local spw, sph = v.fnt:size(" ")
 
  local x, y = 0, 0
 
  v.fnt = fnt:get(font, size)
 
  local spw, sph = v.fnt:size(" ")
 

	
 
	local lines = {}
 
	local line = { h = v.fnt:height() }
 
	local link_list = {}
 
	local maxw = v.w
 
	local maxh = v.h
 
	local W = 0
 
	local H = 0
 
  local lines = {}
 
  local line = { h = v.fnt:height() }
 
  local link_list = {}
 
  local maxw = v.w
 
  local maxh = v.h
 
  local W = 0
 
  local H = 0
 

	
 
	local function newline()
 
		line.y = y
 
		line.w = 0
 
		if #line > 0 then
 
			line.w = line[#line].x + line[#line].w
 
		end
 
		local h = v.fnt:height()
 
		for _, w in ipairs(line) do
 
			if w.h > h then
 
				h = w.h
 
			end
 
		end
 
		y = y + h * intvl
 
		if y > H then
 
			H = y
 
		end
 
		
 
		if #line == 1 and line[1].txt == '[break]' then line.pgbrk = true end
 
		table.insert(lines, line)
 
		
 
		line = { h = v.fnt:height() }
 
		x = 0
 
		if maxh and y > maxh then
 
			return true
 
		end
 
	end
 
  local function newline()
 
    line.y = y
 
    line.w = 0
 
    if #line > 0 then
 
      line.w = line[#line].x + line[#line].w
 
    end
 
    local h = v.fnt:height()
 
    for _, w in ipairs(line) do
 
      if w.h > h then
 
        h = w.h
 
      end
 
    end
 
    y = y + h * intvl
 
    if y > H then
 
      H = y
 
    end
 
    
 
    if #line == 1 and line[1].txt == '[break]' then line.pgbrk = true end
 
    table.insert(lines, line)
 
    
 
    line = { h = v.fnt:height() }
 
    x = 0
 
    if maxh and y > maxh then
 
      return true
 
    end
 
  end
 

	
 
	local links
 
	text, links = preparse_links(text)
 
	local styles = {}
 
	local ww
 
	for w in text:gmatch("[^ \t]+") do
 
		while w and w ~= '' do
 
			local s, _ = w:find("\n", 1, true)
 
			if not s then
 
				ww = w
 
				w = false
 
			elseif s > 1 then
 
				ww = w:sub(1, s - 1)
 
				w = w:sub(s)
 
			else -- s == 1
 
				ww = '\n'
 
				w = w:sub(2)
 
			end
 
			if ww == '\n' then
 
				newline()
 
			else
 
				local t, act
 
				local applist = {}
 
				local xx = 0
 
  local links
 
  text, links = preparse_links(text)
 
  local styles = {}
 
  local ww
 
  for w in text:gmatch("[^ \t]+") do
 
    while w and w ~= '' do
 
      local s, _ = w:find("\n", 1, true)
 
      if not s then
 
        ww = w
 
        w = false
 
      elseif s > 1 then
 
        ww = w:sub(1, s - 1)
 
        w = w:sub(s)
 
      else -- s == 1
 
        ww = '\n'
 
        w = w:sub(2)
 
      end
 
      if ww == '\n' then
 
        newline()
 
      else
 
        local t, act
 
        local applist = {}
 
        local xx = 0
 

	
 
				while ww and ww ~= '' do
 
					s, _ = ww:find("\3[0-9]+\4", 1)
 
					local id
 
					if s == 1 then
 
						local n = std.tonum(ww:sub(s + 1, _ - 1))
 
						local ll = links[n]
 
						act, t, id = ll[1], ll[2], ll[3]
 
						ww = ww:sub(_ + 1)
 
					elseif s then
 
						t = ww:sub(1, s - 1)
 
						ww = ww:sub(s)
 
					else
 
						t = ww
 
						ww = false
 
					end
 
					while t:find("^%[[ibu]%]") do
 
						table.insert(styles, t:sub(2, 2))
 
						t = t:gsub("^%[[ibu]%]", "")
 
					end
 
        while ww and ww ~= '' do
 
          s, _ = ww:find("\3[0-9]+\4", 1)
 
          local id
 
          if s == 1 then
 
            local n = std.tonum(ww:sub(s + 1, _ - 1))
 
            local ll = links[n]
 
            act, t, id = ll[1], ll[2], ll[3]
 
            ww = ww:sub(_ + 1)
 
          elseif s then
 
            t = ww:sub(1, s - 1)
 
            ww = ww:sub(s)
 
          else
 
            t = ww
 
            ww = false
 
          end
 
          while t:find("^%[[ibu]%]") do
 
            table.insert(styles, t:sub(2, 2))
 
            t = t:gsub("^%[[ibu]%]", "")
 
          end
 

	
 
					local st = style
 
          local st = style
 

	
 
					local m = { b = 1, i = 2, u = 4 }
 
          local m = { b = 1, i = 2, u = 4 }
 

	
 
					for i = 1, #styles do
 
						st = st + m[styles[i]]
 
					end
 
          for i = 1, #styles do
 
            st = st + m[styles[i]]
 
          end
 

	
 
					while t:find("%[/[ibu]%]$") do
 
						table.remove(styles, #styles)
 
						t = t:gsub("%[/[ibu]%]$", "")
 
					end
 
					local width, height = v.fnt:size(t, st)
 
					if height > line.h then
 
						line.h = height
 
					end
 
          while t:find("%[/[ibu]%]$") do
 
            table.remove(styles, #styles)
 
            t = t:gsub("%[/[ibu]%]$", "")
 
          end
 
          local width, height = v.fnt:size(t, st)
 
          if height > line.h then
 
            line.h = height
 
          end
 

	
 
					if t == '[pause]' then
 
						width = 0
 
					end
 
          if t == '[pause]' then
 
            width = 0
 
          end
 

	
 
					local witem = { style = st,
 
							action = act, id = id, x = xx, y = y,
 
							w = width, h = height, txt = t }
 
					if id then
 
						table.insert(link_list, witem)
 
					end
 
					table.insert(applist, witem)
 
					xx = xx + width
 
				end
 
				local sx = 0;
 
          local witem = { style = st,
 
              action = act, id = id, x = xx, y = y,
 
              w = width, h = height, txt = t }
 
          if id then
 
            table.insert(link_list, witem)
 
          end
 
          table.insert(applist, witem)
 
          xx = xx + width
 
        end
 
        local sx = 0;
 

	
 
				if maxw and x + xx + spw > maxw and #line > 0 then
 
					newline()
 
				else
 
					sx = x
 
				end
 
        if maxw and x + xx + spw > maxw and #line > 0 then
 
          newline()
 
        else
 
          sx = x
 
        end
 

	
 
				for k, v in ipairs(applist) do
 
					v.y = y
 
					v.x = v.x + sx
 
					x = v.x + v.w
 
					if k ~= 1 then
 
						v.unbreak = true
 
					end
 
					v.line = line
 
					table.insert(line, v)
 
				end
 
				if #applist > 0 then
 
					for i = #applist, 1, -1 do
 
						if applist[i].w > 0 then
 
							x = x + spw
 
							break
 
						end
 
					end
 
				end
 
				if x > W then
 
					W = x
 
				end
 
			end
 
		end
 
	end
 
        for k, v in ipairs(applist) do
 
          v.y = y
 
          v.x = v.x + sx
 
          x = v.x + v.w
 
          if k ~= 1 then
 
            v.unbreak = true
 
          end
 
          v.line = line
 
          table.insert(line, v)
 
        end
 
        if #applist > 0 then
 
          for i = #applist, 1, -1 do
 
            if applist[i].w > 0 then
 
              x = x + spw
 
              break
 
            end
 
          end
 
        end
 
        if x > W then
 
          W = x
 
        end
 
      end
 
    end
 
  end
 

	
 
	if #line > 0 then
 
		newline()
 
	end
 
  if #line > 0 then
 
    newline()
 
  end
 

	
 
	if (maxw or W) ~= 0 and (maxh or H) ~= 0 then
 
		v.sprite = sprite.new(maxw or W, maxh or H)
 
	end
 
	local pages = {}
 
	local off = 0;
 
	if #lines >= 1 then
 
		table.insert(pages, 1)
 
	end
 
	local brk
 
	for _, l in ipairs(lines) do
 
		l.page = #pages
 
		make_align(l, maxw or W, align)
 
		if l.pgbrk then
 
			brk = true
 
		elseif (l.y + l.h - off > (maxh or H)) or brk then
 
			off = l.y
 
			table.insert(pages, _)
 
			l.page = l.page + 1
 
			brk = false
 
		else
 
			brk = false
 
		end
 
	end
 
	
 
	if #pages > 1 then
 
		local next = pixels.new(sph, sph)
 
  if (maxw or W) ~= 0 and (maxh or H) ~= 0 then
 
    v.sprite = sprite.new(maxw or W, maxh or H)
 
  end
 
  local pages = {}
 
  local off = 0;
 
  if #lines >= 1 then
 
    table.insert(pages, 1)
 
  end
 
  local brk
 
  for _, l in ipairs(lines) do
 
    l.page = #pages
 
    make_align(l, maxw or W, align)
 
    if l.pgbrk then
 
      brk = true
 
    elseif (l.y + l.h - off > (maxh or H)) or brk then
 
      off = l.y
 
      table.insert(pages, _)
 
      l.page = l.page + 1
 
      brk = false
 
    else
 
      brk = false
 
    end
 
  end
 
  
 
  if #pages > 1 then
 
    local next = pixels.new(sph, sph)
 

	
 
		local r, g, b = color2rgb(v.color or theme.get('win.col.fg'))
 
    local r, g, b = color2rgb(v.color or theme.get('win.col.fg'))
 

	
 
		next:fill_poly({0, 0, sph - 1, 0, sph / 2, sph / 2 - 1}, r, g, b)
 
		next:polyAA({0, 0, sph - 1, 0, sph / 2, sph / 2 - 1}, r, g, b)
 
    next:fill_poly({0, 0, sph - 1, 0, sph / 2, sph / 2 - 1}, r, g, b)
 
    next:polyAA({0, 0, sph - 1, 0, sph / 2, sph / 2 - 1}, r, g, b)
 

	
 
		v.btn = next:sprite()
 
	end;
 
	
 
	v.__pages = pages
 
	v.__lines = lines
 
	v.__link_list = link_list
 
	if v.sprite then
 
		v.w, v.h = v.sprite:size()
 
	else
 
		v.w, v.h = 0, 0
 
	end
 
	if #link_list > 0 or #pages > 1 then
 
		v.click = true
 
	end
 
	std.setmt(v, txt_mt)
 
	txt_mt.__index = txt_mt
 
	self:make_page(v)
 
	return img:new_spr(v, v.sprite)
 
    v.btn = next:sprite()
 
  end;
 
  
 
  v.__pages = pages
 
  v.__lines = lines
 
  v.__link_list = link_list
 
  if v.sprite then
 
    v.w, v.h = v.sprite:size()
 
  else
 
    v.w, v.h = 0, 0
 
  end
 
  if #link_list > 0 or #pages > 1 then
 
    v.click = true
 
  end
 
  std.setmt(v, txt_mt)
 
  txt_mt.__index = txt_mt
 
  self:make_page(v)
 
  return img:new_spr(v, v.sprite)
 
end
 

	
 
function txt:make_tw(v, step)
 
	local n = 0
 
	local spr = v.sprite
 
	local lnr = v.__pages[v.page_nr]
 
	for _ = lnr, #v.__lines do
 
		if n >= step then
 
			break
 
		end
 
		local l = v.__lines[_]
 
		if l.y + l.h - v.__offset > v.h or l.pgbrk then
 
			v.started = false
 
			v.finished = true
 
			break
 
		end
 
		for _, w in ipairs(l) do
 
			if n >= step then
 
				break
 
			end
 
			if w.txt:len() + n <= step then
 
				n = n + w.txt:len()
 
				n = n + 1
 
				if n >= step and w.spr then
 
					w.spr:copy(spr, w.x, w.y - v.__offset)
 
				end
 
			else
 
				local nm = step - n
 
				local i = 1
 
				while i < nm do
 
					i = i + utf_ff(w.txt, i)
 
				end
 
				step = step + i - nm
 
				local txt = w.txt:sub(1, i - 1)
 
				local ww, hh = v.fnt:size(txt)
 
				if w.spr then
 
					if type(decor.beep) == 'function' then
 
						decor.beep(v)
 
					end
 
					w.spr:copy(0, 0, ww, hh, spr, w.x, w.y - v.__offset)
 
				end
 
				n = step
 
			end
 
		end
 
	end
 
	v.step = n
 
	if n < step then
 
		v.started = false
 
		v.finished = true
 
	end
 
	return step > n
 
  local n = 0
 
  local spr = v.sprite
 
  local lnr = v.__pages[v.page_nr]
 
  for _ = lnr, #v.__lines do
 
    if n >= step then
 
      break
 
    end
 
    local l = v.__lines[_]
 
    if l.y + l.h - v.__offset > v.h or l.pgbrk then
 
      v.started = false
 
      v.finished = true
 
      break
 
    end
 
    for _, w in ipairs(l) do
 
      if n >= step then
 
        break
 
      end
 
      if w.txt:len() + n <= step then
 
        n = n + w.txt:len()
 
        n = n + 1
 
        if n >= step and w.spr then
 
          w.spr:copy(spr, w.x, w.y - v.__offset)
 
        end
 
      else
 
        local nm = step - n
 
        local i = 1
 
        while i < nm do
 
          i = i + utf_ff(w.txt, i)
 
        end
 
        step = step + i - nm
 
        local txt = w.txt:sub(1, i - 1)
 
        local ww, hh = v.fnt:size(txt)
 
        if w.spr then
 
          if type(decor.beep) == 'function' then
 
            decor.beep(v)
 
          end
 
          w.spr:copy(0, 0, ww, hh, spr, w.x, w.y - v.__offset)
 
        end
 
        n = step
 
      end
 
    end
 
  end
 
  v.step = n
 
  if n < step then
 
    v.started = false
 
    v.finished = true
 
  end
 
  return step > n
 
end
 

	
 
function txt:link(v, x, y)
 
	if v.typewriter and v.started then
 
		return
 
	end
 
	local off = v.__offset or 0
 
	y = y + off
 
  if v.typewriter and v.started then
 
    return
 
  end
 
  local off = v.__offset or 0
 
  y = y + off
 

	
 
	for _, w in ipairs(v.__link_list) do
 
		if w.line.page == (v.page_nr or 1) then
 
			if x >= w.x and y >= w.y then
 
				if x < w.x + w.w and y < w.y + w.h then
 
					return w, _
 
				end
 
				local next = v.__link_list[_ + 1]
 
				if next and next.id == w.id and
 
				x < next.x and y < next.y + next.h then
 
					return w, _
 
				end
 
			end
 
		end
 
	end
 
  for _, w in ipairs(v.__link_list) do
 
    if w.line.page == (v.page_nr or 1) then
 
      if x >= w.x and y >= w.y then
 
        if x < w.x + w.w and y < w.y + w.h then
 
          return w, _
 
        end
 
        local next = v.__link_list[_ + 1]
 
        if next and next.id == w.id and
 
        x < next.x and y < next.y + next.h then
 
          return w, _
 
        end
 
      end
 
    end
 
  end
 
end
 

	
 
function txt:click(v, press, x, y)
 
	local w = self:link(v, x, y)
 
	if w then
 
		return std.cmd_parse(w.action)
 
	end
 
	return {}
 
  local w = self:link(v, x, y)
 
  if w then
 
    return std.cmd_parse(w.action)
 
  end
 
  return {}
 
end
 

	
 
function txt:render(v)
 
	if v.w == 0 or v.h == 0 then
 
		return
 
	end
 
	if v.typewriter and v.started then
 
		local d = instead.ticks() - (v.__last_tw or 0)
 
		decor.dirty = true
 
		if d > (v.delay or 25) then
 
			v.__last_tw = instead.ticks()
 
			v.step = (v.step or 0) + (v.speed or 1)
 
			txt:make_tw(v, v.step)
 
		end
 
		img:render(v)
 
		return
 
	end
 
	local x, y = instead.mouse_pos()
 
	x = x - v.x + v.xc
 
	y = y - v.y + v.yc
 
	local w = txt:link(v, x, y)
 
  if v.w == 0 or v.h == 0 then
 
    return
 
  end
 
  if v.typewriter and v.started then
 
    local d = instead.ticks() - (v.__last_tw or 0)
 
    decor.dirty = true
 
    if d > (v.delay or 25) then
 
      v.__last_tw = instead.ticks()
 
      v.step = (v.step or 0) + (v.speed or 1)
 
      txt:make_tw(v, v.step)
 
    end
 
    img:render(v)
 
    return
 
  end
 
  local x, y = instead.mouse_pos()
 
  x = x - v.x + v.xc
 
  y = y - v.y + v.yc
 
  local w = txt:link(v, x, y)
 

	
 
	local action = w and w.action or false
 
	local id = w and w.id or false
 
	
 
	for _, w in ipairs(v.__link_list) do
 
		if w.line.page == (v.page_nr or 1) then
 
			if w.id == id then
 
				if not w.__active then
 
					w.__active = true
 
					w.link:copy(v.sprite, w.x, w.y - v.__offset)
 
					decor.dirty = true
 
				end
 
			else
 
				if w.__active then
 
					w.__active = false
 
					w.spr:copy(v.sprite, w.x, w.y - v.__offset)
 
					decor.dirty = true
 
				end
 
			end
 
		end
 
	end
 
	
 
	img:render(v)
 
	if v.btn and v:page() < v:pages() then
 
		local w, h = v.btn:size()
 
		v.btn:draw(sprite.scr(), v.x + v.w - v.xc - w, v.y + v.h - v.yc - h)
 
	end;
 
  local action = w and w.action or false
 
  local id = w and w.id or false
 
  
 
  for _, w in ipairs(v.__link_list) do
 
    if w.line.page == (v.page_nr or 1) then
 
      if w.id == id then
 
        if not w.__active then
 
          w.__active = true
 
          w.link:copy(v.sprite, w.x, w.y - v.__offset)
 
          decor.dirty = true
 
        end
 
      else
 
        if w.__active then
 
          w.__active = false
 
          w.spr:copy(v.sprite, w.x, w.y - v.__offset)
 
          decor.dirty = true
 
        end
 
      end
 
    end
 
  end
 
  
 
  img:render(v)
 
  if v.btn and v:page() < v:pages() then
 
    local w, h = v.btn:size()
 
    v.btn:draw(sprite.scr(), v.x + v.w - v.xc - w, v.y + v.h - v.yc - h)
 
  end;
 
end
 

	
 
function txt:delete(v)
 
	if v.sprite then
 
		fnt:put(v.font or theme.get('win.fnt.name'), v.size)
 
	end
 
  if v.sprite then
 
    fnt:put(v.font or theme.get('win.fnt.name'), v.size)
 
  end
 
end
 

	
 
decor = obj {
 
	nam = '@decor';
 
	{
 
		img = img;
 
		fnt = fnt;
 
		txt = txt;
 
		simple_txt = simple_txt;
 
		raw = raw;
 
		dirty = false;
 
  nam = '@decor';
 
  {
 
    img = img;
 
    fnt = fnt;
 
    txt = txt;
 
    simple_txt = simple_txt;
 
    raw = raw;
 
    dirty = false;
 
    needsort = false;
 
		objects = {
 
		};
 
		bgcol = false;
 
		bgsprite = false;
 
		bgr = false;
 
	}
 
    objects = {
 
    };
 
    bgcol = false;
 
    bgsprite = false;
 
    bgr = false;
 
  }
 
}
 

	
 
function decor:zap()
 
	local l = {}
 
	for k, v in pairs(self.objects) do
 
		table.insert(l, k)
 
	end
 
	for _, name in ipairs(l) do
 
		local tt = self.objects[name].type
 
		self[tt]:delete(self.objects[name])
 
		self.objects[name] = nil
 
	end
 
  local l = {}
 
  for k, v in pairs(self.objects) do
 
    table.insert(l, k)
 
  end
 
  for _, name in ipairs(l) do
 
    local tt = self.objects[name].type
 
    self[tt]:delete(self.objects[name])
 
    self.objects[name] = nil
 
  end
 
end
 

	
 
function decor:new(v)
 
	if type(v) == 'string' then
 
		v = self.objects[v]
 
	end
 
	local name = v[1]
 
	local t = v[2]
 
	if not v.z then
 
		v.z = 0
 
	end
 
	if type(name) ~= 'string' then
 
		std.err("Wrong parameter to decor:new(): name", 2)
 
	end
 
	if self.objects[name] then
 
		local tt = self.objects[name].type
 
		self[tt]:delete(self.objects[name])
 
	end
 
	if t == nil then
 
		self.objects[name] = nil
 
		return
 
	end
 
	if type(t) ~= 'string' then
 
		std.err("Wrong parameter to decor:new(): type", 2)
 
	end
 
	if not self[t] or type(self[t].new) ~= 'function' then
 
		std.err("Wrong type decorator: "..t, 2)
 
	end
 
	v.name = name
 
	v.type = t
 
	self.objects[name] = self[t]:new(v)
 
	return v
 
  if type(v) == 'string' then
 
    v = self.objects[v]
 
  end
 
  local name = v[1]
 
  local t = v[2]
 
  if not v.z then
 
    v.z = 0
 
  end
 
  if type(name) ~= 'string' then
 
    std.err("Wrong parameter to decor:new(): name", 2)
 
  end
 
  if self.objects[name] then
 
    local tt = self.objects[name].type
 
    self[tt]:delete(self.objects[name])
 
  end
 
  if t == nil then
 
    self.objects[name] = nil
 
    return
 
  end
 
  if type(t) ~= 'string' then
 
    std.err("Wrong parameter to decor:new(): type", 2)
 
  end
 
  if not self[t] or type(self[t].new) ~= 'function' then
 
    std.err("Wrong type decorator: "..t, 2)
 
  end
 
  v.name = name
 
  v.type = t
 
  self.objects[name] = self[t]:new(v)
 
  return v
 
end;
 

	
 
function decor:get(n)
 
	if type(n) ~= 'string' then
 
		std.err("Wrong parameter to decor:get(): name", 2)
 
	end
 
	return self.objects[n]
 
  if type(n) ~= 'string' then
 
    std.err("Wrong parameter to decor:get(): name", 2)
 
  end
 
  return self.objects[n]
 
end
 

	
 
local list = {}
 
local after_list = {}
 

	
 
function decor:process()
 
	local t = instead.ticks()
 
	for _, v in pairs(self.objects) do
 
  local t = instead.ticks()
 
  for _, v in pairs(self.objects) do
 
    local r = self[v.type]:update(v);
 
    decor.dirty = decor.dirty or r
 
	end
 
  end
 
  deltaticks = nil;
 
end
 

	
 
@@ -1150,123 +1152,124 @@ function decor:sort()
 
end
 

	
 
function decor:render()
 
	if not decor.dirty then
 
		return
 
	end
 
	decor.dirty = false
 
	for _, v in ipairs(list) do
 
		self[v.type]:render(v)
 
	end
 
  if not decor.dirty then
 
    return
 
  end
 
  decor.dirty = false
 
  for _, v in ipairs(list) do
 
    self[v.type]:render(v)
 
  end
 
end
 

	
 
std.mod_init(function(s)
 
	local oldrender = sprite.render_callback()
 
	sprite.render_callback(
 
		function()
 
			for _, v in ipairs(after_list) do
 
				decor[v.type]:render(v)
 
			end
 
			if oldrender then
 
				oldrender()
 
			end
 
		end)
 
  local oldrender = sprite.render_callback()
 
  sprite.render_callback(
 
    function()
 
      for _, v in ipairs(after_list) do
 
        decor[v.type]:render(v)
 
      end
 
      if oldrender then
 
        oldrender()
 
      end
 
    end)
 
end)
 

	
 
function decor:click_filter(press, x, y)
 
	local c = {}
 
	for _, v in pairs(self.objects) do
 
		if v.click and x >= v.x - v.xc and y >= v.y - v.yc and
 
		x < v.x - v.xc + v.w and y < v.y - v.yc + v.h then
 
			if v[2] == 'txt' then
 
				if not press then
 
					table.insert(c, v)
 
				end
 
			else
 
				table.insert(c, v)
 
			end
 
		end
 
	end
 
	if #c == 0 then
 
		return false
 
	end
 
	local e = c[1]
 
	for _, v in ipairs(c) do
 
		if v.z == e.z then
 
			if v.name > e.name then
 
				e = v
 
			end
 
		elseif v.z < e.z then
 
			e = v
 
		end
 
	end
 
	return e
 
  local c = {}
 
  for _, v in pairs(self.objects) do
 
    if v.click and x >= v.x - v.xc and y >= v.y - v.yc and
 
    x < v.x - v.xc + v.w and y < v.y - v.yc + v.h then
 
      if v[2] == 'txt' then
 
        if not press then
 
          table.insert(c, v)
 
        end
 
      else
 
        table.insert(c, v)
 
      end
 
    end
 
  end
 
  if #c == 0 then
 
    return false
 
  end
 
  local e = c[1]
 
  for _, v in ipairs(c) do
 
    if v.z == e.z then
 
      if v.name > e.name then
 
        e = v
 
      end
 
    elseif v.z < e.z then
 
      e = v
 
    end
 
  end
 
  return e
 
end
 

	
 
function decor:cache_clear()
 
	self.img:clear();
 
	self.fnt:clear();
 
  self.img:clear();
 
  self.fnt:clear();
 
end
 

	
 
function decor:load()
 
	for _, v in pairs(self.objects) do
 
		D(v)
 
	end;
 
  for _, v in pairs(self.objects) do
 
    D(v)
 
  end;
 
end
 
std.mod_cmd(
 
	function(cmd)
 
		if cmd[1] == '@decor_click' then
 
			local nam = cmd[2]
 
			local e = decor.objects[nam]
 
			local t = e[2]
 
			local press, x, y, btn = cmd[3], cmd[4], cmd[5], cmd[6]
 
			local r, v
 
			local a
 
			if type(decor[t].click) == 'function' then
 
				a = decor[t]:click(e, press, x, y, btn)
 
			else
 
				a = { }
 
			end
 
			table.insert(a, 1, nam)
 
			table.insert(a, 2, press)
 
			table.insert(a, 3, x - e.xc)
 
			table.insert(a, 4, y - e.yc)
 
			table.insert(a, 5, btn)
 
  function(cmd)
 
    if cmd[1] == '@decor_click' then
 
      local nam = cmd[2]
 
      local e = decor.objects[nam]
 
      local t = e[2]
 
      local press, x, y, btn = cmd[3], cmd[4], cmd[5], cmd[6]
 
      local r, v
 
      local a
 
      if type(decor[t].click) == 'function' then
 
        a = decor[t]:click(e, press, x, y, btn)
 
      else
 
        a = { }
 
      end
 
      table.insert(a, 1, nam)
 
      table.insert(a, 2, press)
 
      table.insert(a, 3, x - e.xc)
 
      table.insert(a, 4, y - e.yc)
 
      table.insert(a, 5, btn)
 

	
 
			local r, v = std.call(std.here(), 'ondecor', std.unpack(a))
 
			if not r and not v then
 
				r, v = std.call(std.game, 'ondecor', std.unpack(a))
 
			end
 
			if not r and not v then
 
				return nil, false
 
			end
 
			return r, v
 
		end;
 
      local r, v = std.call(std.here(), 'ondecor', std.unpack(a))
 
      if not r and not v then
 
        r, v = std.call(std.game, 'ondecor', std.unpack(a))
 
      end
 
      if not r and not v then
 
        return nil, false
 
      end
 
      return r, v
 
    end;
 
end)
 
std.mod_start(
 
	function(load)
 
		instead.wait_use(false)
 
		instead.grab_events(true)
 
		if load then
 
			decor:load()
 
		end
 
		decor:render()
 
  function(load)
 
    instead.wait_use(false)
 
    instead.grab_events(true)
 
    if load then
 
      decor:load()
 
    end
 
    decor:render()
 
end)
 

	
 
std.mod_step(
 
	function(state)
 
		if not state then
 
			if std.cmd[1] == '@timer' then
 
				decor:cache_clear()
 
				decor:process()
 
  function(state)
 
    if not state then
 
      if std.cmd[1] == '@timer' then
 
        decor:cache_clear()
 
        decor:process()
 
        decor:sort()
 
				decor:render()
 
			end
 
			return;
 
		end
 
		if not iface:raw_mode() then -- debugger
 
			decor:cache_clear()
 
			decor:process()
 
        decor:render()
 
      end
 
      return;
 
    end
 
    if not iface:raw_mode() then -- debugger
 
      decor:cache_clear()
 
      decor:process()
 
      decor:sort()
 
		end
 
    end
 
end)
 

	
 
local input = std.ref '@input'
 
@@ -1292,20 +1295,20 @@ end;
 
local clickfn = input.click
 

	
 
function input:click(press, btn, x, y, px, py, ...)
 
	local e = decor:click_filter(press, x, y)
 
	if e then
 
		x = x - e.x + e.xc
 
		y = y - e.y + e.yc
 
		local a
 
		for _, v in std.ipairs {e[1], press, x, y, btn} do
 
			a = (a and (a..', ') or ' ') .. std.dump(v)
 
		end
 
		return '@decor_click'.. (a or '')
 
	end
 
	if clickfn then
 
		return clickfn(input, press, btn, x, y, px, py, ...)
 
	end
 
	return false
 
  local e = decor:click_filter(press, x, y)
 
  if e then
 
    x = x - e.x + e.xc
 
    y = y - e.y + e.yc
 
    local a
 
    for _, v in std.ipairs {e[1], press, x, y, btn} do
 
      a = (a and (a..', ') or ' ') .. std.dump(v)
 
    end
 
    return '@decor_click'.. (a or '')
 
  end
 
  if clickfn then
 
    return clickfn(input, press, btn, x, y, px, py, ...)
 
  end
 
  return false
 
end
 

	
 
function decor:force_paint(needsort)
 
@@ -1314,16 +1317,16 @@ function decor:force_paint(needsort)
 
end;
 

	
 
function D(n)
 
	if n == nil then
 
  if n == nil then
 
    decor.dirty = true
 
    decor.needsort = true
 
		return decor:zap()
 
	end
 
	
 
	if type(n) == 'table' then
 
    return decor:zap()
 
  end
 
  
 
  if type(n) == 'table' then
 
    decor.dirty = true
 
    decor.needsort = true
 
		return decor:new(n)
 
	end
 
	return decor:get(n)
 
    return decor:new(n)
 
  end
 
  return decor:get(n)
 
end
lib/dire/color2rgb.lua
Show inline comments
 
local colors = {
 
	aliceblue = 0xf0f8ff,
 
	antiquewhite = 0xfaebd7,
 
	aqua = 0x00ffff,
 
	aquamarine = 0x7fffd4,
 
	azure = 0xf0ffff,
 
	beige = 0xf5f5dc,
 
	bisque = 0xffe4c4,
 
	black = 0x000000,
 
	blanchedalmond = 0xffebcd,
 
	blue = 0x0000ff,
 
	blueviolet = 0x8a2be2,
 
	brown = 0xa52a2a,
 
	burlywood = 0xdeb887,
 
	cadetblue = 0x5f9ea0,
 
	chartreuse = 0x7fff00,
 
	chocolate = 0xd2691e,
 
	coral = 0xff7f50,
 
	cornflowerblue = 0x6495ed,
 
	cornsilk = 0xfff8dc,
 
	crimson = 0xdc143c,
 
	cyan = 0x00ffff,
 
	darkblue = 0x00008b,
 
	darkcyan = 0x008b8b,
 
	darkgoldenrod = 0xb8860b,
 
	darkgray = 0xa9a9a9,
 
	darkgrey = 0xa9a9a9,
 
	darkgreen = 0x006400,
 
	darkkhaki = 0xbdb76b,
 
	darkmagenta = 0x8b008b,
 
	darkolivegreen = 0x556b2f,
 
	darkorange = 0xff8c00,
 
	darkorchid = 0x9932cc,
 
	darkred = 0x8b0000,
 
	darksalmon = 0xe9967a,
 
	darkseagreen = 0x8fbc8f,
 
	darkslateblue = 0x483d8b,
 
	darkslategray = 0x2f4f4f,
 
	darkslategrey = 0x2f4f4f,
 
	darkturquoise = 0x00ced1,
 
	darkviolet = 0x9400d3,
 
	deeppink = 0xff1493,
 
	deepskyblue = 0x00bfff,
 
	dimgray = 0x696969,
 
	dimgrey = 0x696969,
 
	dodgerblue = 0x1e90ff,
 
	feldspar = 0xd19275,
 
	firebrick = 0xb22222,
 
	floralwhite = 0xfffaf0,
 
	forestgreen = 0x228b22,
 
	fuchsia = 0xff00ff,
 
	gainsboro = 0xdcdcdc,
 
	ghostwhite = 0xf8f8ff,
 
	gold = 0xffd700,
 
	goldenrod = 0xdaa520,
 
	gray = 0x808080,
 
	grey = 0x808080,
 
	green = 0x008000,
 
	greenyellow = 0xadff2f,
 
	honeydew = 0xf0fff0,
 
	hotpink = 0xff69b4,
 
	indianred = 0xcd5c5c,
 
	indigo = 0x4b0082,
 
	ivory = 0xfffff0,
 
	khaki = 0xf0e68c,
 
	lavender = 0xe6e6fa,
 
	lavenderblush = 0xfff0f5,
 
	lawngreen = 0x7cfc00,
 
	lemonchiffon = 0xfffacd,
 
	lightblue = 0xadd8e6,
 
	lightcoral = 0xf08080,
 
	lightcyan = 0xe0ffff,
 
	lightgoldenrodyellow = 0xfafad2,
 
	lightgray = 0xd3d3d3,
 
	lightgrey = 0xd3d3d3,
 
	lightgreen = 0x90ee90,
 
	lightpink = 0xffb6c1,
 
	lightsalmon = 0xffa07a,
 
	lightseagreen = 0x20b2aa,
 
	lightskyblue = 0x87cefa,
 
	lightslateblue = 0x8470ff,
 
	lightslategray = 0x778899,
 
	lightslategrey = 0x778899,
 
	lightsteelblue = 0xb0c4de,
 
	lightyellow = 0xffffe0,
 
	lime = 0x00ff00,
 
	limegreen = 0x32cd32,
 
	linen = 0xfaf0e6,
 
	magenta = 0xff00ff,
 
	maroon = 0x800000,
 
	mediumaquamarine = 0x66cdaa,
 
	mediumblue = 0x0000cd,
 
	mediumorchid = 0xba55d3,
 
	mediumpurple = 0x9370d8,
 
	mediumseagreen = 0x3cb371,
 
	mediumslateblue = 0x7b68ee,
 
	mediumspringgreen = 0x00fa9a,
 
	mediumturquoise = 0x48d1cc,
 
	mediumvioletred = 0xc71585,
 
	midnightblue = 0x191970,
 
	mintcream = 0xf5fffa,
 
	mistyrose = 0xffe4e1,
 
	moccasin = 0xffe4b5,
 
	navajowhite = 0xffdead,
 
	navy = 0x000080,
 
	oldlace = 0xfdf5e6,
 
	olive = 0x808000,
 
	olivedrab = 0x6b8e23,
 
	orange = 0xffa500,
 
	orangered = 0xff4500,
 
	orchid = 0xda70d6,
 
	palegoldenrod = 0xeee8aa,
 
	palegreen = 0x98fb98,
 
	paleturquoise = 0xafeeee,
 
	palevioletred = 0xd87093,
 
	papayawhip = 0xffefd5,
 
	peachpuff = 0xffdab9,
 
	peru = 0xcd853f,
 
	pink = 0xffc0cb,
 
	plum = 0xdda0dd,
 
	powderblue = 0xb0e0e6,
 
	purple = 0x800080,
 
	red = 0xff0000,
 
	rosybrown = 0xbc8f8f,
 
	royalblue = 0x4169e1,
 
	saddlebrown = 0x8b4513,
 
	salmon = 0xfa8072,
 
	sandybrown = 0xf4a460,
 
	seagreen = 0x2e8b57,
 
	seashell = 0xfff5ee,
 
	sienna = 0xa0522d,
 
	silver = 0xc0c0c0,
 
	skyblue = 0x87ceeb,
 
	slateblue = 0x6a5acd,
 
	slategray = 0x708090,
 
	slategrey = 0x708090,
 
	snow = 0xfffafa,
 
	springgreen = 0x00ff7f,
 
	steelblue = 0x4682b4,
 
	tan = 0xd2b48c,
 
	teal = 0x008080,
 
	thistle = 0xd8bfd8,
 
	tomato = 0xff6347,
 
	turquoise = 0x40e0d0,
 
	violet = 0xee82ee,
 
	violetred = 0xd02090,
 
	wheat = 0xf5deb3,
 
	white = 0xffffff,
 
	whitesmoke = 0xf5f5f5,
 
	yellow = 0xffff00,
 
	yellowgreen = 0x9acd32,
 
  aliceblue = 0xf0f8ff,
 
  antiquewhite = 0xfaebd7,
 
  aqua = 0x00ffff,
 
  aquamarine = 0x7fffd4,
 
  azure = 0xf0ffff,
 
  beige = 0xf5f5dc,
 
  bisque = 0xffe4c4,
 
  black = 0x000000,
 
  blanchedalmond = 0xffebcd,
 
  blue = 0x0000ff,
 
  blueviolet = 0x8a2be2,
 
  brown = 0xa52a2a,
 
  burlywood = 0xdeb887,
 
  cadetblue = 0x5f9ea0,
 
  chartreuse = 0x7fff00,
 
  chocolate = 0xd2691e,
 
  coral = 0xff7f50,
 
  cornflowerblue = 0x6495ed,
 
  cornsilk = 0xfff8dc,
 
  crimson = 0xdc143c,
 
  cyan = 0x00ffff,
 
  darkblue = 0x00008b,
 
  darkcyan = 0x008b8b,
 
  darkgoldenrod = 0xb8860b,
 
  darkgray = 0xa9a9a9,
 
  darkgrey = 0xa9a9a9,
 
  darkgreen = 0x006400,
 
  darkkhaki = 0xbdb76b,
 
  darkmagenta = 0x8b008b,
 
  darkolivegreen = 0x556b2f,
 
  darkorange = 0xff8c00,
 
  darkorchid = 0x9932cc,
 
  darkred = 0x8b0000,
 
  darksalmon = 0xe9967a,
 
  darkseagreen = 0x8fbc8f,
 
  darkslateblue = 0x483d8b,
 
  darkslategray = 0x2f4f4f,
 
  darkslategrey = 0x2f4f4f,
 
  darkturquoise = 0x00ced1,
 
  darkviolet = 0x9400d3,
 
  deeppink = 0xff1493,
 
  deepskyblue = 0x00bfff,
 
  dimgray = 0x696969,
 
  dimgrey = 0x696969,
 
  dodgerblue = 0x1e90ff,
 
  feldspar = 0xd19275,
 
  firebrick = 0xb22222,
 
  floralwhite = 0xfffaf0,
 
  forestgreen = 0x228b22,
 
  fuchsia = 0xff00ff,
 
  gainsboro = 0xdcdcdc,
 
  ghostwhite = 0xf8f8ff,
 
  gold = 0xffd700,
 
  goldenrod = 0xdaa520,
 
  gray = 0x808080,
 
  grey = 0x808080,
 
  green = 0x008000,
 
  greenyellow = 0xadff2f,
 
  honeydew = 0xf0fff0,
 
  hotpink = 0xff69b4,
 
  indianred = 0xcd5c5c,
 
  indigo = 0x4b0082,
 
  ivory = 0xfffff0,
 
  khaki = 0xf0e68c,
 
  lavender = 0xe6e6fa,
 
  lavenderblush = 0xfff0f5,
 
  lawngreen = 0x7cfc00,
 
  lemonchiffon = 0xfffacd,
 
  lightblue = 0xadd8e6,
 
  lightcoral = 0xf08080,
 
  lightcyan = 0xe0ffff,
 
  lightgoldenrodyellow = 0xfafad2,
 
  lightgray = 0xd3d3d3,
 
  lightgrey = 0xd3d3d3,
 
  lightgreen = 0x90ee90,
 
  lightpink = 0xffb6c1,
 
  lightsalmon = 0xffa07a,
 
  lightseagreen = 0x20b2aa,
 
  lightskyblue = 0x87cefa,
 
  lightslateblue = 0x8470ff,
 
  lightslategray = 0x778899,
 
  lightslategrey = 0x778899,
 
  lightsteelblue = 0xb0c4de,
 
  lightyellow = 0xffffe0,
 
  lime = 0x00ff00,
 
  limegreen = 0x32cd32,
 
  linen = 0xfaf0e6,
 
  magenta = 0xff00ff,
 
  maroon = 0x800000,
 
  mediumaquamarine = 0x66cdaa,
 
  mediumblue = 0x0000cd,
 
  mediumorchid = 0xba55d3,
 
  mediumpurple = 0x9370d8,
 
  mediumseagreen = 0x3cb371,
 
  mediumslateblue = 0x7b68ee,
 
  mediumspringgreen = 0x00fa9a,
 
  mediumturquoise = 0x48d1cc,
 
  mediumvioletred = 0xc71585,
 
  midnightblue = 0x191970,
 
  mintcream = 0xf5fffa,
 
  mistyrose = 0xffe4e1,
 
  moccasin = 0xffe4b5,
 
  navajowhite = 0xffdead,
 
  navy = 0x000080,
 
  oldlace = 0xfdf5e6,
 
  olive = 0x808000,
 
  olivedrab = 0x6b8e23,
 
  orange = 0xffa500,
 
  orangered = 0xff4500,
 
  orchid = 0xda70d6,
 
  palegoldenrod = 0xeee8aa,
 
  palegreen = 0x98fb98,
 
  paleturquoise = 0xafeeee,
 
  palevioletred = 0xd87093,
 
  papayawhip = 0xffefd5,
 
  peachpuff = 0xffdab9,
 
  peru = 0xcd853f,
 
  pink = 0xffc0cb,
 
  plum = 0xdda0dd,
 
  powderblue = 0xb0e0e6,
 
  purple = 0x800080,
 
  red = 0xff0000,
 
  rosybrown = 0xbc8f8f,
 
  royalblue = 0x4169e1,
 
  saddlebrown = 0x8b4513,
 
  salmon = 0xfa8072,
 
  sandybrown = 0xf4a460,
 
  seagreen = 0x2e8b57,
 
  seashell = 0xfff5ee,
 
  sienna = 0xa0522d,
 
  silver = 0xc0c0c0,
 
  skyblue = 0x87ceeb,
 
  slateblue = 0x6a5acd,
 
  slategray = 0x708090,
 
  slategrey = 0x708090,
 
  snow = 0xfffafa,
 
  springgreen = 0x00ff7f,
 
  steelblue = 0x4682b4,
 
  tan = 0xd2b48c,
 
  teal = 0x008080,
 
  thistle = 0xd8bfd8,
 
  tomato = 0xff6347,
 
  turquoise = 0x40e0d0,
 
  violet = 0xee82ee,
 
  violetred = 0xd02090,
 
  wheat = 0xf5deb3,
 
  white = 0xffffff,
 
  whitesmoke = 0xf5f5f5,
 
  yellow = 0xffff00,
 
  yellowgreen = 0x9acd32,
 
}
 

	
 
function color2rgb(col)
 
	local r, g, b
 
	if col:find("#", 1, true) then
 
		r = tonumber("0x"..col:sub(2, 3))
 
		g = tonumber("0x"..col:sub(4, 5))
 
		b = tonumber("0x"..col:sub(6, 7))
 
	else
 
		local val = colors[col] or 0
 
		r = math.floor(val / 0x10000) % 256
 
		g = math.floor(val / 0x100) % 256
 
		b = val % 256
 
	end
 
	return r, g, b
 
  local r, g, b
 
  if col:find("#", 1, true) then
 
    r = tonumber("0x"..col:sub(2, 3))
 
    g = tonumber("0x"..col:sub(4, 5))
 
    b = tonumber("0x"..col:sub(6, 7))
 
  else
 
    local val = colors[col] or 0
 
    r = math.floor(val / 0x10000) % 256
 
    g = math.floor(val / 0x100) % 256
 
    b = val % 256
 
  end
 
  return r, g, b
 
end
lib/dire/core.lua
Show inline comments
 
@@ -8,294 +8,294 @@ local drawmethods;
 

	
 
-- Draw src centered to position on dst. Clip to position
 
function dire_draw_center(src, dst, position)
 
	if not src then return end;
 
	local sw, sh = src:size()
 
	local sx = 0
 
	local sy = 0
 
	local dx = 0
 
	local dy = 0
 
  if not src then return end;
 
  local sw, sh = src:size()
 
  local sx = 0
 
  local sy = 0
 
  local dx = 0
 
  local dy = 0
 

	
 
	if sw > position.w then
 
		sx = math.floor((sw - position.w) / 2)
 
		sw = position.w
 
	elseif sw < position.w then
 
		dx = math.floor((position.w - sw) / 2)
 
	end
 
  if sw > position.w then
 
    sx = math.floor((sw - position.w) / 2)
 
    sw = position.w
 
  elseif sw < position.w then
 
    dx = math.floor((position.w - sw) / 2)
 
  end
 

	
 
	if sh > position.h then
 
		sy = math.floor((sh - position.h) / 2)
 
		sh = position.h
 
	elseif sh < position.h then
 
		dy = math.floor((position.h - sh) / 2)
 
	end
 
  if sh > position.h then
 
    sy = math.floor((sh - position.h) / 2)
 
    sh = position.h
 
  elseif sh < position.h then
 
    dy = math.floor((position.h - sh) / 2)
 
  end
 
  
 
	src:blend(sx, sy, sw, sh, dst, position.x + dx, position.y + dy)
 
  src:blend(sx, sy, sw, sh, dst, position.x + dx, position.y + dy)
 
end
 

	
 
-- Draw src tiled to position on dst. Clip to position
 
-- offset: 0 or nil -- left/top, -1 -- center/center, -2 -- right/bottom
 
function dire_draw_tile(src, dst, position, options)
 
	local offset_x = options.xoffset
 
	local offset_y = options.yoffset
 
	local sw, sh = src:size()
 
  local offset_x = options.xoffset
 
  local offset_y = options.yoffset
 
  local sw, sh = src:size()
 

	
 
	if offset_x == nil then
 
		offset_x = 0
 
	elseif offset_x == -1 then
 
		offset_x = math.floor((math.ceil(position.w / sw) * sw - position.w) / 2)
 
	elseif offset_x == -2 then
 
		offset_x = (math.ceil(position.w / sw) * sw - position.w)
 
	elseif offset_x > 0 then
 
		offset_x = offset_x - sw
 
	end
 
  if offset_x == nil then
 
    offset_x = 0
 
  elseif offset_x == -1 then
 
    offset_x = math.floor((math.ceil(position.w / sw) * sw - position.w) / 2)
 
  elseif offset_x == -2 then
 
    offset_x = (math.ceil(position.w / sw) * sw - position.w)
 
  elseif offset_x > 0 then
 
    offset_x = offset_x - sw
 
  end
 

	
 
	if offset_y == nil then
 
		offset_y = 0
 
	elseif offset_y == -1 then
 
		offset_y = math.floor((math.ceil(position.h / sh) * sh - position.h) / 2)
 
	elseif offset_y == -2 then
 
		offset_y = (math.ceil(position.h / sh) * sh - position.h)
 
	elseif offset_y > 0 then
 
		offset_y = offset_y - sw
 
	end
 
  if offset_y == nil then
 
    offset_y = 0
 
  elseif offset_y == -1 then
 
    offset_y = math.floor((math.ceil(position.h / sh) * sh - position.h) / 2)
 
  elseif offset_y == -2 then
 
    offset_y = (math.ceil(position.h / sh) * sh - position.h)
 
  elseif offset_y > 0 then
 
    offset_y = offset_y - sw
 
  end
 

	
 
	local rem_h = position.h;
 
	while rem_h > 0 do
 
		local coffset_x = offset_x
 
		local rem_w = position.w
 
		while rem_w > 0 do
 
			local w = sw - coffset_x
 
			if w > rem_w then w = rem_w end
 
			local h = sh - offset_y
 
			if h > rem_h then h = rem_h end
 
			src:blend(coffset_x, offset_y, w, h, dst, position.x + position.w - rem_w, position.y + position.h - rem_h)
 
			rem_w = rem_w - sw + coffset_x
 
			coffset_x = 0
 
		end;
 
		rem_h = rem_h - sh + offset_y
 
		offset_y = 0
 
	end
 
  local rem_h = position.h;
 
  while rem_h > 0 do
 
    local coffset_x = offset_x
 
    local rem_w = position.w
 
    while rem_w > 0 do
 
      local w = sw - coffset_x
 
      if w > rem_w then w = rem_w end
 
      local h = sh - offset_y
 
      if h > rem_h then h = rem_h end
 
      src:blend(coffset_x, offset_y, w, h, dst, position.x + position.w - rem_w, position.y + position.h - rem_h)
 
      rem_w = rem_w - sw + coffset_x
 
      coffset_x = 0
 
    end;
 
    rem_h = rem_h - sh + offset_y
 
    offset_y = 0
 
  end
 
end
 

	
 
-- Draw src letterboxed to position on dst. Clip to position
 
function dire_draw_letterbox(src, dst, position, options)
 
	local sw, sh = src:size();
 
	local scalex = position.w / sw
 
	local scaley = position.h / sh
 
	if scalex < scaley then
 
		scaley = scalex;
 
	else
 
		scalex = scaley;
 
	end;
 
	local src_scaled;
 
	if scalex == 1 then
 
		src_scaled = src;
 
	else
 
		src_scaled = src:scale(scalex, scaley, options.smooth);
 
		sw, sh = src_scaled:size();
 
	end;
 
	local dx = math.floor((position.w - sw) / 2)
 
	local dy = math.floor((position.h - sh) / 2)
 
	src_scaled:blend(0, 0, sw, sh, dst, position.x + dx, position.y + dy);
 
  local sw, sh = src:size();
 
  local scalex = position.w / sw
 
  local scaley = position.h / sh
 
  if scalex < scaley then
 
    scaley = scalex;
 
  else
 
    scalex = scaley;
 
  end;
 
  local src_scaled;
 
  if scalex == 1 then
 
    src_scaled = src;
 
  else
 
    src_scaled = src:scale(scalex, scaley, options.smooth);
 
    sw, sh = src_scaled:size();
 
  end;
 
  local dx = math.floor((position.w - sw) / 2)
 
  local dy = math.floor((position.h - sh) / 2)
 
  src_scaled:blend(0, 0, sw, sh, dst, position.x + dx, position.y + dy);
 
end
 

	
 
-- Draw src filling position on dst. Clip to position
 
function dire_draw_fill(src, dst, position, options)
 
	local sw, sh = src:size();
 
	local scalex = position.w / sw
 
	local scaley = position.h / sh
 
	if scalex > scaley then
 
		scaley = scalex;
 
	else
 
		scalex = scaley;
 
	end;
 
	local src_scaled;
 
	if scalex == 1 then
 
		src_scaled = src;
 
	else
 
		src_scaled = src:scale(scalex, scaley, options.smooth);
 
		sw, sh = src_scaled:size();
 
	end;
 
	local dx = math.floor((sw - position.w) / 2)
 
	local dy = math.floor((sh - position.h) / 2)
 
	src_scaled:blend(dx, dy, sw - 2 * dx, sh - 2 * dy, dst, position.x, position.y);
 
  local sw, sh = src:size();
 
  local scalex = position.w / sw
 
  local scaley = position.h / sh
 
  if scalex > scaley then
 
    scaley = scalex;
 
  else
 
    scalex = scaley;
 
  end;
 
  local src_scaled;
 
  if scalex == 1 then
 
    src_scaled = src;
 
  else
 
    src_scaled = src:scale(scalex, scaley, options.smooth);
 
    sw, sh = src_scaled:size();
 
  end;
 
  local dx = math.floor((sw - position.w) / 2)
 
  local dy = math.floor((sh - position.h) / 2)
 
  src_scaled:blend(dx, dy, sw - 2 * dx, sh - 2 * dy, dst, position.x, position.y);
 
end
 

	
 
-- Draw src stretching over position on dst. Clip to position
 
function dire_draw_stretch(src, dst, position, options)
 
	local sw, sh = src:size();
 
	local scalex = position.w / sw
 
	local scaley = position.h / sh
 
	local src_scaled;
 
	if scalex == 1 and scaley == 1 then
 
		src_scaled = src;
 
	else
 
		src_scaled = src:scale(scalex, scaley, options.smooth);
 
		sw, sh = src_scaled:size();
 
	end;
 
	src_scaled:blend(0, 0, sw, sh, dst, position.x, position.y);
 
  local sw, sh = src:size();
 
  local scalex = position.w / sw
 
  local scaley = position.h / sh
 
  local src_scaled;
 
  if scalex == 1 and scaley == 1 then
 
    src_scaled = src;
 
  else
 
    src_scaled = src:scale(scalex, scaley, options.smooth);
 
    sw, sh = src_scaled:size();
 
  end;
 
  src_scaled:blend(0, 0, sw, sh, dst, position.x, position.y);
 
end
 

	
 
-- Draw src 9-scaled over position on dst. Clip to position
 
function dire_map_9(src, dst, position, options)
 
	local slice = options.parts;
 
  local slice = options.parts;
 

	
 
	local rval = {};
 
  local rval = {};
 

	
 
	local x, y;
 
	if position.w >= slice.x1 + slice.x3 then
 
		x = {
 
			slice.x1;
 
			position.w - slice.x1 - slice.x3;
 
			slice.x3;
 
		};
 
	else
 
		x = {
 
			math.floor(position.w / 2);
 
			0;
 
			position.w - math.floor(position.w / 2);
 
		};
 
	end;
 
  local x, y;
 
  if position.w >= slice.x1 + slice.x3 then
 
    x = {
 
      slice.x1;
 
      position.w - slice.x1 - slice.x3;
 
      slice.x3;
 
    };
 
  else
 
    x = {
 
      math.floor(position.w / 2);
 
      0;
 
      position.w - math.floor(position.w / 2);
 
    };
 
  end;
 

	
 
	if position.h >= slice.y1 + slice.y3 then
 
		y = {
 
			slice.y1;
 
			position.h - slice.y1 - slice.y3;
 
			slice.y3;
 
		};
 
	else
 
		y = {
 
			math.floor(position.h / 2);
 
			0;
 
			position.h - math.floor(position.h / 2);
 
		};
 
	end;
 
  if position.h >= slice.y1 + slice.y3 then
 
    y = {
 
      slice.y1;
 
      position.h - slice.y1 - slice.y3;
 
      slice.y3;
 
    };
 
  else
 
    y = {
 
      math.floor(position.h / 2);
 
      0;
 
      position.h - math.floor(position.h / 2);
 
    };
 
  end;
 

	
 
	local dx = {
 
		position.x,
 
		position.x + x[1],
 
		position.x + x[1] + x[2];
 
	}
 
  local dx = {
 
    position.x,
 
    position.x + x[1],
 
    position.x + x[1] + x[2];
 
  }
 

	
 
	local dy = {
 
		position.y,
 
		position.y + y[1],
 
		position.y + y[1] + y[2];
 
	}
 
  local dy = {
 
    position.y,
 
    position.y + y[1],
 
    position.y + y[1] + y[2];
 
  }
 

	
 
	for i = 1, 9 do
 
		local iy = math.floor((i - 1) / 3);
 
		local ix = (i - 1) % 3;
 
  for i = 1, 9 do
 
    local iy = math.floor((i - 1) / 3);
 
    local ix = (i - 1) % 3;
 

	
 
		local drawmethod = dire_draw_tile;
 
    local drawmethod = dire_draw_tile;
 

	
 
		if options.drawmethod then
 
			if type(options.drawmethod) == 'table' then
 
				drawmethod = drawmethods[options.drawmethod[i]];
 
			else
 
				drawmethod = drawmethods[options.drawmethod];
 
			end;
 
		end;
 
    if options.drawmethod then
 
      if type(options.drawmethod) == 'table' then
 
        drawmethod = drawmethods[options.drawmethod[i]];
 
      else
 
        drawmethod = drawmethods[options.drawmethod];
 
      end;
 
    end;
 

	
 
		local drawoptions = nil
 
    local drawoptions = nil
 

	
 
		if options.drawoptions then
 
			if typeof(options.drawoptions) == 'table' then
 
				drawoptions = drawmethods[options.drawmethod[i]]
 
			else
 
				drawoptions = drawmethods[options.drawmethod]
 
			end;
 
    if options.drawoptions then
 
      if typeof(options.drawoptions) == 'table' then
 
        drawoptions = drawmethods[options.drawmethod[i]]
 
      else
 
        drawoptions = drawmethods[options.drawmethod]
 
      end;
 

	
 
			if drawoptions.xoffset == nil then
 
				drawoptions.xoffset=-ix
 
			end;
 
      if drawoptions.xoffset == nil then
 
        drawoptions.xoffset=-ix
 
      end;
 

	
 
			if drawoptions.yoffset == nil then
 
				drawoptions.yoffset=-iy
 
			end;
 
		else
 
			drawoptions = {
 
				smooth=options.smooth,
 
				xoffset=-ix,
 
				yoffset=-iy
 
			}
 
		end;
 
      if drawoptions.yoffset == nil then
 
        drawoptions.yoffset=-iy
 
      end;
 
    else
 
      drawoptions = {
 
        smooth=options.smooth,
 
        xoffset=-ix,
 
        yoffset=-iy
 
      }
 
    end;
 

	
 
		rval[#rval + 1] = {
 
			drawmethod, src[i], dst, {x = dx[ix + 1], y = dy[iy + 1], w = x[ix + 1], h = y[iy + 1]}, drawoptions
 
		}
 
	end;
 
    rval[#rval + 1] = {
 
      drawmethod, src[i], dst, {x = dx[ix + 1], y = dy[iy + 1], w = x[ix + 1], h = y[iy + 1]}, drawoptions
 
    }
 
  end;
 

	
 
	return rval;
 
  return rval;
 
end
 

	
 
function dire_draw_9(src, dst, position, options)
 
	local fields;
 
	if dst == nil then
 
		fields = src;
 
	else
 
		fields = dire_map_9(src, dst, position, options);
 
	end;
 
  local fields;
 
  if dst == nil then
 
    fields = src;
 
  else
 
    fields = dire_map_9(src, dst, position, options);
 
  end;
 

	
 
	for k, f in pairs(fields) do
 
		f[1](f[2], f[3], f[4], f[5]);
 
	end;
 
  for k, f in pairs(fields) do
 
    f[1](f[2], f[3], f[4], f[5]);
 
  end;
 
end;
 

	
 
-- pixels: pixels, slice: position
 
-- return 9 new pixels objects, sliced by slice
 
function dire_slice_9(src, slice)
 
	local pw, ph = src:size();
 
	if not slice then
 
		local pw3 = math.floor(pw / 3);
 
		local ph3 = math.floor(ph / 3);
 
		slice = {
 
			x = pw3,
 
			y = ph3,
 
			w = pw - 2 * pw3,
 
			h = ph - 2 * ph3
 
		};
 
	end;
 
	local pw = pw - slice.w - slice.x;
 
	local ph = ph - slice.h - slice.y;
 
	local rpixels = {
 
		pixels.new(slice.x, slice.y),
 
		pixels.new(slice.w, slice.y),
 
		pixels.new(pw, slice.y),
 
		pixels.new(slice.x, slice.h),
 
		pixels.new(slice.w, slice.h),
 
		pixels.new(pw, slice.h),
 
		pixels.new(slice.x, ph),
 
		pixels.new(slice.w, ph),
 
		pixels.new(pw, ph)
 
	};
 
  local pw, ph = src:size();
 
  if not slice then
 
    local pw3 = math.floor(pw / 3);
 
    local ph3 = math.floor(ph / 3);
 
    slice = {
 
      x = pw3,
 
      y = ph3,
 
      w = pw - 2 * pw3,
 
      h = ph - 2 * ph3
 
    };
 
  end;
 
  local pw = pw - slice.w - slice.x;
 
  local ph = ph - slice.h - slice.y;
 
  local rpixels = {
 
    pixels.new(slice.x, slice.y),
 
    pixels.new(slice.w, slice.y),
 
    pixels.new(pw, slice.y),
 
    pixels.new(slice.x, slice.h),
 
    pixels.new(slice.w, slice.h),
 
    pixels.new(pw, slice.h),
 
    pixels.new(slice.x, ph),
 
    pixels.new(slice.w, ph),
 
    pixels.new(pw, ph)
 
  };
 

	
 
	src:blend(0, 0, slice.x, slice.y, rpixels[1], 0, 0);
 
	src:blend(slice.x, 0, slice.w, slice.y, rpixels[2], 0, 0);
 
	src:blend(slice.x + slice.w, 0, pw, slice.y, rpixels[3], 0, 0);
 
	src:blend(0, slice.y, slice.x, slice.h, rpixels[4], 0, 0);
 
	src:blend(slice.x, slice.y, slice.w, slice.h, rpixels[5], 0, 0);
 
	src:blend(slice.x + slice.w, slice.y, pw, slice.h, rpixels[6], 0, 0);
 
	src:blend(0, slice.y + slice.h, slice.x, ph, rpixels[7], 0, 0);
 
	src:blend(slice.x, slice.y + slice.h, slice.w, ph, rpixels[8], 0, 0);
 
	src:blend(slice.x + slice.w, slice.y + slice.h, pw, ph, rpixels[9], 0, 0);
 
  src:blend(0, 0, slice.x, slice.y, rpixels[1], 0, 0);
 
  src:blend(slice.x, 0, slice.w, slice.y, rpixels[2], 0, 0);
 
  src:blend(slice.x + slice.w, 0, pw, slice.y, rpixels[3], 0, 0);
 
  src:blend(0, slice.y, slice.x, slice.h, rpixels[4], 0, 0);
 
  src:blend(slice.x, slice.y, slice.w, slice.h, rpixels[5], 0, 0);
 
  src:blend(slice.x + slice.w, slice.y, pw, slice.h, rpixels[6], 0, 0);
 
  src:blend(0, slice.y + slice.h, slice.x, ph, rpixels[7], 0, 0);
 
  src:blend(slice.x, slice.y + slice.h, slice.w, ph, rpixels[8], 0, 0);
 
  src:blend(slice.x + slice.w, slice.y + slice.h, pw, ph, rpixels[9], 0, 0);
 

	
 

	
 
	return rpixels, {
 
		x1=slice.x,
 
		x2=slice.w,
 
		x3=pw,
 
		y1=slice.y,
 
		y2=slice.h,
 
		y3=ph
 
	};
 
  return rpixels, {
 
    x1=slice.x,
 
    x2=slice.w,
 
    x3=pw,
 
    y1=slice.y,
 
    y2=slice.h,
 
    y3=ph
 
  };
 
end;
 

	
 
drawmethods = {
 
	dire_draw_center,
 
	dire_draw_tile,
 
	dire_draw_letterbox,
 
	dire_draw_fill,
 
	dire_draw_stretch
 
  dire_draw_center,
 
  dire_draw_tile,
 
  dire_draw_letterbox,
 
  dire_draw_fill,
 
  dire_draw_stretch
 
}
 

	
lib/dire/layout.lua
Show inline comments
 
@@ -5,186 +5,186 @@ direlayout = obj {
 
}
 

	
 
local function is_rect(c)
 
	return c.x and c.y and c.h and c.w;
 
  return c.x and c.y and c.h and c.w;
 
end;
 

	
 
local function constraint_to_rect(constraint, canvas)
 
	if is_rect(constraint) then
 
		return constraint;
 
	end;
 
  if is_rect(constraint) then
 
    return constraint;
 
  end;
 

	
 
	if canvas == nil then
 
		canvas = {
 
			x = 0;
 
			y = 0;
 
			w = tonumber(theme.get('scr.w'));
 
			h = tonumber(theme.get('scr.h'));
 
		}
 
	end;
 
  if canvas == nil then
 
    canvas = {
 
      x = 0;
 
      y = 0;
 
      w = tonumber(theme.get('scr.w'));
 
      h = tonumber(theme.get('scr.h'));
 
    }
 
  end;
 

	
 
	local c
 
	if constraint.leftof then
 
		c = constraint_to_rect(constraint.leftof, canvas);
 
  local c
 
  if constraint.leftof then
 
    c = constraint_to_rect(constraint.leftof, canvas);
 

	
 
		canvas = {
 
			x = canvas.x,
 
			y = canvas.y,
 
			w = c.x - canvas.x;
 
			h = canvas.h;
 
		}
 
	end;
 
    canvas = {
 
      x = canvas.x,
 
      y = canvas.y,
 
      w = c.x - canvas.x;
 
      h = canvas.h;
 
    }
 
  end;
 

	
 
	if constraint.bottomof then
 
		c = constraint_to_rect(constraint.bottomof, canvas);
 
  if constraint.bottomof then
 
    c = constraint_to_rect(constraint.bottomof, canvas);
 

	
 
		canvas = {
 
			x = canvas.x,
 
			y = c.y + c.h,
 
			w = canvas.w,
 
			h = canvas.h - c.h - c.y + canvas.y;
 
		}
 
	end;
 
    canvas = {
 
      x = canvas.x,
 
      y = c.y + c.h,
 
      w = canvas.w,
 
      h = canvas.h - c.h - c.y + canvas.y;
 
    }
 
  end;
 

	
 
	if constraint.rightof then
 
		c = constraint_to_rect(constraint.rightof, canvas);
 
  if constraint.rightof then
 
    c = constraint_to_rect(constraint.rightof, canvas);
 

	
 
		canvas = {
 
			x = c.x + c.w,
 
			y = canvas.y,
 
			w = canvas.w - c.w - c.x + canvas.x;
 
			h = canvas.h;
 
		}
 
	end;
 
    canvas = {
 
      x = c.x + c.w,
 
      y = canvas.y,
 
      w = canvas.w - c.w - c.x + canvas.x;
 
      h = canvas.h;
 
    }
 
  end;
 

	
 
	if constraint.topof then
 
		c = constraint_to_rect(constraint.topof, canvas);
 
  if constraint.topof then
 
    c = constraint_to_rect(constraint.topof, canvas);
 

	
 
		canvas = {
 
			x = canvas.x,
 
			y = canvas.y,
 
			w = canvas.w;
 
			h = c.y - canvas.y;
 
		}
 
	end;
 
    canvas = {
 
      x = canvas.x,
 
      y = canvas.y,
 
      w = canvas.w;
 
      h = c.y - canvas.y;
 
    }
 
  end;
 

	
 
	-- if both lx and rx not nil -- center horizontally
 
	-- if both ty and by not nil -- center vertically
 
	-- aspect ratio requirement is always satisfied
 
  -- if both lx and rx not nil -- center horizontally
 
  -- if both ty and by not nil -- center vertically
 
  -- aspect ratio requirement is always satisfied
 

	
 
	-- first attempt to take as much space as possible
 
	local x = 0;
 
	local y = 0;
 
	local w = canvas.w;
 
	local h = canvas.h;
 
  -- first attempt to take as much space as possible
 
  local x = 0;
 
  local y = 0;
 
  local w = canvas.w;
 
  local h = canvas.h;
 

	
 
	if constraint.wf then
 
		w = math.floor(w * constraint.wf);
 
	end;
 
  if constraint.wf then
 
    w = math.floor(w * constraint.wf);
 
  end;
 

	
 
	if constraint.hf then
 
		h = math.floor(h * constraint.hf);
 
	end;
 
  if constraint.hf then
 
    h = math.floor(h * constraint.hf);
 
  end;
 

	
 
	-- then limit width and height to maximum allowed
 
	if constraint.wmax ~= nil and w > constraint.wmax then
 
		w = constraint.wmax
 
	end;
 
	if constraint.hmax ~= nil and h > constraint.hmax then
 
		h = constraint.hmax
 
	end;
 
  -- then limit width and height to maximum allowed
 
  if constraint.wmax ~= nil and w > constraint.wmax then
 
    w = constraint.wmax
 
  end;
 
  if constraint.hmax ~= nil and h > constraint.hmax then
 
    h = constraint.hmax
 
  end;
 

	
 
	-- then handle margins (lx, rx, ty, by)
 
	local llx = constraint.lx or 0;
 
	local tty = constraint.ty or 0;
 
	local rrx = constraint.rx or 0;
 
	local bby = constraint.by or 0;
 
  -- then handle margins (lx, rx, ty, by)
 
  local llx = constraint.lx or 0;
 
  local tty = constraint.ty or 0;
 
  local rrx = constraint.rx or 0;
 
  local bby = constraint.by or 0;
 

	
 
	if w + llx + rrx > canvas.w then
 
		local wmin = constraint.wmin or 1
 
		if wmin >= canvas.w - llx - rrx then
 
			w = wmin;
 
		else
 
			w = canvas.w - llx - rrx
 
		end;
 
	end;
 
  if w + llx + rrx > canvas.w then
 
    local wmin = constraint.wmin or 1
 
    if wmin >= canvas.w - llx - rrx then
 
      w = wmin;
 
    else
 
      w = canvas.w - llx - rrx
 
    end;
 
  end;
 

	
 
	if h + tty + bby > canvas.h then
 
		local hmin = constraint.hmin or 1
 
		if hmin >= canvas.h - tty - bby then
 
			h = hmin;
 
		else
 
			h = canvas.h - tty - bby
 
		end;
 
	end;
 
  if h + tty + bby > canvas.h then
 
    local hmin = constraint.hmin or 1
 
    if hmin >= canvas.h - tty - bby then
 
      h = hmin;
 
    else
 
      h = canvas.h - tty - bby
 
    end;
 
  end;
 

	
 
	-- then apply aspect ratio
 
	local aspect = w / h;
 
	if constraint.rmax ~= nil and aspect > constraint.rmax then
 
		w = math.floor(h * constraint.rmax);
 
	end;
 
  -- then apply aspect ratio
 
  local aspect = w / h;
 
  if constraint.rmax ~= nil and aspect > constraint.rmax then
 
    w = math.floor(h * constraint.rmax);
 
  end;
 

	
 
	if constraint.rmin ~= nil and aspect < constraint.rmin then
 
		h = math.floor(w / constraint.rmin);
 
	end;
 
  if constraint.rmin ~= nil and aspect < constraint.rmin then
 
    h = math.floor(w / constraint.rmin);
 
  end;
 

	
 
	-- then actually position elements
 
	-- if a < 0 then preserve left/top margin as much as possible
 
	-- if a = 0 then reduce both paddings equally
 
	-- if a > 0 then preserve right/bottom margin as much as possible
 
	if constraint.ax == nil or constraint.ax == 0 then
 
		x = llx - math.floor((w + llx + rrx - canvas.w) / 2);
 
	elseif constraint.ax > 0 then
 
		x = canvas.w - w - rrx;
 
		if constraint.ax < 2 and x < llx then
 
			x = llx;
 
		end;
 
	elseif constraint.ax < 0 then
 
		x = llx;
 
		if constraint.ax > -2 and x + w > canvas.w - rrx then
 
			x = canvas.w - rrx - w;
 
		end;
 
	end;
 
  -- then actually position elements
 
  -- if a < 0 then preserve left/top margin as much as possible
 
  -- if a = 0 then reduce both paddings equally
 
  -- if a > 0 then preserve right/bottom margin as much as possible
 
  if constraint.ax == nil or constraint.ax == 0 then
 
    x = llx - math.floor((w + llx + rrx - canvas.w) / 2);
 
  elseif constraint.ax > 0 then
 
    x = canvas.w - w - rrx;
 
    if constraint.ax < 2 and x < llx then
 
      x = llx;
 
    end;
 
  elseif constraint.ax < 0 then
 
    x = llx;
 
    if constraint.ax > -2 and x + w > canvas.w - rrx then
 
      x = canvas.w - rrx - w;
 
    end;
 
  end;
 

	
 
	if constraint.ay == nil or constraint.ay == 0 then
 
		y = tty - math.floor((h + tty + bby - canvas.h) / 2);
 
	elseif constraint.ay > 0 then
 
		y = canvas.h - h - bby;
 
		if constraint.ay < 2 and y < tty then
 
			y = tty;
 
		end;
 
	elseif constraint.ay < 0 then
 
		y = tty;
 
		if constraint.ay > -2 and y + h > canvas.h - bby then
 
			y = canvas.h - bby - h;
 
		end;
 
	end;
 
	
 
	if constraint.dx then
 
		x = x + constraint.dx;
 
	end;
 
	
 
	if constraint.dy then
 
		y = y + constraint.dy;
 
	end;
 
	
 
	x = x + canvas.x;
 
	y = y + canvas.y;
 
	
 
	if constraint.pf then
 
		return constraint.pf({
 
			x = x,
 
			y = y,
 
			w = w,
 
			h = h
 
		});
 
	end;
 
  if constraint.ay == nil or constraint.ay == 0 then
 
    y = tty - math.floor((h + tty + bby - canvas.h) / 2);
 
  elseif constraint.ay > 0 then
 
    y = canvas.h - h - bby;
 
    if constraint.ay < 2 and y < tty then
 
      y = tty;
 
    end;
 
  elseif constraint.ay < 0 then
 
    y = tty;
 
    if constraint.ay > -2 and y + h > canvas.h - bby then
 
      y = canvas.h - bby - h;
 
    end;
 
  end;
 
  
 
  if constraint.dx then
 
    x = x + constraint.dx;
 
  end;
 
  
 
  if constraint.dy then
 
    y = y + constraint.dy;
 
  end;
 
  
 
  x = x + canvas.x;
 
  y = y + canvas.y;
 
  
 
  if constraint.pf then
 
    return constraint.pf({
 
      x = x,
 
      y = y,
 
      w = w,
 
      h = h
 
    });
 
  end;
 

	
 
	return {
 
		x = x,
 
		y = y,
 
		w = w,
 
		h = h
 
	}
 
  return {
 
    x = x,
 
    y = y,
 
    w = w,
 
    h = h
 
  }
 
end;
 

	
 
direlayout.constraint_to_rect = constraint_to_rect;
lib/dire/theme.lua
Show inline comments
 
@@ -21,12 +21,12 @@ local theme_changed = true
 
local background = nil
 

	
 
local gfx = {
 
	inv = {},
 
	win = {},
 
  inv = {},
 
  win = {},
 
};
 
local gfx_sprite = {
 
	inv = {},
 
	win = {}
 
  inv = {},
 
  win = {}
 
};
 

	
 
local bgsprite = nil
 
@@ -39,45 +39,45 @@ local menu_button_sprite = nil
 
local cursor_options = {};
 

	
 
local area_options = {
 
	inv={},
 
	text={},
 
	image={},
 
	menu={}
 
  inv={},
 
  text={},
 
  image={},
 
  menu={}
 
}
 

	
 
local draw_order = {'inv', 'menu', 'text', 'image'}
 

	
 
local function draw_pixels(src, tgt, rect, options)
 
	if not options then
 
		options = {};
 
	end;
 
  if not options then
 
    options = {};
 
  end;
 

	
 
	options.smooth = smooth;
 
  options.smooth = smooth;
 

	
 
	local mode = options.mode or 1
 
  local mode = options.mode or 1
 

	
 
	if mode == 1 then
 
		dire_draw_center(src, tgt, rect, options);
 
	elseif mode == 2 then
 
		if options.xoffset == nil then
 
			options.xoffset = -1;
 
		end;
 
		if options.yoffset == nil then
 
			options.yoffset = -1;
 
		end;
 
		dire_draw_tile(src, tgt, rect, options);
 
	elseif mode == 3 then
 
		dire_draw_letterbox(src, tgt, rect, options);
 
	elseif mode == 4 then
 
		dire_draw_fill(src, tgt, rect, options);
 
	elseif mode == 5 then
 
		dire_draw_stretch(src, tgt, rect, options);
 
	elseif mode == 6 then
 
		if not options.drawmethod then
 
			options.drawmethod = 2;
 
		end;
 
		dire_draw_9(src, tgt, rect, options);
 
	end;
 
  if mode == 1 then
 
    dire_draw_center(src, tgt, rect, options);
 
  elseif mode == 2 then
 
    if options.xoffset == nil then
 
      options.xoffset = -1;
 
    end;
 
    if options.yoffset == nil then
 
      options.yoffset = -1;
 
    end;
 
    dire_draw_tile(src, tgt, rect, options);
 
  elseif mode == 3 then
 
    dire_draw_letterbox(src, tgt, rect, options);
 
  elseif mode == 4 then
 
    dire_draw_fill(src, tgt, rect, options);
 
  elseif mode == 5 then
 
    dire_draw_stretch(src, tgt, rect, options);
 
  elseif mode == 6 then
 
    if not options.drawmethod then
 
      options.drawmethod = 2;
 
    end;
 
    dire_draw_9(src, tgt, rect, options);
 
  end;
 
end;
 

	
 
local scaled_constraint_fields = {'wmax', 'wmin', 'hmax', 'hmin', 'lx', 'ty', 'rx', 'by', 'x', 'y', 'w', 'h'};
 
@@ -85,617 +85,617 @@ local no_scaled_constraint_fields = {'wf
 
local map_option_fields = {'x1', 'x2', 'x3', 'y1', 'y2', 'y3'}
 

	
 
local function __scale_pixels(pixels, scale, smooth)
 
	if scale and scale ~= 1 then
 
		if type(pixels) == 'table' then
 
			local rval = {}
 
			
 
			for i, v in pairs(pixels) do
 
				rval[i] = v:scale(scale, scale, smooth);
 
			end;
 
			
 
			return rval;
 
		else
 
			return pixels:scale(scale, scale, smooth);
 
		end;
 
	end;
 
	return pixels;
 
  if scale and scale ~= 1 then
 
    if type(pixels) == 'table' then
 
      local rval = {}
 
      
 
      for i, v in pairs(pixels) do
 
        rval[i] = v:scale(scale, scale, smooth);
 
      end;
 
      
 
      return rval;
 
    else
 
      return pixels:scale(scale, scale, smooth);
 
    end;
 
  end;
 
  return pixels;
 
end;
 

	
 
local function __scale_map(map, scale, smooth)
 
	if not map then
 
		return nil;
 
	end;
 
  if not map then
 
    return nil;
 
  end;
 

	
 
	if scale and scale ~= 1 then
 
		local pixels = __scale_pixels(map.p, scale);
 
		local options;
 
		
 
		if map.o then
 
			options = {};
 
			for k, v in pairs(map.o) do
 
				options[k] = v;
 
			end;
 
			
 
			if map.o.parts then
 
				options.parts = {}
 
				for k, v in pairs(map.o.parts) do
 
					options.parts[k] = math.floor(v * scale);
 
				end;
 
			end;
 
		end;
 
		
 
		return {
 
			p = pixels,
 
			o = options,
 
			w = map.w * scale,
 
			h = map.h * scale
 
		}
 
	else
 
		return map;
 
	end;
 
  if scale and scale ~= 1 then
 
    local pixels = __scale_pixels(map.p, scale);
 
    local options;
 
    
 
    if map.o then
 
      options = {};
 
      for k, v in pairs(map.o) do
 
        options[k] = v;
 
      end;
 
      
 
      if map.o.parts then
 
        options.parts = {}
 
        for k, v in pairs(map.o.parts) do
 
          options.parts[k] = math.floor(v * scale);
 
        end;
 
      end;
 
    end;
 
    
 
    return {
 
      p = pixels,
 
      o = options,
 
      w = map.w * scale,
 
      h = map.h * scale
 
    }
 
  else
 
    return map;
 
  end;
 
end;
 

	
 
local function map_to_sprite(map, doscale, scalefactor)
 
	if not map then
 
		return nil;
 
	end;
 
	
 
	if type(map.p) == 'function' then
 
		error('Not implemented yet')
 
	else
 
		if control_scaling and doscale then
 
  if not map then
 
    return nil;
 
  end;
 
  
 
  if type(map.p) == 'function' then
 
    error('Not implemented yet')
 
  else
 
    if control_scaling and doscale then
 
      if scalefactor then
 
        map = __scale_map(map, scalefactor, smooth);
 
      else
 
        map = __scale_map(map, scale, smooth);
 
      end;
 
		end;
 
		
 
		local trect = { x = 0, y = 0, w = map.w, h = map.h };
 
		local tgt_pixels = pixels.new(trect.w, trect.h);
 
	
 
		draw_pixels(map.p, tgt_pixels, trect, map.o)
 
		return tgt_pixels:tosprite();
 
	end;
 
    end;
 
    
 
    local trect = { x = 0, y = 0, w = map.w, h = map.h };
 
    local tgt_pixels = pixels.new(trect.w, trect.h);
 
  
 
    draw_pixels(map.p, tgt_pixels, trect, map.o)
 
    return tgt_pixels:tosprite();
 
  end;
 
end;
 

	
 
local function pixels_to_map(p)
 
	local w, h = p:size();
 
	return {
 
		p=p,
 
		options={},
 
		w=w,
 
		h=h
 
	}
 
  local w, h = p:size();
 
  return {
 
    p=p,
 
    options={},
 
    w=w,
 
    h=h
 
  }
 
end;
 

	
 
local function scale_rect(area, noscale)
 
	if noscale or scale == 1 then
 
		return area;
 
	end;
 
  if noscale or scale == 1 then
 
    return area;
 
  end;
 

	
 
	local rval = {};
 
  local rval = {};
 

	
 
	for _, f in pairs(scaled_constraint_fields) do
 
		if area[f] then
 
			rval[f] = math.floor(area[f] * scale);
 
		end;
 
	end;
 
  for _, f in pairs(scaled_constraint_fields) do
 
    if area[f] then
 
      rval[f] = math.floor(area[f] * scale);
 
    end;
 
  end;
 

	
 
	for _, f in pairs(no_scaled_constraint_fields) do
 
		rval[f] = area[f];
 
	end;
 
  for _, f in pairs(no_scaled_constraint_fields) do
 
    rval[f] = area[f];
 
  end;
 

	
 
	return rval;
 
  return rval;
 
end;
 

	
 
local function draw(src, tgt, rect)
 
	if src.color then
 
		local bgcolorr, bgcolorg, bgcolorb = color2rgb(src.color);
 
		tgt:fill(rect.x, rect.y, rect.w, rect.h, bgcolorr, bgcolorg, bgcolorb, src.alpha or 255)
 
	end;
 
  if src.color then
 
    local bgcolorr, bgcolorg, bgcolorb = color2rgb(src.color);
 
    tgt:fill(rect.x, rect.y, rect.w, rect.h, bgcolorr, bgcolorg, bgcolorb, src.alpha or 255)
 
  end;
 

	
 
	if type(src.image) == 'function' then
 
		src.image(tgt, rect, src.options);
 
	end;
 
	
 
	if src._map then
 
		local map = src._map;
 
		if control_scaling and map.o.scale then
 
			map = __scale_map(map, scale, smooth);
 
		end;
 
  if type(src.image) == 'function' then
 
    src.image(tgt, rect, src.options);
 
  end;
 
  
 
  if src._map then
 
    local map = src._map;
 
    if control_scaling and map.o.scale then
 
      map = __scale_map(map, scale, smooth);
 
    end;
 

	
 
		draw_pixels(map.p, tgt, rect, map.o);
 
	end;
 
    draw_pixels(map.p, tgt, rect, map.o);
 
  end;
 
end;
 

	
 
local function apply_font(data, prefix)
 
 	if data and data.color then
 
		theme.set(prefix .. '.col.fg', data.color);
 
	else
 
		theme.reset(prefix .. '.col.fg');
 
	end;
 
   if data and data.color then
 
    theme.set(prefix .. '.col.fg', data.color);
 
  else
 
    theme.reset(prefix .. '.col.fg');
 
  end;
 

	
 
	if data and data.link then
 
		theme.set(prefix .. '.col.link', data.link);
 
	else
 
		theme.reset(prefix .. '.col.link');
 
	end;
 
  if data and data.link then
 
    theme.set(prefix .. '.col.link', data.link);
 
  else
 
    theme.reset(prefix .. '.col.link');
 
  end;
 

	
 
	if data and data.alink then
 
		theme.set(prefix .. '.col.alink', data.alink);
 
	else
 
		theme.reset(prefix .. '.col.alink');
 
	end;
 
  if data and data.alink then
 
    theme.set(prefix .. '.col.alink', data.alink);
 
  else
 
    theme.reset(prefix .. '.col.alink');
 
  end;
 

	
 
	if data and data.font then
 
		theme.set(prefix .. '.fnt.name', data.font);
 
	else
 
		theme.reset(prefix .. '.fnt.name');
 
	end;
 
	
 
	if data and data.size then
 
		local size = data.size;
 
  if data and data.font then
 
    theme.set(prefix .. '.fnt.name', data.font);
 
  else
 
    theme.reset(prefix .. '.fnt.name');
 
  end;
 
  
 
  if data and data.size then
 
    local size = data.size;
 

	
 
		if control_scaling and not data.noscale then
 
			size = math.floor(size * scale);
 
		end;
 
    if control_scaling and not data.noscale then
 
      size = math.floor(size * scale);
 
    end;
 

	
 
		theme.set(prefix .. '.fnt.size', size);
 
	else
 
		theme.reset(prefix .. '.fnt.size');
 
	end;
 
    theme.set(prefix .. '.fnt.size', size);
 
  else
 
    theme.reset(prefix .. '.fnt.size');
 
  end;
 

	
 
	if data and data.height then
 
		theme.set(prefix .. '.col.height', data.height);
 
	else
 
		theme.reset(prefix .. '.col.height');
 
	end;
 
  if data and data.height then
 
    theme.set(prefix .. '.col.height', data.height);
 
  else
 
    theme.reset(prefix .. '.col.height');
 
  end;
 
end;
 

	
 
local function apply_area_options(area, leftof, rightof, topof, bottomof, px, prefix)
 
	local rect = area.rect;
 
	local crect = nil;
 
  local rect = area.rect;
 
  local crect = nil;
 

	
 
	if rect then
 
		rect.leftof = leftof;
 
		rect.rightof = rightof;
 
		rect.topof = topof;
 
		rect.bottomof = bottomof;
 
  if rect then
 
    rect.leftof = leftof;
 
    rect.rightof = rightof;
 
    rect.topof = topof;
 
    rect.bottomof = bottomof;
 

	
 
		rect = direlayout.constraint_to_rect(scale_rect(rect, rect.noscale), default_canvas);
 
	else
 
		theme.reset(prefix .. '.x');
 
		theme.reset(prefix .. '.y');
 
		theme.reset(prefix .. '.w');
 
		theme.reset(prefix .. '.h');
 
    rect = direlayout.constraint_to_rect(scale_rect(rect, rect.noscale), default_canvas);
 
  else
 
    theme.reset(prefix .. '.x');
 
    theme.reset(prefix .. '.y');
 
    theme.reset(prefix .. '.w');
 
    theme.reset(prefix .. '.h');
 

	
 
		rect = {
 
			x = tonumber(theme.get(prefix .. '.x')),
 
			y = tonumber(theme.get(prefix .. '.y')),
 
			w = tonumber(theme.get(prefix .. '.w')),
 
			h = tonumber(theme.get(prefix .. '.h')),
 
		};
 
	end;
 
    rect = {
 
      x = tonumber(theme.get(prefix .. '.x')),
 
      y = tonumber(theme.get(prefix .. '.y')),
 
      w = tonumber(theme.get(prefix .. '.w')),
 
      h = tonumber(theme.get(prefix .. '.h')),
 
    };
 
  end;
 

	
 
	if area.contentrect then
 
		crect = direlayout.constraint_to_rect(scale_rect(area.contentrect, area.contentrect.noscale), rect);
 
	end;
 
  if area.contentrect then
 
    crect = direlayout.constraint_to_rect(scale_rect(area.contentrect, area.contentrect.noscale), rect);
 
  end;
 

	
 
	if crect == nil then
 
		crect = rect;
 
	end;
 
  if crect == nil then
 
    crect = rect;
 
  end;
 

	
 
	if area.bg then
 
		draw(area.bg, px, rect);
 
	end;
 
  if area.bg then
 
    draw(area.bg, px, rect);
 
  end;
 

	
 
	return rect, crect;
 
  return rect, crect;
 
end;
 

	
 
local function apply_content_options(area, crect, px, prefix)
 
	if area._up_map then
 
		gfx_sprite[prefix].up = map_to_sprite(area._up_map, area.scaleui);
 
	else
 
		gfx_sprite[prefix].up = map_to_sprite(gfx[prefix].up, area.scaleui);
 
	end;
 
	theme.set(prefix .. '.gfx.up', gfx_sprite[prefix].up);
 
  if area._up_map then
 
    gfx_sprite[prefix].up = map_to_sprite(area._up_map, area.scaleui);
 
  else
 
    gfx_sprite[prefix].up = map_to_sprite(gfx[prefix].up, area.scaleui);
 
  end;
 
  theme.set(prefix .. '.gfx.up', gfx_sprite[prefix].up);
 

	
 
	if area._down_map then
 
		gfx_sprite[prefix].down = map_to_sprite(area._down_map, area.scaleui);
 
	else
 
		gfx_sprite[prefix].down = map_to_sprite(gfx[prefix].down, area.scaleui);
 
	end;
 
	theme.set(prefix .. '.gfx.down', gfx_sprite[prefix].down);
 
  if area._down_map then
 
    gfx_sprite[prefix].down = map_to_sprite(area._down_map, area.scaleui);
 
  else
 
    gfx_sprite[prefix].down = map_to_sprite(gfx[prefix].down, area.scaleui);
 
  end;
 
  theme.set(prefix .. '.gfx.down', gfx_sprite[prefix].down);
 

	
 
	local upx = -1;
 
	local upy = -1;
 
	
 
	if area.uppos then
 
		local x,y = gfx_sprite[prefix].up:size();
 
	
 
		if area.uppos.x == nil then
 
			theme.reset(prefix .. '.up.x');
 
		elseif area.uppos.ax < 0 then
 
			theme.set(prefix .. '.up.x', crect.x + area.uppos.x);
 
		else
 
			theme.set(prefix .. '.up.x', crect.x + crect.w + area.uppos.x - x);
 
		end;
 
		
 
		if area.uppos.y == nil then
 
			theme.reset(prefix .. '.up.y');
 
		elseif area.uppos.ay < 0 then
 
			theme.set(prefix .. '.up.y', crect.y + area.uppos.y);
 
		else
 
			theme.set(prefix .. '.up.y', crect.y + crect.h + area.uppos.y - y);
 
		end;
 
	else
 
		theme.reset(prefix .. '.up.x');
 
		theme.reset(prefix .. '.up.y');
 
	end;
 
	
 
	if area.downpos then
 
		local x,y = gfx_sprite[prefix].down:size();
 
	
 
		if area.downpos.x == nil then
 
			theme.reset(prefix .. '.down.x');
 
		elseif area.downpos.ax < 0 then
 
			theme.set(prefix .. '.down.x', crect.x + area.downpos.x);
 
		else
 
			theme.set(prefix .. '.down.x', crect.x + crect.w + area.downpos.x - x);
 
		end;
 
		
 
		if area.downpos.y == nil then
 
			theme.reset(prefix .. '.down.y');
 
		elseif area.downpos.ay < 0 then
 
			theme.set(prefix .. '.down.y', crect.y + area.downpos.y);
 
		else
 
			theme.set(prefix .. '.down.y', crect.y + crect.h + area.downpos.y - y);
 
		end;
 
	else
 
		theme.reset(prefix .. '.down.x');
 
		theme.reset(prefix .. '.down.y');
 
	end;
 
  local upx = -1;
 
  local upy = -1;
 
  
 
  if area.uppos then
 
    local x,y = gfx_sprite[prefix].up:size();
 
  
 
    if area.uppos.x == nil then
 
      theme.reset(prefix .. '.up.x');
 
    elseif area.uppos.ax < 0 then
 
      theme.set(prefix .. '.up.x', crect.x + area.uppos.x);
 
    else
 
      theme.set(prefix .. '.up.x', crect.x + crect.w + area.uppos.x - x);
 
    end;
 
    
 
    if area.uppos.y == nil then
 
      theme.reset(prefix .. '.up.y');
 
    elseif area.uppos.ay < 0 then
 
      theme.set(prefix .. '.up.y', crect.y + area.uppos.y);
 
    else
 
      theme.set(prefix .. '.up.y', crect.y + crect.h + area.uppos.y - y);
 
    end;
 
  else
 
    theme.reset(prefix .. '.up.x');
 
    theme.reset(prefix .. '.up.y');
 
  end;
 
  
 
  if area.downpos then
 
    local x,y = gfx_sprite[prefix].down:size();
 
  
 
    if area.downpos.x == nil then
 
      theme.reset(prefix .. '.down.x');
 
    elseif area.downpos.ax < 0 then
 
      theme.set(prefix .. '.down.x', crect.x + area.downpos.x);
 
    else
 
      theme.set(prefix .. '.down.x', crect.x + crect.w + area.downpos.x - x);
 
    end;
 
    
 
    if area.downpos.y == nil then
 
      theme.reset(prefix .. '.down.y');
 
    elseif area.downpos.ay < 0 then
 
      theme.set(prefix .. '.down.y', crect.y + area.downpos.y);
 
    else
 
      theme.set(prefix .. '.down.y', crect.y + crect.h + area.downpos.y - y);
 
    end;
 
  else
 
    theme.reset(prefix .. '.down.x');
 
    theme.reset(prefix .. '.down.y');
 
  end;
 

	
 
	-- TODO Questionable
 
	local pad;
 
	if area.pad_scroll and theme.get(prefix .. '.up.x') == '-1' and theme.get(prefix .. '.up.y') == '-1' then
 
		pad = tonumber(theme.get('scr.gfx.pad'));
 
  -- TODO Questionable
 
  local pad;
 
  if area.pad_scroll and theme.get(prefix .. '.up.x') == '-1' and theme.get(prefix .. '.up.y') == '-1' then
 
    pad = tonumber(theme.get('scr.gfx.pad'));
 

	
 
		local wscroll, _ = gfx_sprite[prefix].up:size();
 
		local wscroll2, _ = gfx_sprite[prefix].down:size();
 
    local wscroll, _ = gfx_sprite[prefix].up:size();
 
    local wscroll2, _ = gfx_sprite[prefix].down:size();
 

	
 
		if wscroll2 > wscroll then
 
			wscroll = wscroll2;
 
		end;
 
    if wscroll2 > wscroll then
 
      wscroll = wscroll2;
 
    end;
 

	
 
		pad = pad + wscroll;
 
    pad = pad + wscroll;
 

	
 
		if area.pad_scroll == 1 then
 
			crect.w = crect.w - pad
 
		elseif area.pad_scroll == 2 then
 
			crect.x = crect.x + pad
 
			crect.w = crect.w - 2 * pad
 
		end;
 
	end;
 
    if area.pad_scroll == 1 then
 
      crect.w = crect.w - pad
 
    elseif area.pad_scroll == 2 then
 
      crect.x = crect.x + pad
 
      crect.w = crect.w - 2 * pad
 
    end;
 
  end;
 

	
 
	theme.set(prefix .. '.x', crect.x);
 
	theme.set(prefix .. '.y', crect.y);
 
	theme.set(prefix .. '.w', crect.w);
 
	theme.set(prefix .. '.h', crect.h);
 
  theme.set(prefix .. '.x', crect.x);
 
  theme.set(prefix .. '.y', crect.y);
 
  theme.set(prefix .. '.w', crect.w);
 
  theme.set(prefix .. '.h', crect.h);
 
end;
 

	
 
local function apply_text(px, leftof, rightof, topof, bottomof)
 
	local area = area_options['text'];
 
	if area then
 
		local rect, crect = apply_area_options(area, leftof, rightof, topof, bottomof, px, 'win');
 
		apply_content_options(area, crect, px, 'win');
 
		apply_font(area.text, 'win');
 
  local area = area_options['text'];
 
  if area then
 
    local rect, crect = apply_area_options(area, leftof, rightof, topof, bottomof, px, 'win');
 
    apply_content_options(area, crect, px, 'win');
 
    apply_font(area.text, 'win');
 

	
 
		if area.align then
 
			theme.set('win.align', area.align);
 
		else
 
			theme.reset('win.align');
 
		end;
 
    if area.align then
 
      theme.set('win.align', area.align);
 
    else
 
      theme.reset('win.align');
 
    end;
 

	
 
		if area.scrollmode then
 
			theme.set('win.scroll.mode', area.scrollmode);
 
		else
 
			theme.reset('win.scroll.mode');
 
		end;
 
    if area.scrollmode then
 
      theme.set('win.scroll.mode', area.scrollmode);
 
    else
 
      theme.reset('win.scroll.mode');
 
    end;
 

	
 
		if area.waysmode then
 
			theme.set('win.ways.mode', area.waysmode);
 
		else
 
			theme.reset('win.ways.mode');
 
		end;
 
    if area.waysmode then
 
      theme.set('win.ways.mode', area.waysmode);
 
    else
 
      theme.reset('win.ways.mode');
 
    end;
 

	
 
		if area.height then
 
			theme.set('win.fnt.height', area.height);
 
		else
 
			theme.reset('win.fnt.height');
 
		end;
 
		
 
		return rect;
 
	end;
 
    if area.height then
 
      theme.set('win.fnt.height', area.height);
 
    else
 
      theme.reset('win.fnt.height');
 
    end;
 
    
 
    return rect;
 
  end;
 
end;
 

	
 
local function apply_inv(px, leftof, rightof, topof, bottomof)
 
	local area = area_options['inv'];
 
	if area then
 
  local area = area_options['inv'];
 
  if area then
 

	
 
		local rect, crect = apply_area_options(area, leftof, rightof, topof, bottomof, px, 'inv');
 
		apply_content_options(area, crect, px, 'inv');
 
		apply_font(area.text, 'inv');
 
    local rect, crect = apply_area_options(area, leftof, rightof, topof, bottomof, px, 'inv');
 
    apply_content_options(area, crect, px, 'inv');
 
    apply_font(area.text, 'inv');
 

	
 
		if area.mode then
 
			theme.set('inv.mode', area.mode);
 
		else
 
			theme.reset('inv.mode');
 
		end;
 
		
 
		if area.height then
 
			theme.set('inv.fnt.height', area.height);
 
		else
 
			theme.reset('inv.fnt.height');
 
		end;
 
    if area.mode then
 
      theme.set('inv.mode', area.mode);
 
    else
 
      theme.reset('inv.mode');
 
    end;
 
    
 
    if area.height then
 
      theme.set('inv.fnt.height', area.height);
 
    else
 
      theme.reset('inv.fnt.height');
 
    end;
 

	
 
		return rect;
 
	end;
 
    return rect;
 
  end;
 
end;
 

	
 
local function apply_image(px, leftof, rightof, topof, bottomof)
 
	local area = area_options['image'];
 
	if area then
 
		local rect, crect = apply_area_options(area, leftof, rightof, topof, bottomof, px, 'scr.gfx');
 
		if area.mode then
 
			theme.set('scr.gfx.mode', area.mode);
 
		else
 
			theme.reset('scr.gfx.mode');
 
		end;
 
		local mode = theme.get('scr.gfx.mode');
 
		if mode == 'embedded' or mode == 'fixed' then
 
			theme.set('scr.gfx.w', crect.w);
 
			theme.set('scr.gfx.h', crect.h);
 
		elseif mode == 'float' then
 
			theme.set('scr.gfx.x', crect.x);
 
			theme.set('scr.gfx.y', crect.y);
 
			theme.set('scr.gfx.w', crect.w);
 
			theme.set('scr.gfx.h', crect.h);
 
		end;
 
		return rect;
 
	end;
 
  local area = area_options['image'];
 
  if area then
 
    local rect, crect = apply_area_options(area, leftof, rightof, topof, bottomof, px, 'scr.gfx');
 
    if area.mode then
 
      theme.set('scr.gfx.mode', area.mode);
 
    else
 
      theme.reset('scr.gfx.mode');
 
    end;
 
    local mode = theme.get('scr.gfx.mode');
 
    if mode == 'embedded' or mode == 'fixed' then
 
      theme.set('scr.gfx.w', crect.w);
 
      theme.set('scr.gfx.h', crect.h);
 
    elseif mode == 'float' then
 
      theme.set('scr.gfx.x', crect.x);
 
      theme.set('scr.gfx.y', crect.y);
 
      theme.set('scr.gfx.w', crect.w);
 
      theme.set('scr.gfx.h', crect.h);
 
    end;
 
    return rect;
 
  end;
 
end;
 

	
 
local function apply_menu(px, leftof, rightof, topof, bottomof)
 
	local area = area_options.menu;
 
	if area then
 
		local rect = area.buttonrect;
 
  local area = area_options.menu;
 
  if area then
 
    local rect = area.buttonrect;
 

	
 
		if rect then
 
			rect.leftof = leftof;
 
			rect.rightof = rightof;
 
			rect.topof = topof;
 
			rect.bottomof = bottomof;
 
			rect = direlayout.constraint_to_rect(scale_rect(rect, rect.noscale), default_canvas);
 
			theme.set('menu.button.x', rect.x);
 
			theme.set('menu.button.y', rect.y);
 
    if rect then
 
      rect.leftof = leftof;
 
      rect.rightof = rightof;
 
      rect.topof = topof;
 
      rect.bottomof = bottomof;
 
      rect = direlayout.constraint_to_rect(scale_rect(rect, rect.noscale), default_canvas);
 
      theme.set('menu.button.x', rect.x);
 
      theme.set('menu.button.y', rect.y);
 

	
 
			if area.button then
 
				menu_button_sprite = map_to_sprite(area.button._map, area.button.options.scale);
 
				theme.set('menu.gfx.button', menu_button_sprite);
 
			else
 
				theme.reset('menu.gfx.button');
 
			end;
 
		else
 
			theme.reset('menu.button.x');
 
			theme.reset('menu.button.y');
 
			theme.reset('menu.gfx.button');
 
		end;
 
      if area.button then
 
        menu_button_sprite = map_to_sprite(area.button._map, area.button.options.scale);
 
        theme.set('menu.gfx.button', menu_button_sprite);
 
      else
 
        theme.reset('menu.gfx.button');
 
      end;
 
    else
 
      theme.reset('menu.button.x');
 
      theme.reset('menu.button.y');
 
      theme.reset('menu.gfx.button');
 
    end;
 

	
 
		if area.bg and area.bg.color then
 
			theme.set('menu.col.bg', area.bg.color);
 
		else
 
			theme.reset('menu.col.bg');
 
		end;
 
    if area.bg and area.bg.color then
 
      theme.set('menu.col.bg', area.bg.color);
 
    else
 
      theme.reset('menu.col.bg');
 
    end;
 

	
 
		if area.bg and area.bg.alpha then
 
			theme.set('menu.col.alpha', area.bg.alpha);
 
		else
 
			theme.reset('menu.col.alpha');
 
		end;
 
    if area.bg and area.bg.alpha then
 
      theme.set('menu.col.alpha', area.bg.alpha);
 
    else
 
      theme.reset('menu.col.alpha');
 
    end;
 

	
 
		if area.border and area.border.color then
 
			theme.set('menu.col.border', area.border.color);
 
		else
 
			theme.reset('menu.col.border');
 
		end;
 
    if area.border and area.border.color then
 
      theme.set('menu.col.border', area.border.color);
 
    else
 
      theme.reset('menu.col.border');
 
    end;
 

	
 
		if area.border and area.border.width then
 
			theme.set('menu.bw', area.border.width);
 
		else
 
			theme.reset('menu.bw');
 
		end;
 
    if area.border and area.border.width then
 
      theme.set('menu.bw', area.border.width);
 
    else
 
      theme.reset('menu.bw');
 
    end;
 

	
 
		if area.height then
 
			theme.set('menu.fnt.height', area.height);
 
		else
 
			theme.reset('menu.fnt.height');
 
		end;
 
		
 
		apply_font(area.text, 'menu');
 
    if area.height then
 
      theme.set('menu.fnt.height', area.height);
 
    else
 
      theme.reset('menu.fnt.height');
 
    end;
 
    
 
    apply_font(area.text, 'menu');
 

	
 
		return rect;
 
	end;
 
    return rect;
 
  end;
 
end;
 

	
 
local function __draw_order(dep_tree, inuse, stack, key, value)
 
	if inuse[key] then
 
		error('Loop in components\' draw order');
 
	end;
 
	stack[#stack + 1] = key;
 
	inuse[key] = 1;
 
  if inuse[key] then
 
    error('Loop in components\' draw order');
 
  end;
 
  stack[#stack + 1] = key;
 
  inuse[key] = 1;
 

	
 
	for key2, value2 in pairs(value) do
 
		__draw_order(dep_tree, inuse, stack, value2, dep_tree[value2] or {});
 
	end;
 
  for key2, value2 in pairs(value) do
 
    __draw_order(dep_tree, inuse, stack, value2, dep_tree[value2] or {});
 
  end;
 

	
 
	inuse[key] = nil;
 
	assert(stack[#stack] == key);
 
	stack[#stack] = nil;
 
  inuse[key] = nil;
 
  assert(stack[#stack] == key);
 
  stack[#stack] = nil;
 

	
 
	for i = 1, #draw_order do
 
		if draw_order[i] == key then return end;
 
	end;
 
  for i = 1, #draw_order do
 
    if draw_order[i] == key then return end;
 
  end;
 

	
 
	draw_order[#draw_order + 1] = key;
 
  draw_order[#draw_order + 1] = key;
 
end;
 

	
 
local function calculate_draw_order()
 
	draw_order = {};
 
	local dep_tree = {};
 
	local inuse = {};
 
	local stack = {};
 
  draw_order = {};
 
  local dep_tree = {};
 
  local inuse = {};
 
  local stack = {};
 

	
 
	for key, value in pairs(area_options) do
 
		dep_tree[key] = {}
 
		if value.topof then
 
			dep_tree[key][#dep_tree[key] + 1] = value.topof
 
		end;
 
  for key, value in pairs(area_options) do
 
    dep_tree[key] = {}
 
    if value.topof then
 
      dep_tree[key][#dep_tree[key] + 1] = value.topof
 
    end;
 

	
 
		if value.leftof then
 
			dep_tree[key][#dep_tree[key] + 1] = value.leftof
 
		end;
 
    if value.leftof then
 
      dep_tree[key][#dep_tree[key] + 1] = value.leftof
 
    end;
 

	
 
		if value.rightof then
 
			dep_tree[key][#dep_tree[key] + 1] = value.rightof
 
		end;
 
    if value.rightof then
 
      dep_tree[key][#dep_tree[key] + 1] = value.rightof
 
    end;
 

	
 
		if value.bottomof then
 
			dep_tree[key][#dep_tree[key] + 1] = value.bottomof
 
		end;
 
	end;
 
    if value.bottomof then
 
      dep_tree[key][#dep_tree[key] + 1] = value.bottomof
 
    end;
 
  end;
 

	
 
	for key, value in pairs(dep_tree) do
 
		if not inuse[key] then
 
			__draw_order(dep_tree, inuse, stack, key, value);
 
		end;
 
	end;
 
  for key, value in pairs(dep_tree) do
 
    if not inuse[key] then
 
      __draw_order(dep_tree, inuse, stack, key, value);
 
    end;
 
  end;
 
end;
 

	
 
local function get_picture_map(image, options)
 
	local px = nil;
 
	local parts = nil;
 
	local istable = false;
 
	local w = nil;
 
	local h = nil;
 
	if type(image) == 'string' then
 
		px = pixels.new(image);
 
		w, h = px:size();
 
	elseif type(image) == 'userdata' then
 
		px = image;
 
		w, h = px:size();
 
	elseif type(image) == 'function' then
 
		return {
 
			p=image,
 
			o=options,
 
			w=1, -- TODO think of default size in this case
 
			h=1 -- TODO think of default size in this case
 
		}
 
	elseif image == nil then
 
		return nil;
 
	else
 
		error('Invalid image parameter');
 
	end;
 
  local px = nil;
 
  local parts = nil;
 
  local istable = false;
 
  local w = nil;
 
  local h = nil;
 
  if type(image) == 'string' then
 
    px = pixels.new(image);
 
    w, h = px:size();
 
  elseif type(image) == 'userdata' then
 
    px = image;
 
    w, h = px:size();
 
  elseif type(image) == 'function' then
 
    return {
 
      p=image,
 
      o=options,
 
      w=1, -- TODO think of default size in this case
 
      h=1 -- TODO think of default size in this case
 
    }
 
  elseif image == nil then
 
    return nil;
 
  else
 
    error('Invalid image parameter');
 
  end;
 

	
 
	if options and options.mode == 6 then
 
		if not istable then
 
			px, options.parts = dire_slice_9(px, options.slice);
 
		end;
 
	end;
 
  if options and options.mode == 6 then
 
    if not istable then
 
      px, options.parts = dire_slice_9(px, options.slice);
 
    end;
 
  end;
 

	
 
	return {
 
		p=px, 
 
		o=options,
 
		w=w,
 
		h=h
 
	}
 
  return {
 
    p=px, 
 
    o=options,
 
    w=w,
 
    h=h
 
  }
 
end;
 

	
 
local area_functions = {
 
	text = apply_text;
 
	inv = apply_inv;
 
	image = apply_image;
 
	menu = apply_menu;
 
  text = apply_text;
 
  inv = apply_inv;
 
  image = apply_image;
 
  menu = apply_menu;
 
}
 

	
 
local function set_theme()
 
	local px = pixels.new(scr_width, scr_height);
 
	if background then
 
		draw(background, px, {x = 0, y = 0, w = scr_width_adjusted, h = scr_height_adjusted});
 
	else
 
		draw({color=theme.get('scr.col.bg')}, px, {x = 0, y = 0, w = scr_width_adjusted, h = scr_height_adjusted});
 
	end;
 
  local px = pixels.new(scr_width, scr_height);
 
  if background then
 
    draw(background, px, {x = 0, y = 0, w = scr_width_adjusted, h = scr_height_adjusted});
 
  else
 
    draw({color=theme.get('scr.col.bg')}, px, {x = 0, y = 0, w = scr_width_adjusted, h = scr_height_adjusted});
 
  end;
 

	
 
	local areas = {};
 
  local areas = {};
 

	
 
	for i = 1, #draw_order do
 
		local area = draw_order[i];
 
		areas[area] = area_functions[area](px, areas[area_options[area].leftof], areas[area_options[area].rightof], areas[area_options[area].topof], areas[area_options[area].bottomof]);
 
	end;
 
  for i = 1, #draw_order do
 
    local area = draw_order[i];
 
    areas[area] = area_functions[area](px, areas[area_options[area].leftof], areas[area_options[area].rightof], areas[area_options[area].topof], areas[area_options[area].bottomof]);
 
  end;
 

	
 
	bgsprite = px:tosprite();
 
	theme.set('scr.gfx.bg', bgsprite);
 
  bgsprite = px:tosprite();
 
  theme.set('scr.gfx.bg', bgsprite);
 

	
 
  local s = scale;
 
  if cursor_options.scalefactor then
 
    s = cursor_options.scalefactor;
 
  end;
 

	
 
	if cursor_options.x then
 
		if control_scaling and s ~= 1 and cursor_options.scale then
 
			theme.set('scr.gfx.cursor.x', math.floor(cursor_options.x * s));
 
		else
 
			theme.set('scr.gfx.cursor.x', cursor_options.x);
 
		end;
 
	else
 
		theme.reset('scr.gfx.cursor.x');
 
	end;
 
  if cursor_options.x then
 
    if control_scaling and s ~= 1 and cursor_options.scale then
 
      theme.set('scr.gfx.cursor.x', math.floor(cursor_options.x * s));
 
    else
 
      theme.set('scr.gfx.cursor.x', cursor_options.x);
 
    end;
 
  else
 
    theme.reset('scr.gfx.cursor.x');
 
  end;
 

	
 
	if cursor_options.y then
 
		if control_scaling and s ~= 1 and cursor_options.scale then
 
			theme.set('scr.gfx.cursor.y', math.floor(cursor_options.y * s));
 
		else
 
			theme.set('scr.gfx.cursor.y', cursor_options.y);
 
		end;
 
	else
 
		theme.reset('scr.gfx.cursor.y');
 
	end;
 
  if cursor_options.y then
 
    if control_scaling and s ~= 1 and cursor_options.scale then
 
      theme.set('scr.gfx.cursor.y', math.floor(cursor_options.y * s));
 
    else
 
      theme.set('scr.gfx.cursor.y', cursor_options.y);
 
    end;
 
  else
 
    theme.reset('scr.gfx.cursor.y');
 
  end;
 

	
 
	if cursor_options._normal_map then
 
		cursor_sprite = map_to_sprite(cursor_options._normal_map, cursor_options.scale, s);
 
	else
 
		cursor_sprite = map_to_sprite(default_cursor, cursor_options.scale, s);
 
	end;
 
  if cursor_options._normal_map then
 
    cursor_sprite = map_to_sprite(cursor_options._normal_map, cursor_options.scale, s);
 
  else
 
    cursor_sprite = map_to_sprite(default_cursor, cursor_options.scale, s);
 
  end;
 

	
 
	if cursor_options._use_map then
 
		cursor_use_sprite = map_to_sprite(cursor_options._use_map, cursor_options.scale, s);
 
	else
 
		cursor_use_sprite = map_to_sprite(default_cursor_use, cursor_options.scale, s);
 
	end;
 
  if cursor_options._use_map then
 
    cursor_use_sprite = map_to_sprite(cursor_options._use_map, cursor_options.scale, s);
 
  else
 
    cursor_use_sprite = map_to_sprite(default_cursor_use, cursor_options.scale, s);
 
  end;
 
  
 
	theme.set('scr.gfx.cursor.normal', cursor_sprite);
 
	theme.set('scr.gfx.cursor.use', cursor_use_sprite);
 
  theme.set('scr.gfx.cursor.normal', cursor_sprite);
 
  theme.set('scr.gfx.cursor.use', cursor_use_sprite);
 
  
 
  theme_changed = false;
 
end;
 

	
 
std.mod_init(function()
 
	local scalemode = theme.get('scr.gfx.scalable');
 
	smooth = (scalemode % 2) == 1;
 
  local scalemode = theme.get('scr.gfx.scalable');
 
  smooth = (scalemode % 2) == 1;
 

	
 
	scr_width = tonumber(theme.get('scr.w'));
 
	scr_height = tonumber(theme.get('scr.h'));
 
  scr_width = tonumber(theme.get('scr.w'));
 
  scr_height = tonumber(theme.get('scr.h'));
 
  
 
  
 
  local dpi = 96;
 
@@ -712,18 +712,18 @@ std.mod_init(function()
 
  
 
  scr_inches = math.sqrt(phys_width * phys_width + phys_height * phys_height);
 

	
 
	if default_canvas == nil then
 
		default_canvas = {
 
			x = 0,
 
			y = 0,
 
			w = scr_width,
 
			h = scr_height
 
		}
 
	end;
 
  if default_canvas == nil then
 
    default_canvas = {
 
      x = 0,
 
      y = 0,
 
      w = scr_width,
 
      h = scr_height
 
    }
 
  end;
 

	
 
	if theme.get('scr.scale_aware') == '2' then
 
		control_scaling = true;
 
		scale = tonumber(theme.get('scr.gfx.scale'));
 
  if theme.get('scr.scale_aware') == '2' then
 
    control_scaling = true;
 
    scale = tonumber(theme.get('scr.gfx.scale'));
 
    scaled_width = math.ceil(scr_width / scale);
 
    scaled_height = math.ceil(scr_height / scale);
 
    scr_width_adjusted = math.ceil(scaled_width * scale);
 
@@ -733,35 +733,35 @@ std.mod_init(function()
 
    scaled_height = 1;
 
    scr_width_adjusted = scr_width;
 
    scr_height_adjusted = scr_height;
 
	end;
 
  end;
 

	
 
	gfx.win.up = pixels_to_map(pixels.new(theme.get('win.gfx.up')));
 
	gfx.win.down = pixels_to_map(pixels.new(theme.get('win.gfx.down')));
 
  gfx.win.up = pixels_to_map(pixels.new(theme.get('win.gfx.up')));
 
  gfx.win.down = pixels_to_map(pixels.new(theme.get('win.gfx.down')));
 

	
 
	gfx_sprite.win.up = map_to_sprite(gfx.win.up);
 
	gfx_sprite.win.down = map_to_sprite(gfx.win.down);
 
  gfx_sprite.win.up = map_to_sprite(gfx.win.up);
 
  gfx_sprite.win.down = map_to_sprite(gfx.win.down);
 

	
 
	theme.set('win.gfx.up', gfx_sprite.win.up);
 
	theme.set('win.gfx.down', gfx_sprite.win.down);
 
  theme.set('win.gfx.up', gfx_sprite.win.up);
 
  theme.set('win.gfx.down', gfx_sprite.win.down);
 

	
 
	gfx.inv.up = pixels_to_map(pixels.new(theme.get('inv.gfx.up')));
 
	gfx.inv.down = pixels_to_map(pixels.new(theme.get('inv.gfx.down')));
 
  gfx.inv.up = pixels_to_map(pixels.new(theme.get('inv.gfx.up')));
 
  gfx.inv.down = pixels_to_map(pixels.new(theme.get('inv.gfx.down')));
 

	
 
	gfx_sprite.inv.up = map_to_sprite(gfx.inv.up);
 
	gfx_sprite.inv.down = map_to_sprite(gfx.inv.down);
 
  gfx_sprite.inv.up = map_to_sprite(gfx.inv.up);
 
  gfx_sprite.inv.down = map_to_sprite(gfx.inv.down);
 

	
 
	theme.set('inv.gfx.up', gfx_sprite.inv.up);
 
	theme.set('inv.gfx.down', gfx_sprite.inv.down);
 
  theme.set('inv.gfx.up', gfx_sprite.inv.up);
 
  theme.set('inv.gfx.down', gfx_sprite.inv.down);
 

	
 
	default_cursor = pixels_to_map(pixels.new(theme.get('scr.gfx.cursor.normal')));
 
	default_cursor_use = pixels_to_map(pixels.new(theme.get('scr.gfx.cursor.use')));
 
	set_theme();
 
  default_cursor = pixels_to_map(pixels.new(theme.get('scr.gfx.cursor.normal')));
 
  default_cursor_use = pixels_to_map(pixels.new(theme.get('scr.gfx.cursor.use')));
 
  set_theme();
 
end);
 

	
 
std.mod_step(function(state)
 
	if theme_changed then
 
		set_theme();
 
	end;
 
  if theme_changed then
 
    set_theme();
 
  end;
 
end);
 

	
 
diretheme = obj {
 
@@ -771,185 +771,185 @@ diretheme = obj {
 
diretheme.set_theme = set_theme;
 

	
 
diretheme.get_canvas = function()
 
	return default_canvas;
 
  return default_canvas;
 
end;
 

	
 
diretheme.set_canvas = function(canvas)
 
	theme_changed = true;
 
	local width = tonumber(theme.get('scr.w'));
 
	local height = tonumber(theme.get('scr.h'));
 
	if canvas then
 
		default_canvas = direlayout.constraint_to_rect(canvas, {x=0, y=0, w=width, h=height});
 
	else
 
		default_canvas = {x=0, y=0, w=width, h=height};
 
	end;
 
  theme_changed = true;
 
  local width = tonumber(theme.get('scr.w'));
 
  local height = tonumber(theme.get('scr.h'));
 
  if canvas then
 
    default_canvas = direlayout.constraint_to_rect(canvas, {x=0, y=0, w=width, h=height});
 
  else
 
    default_canvas = {x=0, y=0, w=width, h=height};
 
  end;
 
  return default_canvas
 
end;
 

	
 
diretheme.set_background = function(color, alpha, image, options)
 
	theme_changed = true;
 
	if color or image then
 
		background = {
 
			color=color,
 
			alpha=alpha,
 
			image=image,
 
			options=options
 
		};
 
		if image and type(image) ~= 'function' then
 
			if not options then
 
				options = {};
 
			end;
 
  theme_changed = true;
 
  if color or image then
 
    background = {
 
      color=color,
 
      alpha=alpha,
 
      image=image,
 
      options=options
 
    };
 
    if image and type(image) ~= 'function' then
 
      if not options then
 
        options = {};
 
      end;
 

	
 
			background._map = get_picture_map(image, options);
 
		end;
 
	else
 
		background = nil;
 
	end;
 
      background._map = get_picture_map(image, options);
 
    end;
 
  else
 
    background = nil;
 
  end;
 
end;
 

	
 
diretheme.set_text_area = function(options, reset)
 
	theme_changed = true;
 
  theme_changed = true;
 

	
 
	if options == nil then
 
		options = {}
 
	end;
 
  if options == nil then
 
    options = {}
 
  end;
 

	
 
	if options.bg and options.bg.image and type(options.bg.image) ~= 'function' then
 
		options.bg._map = get_picture_map(options.bg.image, options.bg.options);
 
	end;
 
  if options.bg and options.bg.image and type(options.bg.image) ~= 'function' then
 
    options.bg._map = get_picture_map(options.bg.image, options.bg.options);
 
  end;
 

	
 
	if reset then
 
		area_options['text'] = options;
 
	else
 
		for k,v in pairs(options) do area_options['text'][k] = v end
 
		options = area_options['text']
 
	end;
 
  if reset then
 
    area_options['text'] = options;
 
  else
 
    for k,v in pairs(options) do area_options['text'][k] = v end
 
    options = area_options['text']
 
  end;
 

	
 
	options._up_map = get_picture_map(options.up);
 
	options._down_map = get_picture_map(options.down);
 
  options._up_map = get_picture_map(options.up);
 
  options._down_map = get_picture_map(options.down);
 

	
 
	calculate_draw_order();
 
  calculate_draw_order();
 
end;
 

	
 
diretheme.set_image_area = function(options, reset)
 
	theme_changed = true;
 
  theme_changed = true;
 

	
 
	if options == nil then
 
		options = {}
 
	end;
 
  if options == nil then
 
    options = {}
 
  end;
 

	
 
	if options.bg and options.bg.image and type(options.bg.image) ~= 'function' then
 
		options.bg._map = get_picture_map(options.bg.image, options.bg.options);
 
	end;
 
  if options.bg and options.bg.image and type(options.bg.image) ~= 'function' then
 
    options.bg._map = get_picture_map(options.bg.image, options.bg.options);
 
  end;
 

	
 
	if reset then
 
		area_options['image'] = options;
 
	else
 
		for k,v in pairs(options) do area_options['image'][k] = v end
 
	end;
 
  if reset then
 
    area_options['image'] = options;
 
  else
 
    for k,v in pairs(options) do area_options['image'][k] = v end
 
  end;
 

	
 
	calculate_draw_order();
 
  calculate_draw_order();
 
end;
 

	
 
diretheme.set_inventory_area = function(options, reset)
 
	theme_changed = true;
 
  theme_changed = true;
 

	
 
	if options == nil then
 
		options = {}
 
	end;
 
  if options == nil then
 
    options = {}
 
  end;
 

	
 
	if reset then
 
		area_options['inv'] = options;
 
	else
 
		for k,v in pairs(options) do area_options['inv'][k] = v end
 
  if reset then
 
    area_options['inv'] = options;
 
  else
 
    for k,v in pairs(options) do area_options['inv'][k] = v end
 

	
 
		options = area_options['inv'];
 
	end;
 
    options = area_options['inv'];
 
  end;
 

	
 
	if options.bg and options.bg.image and type(options.bg.image) ~= 'function' then
 
		options.bg._map = get_picture_map(options.bg.image, options.bg.options);
 
	end;
 
  if options.bg and options.bg.image and type(options.bg.image) ~= 'function' then
 
    options.bg._map = get_picture_map(options.bg.image, options.bg.options);
 
  end;
 

	
 
	options._up_map = get_picture_map(options.up);
 
	options._down_map = get_picture_map(options.down);
 
  options._up_map = get_picture_map(options.up);
 
  options._down_map = get_picture_map(options.down);
 

	
 
	calculate_draw_order();
 
  calculate_draw_order();
 
end;
 

	
 
diretheme.set_menu = function(options, reset)
 
	theme_changed = true;
 
  theme_changed = true;
 

	
 
	if options == nil then
 
		options = {}
 
	end;
 
  if options == nil then
 
    options = {}
 
  end;
 

	
 
	if options.button and options.button.image then
 
		options.button._map = get_picture_map(options.button.image, options.button.options);
 
	end;
 
  if options.button and options.button.image then
 
    options.button._map = get_picture_map(options.button.image, options.button.options);
 
  end;
 

	
 
	if reset then
 
		area_options['menu'] = options;
 
	else
 
		for k,v in pairs(options) do area_options['menu'][k] = v end
 
	end;
 
  if reset then
 
    area_options['menu'] = options;
 
  else
 
    for k,v in pairs(options) do area_options['menu'][k] = v end
 
  end;
 

	
 
	calculate_draw_order();
 
  calculate_draw_order();
 
end;
 

	
 
diretheme.set_cursor = function(options, reset)
 
	reset = reset or not options
 
	theme_changed = true
 
  reset = reset or not options
 
  theme_changed = true
 

	
 
	if not options then
 
		options = {}
 
	end;
 
  if not options then
 
    options = {}
 
  end;
 

	
 
	if options.normal then
 
		options._normal_map = get_picture_map(options.normal)
 
	end;
 
  if options.normal then
 
    options._normal_map = get_picture_map(options.normal)
 
  end;
 

	
 
	if options.use then
 
		options._use_map = get_picture_map(options.use)
 
	end;
 
  if options.use then
 
    options._use_map = get_picture_map(options.use)
 
  end;
 

	
 
	if reset then
 
		cursor_options = options
 
	else
 
		for k,v in pairs(options) do cursor_options[k] = v end
 
	end
 
  if reset then
 
    cursor_options = options
 
  else
 
    for k,v in pairs(options) do cursor_options[k] = v end
 
  end
 
end
 

	
 
diretheme.set_scale = function(s)
 
	if control_scaling then
 
		theme_changed = true
 
		if not s then
 
			theme.reset('scr.gfx.scale')
 
			scale = tonumber(theme.get('scr.gfx.scale'))
 
		else
 
			scale = s
 
			theme.set('scr.gfx.scale', s)
 
		end;
 
  if control_scaling then
 
    theme_changed = true
 
    if not s then
 
      theme.reset('scr.gfx.scale')
 
      scale = tonumber(theme.get('scr.gfx.scale'))
 
    else
 
      scale = s
 
      theme.set('scr.gfx.scale', s)
 
    end;
 
    scaled_width = math.ceil(scr_width / scale);
 
    scaled_height = math.ceil(scr_height / scale);
 
    scr_width_adjusted = math.ceil(scaled_width * scale);
 
    scr_height_adjusted = math.ceil(scaled_height * scale);
 
	end
 
  end
 
end
 

	
 
diretheme.get_scale = function(s)
 
	if control_scaling then
 
		return scale;
 
	else
 
		return tonumber(theme.get('scr.gfx.scale'));
 
	end;
 
  if control_scaling then
 
    return scale;
 
  else
 
    return tonumber(theme.get('scr.gfx.scale'));
 
  end;
 
end;
 

	
 
diretheme.get_smooth = function(s)
 
	return smooth;
 
  return smooth;
 
end;
 

	
 
diretheme.get_screen = function(s)
 
	return scr_width, scr_height
 
  return scr_width, scr_height
 
end;
 

	
 
diretheme.get_inches = function(s)
lib/fading.lua
Show inline comments
 
@@ -3,197 +3,197 @@ require "theme"
 
require "timer"
 

	
 
local f = std.obj {
 
	{
 
		started = false;
 
		timer = false;
 
		effects = {};
 
  {
 
    started = false;
 
    timer = false;
 
    effects = {};
 
    effect = false;
 
    defeffect = false;
 
	};
 
	delay = 20; -- default delay
 
	max = 16; -- default max
 
	nam = '@fading';
 
	enabled = false;
 
  };
 
  delay = 20; -- default delay
 
  max = 16; -- default max
 
  nam = '@fading';
 
  enabled = false;
 
}
 

	
 
function f.effects.fadeblack(s, src, dst)
 
	sprite.scr():fill('black')
 
	if s.step < s.max / 2 then -- fadeout old
 
		local alpha = 255 - (s.step * 2 / s.max) * 255;
 
		if alpha > 0 then
 
			src:draw(sprite.scr(), 0, 0, alpha);
 
		end
 
	else -- fadein new
 
		local alpha = ((s.step - 1 - s.max / 2) / s.max) * 255 * 2;
 
		if alpha > 0 then
 
			dst:draw(sprite.scr(), 0, 0, alpha);
 
		end
 
	end
 
  sprite.scr():fill('black')
 
  if s.step < s.max / 2 then -- fadeout old
 
    local alpha = 255 - (s.step * 2 / s.max) * 255;
 
    if alpha > 0 then
 
      src:draw(sprite.scr(), 0, 0, alpha);
 
    end
 
  else -- fadein new
 
    local alpha = ((s.step - 1 - s.max / 2) / s.max) * 255 * 2;
 
    if alpha > 0 then
 
      dst:draw(sprite.scr(), 0, 0, alpha);
 
    end
 
  end
 
end
 

	
 
function f.effects.fadewhite(s, src, dst)
 
	sprite.scr():fill('white')
 
	if s.step < s.max / 8 then -- fadeout old
 
		local pos = s.step * 8 / s.max
 
		local alpha = (1 - pos) * 255;
 
		if alpha > 0 then
 
			src:draw(sprite.scr(), 0, 0, alpha);
 
		end
 
	else -- fadein new
 
		local pos = (s.step - s.max / 8) / (s.max - s.max/ 8);
 
		local alpha = pos * 255
 
		if alpha > 0 then
 
			dst:draw(sprite.scr(), 0, 0, alpha);
 
		end
 
	end
 
  sprite.scr():fill('white')
 
  if s.step < s.max / 8 then -- fadeout old
 
    local pos = s.step * 8 / s.max
 
    local alpha = (1 - pos) * 255;
 
    if alpha > 0 then
 
      src:draw(sprite.scr(), 0, 0, alpha);
 
    end
 
  else -- fadein new
 
    local pos = (s.step - s.max / 8) / (s.max - s.max/ 8);
 
    local alpha = pos * 255
 
    if alpha > 0 then
 
      dst:draw(sprite.scr(), 0, 0, alpha);
 
    end
 
  end
 
end
 

	
 
function f.effects.crossfade(s, src, dst)
 
	local alpha = ((s.step - 1) / s.max) * 255;
 
--	src:draw(sprite.scr(), 0, 0, 255 - alpha);
 
	src:copy(sprite.scr());
 
	dst:draw(sprite.scr(), 0, 0, alpha);
 
  local alpha = ((s.step - 1) / s.max) * 255;
 
--  src:draw(sprite.scr(), 0, 0, 255 - alpha);
 
  src:copy(sprite.scr());
 
  dst:draw(sprite.scr(), 0, 0, alpha);
 
end
 

	
 
function f.effects.move_left(s, src, dst)
 
--	sprite.scr():fill('black')
 
	local x = theme.scr.w() * s.step / s.max
 
	src:copy(sprite.scr(), x, 0);
 
	dst:copy(sprite.scr(), x - theme.scr.w(), 0);
 
--  sprite.scr():fill('black')
 
  local x = theme.scr.w() * s.step / s.max
 
  src:copy(sprite.scr(), x, 0);
 
  dst:copy(sprite.scr(), x - theme.scr.w(), 0);
 
end
 

	
 
function f.effects.move_right(s, src, dst)
 
--	sprite.scr():fill('black')
 
	local x = theme.scr.w() * s.step / s.max
 
	dst:copy(sprite.scr(), theme.scr.w() - x, 0);
 
	src:copy(sprite.scr(), -x, 0);
 
--  sprite.scr():fill('black')
 
  local x = theme.scr.w() * s.step / s.max
 
  dst:copy(sprite.scr(), theme.scr.w() - x, 0);
 
  src:copy(sprite.scr(), -x, 0);
 
end
 

	
 
function f.effects.move_up(s, src, dst)
 
--	sprite.scr():fill('black')
 
	local y = theme.scr.h() * s.step / s.max
 
	src:copy(sprite.scr(), 0, y);
 
	dst:copy(sprite.scr(), 0, y - theme.scr.h());
 
--  sprite.scr():fill('black')
 
  local y = theme.scr.h() * s.step / s.max
 
  src:copy(sprite.scr(), 0, y);
 
  dst:copy(sprite.scr(), 0, y - theme.scr.h());
 
end
 

	
 
function f.effects.move_down(s, src, dst)
 
--	sprite.scr():fill('black')
 
	local y = theme.scr.h() * s.step / s.max
 
	dst:copy(sprite.scr(), 0, theme.scr.h() - y);
 
	src:copy(sprite.scr(), 0, -y);
 
--  sprite.scr():fill('black')
 
  local y = theme.scr.h() * s.step / s.max
 
  dst:copy(sprite.scr(), 0, theme.scr.h() - y);
 
  src:copy(sprite.scr(), 0, -y);
 
end
 

	
 
function f.effects.animate(s, src, dst)
 
	s.animate(s.step, src, dst);
 
  s.animate(s.step, src, dst);
 
end;
 

	
 
local scr, scr2
 
local cb = timer.callback
 

	
 
function timer:callback(...)
 
	if f.started then
 
		return '@fading'
 
	end
 
	return cb(self, ...)
 
  if f.started then
 
    return '@fading'
 
  end
 
  return cb(self, ...)
 
end
 

	
 
function f.start()
 
	if f.effect[1] == 'none' then
 
		f.started = false
 
		if f.defeffect then
 
			f.effect = std.clone(f.defeffect)
 
		end
 
		return
 
	end
 
	local old = sprite.direct()
 
	sprite.direct(true)
 
	sprite.scr():copy(scr)
 
	sprite.direct(old)
 
	f.timer = timer:get()
 
	f.effect.step = 0
 
	f.started = true
 
	instead.timer(f.effect.delay or 20)
 
  if f.effect[1] == 'none' then
 
    f.started = false
 
    if f.defeffect then
 
      f.effect = std.clone(f.defeffect)
 
    end
 
    return
 
  end
 
  local old = sprite.direct()
 
  sprite.direct(true)
 
  sprite.scr():copy(scr)
 
  sprite.direct(old)
 
  f.timer = timer:get()
 
  f.effect.step = 0
 
  f.started = true
 
  instead.timer(f.effect.delay or 20)
 
end
 

	
 
function f.change(ops)
 
	if type(ops) == 'string' then
 
		ops = { ops }
 
	end
 
	ops.forever = true
 
	f.set(ops)
 
  if type(ops) == 'string' then
 
    ops = { ops }
 
  end
 
  ops.forever = true
 
  f.set(ops)
 
end
 

	
 
function f.set(ops)
 
	if type(ops) == 'string' then
 
		ops = { ops }
 
	end
 
	ops.delay = ops.delay or f.delay
 
	ops.max = ops.max or f.max
 
	f.effect = std.clone(ops)
 
	if ops.forever then
 
		f.defeffect = std.clone(f.effect)
 
	end
 
  if type(ops) == 'string' then
 
    ops = { ops }
 
  end
 
  ops.delay = ops.delay or f.delay
 
  ops.max = ops.max or f.max
 
  f.effect = std.clone(ops)
 
  if ops.forever then
 
    f.defeffect = std.clone(f.effect)
 
  end
 
end
 

	
 

	
 
std.mod_cmd(function(cmd)
 
	if cmd[1] ~= '@fading' then
 
		if f.started and cmd[1] ~= 'save'
 
			and cmd[1] ~= 'way'
 
			and cmd[1] ~= 'inv' then
 
			return true, false
 
		end
 
		return
 
	end
 
	f.effect.step = f.effect.step + 1
 
  if cmd[1] ~= '@fading' then
 
    if f.started and cmd[1] ~= 'save'
 
      and cmd[1] ~= 'way'
 
      and cmd[1] ~= 'inv' then
 
      return true, false
 
    end
 
    return
 
  end
 
  f.effect.step = f.effect.step + 1
 

	
 
	f.effects[f.effect[1]](f.effect, scr, scr2)
 
  f.effects[f.effect[1]](f.effect, scr, scr2)
 

	
 
	if f.effect.step > f.effect.max then
 
		f.started = false
 
		if f.defeffect then
 
			f.effect = std.clone(f.defeffect)
 
		end
 
		instead.timer(f.timer)
 
		sprite.direct(false)
 
		return std.nop()
 
	end
 
	return
 
  if f.effect.step > f.effect.max then
 
    f.started = false
 
    if f.defeffect then
 
      f.effect = std.clone(f.defeffect)
 
    end
 
    instead.timer(f.timer)
 
    sprite.direct(false)
 
    return std.nop()
 
  end
 
  return
 
end, -1)
 
std.mod_init(function()
 
	f.change { 'crossfade', max = 8 };
 
			
 
	local oldrender = sprite.render_callback()
 
	sprite.render_callback(function()
 
		if f.started and not sprite.direct() then
 
			if oldrender then
 
				oldrender()
 
			end
 
			sprite.direct(true)
 
			sprite.scr():copy(scr2)
 
			scr:copy(sprite.scr())
 
		elseif not f.started and oldrender then
 
			oldrender()
 
		end
 
	end)			
 
  f.change { 'crossfade', max = 8 };
 
      
 
  local oldrender = sprite.render_callback()
 
  sprite.render_callback(function()
 
    if f.started and not sprite.direct() then
 
      if oldrender then
 
        oldrender()
 
      end
 
      sprite.direct(true)
 
      sprite.scr():copy(scr2)
 
      scr:copy(sprite.scr())
 
    elseif not f.started and oldrender then
 
      oldrender()
 
    end
 
  end)      
 
end)
 

	
 

	
 
std.mod_start(function()
 
	scr = sprite.new(theme.get 'scr.w', theme.get 'scr.h')
 
	scr2 = sprite.new(theme.get 'scr.w', theme.get 'scr.h')
 
	if f.defeffect then
 
		f.effect = std.clone(f.defeffect)
 
	end
 
  scr = sprite.new(theme.get 'scr.w', theme.get 'scr.h')
 
  scr2 = sprite.new(theme.get 'scr.w', theme.get 'scr.h')
 
  if f.defeffect then
 
    f.effect = std.clone(f.defeffect)
 
  end
 
end)
 

	
 
std.mod_step(function(state)
 
	if not state then
 
		return
 
	end
 
	if f.enabled and (player_moved() or f.effect.now) and std.cmd[1] ~= 'load' and std.cmd[1] ~= '@fading' then
 
		f.start()
 
	end
 
  if not state then
 
    return
 
  end
 
  if f.enabled and (player_moved() or f.effect.now) and std.cmd[1] ~= 'load' and std.cmd[1] ~= '@fading' then
 
    f.start()
 
  end
 
end)
 

	
 
fading = f
lib/link.lua
Show inline comments
 
require "fmt"
 

	
 
if not instead.atleast(3, 2) then
 
	std.dprint("Warning: link module is not functional on this INSTEAD version")
 
	function instead.clipboard()
 
		return false
 
	end
 
  std.dprint("Warning: link module is not functional on this INSTEAD version")
 
  function instead.clipboard()
 
    return false
 
  end
 
end
 

	
 
obj {
 
	nam = '$link';
 
	act = function(s, w)
 
		if not instead.clipboard or instead.clipboard() ~= w then
 
			std.pr ('{@link ', w, '|', w, '}')
 
		else
 
			std.pr(fmt.u (w) ..' [' .. translate_now("link_locale", 'copied') .. ']')
 
		end
 
	end;
 
  nam = '$link';
 
  act = function(s, w)
 
    if not instead.clipboard or instead.clipboard() ~= w then
 
      std.pr ('{@link ', w, '|', w, '}')
 
    else
 
      std.pr(fmt.u (w) ..' [' .. translate_now("link_locale", 'copied') .. ']')
 
    end
 
  end;
 
}
 

	
 
obj {
 
	nam = '@link';
 
	act = function(s, w)
 
		if instead.clipboard then
 
			instead.clipboard(w)
 
		end
 
	end;
 
  nam = '@link';
 
  act = function(s, w)
 
    if instead.clipboard then
 
      instead.clipboard(w)
 
    end
 
  end;
 
}
lib/locale.lua
Show inline comments
 
local language = ''
 

	
 
local lang_map = {
 
	['ru'] = 'ru',
 
	['by'] = 'ru',
 
	['uk'] = 'ru'
 
  ['ru'] = 'ru',
 
  ['by'] = 'ru',
 
  ['uk'] = 'ru'
 
}
 

	
 
local lang_list = {
 
  {'en', 'English'},
 
  {'eo', 'Esperanto'},
 
  {'ru', 'Русский'},
 
}
 

	
 
@@ -16,24 +17,24 @@ local default_locale = {};
 
local locale = {};
 

	
 
function translate_now(domain, key, subst)
 
	local lang = language
 
	if lang == '' then
 
		if lang_map[LANG] then
 
			lang = lang_map[LANG];
 
		else
 
			lang = 'en';
 
		end;
 
	end;
 
  local lang = language
 
  if lang == '' then
 
    if lang_map[LANG] then
 
      lang = lang_map[LANG];
 
    else
 
      lang = 'en';
 
    end;
 
  end;
 
  local val = key;
 
  local table = locale[domain];
 
  local default_table = default_locale[domain];
 
	if table[key] ~= nil  then
 
  if table[key] ~= nil  then
 
    if table[key] ~= nil then
 
      val = table[key];
 
    elseif default_table[key] ~= nil then
 
      val = default_table[key]
 
    end;
 
	end
 
  end
 
  
 
  if subst then
 
    for k, s in pairs(subst) do
 
@@ -45,25 +46,25 @@ function translate_now(domain, key, subs
 
end;
 

	
 
function translate(domain, key, subst)
 
	return function()
 
		return translate_now(domain, key, subst);
 
	end;
 
  return function()
 
    return translate_now(domain, key, subst);
 
  end;
 
end;
 

	
 
function set_language(lng)
 
	language = lng;
 
	prefs.language = lng;
 
	prefs:store();
 
  language = lng;
 
  prefs.language = lng;
 
  prefs:store();
 
  
 
  dofile('translation/' .. get_language() .. '.lua');
 
end;
 

	
 
obj {
 
	nam = '@set_language';
 
	act = function(s, w)
 
  nam = '@set_language';
 
  act = function(s, w)
 
    set_language(w);
 
		walk(here())
 
	end;
 
    walk(here())
 
  end;
 
}
 

	
 
function get_language_saved()
 
@@ -71,13 +72,13 @@ function get_language_saved()
 
end;
 

	
 
function get_language()
 
	if language and language ~= '' then
 
		return language;
 
	elseif lang_map[LANG] then
 
		return lang_map[LANG];
 
	else
 
		return lang_list[1][1];
 
	end;
 
  if language and language ~= '' then
 
    return language;
 
  elseif lang_map[LANG] then
 
    return lang_map[LANG];
 
  else
 
    return lang_list[1][1];
 
  end;
 
end;
 

	
 
function get_default_language()
 
@@ -95,12 +96,12 @@ end;
 
std.mod_init(function()
 
  dofile('translation/' .. get_language_list()[1][1] .. '.lua');
 
  default_locale = locale;
 
	prefs:load();
 
	if prefs.language then
 
		language = prefs.language;
 
	else
 
		prefs.language = '';
 
	end;
 
  prefs:load();
 
  if prefs.language then
 
    language = prefs.language;
 
  else
 
    prefs.language = '';
 
  end;
 
  
 
  dofile('translation/' .. get_language() .. '.lua');
 
end)
lib/smoke.lua
Show inline comments
 
@@ -4,7 +4,7 @@ Smoke is always transitioned to outside 
 
function smokebg(image, position)
 
  --[[
 
    position: 0 or nil -- center, 1 -- bottom-left
 
  ]]
 
  ]]  
 
  local realscale = diretheme.get_scale();
 
  local ws, hs = diretheme.get_scaled_screen();
 
  local w = ws * realscale;
 
@@ -44,6 +44,10 @@ function coords(x)
 
end;
 

	
 
function enableSmoke(image, position)
 
  if prefs.simplified_animation then
 
    return
 
  end;
 
  
 
  local bg = smokebg(image, position);
 
  
 
  local w, h = diretheme.get_screen();
lib/tiny/stubs.lua
Show inline comments
 
new file 100644
 
--[[
 
  Stub anything to make the game work with tiny instead/plainstead
 
]]
 

	
 
require "click"
 

	
 
-- core instead
 
if std.rawget(_G, "LANG") == nil then
 
  std.rawset(_G, "LANG", 'en');
 
end;
 

	
 
if not std.savepath then
 
  std.savepath = instead.savepath
 
end;
 

	
 
if not instead.autosave then
 
  instead.autosave = function() end;
 
end;
 

	
 
-- lib/fading
 
declare {
 
  fading = {};
 
}
 

	
 
-- lib/smoke
 
function enableSmoke(image, position)
 
end;
 
  
 
-- lib/decor
 
function D(n)
 
  
 
end;
 

	
 
-- diretheme
 
diretheme = obj {
 
  nam = '@diretheme',
 
  get_screen = function() return 800,600; end;
 
  get_scaled_screen = function() return 800,600; end;
 
  get_scale = function() return 1; end;
 
  get_inches = function() return 14; end;
 
  set_theme = function() end;
 
}
lib/utils.lua
Show inline comments
 
@@ -5,30 +5,30 @@ function set_global_keysfilter(func)
 
end;
 

	
 
function keys:filter(press, key)
 
	local rval;
 
	if here().keysfilter then
 
		return here():keysfilter(press, key);
 
	end;
 
	if keysfilter then
 
		return keysfilter(press, key);
 
	end;
 
  local rval;
 
  if here().keysfilter then
 
    return here():keysfilter(press, key);
 
  end;
 
  if keysfilter then
 
    return keysfilter(press, key);
 
  end;
 
end
 

	
 
--[[
 
	Walk from links
 
  Walk from links
 
]]
 
obj {
 
	nam = '@walk';
 
	act = function(s, w)
 
		walk(w)
 
	end;
 
  nam = '@walk';
 
  act = function(s, w)
 
    walk(w)
 
  end;
 
}
 

	
 
obj {
 
	nam = '@walkin';
 
	act = function(s, w)
 
		walkin(w)
 
	end;
 
  nam = '@walkin';
 
  act = function(s, w)
 
    walkin(w)
 
  end;
 
}
 

	
 
function random_phrase(phrases)
 
@@ -36,68 +36,68 @@ function random_phrase(phrases)
 
end;
 

	
 
--[[
 
	Raw text display
 
  Raw text display
 
]]
 
obj {
 
	nam = '$raw';
 
	act = function(s)
 
		local r = std.call(here(), 'rawdsc');
 
		r = string.gsub(r, '\\?[\\^]', { ['^'] = '\n', ['\\^'] = '^'} );
 
  nam = '$raw';
 
  act = function(s)
 
    local r = std.call(here(), 'rawdsc');
 
    r = string.gsub(r, '\\?[\\^]', { ['^'] = '\n', ['\\^'] = '^'} );
 

	
 
		local spaces = false;
 
		local state = '';
 
    local spaces = false;
 
    local state = '';
 

	
 
		for token in string.gmatch(r, '.') do
 
			if spaces then
 
				if token ~= ' ' then
 
					spaces = false;
 
					pr(fmt.nb(state));
 
					state = token;
 
				else
 
					state = state .. token;
 
				end;
 
			else
 
				if token == ' ' then
 
					spaces = true;
 
					pr(state);
 
					state = token;
 
				else
 
					state = state .. token;
 
				end;
 
			end;
 
		end;
 
    for token in string.gmatch(r, '.') do
 
      if spaces then
 
        if token ~= ' ' then
 
          spaces = false;
 
          pr(fmt.nb(state));
 
          state = token;
 
        else
 
          state = state .. token;
 
        end;
 
      else
 
        if token == ' ' then
 
          spaces = true;
 
          pr(state);
 
          state = token;
 
        else
 
          state = state .. token;
 
        end;
 
      end;
 
    end;
 

	
 
		if spaces then
 
			pr(fmt.nb(state));
 
		else
 
			pr(state);
 
		end;
 
	end;
 
    if spaces then
 
      pr(fmt.nb(state));
 
    else
 
      pr(state);
 
    end;
 
  end;
 
}
 

	
 
--[[
 
	Fading control
 
  Fading control
 
]]
 
local oldfading = instead.fading
 

	
 
instead.fading = function()
 
	if here().nofading then
 
		return false;
 
	else
 
		return oldfading()
 
	end;
 
  if here().nofading then
 
    return false;
 
  else
 
    return oldfading()
 
  end;
 
end
 

	
 
local __ds = false;
 

	
 
function has_object (tab, val)
 
	for index, value in ipairs(tab) do
 
		if value.nam == val then
 
			return true
 
		end
 
	end
 
  for index, value in ipairs(tab) do
 
    if value.nam == val then
 
      return true
 
    end
 
  end
 

	
 
	return false
 
  return false
 
end;
 

	
 
function Set (list)
 
@@ -109,72 +109,72 @@ end
 
local old_dlg = dlg;
 

	
 
dlg = function(s)
 
	s.noinv = true;
 
	s.nofollow = true;
 
	return old_dlg(s);
 
  s.noinv = true;
 
  s.nofollow = true;
 
  return old_dlg(s);
 
end;
 

	
 
function table.copy(t)
 
  local t2 = {};
 
  for k,v in pairs(t) do
 
	if type(v) == "table" then
 
		t2[k] = table.copy(v);
 
	else
 
		t2[k] = v;
 
	end
 
  if type(v) == "table" then
 
    t2[k] = table.copy(v);
 
  else
 
    t2[k] = v;
 
  end
 
  end
 
  return t2;
 
end
 

	
 
pathout = std.class({
 
	__path_type = true;
 
	new = function(_, t)
 
		if type(t) ~= 'table' then
 
			std.err("Wrong path argument. Use {} as path argument.", 2)
 
		end
 
		local n, s = t[1], t[2]
 
  __path_type = true;
 
  new = function(_, t)
 
    if type(t) ~= 'table' then
 
      std.err("Wrong path argument. Use {} as path argument.", 2)
 
    end
 
    local n, s = t[1], t[2]
 

	
 
		if not s then
 
			s = n
 
			n = nil
 
		end
 
    if not s then
 
      s = n
 
      n = nil
 
    end
 

	
 
		local new = {
 
			before = s;
 
		}
 
    local new = {
 
      before = s;
 
    }
 

	
 
		for k, v in std.pairs(t) do
 
			if type(k) == 'string' then
 
				new[k] = v
 
			end
 
		end
 
    for k, v in std.pairs(t) do
 
      if type(k) == 'string' then
 
        new[k] = v
 
      end
 
    end
 

	
 
		new.nam = n or new.nam
 
    new.nam = n or new.nam
 

	
 
		return std.room(new)
 
	end;
 
	disp = function(s)
 
		if s.after ~= nil and visited(w) then
 
			return std.call(s, 'after')
 
		end
 
		return std.call(s, 'before')
 
	end;
 
	onwalk = function(s, _)
 
		local r = here():from();
 
		walk(r, true, false, false)
 
		return false
 
	end;
 
    return std.room(new)
 
  end;
 
  disp = function(s)
 
    if s.after ~= nil and visited(w) then
 
      return std.call(s, 'after')
 
    end
 
    return std.call(s, 'before')
 
  end;
 
  onwalk = function(s, _)
 
    local r = here():from();
 
    walk(r, true, false, false)
 
    return false
 
  end;
 
}, std.room)
 

	
 
function robj(t)
 
	if not t.way then
 
		t.way = {
 
			pathout {'Назад'};
 
		};
 
	else
 
		table.insert(t.way, pathout {'Назад'});
 
	end;
 
	return room(t);
 
  if not t.way then
 
    t.way = {
 
      pathout {'Назад'};
 
    };
 
  else
 
    table.insert(t.way, pathout {'Назад'});
 
  end;
 
  return room(t);
 
end;
 

	
 
function split(text, delim)
 
@@ -200,7 +200,17 @@ function split(text, delim)
 
    return result
 
end;
 

	
 
function scale_frame_data(fd)
 
local max = math.max;
 

	
 
function cut_height(h, dy, max_height)
 
  if max_height and h + dy > max_height then
 
    return max(h - (h + dy - max_height), 0);
 
  else
 
    return h;
 
  end;
 
end;
 

	
 
function scale_frame_data(fd, fw, fh)
 
  local scale = diretheme.get_scale();
 
  for _, frame in ipairs(fd) do
 
    if frame['x'] then
 
@@ -213,7 +223,7 @@ function scale_frame_data(fd)
 
      frame['w'] = frame['w'] * scale;
 
    end;
 
    if frame['h'] then
 
      frame['h'] = frame['h'] * scale;
 
      frame['h'] = cut_height(frame['h'] * scale, frame['dy'], fh);
 
    end;
 
    if frame['dx'] then
 
      frame['dx'] = frame['dx'] * scale;
 
@@ -225,3 +235,22 @@ function scale_frame_data(fd)
 
  
 
  return fd;
 
end;
 

	
 
function cat_list(list, sep)
 
  local rval;
 

	
 
  if sep == nil then
 
    sep = '';
 
  end;
 

	
 
  for i, v in ipairs(list) do
 
    if rval then
 
      rval = rval .. sep .. v;
 
    else
 
      rval = v;
 
    end;
 
  end;
 

	
 
  return rval;
 
end;
 

	
main3.lua
Show inline comments
 
@@ -3,23 +3,28 @@
 
-- $Author: Khaelenmore Thaal & Sabra Naikomy$
 
-- $Info: A tiny illustrated text adventure$
 

	
 
if instead.tiny then
 
  require "lib/tiny/stubs"
 
end;
 
require "lib/link"
 
require "noinv"
 
require 'snd'
 
require 'keys'
 
require "timer"
 
require "theme"
 
require "lib/decor"
 
if not instead.tiny then
 
  require "lib/decor"
 
end;
 
require "prefs"
 
if not instead.tiny then
 
  require "lib/dire/theme"
 
end;
 
require 'lib/utils'
 
require "lib/dire/theme"
 
require "lib/locale"
 
require "lib/fading"
 
require "lib/smoke"
 

	
 
declare({
 
    closed_beta_participants = 'arbtttrn6, De@th K!d, Fehatt, Lesha Pak, Łukasz Sawicki, Niko Flang, Oleg Bosh, Terracon, Андрей Лобанов';
 
})
 
if not instead.tiny then
 
  require "lib/fading"
 
  require "lib/smoke"
 
end
 

	
 
fmt.quotes = false;
 
fmt.filter = function(r)
 
@@ -29,30 +34,32 @@ fmt.filter = function(r)
 
        r = r:gsub('"([^"]*)"', translate_now("common_locale", 'quotes'));
 
    end;
 
    
 
    r = r:gsub('<tab>', fmt.nb('    '));
 
    
 
    return r;
 
end;
 

	
 
game.act = translate('main_locale', 'empty_act');
 
game.use = function(s)
 
	return translate_now('main_locale', random_phrase({
 
  return translate_now('main_locale', random_phrase({
 
    'empty_use_1',
 
		'empty_use_2',
 
		'empty_use_3',
 
		'empty_use_4',
 
		'empty_use_5'
 
    'empty_use_2',
 
    'empty_use_3',
 
    'empty_use_4',
 
    'empty_use_5'
 
  }));
 
end;
 
game.inv = translate("main_locale", 'empty_inv');
 

	
 
instead.notitle = function()
 
	return here().notitle;
 
  return here().notitle;
 
end;
 

	
 
function get_graphic_scale()
 
	local rval = prefs.graphic_scale;
 
	
 
	if not rval then
 
		local w, h = diretheme.get_screen();
 
  local rval = prefs.graphic_scale;
 
  
 
  if not rval then
 
    local w, h = diretheme.get_screen();
 
    local wsrec
 
    if diretheme.get_inches() < 7 then
 
      -- On a screen smaller than 7 inch
 
@@ -67,12 +74,12 @@ function get_graphic_scale()
 
      rval = wsrec;
 
    end;
 
    
 
		if rval < 1 then
 
    if rval < 1 then
 
      rval = 1;
 
    end;
 
	end;
 
	
 
	return rval;
 
  end;
 
  
 
  return rval;
 
end;
 

	
 
function get_cursor_scale()
 
@@ -86,71 +93,72 @@ function get_cursor_scale()
 
end;
 

	
 
function get_font_scale()
 
	local rval = prefs.font_scale;
 
	if not rval then
 
		rval = get_graphic_scale() * 100;
 
  local rval = prefs.font_scale;
 
  if not rval then
 
    rval = get_graphic_scale() * 100;
 
    
 
    if diretheme.get_inches() < 7 then
 
      rval = rval + math.floor(rval / 2);
 
    end;
 
	end;
 
	
 
	return rval;
 
  end;
 
  
 
  return rval;
 
end;
 

	
 
function get_inventory_font_scale()
 
	local rval = prefs.inventory_scale;
 
	if not rval then
 
		rval = get_font_scale();
 
	end;
 
	return rval;
 
  local rval = prefs.inventory_scale;
 
  if not rval then
 
    rval = get_font_scale();
 
  end;
 
  return rval;
 
end;
 

	
 
instead.nosave = function()
 
	return here().nosave
 
  return here().nosave
 
end
 

	
 
instead.noautosave = function()
 
	return here().noautosave
 
  return here().noautosave
 
end
 

	
 
std.strip_call = false;
 
std.phrase_show = false;
 

	
 
declare {
 
	current_theme = false,
 
	sounds = {
 
		['bubble'] = snd.new('sound/bubble.ogg');
 
		['potion'] = snd.new('sound/potion.ogg');
 
		['error_beep'] = snd.new('sound/error_beep.ogg');
 
		['long_beep'] = snd.new('sound/long_beep.ogg'); 
 
		['short_beep'] = snd.new('sound/short_beep.ogg'); 
 
		['note_c'] = snd.new('sound/c.ogg');
 
		['note_d'] = snd.new('sound/d.ogg');
 
		['note_e'] = snd.new('sound/e.ogg');
 
		['note_f'] = snd.new('sound/f.ogg');
 
		['note_g'] = snd.new('sound/g.ogg');
 
		['note_a'] = snd.new('sound/a.ogg');
 
		['note_b'] = snd.new('sound/b.ogg');
 
		['wind_gust_1'] = snd.new('sound/wind_blow_1.ogg');
 
		['wind_gust_2'] = snd.new('sound/wind_blow_2.ogg');
 
		['wind_gust_3'] = snd.new('sound/wind_blow_3.ogg');
 
		['open_door'] = snd.new('sound/open_door.ogg');
 
		['pc_startup'] = snd.new('sound/pc_startup.ogg');
 
		['keyboard1'] = snd.new('sound/keyboard1.ogg');
 
		['keyboard2'] = snd.new('sound/keyboard2.ogg');
 
		['keyboard3'] = snd.new('sound/keyboard3.ogg');
 
		['keyboard4'] = snd.new('sound/keyboard4.ogg');
 
		['keyboard5'] = snd.new('sound/keyboard5.ogg');
 
    ['irradiated'] = snd.new('sound/irradiated.ogg');
 
	},
 
	gusts = {
 
		'wind_gust_1';
 
		'wind_gust_2';
 
		'wind_gust_3';
 
	},
 
	menu_sprites = {
 
	},
 
  current_theme = false,
 
  sound_names = {
 
    ['bubble'] = 'sound/bubble.ogg';
 
    ['potion'] = 'sound/potion.ogg';
 
    ['error_beep'] = 'sound/error_beep.ogg';
 
    ['long_beep'] = 'sound/long_beep.ogg';
 
    ['short_beep'] = 'sound/short_beep.ogg';
 
    ['note_c'] = 'sound/c.ogg';
 
    ['note_d'] = 'sound/d.ogg';
 
    ['note_e'] = 'sound/e.ogg';
 
    ['note_f'] = 'sound/f.ogg';
 
    ['note_g'] = 'sound/g.ogg';
 
    ['note_a'] = 'sound/a.ogg';
 
    ['note_b'] = 'sound/b.ogg';
 
    ['wind_gust_1'] = 'sound/wind_blow_1.ogg';
 
    ['wind_gust_2'] = 'sound/wind_blow_2.ogg';
 
    ['wind_gust_3'] = 'sound/wind_blow_3.ogg';
 
    ['open_door'] = 'sound/open_door.ogg';
 
    ['pc_startup'] = 'sound/pc_startup.ogg';
 
    ['keyboard1'] = 'sound/keyboard1.ogg';
 
    ['keyboard2'] = 'sound/keyboard2.ogg';
 
    ['keyboard3'] = 'sound/keyboard3.ogg';
 
    ['keyboard4'] = 'sound/keyboard4.ogg';
 
    ['keyboard5'] = 'sound/keyboard5.ogg';
 
    ['irradiated'] = 'sound/irradiated.ogg';
 
  };
 
  sounds = {},
 
  gusts = {
 
    'wind_gust_1';
 
    'wind_gust_2';
 
    'wind_gust_3';
 
  },
 
  menu_sprites = {
 
  },
 
  last_location = false
 
}
 

	
 
@@ -158,6 +166,42 @@ global {
 
  in_game = false,
 
}
 

	
 
function load_sounds(...)
 
  for i = 1, #arg do
 
    local s = arg[i];
 
    if not sounds[s] then
 
      sounds[s] = snd.new(sound_names[s]);
 
    end;
 
  end;
 
end;
 

	
 
if instead.tiny then
 
  function DSA () end;
 
  function DS () end;
 
else
 
  function DSA (data)
 
    local scale = diretheme.get_scale();
 
    data[3] = get_sprite(data[3]);
 
    data['x'] = data['x'] * scale;
 
    data['y'] = data['y'] * scale;
 
    data['w'] = data['w'] * scale;
 
    data['h'] = data['h'] * scale;
 
    D(data);
 
  end;
 

	
 
  function DS (data)
 
    local scale = diretheme.get_scale();
 
    data[3] = get_sprite(data[3], 'fuchsia');
 
    data['background'] = true;
 
    data['x'] = data['x'] * scale;
 
    data['y'] = data['y'] * scale;
 
    data['w'] = data['w'] * scale;
 
    data['h'] = data['h'] * scale;
 
    D(data);
 
  end;
 
end;
 

	
 
include "game_theme"
 
include "tutorial"
 
include "computer_parts"
 
include "solarscale"
 
@@ -165,61 +209,22 @@ include "tower"
 
include "forest"
 
include "ending"
 

	
 
function get_sprite(path, transparent)
 
	local s = diretheme.get_scale();
 
	
 
	if not menu_sprites[path] then
 
    if s ~= 1 then
 
      menu_sprites[path] = pixels.new(path):scale(s, s):sprite();
 
    else
 
      menu_sprites[path] = sprite.new(path);
 
    end;
 
    if transparent then
 
      menu_sprites[path]:colorkey(transparent);
 
    end;
 
	end;
 
	
 
	return menu_sprites[path];
 
if instead.tiny then
 
  include "tiny_menu"
 
else
 
  include "menu"
 
end;
 

	
 
function get_button(button_name)
 
  local path = 'images/title/' .. button_name .. '.' .. get_language() .. '.png';
 
  if menu_sprites[path] then
 
    return menu_sprites[path];
 
  end;
 
  
 
  local sprite = nil;
 
  
 
  --Check if file exists(only used here, so not moved to function)
 
  local f = io.open(path, 'r');  
 
  if f then
 
    f:close();
 
    sprite = get_sprite(path, 'fuchsia')
 
  end;
 
  
 
  if not sprite then
 
    local path = 'images/title/' .. button_name .. '.' .. get_default_language() .. '.png';
 
    sprite = get_sprite(path, 'fuchsia');
 
  end;
 
  return sprite
 
end;
 

	
 
function stop_menu()
 
	D {'bgframe'};
 
	D {'background'};
 
	D {'bganim'};
 
	D {'title'};
 
end;
 

	
 
game.ondecor = function(s, name, press, x, y, btn)
 
	if press then
 
		if name == 'settings_open' then
 
			in_game = true;
 
			walkin('intro_settings');
 
			return true;
 
		end;
 
	end;
 
	return false;
 
  if press then
 
    if name == 'settings_open' then
 
      in_game = true;
 
      walkin('intro_settings');
 
      return true;
 
    end;
 
  end;
 
  return false;
 
end;
 

	
 
game.afterwalk = function()
 
@@ -230,1626 +235,107 @@ game.afterwalk = function()
 
      _(last_location):themeDispose();
 
    end;
 
  end;
 
	>
 
  
 
  local theme = std.call(here(), 'theme');
 
  
 
  if theme == nil then
 
    error("Theme is unset here: " .. tostring(here().nam));
 
  end;
 
  
 
	if theme ~= nil and theme ~= current_theme then
 
		dprint('Switch theme', current_theme, '->', theme);
 
		set_theme(theme);
 
	end;
 
  if theme ~= nil and theme ~= current_theme then
 
    dprint('Switch theme', current_theme, '->', theme);
 
    set_theme(theme);
 
  end;
 
  
 
  if here().themeInit then
 
		here():themeInit();
 
	end;
 
    here():themeInit();
 
  end;
 
  
 
  last_location = here().nam;
 
end;
 

	
 
function cat_list(list, sep)
 
	local rval;
 

	
 
	if sep == nil then
 
		sep = '';
 
	end;
 

	
 
	for i, v in ipairs(list) do
 
		if rval then
 
			rval = rval .. sep .. v;
 
		else
 
			rval = v;
 
		end;
 
	end;
 

	
 
	return rval;
 
end;
 

	
 
function init_menu(with_text, buttons)
 
  local scale = diretheme.get_scale();
 
	
 
	local w = 960 * scale;
 
	local h = 600 * scale;
 
	local sw, sh = diretheme.get_screen();
 
	local ox = math.floor((sw - w) / 2);
 
	local oy = math.floor((sh - h) / 2)
 
	
 
	local button_dy = 0;
 
	local button_dx = 0;
 
	if sh < 520 * scale then
 
		button_dy = -50;
 
		button_dx = 20;
 
	end;
 
	
 
	local btop = 515;
 
	
 
	if #buttons == 5 then
 
		btop = 435;
 
	end;
 
	
 
	if sh <= 560 * scale then
 
		btop = btop - 20;
 
	end;
 
	
 
	if #buttons == 1 then
 
		D {
 
			buttons[1], 
 
			'img', 
 
      get_button(buttons[1]),
 
			x=ox + 398 * scale, 
 
			y=oy + (btop + button_dy) * scale,
 
			click=true,
 
      background=true,
 
      z=3
 
		};
 
	else
 
		D {
 
			buttons[1], 
 
			'img', 
 
			get_button(buttons[1]),
 
			x=ox + (157 + button_dx) * scale, 
 
			y=oy + (btop + button_dy) * scale,
 
			click=true,
 
      background=true,
 
      z=3
 
		};
 
		D {
 
			buttons[2], 
 
			'img', 
 
			get_button(buttons[2]),
 
			x=ox + 398 * scale,
 
			y=oy + (btop + button_dy) * scale,
 
			click=true,
 
      background=true,
 
      z=3
 
		};
 
		D {
 
			buttons[3], 
 
			'img', 
 
			get_button(buttons[3]),
 
			x=ox + (639 - button_dx) * scale,
 
			y=oy + (btop + button_dy) * scale,
 
			click=true,
 
      background=true,
 
      z=3
 
		};
 
	end;
 
	
 
	if #buttons == 5 then
 
		btop = btop + 80
 
		D {
 
			buttons[4], 
 
			'img', 
 
			get_button(buttons[4]),
 
			x=ox + (278 + button_dx / 2) * scale, 
 
			y=oy + (btop + button_dy) * scale,
 
			click=true,
 
      background=true,
 
      z=3
 
		};
 
		
 
		D {
 
			buttons[5], 
 
			'img', 
 
			get_button(buttons[5]),
 
			x=ox + (519 - button_dx / 2) * scale, 
 
			y=oy + (btop + button_dy) * scale,
 
			click=true,
 
      background=true,
 
      z=3
 
		};
 
	end;
 
	
 
  if sw > w or sh > h then
 
    local bgframe_pixels = pixels.new('images/main_theme/text_bg.png');
 
    local tbg, tbg_slice;
 
    tbg, tbg_slice = dire_slice_9(bgframe_pixels, {
 
      x = 9,
 
      y = 6,
 
      w = 96,
 
      h = 96
 
    });
 
    
 
    local bgframe = pixels.new(978, 612);
 
    dire_draw_9(tbg, bgframe, {x = 0; y = 0; w = 978; h = 612}, {parts=tbg_slice});
 
    D {'bgframe', 'img', bgframe:scale(scale, scale):sprite(), x=ox - 9 * scale, y=oy - 6 * scale, w=w + 18 * scale, h=h + 12 * scale, background=true, z=5};
 
end;
 
  
 
  if not D('background') then
 
    D {'background', 'img', get_sprite('images/title/bg.png'), x=ox, y=oy, z=4, background=true};
 
  end;
 

	
 
	if not D('bganim') then
 
		D {'bganim', 'img', get_sprite('images/title/bg_frames.png'), x=ox, y=oy, w=w, h=h, frames=16, z=3, delay=200, animated=true, background=true, frame_data=scale_frame_data({
 
       {},
 
       {x=0, y=0, w=960, h=302, dx=0, dy=0},
 
       {x=960, y=0, w=960, h=302, dx=0, dy=0},
 
       {x=1920, y=0, w=960, h=302, dx=0, dy=0},
 
       {x=2880, y=0, w=960, h=302, dx=0, dy=0},
 
       {x=0, y=302, w=960, h=302, dx=0, dy=0},
 
       {x=960, y=302, w=960, h=302, dx=0, dy=0},
 
       {x=1920, y=302, w=960, h=302, dx=0, dy=0},
 
       {x=2880, y=302, w=960, h=302, dx=0, dy=0},
 
       {x=0, y=604, w=960, h=302, dx=0, dy=0},
 
       {x=960, y=604, w=960, h=302, dx=0, dy=0},
 
       {x=1920, y=604, w=960, h=302, dx=0, dy=0},
 
       {x=2880, y=604, w=960, h=302, dx=0, dy=0},
 
       {x=0, y=906, w=960, h=302, dx=0, dy=0},
 
       {x=960, y=906, w=960, h=302, dx=0, dy=0},
 
       {x=1920, y=906, w=960, h=302, dx=0, dy=0}
 
    })};
 
	end;
 
	if not D('title') then
 
		D {'title', 'img', get_sprite('images/title/title.png', 'fuchsia'), x=ox + 230 * scale, y=oy + 88  * scale, z=2, background=true};
 
	end;
 
	
 
	if with_text then
 
		D {'textbg', 'img', get_sprite('images/title/text_background.png', 'fuchsia'), x=ox + 180 * scale, z=1, y=oy + (126 + button_dy) * scale, background=true};
 
		if sh < 520 * scale then
 
			D {'title'}
 
		else
 
			D('title').y = oy + 40 * scale;
 
		end;
 
	else
 
		D('title').y = oy + 88 * scale;
 
	end;
 
	
 
	timer:set(25);
 
end;
 

	
 
room {
 
	nam = 'main';
 
	notitle = true;
 
	nosave = true;
 
	noautosave = true;
 
	noinv = true;
 
	nofading = true;
 
	disp = '';
 
	theme = 'menu';
 
	onenter = function(s)
 
		in_game = false;
 
	end;
 
	themeInit = function(s)
 
		init_menu(false, {'start', 'load', 'about', 'settings', 'quit'});
 
	end;
 
	themeDispose = function(s)
 
		D {'start'};
 
		D {'load'};
 
		D {'about'};
 
		D {'settings'};
 
		D {'quit'};
 
		timer:stop();
 
	end;
 
	ondecor = function(s, name, press, x, y, btn)
 
		if press then
 
			if name == 'start' then
 
				walk('intro_start');
 
				return true;
 
			elseif  name == 'load' then
 
				instead.menu('load');
 
				return true;
 
			elseif name == 'about' then
 
				walk('intro_info');
 
				return true;
 
			elseif name == 'settings' then
 
				walk('intro_settings');
 
				return true;
 
			elseif  name == 'quit' then
 
				instead.menu('exit');
 
				return true;
 
			end;
 
		end;
 
		return false;
 
	end;
 
	enter = function(s)
 
    if prefs.completed then
 
      snd.music('sound/bgm_credits.ogg');
 
    else
 
      snd.music('sound/bgm_intro.ogg');
 
  nosave = true;
 
  noautosave = true;
 
  nofollow = true;
 
  theme = 'black';
 
  noinv = true;
 
  nam = 'resolution_warning';
 
  title = translate("menu_locale", 'warning');
 
  decor = translate("menu_locale", 'resolution_warning');
 
  onenter = stop_menu;
 
}: with {
 
  obj {
 
    nam = '#sysset';
 
    dsc = function(s) return '{' .. translate_now("menu_locale", 'system_settings') .. '}'; end;
 
    act = function(s)
 
      instead.menu();
 
    end;
 
	end;
 
}
 

	
 
room {
 
	nam = 'intro_start';
 
	notitle = true;
 
	nosave = true;
 
	noautosave = true;
 
	noinv = true;
 
	nofading = true;
 
	disp = '';
 
	theme = 'menu';
 
	themeInit = function(s)
 
		init_menu(true, {'back', 'tutorial', 'start'});
 
	end;
 
	themeDispose = function(s)
 
		D {'back'};
 
		D {'tutorial'};
 
		D {'start'};
 
		D {'textbg'};
 
		timer:stop();
 
	end;
 
	ondecor = function(s, name, press, x, y, btn)
 
		if press then
 
			if name == 'start' then
 
				walk('above_forest');
 
				in_game = true;
 
				return true;
 
			elseif name == 'tutorial' then
 
				walk('tutorial_start');
 
				in_game = true;
 
				return true;
 
			elseif name == 'back' then
 
				walk('main');
 
				return true;
 
			end;
 
		end;
 
		return false;
 
	end;
 
	decor = translate("menu_locale", 'intro');
 
}
 

	
 
room {
 
	nam = 'intro_info';
 
	notitle = true;
 
	nosave = true;
 
	noautosave = true;
 
	noinv = true;
 
	nofading = true;
 
	disp = '';
 
	theme = 'menu';
 
	themeInit = function(s)
 
		init_menu(true, {'back'});
 
	end;
 
	themeDispose = function(s)
 
		D {'start'};
 
		D {'back'};
 
		D {'settings'};
 
		D {'textbg'};
 
		timer:stop();
 
	end;
 
	ondecor = function(s, name, press, x, y, btn)
 
		if press then
 
			if name == 'back' then
 
				if in_game then
 
					walk('menu');
 
				else
 
					walk('main');
 
				end;
 
				return true;
 
			end;
 
		end;
 
		return false;
 
	end;
 
	decor = function(s)
 
		return translate_now("menu_locale", 'credits_author') .. ': Khaelenmore Thaal^' ..
 
			translate_now("menu_locale", 'credits_art') .. ': Sabra Naikomy^' ..
 
			translate_now("menu_locale", 'credits_music') .. ': Khaelenmore Thaal^' ..
 
			translate_now("menu_locale", 'credits_engine') .. ': INSTEAD ' .. translate_now("menu_locale", 'credits_engine_author') .. ' {$link https://github.com/instead-hub/instead/}^' ..
 
			translate_now("menu_locale", 'credits_sounds') .. ': {$link https://freesound.org/} CC-0^' ..
 
			translate_now("menu_locale", 'credits_fonts') .. ': VileR {$link https://int10h.org/oldschool-pc-fonts/} CC-BY-SA 4.0^^' ..
 
      translate_now("menu_locale", 'credits_closed_beta') .. ': ' .. closed_beta_participants .. '^^'..
 
			translate_now("menu_locale", 'credits_thanks');
 
	end;
 
}
 

	
 
obj {
 
	nam = 'empty';
 
	dsc = '^';
 
  }
 
}
 

	
 
room {
 
	nam = 'intro_settings';
 
	nofollow = true;
 
	notitle = true;
 
	nosave = true;
 
	noautosave = true;
 
	noinv = true;
 
	nofading = true;
 
	disp = '';
 
	theme = 'menu';
 
	themeInit = function(s)
 
    init_menu(true, {'back'});
 
	end;
 
	themeDispose = function(s)
 
		D {'start'};
 
		D {'about'};
 
		D {'back'};
 
		D {'textbg'};
 
		timer:stop();
 
	end;
 
	ondecor = function(s, name, press, x, y, btn)
 
		if press then
 
			if name == 'back' then
 
				if in_game then
 
					stop_menu();
 
					walkback();
 
				else
 
					walk('main');
 
				end;
 
				return true;
 
			end;
 
		end;
 
		return false;
 
	end;
 
}:with {
 
	obj {
 
		nam = '#system_settings';
 
		dsc = function(s)
 
			return fmt.c(fmt.b('{[' .. translate_now("menu_locale", 'system_settings') .. ']}^^'));
 
		end;
 
		act = function(s)
 
			instead.menu('settings');
 
		end;
 
	};
 
	obj {
 
		nam = '#language';
 
		dsc = function(s)
 
			local l = translate_now("menu_locale", 'auto_option');
 
			
 

	
 
			pn(fmt.c(fmt.b(translate_now("menu_locale", 'language'))));
 
			
 
			local t;
 
			if get_language_saved() == '' then
 
				t = l;
 
			else
 
				t = '{#l_auto|'.. l .. '}';
 
			end;
 
			
 
      for i, language in ipairs(get_language_list()) do
 
        if get_language_saved() == language[1] then
 
          t = t .. ' | ' .. language[2];
 
        else
 
          t = t .. ' | ' .. '{@set_language ' .. language[1] .. '|' .. language[2] .. '}';
 
        end;
 
      end;
 
		
 
			pn(fmt.c(t) .. '^')
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#l_auto';
 
			act = function(s)
 
				set_language('');
 
				walk(here());
 
			end;
 
		};
 
	};
 
	obj {
 
		nam = '#graphics_scale';
 
		dsc = function(s)
 
			local graphic_scale = get_graphic_scale();
 
			
 
			pn(fmt.c(fmt.b(translate_now("menu_locale", 'graphic_scale')) .. ' {[' .. translate_now("menu_locale", 'auto_option') .. ']}'))
 
		
 
			local t = '';
 
			
 
			if graphic_scale > 1 then
 
				t = t .. '{#g_less|<<} ';
 
			else
 
				t = t .. '<< ';
 
			end;
 

	
 
			local l =  translate_now("menu_locale", 'auto_option') .. ' (' .. tostring(graphic_scale * 100) .. '%)';
 
			
 
			
 
			if prefs.graphic_scale then
 
				l = tostring(graphic_scale * 100) .. '%';
 
			end;
 

	
 
			t = t .. l;
 

	
 
			local w, h = diretheme.get_screen();
 
		
 
			local wsmax = math.floor(w / 640);
 
			local smax = math.floor(h / 480);
 
			if wsmax < smax then
 
				smax = wsmax;
 
			end;
 
		
 
			if smax < 1 then
 
				smax = 1;
 
			end;
 
		
 
			if graphic_scale < smax then
 
				t = t .. ' {#g_more|>>}';
 
			else
 
				t = t .. ' >>';
 
			end;
 
		
 
			pn(fmt.c(t) .. '^');
 
		end;
 
		act = function(s)
 
			prefs.graphic_scale = false;
 
			prefs:store();
 
		
 
			set_theme(std.call(here(), 'theme'));
 
			menu_sprites = {};
 
			here():themeDispose();
 
			stop_menu();
 
			here():themeInit();
 
			walk(here());
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#g_less';
 
			act = function(s)
 
				prefs.graphic_scale = get_graphic_scale() - 1;
 
				
 
				prefs:store();
 
		
 
				set_theme(std.call(here(), 'theme'));
 
				menu_sprites = {};
 
				here():themeDispose();
 
				stop_menu();
 
				here():themeInit();
 
				walk(here());
 
			end;
 
		};
 
		obj {
 
			nam = '#g_more';
 
			act = function(s)
 
				prefs.graphic_scale = get_graphic_scale() + 1;
 
				
 
				prefs:store();
 
		
 
				set_theme(std.call(here(), 'theme'));
 
				menu_sprites = {};
 
				here():themeDispose();
 
				stop_menu();
 
				here():themeInit();
 
				walk(here());
 
			end;
 
		};
 
	};
 
  nosave = true;
 
  noautosave = true;
 
  nofollow = true;
 
  theme = 'black';
 
  noinv = true;
 
  nam = 'theme_warning';
 
  title = translate("menu_locale", 'warning');
 
  decor = translate("menu_locale", 'theme_warning');
 
  onenter = stop_menu;
 
}: with {
 
  obj {
 
		nam = '#cursor_scale';
 
		dsc = function(s)
 
			local cursor_scale = get_cursor_scale();
 
			
 
			pn(fmt.c(fmt.b(translate_now("menu_locale", 'cursor_scale')) .. ' {[' .. translate_now("menu_locale", 'auto_option') .. ']}'))
 
		
 
			local t = '';
 
			
 
			if cursor_scale > 1 then
 
				t = t .. '{#cursor_less|<<} ';
 
			else
 
				t = t .. '<< ';
 
			end;
 

	
 
			local l = translate_now("menu_locale", 'auto_option') .. ' (' .. tostring(cursor_scale * 100) .. '%)';
 
			
 
			if prefs.cursor_scale then
 
				l = tostring(cursor_scale * 100) .. '%';
 
			end;
 

	
 
			t = t .. l;
 

	
 
			local w, h = diretheme.get_screen();
 
		
 
			local wsmax = math.floor(w / 640);
 
			local smax = math.floor(h / 480);
 
			if wsmax < smax then
 
				smax = wsmax;
 
			end;
 
		
 
			if smax < 1 then
 
				smax = 1;
 
			end;
 
		
 
			if cursor_scale < smax then
 
				t = t .. ' {#cursor_more|>>}';
 
			else
 
				t = t .. ' >>';
 
			end;
 
		
 
			pn(fmt.c(t) .. '^');
 
		end;
 
		act = function(s)
 
			prefs.cursor_scale = false;
 
			prefs:store();
 
		
 
			set_theme(std.call(here(), 'theme'));
 
			menu_sprites = {};
 
			here():themeDispose();
 
			stop_menu();
 
			here():themeInit();
 
			walk(here());
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#cursor_less';
 
			act = function(s)
 
				prefs.cursor_scale = get_cursor_scale() - 1;
 
				
 
				prefs:store();
 
		
 
				set_theme(std.call(here(), 'theme'));
 
				menu_sprites = {};
 
				here():themeDispose();
 
				stop_menu();
 
				here():themeInit();
 
				walk(here());
 
			end;
 
		};
 
		obj {
 
			nam = '#cursor_more';
 
			act = function(s)
 
				prefs.cursor_scale = get_cursor_scale() + 1;
 
				
 
				prefs:store();
 
		
 
				set_theme(std.call(here(), 'theme'));
 
				menu_sprites = {};
 
				here():themeDispose();
 
				stop_menu();
 
				here():themeInit();
 
				walk(here());
 
			end;
 
		};
 
	};
 
	obj {
 
		nam = '#font_scale';
 
		dsc = function(s)		
 
			local graphic_scale = get_graphic_scale();
 
			local font_scale = get_font_scale();
 
				
 
			pn(fmt.c(fmt.b(translate_now("menu_locale", 'font_scale')) .. ' {[' .. translate_now("menu_locale", 'auto_option') .. ']}'));
 
		
 
			local t = '';
 
		
 
			if font_scale > 50 then
 
				t = t .. '{#f_less|<<} ';
 
			else
 
				t = t .. '<< ';
 
			end;
 
		
 
			if prefs.font_scale then
 
				t = t .. tostring(font_scale) .. '%';
 
			else
 
				t = t .. translate_now("menu_locale", 'auto_option') .. ' (' .. tostring(font_scale) .. '%)';
 
			end;
 
		
 
		
 
			if font_scale < graphic_scale * 200 then
 
				t = t .. ' {#f_more|>>}';
 
			else
 
				t = t .. ' >>';
 
			end;
 
		
 
			pn(fmt.c(t) .. '^');
 
		end;
 
		act = function(s)
 
			prefs.font_scale = false;
 
		
 
			prefs:store();
 
			set_theme(std.call(here(), 'theme'));
 
			walk(here());
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#f_less';
 
			act = function(s)
 
				prefs.font_scale = get_font_scale() - 10;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
		obj {
 
			nam = '#f_more';
 
			act = function(s)
 
				prefs.font_scale = get_font_scale() + 10;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
	};
 
	obj {
 
		nam = '#inv_font_scale';
 
		dsc = function(s)		
 
			local graphic_scale = get_graphic_scale();
 
			local font_scale = get_inventory_font_scale();
 
				
 
			pn(fmt.c(fmt.b(translate_now("menu_locale", 'inventory_scale')) .. ' {[' .. translate_now("menu_locale", 'auto_option') .. ']}'));
 
		
 
			local t = '';
 
		
 
			if font_scale > 50 then
 
				t = t .. '{#if_less|<<} ';
 
			else
 
				t = t .. '<< ';
 
			end;
 
		
 
			if prefs.inventory_scale then
 
				t = t .. tostring(font_scale) .. '%';
 
			else
 
				t = t .. translate_now("menu_locale", 'auto_option') .. ' (' .. tostring(font_scale) .. '%)';
 
			end;
 
		
 
		
 
			if font_scale < graphic_scale * 200 then
 
				t = t .. ' {#if_more|>>}';
 
			else
 
				t = t .. ' >>';
 
			end;
 
		
 
			pn(fmt.c(t) .. '^');
 
		end;
 
		act = function(s)
 
			prefs.inventory_scale = false;
 
		
 
			prefs:store();
 
			set_theme(std.call(here(), 'theme'));
 
			walk(here());
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#if_less';
 
			act = function(s)
 
				prefs.inventory_scale = get_inventory_font_scale() - 10;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
		obj {
 
			nam = '#if_more';
 
			act = function(s)
 
				prefs.inventory_scale = get_inventory_font_scale() + 10;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
	};
 
	obj {
 
		nam = '#text_width';
 
		dsc = function(s)
 
			pn(fmt.c(fmt.b(translate_now("menu_locale", 'text_width'))));
 
			local t = '';
 
			if prefs.text_width > 40 then
 
				t = t .. '{#fw_less|<<} ';
 
			else
 
				t = t .. '<< ';
 
			end;
 

	
 
			t = t .. tostring(prefs.text_width) .. '%';
 
		
 
			if prefs.text_width < 100 then
 
				t = t .. ' {#fw_more|>>}';
 
			else
 
				t = t .. ' >>';
 
			end;
 
		
 
			pn(fmt.c(t) .. '^');
 
		end;
 
		act = function(s)
 
			if not prefs.text_width then
 
				prefs.text_width = 100;
 
			end;
 
		
 
			prefs.text_width = prefs.text_width + 20;
 
		
 
			if prefs.text_width > 100 then
 
				prefs.text_width = 40;
 
			end;
 
		
 
			prefs:store();
 
		
 
			walk(here());
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#fw_less';
 
			act = function(s)
 
				prefs.text_width = prefs.text_width - 10;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
		obj {
 
			nam = '#fw_more';
 
			act = function(s)
 
				prefs.text_width = prefs.text_width + 10;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
	};
 
	obj {
 
		nam = '#text_alignment';
 
		dsc = function(s)
 
			pn(fmt.c(fmt.b(translate_now("menu_locale", 'text_alignment'))));
 
			
 
			local t = '';
 
		
 
			if prefs.text_alignment == 1 then
 
				t = t .. translate_now("menu_locale", 'text_alignment_justify') .. ' | ';
 
			else
 
				t = t .. '{#align_just|' .. translate_now("menu_locale", 'text_alignment_justify') .. '} | ';
 
			end;
 
			
 
		
 
			if prefs.text_alignment == 2 then
 
				t = t .. translate_now("menu_locale", 'text_alignment_left');
 
			else
 
				t = t .. '{#align_left|' .. translate_now("menu_locale", 'text_alignment_left') .. '}';
 
			end;
 
			pn(fmt.c(t) .. '^');
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#align_just';
 
			act = function(s)
 
				prefs.text_alignment = 1;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
		obj {
 
			nam = '#align_left';
 
			act = function(s)
 
				prefs.text_alignment = 2;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
	};
 
	obj {
 
		nam = '#padding';
 
		dsc = function(s)
 
			pn(fmt.c(fmt.b(translate_now("menu_locale", 'padding'))));
 
			
 
			local t = '';
 
		
 
			if prefs.text_padding == 1 then
 
				t = t .. translate_now("menu_locale", 'normal') .. ' | ';
 
			else
 
				t = t .. '{#pad_norm|' .. translate_now("menu_locale", 'normal') .. '} | ';
 
			end;
 
			
 
		
 
			if prefs.text_padding == 2 then
 
				t = t .. translate_now("menu_locale", 'extended');
 
			else
 
				t = t .. '{#pad_large|' .. translate_now("menu_locale", 'extended') .. '}';
 
			end;
 
			pn(fmt.c(t) .. '^');
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#pad_norm';
 
			act = function(s)
 
				prefs.text_padding = 1;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
		obj {
 
			nam = '#pad_large';
 
			act = function(s)
 
				prefs.text_padding = 2;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
	};
 
	obj {
 
		nam = '#interval';
 
		dsc = function(s)
 
			pn(fmt.c(fmt.b(translate_now("menu_locale", 'interval'))));
 
			
 
			local t = '';
 
		
 
			if prefs.text_interval == 1 then
 
				t = t .. translate_now("menu_locale", 'normal') .. ' | ';
 
			else
 
				t = t .. '{#int_norm|' .. translate_now("menu_locale", 'normal') .. '} | ';
 
			end;
 
			
 
		
 
			if prefs.text_interval == 2 then
 
				t = t .. translate_now("menu_locale", 'extended');
 
			else
 
				t = t .. '{#int_large|' .. translate_now("menu_locale", 'extended') .. '}';
 
			end;
 
			pn(fmt.c(t) .. '^');
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#int_norm';
 
			act = function(s)
 
				prefs.text_interval = 1;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
		obj {
 
			nam = '#int_large';
 
			act = function(s)
 
				prefs.text_interval = 2;
 
			
 
				prefs:store();
 
				set_theme(std.call(here(), 'theme'));
 
				walk(here());
 
			end;
 
		};
 
	};
 
  obj {
 
    nam = '#textinput';
 
    dsc = function(s)
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'use_text_input'))));
 
      
 
      local t = '';
 
      if prefs.text_input then
 
        t = '{#ti_disable|' .. translate_now("menu_locale", 'disable') .. '} | ' .. translate_now("menu_locale", 'enable');
 
			else
 
				t = translate_now("menu_locale", 'disable') .. ' | {#ti_enable|' .. translate_now("menu_locale", 'enable') .. '}';
 
			end;
 
      
 
      pn(fmt.c(t) .. '^');
 
    nam = '#sysset';
 
    dsc = function(s) return '{' .. translate_now("menu_locale", 'system_settings') .. '}'; end;
 
    act = function(s)
 
      instead.menu();
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#ti_disable';
 
      act = function(s)
 
        prefs.text_input = false;
 
        prefs:store();
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#ti_enable';
 
      act = function(s)
 
        prefs.text_input = true;
 
        prefs:store();
 
        walk(here());
 
      end;
 
    };
 
  };
 
}
 

	
 
room {
 
	nosave = true;
 
	noautosave = true;
 
  nofollow = true;
 
	theme = 'black';
 
  noinv = true;
 
	nam = 'resolution_warning';
 
	title = translate("menu_locale", 'warning');
 
	decor = translate("menu_locale", 'resolution_warning');
 
	onenter = stop_menu;
 
}: with {
 
	obj {
 
		nam = '#sysset';
 
		dsc = function(s) return '{' .. translate_now("menu_locale", 'system_settings') .. '}'; end;
 
		act = function(s)
 
			instead.menu();
 
		end;
 
	}
 
}
 

	
 
room {
 
	nosave = true;
 
	noautosave = true;
 
  nofollow = true;
 
	theme = 'black';
 
  noinv = true;
 
	nam = 'theme_warning';
 
	title = translate("menu_locale", 'warning');
 
	decor = translate("menu_locale", 'theme_warning');
 
	onenter = stop_menu;
 
}: with {
 
	obj {
 
		nam = '#sysset';
 
		dsc = function(s) return '{' .. translate_now("menu_locale", 'system_settings') .. '}'; end;
 
		act = function(s)
 
			instead.menu();
 
		end;
 
	}
 
  }
 
}
 

	
 
function set_theme(t)  
 
  -- resetting defaults
 
  fmt.para = true;
 
  std.scene_delim = '^^';
 
  theme.set('snd.click', 'sound/click.wav');
 
  
 
	D {'settings_open'};
 

	
 
  local tname, tcolor_text, tcolor_link, tcolor_alink;
 

	
 
  local width, height = diretheme.get_screen();
 
	
 
  -- 640x480 is the base size
 
	local scale = get_graphic_scale();
 
	local max_scale_x = math.floor(width / 640);
 
	local max_scale_y = math.floor(height / 480);
 
	-- Fail-safe for too small screen
 
  if max_scale_x < 1 then max_scale_x = 1; end;
 
  if max_scale_y < 1 then max_scale_y = 1; end;
 
	  
 
  local max_scale = math.min(max_scale_x, max_scale_y);
 
  
 
  if scale > max_scale then
 
    scale = max_scale;
 
    prefs.graphic_scale = false;
 
  end;
 
  
 
  local cursor_scale = get_cursor_scale();
 
  if cursor_scale > 2 * max_scale then
 
    cursor_scale = 2 * max_scale;
 
  end;
 
  
 
	local font_scale = get_font_scale() / 100;
 
	if font_scale > 2 * scale then
 
		font_scale = scale;
 
		prefs.font_scale = font_scale * 100
 
	end;
 
	
 
  local inv_scale = get_inventory_font_scale() / 100;
 
	
 
	local text_align = 'justify';
 
	if prefs.text_alignment == 2 then
 
		text_align = 'left';
 
	end;
 
	
 
	local hpadding, vpadding = 0, 0;
 
	if prefs.text_padding == 2 then
 
		hpadding, vpadding = 24, 12;
 
	end;
 
	
 
	local interval = '1.0';
 
	if prefs.text_interval == 2 then
 
		interval = '1.5';
 
	end;
 
	
 
	local canvas = diretheme.set_canvas({rmax = 2, rmin = 1});
 
	diretheme.set_scale(scale);
 

	
 
  local scaled_width, scaled_height = diretheme.get_scaled_screen();
 

	
 
	current_theme = t;
 
  local tvariant = 0;
 
  if t:match("_bw$") then
 
    t = t:gsub("_bw$", "");
 
    tvariant = 1;
 
  end;
 
  
 
  -- Most text area settings are per-theme
 
  local text_area = {};
 
  
 
  -- Hide inventory by default
 
  local inventory = {
 
    rect = {
 
      lx = width + 1,
 
      y = 0,
 
      wmax = 1,
 
      wmin = 1,
 
      ty = 2,
 
      by = 2,
 
      ax = 1
 
    }
 
  };
 
  
 
  -- And image
 
  local image_area = {
 
    rect = {
 
      lx = width + 1,
 
      ax = 1,
 
      wmax = 584,
 
      hmax = 258,
 
      wmin = 584,
 
      hmin = 258
 
    };
 
    bg = {};
 
    mode = 'float';
 
  };
 
  
 
  -- Preset colors
 
  local theme_directory = nil;
 
  local text_color, link_color, alink_color;
 
  local inv_color, inv_link, inv_alink;
 
  if t == 'terminal' or t == 'black' then
 
    diretheme.set_canvas({
 
      lx = 0, ty = 0, rx = 0, by = 0
 
    });
 
    text_color = '#D0FFFF';
 
    link_color = '#ABDECE';
 
    alink_color = '#9BCEBE';  
 
    theme_directory = 'images/tower_theme';
 
    
 
    text_area.text = {
 
      font = 'fonts/vga.ttf',
 
      color = text_color,
 
      link = link_color,
 
      alink = alink_color,
 
      size = 16
 
    };
 
function start(load)
 
  dprint('start', load);
 
  last_location = here().nam;
 
  local w, h = diretheme.get_screen();
 
  local name = theme.name();
 
  if instead.tiny then
 
    if not load then
 
      take('tiny_ingame_settings');
 
    end;
 
  else
 
    canvas = diretheme.set_canvas({
 
      lx = 0, ty = 0, rx = 0, by = 0, rmin = 1.2, rmax = 1.8
 
    });
 
    
 
    if t == 'menu' or t == 'main' or t == 'ending_outside' or t == 'credits_outside' then
 
      inv_color = '#403426';
 
      inv_link = '#403426';
 
      inv_alink = '#61503A';
 
      
 
      if tvariant == 0 then
 
        text_color = '#000504';
 
        link_color = '#80382A';
 
        alink_color = '#80605D';
 
        theme_directory = 'images/main_theme';
 
      else
 
        text_color = '#040404';
 
        link_color = '#434343';
 
        alink_color = '#585858';
 
        theme_directory = 'images/bwm_theme';
 
    if here() ~= _'theme_warning' and here() ~= _'resolution_warning' then
 
      if name ~= '.' then
 
        walkin('theme_warning');
 
        
 
        game:reaction(false);
 
        local r = game:display(true);
 
        game:lastdisp(r);
 
      end;
 
      
 
      text_area.uppos = {ax=1, x = 12, y = 0, ay=-1};
 
      text_area.downpos = {ax=1, x = 12, y = 0, ay=1};
 
      text_area.bg = {
 
        image = theme_directory .. '/text_bg.png',
 
        options = {
 
          mode = 6,
 
          drawmethod = 2,
 
          slice = {
 
            x = 9,
 
            y = 6,
 
            w = 96,
 
            h = 96
 
          },
 
          scale = true
 
        }
 
      };
 
    elseif t == 'tower' or t == 'ending_inside' or t == 'credits_inside' then
 
      inv_color = '#6b9e8e';
 
      inv_link = '#9bcebe';
 
      inv_alink = '#Bbeede';
 
      
 
      if tvariant == 0 then
 
        text_color = '#93DDCD';
 
        link_color = '#E0F0EA';
 
        alink_color = '#FFFFFF';
 
        theme_directory = 'images/tower_theme';
 
      else
 
        text_color = '#ADADAD';
 
        link_color = '#CDCDCD';
 
        alink_color = '#BDBDBD';
 
        theme_directory = 'images/bwt_theme';
 
      if w < 640 or h < 480 then
 
        walkin('resolution_warning');
 
        
 
        game:reaction(false);
 
        local r = game:display(true);
 
        game:lastdisp(r);
 
      end;
 
      
 
      text_area.uppos = {ax=1, x = 16, y = 0, ay=-1};
 
      text_area.downpos = {ax=1, x = 16, y = 0, ay=1};
 
      text_area.bg = {
 
        image = theme_directory .. '/text_bg.png',
 
        options = {
 
          mode = 6,
 
          drawmethod = 2,
 
          slice = {
 
            x = 6,
 
            y = 6,
 
            w = 128,
 
            h = 128
 
          },
 
          scale = true
 
        }
 
      };
 
    end;
 
    
 
    if t == 'ending_inside' or t == 'ending_outside' then
 
      canvas = diretheme.set_canvas({
 
        lx = 0, ty = 0, rx = 0, by = 0
 
      });
 
    end;
 
  
 
    text_area.align = text_align;
 
    text_area.height = interval;
 
    text_area.scaleui = true;
 
    text_area.up = theme_directory .. '/arrow_up.png';
 
    text_area.down = theme_directory .. '/arrow_down.png';
 
    text_area.text = {
 
      font = 'fonts/{sans,sans-b,sans-i,sans-bi}.ttf',
 
      color = text_color,
 
      link = link_color,
 
      alink = alink_color,
 
      size = math.floor(16 * font_scale),
 
      noscale = true
 
    };
 
    
 
    inventory.up = theme_directory .. '/arrow_up.png';
 
    inventory.down = theme_directory .. '/arrow_down.png';
 
    inventory.uppos = {ax=1, x = 8, y = 0, ay=-1};
 
    inventory.downpos = {ax=1, x = 8, y = 0, ay=1};
 
    inventory.text = {
 
      color = inv_color,
 
      link = inv_link,
 
      alink = inv_alink,
 
      size = math.floor(16 * inv_scale),
 
      noscale = true
 
    };
 
    inventory.height = interval;
 
  end;
 
  
 
  if t == 'main' or t == 'tower' then
 
    std.scene_delim = '^' .. fmt.c(fmt.img(theme_directory .. '/line_separator.png')) .. '^'
 
  end;
 
  
 
 -- And menu, but need theme_directory to have proper button image
 
  local menu = {
 
    button = {
 
      image = theme_directory ..'/menu.png';
 
      options = {
 
        mode = 1,
 
        scale = true
 
      }
 
    };
 
    buttonrect = {
 
      x = width + 1,
 
      y = 0,
 
      w = 50,
 
      h = 16
 
    };
 
    text = {
 
      size = math.floor(15 * font_scale),
 
      noscale = true
 
    },
 
    height = interval,
 
    scaleui = true;
 
  };
 
  
 
  local cursor, active_cursor = 'images/cursor.png', 'images/cursor_active.png';
 
  if tvariant == 1 then
 
    cursor, active_cursor = 'images/cursor_bw.png', 'images/cursor_active_bw.png'
 
  end;
 
  
 
  diretheme.set_cursor({
 
		x = 2,
 
		y = 2,
 
		normal = cursor,
 
		active = active_cursor,
 
    scale = true;
 
		scalefactor = cursor_scale;
 
	});
 
  
 
	if t == 'menu' then
 
		diretheme.set_background('#89C6AE', 255, 'images/main_theme/background.png', {mode=2, scale=true});
 
    local padding_delta = -10;
 
    if height < 520 * scale then
 
      padding_delta = -95;
 
    end;
 
    
 
    text_area.rect = {
 
      ty = padding_delta + vpadding,
 
      wmax = 538 - hpadding * 2,
 
      hmax = 322 - vpadding * 2,
 
      ay = 0
 
    };
 
    text_area.text = text_area.text;
 
    text_area.uppos = {ax=1, x = 15, y = 65, ay=-1};
 
    text_area.downpos = {ax=1, x = 15, y = -20, ay=1};
 
    text_area.contentrect = {wf=prefs.text_width / 100};
 
    text_area.bg = '';
 
	elseif t == 'main' then
 
		diretheme.set_background('#89C6AE', 255, 'images/main_theme/background.png', {mode=2, scale = true});
 
		
 
		local image_bg = 'images/main_theme/picture_bg.png';
 
		if canvas.w < 800 * scale then
 
			image_bg = 'images/main_theme/picture_bg_small.png';
 
		end;
 
		
 
    image_area.leftof = 'inv';
 
    image_area.topof = 'text';
 
    image_area.rect = {
 
      ax = 0,
 
      wmax = 584,
 
      hmax = 265,
 
      wmin = 584,
 
      hmin = 265
 
    };
 
    image_area.contentrect = {
 
      ax = 0,
 
      ay = -1,
 
      ty = 11,
 
      wmin = 320,
 
      hmin = 240,
 
      wmax = 320,
 
      hmax = 240
 
    };
 
    image_area.bg = {
 
      image = image_bg,
 
      options = {
 
        mode = 1,
 
        scale = true
 
      }
 
    };
 
		
 
    text_area.leftof = 'inv';
 
    text_area.rect = {
 
      lx = 7,
 
      ty = 266,
 
      rx = 8,
 
      by = 2,
 
      ax = 1,
 
      ay = 1
 
    };
 
    text_area.contentrect = {
 
      lx = 21 + hpadding,
 
      rx = 21 + hpadding,
 
      ty = 14 + vpadding,
 
      by = 14 + vpadding,
 
      wf=prefs.text_width / 100
 
    };
 
    
 
		inventory.rect = {
 
      rx = 2,
 
      y = 2,
 
      wmax = 208,
 
      wmin = 208,
 
      ty = 2,
 
      by = 2,
 
      ax = 1
 
    };
 
    inventory.contentrect = {
 
      lx = 25,
 
      rx = 25,
 
      ty = 40,
 
      by = 40
 
    };
 
    inventory.bg = {
 
      image = function(tpx, rect)
 
        local top = pixels.new('images/main_theme/inv_top.png'):scale(scale, scale, false);
 
        local mid = pixels.new('images/main_theme/inv_mid.png'):scale(scale, scale, false);
 
        local bottom = pixels.new('images/main_theme/inv_bottom.png'):scale(scale, scale, false);
 
        
 
        dire_draw_tile(mid, tpx, { x=rect.x + 11 * scale, y=rect.y + 10 * scale, w=rect.w - 22 * scale, h = rect.h - 20 * scale}, {});
 
        dire_draw_center(top, tpx, {x=rect.x, y=rect.y, w=208 * scale, h=60 * scale});
 
        dire_draw_center(bottom, tpx, {x=rect.x, y=rect.y + rect.h - 60 * scale, w=208 * scale, h=60 * scale});
 
      end,
 
      options = {scale = true}
 
    };
 

	
 
    menu.buttonrect = {
 
      wmin = 50,
 
      wmax = 50,
 
      hmin = 16,
 
      hmax = 16,
 
      by = 12,
 
      ay = 1,
 
      rx = 81,
 
      ax = 1
 
    };
 

	
 
		D {
 
			'settings_open', 
 
			'raw',
 
			x=canvas.x + canvas.w - 33 * scale, 
 
			y=canvas.y + canvas.h - 30 * scale, 
 
      xc=0,
 
      yc=0,
 
      w=24 * scale,
 
      h=22 * scale,
 
			click=true
 
		};
 
	elseif t == 'tower' then
 
		diretheme.set_background('#181E37', 255, 'images/tower_theme/background.png', {mode=2, scale=true});
 
		
 
		local image_bg = 'images/tower_theme/picture_bg.png';
 
		if canvas.w < 800 * scale then
 
			image_bg = 'images/tower_theme/picture_bg_small.png';
 
		end;
 
		
 
    image_area.leftof='inv';
 
    image_area.topof='text';
 
    image_area.rect = {
 
      ax = 0,
 
      maxw = 584,
 
      maxh = 258,
 
      minw = 584,
 
      minh = 258
 
    };
 
    image_area.contentrect = {
 
      ax = 0,
 
      ay = -1,
 
      ty = 12,
 
      wmin = 320,
 
      hmin = 240,
 
      wmax = 320,
 
      hmax = 240
 
    };
 
    image_area.bg = {
 
      image = image_bg,
 
      options = {
 
        mode = 1,
 
        scale = true
 
      }
 
    };
 
		
 
    text_area.leftof = 'inv';
 
    text_area.rect = {
 
      lx = 7,
 
      ty = 266,
 
      rx = 8,
 
      by = 2,
 
      ax = 1,
 
      ay = 1
 
    };
 
    text_area.contentrect = {
 
      lx = 21 + hpadding,
 
      rx = 21 + hpadding,
 
      ty = 14 + vpadding,
 
      by = 14 + vpadding,
 
      wf = prefs.text_width / 100
 
    };
 
  set_theme(std.call(here(), 'theme'));
 
  
 
    inventory.rect = {
 
      rx = 2,
 
      y = 2,
 
      wmax = 208,
 
      wmin = 208,
 
      ty = 2,
 
      by = 2,
 
      ax = 1
 
    };
 
    inventory.contentrect = {
 
      lx = 12,
 
      rx = 16,
 
      ty = 10,
 
      by = 40
 
    };
 
    inventory.bg = {
 
      image = function(tpx, rect)
 
        local bg = pixels.new('images/tower_theme/inv_bg.png'):scale(scale, scale, false);
 
        local icon = pixels.new('images/tower_theme/settings.png'):scale(scale, scale, false);
 
        
 
        local tbg, tbg_slice = dire_slice_9(bg, {
 
          x = 7 * scale,
 
          y = 11 * scale,
 
          w = 194 * scale,
 
          h = 38 * scale
 
        })
 
        
 
        dire_draw_9(tbg, tpx, rect, {parts=tbg_slice});
 
        
 
        dire_draw_center(icon, tpx, {x = rect.x + rect.w - 33 * scale, y = rect.y + rect.h - 35 * scale, w = 24 * scale, h = 22 * scale});
 
      end
 
    };
 
    
 
    menu.buttonrect = {
 
      wmin = 50,
 
      wmax = 50,
 
      hmin = 16,
 
      hmax = 16,
 
      by = 20,
 
      ay = 1,
 
      rx = 81,
 
      ax = 1
 
    };
 
		
 
		D {
 
			'settings_open', 
 
			'raw', 
 
			x=canvas.x + canvas.w - 35 * scale, 
 
			y=canvas.y + canvas.h - 37 * scale,
 
      xc=0,
 
      yc=0,
 
      w=24 * scale,
 
      h=22 * scale,
 
			click=true
 
		};
 
	elseif t == 'terminal' then
 
		theme.set('snd.click', '');
 
		
 
    local upshift = 0;
 
    if height / scale < 540 then
 
      upshift = 19;
 
    end;
 
    
 
    local px = pixels.new(scaled_width, scaled_height);
 
		local tiles_src = pixels.new('images/terminal/table_tiles.png');
 
    local backdrop_src = pixels.new('images/terminal/backdrop.png');
 
		
 
		local tabletop = scaled_height - 422 - upshift
 
		if tabletop < 335 - upshift then
 
			tabletop = 335 - upshift;
 
		end;
 
		
 
		dire_draw_tile(tiles_src, px, {
 
			w = scaled_width,
 
			h = 422,
 
			x = 0,
 
			y = tabletop
 
		}, {xoffset = -1, yoffxet = -1});
 

	
 
    dire_draw_tile(backdrop_src, px, {
 
			w = scaled_width,
 
			h = tabletop,
 
			x = 0,
 
			y = 0
 
		}, {xoffset = -1, yoffset = -2});
 
		
 
		diretheme.set_background('#181E37', 255, px, {mode=5});
 
		
 
		local ty
 
		if here().ticks ~= nil and here().ticks < 128 and here().graphical then
 
			ty = 72
 
		else
 
			ty = 2
 
		end;		
 

	
 
    text_area.rect = {
 
      ty = 0 - upshift,
 
      by = 189,
 
      wmin = 808,
 
      hmin = 568,
 
      wmax = 808,
 
      hmax = 568,
 
      ax = 0,
 
      ay = 1
 
    };
 
    text_area.contentrect = {
 
      wmax = 569,
 
      hmax = 390,
 
      ty = ty,
 
      ax = 0,
 
      ay = -2,
 
      dx = -16
 
    };
 
    text_area.bg = {
 
      image = 'images/terminal/bg_text.png',
 
      options = {
 
        mode = 1,
 
        scale = true
 
      }
 
    };
 
	elseif t == 'ending_outside' then
 
		diretheme.set_background('#89C6AE', 255, theme_directory .. '/background.png', {mode=2, scale=true});
 
		
 
    text_area.rect = {
 
      lx = 24,
 
      rx = 24,
 
      wmax = 600,
 
      hmax = 160,
 
      by = 24,
 
      ay = 1
 
    };
 
    text_area.contentrect = {
 
      lx = 18 + hpadding,
 
      rx = 18 + hpadding,
 
      ty = 14 + vpadding,
 
      by = 14 + vpadding,
 
      wf = prefs.text_width / 100
 
    };
 
	elseif t == 'ending_inside' then
 
		diretheme.set_background('#181E37', 255, theme_directory .. '/background.png', {mode=2});
 
		
 
    text_area.rect = {
 
      lx = 24,
 
      rx = 24,
 
      wmax = 600,
 
      hmax = 160,
 
      by = 24,
 
      ay = 1
 
    };
 
    text_area.contentrect = {
 
      lx = 18 + hpadding,
 
      rx = 18 + hpadding,
 
      ty = 14 + vpadding,
 
      by = 14 + vpadding,
 
      wf = prefs.text_width / 100
 
    };
 
  elseif t == 'credits_outside' or t == 'credits_inside' then
 
    -- text scaled on top of picture
 
    text_area.rect = {
 
      wmax = 960,
 
      hmax = 600
 
    };
 
    text_area.bg = {};
 
    text_area.align = 'center';
 
    text_area.content_rect = {
 
      wf = prefs.text_width / 100
 
    };
 
	elseif t == 'black' then    
 
		fmt.para = false;
 
		diretheme.set_background('#000000', 255);
 
		
 
		text_area.rect = {
 
      wmax = 600,
 
      hmax = 400,
 
      ax = 0,
 
      ay = 0
 
    };
 
    text_area.align = 'center';
 
	end;
 
  
 
  diretheme.set_image_area(image_area, true);
 
  diretheme.set_text_area(text_area, true);
 
  diretheme.set_inventory_area(inventory, true);
 
  
 
  diretheme.set_menu(menu, true);
 
end;
 

	
 
function start(load)
 
	dprint('start', load);
 
  last_location = here().nam;
 
	local w, h = diretheme.get_screen();
 
	local name = theme.name();
 
	if here() ~= _'theme_warning' and here() ~= _'resolution_warning' then
 
		if name ~= '.' then
 
			walkin('theme_warning');
 
      
 
      game:reaction(false);
 
      local r = game:display(true);
 
      game:lastdisp(r);
 
		end;
 
		
 
		if w < 640 or h < 480 then
 
			walkin('resolution_warning');
 
      
 
      game:reaction(false);
 
      local r = game:display(true);
 
      game:lastdisp(r);
 
		end;
 
	end;
 
  
 
	set_theme(std.call(here(), 'theme'));
 
	
 
  diretheme.set_theme();
 
  
 
	if load then
 
		if here().themeInit then
 
			here():themeInit();
 
		end;
 
  if load then
 
    if here().themeInit then
 
      here():themeInit();
 
    end;
 

	
 
		if here().onboot then
 
			here():onboot();
 
		end;
 
	else
 
    if here().onboot then
 
      here():onboot();
 
    end;
 
  else
 
    local words = {
 
      "biography",
 
      "algorithm",
 
@@ -1931,64 +417,75 @@ function start(load)
 
    password2 = make_password();
 
    
 
    local computer_parts = {
 
			'cvx-rst-i3sb',
 
			'mcpu70-cvx-7mhz',
 
			'rst-m16-16mb',
 
			'tva-rx1',
 
			'fna-100-10mbs_1',
 
			'kbc-s'
 
		};
 
      'cvx-rst-i3sb',
 
      'mcpu70-cvx-7mhz',
 
      'rst-m16-16mb',
 
      'tva-rx1',
 
      'fna-100-10mbs_1',
 
      'kbc-s'
 
    };
 
    
 
		local bpi = rnd(#computer_parts);
 
		_(computer_parts[bpi]).status = false;
 
		computer_parts[bpi] = computer_parts[#computer_parts];
 
		computer_parts[#computer_parts] = nil;
 
    local bpi = rnd(#computer_parts);
 
    _(computer_parts[bpi]).status = false;
 
    computer_parts[bpi] = computer_parts[#computer_parts];
 
    computer_parts[#computer_parts] = nil;
 
 
 
		bpi = rnd(#computer_parts);
 
		_(computer_parts[bpi]).status = false;
 
		
 
		-- Debug
 
	end;
 
    bpi = rnd(#computer_parts);
 
    _(computer_parts[bpi]).status = false;
 
    
 
    -- Debug
 
  end;
 
end;
 

	
 
function init()   
 
	if not prefs.graphic_scale then
 
		prefs.graphic_scale = false;
 
	end;
 
function init()
 
  if not prefs.graphic_scale then
 
    prefs.graphic_scale = false;
 
  end;
 
  
 
  if not prefs.cursor_scale then
 
		prefs.cursor_scale = false;
 
	end;
 
    prefs.cursor_scale = false;
 
  end;
 
  
 
  if not prefs.text_input then
 
    prefs.text_input = true;
 
  end;
 
  
 
  if not prefs.completed then
 
		prefs.completed = false;
 
	end;
 
	
 
	if not prefs.font_scale then
 
		prefs.font_scale = false;
 
	end;
 
	
 
	if not prefs.inventory_scale then
 
		prefs.inventory_scale = false;
 
	end;
 
	
 
	if not prefs.text_alignment then
 
		prefs.text_alignment = 1;
 
	end;
 
	
 
	if not prefs.text_padding then
 
		prefs.text_padding = 1;
 
	end;
 
	
 
	if not prefs.text_interval then
 
		prefs.text_interval = 1;
 
	end;
 
	
 
	if not prefs.text_width then
 
		prefs.text_width = 100;
 
	end;
 
    prefs.completed = false;
 
  end;
 
  
 
  if not prefs.font_scale then
 
    prefs.font_scale = false;
 
  end;
 
  
 
  if not prefs.inventory_scale then
 
    prefs.inventory_scale = false;
 
  end;
 
  
 
  if not prefs.text_alignment then
 
    prefs.text_alignment = 1;
 
  end;
 
  
 
  if not prefs.text_padding then
 
    prefs.text_padding = 1;
 
  end;
 
  
 
  if not prefs.text_interval then
 
    prefs.text_interval = 1;
 
  end;
 
  
 
  if not prefs.text_width then
 
    prefs.text_width = 100;
 
  end;
 
  
 
  if not instead.tiny and prefs.simplified_animation == nil then
 
    -- Tiny performance test
 
    local a = sprite.new(640, 480);
 
    local b = sprite.new(640, 480);
 
    local t = instead.ticks();
 
    b:copy(a, 0, 0);
 
    t = instead.ticks() - t;
 
    dprint(t);
 
    prefs.simplified_animation = t > 10;
 
  end;
 
end;
menu.lua
Show inline comments
 
new file 100644
 
function get_sprite(path, transparent)
 
  local s = diretheme.get_scale();
 
  
 
  if not menu_sprites[path] then
 
    if s ~= 1 then
 
      menu_sprites[path] = pixels.new(path):scale(s, s):sprite();
 
    else
 
      menu_sprites[path] = sprite.new(path);
 
    end;
 
    if transparent then
 
      menu_sprites[path]:colorkey(transparent);
 
    end;
 
  end;
 
  
 
  return menu_sprites[path];
 
end;
 

	
 
function get_button(button_name)
 
  local path = 'images/title/' .. button_name .. '.' .. get_language() .. '.png';
 
  if menu_sprites[path] then
 
    return menu_sprites[path];
 
  end;
 
  
 
  local sprite = nil;
 
  
 
  --Check if file exists(only used here, so not moved to function)
 
  local f = io.open(path, 'r');  
 
  if f then
 
    f:close();
 
    sprite = get_sprite(path, 'fuchsia')
 
  end;
 
  
 
  if not sprite then
 
    local path = 'images/title/' .. button_name .. '.' .. get_default_language() .. '.png';
 
    sprite = get_sprite(path, 'fuchsia');
 
  end;
 
  return sprite
 
end;
 

	
 
function stop_menu()
 
  D {'bgframe'};
 
  D {'background'};
 
  D {'bganim'};
 
  D {'title'};
 
end;
 

	
 
function init_menu(with_text, buttons)
 
  local scale = diretheme.get_scale();
 
  
 
  local w = 960 * scale;
 
  local h = 600 * scale;
 
  local sw, sh = diretheme.get_screen();
 
  local ox = math.floor((sw - w) / 2);
 
  local oy = math.floor((sh - h) / 2)
 
  
 
  local button_dy = 0;
 
  local button_dx = 0;
 
  if sh < 520 * scale then
 
    button_dy = -50;
 
    button_dx = 20;
 
  end;
 
  
 
  local btop = 515;
 
  
 
  if #buttons == 5 then
 
    btop = 435;
 
  end;
 
  
 
  if sh <= 560 * scale then
 
    btop = btop - 20;
 
  end;
 
  
 
  if #buttons == 1 then
 
    D {
 
      buttons[1], 
 
      'img', 
 
      get_button(buttons[1]),
 
      x=ox + 398 * scale, 
 
      y=oy + (btop + button_dy) * scale,
 
      click=true,
 
      background=true,
 
      z=3
 
    };
 
  else
 
    D {
 
      buttons[1], 
 
      'img', 
 
      get_button(buttons[1]),
 
      x=ox + (157 + button_dx) * scale, 
 
      y=oy + (btop + button_dy) * scale,
 
      click=true,
 
      background=true,
 
      z=3
 
    };
 
    D {
 
      buttons[2], 
 
      'img', 
 
      get_button(buttons[2]),
 
      x=ox + 398 * scale,
 
      y=oy + (btop + button_dy) * scale,
 
      click=true,
 
      background=true,
 
      z=3
 
    };
 
    D {
 
      buttons[3], 
 
      'img', 
 
      get_button(buttons[3]),
 
      x=ox + (639 - button_dx) * scale,
 
      y=oy + (btop + button_dy) * scale,
 
      click=true,
 
      background=true,
 
      z=3
 
    };
 
  end;
 
  
 
  if #buttons == 5 then
 
    btop = btop + 80
 
    D {
 
      buttons[4], 
 
      'img', 
 
      get_button(buttons[4]),
 
      x=ox + (278 + button_dx / 2) * scale, 
 
      y=oy + (btop + button_dy) * scale,
 
      click=true,
 
      background=true,
 
      z=3
 
    };
 
    
 
    D {
 
      buttons[5], 
 
      'img', 
 
      get_button(buttons[5]),
 
      x=ox + (519 - button_dx / 2) * scale, 
 
      y=oy + (btop + button_dy) * scale,
 
      click=true,
 
      background=true,
 
      z=3
 
    };
 
  end;
 
  
 
  if sw > w or sh > h then
 
    local bgframe_pixels = pixels.new('images/main_theme/text_bg.png');
 
    local tbg, tbg_slice;
 
    tbg, tbg_slice = dire_slice_9(bgframe_pixels, {
 
      x = 9,
 
      y = 6,
 
      w = 96,
 
      h = 96
 
    });
 
    
 
    local bgframe = pixels.new(978, 612);
 
    dire_draw_9(tbg, bgframe, {x = 0; y = 0; w = 978; h = 612}, {parts=tbg_slice});
 
    D {'bgframe', 'img', bgframe:scale(scale, scale):sprite(), x=ox - 9 * scale, y=oy - 6 * scale, w=w + 18 * scale, h=h + 12 * scale, background=true, z=5};
 
  end;
 
  
 
  if not D('background') then
 
    D {'background', 'img', get_sprite('images/title/bg.png'), x=ox, y=oy, z=4, background=true};
 
  end;
 

	
 
  if prefs.simplified_animation then
 
    D {'bganim'};
 
  elseif not D('bganim') then
 
    D {'bganim', 'img', get_sprite('images/title/bg_frames.png'), x=ox, y=oy, w=w, h=h, frames=16, z=3, delay=200, animated=true, background=true, frame_data=scale_frame_data({
 
       {},
 
       {x=0, y=0, w=960, h=302, dx=0, dy=0},
 
       {x=960, y=0, w=960, h=302, dx=0, dy=0},
 
       {x=1920, y=0, w=960, h=302, dx=0, dy=0},
 
       {x=2880, y=0, w=960, h=302, dx=0, dy=0},
 
       {x=0, y=302, w=960, h=302, dx=0, dy=0},
 
       {x=960, y=302, w=960, h=302, dx=0, dy=0},
 
       {x=1920, y=302, w=960, h=302, dx=0, dy=0},
 
       {x=2880, y=302, w=960, h=302, dx=0, dy=0},
 
       {x=0, y=604, w=960, h=302, dx=0, dy=0},
 
       {x=960, y=604, w=960, h=302, dx=0, dy=0},
 
       {x=1920, y=604, w=960, h=302, dx=0, dy=0},
 
       {x=2880, y=604, w=960, h=302, dx=0, dy=0},
 
       {x=0, y=906, w=960, h=302, dx=0, dy=0},
 
       {x=960, y=906, w=960, h=302, dx=0, dy=0},
 
       {x=1920, y=906, w=960, h=302, dx=0, dy=0}
 
    })};
 
  end;
 
  if not D('title') then
 
    D {'title', 'img', get_sprite('images/title/title.png', 'fuchsia'), x=ox + 230 * scale, y=oy + 88  * scale, z=2, background=true};
 
  end;
 
  
 
  if with_text then
 
    D {'textbg', 'img', get_sprite('images/title/text_background.png', 'fuchsia'), x=ox + 180 * scale, z=1, y=oy + (126 + button_dy) * scale, background=true};
 
    if sh < 520 * scale then
 
      D {'title'}
 
    else
 
      D('title').y = oy + 40 * scale;
 
    end;
 
  else
 
    D('title').y = oy + 88 * scale;
 
  end;
 
  
 
  timer:set(25);
 
end;
 

	
 
room {
 
  nam = 'main';
 
  notitle = true;
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
  nofading = true;
 
  disp = '';
 
  theme = 'menu';
 
  onenter = function(s)
 
    in_game = false;
 
  end;
 
  themeInit = function(s)
 
    init_menu(false, {'start', 'load', 'about', 'settings', 'quit'});
 
  end;
 
  themeDispose = function(s)
 
    D {'start'};
 
    D {'load'};
 
    D {'about'};
 
    D {'settings'};
 
    D {'quit'};
 
    timer:stop();
 
  end;
 
  ondecor = function(s, name, press, x, y, btn)
 
    if press then
 
      if name == 'start' then
 
        walk('intro_start');
 
        return true;
 
      elseif  name == 'load' then
 
        instead.menu('load');
 
        return true;
 
      elseif name == 'about' then
 
        walk('intro_info');
 
        return true;
 
      elseif name == 'settings' then
 
        walk('intro_settings');
 
        return true;
 
      elseif  name == 'quit' then
 
        instead.menu('exit');
 
        return true;
 
      end;
 
    end;
 
    return false;
 
  end;
 
  enter = function(s)
 
    if prefs.completed then
 
      snd.music('sound/bgm_credits.ogg');
 
    else
 
      snd.music('sound/bgm_intro.ogg');
 
    end;
 
  end;
 
}
 

	
 
room {
 
  nam = 'intro_start';
 
  notitle = true;
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
  nofading = true;
 
  disp = '';
 
  theme = 'menu';
 
  themeInit = function(s)
 
    init_menu(true, {'back', 'tutorial', 'start'});
 
  end;
 
  themeDispose = function(s)
 
    D {'back'};
 
    D {'tutorial'};
 
    D {'start'};
 
    D {'textbg'};
 
    timer:stop();
 
  end;
 
  ondecor = function(s, name, press, x, y, btn)
 
    if press then
 
      if name == 'start' then
 
        walk('above_forest');
 
        in_game = true;
 
        return true;
 
      elseif name == 'tutorial' then
 
        walk('tutorial_start');
 
        in_game = true;
 
        return true;
 
      elseif name == 'back' then
 
        walk('main');
 
        return true;
 
      end;
 
    end;
 
    return false;
 
  end;
 
  decor = translate("menu_locale", 'intro');
 
}
 

	
 
room {
 
  nam = 'intro_info';
 
  notitle = true;
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
  nofading = true;
 
  disp = '';
 
  theme = 'menu';
 
  themeInit = function(s)
 
    init_menu(true, {'back'});
 
  end;
 
  themeDispose = function(s)
 
    D {'start'};
 
    D {'back'};
 
    D {'settings'};
 
    D {'textbg'};
 
    timer:stop();
 
  end;
 
  ondecor = function(s, name, press, x, y, btn)
 
    if press then
 
      if name == 'back' then
 
        if in_game then
 
          walk('menu');
 
        else
 
          walk('main');
 
        end;
 
        return true;
 
      end;
 
    end;
 
    return false;
 
  end;
 
  decor = function(s)
 
    return credits_text(false);
 
  end;
 
}
 

	
 
room {
 
  nam = 'intro_settings';
 
  nofollow = true;
 
  notitle = true;
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
  nofading = true;
 
  disp = '';
 
  theme = 'menu';
 
  themeInit = function(s)
 
    init_menu(true, {'back'});
 
  end;
 
  themeDispose = function(s)
 
    D {'start'};
 
    D {'about'};
 
    D {'back'};
 
    D {'textbg'};
 
    timer:stop();
 
  end;
 
  ondecor = function(s, name, press, x, y, btn)
 
    if press then
 
      if name == 'back' then
 
        if in_game then
 
          stop_menu();
 
          walkback();
 
        else
 
          walk('main');
 
        end;
 
        return true;
 
      end;
 
    end;
 
    return false;
 
  end;
 
}:with {
 
  obj {
 
    nam = '#system_settings';
 
    dsc = function(s)
 
      return fmt.c(fmt.b('{[' .. translate_now("menu_locale", 'system_settings') .. ']}^^'));
 
    end;
 
    act = function(s)
 
      instead.menu('settings');
 
    end;
 
  };
 
  obj {
 
    nam = '#language';
 
    dsc = function(s)
 
      local l = translate_now("menu_locale", 'auto_option');
 
      
 

	
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'language'))));
 
      
 
      local t;
 
      if get_language_saved() == '' then
 
        t = l;
 
      else
 
        t = '{#l_auto|'.. l .. '}';
 
      end;
 
      
 
      for i, language in ipairs(get_language_list()) do
 
        if get_language_saved() == language[1] then
 
          t = t .. ' | ' .. language[2];
 
        else
 
          t = t .. ' | ' .. '{@set_language ' .. language[1] .. '|' .. language[2] .. '}';
 
        end;
 
      end;
 
    
 
      pn(fmt.c(t) .. '^')
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#l_auto';
 
      act = function(s)
 
        set_language('');
 
        walk(here());
 
      end;
 
    };
 
  };
 
  obj {
 
    nam = '#graphics_scale';
 
    dsc = function(s)
 
      local graphic_scale = get_graphic_scale();
 
      
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'graphic_scale')) .. ' {[' .. translate_now("menu_locale", 'auto_option') .. ']}'))
 
    
 
      local t = '';
 
      
 
      if graphic_scale > 1 then
 
        t = t .. '{#g_less|<<} ';
 
      else
 
        t = t .. '<< ';
 
      end;
 

	
 
      local l =  translate_now("menu_locale", 'auto_option') .. ' (' .. tostring(graphic_scale * 100) .. '%)';
 
      
 
      
 
      if prefs.graphic_scale then
 
        l = tostring(graphic_scale * 100) .. '%';
 
      end;
 

	
 
      t = t .. l;
 

	
 
      local w, h = diretheme.get_screen();
 
    
 
      local wsmax = math.floor(w / 640);
 
      local smax = math.floor(h / 480);
 
      if wsmax < smax then
 
        smax = wsmax;
 
      end;
 
    
 
      if smax < 1 then
 
        smax = 1;
 
      end;
 
    
 
      if graphic_scale < smax then
 
        t = t .. ' {#g_more|>>}';
 
      else
 
        t = t .. ' >>';
 
      end;
 
    
 
      pn(fmt.c(t) .. '^');
 
    end;
 
    act = function(s)
 
      prefs.graphic_scale = false;
 
      prefs:store();
 
    
 
      set_theme(std.call(here(), 'theme'));
 
      menu_sprites = {};
 
      here():themeDispose();
 
      stop_menu();
 
      here():themeInit();
 
      walk(here());
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#g_less';
 
      act = function(s)
 
        prefs.graphic_scale = get_graphic_scale() - 1;
 
        
 
        prefs:store();
 
    
 
        set_theme(std.call(here(), 'theme'));
 
        menu_sprites = {};
 
        here():themeDispose();
 
        stop_menu();
 
        here():themeInit();
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#g_more';
 
      act = function(s)
 
        prefs.graphic_scale = get_graphic_scale() + 1;
 
        
 
        prefs:store();
 
    
 
        set_theme(std.call(here(), 'theme'));
 
        menu_sprites = {};
 
        here():themeDispose();
 
        stop_menu();
 
        here():themeInit();
 
        walk(here());
 
      end;
 
    };
 
  };
 
  obj {
 
    nam = '#cursor_scale';
 
    dsc = function(s)
 
      local cursor_scale = get_cursor_scale();
 
      
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'cursor_scale')) .. ' {[' .. translate_now("menu_locale", 'auto_option') .. ']}'))
 
    
 
      local t = '';
 
      
 
      if cursor_scale > 1 then
 
        t = t .. '{#cursor_less|<<} ';
 
      else
 
        t = t .. '<< ';
 
      end;
 

	
 
      local l = translate_now("menu_locale", 'auto_option') .. ' (' .. tostring(cursor_scale * 100) .. '%)';
 
      
 
      if prefs.cursor_scale then
 
        l = tostring(cursor_scale * 100) .. '%';
 
      end;
 

	
 
      t = t .. l;
 

	
 
      local w, h = diretheme.get_screen();
 
    
 
      local wsmax = math.floor(w / 640);
 
      local smax = math.floor(h / 480);
 
      if wsmax < smax then
 
        smax = wsmax;
 
      end;
 
    
 
      if smax < 1 then
 
        smax = 1;
 
      end;
 
    
 
      if cursor_scale < smax then
 
        t = t .. ' {#cursor_more|>>}';
 
      else
 
        t = t .. ' >>';
 
      end;
 
    
 
      pn(fmt.c(t) .. '^');
 
    end;
 
    act = function(s)
 
      prefs.cursor_scale = false;
 
      prefs:store();
 
    
 
      set_theme(std.call(here(), 'theme'));
 
      menu_sprites = {};
 
      here():themeDispose();
 
      stop_menu();
 
      here():themeInit();
 
      walk(here());
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#cursor_less';
 
      act = function(s)
 
        prefs.cursor_scale = get_cursor_scale() - 1;
 
        
 
        prefs:store();
 
    
 
        set_theme(std.call(here(), 'theme'));
 
        menu_sprites = {};
 
        here():themeDispose();
 
        stop_menu();
 
        here():themeInit();
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#cursor_more';
 
      act = function(s)
 
        prefs.cursor_scale = get_cursor_scale() + 1;
 
        
 
        prefs:store();
 
    
 
        set_theme(std.call(here(), 'theme'));
 
        menu_sprites = {};
 
        here():themeDispose();
 
        stop_menu();
 
        here():themeInit();
 
        walk(here());
 
      end;
 
    };
 
  };
 
  obj {
 
    nam = '#font_scale';
 
    dsc = function(s)    
 
      local graphic_scale = get_graphic_scale();
 
      local font_scale = get_font_scale();
 
        
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'font_scale')) .. ' {[' .. translate_now("menu_locale", 'auto_option') .. ']}'));
 
    
 
      local t = '';
 
    
 
      if font_scale > 50 then
 
        t = t .. '{#f_less|<<} ';
 
      else
 
        t = t .. '<< ';
 
      end;
 
    
 
      if prefs.font_scale then
 
        t = t .. tostring(font_scale) .. '%';
 
      else
 
        t = t .. translate_now("menu_locale", 'auto_option') .. ' (' .. tostring(font_scale) .. '%)';
 
      end;
 
    
 
    
 
      if font_scale < graphic_scale * 200 then
 
        t = t .. ' {#f_more|>>}';
 
      else
 
        t = t .. ' >>';
 
      end;
 
    
 
      pn(fmt.c(t) .. '^');
 
    end;
 
    act = function(s)
 
      prefs.font_scale = false;
 
    
 
      prefs:store();
 
      set_theme(std.call(here(), 'theme'));
 
      walk(here());
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#f_less';
 
      act = function(s)
 
        prefs.font_scale = get_font_scale() - 10;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#f_more';
 
      act = function(s)
 
        prefs.font_scale = get_font_scale() + 10;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
  };
 
  obj {
 
    nam = '#inv_font_scale';
 
    dsc = function(s)    
 
      local graphic_scale = get_graphic_scale();
 
      local font_scale = get_inventory_font_scale();
 
        
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'inventory_scale')) .. ' {[' .. translate_now("menu_locale", 'auto_option') .. ']}'));
 
    
 
      local t = '';
 
    
 
      if font_scale > 50 then
 
        t = t .. '{#if_less|<<} ';
 
      else
 
        t = t .. '<< ';
 
      end;
 
    
 
      if prefs.inventory_scale then
 
        t = t .. tostring(font_scale) .. '%';
 
      else
 
        t = t .. translate_now("menu_locale", 'auto_option') .. ' (' .. tostring(font_scale) .. '%)';
 
      end;
 
    
 
    
 
      if font_scale < graphic_scale * 200 then
 
        t = t .. ' {#if_more|>>}';
 
      else
 
        t = t .. ' >>';
 
      end;
 
    
 
      pn(fmt.c(t) .. '^');
 
    end;
 
    act = function(s)
 
      prefs.inventory_scale = false;
 
    
 
      prefs:store();
 
      set_theme(std.call(here(), 'theme'));
 
      walk(here());
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#if_less';
 
      act = function(s)
 
        prefs.inventory_scale = get_inventory_font_scale() - 10;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#if_more';
 
      act = function(s)
 
        prefs.inventory_scale = get_inventory_font_scale() + 10;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
  };
 
  obj {
 
    nam = '#text_width';
 
    dsc = function(s)
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'text_width'))));
 
      local t = '';
 
      if prefs.text_width > 40 then
 
        t = t .. '{#fw_less|<<} ';
 
      else
 
        t = t .. '<< ';
 
      end;
 

	
 
      t = t .. tostring(prefs.text_width) .. '%';
 
    
 
      if prefs.text_width < 100 then
 
        t = t .. ' {#fw_more|>>}';
 
      else
 
        t = t .. ' >>';
 
      end;
 
    
 
      pn(fmt.c(t) .. '^');
 
    end;
 
    act = function(s)
 
      if not prefs.text_width then
 
        prefs.text_width = 100;
 
      end;
 
    
 
      prefs.text_width = prefs.text_width + 20;
 
    
 
      if prefs.text_width > 100 then
 
        prefs.text_width = 40;
 
      end;
 
    
 
      prefs:store();
 
    
 
      walk(here());
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#fw_less';
 
      act = function(s)
 
        prefs.text_width = prefs.text_width - 10;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#fw_more';
 
      act = function(s)
 
        prefs.text_width = prefs.text_width + 10;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
  };
 
  obj {
 
    nam = '#text_alignment';
 
    dsc = function(s)
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'text_alignment'))));
 
      
 
      local t = '';
 
    
 
      if prefs.text_alignment == 1 then
 
        t = t .. translate_now("menu_locale", 'text_alignment_justify') .. ' | ';
 
      else
 
        t = t .. '{#align_just|' .. translate_now("menu_locale", 'text_alignment_justify') .. '} | ';
 
      end;
 
      
 
    
 
      if prefs.text_alignment == 2 then
 
        t = t .. translate_now("menu_locale", 'text_alignment_left');
 
      else
 
        t = t .. '{#align_left|' .. translate_now("menu_locale", 'text_alignment_left') .. '}';
 
      end;
 
      pn(fmt.c(t) .. '^');
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#align_just';
 
      act = function(s)
 
        prefs.text_alignment = 1;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#align_left';
 
      act = function(s)
 
        prefs.text_alignment = 2;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
  };
 
  obj {
 
    nam = '#padding';
 
    dsc = function(s)
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'padding'))));
 
      
 
      local t = '';
 
    
 
      if prefs.text_padding == 1 then
 
        t = t .. translate_now("menu_locale", 'normal') .. ' | ';
 
      else
 
        t = t .. '{#pad_norm|' .. translate_now("menu_locale", 'normal') .. '} | ';
 
      end;
 
      
 
    
 
      if prefs.text_padding == 2 then
 
        t = t .. translate_now("menu_locale", 'extended');
 
      else
 
        t = t .. '{#pad_large|' .. translate_now("menu_locale", 'extended') .. '}';
 
      end;
 
      pn(fmt.c(t) .. '^');
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#pad_norm';
 
      act = function(s)
 
        prefs.text_padding = 1;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#pad_large';
 
      act = function(s)
 
        prefs.text_padding = 2;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
  };
 
  obj {
 
    nam = '#interval';
 
    dsc = function(s)
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'interval'))));
 
      
 
      local t = '';
 
    
 
      if prefs.text_interval == 1 then
 
        t = t .. translate_now("menu_locale", 'normal') .. ' | ';
 
      else
 
        t = t .. '{#int_norm|' .. translate_now("menu_locale", 'normal') .. '} | ';
 
      end;
 
      
 
    
 
      if prefs.text_interval == 2 then
 
        t = t .. translate_now("menu_locale", 'extended');
 
      else
 
        t = t .. '{#int_large|' .. translate_now("menu_locale", 'extended') .. '}';
 
      end;
 
      pn(fmt.c(t) .. '^');
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#int_norm';
 
      act = function(s)
 
        prefs.text_interval = 1;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#int_large';
 
      act = function(s)
 
        prefs.text_interval = 2;
 
      
 
        prefs:store();
 
        set_theme(std.call(here(), 'theme'));
 
        walk(here());
 
      end;
 
    };
 
  };
 
  obj {
 
    nam = '#textinput';
 
    dsc = function(s)
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'use_text_input'))));
 
      
 
      local t = '';
 
      if prefs.text_input then
 
        t = '{#ti_disable|' .. translate_now("menu_locale", 'disable') .. '} | ' .. translate_now("menu_locale", 'enable');
 
      else
 
        t = translate_now("menu_locale", 'disable') .. ' | {#ti_enable|' .. translate_now("menu_locale", 'enable') .. '}';
 
      end;
 
      
 
      pn(fmt.c(t) .. '^');
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#ti_disable';
 
      act = function(s)
 
        prefs.text_input = false;
 
        prefs:store();
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#ti_enable';
 
      act = function(s)
 
        prefs.text_input = true;
 
        prefs:store();
 
        walk(here());
 
      end;
 
    };
 
  };
 
  obj {
 
    nam = '#simplified_animation';
 
    dsc = function(s)
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'simplified_animation'))));
 
      
 
      local t = '';
 
      if prefs.simplified_animation then
 
        t = '{#sa_disable|' .. translate_now("menu_locale", 'disable') .. '} | ' .. translate_now("menu_locale", 'enable');
 
      else
 
        t = translate_now("menu_locale", 'disable') .. ' | {#sa_enable|' .. translate_now("menu_locale", 'enable') .. '}';
 
      end;
 
      
 
      pn(fmt.c(t) .. '^');
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#sa_disable';
 
      act = function(s)
 
        prefs.simplified_animation = false;
 
        prefs:store();
 
        walk(here());
 
      end;
 
    };
 
    obj {
 
      nam = '#sa_enable';
 
      act = function(s)
 
        prefs.simplified_animation = true;
 
        prefs:store();
 
        walk(here());
 
      end;
 
    };
 
  };
 
}
solarscale.lua
Show inline comments
 
obj {
 
	level_1_visited = false;
 
	level_2_visited = false;
 
	level_3_visited = false;
 
	level_4_visited = false;
 
	level_4_2_visited = false;
 
	level_3_2_visited = false;
 
	level_2_2_visited = false;
 
	level_1_2_visited = false;
 
  level_1_visited = false;
 
  level_2_visited = false;
 
  level_3_visited = false;
 
  level_4_visited = false;
 
  level_4_2_visited = false;
 
  level_3_2_visited = false;
 
  level_2_2_visited = false;
 
  level_1_2_visited = false;
 
  tower_discussed = false;
 
  after_discussed = false;
 
  tower_know_discussed = false;
 
  tea_found = false;
 
	tea_asked = false;
 
	tea_given = false;
 
  tea_asked = false;
 
  tea_given = false;
 
  crater_left = false;
 
  crater_left_discussed = false;
 
  connection_discussed = false;
 
	nam = 'solarscale_ally';
 
  nam = 'solarscale_ally';
 
  nofollowloc = false;
 
	dsc = function(s)
 
		if here()^'above_forest' or here()^'above_near_village' or here()^'above_village' or here()^'above_crater' or here()^'above_west' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_outside');
 
		elseif here()^'forest_glade' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_glade');
 
		elseif here()^'crater_near_tower' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_near_tower');
 
		elseif here()^'tower_level_2' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_tower_level_2');
 
		elseif here()^'tower_level_3' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_tower_level_3');
 
		elseif here()^'tower_level_4' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_tower_level_4');
 
		elseif here()^'tower_level_4_room_2' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_tower_level_4_room_2');
 
		elseif here()^'tower_level_3_room_2' then
 
			if here().light then
 
				return translate_now("solarscale_locale", 'solarscale_ally_tower_level_3_room_2_lit');
 
			else
 
				return translate_now("solarscale_locale", 'solarscale_ally_tower_level_3_room_2_dark');
 
			end;
 
  dsc = function(s)
 
    if here()^'above_forest' or here()^'above_near_village' or here()^'above_village' or here()^'above_crater' or here()^'above_west' then
 
      return translate_now("solarscale_locale", 'solarscale_ally_outside');
 
    elseif here()^'forest_glade' then
 
      return translate_now("solarscale_locale", 'solarscale_ally_glade');
 
    elseif here()^'crater_near_tower' then
 
      return translate_now("solarscale_locale", 'solarscale_ally_near_tower');
 
    elseif here()^'tower_level_2' then
 
      return translate_now("solarscale_locale", 'solarscale_ally_tower_level_2');
 
    elseif here()^'tower_level_3' then
 
      return translate_now("solarscale_locale", 'solarscale_ally_tower_level_3');
 
    elseif here()^'tower_level_4' then
 
      return translate_now("solarscale_locale", 'solarscale_ally_tower_level_4');
 
    elseif here()^'tower_level_4_room_2' then
 
      return translate_now("solarscale_locale", 'solarscale_ally_tower_level_4_room_2');
 
    elseif here()^'tower_level_3_room_2' then
 
      if here().light then
 
        return translate_now("solarscale_locale", 'solarscale_ally_tower_level_3_room_2_lit');
 
      else
 
        return translate_now("solarscale_locale", 'solarscale_ally_tower_level_3_room_2_dark');
 
      end;
 
    elseif here()^'tower_level_2_room_2' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_tower_level_2_room_2');
 
		elseif here()^'tower_level_1_room_2' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_tower_level_1_room_2');
 
		end;
 
	
 
		return translate_now("solarscale_locale", 'solarscale_ally_follows');
 
	end;
 
	act = function(s)
 
		walkin('solarscale_ally_dlg');
 
	end;
 
	life = function(s)
 
		if not here().nofollow then
 
      return translate_now("solarscale_locale", 'solarscale_ally_tower_level_2_room_2');
 
    elseif here()^'tower_level_1_room_2' then
 
      return translate_now("solarscale_locale", 'solarscale_ally_tower_level_1_room_2');
 
    end;
 
  
 
    return translate_now("solarscale_locale", 'solarscale_ally_follows');
 
  end;
 
  act = function(s)
 
    walkin('solarscale_ally_dlg');
 
  end;
 
  life = function(s)
 
    if not here().nofollow then
 
      s.nofollowloc = here().nam;
 
      
 
			if (here() ~= where('solarscale_ally')) then
 
				if here()^'crater_near_tower' then
 
					p(translate_now("solarscale_locale", 'solarscale_ally_near_tower_life'));
 
      if (here() ~= where('solarscale_ally')) then
 
        if here()^'crater_near_tower' then
 
          p(translate_now("solarscale_locale", 'solarscale_ally_near_tower_life'));
 
        elseif here()^'above_forest' and not solarscale_glade_visited then
 
					p(translate_now("solarscale_locale", 'solarscale_ally_glade_suggestion'));
 
          p(translate_now("solarscale_locale", 'solarscale_ally_glade_suggestion'));
 
        elseif here()^'forest_glade' and not solarscale_glade_visited then
 
          solarscale_glade_visited = true;
 
					p(translate_now("solarscale_locale", 'solarscale_ally_glade_life'));
 
				elseif here()^'tower_level_1' and not s.level_1_visited then
 
					s.level_1_visited = true;
 
					p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_1_life'));
 
				elseif here()^'tower_level_2' and not s.level_2_visited then
 
					s.level_2_visited = true;
 
					p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_2_life'));
 
				elseif here()^'tower_level_3' and not s.level_3_visited then
 
					s.level_3_visited = true;
 
					p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_3_life'));
 
				elseif here()^'tower_level_4' and not s.level_4_visited then
 
					s.level_4_visited = true;
 
					p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_4_life'));
 
				elseif here()^'tower_level_4_room_2' and not s.level_4_2_visited then
 
					s.level_4_2_visited = true;
 
					p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_4_room_2_life'));
 
				elseif here()^'tower_level_3_room_2' and not s.level_3_2_visited then
 
					s.level_3_2_visited = true;
 
					p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_3_room_2_life'));
 
				elseif here()^'tower_level_2_room_2' and not s.level_2_2_visited then
 
					s.level_2_2_visited = true;
 
					p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_2_room_2_life'));
 
				elseif here()^'tower_level_1_room_2' and not s.level_1_2_visited then
 
					s.level_1_2_visited = true;
 
					p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_1_room_2_life'));
 
				elseif here()^'above_forest' and where('solarscale_ally') and where('solarscale_ally')^'forest_glade' then
 
					p(translate_now("solarscale_locale", 'solarscale_ally_glade_left'));
 
          p(translate_now("solarscale_locale", 'solarscale_ally_glade_life'));
 
        elseif here()^'tower_level_1' and not s.level_1_visited then
 
          s.level_1_visited = true;
 
          p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_1_life'));
 
        elseif here()^'tower_level_2' and not s.level_2_visited then
 
          s.level_2_visited = true;
 
          p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_2_life'));
 
        elseif here()^'tower_level_3' and not s.level_3_visited then
 
          s.level_3_visited = true;
 
          p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_3_life'));
 
        elseif here()^'tower_level_4' and not s.level_4_visited then
 
          s.level_4_visited = true;
 
          p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_4_life'));
 
        elseif here()^'tower_level_4_room_2' and not s.level_4_2_visited then
 
          s.level_4_2_visited = true;
 
          p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_4_room_2_life'));
 
        elseif here()^'tower_level_3_room_2' and not s.level_3_2_visited then
 
          s.level_3_2_visited = true;
 
          p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_3_room_2_life'));
 
        elseif here()^'tower_level_2_room_2' and not s.level_2_2_visited then
 
          s.level_2_2_visited = true;
 
          p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_2_room_2_life'));
 
        elseif here()^'tower_level_1_room_2' and not s.level_1_2_visited then
 
          s.level_1_2_visited = true;
 
          p(translate_now("solarscale_locale", 'solarscale_ally_tower_level_1_room_2_life'));
 
        elseif here()^'above_forest' and where('solarscale_ally') and where('solarscale_ally')^'forest_glade' then
 
          p(translate_now("solarscale_locale", 'solarscale_ally_glade_left'));
 
        elseif where('solarscale_ally') and where('solarscale_ally')^'inside_crater_glade' and here()^'above_crater' and not s.crater_left then
 
          s.crater_left = true;
 
          
 
          p(translate_now("solarscale_locale", 'solarscale_ally_above_crater_life'));
 
				else
 
					p(translate_now("solarscale_locale", 'solarscale_ally_follow_life'));
 
				end;
 
				remove('solarscale_ally', where('solarscale_ally'));
 
				put('solarscale_ally', where(pl));
 
			end;
 
		elseif type(here().nofollow) == 'function' then
 
        else
 
          p(translate_now("solarscale_locale", 'solarscale_ally_follow_life'));
 
        end;
 
        remove('solarscale_ally', where('solarscale_ally'));
 
        put('solarscale_ally', where(pl));
 
      end;
 
    elseif type(here().nofollow) == 'function' then
 
      if here().nam ~= s.nofollowloc then
 
        s.nofollowloc = here().nam;
 
        local nofollow = here():nofollow();
 
@@ -106,57 +106,57 @@ obj {
 
          return nofollow;
 
        end;
 
      end;
 
		elseif type(here().nofollow) == 'string' then
 
    elseif type(here().nofollow) == 'string' then
 
      if here().nam ~= s.nofollowloc then
 
        s.nofollowloc = here().nam;
 
        return here().nofollow;
 
      end;
 
		end;
 
	end;
 
	used = translate("solarscale_locale", 'solarscale_used');
 
    end;
 
  end;
 
  used = translate("solarscale_locale", 'solarscale_used');
 
}
 

	
 
dlg {
 
	nam = 'solarscale_ally_dlg';
 
	disp = translate("solarscale_locale", 'disp');
 
	pic = function(s)
 
		local pic = std.call(from(), 'pic');
 
		local spic = 'images/characters/solarscale.png';
 
		if not power_on and (from() ^ 'tower_level_4_room_2' or from() ^ 'tower_level_3_room_2' and not from().light) then
 
			spic = 'images/characters/solarscale_tower_dark.png';
 
		elseif from() ^ 'tower_level_4' or from() ^ 'tower_level_3' or from() ^ 'tower_level_4_room_2' or from() ^ 'tower_level_1_room_2' or from() ^ 'tower_level_2' or from() ^ 'tower_level_3_room_2' and not power_on then
 
			spic = 'images/characters/solarscale_tower_dusk.png';
 
		elseif not power_on and (from() ^ 'tower_level_2_room_2' or from() ^ 'tower_level_2_airlock') then
 
			spic = 'images/characters/solarscale_tower_dusk_red.png';
 
		elseif from() ^ 'tower_level_2_room_2' or from() ^ 'tower_level_2_airlock' or from() ^ 'tower_level_3_room_2' or from() ^ 'tower_level_1' then
 
			spic = 'images/characters/solarscale_tower_synth.png';
 
		end;
 
		return pic .. ';' .. spic;
 
	end;
 
	theme = function(s) 
 
		return here():from().theme;
 
	end;
 
	enter = function(s)
 
  nam = 'solarscale_ally_dlg';
 
  disp = translate("solarscale_locale", 'disp');
 
  pic = function(s)
 
    local pic = std.call(from(), 'pic');
 
    local spic = 'images/characters/solarscale.png';
 
    if not power_on and (from() ^ 'tower_level_4_room_2' or from() ^ 'tower_level_3_room_2' and not from().light) then
 
      spic = 'images/characters/solarscale_tower_dark.png';
 
    elseif from() ^ 'tower_level_4' or from() ^ 'tower_level_3' or from() ^ 'tower_level_4_room_2' or from() ^ 'tower_level_1_room_2' or from() ^ 'tower_level_2' or from() ^ 'tower_level_3_room_2' and not power_on then
 
      spic = 'images/characters/solarscale_tower_dusk.png';
 
    elseif not power_on and (from() ^ 'tower_level_2_room_2' or from() ^ 'tower_level_2_airlock') then
 
      spic = 'images/characters/solarscale_tower_dusk_red.png';
 
    elseif from() ^ 'tower_level_2_room_2' or from() ^ 'tower_level_2_airlock' or from() ^ 'tower_level_3_room_2' or from() ^ 'tower_level_1' then
 
      spic = 'images/characters/solarscale_tower_synth.png';
 
    end;
 
    return pic .. ';' .. spic;
 
  end;
 
  theme = function(s) 
 
    return here():from().theme;
 
  end;
 
  enter = function(s)
 
    local ss = _'solarscale_ally'
 
		local from = here():from();
 
		if from^'above_forest' and not solarscale_glade_visited then
 
    local from = here():from();
 
    if from^'above_forest' and not solarscale_glade_visited then
 
      return translate_now("solarscale_locale", 'solarscale_ally_glade_suggestion');
 
    elseif (from^'above_crater' or from^'above_near_village' or from^'above_village' or from^'above_west' or from^'near_village') and not solarscale_glade_visited and not ss.crater_left_discussed then
 
      return translate_now("solarscale_locale", 'solarscale_ally_dlg_above_crater_enter');
 
    elseif from^'above_forest' or from^'above_crater' or from^'inside_crater_path' or from ^'inside_crater_glade' or from^'above_west' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_dlg_enter_back_to_tower_' .. tostring(rnd(3)));
 
      return translate_now("solarscale_locale", 'solarscale_ally_dlg_enter_back_to_tower_' .. tostring(rnd(3)));
 
    elseif ss.level_1_visited and not ss.tower_discussed then
 
      push(); --Add root phrase to the tree
 
      push('#about_tower_1');
 
      ss.tower_discussed = true;
 
      return translate_now("solarscale_locale", 'solarscale_ally_tower_first_enter');
 
		elseif from^'tower_level_4_room_2' then
 
    elseif from^'tower_level_4_room_2' then
 
      local phrase = translate_now("solarscale_locale", 'solarscale_ally_terminal');
 
			if power_on then
 
				if pc_status ~= 'fail' then
 
					phrase = phrase .. ' ' .. translate_now("solarscale_locale", 'solarscale_ally_terminal_try');
 
				end;
 
			end;
 
      if power_on then
 
        if pc_status ~= 'fail' then
 
          phrase = phrase .. ' ' .. translate_now("solarscale_locale", 'solarscale_ally_terminal_try');
 
        end;
 
      end;
 
      
 
      return phrase;
 
    elseif from^'tower_level_3_room_2' then
 
@@ -165,16 +165,16 @@ dlg {
 
      end;
 
    elseif from^'crater_near_tower' then
 
      return translate_now("solarscale_locale", 'solarscale_ally_near_tower');
 
		elseif from^'forest_glade' then
 
    elseif from^'forest_glade' then
 
      return string.gsub(translate_now("solarscale_locale", 'solarscale_ally_glade'), '[{}]', '') .. ' ' .. translate_now("solarscale_locale", 'solarscale_ally_glade_enter');
 
		elseif from^'above_village' then
 
			return translate_now("solarscale_locale", 'solarscale_ally_above_village');
 
    elseif from^'above_village' then
 
      return translate_now("solarscale_locale", 'solarscale_ally_above_village');
 
    else
 
      return translate_now("solarscale_locale", 'solarscale_dlg_enter_generic_' .. tostring(rnd(3)));
 
		end;
 
		
 
	end;
 
	phr = {
 
    end;
 
    
 
  end;
 
  phr = {
 
    {cond=function(s) return not solarscale_glade_visited and here():from()^'above_forest' end, translate("solarscale_locale", 'solarscale_ally_glade_question'), translate("solarscale_locale", 'solarscale_ally_glade_answer')};
 
    {'#above_crater_1', cond=function(s) return (from()^'above_crater' or from()^'above_near_village' or from()^'above_village' or from()^'above_west' or from()^'near_village') and not solarscale_glade_visited and not _'solarscale_ally'.crater_left_discussed end, translate("solarscale_locale", 'solarscale_ally_dlg_above_crater_1'), function(s)
 
      close('#above_crater_1');
 
@@ -234,381 +234,381 @@ dlg {
 
      {translate("solarscale_locale", 'solarscale_ally_dlg_connection_2'), translate("solarscale_locale", 'solarscale_ally_dlg_connection_2_response')};
 
    };
 
    
 
		{cond=function(s) return here():from()^'tower_level_1' and not have('tower_box') and not _('tower_level_1').keys_taken and not have('tower_level_2_key') and _('level_1_up'):disabled() end, translate("solarscale_locale", 'solarscale_ally_dlg_level_1_1'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_1_response')};
 
    {cond=function(s) return here():from()^'tower_level_1' and not have('tower_box') and not _('tower_level_1').keys_taken and not have('tower_level_2_key') and _('level_1_up'):disabled() end, translate("solarscale_locale", 'solarscale_ally_dlg_level_1_1'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_1_response')};
 
    {cond=function(s) return here():from()^'tower_level_1' and have('tower_box') and not _('tower_level_1').keys_taken and _('level_1_up'):disabled() end, translate("solarscale_locale", 'solarscale_do_you_have_any_ideas'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_2_response'), 
 
			only=true;
 
			{function(s) return '[' .. translate_now("solarscale_locale", 'solarscale_pass_box') .. '] ' .. translate_now("solarscale_locale", 'solarscale_accept_help') end, translate("solarscale_locale", 'solarscale_ally_dlg_level_1_2_agree_response')};
 
			{translate("solarscale_locale", 'solarscale_ally_dlg_not_now'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
		};
 
      only=true;
 
      {function(s) return '[' .. translate_now("solarscale_locale", 'solarscale_pass_box') .. '] ' .. translate_now("solarscale_locale", 'solarscale_accept_help') end, translate("solarscale_locale", 'solarscale_ally_dlg_level_1_2_agree_response')};
 
      {translate("solarscale_locale", 'solarscale_ally_dlg_not_now'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
    };
 
    {cond=function(s) return here():from()^'tower_level_1' and not have('tower_box') and _('tower_level_1').keys_taken and not have('tower_level_2_key') and _('level_1_up'):disabled() end, translate("solarscale_locale", 'solarscale_do_you_have_any_ideas'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_response'),
 
			only=true;
 
			{translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_1'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_1_or_2_response')};
 
			{translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_2'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_1_or_2_response')};
 
			{translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_3'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_3_response')};
 
		};
 
      only=true;
 
      {translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_1'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_1_or_2_response')};
 
      {translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_2'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_1_or_2_response')};
 
      {translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_3'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_3_3_response')};
 
    };
 
    {cond=function(s) return here():from()^'tower_level_1' and have('tower_box') and _('tower_level_1').keys_taken and not have('tower_level_2_key') and _('level_1_up'):disabled() end, translate("solarscale_locale", 'solarscale_do_you_have_any_ideas'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_4_response'),
 
			only=true;
 
			{function(s) return '[' .. translate_now("solarscale_locale", 'solarscale_pass_items_level_1') .. '] ' .. translate_now("solarscale_locale", 'solarscale_accept_help') end, function(s)
 
				if solarscale_helps > 0 then
 
					open('#level1_agree');
 
					open('#level1_disagree');
 
					close('#level1_no_help');
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_response') .. ' ' .. translate_now("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_response_positive');
 
				else
 
					close('#level1_agree');
 
					close('#level1_disagree');
 
					open('#level1_no_help');
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_response') .. ' ' .. translate_now("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_response_negative');
 
				end;
 
			end,
 
				only=true;
 
				{'#level1_agree', translate("solarscale_locale", 'solarscale_accept_help'), function(s)
 
					remove('tower_box', pl);
 
					remove('tower_hint_1', pl);
 
					remove('tower_key_0', pl);
 
					remove('tower_key_1', pl);
 
					remove('tower_key_2', pl);
 
					remove('tower_key_3', pl);
 
					take('tower_level_2_key');
 
					solarscale_helps = solarscale_helps - 1;
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_1_response');
 
				end};
 
				{'#level1_disagree', translate("solarscale_locale", 'solarscale_ally_reject_help'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_no_help_response')};
 
				{'#level1_no_help', translate("solarscale_locale", 'solarscale_ally_no_help'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_no_help_response')};
 
			};
 
			{translate("solarscale_locale", 'solarscale_ally_dlg_not_now'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
		};
 
      only=true;
 
      {function(s) return '[' .. translate_now("solarscale_locale", 'solarscale_pass_items_level_1') .. '] ' .. translate_now("solarscale_locale", 'solarscale_accept_help') end, function(s)
 
        if solarscale_helps > 0 then
 
          open('#level1_agree');
 
          open('#level1_disagree');
 
          close('#level1_no_help');
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_response') .. ' ' .. translate_now("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_response_positive');
 
        else
 
          close('#level1_agree');
 
          close('#level1_disagree');
 
          open('#level1_no_help');
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_response') .. ' ' .. translate_now("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_response_negative');
 
        end;
 
      end,
 
        only=true;
 
        {'#level1_agree', translate("solarscale_locale", 'solarscale_accept_help'), function(s)
 
          remove('tower_box', pl);
 
          remove('tower_hint_1', pl);
 
          remove('tower_key_0', pl);
 
          remove('tower_key_1', pl);
 
          remove('tower_key_2', pl);
 
          remove('tower_key_3', pl);
 
          take('tower_level_2_key');
 
          solarscale_helps = solarscale_helps - 1;
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_1_response');
 
        end};
 
        {'#level1_disagree', translate("solarscale_locale", 'solarscale_ally_reject_help'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_no_help_response')};
 
        {'#level1_no_help', translate("solarscale_locale", 'solarscale_ally_no_help'), translate("solarscale_locale", 'solarscale_ally_dlg_level_1_4_1_no_help_response')};
 
      };
 
      {translate("solarscale_locale", 'solarscale_ally_dlg_not_now'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
    };
 
    {cond=function(s) return here():from()^'tower_level_2' end, translate("solarscale_locale", 'solarscale_ally_dlg_level_2_1'), translate("solarscale_locale", 'solarscale_ally_dlg_level_2_1_response'), 
 
			{translate("solarscale_locale", 'solarscale_ally_dlg_level_2_1_1'), translate("solarscale_locale", 'solarscale_ally_dlg_level_2_1_1_response')};
 
		};
 
      {translate("solarscale_locale", 'solarscale_ally_dlg_level_2_1_1'), translate("solarscale_locale", 'solarscale_ally_dlg_level_2_1_1_response')};
 
    };
 
    {cond=function(s) return here():from()^'tower_level_3' and _('level_3_up'):disabled() end, translate("solarscale_locale", 'solarscale_ally_dlg_level_3_1'), function(s)
 
			if solarscale_helps > 0 then
 
				open('#level3_agree');
 
				open('#level3_disagree');
 
				close('#level3_no_help');
 
				return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_3_1_response');
 
			else
 
				close('#level3_agree');
 
				close('#level3_disagree');
 
				open('#level3_no_help');
 
				return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_3_1_response_negative');
 
			end;
 
		end, only=true, 
 
			{"#level3_agree", translate("solarscale_locale", 'solarscale_accept_help'), function(s)
 
				remove('figure_wolf', pl);
 
				remove('figure_tiger', pl);
 
				remove('figure_lion', pl);
 
				remove('figure_knight', pl);
 
				remove('figure_tower', pl);
 
				_('tower_level_3_table').solved = true;
 
				_('level_3_up'):enable();
 
				solarscale_helps = solarscale_helps - 1;
 
				return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_3_1_1_response');
 
			end};
 
			{"#level3_disagree", translate("solarscale_locale", 'solarscale_let_me_try'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
			{"#level3_no_help", translate("solarscale_locale", 'solarscale_let_me_try_2'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
		};
 
      if solarscale_helps > 0 then
 
        open('#level3_agree');
 
        open('#level3_disagree');
 
        close('#level3_no_help');
 
        return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_3_1_response');
 
      else
 
        close('#level3_agree');
 
        close('#level3_disagree');
 
        open('#level3_no_help');
 
        return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_3_1_response_negative');
 
      end;
 
    end, only=true, 
 
      {"#level3_agree", translate("solarscale_locale", 'solarscale_accept_help'), function(s)
 
        remove('figure_wolf', pl);
 
        remove('figure_tiger', pl);
 
        remove('figure_lion', pl);
 
        remove('figure_knight', pl);
 
        remove('figure_tower', pl);
 
        _('tower_level_3_table').solved = true;
 
        _('level_3_up'):enable();
 
        solarscale_helps = solarscale_helps - 1;
 
        return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_3_1_1_response');
 
      end};
 
      {"#level3_disagree", translate("solarscale_locale", 'solarscale_let_me_try'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
      {"#level3_no_help", translate("solarscale_locale", 'solarscale_let_me_try_2'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
    };
 
    {cond=function(s) return here():from()^'tower_level_4' and _('level_4_next_room'):disabled() end, translate("solarscale_locale", 'solarscale_do_you_have_any_ideas'), function(s)
 
			if solarscale_helps > 0 then
 
				open('#level4_agree');
 
				open('#level4_disagree');
 
				close('#level4_no_help');
 
				
 
				return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_1_response');
 
			else
 
				close('#level4_agree');
 
				close('#level4_disagree');
 
				open('#level4_no_help');
 
				
 
				return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_1_response_negative');
 
			end;
 
		end, only=true,
 
			{"#level4_agree", translate("solarscale_locale", 'solarscale_ally_dlg_level_4_1_1'), function(s)
 
				candles_solved = true;
 
				_('level_3_up'):enable();
 
				solarscale_helps = solarscale_helps - 1;
 
				
 
				local c = _('tower_candelabra')
 
      if solarscale_helps > 0 then
 
        open('#level4_agree');
 
        open('#level4_disagree');
 
        close('#level4_no_help');
 
        
 
        return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_1_response');
 
      else
 
        close('#level4_agree');
 
        close('#level4_disagree');
 
        open('#level4_no_help');
 
        
 
        return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_1_response_negative');
 
      end;
 
    end, only=true,
 
      {"#level4_agree", translate("solarscale_locale", 'solarscale_ally_dlg_level_4_1_1'), function(s)
 
        candles_solved = true;
 
        _('level_3_up'):enable();
 
        solarscale_helps = solarscale_helps - 1;
 
        
 
        local c = _('tower_candelabra')
 
        c:initnotes();
 

	
 
				local ns = table.copy(c.notesequence);
 
				ns[#ns + 1] = gusts[rnd(#gusts)];
 
				ns[#ns + 1]	= 'open_door';
 
				
 
				play_sound(ns, 600);
 
			
 
				_('level_4_next_room'):enable();
 
				
 
				return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_1_1_response');
 
			end};
 
			{"#level4_disagree", translate("solarscale_locale", 'solarscale_let_me_try'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
			{"#level4_no_help", translate("solarscale_locale", 'solarscale_let_me_try_2'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
		};
 
        local ns = table.copy(c.notesequence);
 
        ns[#ns + 1] = gusts[rnd(#gusts)];
 
        ns[#ns + 1]  = 'open_door';
 
        
 
        play_sound(ns, 600);
 
      
 
        _('level_4_next_room'):enable();
 
        
 
        return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_1_1_response');
 
      end};
 
      {"#level4_disagree", translate("solarscale_locale", 'solarscale_let_me_try'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
      {"#level4_no_help", translate("solarscale_locale", 'solarscale_let_me_try_2'), translate("solarscale_locale", 'solarscale_nods_silently')};
 
    };
 
    
 
    
 
    {cond=function(s) return here():from()^'tower_level_4_room_2' and power_on and pc_status ~= 'fail' end, translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1'), function(s)
 
			p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_turnon'));
 
			local rval = _('system_unit'):check(true);
 
		
 
			close('#tl4r2a');
 
      p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_turnon'));
 
      local rval = _('system_unit'):check(true);
 
    
 
      close('#tl4r2a');
 
      close('#tl4r2b');
 
    
 
			if rval == 'motherboard' then
 
				p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_issue', {broken=translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_motherboard')}));
 
      if rval == 'motherboard' then
 
        p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_issue', {broken=translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_motherboard')}));
 
        open('#tl4r2b');
 
				return;
 
			elseif rval == 'cpu' then
 
        return;
 
      elseif rval == 'cpu' then
 
        p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_issue', {broken=translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_cpu')}));
 
        open('#tl4r2b');
 
				return;
 
			elseif rval == 'ram' then
 
        return;
 
      elseif rval == 'ram' then
 
        p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_issue', {broken=translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_ram')}));
 
        open('#tl4r2b');
 
				return;
 
			elseif rval == 'video' then
 
        return;
 
      elseif rval == 'video' then
 
        p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_issue', {broken=translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_video')}));
 
        open('#tl4r2b');
 
				return;
 
			elseif rval == 'keyboard' then
 
        return;
 
      elseif rval == 'keyboard' then
 
        p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_issue', {broken=translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_keyboard')}));
 
        open('#tl4r2b');
 
				return;
 
        return;
 
      elseif rval == 'network' then
 
        p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_issue', {broken=translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_network')}));
 
        open('#tl4r2b');
 
				return;
 
			end;
 
		
 
			open('#tl4r2a');
 
		
 
			p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_fixed'));
 
		end,
 
		{
 
			'#tl4r2a', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_1'),
 
			function(s)
 
				walkin('terminal');
 
			end;
 
		},
 
		{'#tl4r2b', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2'), function(s)
 
			if have('part_box') then
 
				if solarscale_helps > 0 then
 
					open('#tl4r2cfa');
 
					open('#tl4r2cfb');
 
					close('#tl4r2cfc');
 
					close('#tl4r2cfd');
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response');
 
				else
 
					close('#tl4r2cfa');
 
					close('#tl4r2cfb');
 
					close('#tl4r2cfc');
 
					open('#tl4r2cfd');
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_negative');
 
				end;
 
			else
 
				if solarscale_helps > 0 then
 
        return;
 
      end;
 
    
 
      open('#tl4r2a');
 
    
 
      p(translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_response_fixed'));
 
    end,
 
    {
 
      '#tl4r2a', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_1'),
 
      function(s)
 
        walkin('terminal');
 
      end;
 
    },
 
    {'#tl4r2b', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2'), function(s)
 
      if have('part_box') then
 
        if solarscale_helps > 0 then
 
          open('#tl4r2cfa');
 
          open('#tl4r2cfb');
 
          close('#tl4r2cfc');
 
          close('#tl4r2cfd');
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response');
 
        else
 
          close('#tl4r2cfa');
 
          close('#tl4r2cfb');
 
          close('#tl4r2cfc');
 
          open('#tl4r2cfd');
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_negative');
 
        end;
 
      else
 
        if solarscale_helps > 0 then
 
          close('#tl4r2cfa');
 
          close('#tl4r2cfb');
 
          close('#tl4r2cfd');
 
          open('#tl4r2cfc');
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_no_parts');
 
				else
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_no_parts');
 
        else
 
          close('#tl4r2cfa');
 
					close('#tl4r2cfb');
 
					close('#tl4r2cfc');
 
					open('#tl4r2cfd');
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_negative');
 
				end;
 
			end;
 
		end, only=true,
 
			{'#tl4r2cfa', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_1'), function(s)
 
				walkout();
 
				local motherboard = lookup('#motherboard', _'system_unit');
 
				local cpu= lookup('#cpu', _'system_unit');
 
				local ram = lookup('#ram', _'system_unit');
 
				local slot1 = lookup('#slot1', _'system_unit');
 
				local slot2 = lookup('#slot2', _'system_unit');
 
				local slot3 = lookup('#slot3', _'system_unit');
 
				local slot4 = lookup('#slot4', _'system_unit');
 
				
 
				if motherboard.device then
 
					put(motherboard.device, 'part_box_inside');
 
				end;
 
			
 
				if cpu.device then
 
					put(cpu.device, 'part_box_inside');
 
				end;
 
			
 
				if ram.device then
 
					put(ram.device, 'part_box_inside');
 
				end;
 
			
 
				if slot1.device then
 
					put(slot1.device, 'part_box_inside');
 
				end;
 
			
 
				if slot2.device then
 
					put(slot2.device, 'part_box_inside');
 
				end;
 
			
 
				if slot3.device then
 
					put(slot3.device, 'part_box_inside');
 
				end;
 
			
 
				if slot4.device then
 
					put(slot4.device, 'part_box_inside');
 
				end;
 
			
 
				remove('crx-rdt-i3sb', 'part_box_inside');
 
				remove('rcpu200-crx-20mhz', 'part_box_inside');
 
				remove('rdt-m32-32mb', 'part_box_inside');
 
				remove('gva-rx4', 'part_box_inside');
 
				remove('fna-100-10mbs_2', 'part_box_inside');
 
				remove('kbc-p', 'part_box_inside');
 
						
 
				remove('crx-rdt-i3sb', me());
 
				remove('rcpu200-crx-20mhz', me());
 
				remove('rdt-m32-32mb', me());
 
				remove('gva-rx4', me());
 
				remove('fna-100-10mbs_2', me());
 
				remove('kbc-p', me());
 
				
 
				motherboard.device = _'crx-rdt-i3sb';
 
				cpu.device = _'rcpu200-crx-20mhz';
 
				ram.device = _'rdt-m32-32mb';
 
				slot1.device = _'gva-rx4';
 
				slot2.device = _'fna-100-10mbs_2';
 
				slot3.device = _'kbc-p';
 
				slot4.device = false;
 
			
 
				solarscale_helps = solarscale_helps - 1;
 
				pc_status = 'ok';
 
				
 
				lookup('#computer', 'tower_level_4_room_2').assembled = true;
 
			
 
				return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_1_response');
 
			end},
 
			{'#tl4r2cfb', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_2'), function(s)
 
				walkout();
 
				return translate_now("solarscale_locale", 'solarscale_nods_silently');
 
			end},
 
			{'#tl4r2cfc', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_3'), translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_3_response')},
 
			{'#tl4r2cfd', translate("solarscale_locale", 'solarscale_ally_dlg_end'), function(s)
 
				walkout();
 
			end}
 
		};
 
		{
 
			'#tl4r2c', translate("solarscale_locale", 'solarscale_ally_dlg_end'),
 
			function(s)
 
				walkout();
 
			end;
 
		}};
 
          close('#tl4r2cfb');
 
          close('#tl4r2cfc');
 
          open('#tl4r2cfd');
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_negative');
 
        end;
 
      end;
 
    end, only=true,
 
      {'#tl4r2cfa', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_1'), function(s)
 
        walkout();
 
        local motherboard = lookup('#motherboard', _'system_unit');
 
        local cpu= lookup('#cpu', _'system_unit');
 
        local ram = lookup('#ram', _'system_unit');
 
        local slot1 = lookup('#slot1', _'system_unit');
 
        local slot2 = lookup('#slot2', _'system_unit');
 
        local slot3 = lookup('#slot3', _'system_unit');
 
        local slot4 = lookup('#slot4', _'system_unit');
 
        
 
        if motherboard.device then
 
          put(motherboard.device, 'part_box_inside');
 
        end;
 
      
 
        if cpu.device then
 
          put(cpu.device, 'part_box_inside');
 
        end;
 
      
 
        if ram.device then
 
          put(ram.device, 'part_box_inside');
 
        end;
 
      
 
        if slot1.device then
 
          put(slot1.device, 'part_box_inside');
 
        end;
 
      
 
        if slot2.device then
 
          put(slot2.device, 'part_box_inside');
 
        end;
 
      
 
        if slot3.device then
 
          put(slot3.device, 'part_box_inside');
 
        end;
 
      
 
        if slot4.device then
 
          put(slot4.device, 'part_box_inside');
 
        end;
 
      
 
        remove('crx-rdt-i3sb', 'part_box_inside');
 
        remove('rcpu200-crx-20mhz', 'part_box_inside');
 
        remove('rdt-m32-32mb', 'part_box_inside');
 
        remove('gva-rx4', 'part_box_inside');
 
        remove('fna-100-10mbs_2', 'part_box_inside');
 
        remove('kbc-p', 'part_box_inside');
 
            
 
        remove('crx-rdt-i3sb', me());
 
        remove('rcpu200-crx-20mhz', me());
 
        remove('rdt-m32-32mb', me());
 
        remove('gva-rx4', me());
 
        remove('fna-100-10mbs_2', me());
 
        remove('kbc-p', me());
 
        
 
        motherboard.device = _'crx-rdt-i3sb';
 
        cpu.device = _'rcpu200-crx-20mhz';
 
        ram.device = _'rdt-m32-32mb';
 
        slot1.device = _'gva-rx4';
 
        slot2.device = _'fna-100-10mbs_2';
 
        slot3.device = _'kbc-p';
 
        slot4.device = false;
 
      
 
        solarscale_helps = solarscale_helps - 1;
 
        pc_status = 'ok';
 
        
 
        lookup('#computer', 'tower_level_4_room_2').assembled = true;
 
      
 
        return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_1_response');
 
      end},
 
      {'#tl4r2cfb', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_2'), function(s)
 
        walkout();
 
        return translate_now("solarscale_locale", 'solarscale_nods_silently');
 
      end},
 
      {'#tl4r2cfc', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_3'), translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_3_response')},
 
      {'#tl4r2cfd', translate("solarscale_locale", 'solarscale_ally_dlg_end'), function(s)
 
        walkout();
 
      end}
 
    };
 
    {
 
      '#tl4r2c', translate("solarscale_locale", 'solarscale_ally_dlg_end'),
 
      function(s)
 
        walkout();
 
      end;
 
    }};
 
    {cond=function(s) return here():from()^'tower_level_4_room_2' and pc_status == 'fail'; end, translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2'), function(s)
 
			if have('part_box') then
 
				if solarscale_helps > 0 then
 
					open('#tl4r2fa');
 
					open('#tl4r2fb');
 
					close('#tl4r2fc');
 
					close('#tl4r2fd');
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response');
 
				else
 
					close('#tl4r2fa');
 
					close('#tl4r2fb');
 
					close('#tl4r2fc');
 
					open('#tl4r2fd');
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_negative');
 
				end;
 
			else
 
				if solarscale_helps > 0 then
 
      if have('part_box') then
 
        if solarscale_helps > 0 then
 
          open('#tl4r2fa');
 
          open('#tl4r2fb');
 
          close('#tl4r2fc');
 
          close('#tl4r2fd');
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response');
 
        else
 
          close('#tl4r2fa');
 
          close('#tl4r2fb');
 
          close('#tl4r2fc');
 
          open('#tl4r2fd');
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_negative');
 
        end;
 
      else
 
        if solarscale_helps > 0 then
 
          close('#tl4r2fa');
 
          close('#tl4r2fb');
 
          close('#tl4r2fd');
 
          open('#tl4r2fc');
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_no_parts');
 
				else
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_no_parts');
 
        else
 
          close('#tl4r2fa');
 
					close('#tl4r2fb');
 
					close('#tl4r2fc');
 
					open('#tl4r2fd');
 
					return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_negative');
 
				end;
 
			end;
 
		end, only=true,
 
			{'#tl4r2fa', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_1'), function(s)
 
				walkout();
 
				local motherboard = lookup('#motherboard', _'system_unit');
 
				local cpu= lookup('#cpu', _'system_unit');
 
				local ram = lookup('#ram', _'system_unit');
 
				local slot1 = lookup('#slot1', _'system_unit');
 
				local slot2 = lookup('#slot2', _'system_unit');
 
				local slot3 = lookup('#slot3', _'system_unit');
 
				local slot4 = lookup('#slot4', _'system_unit');
 
				
 
				if motherboard.device then
 
					put(motherboard.device, 'part_box_inside');
 
				end;
 
			
 
				if cpu.device then
 
					put(cpu.device, 'part_box_inside');
 
				end;
 
			
 
				if ram.device then
 
					put(ram.device, 'part_box_inside');
 
				end;
 
			
 
				if slot1.device then
 
					put(slot1.device, 'part_box_inside');
 
				end;
 
			
 
				if slot2.device then
 
					put(slot2.device, 'part_box_inside');
 
				end;
 
			
 
				if slot3.device then
 
					put(slot3.device, 'part_box_inside');
 
				end;
 
			
 
				if slot4.device then
 
					put(slot4.device, 'part_box_inside');
 
				end;
 
			
 
				remove('crx-rdt-i3sb', 'part_box_inside');
 
				remove('rcpu200-crx-20mhz', 'part_box_inside');
 
				remove('rdt-m32-32mb', 'part_box_inside');
 
				remove('gva-rx4', 'part_box_inside');
 
				remove('fna-100-10mbs_2', 'part_box_inside');
 
				remove('kbc-p', 'part_box_inside');
 
					
 
				remove('crx-rdt-i3sb', me());
 
				remove('rcpu200-crx-20mhz', me());
 
				remove('rdt-m32-32mb', me());
 
				remove('gva-rx4', me());
 
				remove('fna-100-10mbs_2', me());
 
				remove('kbc-p', me());
 
			
 
				motherboard.device = _'crx-rdt-i3sb';
 
				cpu.device = _'rcpu200-crx-20mhz';
 
				ram.device = _'rdt-m32-32mb';
 
				slot1.device = _'gva-rx4';
 
				slot2.device = _'fna-100-10mbs_2';
 
				slot3.device = _'kbc-p';
 
				slot4.device = false;
 
			
 
				solarscale_helps = solarscale_helps - 1;
 
				pc_status = 'ok';
 
					
 
				lookup('#computer', 'tower_level_4_room_2').assembled = true;
 
			
 
				return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_1_response');
 
			end},
 
			{'#tl4r2fb', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_2'), function(s)
 
				walkout();
 
				return translate_now("solarscale_locale", 'solarscale_nods_silently');
 
			end},
 
			{'#tl4r2fc', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_3'), translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_3_response')},
 
			{'#tl4r2fd', translate("solarscale_locale", 'solarscale_ally_dlg_end'), function(s)
 
				walkout();
 
			end}
 
		};
 
          close('#tl4r2fb');
 
          close('#tl4r2fc');
 
          open('#tl4r2fd');
 
          return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_response_negative');
 
        end;
 
      end;
 
    end, only=true,
 
      {'#tl4r2fa', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_1'), function(s)
 
        walkout();
 
        local motherboard = lookup('#motherboard', _'system_unit');
 
        local cpu= lookup('#cpu', _'system_unit');
 
        local ram = lookup('#ram', _'system_unit');
 
        local slot1 = lookup('#slot1', _'system_unit');
 
        local slot2 = lookup('#slot2', _'system_unit');
 
        local slot3 = lookup('#slot3', _'system_unit');
 
        local slot4 = lookup('#slot4', _'system_unit');
 
        
 
        if motherboard.device then
 
          put(motherboard.device, 'part_box_inside');
 
        end;
 
      
 
        if cpu.device then
 
          put(cpu.device, 'part_box_inside');
 
        end;
 
      
 
        if ram.device then
 
          put(ram.device, 'part_box_inside');
 
        end;
 
      
 
        if slot1.device then
 
          put(slot1.device, 'part_box_inside');
 
        end;
 
      
 
        if slot2.device then
 
          put(slot2.device, 'part_box_inside');
 
        end;
 
      
 
        if slot3.device then
 
          put(slot3.device, 'part_box_inside');
 
        end;
 
      
 
        if slot4.device then
 
          put(slot4.device, 'part_box_inside');
 
        end;
 
      
 
        remove('crx-rdt-i3sb', 'part_box_inside');
 
        remove('rcpu200-crx-20mhz', 'part_box_inside');
 
        remove('rdt-m32-32mb', 'part_box_inside');
 
        remove('gva-rx4', 'part_box_inside');
 
        remove('fna-100-10mbs_2', 'part_box_inside');
 
        remove('kbc-p', 'part_box_inside');
 
          
 
        remove('crx-rdt-i3sb', me());
 
        remove('rcpu200-crx-20mhz', me());
 
        remove('rdt-m32-32mb', me());
 
        remove('gva-rx4', me());
 
        remove('fna-100-10mbs_2', me());
 
        remove('kbc-p', me());
 
      
 
        motherboard.device = _'crx-rdt-i3sb';
 
        cpu.device = _'rcpu200-crx-20mhz';
 
        ram.device = _'rdt-m32-32mb';
 
        slot1.device = _'gva-rx4';
 
        slot2.device = _'fna-100-10mbs_2';
 
        slot3.device = _'kbc-p';
 
        slot4.device = false;
 
      
 
        solarscale_helps = solarscale_helps - 1;
 
        pc_status = 'ok';
 
          
 
        lookup('#computer', 'tower_level_4_room_2').assembled = true;
 
      
 
        return translate_now("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_1_response');
 
      end},
 
      {'#tl4r2fb', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_2'), function(s)
 
        walkout();
 
        return translate_now("solarscale_locale", 'solarscale_nods_silently');
 
      end},
 
      {'#tl4r2fc', translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_3'), translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_1_2_3_response')},
 
      {'#tl4r2fd', translate("solarscale_locale", 'solarscale_ally_dlg_end'), function(s)
 
        walkout();
 
      end}
 
    };
 
    {cond=function(s) return here():from()^'tower_level_4_room_2' and not power_on end, translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_3'), translate("solarscale_locale", 'solarscale_ally_dlg_level_4_room_2_3_response')};
 
    
 
    {cond=function(s) return here():from()^'tower_level_3_room_2' and not _'tower_level_3_room_2'.light end, translate("solarscale_locale", 'solarscale_ally_dlg_light'), function(s)
 
@@ -636,11 +636,11 @@ dlg {
 
      {'#level32_no_help', translate("solarscale_locale", 'solarscale_let_me_try_2'), translate("solarscale_locale", 'solarscale_nods_silently')},
 
    };
 
    {cond=function(s) return here():from()^'tower_level_1_room_2' and _'solarscale_ally'.tea_found and not _'solarscale_ally'.tea_asked end, translate("solarscale_locale", 'solarscale_ally_ask_tea'), function(s)
 
			_'solarscale_ally'.tea_asked = true;
 
			return translate_now("solarscale_locale", 'solarscale_ally_ask_tea_response')
 
		end};
 
      _'solarscale_ally'.tea_asked = true;
 
      return translate_now("solarscale_locale", 'solarscale_ally_ask_tea_response')
 
    end};
 
    {translate("solarscale_locale", 'solarscale_ally_dlg_end'), function(s) walkout(); end};
 
	};
 
  };
 
}
 

	
 
dlg {
 
@@ -648,23 +648,23 @@ dlg {
 
  repeat_question = false;
 
  nam = 'solarscale_tea_dlg';
 
  disp = translate("solarscale_locale", 'disp');
 
	pic = function(s)
 
		local pic = std.call(from(), 'pic');
 
		local spic = 'images/characters/solarscale.png';
 
		if not power_on and (from() ^ 'tower_level_4_room_2' or from() ^ 'tower_level_3_room_2' and not from().light) then
 
			spic = 'images/characters/solarscale_tower_dark.png';
 
		elseif from() ^ 'tower_level_4' or from() ^ 'tower_level_3' or from() ^ 'tower_level_4_room_2' or from() ^ 'tower_level_1_room_2' or from() ^ 'tower_level_2' or from() ^ 'tower_level_3_room_2' and not power_on then
 
			spic = 'images/characters/solarscale_tower_dusk.png';
 
		elseif not power_on and (from() ^ 'tower_level_2_room_2' or from() ^ 'tower_level_2_airlock') then
 
			spic = 'images/characters/solarscale_tower_dusk_red.png';
 
		elseif from() ^ 'tower_level_2_room_2' or from() ^ 'tower_level_2_airlock' or from() ^ 'tower_level_3_room_2' or from() ^ 'tower_level_1' then
 
			spic = 'images/characters/solarscale_tower_synth.png';
 
		end;
 
		return pic .. ';' .. spic;
 
	end;
 
  pic = function(s)
 
    local pic = std.call(from(), 'pic');
 
    local spic = 'images/characters/solarscale.png';
 
    if not power_on and (from() ^ 'tower_level_4_room_2' or from() ^ 'tower_level_3_room_2' and not from().light) then
 
      spic = 'images/characters/solarscale_tower_dark.png';
 
    elseif from() ^ 'tower_level_4' or from() ^ 'tower_level_3' or from() ^ 'tower_level_4_room_2' or from() ^ 'tower_level_1_room_2' or from() ^ 'tower_level_2' or from() ^ 'tower_level_3_room_2' and not power_on then
 
      spic = 'images/characters/solarscale_tower_dusk.png';
 
    elseif not power_on and (from() ^ 'tower_level_2_room_2' or from() ^ 'tower_level_2_airlock') then
 
      spic = 'images/characters/solarscale_tower_dusk_red.png';
 
    elseif from() ^ 'tower_level_2_room_2' or from() ^ 'tower_level_2_airlock' or from() ^ 'tower_level_3_room_2' or from() ^ 'tower_level_1' then
 
      spic = 'images/characters/solarscale_tower_synth.png';
 
    end;
 
    return pic .. ';' .. spic;
 
  end;
 
  theme = function(s) 
 
		return here():from().theme;
 
	end;
 
    return here():from().theme;
 
  end;
 
  enter = translate("solarscale_locale", 'tea_start');
 
  phr = {
 
    {translate("solarscale_locale", 'solarscale_don_t_know'), function(s)
terminal.lua
Show inline comments
 
deleted file
terminal/base.lua
Show inline comments
 
new file 100644
 
function terminal(s) 
 
  s[#s + 1] = {
 
    _keyts = 0;
 
    _key = 0;
 
    _keypress = false;
 
    path = 'C:\\';
 
    entry = '';
 
    noinv = true;
 
    status = 'command';
 
    theme = 'terminal';
 
    format_percent = 0;
 
    mx = false;
 
    my = false;
 
    directory_structure = {
 
      ['C:'] = {
 
        ['DOCS'] = {
 
          ['PASSWORD.TXT'] = function(s, command, args)
 
            if command == 'PRINT.COM' then
 
              s:push(translate_now("terminal_locale", 'binary_data'));
 
            else
 
              s:push(translate_now("terminal_locale", 'bad_command'));
 
            end;
 
          end;
 
          ['CRYPT.COM'] = function(s, command, args)
 
            if command == 'PRINT.COM' then
 
              s:push(translate_now("terminal_locale", 'binary_data'));
 
            elseif command == '' then
 
              if not args then
 
                s:push(translate_now("terminal_locale", 'crypt_usage'));
 
              else
 
                local new_args = {};
 
                for i in string.gmatch(args, "%S+") do
 
                  if i and i ~= '' then
 
                    new_args[#new_args + 1] = i;
 
                  end;
 
                end;
 

	
 
                if #new_args > 2 then
 
                  s:push(translate_now("terminal_locale", 'crypt_usage'));
 
                  return
 
                elseif #new_args < 2 then
 
                  s:push(translate_now("terminal_locale", 'crypt_key_unset'));
 
                  return;
 
                end;
 
                local name, path;
 
                name, path = s:walk_directory(new_args[1], true);
 
                
 
                if name ~= nil and path == 'C:\\DOCS\\PASSWORD.TXT' then
 
                  name, path = s:walk_directory(new_args[2], true);
 
                  if name ~= nil and path == 'C:\\DOCS\\KEY.TXT' then
 
                    s:push(translate_now("terminal_locale", 'crypt_key_locked'));
 
                    s.status = 'crypt';
 
                    return true;
 
                  else
 
                    s:push(translate_now("terminal_locale", 'crypt_invalid_key'));
 
                  end;
 
                  
 
                else
 
                  s:push(translate_now("terminal_locale", 'crypt_unencrypted'));
 
                end;
 
              end;
 
            end;
 
          end;
 
          ['CRYPT.CFG'] = function(s, command, args)
 
            if command == 'PRINT.COM' then
 
              s:push('[MAIN]');
 
              s:push('ALGORITHM=AES');
 
              s:push('[RSA]');
 
              s:push('HARDWARE=FALSE');
 
              s:push(';KEY=KEY.TXT');
 
            else
 
              s:push(translate_now("terminal_locale", 'bad_command'));
 
            end;
 
          end;
 
          ['KEY.TXT'] = function(s, command, args)
 
            if command == 'PRINT.COM' then
 
              s:push(translate_now("terminal_locale", 'binary_data'));
 
            else
 
              s:push(translate_now("terminal_locale", 'bad_command'));
 
            end;
 
          end;
 
        },
 
        ['SYSTEM'] = {
 
          ['CONNECT.EXE'] = function(s, command, args)
 
            if command == 'PRINT.COM' then
 
              s:push(translate_now("terminal_locale", 'binary_data'));
 
            elseif command == '' then
 
              s.status = 'connect';
 
              return true;
 
            end;
 
          end;
 
          ['FORMAT.COM'] = function(s, command, args)
 
            if command == 'PRINT.COM' then
 
              s:push(translate_now("terminal_locale", 'binary_data'));
 
            elseif command == '' then
 
              if args and args:lower() == 'c:' then
 
                s.status = 'format';
 
                return true;
 
              elseif args and string.match(args, "^[A-z]:$") == args then
 
                s:push(translate_now("terminal_locale", 'format_invalid_device'));
 
              else
 
                s:push(translate_now("terminal_locale", 'format_usage'));
 
              end;
 
            end;
 
          end;
 
          ['HELP.COM'] = function(s, command, args)
 
            if command == 'PRINT.COM' then
 
              s:push(translate_now("terminal_locale", 'binary_data'));
 
            elseif command == '' then
 
              s:push(translate_now("terminal_locale", 'help_cd'));
 
              s:push(translate_now("terminal_locale", 'help_dir'));
 
              s:push(translate_now("terminal_locale", 'help_disk'));
 
              s:push(translate_now("terminal_locale", 'help_connect'));
 
              s:push(translate_now("terminal_locale", 'help_format'));
 
              s:push(translate_now("terminal_locale", 'help_help'));
 
              s:push(translate_now("terminal_locale", 'help_print'));
 
              s:push(translate_now("terminal_locale", 'help_exit'));
 
              s:push(translate_now("terminal_locale", 'help_com_exe'));
 
            end;
 
          end;
 
          ['PRINT.COM'] = function(s, command, args)
 
            if command == 'PRINT.COM' then
 
              s:push(translate_now("terminal_locale", 'binary_data'));
 
            elseif command == '' then
 
              if args then
 
                local cmd = s:walk_directory(args:upper(), true);
 
                if type(cmd) == 'function' then
 
                  cmd(s, 'PRINT.COM', '')
 
                else
 
                  s:push(translate_now("terminal_locale", 'print_no_file'));
 
                end;
 
              else
 
                s:push(translate_now("terminal_locale", 'print_usage'));
 
              end;
 
            end;
 
          end;
 
        },
 
        ['AUTOEXEC.BAT'] = function(s, command, args)
 
          if command == 'PRINT.COM' then
 
            s:push('SET PATH=C:\\SYSTEM');
 
            s:push(translate_now("terminal_locale", 'connect_comment'));
 
          elseif command == '' then
 
            s:push(translate_now("terminal_locale", 'bad_command'));
 
          end;
 
        end;
 
        ['CONFIG.SYS'] = function(s, command, args)
 
          if command == 'PRINT.COM' then
 
            s:push('DEVICE=C:\\SYSTEM\\HIMEM.SYS');
 
            s:push('DOS=HIGH,UMB');
 
            s:push('FILES=30');
 
            s:push('STACKS=0,0');
 
            s:push('BUFFERS=20');
 
            s:push('DEVICE=C:\\SYSTEM\\EMM386.EXE');
 
            s:push('DEVICE=C:\\SYSTEM\\TOWER.SYS');
 
          elseif command == '' then
 
            s:push(translate_now("terminal_locale", 'bad_command'));
 
          end;
 
        end;
 
        ['COMMAND.COM'] = function(s, command, args)
 
          if command == 'PRINT.COM' then
 
            s:push(translate_now("terminal_locale", 'binary_data'));
 
          elseif command == '' then
 
            s:push(translate_now("terminal_locale", 'command_already_started'));
 
          end;
 
        end;
 
        ['HELLO.TXT'] = function(s, command, args)
 
          if command == 'PRINT.COM' then
 
            s:push(translate_now("terminal_locale", 'hello_txt'));
 
          elseif command == '' then
 
            s:push(translate_now("terminal_locale", 'bad_command'));
 
          end;
 
        end;
 
      }
 
    };
 
  };
 
  
 
  s.disp = '';
 
  s.nofollow = true;
 
  s.nofading = true;
 
  
 
  s.themeInit = function(s)
 
    load_sounds('error_beep', 'keyboard1', 'keyboard2', 'keyboard3', 'keyboard4', 'keyboard5');
 
  end;
 
  
 
  s.query_formatter = function(s, path, entry)
 
    if s.status == 'command' then
 
      return s.path .. '>' .. s.entry .. '_';
 
    elseif s.status == 'crypt' or s.status == 'connect' then
 
      return translate_now("terminal_locale", 'query_password') .. entry .. '_';
 
    elseif s.status == 'format' then
 
      return translate_now("terminal_locale", 'query_type_yes') .. entry .. '_';
 
    elseif s.status == 'wait_format' then
 
      return translate_now("terminal_locale", 'query_formatting') .. " " .. tostring(s.format_percent) .. '%';
 
    elseif s.status == 'format_done' then
 
    end;
 
    return '';
 
  end;
 
  
 
  s.command_preprocessor = function(s, command)
 
    if s.status == 'crypt' then
 
      s.status = 'command';
 
      s:push(translate_now("terminal_locale", 'query_password') .. command);
 
      if command == password1 then
 
        s:push(password2);
 
        s:push('');
 
      else
 
        s:push(translate_now("terminal_locale", 'invalid_password'));
 
        s:push('');
 
      end;
 
      s.entry = '';
 
      return true;
 
    elseif s.status == 'connect' then
 
      s.entry = '';
 
      s.status = 'command';
 
      s:push(translate_now("terminal_locale", 'query_password') .. command);
 
      if command == password2 then
 
        if irradiated then
 
          snd.music('sound/bgm_ending_space_irradiated.ogg');
 
        else
 
          snd.music('sound/bgm_ending_space.ogg');
 
        end;
 
        if solarscale_with_me then
 
          walk('ending_solarscale_pre');
 
        else
 
          walk('ending_dissolving_tower_solarscale');
 
        end;
 
        
 
      else
 
        s:push(translate_now("terminal_locale", 'invalid_password_2'));
 
      end;
 
      
 
      return true;
 
    elseif s.status == 'format' then
 
      s.status = 'format';
 
      s.entry = '';
 
      s:push(translate_now("terminal_locale", 'query_type_yes') .. command);
 
      --s:push("Type 'Yes' to confirm:" .. command);
 
      if command:lower() == 'yes' then
 
        s.status = 'wait_format';
 
        if instead.tiny then
 
          _'#fail': enable();
 
        end;
 
        timer:set(25);
 
      else
 
        s:push(translate_now("terminal_locale", 'operation_cancelled'));
 
        s.status = 'command';
 
      end;
 
      
 
      return true;
 
    elseif s.status == 'wait_format' then
 
      s.entry = '';
 
      return true;
 
    end;
 
  end;
 
  
 
  s.puch_cmd = function(s, text)
 
    s:push_line(text);
 
  end;
 
  
 
  s.push = function(s, text)
 
    local lines = split(text, '^');
 
    
 
    for _, l in ipairs(lines) do
 
      s:push_line(l);
 
    end;
 
  end;
 
  
 
  local oldenter = s.onenter;
 
  
 
  s.onenter = function(s)
 
    s.path = 'C:\\';
 
    s.entry = '';
 
    
 
    if oldenter then
 
      s:oldenter();
 
    end;
 
    
 
    s:process_directory_structure(s.directory_structure['C:']);
 
    s:push(translate_now("terminal_locale", 'tower_os_line_1'));
 
    s:push('');
 
    s:push(translate_now("terminal_locale", 'tower_os_line_2'));
 
    s:push('');
 
    s:push(translate_now("terminal_locale", 'tower_os_line_3'));
 
    s:push('');
 

	
 
    s:makekeyboard();
 
    
 
    instead.autosave();
 
  end;
 
  
 
  s.process_command = function(s, str)
 
    s:puch_cmd(s.path .. '>' .. str);
 
    
 
    local rval = {}
 
    
 
    for i in string.gmatch(str, "%S+") do
 
      if (#rval > 0) then
 
        if rval[2] then
 
          rval[2] = rval[2] .. ' ' .. i;
 
        else
 
          rval[2] = i;
 
        end;
 
      else
 
        rval[1] = i;
 
      end;
 
      
 
    end;
 
    
 
    return rval;
 
  end;
 
  
 
  s.process_directory_structure = function(s, current, parent)
 
    current['.'] = current;
 
    current['..'] = parent;
 
    for k,v in pairs(current) do
 
      if k ~= '.' and k ~= '..' and type(v) == 'table' then
 
        s:process_directory_structure(v, current);
 
      end;
 
    end;
 
  end;
 
  
 
  s.walk_directory = function(s, path, no_replace)
 
    local location = s.directory_structure;
 
    
 
    if path:sub(1, 2):upper() ~= 'C:' then
 
      path = s.path .. path;
 
    end;
 
    
 
    local spath = {};
 
    
 
    for part in string.gmatch(path, "[^\\\\]+") do
 
      part = part:upper();
 
      if part == '.' then
 
      elseif part == '..' then
 
        spath[#spath] = nil;
 
      else
 
        spath[#spath + 1] = part;
 
      end;
 
      local oloc = location;
 
      location = location[part];
 
      if not no_replace then
 
        if location == nil then
 
          location = oloc[part .. '.COM'];
 
        end;
 
        if location == nil then
 
          location = oloc[part .. '.EXE'];
 
        end;
 
      end;
 

	
 
      if location == nil then
 
        return nil, nil
 
      end;
 
    end;
 
    return location, cat_list(spath, '\\');
 
  end;
 
  
 
  s.call_command = function(s, command, args)
 
    local r = false;
 
    if command == '' or not command then
 
      return
 
    end;
 
    
 
    command = command:lower();
 
    
 
    if command == 'dir' then
 
      local rval = {};
 
    
 
      local subdir = s:walk_directory(s.path);
 
       local sort = function(s1, s2)
 
         if type(subdir[s1]) == 'function' and type(subdir[s2]) == 'table' then
 
           return false;
 
         elseif type(subdir[s1]) == 'table' and type(subdir[s2]) == 'function' then
 
           return true;
 
         end;
 
         return s1 < s2;
 
      end;
 
      
 
      for k, v in pairs(subdir) do
 
        rval[#rval + 1] = k;
 
      end;
 
      
 
      table.sort(rval, sort);
 
      
 
      for i, v in ipairs(rval) do
 
        s:push(v);
 
      end;
 
    elseif command == 'cd' then
 
      if args then
 
        args = args:upper();
 
        local dir, path = s:walk_directory(args)
 
        if type(dir) == 'table' then
 
          s.path = path .. '\\';
 
        else
 
          s:push(translate_now("terminal_locale", 'cd_invalid_directory', {path=args}));
 
        end;
 
      else
 
        s:push(translate_now("terminal_locale", 'cd_usage'));
 
      end;
 
    elseif command == 'ver' then
 
      s:push(translate_now("terminal_locale", 'tower_os_line_2'));
 
    elseif command == 'exit' then
 
      walk('tower_level_4_room_2');
 
      return true;
 
    elseif command == 'rm' and args and #args >= 2 and (args == '-rf . /' or args == '-rf /') then
 
      s:push(translate_now("terminal_locale", random_phrase({'unix_line_3', 'unix_line_4'})));
 
    elseif command == 'sudo' or command == 'su' or command == 'ls' or command == 'rm' then
 
      s:push(translate_now("terminal_locale", random_phrase({'unix_line_1', 'unix_line_2'})));
 
    elseif command == 'cat' then
 
      s:push(translate_now("terminal_locale", random_phrase({'cat_line_1', 'cat_line_2', 'cat_line_3'})));
 
    elseif command == 'more' or command == 'less' then
 
      s:push(translate_now("terminal_locale", 'more_line_1'));
 
    elseif command == 'head' or command == 'tail' then
 
      s:push(translate_now("terminal_locale", random_phrase({'head_line_1', 'head_line_2'})));
 
    elseif command == 'echo' then
 
      if args then
 
        s:push(args);
 
      else
 
        s:push('');
 
      end;
 
    elseif command == 'help' or command:lower() == 'help.com' then
 
      r = s.directory_structure['C:']['SYSTEM']['HELP.COM'](s, '', args);
 
    elseif command == 'print' or command:lower() == 'print.com' then
 
      r = s.directory_structure['C:']['SYSTEM']['PRINT.COM'](s, '', args);
 
    elseif command == 'format' or command:lower() == 'format.com' then
 
      r = s.directory_structure['C:']['SYSTEM']['FORMAT.COM'](s, '', args);
 
    elseif command == 'connect' or command:lower() == 'connect.exe' then
 
      r = s.directory_structure['C:']['SYSTEM']['CONNECT.EXE'](s, '', args);
 
    elseif #command == 2 and command:sub(2, 2) == ':' then
 
      if (s.directory_structure[command]) then
 
        s.path = command:upper() .. '\\';
 
      else
 
        s:push(translate_now("terminal_locale", 'format_invalid_device'));
 
      end;
 
    else
 
      local cmd = s:walk_directory(command:upper())
 
      if type(cmd) == 'function' then
 
        r = cmd(s, '', args);
 
      else
 
        s:push(translate_now("terminal_locale", 'bad_command'));
 
      end;
 
    end;
 
    if not r then
 
      s:push('');
 
    end;
 
  end;
 
  
 
  return room(s);
 
end;
 
\ No newline at end of file
terminal/common.lua
Show inline comments
 
new file 100644
 
if instead.tiny then
 
  include "terminal/tiny.lua"
 
else
 
  include "terminal/full.lua"
 
end;
 

	
 
function make_password()
 
  local words = {
 
    'Alpha';
 
    'Ancient';
 
    'Beta';
 
    'Biography';
 
    'Clear';
 
    'Catalyst';
 
    'Delta';
 
    'Destination';
 
    'Endless';
 
    'Esoteric';
 
    'Flower';
 
    'Freedom';
 
    'Gamma';
 
    'Geography';
 
    'Home';
 
    'History';
 
    'Infinite';
 
    'Initial';
 
    'Instead';
 
    'Journey';
 
    'King';
 
    'Knight';
 
    'Knowledge';
 
    'Lion';
 
    'Lost';
 
    'Magic';
 
    'Micron';
 
    'Night';
 
    'Novel';
 
    'Omega';
 
    'Ocean';
 
    'Precise';
 
    'Power';
 
    'Quality';
 
    'Question';
 
    'Rarity';
 
    'Reason';
 
    'Silent';
 
    'Secret';
 
    'Tiger';
 
    'Theta';
 
    'Tower';
 
    'Ultimate';
 
    'Universe';
 
    'Visitor';
 
    'Vital';
 
    'Wolf';
 
    'Wizardry';
 
  };
 
  local numbers = {'0','1','2','3','4','5','6','7','8','9'};
 
  
 
  return random_phrase(words) .. '_' .. random_phrase(words) .. '_' .. random_phrase(numbers) .. random_phrase(numbers);
 
end;
terminal/full.lua
Show inline comments
 
new file 100644
 
include "terminal/base"
 

	
 
local input = std.ref '@input'
 
function input:text(char)
 
  return '@text "\\' .. char .. '"';
 
end;
 

	
 
std.mod_cmd(function(cmd)
 
  if cmd[1] == '@text' then
 
    if here().ontext then
 
      here():ontext(tostring(cmd[2]));
 
    end;
 
  end;
 
end)
 

	
 
function getscreen(graphical)
 
  local d = D('terminal_screen');
 
  if not d or d.graphical ~= graphical then
 
    local scale = diretheme.get_scale();
 
    local sw, sh = diretheme.get_scaled_screen();
 
    local x = math.floor((sw - 569) / 2 - 16);
 
    local dy = 0;
 
    if sh < 540 then
 
      dy = 19;
 
    end;
 
    local y = math.max(sh - 736 - dy, 25 - dy);
 
    local h = 320;
 
    if sh < 500 then
 
      h = h - 16;
 
    end;
 
    local offset = 0;
 
    if graphical then
 
      offset = 70 * scale;
 
    end;
 
    d = D {'terminal_screen', 'simple_txt', {}, w = 569 * scale, h = h * scale, x = x * scale, y = y * scale, color = '#D0FFFF', color_link = '#abdece', color_alink = '#9bcebe', background=true, z=1000, font = 'fonts/vga.ttf', size=16 * scale, graphical = graphical, bgcolor='#000000', offset = offset};
 
  end;
 
  return d;
 
end;
 

	
 
function terminal_untheme(s)
 
  std.kh_leave_spaces = false;
 
  fmt.para = true;
 
end;
 

	
 
local function btn_anim_process(v)
 
  if v.animated == 1 then
 
    v.animated = true;
 
  elseif v.animated and v.frame_nr == 0 then
 
    v.animated = false;
 
    return true;
 
  else
 
    return true;
 
  end;
 
end;
 

	
 
local function shift_anim_process(v) 
 
  if v.frame_nr == 2 then
 
    v.animated = false;
 
  else
 
    return true;
 
  end;
 
end;
 

	
 
local keymapping = {
 
  ['`'] = '~',
 
  ['1'] = '!',
 
  ['2'] = '@',
 
  ['3'] = '#',
 
  ['4'] = '$',
 
  ['5'] = '%',
 
  ['6'] = '^',
 
  ['7'] = '&',
 
  ['8'] = '*',
 
  ['9'] = '(',
 
  ['0'] = ')',
 
  ['-'] = '_',
 
  ['='] = '+',
 
  ['q'] = 'Q', 
 
  ['w'] = 'W', 
 
  ['e'] = 'E',
 
  ['r'] = 'R',
 
  ['t'] = 'T',
 
  ['y'] = 'Y',
 
  ['u'] = 'U',
 
  ['i'] = 'I', 
 
  ['o'] = 'O',
 
  ['p'] = 'P',
 
  ['['] = '{',
 
  [']'] = '}',
 
  ['\\'] = '|',
 
  ['a'] = 'A',
 
  ['s'] = 'S',
 
  ['d'] = 'D',
 
  ['f'] = 'F',
 
  ['g'] = 'G',
 
  ['h'] = 'H',
 
  ['j'] = 'J',
 
  ['k'] = 'K',
 
  ['l'] = 'L',
 
  [';'] = ':',
 
  ["'"] = '"',
 
  ['z'] = 'Z',
 
  ['x'] = 'X',
 
  ['c'] = 'C',
 
  ['v'] = 'V',
 
  ['b'] = 'B',
 
  ['n'] = 'N',
 
  ['m'] = 'M',
 
  [','] = '.',
 
  ['.'] = ',',
 
  ['/'] = '?',
 
};
 

	
 
local reverse_keymapping = {
 
  ['>'] = '>';
 
  ['<'] = '<'
 
};
 
for k, v in pairs(keymapping) do
 
  reverse_keymapping[v] = k;
 
end;
 

	
 
local key_sounds = {
 
  'keyboard1', 'keyboard2', 'keyboard3', 'keyboard4', 'keyboard5'
 
}
 

	
 
local handled_keys = Set {
 
  '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 'backspace','shift',
 
  'q', 'w', 'e', 'r', 't', 'y', 'u','i', 'o', 'p', '[', ']', '\\', 
 
  'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', "'", 'return',
 
  'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 
 
  'space', 'left', 'right', 'up', 'down', 'left shift'
 
}
 

	
 
local release_handled_keys = Set {
 
  'left shift'
 
}
 

	
 
local mapping_decor_key = {
 
  btn_backquote = '`';
 
  btn_1 = '1';
 
  btn_2 = '2';
 
  btn_3 = '3';
 
  btn_4 = '4';
 
  btn_5 = '5';
 
  btn_6 = '6';
 
  btn_7 = '7';
 
  btn_8 = '8';
 
  btn_9 = '9';
 
  btn_0 = '0';
 
  btn_minus = '-';
 
  btn_backspace = 'backspace';
 
  
 
  btn_q = 'q';
 
  btn_w = 'w';
 
  btn_e = 'e';
 
  btn_r = 'r';
 
  btn_t = 't';
 
  btn_y = 'y';
 
  btn_u = 'u';
 
  btn_i = 'i';
 
  btn_o = 'o';
 
  btn_p = 'p';
 
  btn_left_bracket = '[';
 
  btn_right_bracket = ']';
 
  btn_equal = '=';
 

	
 
  btn_a = 'a';
 
  btn_s = 's';
 
  btn_d = 'd';
 
  btn_f = 'f';
 
  btn_g = 'g';
 
  btn_h = 'h';
 
  btn_j = 'j';
 
  btn_k = 'k';
 
  btn_l = 'l';
 
  btn_semicolon = ';';
 
  btn_enter = 'return';
 

	
 

	
 
  btn_z = 'z';
 
  btn_x = 'x';
 
  btn_c = 'c';
 
  btn_v = 'v';
 
  btn_b = 'b';
 
  btn_n = 'n';
 
  btn_m = 'm';
 
  btn_comma = ',';
 
  btn_slash = '/';
 
  btn_backslash = '\\';
 
  btn_quote = '\'';
 
  btn_space = 'space';
 
};
 

	
 
local back_mapping_decor_key = {};
 

	
 
for k, v in pairs(mapping_decor_key) do
 
  back_mapping_decor_key[v] = k;
 
end;
 

	
 
function click:filter(press, btn, x, y, px, py)
 
  return not press
 
end
 

	
 
room {
 
  {
 
    ticks = 0;
 
    ram = 0;
 
  };
 
  nam = 'terminal_boot';
 
  disp = '';
 
  nosave = true;
 
  noautosave = true;
 
  nofollow = true;
 
  noinv = true;
 
  nofading = true;
 
  network = false;
 
  graphical = false;
 
  theme = 'terminal';
 
  themeInit = function(s)
 
    load_sounds('error_beep', 'pc_startup', 'keyboard1', 'keyboard2', 'keyboard3', 'keyboard4', 'keyboard5');
 
    timer:set(25);
 
    
 
    local scale = diretheme.get_scale();
 
    local width, height = diretheme.get_scaled_screen();
 
    
 
    local rc = 0;
 
    if s.graphical then
 
      local animx = math.max(math.floor((width - 640) / 2) + 20, 20) * scale;
 
      local animy = math.max(height - 734, 26) * scale;
 
      
 
      if height < 540 then
 
        animy = animy - 19 * scale;
 
      end;
 
      D {'logo', 'img', get_sprite('images/terminal/pc_anim.png'), x = animx, y = animy, w=64 * scale, h=64 * scale, frames = 24, z = 1, delay=175, speed=175, animated=true, background=true, process=function(d)
 
        if d.frame_nr == 8 and rc < 2 then
 
          d.frame_nr = 0;
 
          rc = rc + 1;
 
        elseif d.frame_nr == 9 then
 
          rc = 0;
 
        end;
 
      end};
 
    end;
 
    
 
    local x = math.floor((width - 800) / 2);
 
    
 
    local y = height - 193;
 
    if y < 564 then
 
      y = 564;
 
    end;
 
    
 
    local top = height - 193;
 
    if height < 540 then
 
      top = top + 20;
 
    end;
 

	
 
    local delta = math.ceil((y - top) / 8) * scale;
 
    top = top * scale;
 
    
 
    DS {'keyboard', 'img', 'images/terminal/keyboard.png', x = x - 116, y = y, w=1036, h=191, z=0, speed=25, process=function(d)
 
      if s.network and s.ticks >= 128 and delta > 0 then
 
        d.y = d.y - delta;
 
        delta = delta - scale;
 
        if d.y < top then
 
           d.y = top;
 
           delta = 0;
 
        end;
 
      else
 
        return true;
 
      end;
 
    end};
 
  end;
 
  onenter = function(s)
 
    s.ticks = 0;
 
    s.ram = 0;
 
    local d = getscreen(s.graphical);
 
    d:drop_all();
 
    
 
    stop_sound();
 
  end;
 
  onexit = function(s)
 
    D {'logo'};
 
    D {'keyboard'};
 
    D {'terminal_screen'};
 
  end;
 
  timer = function(s)
 
    if s.ticks ~= 33 then
 
      s.ticks = s.ticks + 1;
 
    else
 
      local ram = lookup('#ram', _'system_unit').device;
 

	
 
      s.ram = s.ram + ram.size * 16;
 
      if s.ram > ram.size * 1024 then
 
        s.ram = ram.size * 1024;
 
        s.ticks = s.ticks + 1;
 
      end;
 
    end;
 
    if s.network then
 
      if s.ticks == 128 then
 
        D {'logo'};
 
      end;
 
      if s.ticks >= 156 then
 
        walk('terminal');
 
      end;
 
    else
 
      if s.ticks >= 300 then
 
        walk('tower_level_4_room_2');
 
        return;
 
      end;
 
      if s.ticks > 112 then
 
        return false;
 
      end;
 
    end;
 
    
 
    s:makescreen();
 
    
 
    return false;
 
  end;
 
  dsc = '';
 
  txt = {};
 
  makescreen = function(s)
 
    local d = getscreen(s.graphical and s.ticks < 128);
 
    if s.ticks < 128 then
 
      local motherboard = lookup('#motherboard', _'system_unit').device;
 
      local cpu = lookup('#cpu', _'system_unit').device;
 
      local ram = lookup('#ram', _'system_unit').device;
 
      
 
      if s.ticks == 1 then
 
        d:insert_line('TOWER BIOS 1.0');
 
      end;
 

	
 
      if s.ticks == 8 then
 
        d:insert_line(translate_now("terminal_locale", 'motherboard') .. ' : ' .. motherboard.name);
 
      end;
 

	
 
      if s.ticks == 16 then
 
        d:insert_line(translate_now("terminal_locale", 'cpu') .. ' : ' .. cpu.name .. ' @ ' .. cpu.speed .. '.0' .. translate_now("terminal_locale", 'mhz'));
 
      end;
 

	
 
      if s.ticks == 24 then
 
        d:insert_line(translate_now("terminal_locale", 'ram') .. ' : '.. ram.name);
 
      end;
 

	
 
      if s.ticks == 32 then
 
        d:insert_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'))
 
      end;
 

	
 
      if s.ticks == 33 then
 
        d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'))
 
      end;
 

	
 
      if s.ticks == 34 then
 
        d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'));
 
      end;
 

	
 
      if s.ticks == 40 then
 
        d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes') .. ' OK');
 
        d:insert_line(' ');
 
      end;
 

	
 
      if s.ticks == 48 then
 
        d:insert_line(translate_now("terminal_locale", 'keyboard') .. ' : ');
 
      end;
 

	
 
      if s.ticks == 56 then
 
        d:replace_line(translate_now("terminal_locale", 'keyboard') .. ' : OK')
 
      end;
 

	
 
      if s.ticks == 64 then
 
        d:insert_line(translate_now("terminal_locale", 'disk') .. ' : ');
 
      end;
 

	
 
      if s.ticks == 72 then
 
        d:replace_line(translate_now("terminal_locale", 'disk') .. ' : ' .. translate_now("terminal_locale", 'missing'));
 
      end;
 

	
 
      if s.ticks == 80 then
 
        d:insert_line(translate_now("terminal_locale", 'network') .. ' : ');
 
      end;
 

	
 
      if s.ticks == 88 then
 
        if s.network then
 
          d:replace_line(translate_now("terminal_locale", 'network') .. ' : OK');
 
        else
 
          d:replace_line(translate_now("terminal_locale", 'network') .. ' : ' .. translate_now("terminal_locale", 'missing'));
 
        end;
 
        d:insert_line(' ');
 
      end;
 

	
 
      if s.ticks == 104 then
 
        d:insert_line(translate_now("terminal_locale", 'boot_from'));
 
      end;
 

	
 
      if s.network then
 
        if s.ticks == 112 then
 
          d:replace_line(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'network_2'));
 
        end;
 

	
 
        if s.ticks == 120 then
 
          d:replace_line(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'network_2') .. '...');
 
        end;
 
      else
 
        if s.ticks == 112 then
 
          d:replace_line(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'no_device'));
 
        end;
 
      end;
 
    elseif s.ticks == 128 then
 
      d:drop_all();
 
      d:insert_line(translate_now("terminal_locale", 'tower_os_line_1'));
 
      d:insert_line(' ');
 
    else
 
      if s.ticks == 136 then
 
        d:insert_line(translate_now("terminal_locale", 'tower_os_line_2'));
 
        d:insert_line(' ');
 
      end;
 

	
 
      if s.ticks == 144 then
 
        d:insert_line(translate_now("terminal_locale", 'tower_os_line_3'));
 
        d:insert_line(' ');
 
      end;
 
    end;
 
  end;
 
}
 

	
 
room {
 
  {
 
    ticks = 0;
 
    ram = 0;
 
  };
 
  nam = 'terminal_boot_failure';
 
  theme = 'terminal';
 
  disp = '';
 
  noinv = true;
 
  nofading = true;
 
  nofollow = true;
 
  graphical = false;
 
  nosave = true;
 
  noautosave = true;
 
  themeInit = function(s)
 
    timer:set(25);
 
    
 
    local scale = diretheme.get_scale();
 
    local width, height = diretheme.get_scaled_screen();
 
    
 
    local rc = 0;
 
    if s.graphical then
 
      local animx = math.max(math.floor((width - 640) / 2) + 20, 20) * scale;
 
      local animy = math.max(height - 734, 26) * scale;
 
      
 
      if height < 540 then
 
        animy = animy - 19 * scale;
 
      end;
 
      D {'logo', 'img', get_sprite('images/terminal/pc_anim.png'), x = animx, y = animy, w=64 * scale, h=64 * scale, frames = 24, z = 1, delay = 175, speed = 175, animated=true, background=true, process=function(d)
 
        if d.frame_nr == 8 and rc < 2 then
 
          d.frame_nr = 0;
 
          rc = rc + 1;
 
        elseif d.frame_nr == 9 then
 
          rc = 0;
 
        end;
 
      end};
 
    end;
 

	
 
    local x = math.floor((width - 800) / 2);
 
    
 
    local y = height - 193;
 
    if height < 540 then
 
      y = y + 20;
 
    end;
 
    
 
    DS {'keyboard', 'img', 'images/terminal/keyboard.png', x = x - 116, y = y, w=1036, h=191, z=0};
 
  end;
 
  onenter = function(s)
 
    s.graphical = _('terminal_boot').graphical;    
 
    s.ticks = 0;
 
    s.ram = 0;
 
    local d = getscreen(s.graphical);
 
    d:drop_all();
 
    
 
    stop_sound();
 
  end;
 
  onboot = function(s)
 
    s:process_directory_structure(s.directory_structure['C:']);
 
    
 
    s:makekeyboard();
 
    local d = getscreen(false);
 
    d:replace_line(s.path .. '>' .. s.entry .. '_');
 
  end;
 
  onexit = function(s)    
 
    enableSmoke('images/endings/tower_ruin.png');
 

	
 
    D {'terminal_screen'};
 
    D {'keyboard'};
 
    D {'logo'};
 
  end;
 
  timer = function(s)
 
    if s.ticks ~= 33 then
 
      s.ticks = s.ticks + 1;
 
    else
 
      local ram = lookup('#ram', _'system_unit').device;
 

	
 
      s.ram = s.ram + ram.size * 16;
 
      if s.ram > ram.size * 1024 then
 
        s.ram = ram.size * 1024;
 
        s.ticks = s.ticks + 1;
 
      end;
 
    end;
 

	
 
    if s.ticks == 128 then
 
      D {'logo'};
 
    end;
 
    if s.ticks >= 200 then
 
      walk('ending_formatted');
 
      return;
 
    end;
 

	
 
    s:makescreen();
 
    
 
    return false;
 
  end;
 
  dsc = '';
 
  txt = '';
 
  makescreen = function(s)
 
    local d = getscreen(s.graphical and s.ticks < 128);
 
    if s.ticks < 128 then
 
      local motherboard = lookup('#motherboard', _'system_unit').device;
 
      local cpu = lookup('#cpu', _'system_unit').device;
 
      local ram = lookup('#ram', _'system_unit').device;
 

	
 
      if s.ticks == 1 then
 
        d:insert_line('TOWER BIOS 1.0');
 
      end;
 

	
 
      if s.ticks == 8 then
 
        d:insert_line(translate_now("terminal_locale", 'motherboard') .. ' : ' .. motherboard.name);
 
      end;
 

	
 
      if s.ticks == 16 then
 
        d:insert_line(translate_now("terminal_locale", 'cpu') .. ' : ' .. cpu.name .. ' @ ' .. cpu.speed .. '.0' .. translate_now("terminal_locale", 'mhz'));
 
      end;
 

	
 
      if s.ticks == 24 then
 
        d:insert_line(translate_now("terminal_locale", 'ram') .. ' : '.. ram.name);
 
      end;
 

	
 
      if s.ticks == 32 then
 
        d:insert_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'))
 
      end;
 

	
 
      if s.ticks == 33 then
 
        d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'))
 
      end;
 

	
 
      if s.ticks == 34 then
 
        d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'));
 
      end;
 

	
 
      if s.ticks == 40 then
 
        d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes') .. ' OK');
 
        d:insert_line(' ');
 
      end;
 

	
 
      if s.ticks == 48 then
 
        d:insert_line(translate_now("terminal_locale", 'keyboard') .. ' : ');
 
      end;
 

	
 
if s.ticks == 56 then
 
        d:replace_line(translate_now("terminal_locale", 'keyboard') .. ' : OK')
 
      end;
 

	
 
      if s.ticks == 64 then
 
        d:insert_line(translate_now("terminal_locale", 'disk') .. ' : ');
 
      end;
 

	
 
      if s.ticks == 72 then
 
        d:replace_line(translate_now("terminal_locale", 'disk') .. ' : ' .. translate_now("terminal_locale", 'missing'));
 
      end;
 

	
 
      if s.ticks == 80 then
 
        d:insert_line(translate_now("terminal_locale", 'network') .. ' : ');
 
      end;
 

	
 
      if s.ticks == 88 then
 
        if s.network then
 
          d:replace_line(translate_now("terminal_locale", 'network') .. ' : OK');
 
        else
 
          d:replace_line(translate_now("terminal_locale", 'network') .. ' : ' .. translate_now("terminal_locale", 'missing'));
 
        end;
 
        d:insert_line(' ');
 
      end;
 

	
 
      if s.ticks == 104 then
 
        d:insert_line(translate_now("terminal_locale", 'boot_from'));
 
      end;
 

	
 

	
 
      if s.ticks == 112 then
 
        d:replace_line(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'network_2'));
 
      end;
 

	
 
      if s.ticks == 120 then
 
        d:replace_line(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'network_2') .. '...');
 
      end;
 
    else
 
      d:drop_all();
 
      d:insert_line(translate_now("terminal_locale", 'no_bootable_medium_found'));
 
    end;
 
  end;
 
}
 

	
 
terminal {
 
  nam = 'terminal';
 
  
 
  keysfilter = function(s, press, key)
 
    return handled_keys[key] ~= nil; -- ловим все нажатия
 
  end;
 
  
 
  timer = function(s)
 
    if s.status == 'wait_format' then
 
      if s.format_percent < 100 then
 
        s.format_percent = s.format_percent + 1;
 
        local d = getscreen(false);
 
        d:replace_line(s:query_formatter(s.path, s.entry));
 
      else
 
        s.status = 'format_done';
 
        s:push(translate_now("terminal_locale", 'formatting_complete'));
 
      end;
 
      return false;
 
    elseif s.status == 'format_done' then
 
      if s.format_percent < 120 then
 
        s:push(translate_now("terminal_locale", 'critical_failure'));
 
      end;
 
      
 
      s.format_percent = s.format_percent + 1;
 
      if s.format_percent > 150 then
 
        timer:stop();
 
        walk('terminal_boot_failure');
 
        return;
 
      end;
 
      return false;
 
    end;
 
    return false;
 
  end;
 
  
 
  push_line = function(s, line)
 
    local d = getscreen(false);
 
    d:replace_line(line);
 
    if s.query_formatter then
 
      d:insert_line(s:query_formatter(s.path, s.entry));
 
    else
 
      d:insert_line(s.path .. '>' .. s.entry .. '_');
 
    end;
 
  end;
 
  
 
  makekeyboard = function(s)
 
    local width, height = diretheme.get_scaled_screen();
 
    
 
    local x = math.floor((width - 800) / 2);
 
    local y = height - 191;
 
    if height < 540 then
 
      y = y + 20;
 
    end;
 
    
 
    DS {'keyboard_bg', 'img', 'images/terminal/keyboard_bg.png', x=x - 116, y=y - 2, w=1036, h=191, z=110};
 
    -- Keyboard row 1
 
    -- D {'btn_backquote', 'img', 'images/terminal/keyboard/btn_backquote.png', x=x + 67, y=y, w=64, h=46, frames=3, z=100, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_1', 'img', 'images/terminal/keyboard/btn_1.png', x=x + 119, y=y, w=58, h=46, frames=3, z=99, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_2', 'img', 'images/terminal/keyboard/btn_2.png', x=x + 167, y=y, w=55, h=46, frames=3, z=98, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_3', 'img', 'images/terminal/keyboard/btn_3.png', x=x + 215, y=y, w=51, h=46, frames=3, z=97, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_4', 'img', 'images/terminal/keyboard/btn_4.png', x=x + 260, y=y, w=49, h=46, frames=3, z=96, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_5', 'img', 'images/terminal/keyboard/btn_5.png', x=x + 307, y=y, w=44, h=46, frames=3, z=95, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_6', 'img', 'images/terminal/keyboard/btn_6.png', x=x + 351, y=y, w=47, h=46, frames=3, z=95, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_7', 'img', 'images/terminal/keyboard/btn_7.png', x=x + 398, y=y, w=48, h=46, frames=3, z=96, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_8', 'img', 'images/terminal/keyboard/btn_8.png', x=x + 444, y=y, w=48, h=46, frames=3, z=97, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_9', 'img', 'images/terminal/keyboard/btn_9.png', x=x + 486, y=y, w=51, h=46, frames=3, z=98, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_0', 'img', 'images/terminal/keyboard/btn_0.png', x=x + 529, y=y, w=55, h=46, frames=3, z=99, delay=50, process=btn_anim_process, click=true};
 
    -- DS {'btn_minus', 'img', 'images/terminal/keyboard/btn_minus.png', x=x + 574, y=y, w=58, h=46, frames=3, z=100, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_backspace', 'img', 'images/terminal/keyboard/btn_backspace.png', x=x + 619, y=y, w=109, h=46, frames=3, z=101, delay=50, process=btn_anim_process, click=true};
 

	
 
    -- Keyboard row 2
 
    DS {'btn_q', 'img', 'images/terminal/keyboard/btn_q.png', x=x + 81, y=y + 26, w=61, h=46, frames=3, z=90, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_w', 'img', 'images/terminal/keyboard/btn_w.png', x=x + 130, y=y + 26, w=59, h=46, frames=3, z=89, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_e', 'img', 'images/terminal/keyboard/btn_e.png', x=x + 180, y=y + 26, w=57, h=46, frames=3, z=88, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_r', 'img', 'images/terminal/keyboard/btn_r.png', x=x + 230, y=y + 26, w=53, h=46, frames=3, z=87, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_t', 'img', 'images/terminal/keyboard/btn_t.png', x=x + 278, y=y + 26, w=50, h=46, frames=3, z=86, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_y', 'img', 'images/terminal/keyboard/btn_y.png', x=x + 327, y=y + 26, w=45, h=46, frames=3, z=85, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_u', 'img', 'images/terminal/keyboard/btn_u.png', x=x + 373, y=y + 26, w=52, h=46, frames=3, z=85, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_i', 'img', 'images/terminal/keyboard/btn_i.png', x=x + 423, y=y + 26, w=52, h=46, frames=3, z=86, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_o', 'img', 'images/terminal/keyboard/btn_o.png', x=x + 471, y=y + 26, w=50, h=46, frames=3, z=87, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_p', 'img', 'images/terminal/keyboard/btn_p.png', x=x + 514, y=y + 26, w=58, h=46, frames=3, z=88, delay=50, process=btn_anim_process, click=true};
 
    -- DS {'btn_left_bracket', 'img', 'images/terminal/keyboard/btn_left_bracket.png', x=x + 562, y=y + 26, w=60, h=46, frames=3, z=89, delay=50, process=btn_anim_process, click=true};
 
    -- DS {'btn_right_bracket', 'img', 'images/terminal/keyboard/btn_right_bracket.png', x=x + 610, y=y + 26, w=62, h=46, frames=3, z=90, delay=50, process=btn_anim_process, click=true};
 
    -- DS {'btn_equal', 'img', 'images/terminal/keyboard/btn_equal.png', x=x + 656, y=y + 26, w=65, h=46, frames=3, z=91, delay=50, process=btn_anim_process, click=true};
 
    
 
    -- Keyboard row 3
 
    DS {'btn_a', 'img', 'images/terminal/keyboard/btn_a.png', x=x + 81, y=y + 52, w=69, h=55, frames=3, z=80, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_s', 'img', 'images/terminal/keyboard/btn_s.png', x=x + 135, y=y + 52, w=67, h=55, frames=3, z=79, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_d', 'img', 'images/terminal/keyboard/btn_d.png', x=x + 191, y=y + 52, w=61, h=55, frames=3, z=78, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_f', 'img', 'images/terminal/keyboard/btn_f.png', x=x + 244, y=y + 52, w=58, h=55, frames=3, z=77, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_g', 'img', 'images/terminal/keyboard/btn_g.png', x=x + 296, y=y + 52, w=53, h=55, frames=3, z=76, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_h', 'img', 'images/terminal/keyboard/btn_h.png', x=x + 346, y=y + 52, w=55, h=55, frames=3, z=75, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_j', 'img', 'images/terminal/keyboard/btn_j.png', x=x + 401, y=y + 52, w=56, h=55, frames=3, z=76, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_k', 'img', 'images/terminal/keyboard/btn_k.png', x=x + 452, y=y + 52, w=55, h=55, frames=3, z=77, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_l', 'img', 'images/terminal/keyboard/btn_l.png', x=x + 500, y=y + 52, w=60, h=55, frames=3, z=78, delay=50, process=btn_anim_process, click=true};
 
    -- DS {'btn_semicolon', 'img', 'images/terminal/keyboard/btn_semicolon.png', x=x + 549, y=y + 52, w=65, h=55, frames=3, z=79, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_enter', 'img', 'images/terminal/keyboard/btn_enter.png', x=x + 599, y=y + 52, w=124, h=55, frames=3, z=80, delay=50, process=btn_anim_process, click=true};
 

	
 
    -- Keyboard row 4
 
    DS {'btn_z', 'img', 'images/terminal/keyboard/btn_z.png', x=x + 89, y=y + 86, w=74, h=59, frames=3, z=70, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_x', 'img', 'images/terminal/keyboard/btn_x.png', x=x + 147, y=y + 86, w=70, h=59, frames=3, z=69, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_c', 'img', 'images/terminal/keyboard/btn_c.png', x=x + 205, y=y + 86, w=64, h=59, frames=3, z=68, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_v', 'img', 'images/terminal/keyboard/btn_v.png', x=x + 261, y=y + 86, w=61, h=59, frames=3, z=67, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_b', 'img', 'images/terminal/keyboard/btn_b.png', x=x + 318, y=y + 86, w=53, h=59, frames=3, z=66, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_n', 'img', 'images/terminal/keyboard/btn_n.png', x=x + 372, y=y + 86, w=60, h=59, frames=3, z=66, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_m', 'img', 'images/terminal/keyboard/btn_m.png', x=x + 429, y=y + 86, w=61, h=59, frames=3, z=67, delay=50, process=btn_anim_process, click=true};
 
    -- DS {'btn_comma', 'img', 'images/terminal/keyboard/btn_comma.png', x=x + 483, y=y + 86, w=62, h=59, frames=3, z=68, delay=50, process=btn_anim_process, click=true};
 
    -- DS {'btn_slash', 'img', 'images/terminal/keyboard/btn_slash.png', x=x + 534, y=y + 86, w=69, h=59, frames=3, z=69, delay=50, process=btn_anim_process, click=true};
 
    -- DS {'btn_backslash', 'img', 'images/terminal/keyboard/btn_backslash.png', x=x + 589, y=y + 86, w=74, h=59, frames=3, z=70, delay=50, process=btn_anim_process, click=true};
 
    DS {'btn_quote', 'img', 'images/terminal/keyboard/btn_quote.png', x=x + 643, y=y + 86, w=78, h=59, frames=3, z=71, delay=50, process=btn_anim_process, click=true};
 

	
 
    local shift_frame = 0;
 
    if keys:state('shift') then
 
      shift_frame = 2;
 
    end;
 

	
 
    DS {'btn_shift', 'img', 'images/terminal/keyboard/btn_shift.png', x=x + 94, y=y + 125, w=139, h=64, frames=3, z=60, delay=50, process=shift_anim_process, click=true, frame_nr=shift_frame};
 
    DS {'btn_space', 'img', 'images/terminal/keyboard/btn_space.png', x=x + 222, y=y + 125, w=494, h=64, frames=3, z=59, delay=50, process=btn_anim_process, click=true};
 

	
 
    DS {'panel_1', 'img', 'images/terminal/keyboard/panel_1.png', x=x + 62, y=y + 37, w=677, h=16, z=92};
 
    DS {'panel_2', 'img', 'images/terminal/keyboard/panel_2.png', x=x + 77, y=y + 62, w=648, h=12,  z=81};
 
    DS {'panel_3', 'img', 'images/terminal/keyboard/panel_3.png', x=x + 78, y=y + 94, w=652, h=20, z=72};
 
    DS {'panel_4', 'img', 'images/terminal/keyboard/panel_4.png', x=x + 78, y=y + 131, w=652, h=23, z=61};
 
    DS {'panel_5', 'img', 'images/terminal/keyboard/panel_5.png', x=x, y=y + 181, w=800, h=10, z=51};
 

	
 
    if keys:state('shift') then
 
      DS {'btn_backquote', 'img', 'images/terminal/keyboard/btn_tilde.png', x=x + 67, y=y, w=64, h=46, frames=3, z=100, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_minus', 'img', 'images/terminal/keyboard/btn_underscore.png', x=x + 574, y=y, w=58, h=46, frames=3, z=100, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_left_bracket', 'img', 'images/terminal/keyboard/btn_left_curly.png', x=x + 562, y=y + 26, w=60, h=46, frames=3, z=89, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_right_bracket', 'img', 'images/terminal/keyboard/btn_right_curly.png', x=x + 610, y=y + 26, w=62, h=46, frames=3, z=90, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_equal', 'img', 'images/terminal/keyboard/btn_plus.png', x=x + 656, y=y + 26, w=65, h=46, frames=3, z=91, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_semicolon', 'img', 'images/terminal/keyboard/btn_colon.png', x=x + 549, y=y + 52, w=65, h=55, frames=3, z=79, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_comma', 'img', 'images/terminal/keyboard/btn_dot.png', x=x + 483, y=y + 86, w=62, h=59, frames=3, z=68, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_slash', 'img', 'images/terminal/keyboard/btn_question.png', x=x + 534, y=y + 86, w=69, h=59, frames=3, z=69, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_backslash', 'img', 'images/terminal/keyboard/btn_vertical.png', x=x + 589, y=y + 86, w=74, h=59, frames=3, z=70, delay=50, process=btn_anim_process, click=true};
 
    else
 
      DS {'btn_backquote', 'img', 'images/terminal/keyboard/btn_backquote.png', x=x + 67, y=y, w=64, h=46, frames=3, z=100, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_minus', 'img', 'images/terminal/keyboard/btn_minus.png', x=x + 574, y=y, w=58, h=46, frames=3, z=100, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_left_bracket', 'img', 'images/terminal/keyboard/btn_left_bracket.png', x=x + 562, y=y + 26, w=60, h=46, frames=3, z=89, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_right_bracket', 'img', 'images/terminal/keyboard/btn_right_bracket.png', x=x + 610, y=y + 26, w=62, h=46, frames=3, z=90, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_equal', 'img', 'images/terminal/keyboard/btn_equal.png', x=x + 656, y=y + 26, w=65, h=46, frames=3, z=91, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_semicolon', 'img', 'images/terminal/keyboard/btn_semicolon.png', x=x + 549, y=y + 52, w=65, h=55, frames=3, z=79, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_comma', 'img', 'images/terminal/keyboard/btn_comma.png', x=x + 483, y=y + 86, w=62, h=59, frames=3, z=68, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_slash', 'img', 'images/terminal/keyboard/btn_slash.png', x=x + 534, y=y + 86, w=69, h=59, frames=3, z=69, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_backslash', 'img', 'images/terminal/keyboard/btn_backslash.png', x=x + 589, y=y + 86, w=74, h=59, frames=3, z=70, delay=50, process=btn_anim_process, click=true};
 
    end;
 
  end;
 
  onexit = function(s)
 
    D {'keyboard_bg'};
 
    -- Keyboard row 1
 
    D {'btn_backquote'};
 
    D {'btn_1'};
 
    D {'btn_2'};
 
    D {'btn_3'};
 
    D {'btn_4'};
 
    D {'btn_5'};
 
    D {'btn_6'};
 
    D {'btn_7'};
 
    D {'btn_8'};
 
    D {'btn_9'};
 
    D {'btn_0'};
 
    D {'btn_minus'};
 
    D {'btn_backspace'};
 

	
 
    -- Keyboard row 2
 
    D {'btn_q'};
 
    D {'btn_w'};
 
    D {'btn_e'};
 
    D {'btn_r'};
 
    D {'btn_t'};
 
    D {'btn_y'};
 
    D {'btn_u'};
 
    D {'btn_i'};
 
    D {'btn_o'};
 
    D {'btn_p'};
 
    D {'btn_left_bracket'};
 
    D {'btn_right_bracket'};
 
    D {'btn_equal'};
 

	
 
    D {'btn_a'};
 
    D {'btn_s'};
 
    D {'btn_d'};
 
    D {'btn_f'};
 
    D {'btn_g'};
 
    D {'btn_h'};
 
    D {'btn_j'};
 
    D {'btn_k'};
 
    D {'btn_l'};
 
    D {'btn_semicolon'};
 
    D {'btn_enter'};
 

	
 
    D {'btn_z'};
 
    D {'btn_x'};
 
    D {'btn_c'};
 
    D {'btn_v'};
 
    D {'btn_b'};
 
    D {'btn_n'};
 
    D {'btn_m'};
 
    D {'btn_comma'};
 
    D {'btn_slash'};
 
    D {'btn_backslash'};
 
    D {'btn_quote'};
 

	
 
    D {'btn_shift'};
 
    D {'btn_space'};
 

	
 
    D {'panel_1'};
 
    D {'panel_2'};
 
    D {'panel_3'};
 
    D {'panel_4'};
 
    D {'panel_5'};
 
    D {'terminal_screen'};
 
  end;
 
  shift_buttons = function(s)
 
    local width, height = diretheme.get_scaled_screen();
 
    
 
    local x = math.floor((width - 800) / 2);
 
    local y = height - 191;
 
    if height < 540 then
 
      y = y + 20;
 
    end;
 

	
 
    if keys:state('shift') then
 
      DS {'btn_backquote', 'img', 'images/terminal/keyboard/btn_tilde.png', x=x + 67, y=y, w=64, h=46, frames=3, z=100, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_minus', 'img', 'images/terminal/keyboard/btn_underscore.png', x=x + 574, y=y, w=58, h=46, frames=3, z=100, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_left_bracket', 'img', 'images/terminal/keyboard/btn_left_curly.png', x=x + 562, y=y + 26, w=60, h=46, frames=3, z=89, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_right_bracket', 'img', 'images/terminal/keyboard/btn_right_curly.png', x=x + 610, y=y + 26, w=62, h=46, frames=3, z=90, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_equal', 'img', 'images/terminal/keyboard/btn_plus.png', x=x + 656, y=y + 26, w=65, h=46, frames=3, z=91, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_semicolon', 'img', 'images/terminal/keyboard/btn_colon.png', x=x + 549, y=y + 52, w=65, h=55, frames=3, z=79, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_comma', 'img', 'images/terminal/keyboard/btn_dot.png', x=x + 483, y=y + 86, w=62, h=59, frames=3, z=68, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_slash', 'img', 'images/terminal/keyboard/btn_question.png', x=x + 534, y=y + 86, w=69, h=59, frames=3, z=69, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_backslash', 'img', 'images/terminal/keyboard/btn_vertical.png', x=x + 589, y=y + 86, w=74, h=59, frames=3, z=70, delay=50, process=btn_anim_process, click=true};
 
    else
 
      DS {'btn_backquote', 'img', 'images/terminal/keyboard/btn_backquote.png', x=x + 67, y=y, w=64, h=46, frames=3, z=100, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_minus', 'img', 'images/terminal/keyboard/btn_minus.png', x=x + 574, y=y, w=58, h=46, frames=3, z=100, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_left_bracket', 'img', 'images/terminal/keyboard/btn_left_bracket.png', x=x + 562, y=y + 26, w=60, h=46, frames=3, z=89, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_right_bracket', 'img', 'images/terminal/keyboard/btn_right_bracket.png', x=x + 610, y=y + 26, w=62, h=46, frames=3, z=90, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_equal', 'img', 'images/terminal/keyboard/btn_equal.png', x=x + 656, y=y + 26, w=65, h=46, frames=3, z=91, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_semicolon', 'img', 'images/terminal/keyboard/btn_semicolon.png', x=x + 549, y=y + 52, w=65, h=55, frames=3, z=79, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_comma', 'img', 'images/terminal/keyboard/btn_comma.png', x=x + 483, y=y + 86, w=62, h=59, frames=3, z=68, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_slash', 'img', 'images/terminal/keyboard/btn_slash.png', x=x + 534, y=y + 86, w=69, h=59, frames=3, z=69, delay=50, process=btn_anim_process, click=true};
 
      DS {'btn_backslash', 'img', 'images/terminal/keyboard/btn_backslash.png', x=x + 589, y=y + 86, w=74, h=59, frames=3, z=70, delay=50, process=btn_anim_process, click=true};
 
    end;
 
  end;
 
  ondecor = function(s, name, press, x, y, btn) 
 
    if not press then
 
      if name == 'btn_shift' then
 
        if keys:state('shift') then
 
          keys:event(false, 'shift');
 
          D(name).frame_nr = 0;
 
          decor.dirty = true;
 
        else
 
          keys:event(true, 'shift');
 
          D(name).animated = 1;
 
          sounds[key_sounds[rnd(#key_sounds)]]:play();
 
        end;
 
        s:shift_buttons();
 
        return false;
 
      end;
 

	
 
      s:handledecor(true, mapping_decor_key[name]);
 
      return;
 
    end;
 

	
 
    return false;
 
  end;
 
  themeDispose = terminal_untheme;
 
  onkey = function(s, press, key)
 
    if not press and not release_handled_keys[key] then
 
      s._keyts = 0;
 
      return false;
 
    end;
 

	
 
    local ticks = instead.ticks();
 
    
 
    if s._key == key and ticks - s._keyts < 100 and s._keypress == press or key == 'return' and keys:state('alt') then
 
      return false;
 
    end;
 

	
 
    s._key = key;
 
    s._keyts = ticks;
 
    s._keypress = press;
 
    
 
    if key == 'left shift' then
 
      if press then
 
        if D('btn_shift').frame_nr ~= 2 then
 
          D('btn_shift').frame_nr = 2;
 
          sounds[key_sounds[rnd(#key_sounds)]]:play();
 
        end;
 
      else
 
        D('btn_shift').frame_nr = 0;
 
        D('btn_shift').animated = false;
 
      end;
 
      decor.dirty = true;
 
      s:shift_buttons();
 
      return;
 
    end;
 
    
 
    if not prefs.text_input or key == 'backspace' or key == 'left' or key == 'space' or key == 'return' then
 
      if keys:state('shift') and keymapping[key] then
 
        key = keymapping[key];
 
      end;
 
      
 
      s:oninput(key);
 
    end;
 
  end;
 
  handledecor = function(s, press, key)
 
    if key == 'left shift' then
 
      if press then
 
        if D('btn_shift').frame_nr ~= 2 then
 
          D('btn_shift').frame_nr = 2;
 
          sounds[key_sounds[rnd(#key_sounds)]]:play();
 
        end;
 
      else
 
        D('btn_shift').frame_nr = 0;
 
        D('btn_shift').animated = false;
 
      end;
 
      decor.dirty = true;
 
      s:shift_buttons();
 
      return;
 
    end;
 
    
 
    if keys:state('shift') and keymapping[key] then
 
      key = keymapping[key];
 
    end;
 
    
 
    s:oninput(key);
 
  end;
 
  ontext = function(s, char)
 
    if prefs.text_input then
 
      if (keymapping[char] or reverse_keymapping[char]) then
 
        s:oninput(char);
 
      elseif char ~= ' ' then
 
        sounds['error_beep']:play();
 
      end;
 
    end;
 
  end;
 
  oninput = function(s, key)
 
    sounds[key_sounds[rnd(#key_sounds)]]:play();
 
    
 
    local name = back_mapping_decor_key[key];
 
    if not name then
 
      local revkey = key;
 
      if reverse_keymapping[key] then
 
        revkey = reverse_keymapping[key];
 
      elseif keymapping[key] then
 
        revkey = keymapping[key];
 
      end;
 
      
 
      name = back_mapping_decor_key[revkey];
 
    end;
 
    
 
    if name then
 
      D(name).animated = 1;
 
      D(name).__delay = instead.ticks() - D(name).delay;
 
    end;
 
  
 
    if key == 'backspace' or key == 'left' then
 
      s.entry = s.entry:sub(1, #s.entry - 1);
 
    elseif key == 'right' or key == 'up' or key == 'down' then
 
    elseif key == 'space' then
 
      if #s.entry + #s.path + 3 > 63 then
 
        sounds['error_beep']:play();
 
        return;
 
      end;
 
      s.entry = s.entry .. ' ';
 
    elseif key == 'return' then
 
      local r = false;
 
      
 
      if s.command_preprocessor then
 
        r = s:command_preprocessor(s.entry);
 
      end;
 
      
 
      if not r then
 
        r = s:process_command(s.entry)
 
        if s:call_command(r[1], r[2]) then
 
          return;
 
        end;
 
        s.entry = '';
 
      end;
 
    else
 
      if #s.entry + #s.path + 3 > 63 then
 
        sounds['error_beep']:play();
 
        return;
 
      end;
 
    
 
      s.entry = s.entry .. key;
 
    end;
 
    if here() ^ s then
 
      local d = getscreen(false);
 
      if s.query_formatter then
 
        d:replace_line(s:query_formatter(s.path, s.entry));
 
      else
 
        d:replace_line(s.path .. '>' .. s.entry .. '_');
 
      end;
 
    end;
 
  end;
 
}
terminal/tiny.lua
Show inline comments
 
new file 100644
 
include "terminal/base"
 

	
 
room {
 
  nam = 'terminal_boot';
 
  disp = '';
 
  nosave = true;
 
  noautosave = true;
 
  nofollow = true;
 
  noinv = true;
 
  nofading = true;
 
  network = false;
 
  graphical = false;
 
  theme = 'terminal';
 
  onenter = function(s)
 
    if not s.network then
 
      pn(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'no_device'));
 
      return false;
 
    else
 
      walk('terminal');
 
    end;
 
  end;
 
  themeInit = function(s)
 
    load_sounds('error_beep', 'pc_startup', 'keyboard1', 'keyboard2', 'keyboard3', 'keyboard4', 'keyboard5');
 
  end;
 
};
 

	
 
local iface_cmd=iface.cmd
 
function iface:cmd(inp,s)
 
  local a=std.split(inp)
 
  if a[1] == '@metaparser' and here().onmp then
 
    inp=inp:sub(#a[1]+2);
 
    inp=inp:sub(2,#inp-1);
 
    return here():onmp(inp);
 
  end;
 
  return iface_cmd(self, inp);
 
end;
 

	
 
terminal {
 
  {
 
    msg = '';
 
  };
 
  nam = 'terminal';
 
  timer = function(s)
 
    if s.status == 'wait_format' then
 
      if s.format_percent < 100 then
 
        s.format_percent = s.format_percent + 1;
 
      else
 
        s.status = 'format_done';
 
        
 
      end;
 
    elseif s.status == 'format_done' then
 
      --[[if s.format_percent < 120 then
 
        p(translate_now("terminal_locale", 'critical_failure'));
 
      end;]]
 
      
 
      s.format_percent = s.format_percent + 1;
 
      if s.format_percent > 150 then
 
        timer:stop();
 
        walk('terminal_boot_failure');
 
        return;
 
      end;
 
    end;
 
  end;
 
  decor = function(s)
 
    if s.status == 'command' then
 
      return s.msg .. '^' .. s.path .. '>';
 
    elseif s.status == 'crypt' or s.status == 'connect' then
 
      return s.msg .. '^' .. translate_now("terminal_locale", 'query_password');
 
    elseif s.status == 'format' then
 
      return s.msg .. '^' .. translate_now("terminal_locale", 'query_type_yes');
 
    elseif s.status == 'wait_format' then
 
      return s.msg .. '^' .. translate_now("terminal_locale", 'query_formatting') .. " " .. tostring(s.format_percent) .. '%';
 
    elseif s.status == 'format_done' then
 
      return s.msg .. '^' .. translate_now("terminal_locale", 'formatting_complete');
 
    end;
 
    return s.msg;
 
  end;
 
  push_line = function(s, line)
 
    s.msg = s.msg .. '^' .. line;
 
  end;
 
  makekeyboard = function(s)
 
  end;
 
  onmp = function(s, text)
 
    s.msg = '';
 
    local r = false;
 
      
 
    if s.command_preprocessor then
 
      r = s:command_preprocessor(text);
 
    end;
 
    
 
    if not here()^'terminal' then
 
        return iface_cmd(iface, "look");
 
      end;
 
    
 
    if not r then
 
      r = s:process_command(text)
 
      if s:call_command(r[1], r[2]) then
 
        if not here()^'terminal' then
 
          return iface_cmd(iface, "look");
 
        end;
 
        return;
 
      end;
 
    end;
 
    
 
    return s:decor();
 
  end;
 
  onenter = function(s)
 
    s.msg = '';
 
  end;
 
  way = {
 
    path {'#fail', translate("common_locale", 'continue'), 'terminal_boot_failure'}: disable();
 
  };
 
}
 

	
 
room {
 
  nam = 'terminal_boot_failure';
 
  theme = 'terminal';
 
  nofollow = true;
 
  noinv = true;
 
  disp = '';
 
  decor = function(s)
 
    pn(translate_now("terminal_locale", 'formatting_complete'));
 
    pn(translate_now("terminal_locale", 'critical_failure'));
 
  end;
 
  way = {
 
    path {translate("common_locale", 'continue'), 'ending_formatted'};
 
  };
 
}
 
\ No newline at end of file
tiny_menu.lua
Show inline comments
 
new file 100644
 
function stop_menu()
 
end;
 

	
 
room {
 
  nam = 'tiny_load';
 
  onenter = function(s)
 
    walk('main');
 
    instead.menu('load');
 
  end;
 
}
 

	
 
room {
 
  nam = 'tiny_quit';
 
  onenter = function(s)
 
    walk('main');
 
    instead.menu('exit');
 
    return false;
 
  end;
 
}
 

	
 
room {
 
  nam = 'tiny_start';
 
  onenter = function(s)
 
    walk('above_forest');
 
    in_game = true;
 
    return false;
 
  end;
 
}
 

	
 
room {
 
  nam = 'tiny_tutorial';
 
  onenter = function(s)
 
    walk('tutorial_start');
 
    in_game = true;
 
  end;
 
}
 

	
 
room {
 
  nam = 'main';
 
  notitle = true;
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
  nofading = true;
 
  disp = '';
 
  theme = 'menu';
 
  decor = 'A Dragon and the Tower';
 
  onenter = function(s)
 
    in_game = false;
 
  end;
 
  themeDispose = function(s)
 
    timer:stop();
 
  end;
 
  enter = function(s)
 
    if prefs.completed then
 
      snd.music('sound/bgm_credits.ogg');
 
    else
 
      snd.music('sound/bgm_intro.ogg');
 
    end;
 
  end;
 
  way = {
 
    path{'Start', 'intro_start'};
 
    --path{'Load', 'tiny_load'};
 
    path{'About', 'intro_info'};
 
    path{'Settings', 'intro_settings'};
 
    --path{'Quit', 'tiny_quit'};
 
  }
 
}
 

	
 
room {
 
  nam = 'intro_start';
 
  notitle = true;
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
  nofading = true;
 
  disp = '';
 
  theme = 'menu';
 
  themeDispose = function(s)
 
    timer:stop();
 
  end;
 
  ondecor = function(s, name, press, x, y, btn)
 
    if press then
 
      if name == 'start' then
 
        walk('above_forest');
 
        in_game = true;
 
        return true;
 
      elseif name == 'tutorial' then
 
        walk('tutorial_start');
 
        in_game = true;
 
        return true;
 
      elseif name == 'back' then
 
        walk('main');
 
        return true;
 
      end;
 
    end;
 
    return false;
 
  end;
 
  decor = translate("menu_locale", 'intro');
 
  way = {
 
    path {'Start', 'tiny_start'};
 
    path {'Tutorial', 'tiny_tutorial'};
 
    path {'Back', 'main'};
 
  }
 
}
 

	
 
room {
 
  nam = 'intro_info';
 
  notitle = true;
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
  nofading = true;
 
  disp = '';
 
  theme = 'menu';
 
  themeDispose = function(s)
 
    timer:stop();
 
  end;
 
  decor = function(s)
 
    return credits_text(false);
 
  end;
 
  way = {
 
    path {'Back', 'main'};
 
  }
 
}
 

	
 
room {
 
  nam = 'tiny_from_settings';
 
  onenter = function(s)
 
    if in_game then
 
      walkback();
 
    else
 
      walk('main');
 
    end;
 
    return false;
 
  end;
 
}
 

	
 
room {
 
  nam = 'intro_settings';
 
  nofollow = true;
 
  notitle = true;
 
  nosave = true;
 
  noautosave = true;
 
  noinv = true;
 
  nofading = true;
 
  disp = '';
 
  theme = 'menu';
 
  themeDispose = function(s)
 
    timer:stop();
 
  end;
 
  way = {
 
    path {'Back', 'tiny_from_settings'};
 
  };
 
}:with {
 
  obj {
 
    nam = '#language';
 
    dsc = function(s)
 
      local l = translate_now("menu_locale", 'auto_option');
 

	
 
      pn(fmt.c(fmt.b(translate_now("menu_locale", 'language'))));
 
      
 
      local t;
 
      if get_language_saved() == '' then
 
        t = l .. ' (Selected)';
 
      else
 
        t = '{#l_auto|'.. l .. '}';
 
      end;
 
      
 
      for i, language in ipairs(get_language_list()) do
 
        if get_language_saved() == language[1] then
 
          t = t .. ' | ' .. language[2] .. ' (Selected)';
 
        else
 
          t = t .. ' | ' .. '{@set_language ' .. language[1] .. '|' .. language[2] .. '}';
 
        end;
 
      end;
 
    
 
      pn(fmt.c(t) .. '^')
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#l_auto';
 
      act = function(s)
 
        set_language('');
 
        walk(here());
 
      end;
 
    };
 
  };
 
}
 

	
 
menu {
 
  nam = 'tiny_ingame_settings';
 
  disp = 'Settings';
 
  inv = function(s)
 
    walk('intro_settings');
 
  end;
 
}
 

	
 
function get_sprite(path, transparent)
 
  return nil;
 
end;
tower.lua
Show inline comments
 
include "terminal"
 
include "terminal/common.lua"
 

	
 
obj {
 
	nam = 'tower_key_0';
 
	value = 1;
 
  nam = 'tower_key_0';
 
  value = 1;
 
  color = 'red';
 
	disp = translate("tower_locale", 'tower_red_key_disp');
 
	disp2 = translate("tower_locale", 'tower_red_key_disp2');
 
	disp3 = translate("tower_locale", 'tower_red_key_disp3');
 
	inv = translate("tower_locale", 'tower_red_key_inv');
 
  disp = translate("tower_locale", 'tower_red_key_disp');
 
  disp2 = translate("tower_locale", 'tower_red_key_disp2');
 
  disp3 = translate("tower_locale", 'tower_red_key_disp3');
 
  inv = translate("tower_locale", 'tower_red_key_inv');
 
}
 

	
 
obj {
 
	nam = 'tower_key_1';
 
	value = 2;
 
  nam = 'tower_key_1';
 
  value = 2;
 
  color = 'gold';
 
	disp = translate("tower_locale", 'tower_gold_key_disp');
 
	disp2 = translate("tower_locale", 'tower_gold_key_disp2');
 
	disp3 = translate("tower_locale", 'tower_gold_key_disp3');
 
	inv = translate("tower_locale", 'tower_gold_key_inv');
 
  disp = translate("tower_locale", 'tower_gold_key_disp');
 
  disp2 = translate("tower_locale", 'tower_gold_key_disp2');
 
  disp3 = translate("tower_locale", 'tower_gold_key_disp3');
 
  inv = translate("tower_locale", 'tower_gold_key_inv');
 
}
 

	
 
obj {
 
	nam = 'tower_key_2';
 
	value = 3;
 
  nam = 'tower_key_2';
 
  value = 3;
 
  color = 'blue';
 
	disp = translate("tower_locale", 'tower_blue_key_disp');
 
	disp2 = translate("tower_locale", 'tower_blue_key_disp2');
 
	disp3 = translate("tower_locale", 'tower_blue_key_disp3');
 
	inv = translate("tower_locale", 'tower_blue_key_inv');
 
  disp = translate("tower_locale", 'tower_blue_key_disp');
 
  disp2 = translate("tower_locale", 'tower_blue_key_disp2');
 
  disp3 = translate("tower_locale", 'tower_blue_key_disp3');
 
  inv = translate("tower_locale", 'tower_blue_key_inv');
 
}
 

	
 
obj {
 
	nam = 'tower_key_3';
 
	value = 4;
 
  nam = 'tower_key_3';
 
  value = 4;
 
  color = 'green';
 
	disp = translate("tower_locale", 'tower_green_key_disp');
 
	disp2 = translate("tower_locale", 'tower_green_key_disp2');
 
	disp3 = translate("tower_locale", 'tower_green_key_disp3');
 
	inv = translate("tower_locale", 'tower_green_key_inv');
 
  disp = translate("tower_locale", 'tower_green_key_disp');
 
  disp2 = translate("tower_locale", 'tower_green_key_disp2');
 
  disp3 = translate("tower_locale", 'tower_green_key_disp3');
 
  inv = translate("tower_locale", 'tower_green_key_inv');
 
}
 

	
 
obj {
 
	nam = 'tower_level_2_key';
 
	disp = translate("tower_locale", 'tower_level_2_key_disp');
 
	inv = translate("tower_locale", 'tower_level_2_key_dsc');
 
  nam = 'tower_level_2_key';
 
  disp = translate("tower_locale", 'tower_level_2_key_disp');
 
  inv = translate("tower_locale", 'tower_level_2_key_dsc');
 
}
 

	
 
obj {
 
	nam = 'tower_hint_1';
 
	disp = translate("tower_locale", 'tower_hint_1_disp');
 
	inv = function(s)
 
  nam = 'tower_hint_1';
 
  disp = translate("tower_locale", 'tower_hint_1_disp');
 
  inv = function(s)
 
    return translate_now("tower_locale", 'tower_hint_1_inv', {target=level_1_target});
 
  end;
 
}
 
@@ -125,108 +125,108 @@ dlg {
 
};
 

	
 
obj {
 
	nam = 'flask';
 
	disp = translate("tower_locale", 'flask_disp');
 
	disp2 = translate("tower_locale", 'flask_disp2');
 
	disp3 = translate("tower_locale", 'flask_disp3');
 
	inv = translate("tower_locale", 'flask_inv');
 
  nam = 'flask';
 
  disp = translate("tower_locale", 'flask_disp');
 
  disp2 = translate("tower_locale", 'flask_disp2');
 
  disp3 = translate("tower_locale", 'flask_disp3');
 
  inv = translate("tower_locale", 'flask_inv');
 
}
 

	
 
obj {
 
	nam = 'potion_open';
 
	disp = translate("tower_locale", 'potion_open_disp');
 
	disp2 = translate("tower_locale", 'potion_open_disp2');
 
	disp3 = translate("tower_locale", 'potion_open_disp3');
 
	inv = translate("tower_locale", 'potion_open_inv');
 
  nam = 'potion_open';
 
  disp = translate("tower_locale", 'potion_open_disp');
 
  disp2 = translate("tower_locale", 'potion_open_disp2');
 
  disp3 = translate("tower_locale", 'potion_open_disp3');
 
  inv = translate("tower_locale", 'potion_open_inv');
 
}
 

	
 
obj {
 
	nam = 'potion_light';
 
	disp = translate("tower_locale", 'potion_light_disp');
 
	disp2 = translate("tower_locale", 'potion_light_disp2');
 
	disp3 = translate("tower_locale", 'potion_light_disp3');
 
	inv = function(s)
 
		if here()^'tower_level_3_room_2' then
 
			remove('potion_light', pl);
 
			here().light = true;
 
			_'#door':enable();
 
			_'#shelves':enable();
 
			_'level_3_room_2_down':enable()
 
			_'#darkness':disable();
 
			return translate_now("tower_locale", 'potion_light_inv_used');
 
		else
 
			return translate_now("tower_locale", 'potion_light_inv');
 
		end;
 
	end;
 
  nam = 'potion_light';
 
  disp = translate("tower_locale", 'potion_light_disp');
 
  disp2 = translate("tower_locale", 'potion_light_disp2');
 
  disp3 = translate("tower_locale", 'potion_light_disp3');
 
  inv = function(s)
 
    if here()^'tower_level_3_room_2' then
 
      remove('potion_light', pl);
 
      here().light = true;
 
      _'#door':enable();
 
      _'#shelves':enable();
 
      _'level_3_room_2_down':enable()
 
      _'#darkness':disable();
 
      return translate_now("tower_locale", 'potion_light_inv_used');
 
    else
 
      return translate_now("tower_locale", 'potion_light_inv');
 
    end;
 
  end;
 
}
 

	
 
obj {
 
	nam = 'candle';
 
	disp = translate("tower_locale", 'candle_disp');
 
	disp2 = translate("tower_locale", 'candle_disp2');
 
	disp3 = translate("tower_locale", 'candle_disp3');
 
	inv = translate("tower_locale", 'candle_inv');
 
  nam = 'candle';
 
  disp = translate("tower_locale", 'candle_disp');
 
  disp2 = translate("tower_locale", 'candle_disp2');
 
  disp3 = translate("tower_locale", 'candle_disp3');
 
  inv = translate("tower_locale", 'candle_inv');
 
}
 

	
 
obj {
 
	nam = 'potion_enrichment';
 
	disp = translate("tower_locale", 'potion_enrichment_disp');
 
	disp2 = translate("tower_locale", 'potion_enrichment_disp2');
 
	disp3 = translate("tower_locale", 'potion_enrichment_disp3');
 
	inv = translate("tower_locale", 'potion_enrichment_inv');
 
  nam = 'potion_enrichment';
 
  disp = translate("tower_locale", 'potion_enrichment_disp');
 
  disp2 = translate("tower_locale", 'potion_enrichment_disp2');
 
  disp3 = translate("tower_locale", 'potion_enrichment_disp3');
 
  inv = translate("tower_locale", 'potion_enrichment_inv');
 
}
 

	
 
obj {
 
	nam = 'emerald';
 
	disp = translate("tower_locale", 'emerald_disp');
 
	disp2 = translate("tower_locale", 'emerald_disp2');
 
	disp3 = translate("tower_locale", 'emerald_disp3');
 
	inv = translate("tower_locale", 'emerald_inv');
 
  nam = 'emerald';
 
  disp = translate("tower_locale", 'emerald_disp');
 
  disp2 = translate("tower_locale", 'emerald_disp2');
 
  disp3 = translate("tower_locale", 'emerald_disp3');
 
  inv = translate("tower_locale", 'emerald_inv');
 
}
 

	
 
obj {
 
	nam = 'password_note';
 
	disp = translate("tower_locale", 'password_note_disp');
 
	disp2 = translate("tower_locale", 'password_note_disp2');
 
	disp3 = translate("tower_locale", 'password_note_disp3');
 
	inv = function(s)
 
  nam = 'password_note';
 
  disp = translate("tower_locale", 'password_note_disp');
 
  disp2 = translate("tower_locale", 'password_note_disp2');
 
  disp3 = translate("tower_locale", 'password_note_disp3');
 
  inv = function(s)
 
    return translate_now("tower_locale", 'password_note_inv', {password=password1});
 
  end;
 
}
 

	
 
obj {
 
	nam = 'tool_box';
 
	dsc = translate("tower_locale", 'tool_box_dsc');
 
	disp = translate("tower_locale", 'tool_box_disp');
 
	disp2 = translate("tower_locale", 'tool_box_disp2');
 
	disp3 = translate("tower_locale", 'tool_box_disp3');
 
	inv = translate("tower_locale", 'tool_box_inv');
 
  nam = 'tool_box';
 
  dsc = translate("tower_locale", 'tool_box_dsc');
 
  disp = translate("tower_locale", 'tool_box_disp');
 
  disp2 = translate("tower_locale", 'tool_box_disp2');
 
  disp3 = translate("tower_locale", 'tool_box_disp3');
 
  inv = translate("tower_locale", 'tool_box_inv');
 
};
 

	
 
obj {
 
	state = 0; -- 0 - empty, 1 - cold water, 2 - hot water
 
	nam = 'kettle';
 
	disp = function(s)
 
		if s.state == 0 then
 
			return translate_now("tower_locale", 'kettle_disp');
 
		elseif s.state == 1 then
 
			return translate_now("tower_locale", 'kettle_disp_water');
 
		elseif s.state == 2 then
 
			return translate_now("tower_locale", 'kettle_disp_hot_water');
 
		end;
 
	end;
 
	disp2 = translate("tower_locale", 'kettle_disp2');
 
	disp3 = translate("tower_locale", 'kettle_disp3');
 
	inv = function(s)
 
  state = 0; -- 0 - empty, 1 - cold water, 2 - hot water
 
  nam = 'kettle';
 
  disp = function(s)
 
    if s.state == 0 then
 
      return translate_now("tower_locale", 'kettle_disp');
 
    elseif s.state == 1 then
 
      return translate_now("tower_locale", 'kettle_disp_water');
 
    elseif s.state == 2 then
 
      return translate_now("tower_locale", 'kettle_disp_hot_water');
 
    end;
 
  end;
 
  disp2 = translate("tower_locale", 'kettle_disp2');
 
  disp3 = translate("tower_locale", 'kettle_disp3');
 
  inv = function(s)
 
    p(translate_now("tower_locale", 'kettle_inv'));
 
		if s.state == 0 then
 
			p(translate_now("tower_locale", 'kettle_inv_empty'));
 
		elseif s.state == 1 then
 
			p(translate_now("tower_locale", 'kettle_inv_water'));
 
		elseif s.state == 2 then
 
			 p(translate_now("tower_locale", 'kettle_inv_hot_water'));
 
		end;
 
	end;
 
    if s.state == 0 then
 
      p(translate_now("tower_locale", 'kettle_inv_empty'));
 
    elseif s.state == 1 then
 
      p(translate_now("tower_locale", 'kettle_inv_water'));
 
    elseif s.state == 2 then
 
       p(translate_now("tower_locale", 'kettle_inv_hot_water'));
 
    end;
 
  end;
 
  dsc = translate("tower_locale", 'kettle_dsc');
 
  tak = function(s)
 
    if not _'solarscale_ally'.tea_asked then
 
@@ -322,162 +322,162 @@ obj {
 
};
 

	
 
room {
 
	keys_taken = false;
 
	theme = 'tower';
 
	nam = 'tower_level_1';
 
	pic = 'images/tower_level_1.png';
 
	disp = translate("tower_locale", 'tower_level_1_disp');
 
	decor = translate("tower_locale", 'tower_level_1_decor');
 
	way = {
 
		path {translate("tower_locale", 'transition_leave'), "ending_left"};
 
		path {"level_1_next_room", translate("tower_locale", 'transition_room'), "tower_level_1_room_2"}:disable();
 
		path {"level_1_up", translate("tower_locale", 'transition_upstairs'), "tower_level_2"}:disable();
 
	};
 
	enter = function(s)
 
		snd.music('sound/bgm_tower.ogg');
 
  keys_taken = false;
 
  theme = 'tower';
 
  nam = 'tower_level_1';
 
  pic = 'images/tower_level_1.png';
 
  disp = translate("tower_locale", 'tower_level_1_disp');
 
  decor = translate("tower_locale", 'tower_level_1_decor');
 
  way = {
 
    path {translate("tower_locale", 'transition_leave'), "ending_left"};
 
    path {"level_1_next_room", translate("tower_locale", 'transition_room'), "tower_level_1_room_2"}:disable();
 
    path {"level_1_up", translate("tower_locale", 'transition_upstairs'), "tower_level_2"}:disable();
 
  };
 
  enter = function(s)
 
    snd.music('sound/bgm_tower.ogg');
 
    instead.autosave();
 
	end;
 
  end;
 
  exit = function(s)
 
    _'ending_left'.state = 0;
 
  end;
 
}: with {
 
	'tower_walls',
 
	obj {
 
		nam = '#ceiling';
 
		act = translate("tower_locale", 'tower_level_1_ceiling');
 
	};
 
	obj {
 
		state = 0;
 
		nam = '#tables';
 
		act = function(s)
 
			p(translate_now("tower_locale", 'tower_level_1_tables'));
 
			if s.state == 0 then
 
				s.state = 1;
 
				p(translate_now("tower_locale", 'tower_level_1_tables_box'));
 
				_'tower_box':enable();
 
			end;
 
		end;
 
	};
 
	obj {
 
		state = 0;
 
		nam = '#candelabra';
 
		act = function(s)
 
			p(translate_now("tower_locale", 'tower_level_1_candelabra'));
 
			if s.state == 0 then
 
				s.state = 1;
 
				p(translate_now("tower_locale", 'tower_level_1_candelabra_keys'));
 
				_'#keys':enable();
 
			else
 
				if not candle_taken then
 
					s.state = 2;
 
					take('candle');
 
					candle_taken = true;
 
					p(translate_now("tower_locale", 'tower_candelabra_candle_taken'));
 
				else
 
					if s.state == 2 then
 
						p(translate_now("tower_locale", 'tower_candelabra_candle_missing'));
 
					end;
 
				end;
 
			end;
 
  'tower_walls',
 
  obj {
 
    nam = '#ceiling';
 
    act = translate("tower_locale", 'tower_level_1_ceiling');
 
  };
 
  obj {
 
    state = 0;
 
    nam = '#tables';
 
    act = function(s)
 
      p(translate_now("tower_locale", 'tower_level_1_tables'));
 
      if s.state == 0 then
 
        s.state = 1;
 
        p(translate_now("tower_locale", 'tower_level_1_tables_box'));
 
        _'tower_box':enable();
 
      end;
 
    end;
 
  };
 
  obj {
 
    state = 0;
 
    nam = '#candelabra';
 
    act = function(s)
 
      p(translate_now("tower_locale", 'tower_level_1_candelabra'));
 
      if s.state == 0 then
 
        s.state = 1;
 
        p(translate_now("tower_locale", 'tower_level_1_candelabra_keys'));
 
        _'#keys':enable();
 
      else
 
        if not candle_taken then
 
          s.state = 2;
 
          take('candle');
 
          candle_taken = true;
 
          p(translate_now("tower_locale", 'tower_candelabra_candle_taken'));
 
        else
 
          if s.state == 2 then
 
            p(translate_now("tower_locale", 'tower_candelabra_candle_missing'));
 
          end;
 
        end;
 
      end;
 

	
 
		end;
 
	};
 
	obj {
 
		nam = '#chairs';
 
		act = translate("tower_locale", 'tower_level_1_chairs');
 
	};
 
	obj {
 
		nam = '#keys';
 
		dsc = translate("tower_locale", 'tower_level_1_keys');
 
		act = function(s)
 
			here().keys_taken = true;
 
			take('tower_key_0');
 
			take('tower_key_1');
 
			take('tower_key_2');
 
			take('tower_key_3');
 
			remove('#keys', here());
 
			return translate_now("tower_locale", 'tower_level_1_keys_take');
 
		end;
 
	}:disable();
 
	obj {
 
		nam = 'tower_box';
 
		disp = translate("tower_locale", 'tower_level_1_box_disp');
 
		dsc = translate("tower_locale", 'tower_level_1_box_dsc');
 
		tak = function(s)
 
			take('tower_hint_1');
 
			return translate_now("tower_locale", 'tower_level_1_box_tak');
 
		end;
 
		inv = function(s)
 
			if here()^'inside_box' then
 
				return translate_now("tower_locale", 'tower_level_1_box_inv');
 
			end;
 
			walkin('inside_box');
 
		end;
 
	}:disable();
 
	obj {
 
		state = false;
 
		nam = '#tower_1_door';
 
		dsc = function(s)
 
			if s.state then
 
				return translate_now("tower_locale", 'tower_level_1_door_open');
 
			else
 
				return translate_now("tower_locale", 'tower_level_1_door_closed');
 
			end;
 
		end;
 
		act = function(s)
 
			if s.state then
 
				return translate_now("tower_locale", 'tower_level_1_door_act_open');
 
			else
 
				return translate_now("tower_locale", 'tower_level_1_door_act_closed');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'hidden_key' or o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' then
 
				return translate_now("common_locale", 'key_does_not_fit');
 
			elseif o^'tower_level_2_key' then
 
				remove('tower_level_2_key', pl);
 
				s.state = true;
 
				enable('level_1_up');
 
				return translate_now("tower_locale", 'tower_level_1_door_use_correct_key');
 
			end;
 
    end;
 
  };
 
  obj {
 
    nam = '#chairs';
 
    act = translate("tower_locale", 'tower_level_1_chairs');
 
  };
 
  obj {
 
    nam = '#keys';
 
    dsc = translate("tower_locale", 'tower_level_1_keys');
 
    act = function(s)
 
      here().keys_taken = true;
 
      take('tower_key_0');
 
      take('tower_key_1');
 
      take('tower_key_2');
 
      take('tower_key_3');
 
      remove('#keys', here());
 
      return translate_now("tower_locale", 'tower_level_1_keys_take');
 
    end;
 
  }:disable();
 
  obj {
 
    nam = 'tower_box';
 
    disp = translate("tower_locale", 'tower_level_1_box_disp');
 
    dsc = translate("tower_locale", 'tower_level_1_box_dsc');
 
    tak = function(s)
 
      take('tower_hint_1');
 
      return translate_now("tower_locale", 'tower_level_1_box_tak');
 
    end;
 
    inv = function(s)
 
      if here()^'inside_box' then
 
        return translate_now("tower_locale", 'tower_level_1_box_inv');
 
      end;
 
      walkin('inside_box');
 
    end;
 
  }:disable();
 
  obj {
 
    state = false;
 
    nam = '#tower_1_door';
 
    dsc = function(s)
 
      if s.state then
 
        return translate_now("tower_locale", 'tower_level_1_door_open');
 
      else
 
        return translate_now("tower_locale", 'tower_level_1_door_closed');
 
      end;
 
    end;
 
    act = function(s)
 
      if s.state then
 
        return translate_now("tower_locale", 'tower_level_1_door_act_open');
 
      else
 
        return translate_now("tower_locale", 'tower_level_1_door_act_closed');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'hidden_key' or o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' then
 
        return translate_now("common_locale", 'key_does_not_fit');
 
      elseif o^'tower_level_2_key' then
 
        remove('tower_level_2_key', pl);
 
        s.state = true;
 
        enable('level_1_up');
 
        return translate_now("tower_locale", 'tower_level_1_door_use_correct_key');
 
      end;
 
      
 
      return false;
 
		end;
 
	}:with {
 
		obj {
 
			nam = '#stairwell';
 
			act = translate("tower_locale", 'tower_level_1_stairwell');
 
		}
 
	};
 
	obj {
 
		nam = '#tower_1_kitchen_door';
 
		dsc = translate("tower_locale", 'tower_level_1_kitchen_door');
 
		act = function(s)
 
			if not _'level_1_next_room':disabled() then
 
				return translate_now("tower_locale", 'tower_level_1_kitchen_door_act_open');
 
			else
 
				return translate_now("tower_locale", 'tower_level_1_kitchen_door_act_closed');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'tower_level_2_key' or o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' or o^'hidden_key' then
 
				return translate_now("tower_locale", 'tower_level_1_kitchen_door_used_key');
 
			end;
 
    end;
 
  }:with {
 
    obj {
 
      nam = '#stairwell';
 
      act = translate("tower_locale", 'tower_level_1_stairwell');
 
    }
 
  };
 
  obj {
 
    nam = '#tower_1_kitchen_door';
 
    dsc = translate("tower_locale", 'tower_level_1_kitchen_door');
 
    act = function(s)
 
      if not _'level_1_next_room':disabled() then
 
        return translate_now("tower_locale", 'tower_level_1_kitchen_door_act_open');
 
      else
 
        return translate_now("tower_locale", 'tower_level_1_kitchen_door_act_closed');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'tower_level_2_key' or o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' or o^'hidden_key' then
 
        return translate_now("tower_locale", 'tower_level_1_kitchen_door_used_key');
 
      end;
 

	
 
			if o^'potion_open' then
 
				return translate_now("tower_locale", 'tower_level_1_kitchen_door_used_potion');
 
			end;
 
      if o^'potion_open' then
 
        return translate_now("tower_locale", 'tower_level_1_kitchen_door_used_potion');
 
      end;
 

	
 
			return false;
 
		end;
 
	};
 
      return false;
 
    end;
 
  };
 
}
 

	
 
room {
 
	nam = 'inside_box';
 
	disp = translate("tower_locale", 'tower_level_1_box_disp');
 
  nam = 'inside_box';
 
  disp = translate("tower_locale", 'tower_level_1_box_disp');
 
  theme = 'tower';
 
	nofollow = true;
 
  nofollow = true;
 
  pic = function(s)
 
    local pic = 'images/box/box_bg.png';
 
    local sum = tostring(s:sum());
 
@@ -522,324 +522,327 @@ room {
 
    local sum = 0;
 
    
 
    if _('keyhole_1').key then
 
			sum = sum + _('keyhole_1').value * _('keyhole_1').key.value;
 
		end;
 
      sum = sum + _('keyhole_1').value * _('keyhole_1').key.value;
 
    end;
 

	
 
		if _('keyhole_2').key then
 
			sum = sum + _('keyhole_2').value * _('keyhole_2').key.value;
 
		end;
 
    if _('keyhole_2').key then
 
      sum = sum + _('keyhole_2').value * _('keyhole_2').key.value;
 
    end;
 

	
 
		if _('keyhole_3').key then
 
			sum = sum + _('keyhole_3').value * _('keyhole_3').key.value;
 
		end;
 
    if _('keyhole_3').key then
 
      sum = sum + _('keyhole_3').value * _('keyhole_3').key.value;
 
    end;
 

	
 
		if _('keyhole_4').key then
 
			sum = sum + _('keyhole_4').value * _('keyhole_4').key.value;
 
		end;
 
    if _('keyhole_4').key then
 
      sum = sum + _('keyhole_4').value * _('keyhole_4').key.value;
 
    end;
 
    
 
    return sum;
 
  end;
 
	value = function(s)
 
		local sum = s:sum();
 
  value = function(s)
 
    local sum = s:sum();
 

	
 
		if sum < 10 then
 
			return '00' .. tostring(sum);
 
		elseif sum < 100 then
 
			return '0' .. tostring(sum);
 
		else
 
			return tostring(sum);
 
		end;
 
	end;
 
	test = function(s)
 
		return s:value() == level_1_target;
 
	end;
 
	decor = function(s)
 
		return translate_now("tower_locale", 'inside_box_decor', {
 
    if sum < 10 then
 
      return '00' .. tostring(sum);
 
    elseif sum < 100 then
 
      return '0' .. tostring(sum);
 
    else
 
      return tostring(sum);
 
    end;
 
  end;
 
  test = function(s)
 
    return s:value() == level_1_target;
 
  end;
 
  decor = function(s)
 
    return translate_now("tower_locale", 'inside_box_decor', {
 
        numbers = s:value()
 
    });
 
	end;
 
	way = {
 
		path {translate("common_locale", 'back'), 'tower_level_1'};
 
	};
 
  end;
 
  way = {
 
    path {translate("common_locale", 'back'), 'tower_level_1'};
 
  };
 
}:with {
 
	obj {
 
		nam = 'keyhole_1';
 
		value = 125;
 
		key = false;
 
		dsc = function(s)
 
			if s.key then
 
  obj {
 
    nam = 'keyhole_1';
 
    value = 125;
 
    key = false;
 
    dsc = function(s)
 
      if s.key then
 
        return translate_now("tower_locale", 'inside_box_keyhole_1_key', {
 
            key = s.key.disp2
 
        }) .. '^';
 
			else
 
				return translate_now("tower_locale", 'inside_box_keyhole_1_empty') .. '^';
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' then
 
      else
 
        return translate_now("tower_locale", 'inside_box_keyhole_1_empty') .. '^';
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' then
 
        if s.key then
 
          return translate_now("tower_locale", 'inside_box_keyhole_used_has_key');
 
        end;
 
				s.key = o;
 
				remove(o, pl);
 
        s.key = o;
 
        remove(o, pl);
 

	
 
				pl:need_scene(true);
 
				p(translate_now("tower_locale", 'inside_box_keyhole_used_insert_key', {
 
        pl:need_scene(true);
 
        p(translate_now("tower_locale", 'inside_box_keyhole_used_insert_key', {
 
              key = o.disp3
 
        }));
 

	
 
				if _('inside_box'):test() then
 
					remove('tower_box', pl);
 
					remove('tower_hint_1', pl);
 
					take('tower_level_2_key');
 
        if _('inside_box'):test() then
 
          remove('tower_box', pl);
 
          remove('tower_hint_1', pl);
 
          take('tower_level_2_key');
 
          p(translate_now("tower_locale", 'inside_box_keyhole_used_open'));
 
					walk('tower_level_1');
 
				end;
 
          walk('tower_level_1');
 
        end;
 
      else
 
        return false;
 
			end;
 
		end;
 
		act = function(s)
 
			pl:need_scene(true);
 
			if s.key then
 
				local key = s.key;
 
				take(key);
 
				s.key = false;
 
				return translate_now("tower_locale", 'inside_box_keyhole_act_key', {
 
      end;
 
    end;
 
    act = function(s)
 
      pl:need_scene(true);
 
      if s.key then
 
        local key = s.key;
 
        take(key);
 
        s.key = false;
 
        return translate_now("tower_locale", 'inside_box_keyhole_act_key', {
 
            key = key.disp3
 
        });
 
			else
 
				return translate_now("tower_locale", 'inside_box_keyhole_act_empty');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = 'keyhole_2';
 
		value = 25;
 
		key = false;
 
		dsc = function(s)
 
			if s.key then
 
      else
 
        return translate_now("tower_locale", 'inside_box_keyhole_act_empty');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = 'keyhole_2';
 
    value = 25;
 
    key = false;
 
    dsc = function(s)
 
      if s.key then
 
        return translate_now("tower_locale", 'inside_box_keyhole_2_key', {
 
            key = s.key.disp2
 
        }) .. '^';
 
			else
 
				return translate_now("tower_locale", 'inside_box_keyhole_2_empty') .. '^';
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' then
 
      else
 
        return translate_now("tower_locale", 'inside_box_keyhole_2_empty') .. '^';
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' then
 
        if s.key then
 
          return translate_now("tower_locale", 'inside_box_keyhole_used_has_key');
 
        end;
 
        
 
				s.key = o;
 
				remove(o, pl);
 
        s.key = o;
 
        remove(o, pl);
 

	
 
				pl:need_scene(true);
 
				p(translate_now("tower_locale", 'inside_box_keyhole_used_insert_key', {
 
        pl:need_scene(true);
 
        p(translate_now("tower_locale", 'inside_box_keyhole_used_insert_key', {
 
              key = o.disp3
 
        }));
 

	
 
				if _('inside_box'):test() then
 
					remove('tower_box', pl);
 
					remove('tower_hint_1', pl);
 
					take('tower_level_2_key');
 
					p(translate_now("tower_locale", 'inside_box_keyhole_used_open'));
 
					walk('tower_level_1');
 
				end;
 
        if _('inside_box'):test() then
 
          remove('tower_box', pl);
 
          remove('tower_hint_1', pl);
 
          take('tower_level_2_key');
 
          p(translate_now("tower_locale", 'inside_box_keyhole_used_open'));
 
          walk('tower_level_1');
 
        end;
 
      else
 
        return false;
 
			end;
 
		end;
 
		act = function(s)
 
			pl:need_scene(true);
 
			if s.key then
 
				local key = s.key;
 
				take(key);
 
				s.key = false;
 
				return translate_now("tower_locale", 'inside_box_keyhole_act_key', {
 
      end;
 
    end;
 
    act = function(s)
 
      pl:need_scene(true);
 
      if s.key then
 
        local key = s.key;
 
        take(key);
 
        s.key = false;
 
        return translate_now("tower_locale", 'inside_box_keyhole_act_key', {
 
            key = key.disp3
 
        });
 
			else
 
				return translate_now("tower_locale", 'inside_box_keyhole_act_empty');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = 'keyhole_3';
 
		value = 5;
 
		key = false;
 
		dsc = function(s)
 
			if s.key then
 
      else
 
        return translate_now("tower_locale", 'inside_box_keyhole_act_empty');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = 'keyhole_3';
 
    value = 5;
 
    key = false;
 
    dsc = function(s)
 
      if s.key then
 
        return translate_now("tower_locale", 'inside_box_keyhole_3_key', {
 
            key = s.key.disp2
 
        }) .. '^';
 
			else
 
				return translate_now("tower_locale", 'inside_box_keyhole_3_empty') .. '^';
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' then
 
      else
 
        return translate_now("tower_locale", 'inside_box_keyhole_3_empty') .. '^';
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' then
 
        if s.key then
 
          return translate_now("tower_locale", 'inside_box_keyhole_used_has_key');
 
        end;
 
        
 
				s.key = o;
 
				remove(o, pl);
 
        s.key = o;
 
        remove(o, pl);
 

	
 
				pl:need_scene(true);
 
				p(translate_now("tower_locale", 'inside_box_keyhole_used_insert_key', {
 
        pl:need_scene(true);
 
        p(translate_now("tower_locale", 'inside_box_keyhole_used_insert_key', {
 
              key = o.disp3
 
        }));
 

	
 
				if _('inside_box'):test() then
 
					remove('tower_box', pl);
 
					remove('tower_hint_1', pl);
 
					take('tower_level_2_key');
 
					p(translate_now("tower_locale", 'inside_box_keyhole_used_open'));
 
					walk('tower_level_1');
 
				end;
 
        if _('inside_box'):test() then
 
          remove('tower_box', pl);
 
          remove('tower_hint_1', pl);
 
          take('tower_level_2_key');
 
          p(translate_now("tower_locale", 'inside_box_keyhole_used_open'));
 
          walk('tower_level_1');
 
        end;
 
      else
 
        return false;
 
			end;
 
		end;
 
		act = function(s)
 
			pl:need_scene(true);
 
			if s.key then
 
				local key = s.key;
 
				take(key);
 
				s.key = false;
 
				return translate_now("tower_locale", 'inside_box_keyhole_act_key', {
 
      end;
 
    end;
 
    act = function(s)
 
      pl:need_scene(true);
 
      if s.key then
 
        local key = s.key;
 
        take(key);
 
        s.key = false;
 
        return translate_now("tower_locale", 'inside_box_keyhole_act_key', {
 
            key = key.disp3
 
        });
 
			else
 
				return translate_now("tower_locale", 'inside_box_keyhole_act_empty');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = 'keyhole_4';
 
		value = 1;
 
		key = false;
 
		dsc = function(s)
 
			if s.key then
 
      else
 
        return translate_now("tower_locale", 'inside_box_keyhole_act_empty');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = 'keyhole_4';
 
    value = 1;
 
    key = false;
 
    dsc = function(s)
 
      if s.key then
 
        return translate_now("tower_locale", 'inside_box_keyhole_4_key', {
 
            key = s.key.disp2
 
        }) .. '^';
 
			else
 
				return translate_now("tower_locale", 'inside_box_keyhole_4_empty') .. '^';
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' then
 
      else
 
        return translate_now("tower_locale", 'inside_box_keyhole_4_empty') .. '^';
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'tower_key_0' or o^'tower_key_1' or o^'tower_key_2' or o^'tower_key_3' then
 
        if s.key then
 
          return translate_now("tower_locale", 'inside_box_keyhole_used_has_key');
 
        end;
 
				s.key = o;
 
				remove(o, pl);
 
        s.key = o;
 
        remove(o, pl);
 

	
 
				pl:need_scene(true);
 
				p(translate_now("tower_locale", 'inside_box_keyhole_used_insert_key', {
 
        pl:need_scene(true);
 
        p(translate_now("tower_locale", 'inside_box_keyhole_used_insert_key', {
 
              key = o.disp3
 
        }));
 

	
 
				if _('inside_box'):test() then
 
					remove('tower_box', pl);
 
					remove('tower_hint_1', pl);
 
					take('tower_level_2_key');
 
					p(translate_now("tower_locale", 'inside_box_keyhole_used_open'));
 
					walk('tower_level_1');
 
				end;
 
        if _('inside_box'):test() then
 
          remove('tower_box', pl);
 
          remove('tower_hint_1', pl);
 
          take('tower_level_2_key');
 
          p(translate_now("tower_locale", 'inside_box_keyhole_used_open'));
 
          walk('tower_level_1');
 
        end;
 
        
 
      else
 
        return false;
 
			end;
 
		end;
 
		act = function(s)
 
			pl:need_scene(true);
 
			if s.key then
 
				local key = s.key;
 
				take(key);
 
				s.key = false;
 
				return translate_now("tower_locale", 'inside_box_keyhole_act_key', {
 
      end;
 
    end;
 
    act = function(s)
 
      pl:need_scene(true);
 
      if s.key then
 
        local key = s.key;
 
        take(key);
 
        s.key = false;
 
        return translate_now("tower_locale", 'inside_box_keyhole_act_key', {
 
            key = key.disp3
 
        });
 
			else
 
				return translate_now("tower_locale", 'inside_box_keyhole_act_empty');
 
			end;
 
		end;
 
	};
 
      else
 
        return translate_now("tower_locale", 'inside_box_keyhole_act_empty');
 
      end;
 
    end;
 
  };
 
}
 

	
 
room {
 
	nam = 'tower_level_2';
 
	pic = 'images/tower_level_2_l.png';
 
	disp = translate("tower_locale", 'tower_level_2_disp');
 
	theme = 'tower';
 
	decor = translate("tower_locale", 'tower_level_2_decor');
 
	way = {
 
		path {translate("tower_locale", 'transition_downstairs'), "tower_level_1"};
 
		path {"level_2_next_room", translate("tower_locale", 'transition_room'), "tower_level_2_room_2"}:disable();
 
		path {"level_2_up", translate("tower_locale", 'transition_upstairs'), "tower_level_3"}:disable();
 
	};
 
  nam = 'tower_level_2';
 
  pic = 'images/tower_level_2_l.png';
 
  disp = translate("tower_locale", 'tower_level_2_disp');
 
  theme = 'tower';
 
  decor = translate("tower_locale", 'tower_level_2_decor');
 
  way = {
 
    path {translate("tower_locale", 'transition_downstairs'), "tower_level_1"};
 
    path {"level_2_next_room", translate("tower_locale", 'transition_room'), "tower_level_2_room_2"}:disable();
 
    path {"level_2_up", translate("tower_locale", 'transition_upstairs'), "tower_level_3"}:disable();
 
  };
 
  themeInit = function(s)
 
    load_sounds('bubble', 'potion');
 
  end;
 
}:with {
 
	'tower_walls',
 
	obj {
 
		state = 0;
 
		nam = '#tables';
 
		act = function(s)
 
			p(translate_now("tower_locale", 'tower_level_2_tables'));
 
			if s.state == 0 then
 
				s.state = 1;
 
				_'red_catalyst':enable();
 
				_'purple_catalyst':enable();
 
				p(translate_now("tower_locale", 'tower_level_2_table_vials'));
 
			end;
 
		end;
 
	};
 
	obj {
 
		state = 0;
 
		nam = '#racks';
 
		act = function(s)
 
			p(translate_now("tower_locale", 'tower_level_2_racks'));
 
			if s.state == 0 then
 
				s.state = 1;
 
				_'blue_catalyst':enable();
 
				_'turquoise_catalyst':enable();
 
				p(translate_now("tower_locale", 'tower_level_2_rack_vials'));
 
			end;
 
		end;
 
	};
 
	obj {
 
		state = 0;
 
		nam = '#cabinets';
 
		act = function(s)
 
			p(translate_now("tower_locale", 'tower_level_2_cabinets'));
 
			if s.state == 0 then
 
				s.state = 1;
 
				_'green_catalyst':enable();
 
				_'yellow_catalyst':enable();
 
				p(translate_now("tower_locale", 'tower_level_2_cabinet_vials'));
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#fire';
 
		act = translate("tower_locale", 'tower_level_2_fire');
 
	};
 
	obj {
 
		nam = 'alchemy_book';
 
		dsc = translate("tower_locale", 'tower_level_2_book');
 
		act = function(s)
 
			walkin('alchemy_book_dlg');
 
		end;
 
	};
 
	obj {
 
		nam = 'tower_cauldron';
 
		act = function()
 
			walkin('cauldron_inside');
 
		end;
 
		used = function(s, o)
 
  'tower_walls',
 
  obj {
 
    state = 0;
 
    nam = '#tables';
 
    act = function(s)
 
      p(translate_now("tower_locale", 'tower_level_2_tables'));
 
      if s.state == 0 then
 
        s.state = 1;
 
        _'red_catalyst':enable();
 
        _'purple_catalyst':enable();
 
        p(translate_now("tower_locale", 'tower_level_2_table_vials'));
 
      end;
 
    end;
 
  };
 
  obj {
 
    state = 0;
 
    nam = '#racks';
 
    act = function(s)
 
      p(translate_now("tower_locale", 'tower_level_2_racks'));
 
      if s.state == 0 then
 
        s.state = 1;
 
        _'blue_catalyst':enable();
 
        _'turquoise_catalyst':enable();
 
        p(translate_now("tower_locale", 'tower_level_2_rack_vials'));
 
      end;
 
    end;
 
  };
 
  obj {
 
    state = 0;
 
    nam = '#cabinets';
 
    act = function(s)
 
      p(translate_now("tower_locale", 'tower_level_2_cabinets'));
 
      if s.state == 0 then
 
        s.state = 1;
 
        _'green_catalyst':enable();
 
        _'yellow_catalyst':enable();
 
        p(translate_now("tower_locale", 'tower_level_2_cabinet_vials'));
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#fire';
 
    act = translate("tower_locale", 'tower_level_2_fire');
 
  };
 
  obj {
 
    nam = 'alchemy_book';
 
    dsc = translate("tower_locale", 'tower_level_2_book');
 
    act = function(s)
 
      walkin('alchemy_book_dlg');
 
    end;
 
  };
 
  obj {
 
    nam = 'tower_cauldron';
 
    act = function()
 
      walkin('cauldron_inside');
 
    end;
 
    used = function(s, o)
 
      if o^'kettle' or o^'cups' or o^'teapot' or o^'teabox' or o.ptype then
 
        return translate_now("tower_locale", 'tower_level_2_cannot_be_thrown')
 
      end;
 
@@ -847,282 +850,282 @@ room {
 
      if cauldron.potion then
 
        return translate_now("tower_locale", 'tower_level_2_potion_in_the_cauldron')
 
      end;
 
			pl:need_scene(true);
 
			table.insert(cauldron.state, o);
 
			remove(o, pl);
 
			sounds['bubble']:play();
 
      pl:need_scene(true);
 
      table.insert(cauldron.state, o);
 
      remove(o, pl);
 
      sounds['bubble']:play();
 
      p(translate_now("tower_locale", 'tower_level_2_cauldron_used', {
 
        item = o.disp3
 
      }));
 
			if cauldron:check_potion() then
 
				sounds['potion']:play();
 
				p(translate_now("tower_locale", 'tower_level_2_potion_ready'));
 
			end;
 
		end;
 
	};
 
	obj {
 
		state = false;
 
		nam = '#tower_2_door';
 
		dsc = function(s)
 
			if s.state then
 
				return translate_now("tower_locale", 'tower_2_door_dsc_open');
 
			else
 
				return translate_now("tower_locale", 'tower_2_door_dsc_closed');
 
			end;
 
		end;
 
		act = function(s)
 
			if s.state then
 
				return translate_now("tower_locale", 'tower_2_door_act_open');
 
			else
 
				return translate_now("tower_locale", 'tower_2_door_act_closed');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'hidden_key' then
 
				return translate_now("common_locale", 'key_does_not_fit');
 
			elseif o^'potion_open' then
 
				remove('potion_open', pl);
 
				s.state = true;
 
				enable('level_2_up');
 
				take('flask');
 
				return translate_now("tower_locale", 'tower_2_door_used_potion');
 
      if cauldron:check_potion() then
 
        sounds['potion']:play();
 
        p(translate_now("tower_locale", 'tower_level_2_potion_ready'));
 
      end;
 
    end;
 
  };
 
  obj {
 
    state = false;
 
    nam = '#tower_2_door';
 
    dsc = function(s)
 
      if s.state then
 
        return translate_now("tower_locale", 'tower_2_door_dsc_open');
 
      else
 
        return translate_now("tower_locale", 'tower_2_door_dsc_closed');
 
      end;
 
    end;
 
    act = function(s)
 
      if s.state then
 
        return translate_now("tower_locale", 'tower_2_door_act_open');
 
      else
 
        return translate_now("tower_locale", 'tower_2_door_act_closed');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'hidden_key' then
 
        return translate_now("common_locale", 'key_does_not_fit');
 
      elseif o^'potion_open' then
 
        remove('potion_open', pl);
 
        s.state = true;
 
        enable('level_2_up');
 
        take('flask');
 
        return translate_now("tower_locale", 'tower_2_door_used_potion');
 
      else
 
        return false;
 
			end;
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#stairwell';
 
			act = translate("tower_locale", 'tower_level_1_stairwell');
 
		}
 
	};
 
	obj {
 
		nam = 'red_catalyst';
 
		dsc = translate("tower_locale", 'red_catalyst_dsc');
 
		disp = translate("tower_locale", 'red_catalyst_disp');
 
		disp2 = translate("tower_locale", 'red_catalyst_disp2');
 
		disp3 = translate("tower_locale", 'red_catalyst_disp3');
 
		tak = translate("tower_locale", 'catalyst_tak');
 
		inv = translate("tower_locale", 'red_catalyst_inv');
 
	}:disable();
 
	obj {
 
		nam = 'green_catalyst';
 
		dsc = translate("tower_locale", 'green_catalyst_dsc');
 
		disp = translate("tower_locale", 'green_catalyst_disp');
 
		disp2 = translate("tower_locale", 'green_catalyst_disp2');
 
		disp3 = translate("tower_locale", 'green_catalyst_disp3');
 
		tak = translate("tower_locale", 'catalyst_tak');
 
		inv = translate("tower_locale", 'green_catalyst_inv');
 
	}:disable();
 
	obj {
 
		nam = 'blue_catalyst';
 
		dsc = translate("tower_locale", 'blue_catalyst_dsc');
 
		disp = translate("tower_locale", 'blue_catalyst_disp');
 
		disp2 = translate("tower_locale", 'blue_catalyst_disp2');
 
		disp3 = translate("tower_locale", 'blue_catalyst_disp3');
 
		tak = translate("tower_locale", 'catalyst_tak');
 
		inv = translate("tower_locale", 'blue_catalyst_inv');
 
	}:disable();
 
      end;
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#stairwell';
 
      act = translate("tower_locale", 'tower_level_1_stairwell');
 
    }
 
  };
 
  obj {
 
    nam = 'red_catalyst';
 
    dsc = translate("tower_locale", 'red_catalyst_dsc');
 
    disp = translate("tower_locale", 'red_catalyst_disp');
 
    disp2 = translate("tower_locale", 'red_catalyst_disp2');
 
    disp3 = translate("tower_locale", 'red_catalyst_disp3');
 
    tak = translate("tower_locale", 'catalyst_tak');
 
    inv = translate("tower_locale", 'red_catalyst_inv');
 
  }:disable();
 
  obj {
 
    nam = 'green_catalyst';
 
    dsc = translate("tower_locale", 'green_catalyst_dsc');
 
    disp = translate("tower_locale", 'green_catalyst_disp');
 
    disp2 = translate("tower_locale", 'green_catalyst_disp2');
 
    disp3 = translate("tower_locale", 'green_catalyst_disp3');
 
    tak = translate("tower_locale", 'catalyst_tak');
 
    inv = translate("tower_locale", 'green_catalyst_inv');
 
  }:disable();
 
  obj {
 
		nam = 'purple_catalyst';
 
		dsc = translate("tower_locale", 'purple_catalyst_dsc');
 
		disp = translate("tower_locale", 'purple_catalyst_disp');
 
		disp2 = translate("tower_locale", 'purple_catalyst_disp2');
 
		disp3 = translate("tower_locale", 'purple_catalyst_disp3');
 
		tak = translate("tower_locale", 'catalyst_tak');
 
		inv = translate("tower_locale", 'purple_catalyst_inv');
 
	}:disable();
 
	obj {
 
		nam = 'yellow_catalyst';
 
		dsc = translate("tower_locale", 'yellow_catalyst_dsc');
 
		disp = translate("tower_locale", 'yellow_catalyst_disp');
 
		disp2 = translate("tower_locale", 'yellow_catalyst_disp2');
 
		disp3 = translate("tower_locale", 'yellow_catalyst_disp3');
 
		tak = translate("tower_locale", 'catalyst_tak');
 
		inv = translate("tower_locale", 'yellow_catalyst_inv');
 
	}:disable();
 
	obj {
 
		nam = 'turquoise_catalyst';
 
		dsc = translate("tower_locale", 'turquoise_catalyst_dsc');
 
		disp = translate("tower_locale", 'turquoise_catalyst_disp');
 
		disp2 = translate("tower_locale", 'turquoise_catalyst_disp2');
 
		disp3 = translate("tower_locale", 'turquoise_catalyst_disp3');
 
		tak = translate("tower_locale", 'catalyst_tak');
 
		inv = translate("tower_locale", 'turquoise_catalyst_inv');
 
	}:disable();
 
    nam = 'blue_catalyst';
 
    dsc = translate("tower_locale", 'blue_catalyst_dsc');
 
    disp = translate("tower_locale", 'blue_catalyst_disp');
 
    disp2 = translate("tower_locale", 'blue_catalyst_disp2');
 
    disp3 = translate("tower_locale", 'blue_catalyst_disp3');
 
    tak = translate("tower_locale", 'catalyst_tak');
 
    inv = translate("tower_locale", 'blue_catalyst_inv');
 
  }:disable();
 
  obj {
 
    nam = 'purple_catalyst';
 
    dsc = translate("tower_locale", 'purple_catalyst_dsc');
 
    disp = translate("tower_locale", 'purple_catalyst_disp');
 
    disp2 = translate("tower_locale", 'purple_catalyst_disp2');
 
    disp3 = translate("tower_locale", 'purple_catalyst_disp3');
 
    tak = translate("tower_locale", 'catalyst_tak');
 
    inv = translate("tower_locale", 'purple_catalyst_inv');
 
  }:disable();
 
  obj {
 
    nam = 'yellow_catalyst';
 
    dsc = translate("tower_locale", 'yellow_catalyst_dsc');
 
    disp = translate("tower_locale", 'yellow_catalyst_disp');
 
    disp2 = translate("tower_locale", 'yellow_catalyst_disp2');
 
    disp3 = translate("tower_locale", 'yellow_catalyst_disp3');
 
    tak = translate("tower_locale", 'catalyst_tak');
 
    inv = translate("tower_locale", 'yellow_catalyst_inv');
 
  }:disable();
 
  obj {
 
    nam = 'turquoise_catalyst';
 
    dsc = translate("tower_locale", 'turquoise_catalyst_dsc');
 
    disp = translate("tower_locale", 'turquoise_catalyst_disp');
 
    disp2 = translate("tower_locale", 'turquoise_catalyst_disp2');
 
    disp3 = translate("tower_locale", 'turquoise_catalyst_disp3');
 
    tak = translate("tower_locale", 'catalyst_tak');
 
    inv = translate("tower_locale", 'turquoise_catalyst_inv');
 
  }:disable();
 
}
 

	
 
dlg {
 
	nam = 'alchemy_book_dlg';
 
  nam = 'alchemy_book_dlg';
 
  theme = 'tower';
 
	pic = 'images/tower_level_2_l.png';
 
	disp = translate("tower_locale", 'alchemy_book_dlg_disp');
 
	enter = translate("tower_locale", 'alchemy_book_dlg_enter');
 
	phr = {
 
  pic = 'images/tower_level_2_l.png';
 
  disp = translate("tower_locale", 'alchemy_book_dlg_disp');
 
  enter = translate("tower_locale", 'alchemy_book_dlg_enter');
 
  phr = {
 
    {always=true, translate("tower_locale", 'alchemy_book_dlg_open'), function(s)
 
        return translate_now("tower_locale", 'alchemy_book_dlg_open_response', {catalyst=_(opening_catalyst).disp2});
 
    end};
 
		{always=true, translate("tower_locale", 'alchemy_book_dlg_light'), function(s)
 
    {always=true, translate("tower_locale", 'alchemy_book_dlg_light'), function(s)
 
        return translate_now("tower_locale", 'alchemy_book_dlg_light_response', {catalyst=_(light_catalyst).disp2});
 
    end};
 
		{always=true, translate("tower_locale", 'alchemy_book_dlg_rich'), function(s)
 
    {always=true, translate("tower_locale", 'alchemy_book_dlg_rich'), function(s)
 
        return translate_now("tower_locale", 'alchemy_book_dlg_rich_response', {catalyst=_(enrichment_catalyst).disp2});
 
    end};
 
		{always=true, translate("tower_locale", 'alchemy_book_dlg_leave'), function() walkout(); end}
 
	};
 
    {always=true, translate("tower_locale", 'alchemy_book_dlg_leave'), function() walkout(); end}
 
  };
 
}
 

	
 
dlg {
 
  theme = 'tower';
 
	state = {};
 
	potion = false;
 
	hideinv = true;
 
	nam = 'cauldron_inside';
 
	pic = 'images/tower_level_2_l.png';
 
	disp = translate("tower_locale", 'cauldron_inside_disp');
 
	check_potion = function(s)
 
		if #s.state == 3 then
 
			if has_object(s.state, 'lock') and has_object(s.state, 'hidden_key') and has_object(s.state, opening_catalyst) then
 
				s.potion = _('potion_open');
 
				return true;
 
			elseif has_object(s.state, 'candle') and has_object(s.state, 'flask') and has_object(s.state, light_catalyst) then
 
				s.potion = _('potion_light');
 
				return true;
 
			elseif has_object(s.state, 'silver_fork') and has_object(s.state, 'emerald') and has_object(s.state, enrichment_catalyst) then
 
				s.potion = _('potion_enrichment');
 
				return true;
 
			end;
 
		end;
 
  state = {};
 
  potion = false;
 
  hideinv = true;
 
  nam = 'cauldron_inside';
 
  pic = 'images/tower_level_2_l.png';
 
  disp = translate("tower_locale", 'cauldron_inside_disp');
 
  check_potion = function(s)
 
    if #s.state == 3 then
 
      if has_object(s.state, 'lock') and has_object(s.state, 'hidden_key') and has_object(s.state, opening_catalyst) then
 
        s.potion = _('potion_open');
 
        return true;
 
      elseif has_object(s.state, 'candle') and has_object(s.state, 'flask') and has_object(s.state, light_catalyst) then
 
        s.potion = _('potion_light');
 
        return true;
 
      elseif has_object(s.state, 'silver_fork') and has_object(s.state, 'emerald') and has_object(s.state, enrichment_catalyst) then
 
        s.potion = _('potion_enrichment');
 
        return true;
 
      end;
 
    end;
 

	
 
		return false;
 
	end;
 
	enter = function(s)
 
		if s.potion then
 
			enable('#take_potion');
 
			disable('#take_all');
 
    return false;
 
  end;
 
  enter = function(s)
 
    if s.potion then
 
      enable('#take_potion');
 
      disable('#take_all');
 
      return translate_now("tower_locale", 'cauldron_inside_enter_potion', {
 
          potion=std.call(s.potion, "disp2");
 
      });
 
		elseif #s.state == 0 then
 
			disable('#take_potion');
 
			disable('#take_all');
 
			return translate_now("tower_locale", 'cauldron_inside_enter_water');
 
		elseif #s.state == 1 then
 
			disable('#take_potion');
 
			enable('#take_all');
 
    elseif #s.state == 0 then
 
      disable('#take_potion');
 
      disable('#take_all');
 
      return translate_now("tower_locale", 'cauldron_inside_enter_water');
 
    elseif #s.state == 1 then
 
      disable('#take_potion');
 
      enable('#take_all');
 
      return translate_now("tower_locale", 'cauldron_inside_enter_single_item', {
 
          item=std.call(s.state[1], "disp2");
 
      });
 
		else
 
			disable('#take_potion');
 
			enable('#take_all');
 
    else
 
      disable('#take_potion');
 
      enable('#take_all');
 

	
 
			local dsc = translate_now("tower_locale", 'cauldron_inside_enter_many_items') .. ' ';
 
      local dsc = translate_now("tower_locale", 'cauldron_inside_enter_many_items') .. ' ';
 

	
 
			for i = 1, #s.state do
 
				dsc = dsc .. std.call(s.state[i], "disp2");
 
				if i < #s.state then
 
					dsc = dsc .. ', ';
 
				end;
 
			end;
 
			return dsc .. '. ';
 
		end;
 
	end;
 
	phr = {
 
		{'#take_potion', translate("tower_locale", 'cauldron_inside_take_potion'), function(s)
 
			local potion = _('cauldron_inside').potion;
 
			_('cauldron_inside').state = {};
 
			take(potion);
 
			_('cauldron_inside').potion = false;
 
			pr(translate_now("tower_locale", 'cauldron_inside_take_potion_response'));
 
			walkout();
 
		end};
 
		{'#take_all', translate("tower_locale", 'cauldron_inside_take_items'), function(s)
 
			local state = _('cauldron_inside').state;
 
			_('cauldron_inside').state = {};
 
			for i = 1, #state do
 
				take(state[i]);
 
			end;
 
			walkout();
 
		end};
 
		{always=true, translate("tower_locale", 'cauldron_inside_leave'), function(s)
 
			walkout();
 
		end;};
 
	}
 
      for i = 1, #s.state do
 
        dsc = dsc .. std.call(s.state[i], "disp2");
 
        if i < #s.state then
 
          dsc = dsc .. ', ';
 
        end;
 
      end;
 
      return dsc .. '. ';
 
    end;
 
  end;
 
  phr = {
 
    {'#take_potion', translate("tower_locale", 'cauldron_inside_take_potion'), function(s)
 
      local potion = _('cauldron_inside').potion;
 
      _('cauldron_inside').state = {};
 
      take(potion);
 
      _('cauldron_inside').potion = false;
 
      pr(translate_now("tower_locale", 'cauldron_inside_take_potion_response'));
 
      walkout();
 
    end};
 
    {'#take_all', translate("tower_locale", 'cauldron_inside_take_items'), function(s)
 
      local state = _('cauldron_inside').state;
 
      _('cauldron_inside').state = {};
 
      for i = 1, #state do
 
        take(state[i]);
 
      end;
 
      walkout();
 
    end};
 
    {always=true, translate("tower_locale", 'cauldron_inside_leave'), function(s)
 
      walkout();
 
    end;};
 
  }
 
}
 

	
 
room {
 
	nam = 'tower_level_3';
 
	theme = 'tower';
 
	disp = translate("tower_locale", 'tower_level_3_disp');
 
	pic = 'images/tower_level_3.png';
 
	decor = translate("tower_locale", 'tower_level_3_decor');
 
  nam = 'tower_level_3';
 
  theme = 'tower';
 
  disp = translate("tower_locale", 'tower_level_3_disp');
 
  pic = 'images/tower_level_3.png';
 
  decor = translate("tower_locale", 'tower_level_3_decor');
 
  enter = function(s)
 
    if tower_accept_level < 1 then
 
      tower_accept_level = 1;
 
    end;
 
  end;
 
	way = {
 
		path {translate("tower_locale", 'transition_downstairs'), "tower_level_2"};
 
		path {"level_3_next_room", translate("tower_locale", 'transition_room'), "tower_level_3_room_2"}:disable();
 
		path {"level_3_up", translate("tower_locale", 'transition_upstairs'), "tower_level_4"}:disable();
 
	};
 
  way = {
 
    path {translate("tower_locale", 'transition_downstairs'), "tower_level_2"};
 
    path {"level_3_next_room", translate("tower_locale", 'transition_room'), "tower_level_3_room_2"}:disable();
 
    path {"level_3_up", translate("tower_locale", 'transition_upstairs'), "tower_level_4"}:disable();
 
  };
 
}:with {
 
  'tower_walls',
 
	obj {
 
		nam = '#bookshelves';
 
		act = translate("tower_locale", 'tower_level_3_bookshelves');
 
	};
 
	obj {
 
		nam = '#fireplace';
 
		act = translate("tower_locale", 'tower_level_3_fireplace');
 
	};
 
	obj {
 
		nam = '#rockchair';
 
		act = translate("tower_locale", 'tower_level_3_rockchair');
 
	};
 
	obj {
 
		nam = 'level_3_room_2_door';
 
		dsc = translate("tower_locale", 'tower_level_3_hidden_door_dsc');
 
		act = translate("tower_locale", 'tower_level_3_hidden_door_act');
 
	}:disable();
 
	obj {
 
		solved = false;
 
		nam = 'tower_level_3_table';
 
		act = function(s)
 
			if s.solved then
 
				return translate_now("tower_locale", 'tower_level_3_table_decor') .. ' ' .. translate_now("tower_locale", 'tower_level_3_table_decor_solved');
 
			else
 
				walkin('tower_level_3_table_in');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#tower_3_door';
 
		dsc = function(s)
 
			if _'level_3_up':disabled() then
 
				return translate_now("tower_locale", 'tower_level_3_door_dsc_locked');
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_door_dsc_open');
 
			end;
 
		end;
 
		act = function(s)
 
			if _'level_3_up':disabled() then
 
				return translate_now("tower_locale", 'tower_level_3_door_act_locked');
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_door_act_open');
 
			end;
 
		end;
 
	}: with {
 
		obj {
 
			nam = '#stairwell';
 
			act = translate("tower_locale", 'tower_level_1_stairwell');
 
		}
 
	};
 
  obj {
 
    nam = '#bookshelves';
 
    act = translate("tower_locale", 'tower_level_3_bookshelves');
 
  };
 
  obj {
 
    nam = '#fireplace';
 
    act = translate("tower_locale", 'tower_level_3_fireplace');
 
  };
 
  obj {
 
    nam = '#rockchair';
 
    act = translate("tower_locale", 'tower_level_3_rockchair');
 
  };
 
  obj {
 
    nam = 'level_3_room_2_door';
 
    dsc = translate("tower_locale", 'tower_level_3_hidden_door_dsc');
 
    act = translate("tower_locale", 'tower_level_3_hidden_door_act');
 
  }:disable();
 
  obj {
 
    solved = false;
 
    nam = 'tower_level_3_table';
 
    act = function(s)
 
      if s.solved then
 
        return translate_now("tower_locale", 'tower_level_3_table_decor') .. ' ' .. translate_now("tower_locale", 'tower_level_3_table_decor_solved');
 
      else
 
        walkin('tower_level_3_table_in');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#tower_3_door';
 
    dsc = function(s)
 
      if _'level_3_up':disabled() then
 
        return translate_now("tower_locale", 'tower_level_3_door_dsc_locked');
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_door_dsc_open');
 
      end;
 
    end;
 
    act = function(s)
 
      if _'level_3_up':disabled() then
 
        return translate_now("tower_locale", 'tower_level_3_door_act_locked');
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_door_act_open');
 
      end;
 
    end;
 
  }: with {
 
    obj {
 
      nam = '#stairwell';
 
      act = translate("tower_locale", 'tower_level_1_stairwell');
 
    }
 
  };
 
}
 

	
 
room {
 
	nam = 'tower_level_3_table_in';
 
  nam = 'tower_level_3_table_in';
 
  pic = function(s)
 
    local p = 'images/table/table_reff.png';
 
    if _'#figures':disabled() then
 
@@ -1176,398 +1179,398 @@ room {
 
    
 
    return p;
 
  end;
 
	theme = 'tower';
 
	nofollow = true;
 
	disp = translate("tower_locale", 'tower_level_3_disp');
 
	decor = function(s)
 
  theme = 'tower';
 
  nofollow = true;
 
  disp = translate("tower_locale", 'tower_level_3_disp');
 
  decor = function(s)
 
    return translate_now("tower_locale", 'tower_level_3_table_decor') .. ' ' .. translate_now("tower_locale", 'tower_level_3_table_decor_unsolved');
 
  end;
 
	way = {
 
		path {translate("common_locale", 'back'), 'tower_level_3'};
 
	};
 
  way = {
 
    path {translate("common_locale", 'back'), 'tower_level_3'};
 
  };
 
}:with {
 
	obj {
 
		nam = '#figures';
 
		dsc = translate("tower_locale", 'tower_level_3_table_in_figures_dsc');
 
		act = function(s)
 
			take('figure_wolf');
 
			take('figure_tiger');
 
			take('figure_lion');
 
			take('figure_knight');
 
			take('figure_tower');
 
			s:disable();
 
			return translate_now("tower_locale", 'tower_level_3_table_in_figures_act');
 
		end;
 
	};
 
	obj {
 
		item = false;
 
		target = 'figure_wolf';
 
		nam = '#north_west';
 
		dsc = function(s)
 
			if s.item then
 
  obj {
 
    nam = '#figures';
 
    dsc = translate("tower_locale", 'tower_level_3_table_in_figures_dsc');
 
    act = function(s)
 
      take('figure_wolf');
 
      take('figure_tiger');
 
      take('figure_lion');
 
      take('figure_knight');
 
      take('figure_tower');
 
      s:disable();
 
      return translate_now("tower_locale", 'tower_level_3_table_in_figures_act');
 
    end;
 
  };
 
  obj {
 
    item = false;
 
    target = 'figure_wolf';
 
    nam = '#north_west';
 
    dsc = function(s)
 
      if s.item then
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_full', {
 
            location='NW',
 
            item=s.item.disp2
 
        });
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_empty', {
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_empty', {
 
            location='NW'
 
        });
 
			end;
 
		end;
 
		act = function(s)
 
			if s.item then
 
				local t = s.item;
 
				take(s.item);
 
				s.item = false;
 
      end;
 
    end;
 
    act = function(s)
 
      if s.item then
 
        local t = s.item;
 
        take(s.item);
 
        s.item = false;
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_act_full', {
 
            item=t.disp3
 
        });
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_table_deepening_act_empty');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if s.item then
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_act_empty');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if s.item then
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_used_full', {
 
            item=s.item.disp2
 
        });
 
			elseif o^'figure_wolf' or o^'figure_lion' or o^'figure_tower' or o^'figure_knight' or o^'figure_tiger' then
 
				s.item = o;
 
      elseif o^'figure_wolf' or o^'figure_lion' or o^'figure_tower' or o^'figure_knight' or o^'figure_tiger' then
 
        s.item = o;
 
        p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_fit', {
 
            item=o.disp3
 
        }));
 
				remove(o, pl);
 
				local niches = {
 
					_('#north_west');
 
					_('#north_east');
 
					_('#middle');
 
					_('#south_west');
 
					_('#south_east');
 
				};
 
        remove(o, pl);
 
        local niches = {
 
          _('#north_west');
 
          _('#north_east');
 
          _('#middle');
 
          _('#south_west');
 
          _('#south_east');
 
        };
 

	
 
				for i = 1, #niches do
 
					if not niches[i].item or niches[i].item.nam ~= niches[i].target then
 
						return;
 
					end;
 
				end;
 
        for i = 1, #niches do
 
          if not niches[i].item or niches[i].item.nam ~= niches[i].target then
 
            return;
 
          end;
 
        end;
 

	
 
				_('tower_level_3_table').solved = true;
 
				walkout();
 
				_('level_3_up'):enable();
 
				p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_open'));
 
        _('tower_level_3_table').solved = true;
 
        walkout();
 
        _('level_3_up'):enable();
 
        p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_open'));
 
      else
 
        return false;
 
			end;
 
		end;
 
	};
 
	obj {
 
		item = false;
 
		target = 'figure_lion';
 
		nam = '#north_east';
 
		dsc = function(s)
 
			if s.item then
 
      end;
 
    end;
 
  };
 
  obj {
 
    item = false;
 
    target = 'figure_lion';
 
    nam = '#north_east';
 
    dsc = function(s)
 
      if s.item then
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_full', {
 
            location='NE',
 
            item=s.item.disp2
 
        });
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_empty', {
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_empty', {
 
            location='NE'
 
        });
 
			end;
 
		end;
 
		act = function(s)
 
			if s.item then
 
				local t = s.item;
 
				take(s.item);
 
				s.item = false;
 
      end;
 
    end;
 
    act = function(s)
 
      if s.item then
 
        local t = s.item;
 
        take(s.item);
 
        s.item = false;
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_act_full', {
 
            item=t.disp3
 
        });
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_table_deepening_act_empty');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if s.item then
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_act_empty');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if s.item then
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_used_full', {
 
            item=s.item.disp2
 
        });
 
			elseif o^'figure_wolf' or o^'figure_lion' or o^'figure_tower' or o^'figure_knight' or o^'figure_tiger' then
 
				s.item = o;
 
      elseif o^'figure_wolf' or o^'figure_lion' or o^'figure_tower' or o^'figure_knight' or o^'figure_tiger' then
 
        s.item = o;
 
        p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_fit', {
 
            item=o.disp3
 
        }));
 
				remove(o, pl);
 
				local niches = {
 
					_('#north_west');
 
					_('#north_east');
 
					_('#middle');
 
					_('#south_west');
 
					_('#south_east');
 
				};
 
        remove(o, pl);
 
        local niches = {
 
          _('#north_west');
 
          _('#north_east');
 
          _('#middle');
 
          _('#south_west');
 
          _('#south_east');
 
        };
 

	
 
				for i = 1, #niches do
 
					if not niches[i].item or niches[i].item.nam ~= niches[i].target then
 
						return;
 
					end;
 
				end;
 
        for i = 1, #niches do
 
          if not niches[i].item or niches[i].item.nam ~= niches[i].target then
 
            return;
 
          end;
 
        end;
 

	
 
				_('tower_level_3_table').solved = true;
 
				walkout();
 
				_('level_3_up'):enable();
 
				p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_open'));
 
        _('tower_level_3_table').solved = true;
 
        walkout();
 
        _('level_3_up'):enable();
 
        p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_open'));
 
      else
 
        return false;
 
			end;
 
		end;
 
	};
 
	obj {
 
		item = false;
 
		target = 'figure_tower';
 
		nam = '#middle';
 
		dsc = function(s)
 
			if s.item then
 
      end;
 
    end;
 
  };
 
  obj {
 
    item = false;
 
    target = 'figure_tower';
 
    nam = '#middle';
 
    dsc = function(s)
 
      if s.item then
 
        return translate_now("tower_locale", 'tower_level_3_table_middle_deepening_dsc_full', {
 
            item=s.item.disp2
 
        });
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_table_middle_deepening_dsc_empty');
 
			end;
 
		end;
 
		act = function(s)
 
			if s.item then
 
				local t = s.item;
 
				take(s.item);
 
				s.item = false;
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_table_middle_deepening_dsc_empty');
 
      end;
 
    end;
 
    act = function(s)
 
      if s.item then
 
        local t = s.item;
 
        take(s.item);
 
        s.item = false;
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_act_full', {
 
            item=t.disp3
 
        });
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_table_deepening_act_empty');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if s.item then
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_act_empty');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if s.item then
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_used_full', {
 
            item=s.item.disp2
 
        });
 
			elseif o^'figure_wolf' or o^'figure_lion' or o^'figure_tower' or o^'figure_knight' or o^'figure_tiger' then
 
				s.item = o;
 
      elseif o^'figure_wolf' or o^'figure_lion' or o^'figure_tower' or o^'figure_knight' or o^'figure_tiger' then
 
        s.item = o;
 
        p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_fit', {
 
            item=o.disp3
 
        }));
 
				remove(o, pl);
 
				local niches = {
 
					_('#north_west');
 
					_('#north_east');
 
					_('#middle');
 
					_('#south_west');
 
					_('#south_east');
 
				};
 
        remove(o, pl);
 
        local niches = {
 
          _('#north_west');
 
          _('#north_east');
 
          _('#middle');
 
          _('#south_west');
 
          _('#south_east');
 
        };
 

	
 
				for i = 1, #niches do
 
					if not niches[i].item or niches[i].item.nam ~= niches[i].target then
 
						return;
 
					end;
 
				end;
 
        for i = 1, #niches do
 
          if not niches[i].item or niches[i].item.nam ~= niches[i].target then
 
            return;
 
          end;
 
        end;
 

	
 
				_('tower_level_3_table').solved = true;
 
				walkout();
 
				_('level_3_up'):enable();
 
				p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_open'));
 
        _('tower_level_3_table').solved = true;
 
        walkout();
 
        _('level_3_up'):enable();
 
        p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_open'));
 
      else
 
        return false;
 
			end;
 
		end;
 
	};
 
	obj {
 
		item = false;
 
		target = 'figure_knight';
 
		nam = '#south_west';
 
		dsc = function(s)
 
			if s.item then
 
      end;
 
    end;
 
  };
 
  obj {
 
    item = false;
 
    target = 'figure_knight';
 
    nam = '#south_west';
 
    dsc = function(s)
 
      if s.item then
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_full', {
 
            location='SW',
 
            item=s.item.disp2
 
        });
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_empty', {
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_empty', {
 
            location='SW'
 
        });
 
			end;
 
		end;
 
		act = function(s)
 
			if s.item then
 
				local t = s.item;
 
				take(s.item);
 
				s.item = false;
 
      end;
 
    end;
 
    act = function(s)
 
      if s.item then
 
        local t = s.item;
 
        take(s.item);
 
        s.item = false;
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_act_full', {
 
            item=t.disp3
 
        });
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_table_deepening_act_empty');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if s.item then
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_act_empty');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if s.item then
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_used_full', {
 
            item=s.item.disp2
 
        });
 
			elseif o^'figure_wolf' or o^'figure_lion' or o^'figure_tower' or o^'figure_knight' or o^'figure_tiger' then
 
				s.item = o;
 
      elseif o^'figure_wolf' or o^'figure_lion' or o^'figure_tower' or o^'figure_knight' or o^'figure_tiger' then
 
        s.item = o;
 
        p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_fit', {
 
            item=o.disp3
 
        }));
 
				remove(o, pl);
 
				local niches = {
 
					_('#north_west');
 
					_('#north_east');
 
					_('#middle');
 
					_('#south_west');
 
					_('#south_east');
 
				};
 
        remove(o, pl);
 
        local niches = {
 
          _('#north_west');
 
          _('#north_east');
 
          _('#middle');
 
          _('#south_west');
 
          _('#south_east');
 
        };
 

	
 
				for i = 1, #niches do
 
					if not niches[i].item or niches[i].item.nam ~= niches[i].target then
 
						return;
 
					end;
 
				end;
 
        for i = 1, #niches do
 
          if not niches[i].item or niches[i].item.nam ~= niches[i].target then
 
            return;
 
          end;
 
        end;
 

	
 
				_('tower_level_3_table').solved = true;
 
				walkout();
 
				_('level_3_up'):enable();
 
				p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_open'));
 
        _('tower_level_3_table').solved = true;
 
        walkout();
 
        _('level_3_up'):enable();
 
        p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_open'));
 
      else
 
        return false;
 
			end;
 
		end;
 
	};
 
	obj {
 
		item = false;
 
		target = 'figure_tiger';
 
		nam = '#south_east';
 
		dsc = function(s)
 
			if s.item then
 
      end;
 
    end;
 
  };
 
  obj {
 
    item = false;
 
    target = 'figure_tiger';
 
    nam = '#south_east';
 
    dsc = function(s)
 
      if s.item then
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_full', {
 
            location='SE',
 
            item=s.item.disp2
 
        });
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_empty', {
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_dsc_empty', {
 
            location='SE'
 
        });
 
			end;
 
		end;
 
		act = function(s)
 
			if s.item then
 
				local t = s.item;
 
				take(s.item);
 
				s.item = false;
 
      end;
 
    end;
 
    act = function(s)
 
      if s.item then
 
        local t = s.item;
 
        take(s.item);
 
        s.item = false;
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_act_full', {
 
            item=t.disp3
 
        });
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_table_deepening_act_empty');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if s.item then
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_act_empty');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if s.item then
 
        return translate_now("tower_locale", 'tower_level_3_table_deepening_used_full', {
 
            item=s.item.disp2
 
        });
 
			elseif o^'figure_wolf' or o^'figure_lion' or o^'figure_tower' or o^'figure_knight' or o^'figure_tiger' then
 
				s.item = o;
 
      elseif o^'figure_wolf' or o^'figure_lion' or o^'figure_tower' or o^'figure_knight' or o^'figure_tiger' then
 
        s.item = o;
 
        p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_fit', {
 
            item=o.disp3
 
        }));
 
				remove(o, pl);
 
				local niches = {
 
					_('#north_west');
 
					_('#north_east');
 
					_('#middle');
 
					_('#south_west');
 
					_('#south_east');
 
				};
 
        remove(o, pl);
 
        local niches = {
 
          _('#north_west');
 
          _('#north_east');
 
          _('#middle');
 
          _('#south_west');
 
          _('#south_east');
 
        };
 

	
 
				for i = 1, #niches do
 
					if not niches[i].item or niches[i].item.nam ~= niches[i].target then
 
						return;
 
					end;
 
				end;
 
        for i = 1, #niches do
 
          if not niches[i].item or niches[i].item.nam ~= niches[i].target then
 
            return;
 
          end;
 
        end;
 

	
 
				_('tower_level_3_table').solved = true;
 
				walkout();
 
				_('level_3_up'):enable();
 
				p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_open'));
 
        _('tower_level_3_table').solved = true;
 
        walkout();
 
        _('level_3_up'):enable();
 
        p(translate_now("tower_locale", 'tower_level_3_table_deepening_used_open'));
 
      else
 
        return false;
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#hint';
 
		act = translate("tower_locale", 'tower_level_3_hint');
 
	}
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#hint';
 
    act = translate("tower_locale", 'tower_level_3_hint');
 
  }
 
}
 

	
 
obj {
 
	nam = 'figure_wolf';
 
	disp = translate("tower_locale", 'figure_wolf_disp');
 
	disp2 = translate("tower_locale", 'figure_wolf_disp2');
 
	disp3 = translate("tower_locale", 'figure_wolf_disp3');
 
	inv = function(s)
 
  nam = 'figure_wolf';
 
  disp = translate("tower_locale", 'figure_wolf_disp');
 
  disp2 = translate("tower_locale", 'figure_wolf_disp2');
 
  disp3 = translate("tower_locale", 'figure_wolf_disp3');
 
  inv = function(s)
 
    return translate_now("tower_locale", 'figure_wolf_inv') .. ' ' .. translate_now("tower_locale", 'figure_common_inv');
 
  end;
 
}
 

	
 
obj {
 
	nam = 'figure_tiger';
 
	disp = translate("tower_locale", 'figure_tiger_disp');
 
	disp2 = translate("tower_locale", 'figure_tiger_disp2');
 
	disp3 = translate("tower_locale", 'figure_tiger_disp3');
 
	inv = function(s)
 
  nam = 'figure_tiger';
 
  disp = translate("tower_locale", 'figure_tiger_disp');
 
  disp2 = translate("tower_locale", 'figure_tiger_disp2');
 
  disp3 = translate("tower_locale", 'figure_tiger_disp3');
 
  inv = function(s)
 
    return translate_now("tower_locale", 'figure_tiger_inv') .. ' ' .. translate_now("tower_locale", 'figure_common_inv');
 
  end;
 
}
 

	
 
obj {
 
	nam = 'figure_lion';
 
  nam = 'figure_lion';
 
  disp = translate("tower_locale", 'figure_lion_disp');
 
	disp2 = translate("tower_locale", 'figure_lion_disp2');
 
	disp3 = translate("tower_locale", 'figure_lion_disp3');
 
  disp2 = translate("tower_locale", 'figure_lion_disp2');
 
  disp3 = translate("tower_locale", 'figure_lion_disp3');
 
  inv = function(s)
 
    return translate_now("tower_locale", 'figure_lion_inv') .. ' ' .. translate_now("tower_locale", 'figure_common_inv');
 
  end;
 
}
 

	
 
obj {
 
	nam = 'figure_knight';
 
  nam = 'figure_knight';
 
  disp = translate("tower_locale", 'figure_knight_disp');
 
	disp2 = translate("tower_locale", 'figure_knight_disp2');
 
	disp3 = translate("tower_locale", 'figure_knight_disp3');
 
  disp2 = translate("tower_locale", 'figure_knight_disp2');
 
  disp3 = translate("tower_locale", 'figure_knight_disp3');
 
  inv = function(s)
 
    return translate_now("tower_locale", 'figure_knight_inv') .. ' ' .. translate_now("tower_locale", 'figure_common_inv');
 
  end;
 
}
 

	
 
obj {
 
	nam = 'figure_tower';
 
  nam = 'figure_tower';
 
  disp = translate("tower_locale", 'figure_tower_disp');
 
	disp2 = translate("tower_locale", 'figure_tower_disp2');
 
	disp3 = translate("tower_locale", 'figure_tower_disp3');
 
  disp2 = translate("tower_locale", 'figure_tower_disp2');
 
  disp3 = translate("tower_locale", 'figure_tower_disp3');
 
  inv = function(s)
 
    return translate_now("tower_locale", 'figure_tower_inv') .. ' ' .. translate_now("tower_locale", 'figure_common_inv');
 
  end;
 
}
 

	
 
room {
 
	nam = 'tower_level_4';
 
	theme = 'tower';
 
	disp = translate("tower_locale", 'tower_level_4_disp');
 
	pic = 'images/tower_level_4.png';
 
	decor = translate("tower_locale", 'tower_level_4_decor');
 
  nam = 'tower_level_4';
 
  theme = 'tower';
 
  disp = translate("tower_locale", 'tower_level_4_disp');
 
  pic = 'images/tower_level_4.png';
 
  decor = translate("tower_locale", 'tower_level_4_decor');
 
  enter = function(s)
 
    if tower_accept_level < 2 then
 
      tower_accept_level = 2;
 
@@ -1575,83 +1578,83 @@ room {
 
    
 
    snd.music('sound/bgm_tower.ogg');
 
  end;
 
	way = {
 
		path {translate("tower_locale", 'transition_downstairs'), "tower_level_3"};
 
		path {"level_4_next_room", translate("tower_locale", 'transition_room'), "tower_level_4_room_2"}:disable();
 
	};
 
  way = {
 
    path {translate("tower_locale", 'transition_downstairs'), "tower_level_3"};
 
    path {"level_4_next_room", translate("tower_locale", 'transition_room'), "tower_level_4_room_2"}:disable();
 
  };
 
}: with {
 
	'tower_walls',
 
	obj {
 
		nam = '#bed';
 
		act = translate("tower_locale", 'tower_level_4_bed');
 
	};
 
	obj {
 
		nam = '#table';
 
		act = translate("tower_locale", 'tower_level_4_table');
 
	};
 
	obj {
 
		nam = '#candelabra';
 
		state = 0;
 
		act = function(s)
 
			if candles_solved then
 
				if not candle_taken then
 
					s.state = 1;
 
					take('candle');
 
					candle_taken = true;
 
					return translate_now("tower_locale", 'tower_candelabra_candle_taken');
 
				else
 
					if s.state == 0 then
 
						return translate_now("tower_locale", 'tower_level_4_chandelier_act');
 
					else
 
						return translate_now("tower_locale", 'tower_level_4_chandelier_act') .. ' ' .. translate_now("tower_locale", 'tower_candelabra_candle_missing');
 
					end;
 
				end;
 
			else
 
				walkin('tower_candelabra');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#tower_4_door';
 
		dsc = function(s)
 
			if _'level_4_next_room':disabled() then
 
  'tower_walls',
 
  obj {
 
    nam = '#bed';
 
    act = translate("tower_locale", 'tower_level_4_bed');
 
  };
 
  obj {
 
    nam = '#table';
 
    act = translate("tower_locale", 'tower_level_4_table');
 
  };
 
  obj {
 
    nam = '#candelabra';
 
    state = 0;
 
    act = function(s)
 
      if candles_solved then
 
        if not candle_taken then
 
          s.state = 1;
 
          take('candle');
 
          candle_taken = true;
 
          return translate_now("tower_locale", 'tower_candelabra_candle_taken');
 
        else
 
          if s.state == 0 then
 
            return translate_now("tower_locale", 'tower_level_4_chandelier_act');
 
          else
 
            return translate_now("tower_locale", 'tower_level_4_chandelier_act') .. ' ' .. translate_now("tower_locale", 'tower_candelabra_candle_missing');
 
          end;
 
        end;
 
      else
 
        walkin('tower_candelabra');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#tower_4_door';
 
    dsc = function(s)
 
      if _'level_4_next_room':disabled() then
 
        return translate_now("tower_locale", 'tower_level_4_door_dsc_locked');
 
			else
 
      else
 
        return translate_now("tower_locale", 'tower_level_4_door_dsc_open');
 
			end;
 
		end;
 
		act = function(s)
 
			if _'level_4_next_room':disabled() then
 
      end;
 
    end;
 
    act = function(s)
 
      if _'level_4_next_room':disabled() then
 
        return translate_now("tower_locale", 'tower_level_4_door_act_locked');
 
			else
 
      else
 
        return translate_now("tower_locale", 'tower_level_4_door_act_open');
 
			end;
 
		end;
 
	};
 
      end;
 
    end;
 
  };
 
}
 

	
 
local candles_offsets = {
 
	{28, 35, 30, 40, -2, -5, 36, 105, -1, -70},
 
	{28, 36, 30, 42, -2, -6, 36, 117, -1, -81},
 
	{28, 36, 30, 44, -2, -5, 36, 128, -1, -92},
 
	{28, 39, 30, 42, -2, -3, 36,  69, -1, -30},
 
	{28, 36, 30, 39, -2, -3, 36, 128, -1, -92},
 
	{28, 36, 30, 39, -2, -3, 36, 117, -1, -81},
 
	{28, 35, 30, 38, -2, -3, 36, 127, -1, -70}
 
  {28, 35, 30, 40, -2, -5, 36, 105, -1, -70},
 
  {28, 36, 30, 42, -2, -6, 36, 117, -1, -81},
 
  {28, 36, 30, 44, -2, -5, 36, 128, -1, -92},
 
  {28, 39, 30, 42, -2, -3, 36,  69, -1, -30},
 
  {28, 36, 30, 39, -2, -3, 36, 128, -1, -92},
 
  {28, 36, 30, 39, -2, -3, 36, 117, -1, -81},
 
  {28, 35, 30, 38, -2, -3, 36, 127, -1, -70}
 
}
 

	
 
function candle(title, note, index, note_name, dx, dy)
 
	return obj {
 
  return obj {
 
    _start = false;
 
    _flame = false;
 
    _blow = false;
 
    _state = 0;
 
    _timeout = 0;
 
		nam = 'candle_' .. note;
 
		dsc = function(s)
 
    nam = 'candle_' .. note;
 
    dsc = function(s)
 
      return '{' .. translate_now("tower_locale", title) .. '}^';
 
    end;
 
		lit = false;
 
    lit = false;
 
    draw = function(s, dst, put_out)
 
      if s._state == 0 then -- no flame
 
        return
 
@@ -1725,114 +1728,117 @@ function candle(title, note, index, note
 
        s._timeout = 0;
 
      end;
 
    end;
 
		act = function(s)
 
    act = function(s)
 
      stop_sound();
 
			sounds[note_name]:play();
 
      sounds[note_name]:play();
 
      p(translate_now("tower_locale", 'tower_level_4_candle_act_lit', {
 
          note=translate_now("note_locale", note_name)
 
      }));
 
			s.lit = true;
 
      s.lit = true;
 
      s._state = 1;
 
      s._timeout = 0;
 
			</i>
 
      
 
      --s:restore();
 
			s:disable();
 
      s:disable();
 

	
 
			if here().notestack[here().playindex] ~= index then
 
				_('tower_candelabra').timerstate = 1;
 
				here().playindex = 1;
 
      if here().notestack[here().playindex] ~= index then
 
        _('tower_candelabra').timerstate = 1;
 
        here().playindex = 1;
 

	
 
				_'candle_c':blow();
 
				_'candle_d':blow();
 
				_'candle_e':blow();
 
				_'candle_f':blow();
 
				_'candle_g':blow();
 
				_'candle_a':blow();
 
				_'candle_b':blow();
 
        _'candle_c':blow();
 
        _'candle_d':blow();
 
        _'candle_e':blow();
 
        _'candle_f':blow();
 
        _'candle_g':blow();
 
        _'candle_a':blow();
 
        _'candle_b':blow();
 

	
 
        pn(translate_now("tower_locale", 'tower_level_4_candle_act_blow'));
 

	
 
				local candelabra = _'tower_candelabra';
 
        local candelabra = _'tower_candelabra';
 

	
 
        p(translate_now("tower_locale", 'tower_level_4_candle_act_sequence'));
 
				for i = 1, 6 do
 
					pr(translate_now("note_locale", candelabra.notesequence[i]) .. ', ');
 
				end;
 
        for i = 1, 6 do
 
          pr(translate_now("note_locale", candelabra.notesequence[i]) .. ', ');
 
        end;
 

	
 
				pr(translate_now("note_locale", candelabra.notesequence[7]) .. '. ');
 
			else
 
				here().playindex = here().playindex + 1;
 
				if here().playindex > 7 then
 
					candles_solved = true;
 
					_('level_4_next_room'):enable();
 
					_('tower_candelabra').timerstate = 4;
 
        pr(translate_now("note_locale", candelabra.notesequence[7]) .. '. ');
 
      else
 
        here().playindex = here().playindex + 1;
 
        if here().playindex > 7 then
 
          candles_solved = true;
 
          _('level_4_next_room'):enable();
 
          _('tower_candelabra').timerstate = 4;
 

	
 
          p(translate_now("tower_locale", 'tower_level_4_candle_act_open'));
 

	
 
					local ns = {
 
						gusts[rnd(#gusts)];
 
						'open_door';
 
					};
 
					stop_sound();
 
					play_sound(ns, 600);
 
          local ns = {
 
            gusts[rnd(#gusts)];
 
            'open_door';
 
          };
 
          stop_sound();
 
          play_sound(ns, 600);
 

	
 
					walk('tower_level_4');
 
				end;
 
			end;
 
		end;
 
		blow = function(s)
 
			s:enable();
 
			s.lit = false;
 
		end;
 
	};
 
          walk('tower_level_4');
 
        end;
 
      end;
 
    end;
 
    blow = function(s)
 
      s:enable();
 
      s.lit = false;
 
    end;
 
  };
 
end;
 

	
 
room {
 
  notes = {
 
		'note_c',
 
		'note_d',
 
		'note_e',
 
		'note_f',
 
		'note_g',
 
		'note_a',
 
		'note_b',
 
	};
 
	text = '';
 
	notestack = {};
 
	notesequence = {};
 
	playindex = 1;
 
	timerstate = 3;
 
	nam = 'tower_candelabra';
 
	disp = translate("tower_locale", 'tower_level_4_disp');
 
	theme = 'tower';
 
	nofollow = true;
 
	dsc = translate("tower_locale", 'tower_candelabra_dsc');
 
    'note_c',
 
    'note_d',
 
    'note_e',
 
    'note_f',
 
    'note_g',
 
    'note_a',
 
    'note_b',
 
  };
 
  text = '';
 
  notestack = {};
 
  notesequence = {};
 
  playindex = 1;
 
  timerstate = 3;
 
  nam = 'tower_candelabra';
 
  disp = translate("tower_locale", 'tower_level_4_disp');
 
  theme = 'tower';
 
  nofollow = true;
 
  dsc = translate("tower_locale", 'tower_candelabra_dsc');
 
  __pic = false;
 
  _pic = false;
 
  _put_out = false;
 
	pic = function(s)
 
  themeInit = function(s)
 
    load_sounds('note_c', 'note_d', 'note_e', 'note_f', 'note_g', 'note_a', 'note_b', 'wind_gust_1', 'wind_gust_2', 'wind_gust_3', 'open_door');
 
  end;
 
  pic = function(s)
 
    return s._pic;
 
  end;
 
	timer = function(s)
 
		if s.timerstate == 1 then
 
			s.timerstate = 6;
 
			sounds[gusts[rnd(#gusts)]]:play();
 
		elseif s.timerstate == 2 then
 
			s.timerstate = 3;
 
			stop_sound();
 
			play_sound(s.notesequence, 600, false);
 
		elseif s.timerstate == 4 then
 
			s.timerstate = 5;
 
			sounds[gusts[rnd(#gusts)]]:play();
 
		elseif s.timerstate == 5 then
 
			s.timerstate = 3;
 
			sounds['open_door']:play();
 
		elseif s.timerstate == 3 then
 
		elseif s.timerstate < 66 then
 
			s.timerstate = s.timerstate + 1;
 
		else 
 
			s.timerstate = 2
 
		end;
 
  timer = function(s)
 
    if s.timerstate == 1 then
 
      s.timerstate = 6;
 
      sounds[gusts[rnd(#gusts)]]:play();
 
    elseif s.timerstate == 2 then
 
      s.timerstate = 3;
 
      stop_sound();
 
      play_sound(s.notesequence, 600, false);
 
    elseif s.timerstate == 4 then
 
      s.timerstate = 5;
 
      sounds[gusts[rnd(#gusts)]]:play();
 
    elseif s.timerstate == 5 then
 
      s.timerstate = 3;
 
      sounds['open_door']:play();
 
    elseif s.timerstate == 3 then
 
    elseif s.timerstate < 66 then
 
      s.timerstate = s.timerstate + 1;
 
    else 
 
      s.timerstate = 2
 
    end;
 
    
 
    s.__pic:copy(s._pic, 0, 0);
 
    local put_out = s._put_out;
 
@@ -1840,54 +1846,54 @@ room {
 
      s._put_out = c:draw(s._pic, put_out) or s._put_out;
 
    end;
 

	
 
		return false;
 
	end;
 
    return false;
 
  end;
 
  initnotes = function(s)
 
    if #s.notestack == 0 then
 
			local ns = {1,2,3,4,5,6,7};
 
      local ns = {1,2,3,4,5,6,7};
 

	
 
			for i = 1, 7 do
 
				local idx = rnd(#ns);
 
				table.insert(s.notestack, ns[idx]);
 
				table.insert(s.notesequence, s.notes[ns[idx]]);
 
				ns[idx] = ns[8 - i];
 
				ns[8 - i] = nil;
 
			end;
 
		end;
 
      for i = 1, 7 do
 
        local idx = rnd(#ns);
 
        table.insert(s.notestack, ns[idx]);
 
        table.insert(s.notesequence, s.notes[ns[idx]]);
 
        ns[idx] = ns[8 - i];
 
        ns[8 - i] = nil;
 
      end;
 
    end;
 

	
 
  end;
 
	enter = function(s)
 
  enter = function(s)
 
    snd.music('sound/amb_tower.ogg');
 
		s:initnotes();
 
    s:initnotes();
 
    
 
		if #s.notesequence == 0 then
 
			s.notesequence = {false, false, false};
 
			for i = 1, 7 do
 
				table.insert(s.notesequence, s.notes[s.notestack[i]][2]);
 
			end;
 
		end;
 
		stop_sound();
 
		play_sound(table.copy(s.notesequence), 600);
 
    if #s.notesequence == 0 then
 
      s.notesequence = {false, false, false};
 
      for i = 1, 7 do
 
        table.insert(s.notesequence, s.notes[s.notestack[i]][2]);
 
      end;
 
    end;
 
    stop_sound();
 
    play_sound(table.copy(s.notesequence), 600);
 

	
 
    p(translate_now("tower_locale", 'tower_candelabra_enter'));
 
		for i = 1, 6 do
 
    for i = 1, 6 do
 
      pr(translate_now("note_locale", s.notesequence[i]) .. ', ');
 
    end;
 

	
 
    pr(translate_now("note_locale", s.notesequence[7]) .. '. ');
 
	end;
 
	obj = {
 
		candle('tower_candle_1', 'c', 1, 'note_c', 57, 70);
 
		candle('tower_candle_2', 'd', 2, 'note_d', 83, 81);
 
		candle('tower_candle_3', 'e', 3, 'note_e', 106, 92);
 
		candle('tower_candle_4', 'f', 4, 'note_f', 143, 30);
 
		candle('tower_candle_5', 'g', 5, 'note_g', 176, 92);
 
		candle('tower_candle_6', 'a', 6, 'note_a', 201, 81);
 
		candle('tower_candle_7', 'b', 7, 'note_b', 226, 70);
 
	};
 
	way = {
 
		path {translate("common_locale", 'back'), 'tower_level_4'};
 
	};
 
  end;
 
  obj = {
 
    candle('tower_candle_1', 'c', 1, 'note_c', 57, 70);
 
    candle('tower_candle_2', 'd', 2, 'note_d', 83, 81);
 
    candle('tower_candle_3', 'e', 3, 'note_e', 106, 92);
 
    candle('tower_candle_4', 'f', 4, 'note_f', 143, 30);
 
    candle('tower_candle_5', 'g', 5, 'note_g', 176, 92);
 
    candle('tower_candle_6', 'a', 6, 'note_a', 201, 81);
 
    candle('tower_candle_7', 'b', 7, 'note_b', 226, 70);
 
  };
 
  way = {
 
    path {translate("common_locale", 'back'), 'tower_level_4'};
 
  };
 
  themeInit = function(s)
 
    timer:set(25);
 
    
 
@@ -1906,104 +1912,107 @@ room {
 
      c:restore();
 
    end;
 
  end;
 
	themeDispose = function(s)
 
		D {'candle_1_fire'};
 
		D {'candle_2_fire'};
 
		D {'candle_3_fire'};
 
		D {'candle_4_fire'};
 
		D {'candle_5_fire'};
 
		D {'candle_6_fire'};
 
		D {'candle_7_fire'};
 
	end;
 
  themeDispose = function(s)
 
    D {'candle_1_fire'};
 
    D {'candle_2_fire'};
 
    D {'candle_3_fire'};
 
    D {'candle_4_fire'};
 
    D {'candle_5_fire'};
 
    D {'candle_6_fire'};
 
    D {'candle_7_fire'};
 
  end;
 
}
 

	
 
room {
 
	nam = 'tower_level_4_room_2';
 
	disp = translate("tower_locale", 'tower_level_4_room_2_disp');
 
	theme = 'tower';
 
	pic = function(s)
 
		if power_on then
 
			return 'images/tower_level_4_room_2_light.png';
 
		else
 
			return 'images/tower_level_4_room_2_dark.png';
 
		end;
 
	end;
 
  nam = 'tower_level_4_room_2';
 
  disp = translate("tower_locale", 'tower_level_4_room_2_disp');
 
  theme = 'tower';
 
  pic = function(s)
 
    if power_on then
 
      return 'images/tower_level_4_room_2_light.png';
 
    else
 
      return 'images/tower_level_4_room_2_dark.png';
 
    end;
 
  end;
 
  enter = function(s)
 
    instead.autosave();
 
  end;
 
	decor = translate("tower_locale", 'tower_level_4_room_2_decor');
 
	way = {
 
		path { translate("tower_locale", 'transition_door'), 'tower_level_4' };
 
		path { translate("tower_locale", 'transition_downstairs'), 'tower_level_3_room_2' };
 
	};
 
  decor = translate("tower_locale", 'tower_level_4_room_2_decor');
 
  way = {
 
    path { translate("tower_locale", 'transition_door'), 'tower_level_4' };
 
    path { translate("tower_locale", 'transition_downstairs'), 'tower_level_3_room_2' };
 
  };
 
  themeInit = function(s)
 
    load_sounds('long_beep', 'short_beep', 'pc_startup');
 
  end;
 
}: with {
 
	obj {
 
		nam = '#ladder';
 
		act = translate("tower_locale", 'tower_level_4_room_2_ladder');
 
	};
 
	obj {
 
		nam = '#servers';
 
		act = function(s)
 
			if power_on then
 
				return translate_now("tower_locale", 'tower_level_4_room_2_servers_powered');
 
			else
 
				return translate_now("tower_locale", 'tower_level_4_room_2_servers');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#table';
 
		act = translate("tower_locale", 'tower_level_4_room_2_table');
 
	};
 
	obj {
 
		nam = '#armchair';
 
		act = translate("tower_locale", 'tower_level_4_room_2_armchair');
 
	};
 
	obj {
 
		assembled = true;
 
		nam = '#computer';
 
		act = function(s)
 
			if s.assembled then
 
				if power_on then
 
					return _('system_unit'):check();
 
				else
 
					return translate_now("tower_locale", 'tower_level_4_room_2_computer_act');
 
				end;
 
			else
 
				walkin('system_unit');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'tool_box' then
 
				s.assembled = not s.assembled;
 
  obj {
 
    nam = '#ladder';
 
    act = translate("tower_locale", 'tower_level_4_room_2_ladder');
 
  };
 
  obj {
 
    nam = '#servers';
 
    act = function(s)
 
      if power_on then
 
        return translate_now("tower_locale", 'tower_level_4_room_2_servers_powered');
 
      else
 
        return translate_now("tower_locale", 'tower_level_4_room_2_servers');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#table';
 
    act = translate("tower_locale", 'tower_level_4_room_2_table');
 
  };
 
  obj {
 
    nam = '#armchair';
 
    act = translate("tower_locale", 'tower_level_4_room_2_armchair');
 
  };
 
  obj {
 
    assembled = true;
 
    nam = '#computer';
 
    act = function(s)
 
      if s.assembled then
 
        if power_on then
 
          return _('system_unit'):check();
 
        else
 
          return translate_now("tower_locale", 'tower_level_4_room_2_computer_act');
 
        end;
 
      else
 
        walkin('system_unit');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'tool_box' then
 
        s.assembled = not s.assembled;
 
        
 
        if s.assembled then
 
          return translate_now("tower_locale", 'tower_level_4_room_2_computer_used_assemble');
 
        else
 
          return translate_now("tower_locale", 'tower_level_4_room_2_computer_used_disassemble');
 
        end;
 
			end;
 
      end;
 
      
 
      return false;
 
		end;
 
	};
 
	obj {
 
		nam = '#monitor';
 
		act = translate("tower_locale", 'tower_level_4_room_2_monitor');
 
	};
 
	obj {
 
		nam = '#manual';
 
		act = function(s)
 
			walkin('terminal_manual');
 
		end;
 
	};
 
    end;
 
  };
 
  obj {
 
    nam = '#monitor';
 
    act = translate("tower_locale", 'tower_level_4_room_2_monitor');
 
  };
 
  obj {
 
    nam = '#manual';
 
    act = function(s)
 
      walkin('terminal_manual');
 
    end;
 
  };
 
}
 

	
 
declare {
 
	sound_index = 1;
 
	sound_data = {};
 
	sound_speed = 600;
 
	sound_last = 0;
 
  sound_index = 1;
 
  sound_data = {};
 
  sound_speed = 600;
 
  sound_last = 0;
 
  
 
  animation_index = 1;
 
  animation_data = false;
 
@@ -2071,7 +2080,7 @@ function animation_tick()
 
        end;
 
        local frame_data = nil;
 
        if animation_item.frame_data then
 
          frame_data = scale_frame_data(animation_item.frame_data)
 
          frame_data = scale_frame_data(animation_item.frame_data, animation_item.w, animation_item.h)
 
        end;
 
        D {
 
          'anim_frames',
 
@@ -2125,6 +2134,9 @@ function animation_set(animation, sync)
 
  {type="anim", image, x, y, w, h, frames, delay, loop} -- show animation with `delay` ms between frames, repeat it `repeat` times
 
  {type="reset", reset: int} -- reset the animation from `reset` item to run it again
 
  ]]
 
  if instead.tiny then
 
    return;
 
  end;
 
  animation_data = animation;
 
  animation_index = 1;
 
  if sync then
 
@@ -2138,65 +2150,65 @@ end;
 

	
 
function sound_tick()
 
  if #sound_data > 0 then
 
		if sound_last + sound_speed <= instead.ticks() then
 
			sound_last = instead.ticks();
 
			if sound_index > #sound_data then
 
				sound_data = {};
 
				return false;
 
			end;
 
    if sound_last + sound_speed <= instead.ticks() then
 
      sound_last = instead.ticks();
 
      if sound_index > #sound_data then
 
        sound_data = {};
 
        return false;
 
      end;
 

	
 
			if sound_data[sound_index] then
 
				sounds[sound_data[sound_index]]:play();
 
			end;
 
      if sound_data[sound_index] then
 
        sounds[sound_data[sound_index]]:play();
 
      end;
 

	
 
			sound_index = sound_index + 1;
 
		end;
 
	end;
 
      sound_index = sound_index + 1;
 
    end;
 
  end;
 
end;
 

	
 
function play_sound(data, speed, immediate)
 
  timer:set(25);
 
	sound_index = 1;
 
	sound_data = data;
 
	sound_speed = speed;
 
	if #sound_data > 0 then
 
		sound_last = instead.ticks();
 
		if immediate then
 
			if sound_data[sound_index] then
 
				sounds[sound_data[sound_index]]:play();
 
			end;
 
			sound_index = sound_index + 1;
 
		end;
 
	end;
 
  sound_index = 1;
 
  sound_data = data;
 
  sound_speed = speed;
 
  if #sound_data > 0 then
 
    sound_last = instead.ticks();
 
    if immediate then
 
      if sound_data[sound_index] then
 
        sounds[sound_data[sound_index]]:play();
 
      end;
 
      sound_index = sound_index + 1;
 
    end;
 
  end;
 
end;
 

	
 
function stop_sound()
 
	sound_data = {};
 
	sound_index = 1;
 
  sound_data = {};
 
  sound_index = 1;
 
end;
 

	
 
function game:timer()
 
	sound_tick();
 
  sound_tick();
 
  animation_tick();
 
	return false;
 
  return false;
 
end;
 

	
 
room {
 
	{
 
		data = false;
 
		sound_index = 1;
 
	};
 
	pic = function(s)
 
		local pic = 'images/terminal_parts/pc_base.png';
 
  {
 
    data = false;
 
    sound_index = 1;
 
  };
 
  pic = function(s)
 
    local pic = 'images/terminal_parts/pc_base.png';
 
    
 
    local motherboard = lookup('#motherboard', _'system_unit');
 
		local cpu = lookup('#cpu', _'system_unit');
 
		local ram = lookup('#ram', _'system_unit');
 
		local slot1 = lookup('#slot1', _'system_unit');
 
		local slot2 = lookup('#slot2', _'system_unit');
 
		local slot3 = lookup('#slot3', _'system_unit');
 
		local slot4 = lookup('#slot4', _'system_unit');
 
		local slots = {slot1, slot2, slot3, slot4};
 
    local cpu = lookup('#cpu', _'system_unit');
 
    local ram = lookup('#ram', _'system_unit');
 
    local slot1 = lookup('#slot1', _'system_unit');
 
    local slot2 = lookup('#slot2', _'system_unit');
 
    local slot3 = lookup('#slot3', _'system_unit');
 
    local slot4 = lookup('#slot4', _'system_unit');
 
    local slots = {slot1, slot2, slot3, slot4};
 
    
 
    if motherboard.device then
 
      pic = pic .. ';images/terminal_parts/motherboard' .. tostring(motherboard.device.slots) .. '.png@26,4'
 
@@ -2238,164 +2250,164 @@ room {
 
    end;
 
    
 
    return pic;
 
	end;
 
	theme = 'tower';
 
	nam = 'system_unit';
 
	nofollow = true;
 
	disp = translate("tower_locale", 'system_unit_disp');
 
	decor = translate("tower_locale", 'system_unit_decor');
 
	enter = function(s)
 
		local motherboard = lookup('#motherboard', _'system_unit');
 
		local cpu = lookup('#cpu', _'system_unit');
 
		local ram = lookup('#ram', _'system_unit');
 
		local slot1 = lookup('#slot1', _'system_unit');
 
		local slot2 = lookup('#slot2', _'system_unit');
 
		local slot3 = lookup('#slot3', _'system_unit');
 
		local slot4 = lookup('#slot4', _'system_unit');
 
		local slots = {slot1, slot2, slot3, slot4};
 
  end;
 
  theme = 'tower';
 
  nam = 'system_unit';
 
  nofollow = true;
 
  disp = translate("tower_locale", 'system_unit_disp');
 
  decor = translate("tower_locale", 'system_unit_decor');
 
  enter = function(s)
 
    local motherboard = lookup('#motherboard', _'system_unit');
 
    local cpu = lookup('#cpu', _'system_unit');
 
    local ram = lookup('#ram', _'system_unit');
 
    local slot1 = lookup('#slot1', _'system_unit');
 
    local slot2 = lookup('#slot2', _'system_unit');
 
    local slot3 = lookup('#slot3', _'system_unit');
 
    local slot4 = lookup('#slot4', _'system_unit');
 
    local slots = {slot1, slot2, slot3, slot4};
 

	
 
		local min = 1;
 
		if motherboard.device then
 
			min = motherboard.device.slots + 1;
 
			cpu:enable();
 
			ram:enable();
 
		else
 
			cpu:disable();
 
			ram:disable();
 
		end;
 
    local min = 1;
 
    if motherboard.device then
 
      min = motherboard.device.slots + 1;
 
      cpu:enable();
 
      ram:enable();
 
    else
 
      cpu:disable();
 
      ram:disable();
 
    end;
 

	
 
		for i = 1, min - 1 do
 
			slots[i]:enable();
 
		end;
 
		for i = min, #slots do
 
			slots[i]:disable();
 
		end;
 
	end;
 
	check = function(s, from_solarscale)
 
		local motherboard = lookup('#motherboard', _'system_unit');
 
		local cpu = lookup('#cpu', _'system_unit');
 
		local ram = lookup('#ram', _'system_unit');
 
		local slot1 = lookup('#slot1', _'system_unit');
 
		local slot2 = lookup('#slot2', _'system_unit');
 
		local slot3 = lookup('#slot3', _'system_unit');
 
		local slot4 = lookup('#slot4', _'system_unit');
 
		local slots = {slot1, slot2, slot3, slot4};
 
		stop_sound();
 
		sounds["pc_startup"]:play();
 
    for i = 1, min - 1 do
 
      slots[i]:enable();
 
    end;
 
    for i = min, #slots do
 
      slots[i]:disable();
 
    end;
 
  end;
 
  check = function(s, from_solarscale)
 
    local motherboard = lookup('#motherboard', _'system_unit');
 
    local cpu = lookup('#cpu', _'system_unit');
 
    local ram = lookup('#ram', _'system_unit');
 
    local slot1 = lookup('#slot1', _'system_unit');
 
    local slot2 = lookup('#slot2', _'system_unit');
 
    local slot3 = lookup('#slot3', _'system_unit');
 
    local slot4 = lookup('#slot4', _'system_unit');
 
    local slots = {slot1, slot2, slot3, slot4};
 
    stop_sound();
 
    sounds["pc_startup"]:play(7);
 

	
 
		if not motherboard.device or not motherboard.device.status then
 
			pc_status = 'fail';
 
			if from_solarscale then
 
    if not motherboard.device or not motherboard.device.status then
 
      pc_status = 'fail';
 
      if from_solarscale then
 
        p(translate_now("tower_locale", 'system_unit_check_fail'));
 
        p(translate_now("tower_locale", 'system_unit_check_no_sound'));
 
				return 'motherboard';
 
			else
 
        return 'motherboard';
 
      else
 
        p(translate_now("tower_locale", 'system_unit_check_turn_on'));
 
        p(translate_now("tower_locale", 'system_unit_check_fail'));
 
        p(translate_now("tower_locale", 'system_unit_check_no_sound'));
 
				return;
 
			end;
 
		end;
 
        return;
 
      end;
 
    end;
 

	
 
		local cpu_valid = false;
 
		if cpu.device and cpu.device.status then
 
			if motherboard.device.cpu == 'CAX' then
 
				cpu_valid = motherboard.device.cpu == cpu.device.slot;
 
			elseif motherboard.device.cpu == 'CVX' then
 
				cpu_valid = cpu.device.slot == 'CVX' or cpu.device.slot == 'CAX';
 
			elseif motherboard.device.cpu == 'CRX' then
 
				cpu_valid = cpu.device.slot ~= 'CXX';
 
			end;
 
		end;
 
    local cpu_valid = false;
 
    if cpu.device and cpu.device.status then
 
      if motherboard.device.cpu == 'CAX' then
 
        cpu_valid = motherboard.device.cpu == cpu.device.slot;
 
      elseif motherboard.device.cpu == 'CVX' then
 
        cpu_valid = cpu.device.slot == 'CVX' or cpu.device.slot == 'CAX';
 
      elseif motherboard.device.cpu == 'CRX' then
 
        cpu_valid = cpu.device.slot ~= 'CXX';
 
      end;
 
    end;
 

	
 
		if not cpu_valid then
 
			play_sound({false, false, false, false, 'long_beep', false, 'short_beep', 'short_beep'}, 300);
 
			pc_status = 'fail';
 
			if from_solarscale then
 
    if not cpu_valid then
 
      play_sound({false, false, false, false, 'long_beep', false, 'short_beep', 'short_beep'}, 300);
 
      pc_status = 'fail';
 
      if from_solarscale then
 
        p(translate_now("tower_locale", 'system_unit_check_fail'));
 
        p(translate_now("tower_locale", 'system_unit_check_1_long_2_short'));
 
				return "cpu";
 
			else
 
        return "cpu";
 
      else
 
        p(translate_now("tower_locale", 'system_unit_check_turn_on'));
 
        p(translate_now("tower_locale", 'system_unit_check_fail'));
 
        p(translate_now("tower_locale", 'system_unit_check_1_long_2_short'));
 
				return;
 
			end
 
		end;
 
        return;
 
      end
 
    end;
 

	
 
		local ram_valid = false;
 
		if ram.device and ram.device.status then
 
			if motherboard.device.ram == 'RKT' then
 
				ram_valid = ram.device.slot == 'RKT';
 
			elseif motherboard.device.ram == 'RST' then
 
				ram_valid = ram.device.slot == 'RKT' or ram.device.slot == 'RST';
 
			elseif motherboard.device.ram == 'RDT' then
 
				ram_valid = true;
 
			end;
 
		end;
 
    local ram_valid = false;
 
    if ram.device and ram.device.status then
 
      if motherboard.device.ram == 'RKT' then
 
        ram_valid = ram.device.slot == 'RKT';
 
      elseif motherboard.device.ram == 'RST' then
 
        ram_valid = ram.device.slot == 'RKT' or ram.device.slot == 'RST';
 
      elseif motherboard.device.ram == 'RDT' then
 
        ram_valid = true;
 
      end;
 
    end;
 

	
 
		if not ram_valid then
 
			play_sound({false, false, false, false, 'short_beep', 'long_beep', false, 'long_beep'}, 300);
 
			pc_status = 'fail';
 
			if from_solarscale then
 
    if not ram_valid then
 
      play_sound({false, false, false, false, 'short_beep', 'long_beep', false, 'long_beep'}, 300);
 
      pc_status = 'fail';
 
      if from_solarscale then
 
        p(translate_now("tower_locale", 'system_unit_check_fail'));
 
        p(translate_now("tower_locale", 'system_unit_check_1_short_2_long'));
 
				return "ram";
 
			else
 
        return "ram";
 
      else
 
        p(translate_now("tower_locale", 'system_unit_check_turn_on'));
 
        p(translate_now("tower_locale", 'system_unit_check_fail'));
 
        p(translate_now("tower_locale", 'system_unit_check_1_short_2_long'));
 
				return;
 
			end;
 
		end;
 
        return;
 
      end;
 
    end;
 

	
 
		-- Now we need to find video, keyboard and network
 
		local video;
 
		local keyboard;
 
		local network;
 
		for i = 1, motherboard.device.slots do
 
			if slots[i].device then
 
				if slots[i].device.ptype == 'video' then
 
					video = slots[i].device;
 
				elseif slots[i].device.ptype == 'keyboard' then
 
					keyboard = slots[i].device;
 
				elseif slots[i].device.ptype == 'network' then
 
					network = slots[i].device;
 
				end;
 
			end;
 
		end;
 
    -- Now we need to find video, keyboard and network
 
    local video;
 
    local keyboard;
 
    local network;
 
    for i = 1, motherboard.device.slots do
 
      if slots[i].device then
 
        if slots[i].device.ptype == 'video' then
 
          video = slots[i].device;
 
        elseif slots[i].device.ptype == 'keyboard' then
 
          keyboard = slots[i].device;
 
        elseif slots[i].device.ptype == 'network' then
 
          network = slots[i].device;
 
        end;
 
      end;
 
    end;
 

	
 
		if not video or not video.status then
 
			play_sound({false, false, false, false,  'long_beep', false, 'short_beep', 'long_beep'}, 300);
 
			pc_status = 'fail';
 
			if from_solarscale then
 
    if not video or not video.status then
 
      play_sound({false, false, false, false,  'long_beep', false, 'short_beep', 'long_beep'}, 300);
 
      pc_status = 'fail';
 
      if from_solarscale then
 
        p(translate_now("tower_locale", 'system_unit_check_fail'));
 
        p(translate_now("tower_locale", 'system_unit_check_1_long_1_short_1_long'));
 
				return "video";
 
			else
 
        return "video";
 
      else
 
        p(translate_now("tower_locale", 'system_unit_check_turn_on'));
 
        p(translate_now("tower_locale", 'system_unit_check_fail'));
 
        p(translate_now("tower_locale", 'system_unit_check_1_long_1_short_1_long'));
 
				return;
 
			end;
 
		end;
 
        return;
 
      end;
 
    end;
 

	
 
		if not keyboard or not keyboard.status then
 
			play_sound({false, false, false, false, 'long_beep', false, 'long_beep', false, 'long_beep'}, 300);
 
			pc_status = 'fail';
 
			if from_solarscale then
 
				p(translate_now("tower_locale", 'system_unit_check_fail'));
 
    if not keyboard or not keyboard.status then
 
      play_sound({false, false, false, false, 'long_beep', false, 'long_beep', false, 'long_beep'}, 300);
 
      pc_status = 'fail';
 
      if from_solarscale then
 
        p(translate_now("tower_locale", 'system_unit_check_fail'));
 
        p(translate_now("tower_locale", 'system_unit_check_3_long'));
 
				return "keyboard";
 
			else
 
        return "keyboard";
 
      else
 
        p(translate_now("tower_locale", 'system_unit_check_turn_on'));
 
        p(translate_now("tower_locale", 'system_unit_check_fail'));
 
        p(translate_now("tower_locale", 'system_unit_check_3_long'));
 
				return;
 
			end;
 
		end;
 
		_('terminal_boot').network = (network and network.status);
 
		_('terminal_boot').graphical = (video.nam == 'gva-rx4');
 
        return;
 
      end;
 
    end;
 
    _('terminal_boot').network = (network and network.status);
 
    _('terminal_boot').graphical = (video.nam == 'gva-rx4');
 
    
 
    pc_status = 'ok';
 
    
 
@@ -2407,720 +2419,721 @@ room {
 
      end;
 
    end;
 

	
 
		if not from_solarscale then
 
			walkin('terminal_boot');
 
		end;
 
	end;
 
	way = {
 
		path {translate("common_locale", 'back'), 'tower_level_4_room_2'}
 
	}
 
    if not from_solarscale then
 
      walkin('terminal_boot');
 
    end;
 
  end;
 
  way = {
 
    path {translate("common_locale", 'back'), 'tower_level_4_room_2'}
 
  }
 
}:with {
 
	obj {
 
		nam = '#motherboard';
 
		device = _'cvx-rst-i3sb';
 
		dsc = function(s)
 
			if s.device then
 
				return '{' .. translate_now("parts_locale", 'motherboard') .. ': ' .. s.device.name .. '}^';
 
			else
 
				return '{' .. translate_now("parts_locale", 'motherboard') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
			end;
 
		end;
 
		act = function(s)
 
			local cpu= lookup('#cpu', _'system_unit');
 
			local ram = lookup('#ram', _'system_unit');
 
			local slot1 = lookup('#slot1', _'system_unit');
 
			local slot2 = lookup('#slot2', _'system_unit');
 
			local slot3 = lookup('#slot3', _'system_unit');
 
			local slot4 = lookup('#slot4', _'system_unit');
 
  obj {
 
    nam = '#motherboard';
 
    device = _'cvx-rst-i3sb';
 
    dsc = function(s)
 
      if s.device then
 
        return '{' .. translate_now("parts_locale", 'motherboard') .. ': ' .. s.device.name .. '}^';
 
      else
 
        return '{' .. translate_now("parts_locale", 'motherboard') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
      end;
 
    end;
 
    act = function(s)
 
      local cpu= lookup('#cpu', _'system_unit');
 
      local ram = lookup('#ram', _'system_unit');
 
      local slot1 = lookup('#slot1', _'system_unit');
 
      local slot2 = lookup('#slot2', _'system_unit');
 
      local slot3 = lookup('#slot3', _'system_unit');
 
      local slot4 = lookup('#slot4', _'system_unit');
 

	
 
			if cpu.device or ram.device or slot1.device or slot2.device or slot3.device or slot4.device then
 
				return translate_now("parts_locale", 'motherboard_not_taken');
 
			end;
 
      if cpu.device or ram.device or slot1.device or slot2.device or slot3.device or slot4.device then
 
        return translate_now("parts_locale", 'motherboard_not_taken');
 
      end;
 

	
 
			if s.device then
 
      if s.device then
 
        local msg = std.call(_(s.device), 'tak');
 
				take(s.device);
 
				s.device = false;
 
        take(s.device);
 
        s.device = false;
 

	
 
				cpu:disable();
 
				ram:disable();
 
				slot1:disable();
 
				slot2:disable();
 
				slot3:disable();
 
				slot4:disable();
 
        cpu:disable();
 
        ram:disable();
 
        slot1:disable();
 
        slot2:disable();
 
        slot3:disable();
 
        slot4:disable();
 
        pc_status = 'fail';
 
				return msg;
 
			end;
 
		end;
 
        return msg;
 
      end;
 
    end;
 

	
 
		used = function(s, o)
 
			if o.part and o.ptype == 'motherboard' then
 
				local cpu = lookup('#cpu', _'system_unit');
 
				local ram = lookup('#ram', _'system_unit');
 
				local slot1 = lookup('#slot1', _'system_unit');
 
				local slot2 = lookup('#slot2', _'system_unit');
 
				local slot3 = lookup('#slot3', _'system_unit');
 
				local slot4 = lookup('#slot4', _'system_unit');
 
				local slots = { slot1, slot2, slot3, slot4 };
 
    used = function(s, o)
 
      if o.part and o.ptype == 'motherboard' then
 
        local cpu = lookup('#cpu', _'system_unit');
 
        local ram = lookup('#ram', _'system_unit');
 
        local slot1 = lookup('#slot1', _'system_unit');
 
        local slot2 = lookup('#slot2', _'system_unit');
 
        local slot3 = lookup('#slot3', _'system_unit');
 
        local slot4 = lookup('#slot4', _'system_unit');
 
        local slots = { slot1, slot2, slot3, slot4 };
 

	
 
				if cpu.device or ram.device or slot1.device or slot2.device or slot3.device or slot4.device then
 
					return translate_now("parts_locale", 'motherboard_not_taken');
 
				end;
 
        if cpu.device or ram.device or slot1.device or slot2.device or slot3.device or slot4.device then
 
          return translate_now("parts_locale", 'motherboard_not_taken');
 
        end;
 

	
 
				if s.device then
 
					return translate_now("parts_locale", 'motherboard_needs_removal');
 
				end;
 
        if s.device then
 
          return translate_now("parts_locale", 'motherboard_needs_removal');
 
        end;
 

	
 
				cpu:enable();
 
				ram:enable();
 
        cpu:enable();
 
        ram:enable();
 

	
 
				for i = 1, o.slots do
 
					slots[i]:enable();
 
				end;
 
        for i = 1, o.slots do
 
          slots[i]:enable();
 
        end;
 

	
 
				remove(o, pl);
 
				s.device = o;
 
        remove(o, pl);
 
        s.device = o;
 
        pc_status = 'fail';
 
				return translate_now("parts_locale", 'motherboard_installed');
 
			end;
 
        return translate_now("parts_locale", 'motherboard_installed');
 
      end;
 
      
 
      return false;
 
		end;
 
	};
 
	obj {
 
		nam = '#cpu';
 
		device = _'mcpu70-cvx-7mhz';
 
		dsc = function(s)
 
			if s.device then
 
				return '{' .. translate_now("parts_locale", 'cpu') .. ': ' .. s.device.name .. '}^';
 
			else
 
				return '{' .. translate_now("parts_locale", 'cpu') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
			end;
 
		end;
 
		act = function(s)
 
			if s.device then
 
    end;
 
  };
 
  obj {
 
    nam = '#cpu';
 
    device = _'mcpu70-cvx-7mhz';
 
    dsc = function(s)
 
      if s.device then
 
        return '{' .. translate_now("parts_locale", 'cpu') .. ': ' .. s.device.name .. '}^';
 
      else
 
        return '{' .. translate_now("parts_locale", 'cpu') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
      end;
 
    end;
 
    act = function(s)
 
      if s.device then
 
        local msg = std.call(_(s.device), 'tak');
 
				take(s.device);
 
				s.device = false;
 
        take(s.device);
 
        s.device = false;
 
        pc_status = 'fail';
 
				return msg;
 
			end;
 
		end;
 
		used = function(s, o)
 
			local motherboard = lookup('#motherboard', _'system_unit');
 
			if o.part and o.ptype == 'cpu' and motherboard.device then
 
				if s.device then
 
					return translate_now("parts_locale", 'cpu_needs_removal');
 
				end;
 
        return msg;
 
      end;
 
    end;
 
    used = function(s, o)
 
      local motherboard = lookup('#motherboard', _'system_unit');
 
      if o.part and o.ptype == 'cpu' and motherboard.device then
 
        if s.device then
 
          return translate_now("parts_locale", 'cpu_needs_removal');
 
        end;
 

	
 
				motherboard = motherboard.device;
 
        motherboard = motherboard.device;
 

	
 
				if (motherboard.cpu == 'CVX' and (o.slot == 'CRX' or o.slot == 'CXX')) or
 
					(motherboard.cpu == 'CRX' and o.slot == 'CXX') or
 
					(motherboard.cpu == 'CAX' and o.slot ~= 'CAX')
 
				then
 
					return translate_now("parts_locale", 'cpu_not_fit');
 
				end;
 
        if (motherboard.cpu == 'CVX' and (o.slot == 'CRX' or o.slot == 'CXX')) or
 
          (motherboard.cpu == 'CRX' and o.slot == 'CXX') or
 
          (motherboard.cpu == 'CAX' and o.slot ~= 'CAX')
 
        then
 
          return translate_now("parts_locale", 'cpu_not_fit');
 
        end;
 

	
 
				remove(o, pl);
 
				s.device = o;
 
        remove(o, pl);
 
        s.device = o;
 
        if lookup('#ram', _'system_unit').device then
 
          pc_status = '';
 
        else
 
          pc_status = 'fail';
 
        end;
 
				return translate_now("parts_locale", 'cpu_installed');
 
			end;
 
        return translate_now("parts_locale", 'cpu_installed');
 
      end;
 
      return false;
 
		end;
 
	};
 
	obj {
 
		nam = '#ram';
 
		device = _'rst-m16-16mb';
 
		dsc = function(s)
 
			if s.device then
 
				return '{' .. translate_now("parts_locale", 'ram') .. ': ' .. s.device.name .. '}^';
 
			else
 
				return '{' .. translate_now("parts_locale", 'ram') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
			end;
 
		end;
 
		act = function(s)
 
			if s.device then
 
    end;
 
  };
 
  obj {
 
    nam = '#ram';
 
    device = _'rst-m16-16mb';
 
    dsc = function(s)
 
      if s.device then
 
        return '{' .. translate_now("parts_locale", 'ram') .. ': ' .. s.device.name .. '}^';
 
      else
 
        return '{' .. translate_now("parts_locale", 'ram') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
      end;
 
    end;
 
    act = function(s)
 
      if s.device then
 
        local msg = std.call(_(s.device), 'tak');
 
				take(s.device);
 
				s.device = false;
 
        take(s.device);
 
        s.device = false;
 
        pc_status = 'fail';
 
				return msg;
 
			end;
 
		end;
 
		used = function(s, o)
 
			local motherboard = lookup('#motherboard', _'system_unit');
 
			if o.part and o.ptype == 'ram' and motherboard.device then
 
				if s.device then
 
					return translate_now("parts_locale", 'ram_needs_removal');
 
				end;
 
        return msg;
 
      end;
 
    end;
 
    used = function(s, o)
 
      local motherboard = lookup('#motherboard', _'system_unit');
 
      if o.part and o.ptype == 'ram' and motherboard.device then
 
        if s.device then
 
          return translate_now("parts_locale", 'ram_needs_removal');
 
        end;
 

	
 
				motherboard = motherboard.device;
 
        motherboard = motherboard.device;
 

	
 
				if  (motherboard.ram == 'RST' and o.slot == 'RDT') or
 
					(motherboard.ram == 'RKT' and o.slot ~= 'RKT')
 
				then
 
					return translate_now("parts_locale", 'ram_not_fit');
 
				end;
 
        if  (motherboard.ram == 'RST' and o.slot == 'RDT') or
 
          (motherboard.ram == 'RKT' and o.slot ~= 'RKT')
 
        then
 
          return translate_now("parts_locale", 'ram_not_fit');
 
        end;
 

	
 
				remove(o, pl);
 
				s.device = o;
 
        remove(o, pl);
 
        s.device = o;
 
        if lookup('#cpu', _'system_unit').device then
 
          pc_status = '';
 
        else
 
          pc_status = 'fail';
 
        end;
 
				return translate_now("parts_locale", 'ram_installed');
 
			end;
 
        return translate_now("parts_locale", 'ram_installed');
 
      end;
 
      return false;
 
		end;
 
	};
 
	obj {
 
		nam = '#slot1';
 
		device = _'tva-rx1';
 
		dsc = function(s)
 
			if s.device then
 
				return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. s.device.name .. '}^';
 
			else
 
				return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
			end;
 
		end;
 
		act = function(s)
 
			if s.device then
 
    end;
 
  };
 
  obj {
 
    nam = '#slot1';
 
    device = _'tva-rx1';
 
    dsc = function(s)
 
      if s.device then
 
        return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. s.device.name .. '}^';
 
      else
 
        return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
      end;
 
    end;
 
    act = function(s)
 
      if s.device then
 
        local msg = std.call(_(s.device), 'tak');
 
				take(s.device);
 
				s.device = false;
 
        take(s.device);
 
        s.device = false;
 
        pc_status = '';
 
				return msg;
 
			end;
 
		end;
 
		used = function(s, o)
 
			local motherboard = lookup('#motherboard', _'system_unit');
 
			if o.part and (o.ptype == 'video' or o.ptype == 'network' or o.ptype == 'keyboard') and motherboard.device then
 
				if s.device then
 
					return translate_now("parts_locale", 'device_needs_removal');
 
				end;
 
        return msg;
 
      end;
 
    end;
 
    used = function(s, o)
 
      local motherboard = lookup('#motherboard', _'system_unit');
 
      if o.part and (o.ptype == 'video' or o.ptype == 'network' or o.ptype == 'keyboard') and motherboard.device then
 
        if s.device then
 
          return translate_now("parts_locale", 'device_needs_removal');
 
        end;
 

	
 
				remove(o, pl);
 
				s.device = o;
 
        remove(o, pl);
 
        s.device = o;
 
        pc_status = '';
 
				return translate_now("parts_locale", 'device_installed');
 
			end;
 
        return translate_now("parts_locale", 'device_installed');
 
      end;
 
      return false;
 
		end;
 
	};
 
	obj {
 
		nam = '#slot2';
 
		device = _'kbc-s';
 
		dsc = function(s)
 
			if s.device then
 
				return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. s.device.name .. '}^';
 
			else
 
				return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
			end;
 
		end;
 
		act = function(s)
 
			if s.device then
 
    end;
 
  };
 
  obj {
 
    nam = '#slot2';
 
    device = _'kbc-s';
 
    dsc = function(s)
 
      if s.device then
 
        return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. s.device.name .. '}^';
 
      else
 
        return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
      end;
 
    end;
 
    act = function(s)
 
      if s.device then
 
        local msg = std.call(_(s.device), 'tak');
 
				take(s.device);
 
				s.device = false;
 
        take(s.device);
 
        s.device = false;
 
        pc_status = '';
 
				return msg;
 
			end;
 
		end;
 
		used = function(s, o)
 
			local motherboard = lookup('#motherboard', _'system_unit');
 
			if o.part and (o.ptype == 'video' or o.ptype == 'network' or o.ptype == 'keyboard') and motherboard.device then
 
				if s.device then
 
					return translate_now("parts_locale", 'device_needs_removal');
 
				end;
 
        return msg;
 
      end;
 
    end;
 
    used = function(s, o)
 
      local motherboard = lookup('#motherboard', _'system_unit');
 
      if o.part and (o.ptype == 'video' or o.ptype == 'network' or o.ptype == 'keyboard') and motherboard.device then
 
        if s.device then
 
          return translate_now("parts_locale", 'device_needs_removal');
 
        end;
 

	
 
				remove(o, pl);
 
				s.device = o;
 
        remove(o, pl);
 
        s.device = o;
 
        pc_status = '';
 
				return translate_now("parts_locale", 'device_installed');
 
			end;
 
        return translate_now("parts_locale", 'device_installed');
 
      end;
 
      return false;
 
		end;
 
	};
 
	obj {
 
		nam = '#slot3';
 
		device = _'fna-100-10mbs_1';
 
		dsc = function(s)
 
			if s.device then
 
				return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. s.device.name .. '}^';
 
			else
 
				return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
			end;
 
		end;
 
		act = function(s)
 
			if s.device then
 
    end;
 
  };
 
  obj {
 
    nam = '#slot3';
 
    device = _'fna-100-10mbs_1';
 
    dsc = function(s)
 
      if s.device then
 
        return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. s.device.name .. '}^';
 
      else
 
        return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
      end;
 
    end;
 
    act = function(s)
 
      if s.device then
 
        local msg = std.call(_(s.device), 'tak');
 
				take(s.device);
 
				s.device = false;
 
        take(s.device);
 
        s.device = false;
 
        pc_status = '';
 
				return msg;
 
			end;
 
		end;
 
		used = function(s, o)
 
			local motherboard = lookup('#motherboard', _'system_unit');
 
			if o.part and (o.ptype == 'video' or o.ptype == 'network' or o.ptype == 'keyboard') and motherboard.device then
 
				if s.device then
 
					return translate_now("parts_locale", 'device_needs_removal');
 
				end;
 
        return msg;
 
      end;
 
    end;
 
    used = function(s, o)
 
      local motherboard = lookup('#motherboard', _'system_unit');
 
      if o.part and (o.ptype == 'video' or o.ptype == 'network' or o.ptype == 'keyboard') and motherboard.device then
 
        if s.device then
 
          return translate_now("parts_locale", 'device_needs_removal');
 
        end;
 

	
 
				remove(o, pl);
 
				s.device = o;
 
        remove(o, pl);
 
        s.device = o;
 
        pc_status = '';
 
				return translate_now("parts_locale", 'device_installed');
 
			end;
 
        return translate_now("parts_locale", 'device_installed');
 
      end;
 
      return false;
 
		end;
 
	};
 
	obj {
 
		nam = '#slot4';
 
		device = false;
 
		dsc = function(s)
 
			if s.device then
 
				return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. s.device.name .. '}^';
 
			else
 
				return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
			end;
 
		end;
 
		act = function(s)
 
			if s.device then
 
    end;
 
  };
 
  obj {
 
    nam = '#slot4';
 
    device = false;
 
    dsc = function(s)
 
      if s.device then
 
        return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. s.device.name .. '}^';
 
      else
 
        return '{' .. translate_now("parts_locale", 'slot') .. ': ' .. translate_now("parts_locale", 'component_not_set') .. '}^';
 
      end;
 
    end;
 
    act = function(s)
 
      if s.device then
 
        local msg = std.call(_(s.device), 'tak');
 
				take(s.device);
 
				s.device = false;
 
        take(s.device);
 
        s.device = false;
 
        pc_status = '';
 
				return msg;
 
			end;
 
		end;
 
		used = function(s, o)
 
			local motherboard = lookup('#motherboard', _'system_unit');
 
			if o.part and (o.ptype == 'video' or o.ptype == 'network' or o.ptype == 'keyboard') and motherboard.device then
 
				if s.device then
 
					return translate_now("parts_locale", 'device_needs_removal');
 
				end;
 
        return msg;
 
      end;
 
    end;
 
    used = function(s, o)
 
      local motherboard = lookup('#motherboard', _'system_unit');
 
      if o.part and (o.ptype == 'video' or o.ptype == 'network' or o.ptype == 'keyboard') and motherboard.device then
 
        if s.device then
 
          return translate_now("parts_locale", 'device_needs_removal');
 
        end;
 

	
 
				remove(o, pl);
 
				s.device = o;
 
        remove(o, pl);
 
        s.device = o;
 
        pc_status = '';
 
				return translate_now("parts_locale", 'device_installed');
 
			end;
 
        return translate_now("parts_locale", 'device_installed');
 
      end;
 
      return false;
 
		end;
 
	};
 
    end;
 
  };
 
}
 

	
 
room {
 
	light = false;
 
	nam = 'tower_level_3_room_2';
 
	disp = translate("tower_locale", 'tower_level_3_room_2_disp');
 
	theme = 'tower';
 
	pic = function(s)
 
		if power_on then
 
			return 'images/tower_level_3_room_2_power.png';
 
		elseif s.light then
 
			return 'images/tower_level_3_room_2_light.png';
 
		else
 
			return 'images/tower_level_3_room_2_dark.png';
 
		end;
 
	end;
 
	decor = function(s)
 
		if s.light then
 
			return translate_now("tower_locale", 'tower_level_3_room_2_decor_lit');
 
		else
 
			return translate_now("tower_locale", 'tower_level_3_room_2_decor_dark');
 
		end;
 
	end;
 
	way = {
 
		path {translate("tower_locale", 'transition_upstairs'), 'tower_level_4_room_2'};
 
		path {'level_3_main_room', translate("tower_locale", 'transition_study'), 'tower_level_3'}:disable();
 
		path {'level_3_room_2_down', translate("tower_locale", 'transition_downstairs'), 'tower_level_2_room_2'}:disable();
 
	};
 
  light = false;
 
  nam = 'tower_level_3_room_2';
 
  disp = translate("tower_locale", 'tower_level_3_room_2_disp');
 
  theme = 'tower';
 
  pic = function(s)
 
    if power_on then
 
      return 'images/tower_level_3_room_2_power.png';
 
    elseif s.light then
 
      return 'images/tower_level_3_room_2_light.png';
 
    else
 
      return 'images/tower_level_3_room_2_dark.png';
 
    end;
 
  end;
 
  decor = function(s)
 
    if s.light then
 
      return translate_now("tower_locale", 'tower_level_3_room_2_decor_lit');
 
    else
 
      return translate_now("tower_locale", 'tower_level_3_room_2_decor_dark');
 
    end;
 
  end;
 
  way = {
 
    path {translate("tower_locale", 'transition_upstairs'), 'tower_level_4_room_2'};
 
    path {'level_3_main_room', translate("tower_locale", 'transition_study'), 'tower_level_3'}:disable();
 
    path {'level_3_room_2_down', translate("tower_locale", 'transition_downstairs'), 'tower_level_2_room_2'}:disable();
 
  };
 
}:with {
 
	obj {
 
		nam = '#ladder';
 
		act = translate("tower_locale", 'tower_level_3_room_2_ladder_up');
 
	};
 
	obj {
 
		nam = '#ladder_down';
 
		act = translate("tower_locale", 'tower_level_3_room_2_ladder_down');
 
	};
 
	obj {
 
		nam = '#floor';
 
		act = translate("tower_locale", 'tower_level_3_room_2_floor');
 
	};
 
	obj {
 
		nam = '#walls';
 
		act = translate("tower_locale", 'tower_level_3_room_2_walls');
 
	};
 
	obj {
 
		nam = '#ceiling';
 
		act = function(s)
 
			if power_on then
 
				return translate_now("tower_locale", 'tower_level_3_room_2_ceiling_power');
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_room_2_ceiling');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#darkness';
 
		used = function(s, o)
 
			if o^'potion_light' then
 
				remove('potion_light', pl);
 
				here().light = true;
 
				_'#door':enable();
 
				_'#shelves':enable();
 
				_'level_3_room_2_down':enable()
 
				s:disable();
 
				return translate_now("tower_locale", 'potion_light_inv_used');
 
			elseif o^'candle' then
 
				return translate_now("tower_locale", 'tower_level_3_room_2_darkness_used_candle');
 
			end;
 
			return false;
 
		end;
 
		act = translate("tower_locale", 'tower_level_3_room_2_darkness');
 
	};
 
	obj {
 
		nam = '#door';
 
		dsc = function(s)
 
			if _ 'level_3_main_room':disabled() then
 
				return translate_now("tower_locale", 'tower_level_3_room_2_door_dsc_closed');
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_room_2_door_dsc_opened');
 
			end;
 
		end;
 
		act = function(s)
 
			if _ 'level_3_main_room':disabled() then
 
				_ 'level_3_main_room':enable();
 
				_('level_3_next_room', 'tower_level_3'):enable();
 
				_('level_3_room_2_door', 'tower_level_3'):enable();
 
				return translate_now("tower_locale", 'tower_level_3_room_2_door_act_open');
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_room_2_door_act_opened');
 
			end;
 
		end;
 
	}:disable();
 
	obj {
 
		state = 0;
 
		nam = '#shelves';
 
		act = function(s)
 
			if not here().light then
 
				return translate_now("tower_locale", 'tower_level_3_room_2_darkness');
 
			elseif s.state == 0 then
 
				s.state = 1;
 
				take('tool_box');
 
				take('emerald');
 
				_'part_box':enable();
 
				return translate_now("tower_locale", 'tower_level_3_room_2_shelves_act_first');
 
			else
 
				return translate_now("tower_locale", 'tower_level_3_room_2_shelves_act_second');
 
			end;
 
		end;
 
	};
 
	'part_box';
 
  obj {
 
    nam = '#ladder';
 
    act = translate("tower_locale", 'tower_level_3_room_2_ladder_up');
 
  };
 
  obj {
 
    nam = '#ladder_down';
 
    act = translate("tower_locale", 'tower_level_3_room_2_ladder_down');
 
  };
 
  obj {
 
    nam = '#floor';
 
    act = translate("tower_locale", 'tower_level_3_room_2_floor');
 
  };
 
  obj {
 
    nam = '#walls';
 
    act = translate("tower_locale", 'tower_level_3_room_2_walls');
 
  };
 
  obj {
 
    nam = '#ceiling';
 
    act = function(s)
 
      if power_on then
 
        return translate_now("tower_locale", 'tower_level_3_room_2_ceiling_power');
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_room_2_ceiling');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#darkness';
 
    used = function(s, o)
 
      if o^'potion_light' then
 
        remove('potion_light', pl);
 
        here().light = true;
 
        _'#door':enable();
 
        _'#shelves':enable();
 
        _'level_3_room_2_down':enable()
 
        s:disable();
 
        return translate_now("tower_locale", 'potion_light_inv_used');
 
      elseif o^'candle' then
 
        return translate_now("tower_locale", 'tower_level_3_room_2_darkness_used_candle');
 
      end;
 
      return false;
 
    end;
 
    act = translate("tower_locale", 'tower_level_3_room_2_darkness');
 
  };
 
  obj {
 
    nam = '#door';
 
    dsc = function(s)
 
      if _ 'level_3_main_room':disabled() then
 
        return translate_now("tower_locale", 'tower_level_3_room_2_door_dsc_closed');
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_room_2_door_dsc_opened');
 
      end;
 
    end;
 
    act = function(s)
 
      if _ 'level_3_main_room':disabled() then
 
        _ 'level_3_main_room':enable();
 
        _('level_3_next_room', 'tower_level_3'):enable();
 
        _('level_3_room_2_door', 'tower_level_3'):enable();
 
        return translate_now("tower_locale", 'tower_level_3_room_2_door_act_open');
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_room_2_door_act_opened');
 
      end;
 
    end;
 
  }:disable();
 
  obj {
 
    state = 0;
 
    nam = '#shelves';
 
    act = function(s)
 
      if not here().light then
 
        return translate_now("tower_locale", 'tower_level_3_room_2_darkness');
 
      elseif s.state == 0 then
 
        s.state = 1;
 
        take('tool_box');
 
        take('emerald');
 
        _'part_box':enable();
 
        return translate_now("tower_locale", 'tower_level_3_room_2_shelves_act_first');
 
      else
 
        return translate_now("tower_locale", 'tower_level_3_room_2_shelves_act_second');
 
      end;
 
    end;
 
  };
 
  'part_box';
 
}
 

	
 
room {
 
	nam = 'tower_level_2_room_2';
 
	theme = 'tower';
 
	pic = function(s)
 
		if power_on then
 
			return 'images/tower_level_2_room_2_light.png';
 
		else
 
			return 'images/tower_level_2_room_2_dark.png';
 
		end;
 
	end;
 
	disp = translate("tower_locale", 'tower_level_2_room_2_disp');
 
	onenter = function(s)
 
		if have('protection_suit', pl) then
 
			put('protection_suit', 'tower_level_2_airlock_cabinet');
 
			remove('protection_suit', pl);
 
			return translate_now("tower_locale", 'tower_level_2_remove_suit');
 
		end;
 
	end;
 
	decor = function(s)
 
  nam = 'tower_level_2_room_2';
 
  theme = 'tower';
 
  pic = function(s)
 
    if power_on then
 
      return 'images/tower_level_2_room_2_light.png';
 
    else
 
      return 'images/tower_level_2_room_2_dark.png';
 
    end;
 
  end;
 
  disp = translate("tower_locale", 'tower_level_2_room_2_disp');
 
  onenter = function(s)
 
    if have('protection_suit', pl) then
 
      put('protection_suit', 'tower_level_2_airlock_cabinet');
 
      remove('protection_suit', pl);
 
      return translate_now("tower_locale", 'tower_level_2_remove_suit');
 
    end;
 
  end;
 
  decor = function(s)
 
    p(translate_now("tower_locale", 'tower_level_2_room_2_decor'));
 
		if power_on then
 
			p(translate_now("tower_locale", 'tower_level_2_room_2_decor_power'));
 
		else
 
			p(translate_now("tower_locale", 'tower_level_2_room_2_decor_nopower'));
 
		end;
 
	end;
 
	way = {
 
		path {translate("tower_locale", 'transition_upstairs'), 'tower_level_3_room_2'};
 
		path {translate("tower_locale", 'transition_airlock'), 'tower_level_2_airlock'};
 
		path {'level_2_main_room', translate("tower_locale", 'transition_lab'), 'tower_level_2'}:disable();
 
		path {translate("tower_locale", 'transition_downstairs'), 'tower_level_1_room_2'};
 
	}
 
    if power_on then
 
      p(translate_now("tower_locale", 'tower_level_2_room_2_decor_power'));
 
    else
 
      p(translate_now("tower_locale", 'tower_level_2_room_2_decor_nopower'));
 
    end;
 
  end;
 
  way = {
 
    path {translate("tower_locale", 'transition_upstairs'), 'tower_level_3_room_2'};
 
    path {translate("tower_locale", 'transition_airlock'), 'tower_level_2_airlock'};
 
    path {'level_2_main_room', translate("tower_locale", 'transition_lab'), 'tower_level_2'}:disable();
 
    path {translate("tower_locale", 'transition_downstairs'), 'tower_level_1_room_2'};
 
  }
 
}:with {
 
	'tower_walls';
 
	obj {
 
		nam = '#floor';
 
		act = translate("tower_locale", 'tower_level_2_room_2_floor');
 
	};
 
	obj {
 
		nam = '#ceiling';
 
		act = translate("tower_locale", 'tower_level_2_room_2_ceiling');
 
	};
 
	obj {
 
		nam = '#lamps';
 
		act = translate("tower_locale", 'tower_level_2_room_2_lamps');
 
	};
 
	obj {
 
		nam = '#emergency_lamps';
 
		act = translate("tower_locale", 'tower_level_2_room_2_emergency_lamps');
 
	};
 
	obj {
 
		nam = '#reactor_door';
 
		dsc = translate("tower_locale", 'tower_level_2_room_2_reactor_door_dsc');
 
		act = translate("tower_locale", 'tower_level_2_room_2_reactor_door_act');
 
	};
 
	obj {
 
		nam = '#control_panel';
 
		dsc = translate("tower_locale", 'tower_level_2_room_2_control_panel_dsc');
 
		act = function(s)
 
			walkin('reactor_control_panel');
 
		end;
 
	};
 
	obj {
 
		nam = '#next_door';
 
		dsc = function(s)
 
			if _'level_2_main_room':disabled() then
 
				return translate_now("tower_locale", 'tower_level_2_room_2_next_door_dsc_closed');
 
			else
 
				return translate_now("tower_locale", 'tower_level_2_room_2_next_door_dsc_open');
 
			end;
 
		end;
 
		act = function(s)
 
			if _'level_2_main_room':disabled() then
 
				_'level_2_main_room':enable();
 
				_'level_2_next_room':enable();
 
				return translate_now("tower_locale", 'tower_level_2_room_2_next_door_act_closed');
 
			else
 
				return translate_now("tower_locale", 'tower_level_2_room_2_next_door_act_open');
 
			end;
 
		end;
 
	}
 
  'tower_walls';
 
  obj {
 
    nam = '#floor';
 
    act = translate("tower_locale", 'tower_level_2_room_2_floor');
 
  };
 
  obj {
 
    nam = '#ceiling';
 
    act = translate("tower_locale", 'tower_level_2_room_2_ceiling');
 
  };
 
  obj {
 
    nam = '#lamps';
 
    act = translate("tower_locale", 'tower_level_2_room_2_lamps');
 
  };
 
  obj {
 
    nam = '#emergency_lamps';
 
    act = translate("tower_locale", 'tower_level_2_room_2_emergency_lamps');
 
  };
 
  obj {
 
    nam = '#reactor_door';
 
    dsc = translate("tower_locale", 'tower_level_2_room_2_reactor_door_dsc');
 
    act = translate("tower_locale", 'tower_level_2_room_2_reactor_door_act');
 
  };
 
  obj {
 
    nam = '#control_panel';
 
    dsc = translate("tower_locale", 'tower_level_2_room_2_control_panel_dsc');
 
    act = function(s)
 
      walkin('reactor_control_panel');
 
    end;
 
  };
 
  obj {
 
    nam = '#next_door';
 
    dsc = function(s)
 
      if _'level_2_main_room':disabled() then
 
        return translate_now("tower_locale", 'tower_level_2_room_2_next_door_dsc_closed');
 
      else
 
        return translate_now("tower_locale", 'tower_level_2_room_2_next_door_dsc_open');
 
      end;
 
    end;
 
    act = function(s)
 
      if _'level_2_main_room':disabled() then
 
        _'level_2_main_room':enable();
 
        _'level_2_next_room':enable();
 
        return translate_now("tower_locale", 'tower_level_2_room_2_next_door_act_closed');
 
      else
 
        return translate_now("tower_locale", 'tower_level_2_room_2_next_door_act_open');
 
      end;
 
    end;
 
  }
 
}
 

	
 
dlg {
 
	theme = 'tower';
 
	nam = 'reactor_control_panel';
 
	disp = translate("tower_locale", 'reactor_control_panel_disp');
 
	pic = function(s)
 
		if power_on then
 
			return 'images/tower_level_2_room_2_light.png';
 
		else
 
			return 'images/tower_level_2_room_2_dark.png';
 
		end;
 
	end;
 
	enter = translate("tower_locale", 'reactor_control_panel_enter');
 
	phr = {
 
		{always=true, translate("tower_locale", 'reactor_control_panel_diagnostic'), function(s)
 
			pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_1'));
 
			pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_2'));
 
			pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_3'));
 
			pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_4'));
 
			if rods_raised then
 
				pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_performance') .. ' 0%');
 
				pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_rods_up'));
 
			elseif rods_enriched then
 
  theme = 'tower';
 
  nam = 'reactor_control_panel';
 
  disp = translate("tower_locale", 'reactor_control_panel_disp');
 
  pic = function(s)
 
    if power_on then
 
      return 'images/tower_level_2_room_2_light.png';
 
    else
 
      return 'images/tower_level_2_room_2_dark.png';
 
    end;
 
  end;
 
  enter = translate("tower_locale", 'reactor_control_panel_enter');
 
  phr = {
 
    {always=true, translate("tower_locale", 'reactor_control_panel_diagnostic'), function(s)
 
      pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_1'));
 
      pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_2'));
 
      pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_3'));
 
      pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_4'));
 
      if rods_raised then
 
        pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_performance') .. ' 0%');
 
        pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_rods_up'));
 
      elseif rods_enriched then
 
        pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_performance') .. ' 101%');
 
				pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_rods_ok'));
 
			else
 
				pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_performance') .. ' 1%');
 
				pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_rods_bad'));
 
			end;
 
		end;};
 
		{cond=function(s) return not rods_raised; end; always=true; translate("tower_locale", 'reactor_control_panel_raise_rods'), function(s)
 
			rods_raised = true;
 
			power_on = false;
 
			return translate_now("tower_locale", 'reactor_control_panel_rods_response')
 
		end;};
 
		{cond=function(s) return rods_raised; end; always=true; translate("tower_locale", 'reactor_control_panel_lower_rods'), function(s)
 
			rods_raised = false;
 
			pr(translate_now("tower_locale", 'reactor_control_panel_rods_response'));
 
			if rods_enriched then
 
				power_on = true;
 
			end;
 
		end;};
 
		{translate("tower_locale", 'reactor_control_panel_leave'), function(s)
 
			walkout();
 
		end;};
 
	};
 
        pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_rods_ok'));
 
      else
 
        pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_performance') .. ' 1%');
 
        pn(translate_now("tower_locale", 'reactor_control_panel_diagnostic_resp_rods_bad'));
 
      end;
 
    end;};
 
    {cond=function(s) return not rods_raised; end; always=true; translate("tower_locale", 'reactor_control_panel_raise_rods'), function(s)
 
      rods_raised = true;
 
      power_on = false;
 
      return translate_now("tower_locale", 'reactor_control_panel_rods_response')
 
    end;};
 
    {cond=function(s) return rods_raised; end; always=true; translate("tower_locale", 'reactor_control_panel_lower_rods'), function(s)
 
      rods_raised = false;
 
      pr(translate_now("tower_locale", 'reactor_control_panel_rods_response'));
 
      if rods_enriched then
 
        power_on = true;
 
      end;
 
    end;};
 
    {translate("tower_locale", 'reactor_control_panel_leave'), function(s)
 
      walkout();
 
    end;};
 
  };
 
}
 

	
 
room {
 
	theme = 'tower';
 
	nam = 'tower_level_2_airlock';
 
	pic = function(s)
 
		if power_on then
 
			return 'images/tower_level_2_room_2_light.png';
 
		else
 
			return 'images/tower_level_2_room_2_dark.png';
 
		end;
 
	end;
 
	disp = translate("tower_locale", 'tower_level_2_airlock_disp');
 
	decor = translate("tower_locale", 'tower_level_2_airlock_decor');
 
	way = {
 
		path {translate("tower_locale", 'transition_control'), 'tower_level_2_room_2'};
 
		path {translate("tower_locale", 'transition_reactor'), 'tower_level_2_reactor'};
 
	};
 
  theme = 'tower';
 
  nam = 'tower_level_2_airlock';
 
  pic = function(s)
 
    if power_on then
 
      return 'images/tower_level_2_room_2_light.png';
 
    else
 
      return 'images/tower_level_2_room_2_dark.png';
 
    end;
 
  end;
 
  disp = translate("tower_locale", 'tower_level_2_airlock_disp');
 
  decor = translate("tower_locale", 'tower_level_2_airlock_decor');
 
  way = {
 
    path {translate("tower_locale", 'transition_control'), 'tower_level_2_room_2'};
 
    path {translate("tower_locale", 'transition_reactor'), 'tower_level_2_reactor'};
 
  };
 
}: with {
 
	obj {
 
		nam = '#walls';
 
		act = translate("tower_locale", 'tower_level_2_airlock_walls');
 
	};
 
	obj {
 
		nam = '#ceiling';
 
		act = translate("tower_locale", 'tower_level_2_airlock_ceiling');
 
	};
 
	obj {
 
		nam = '#lamp';
 
		act = translate("tower_locale", 'tower_level_2_airlock_lamp');
 
	};
 
	obj {
 
		nam = 'tower_level_2_airlock_cabinet';
 
		dsc = translate("tower_locale", 'tower_level_2_airlock_locker_dsc');
 
		act = translate("tower_locale", 'tower_level_2_airlock_locker_act');
 
		used = function(s, o)
 
			if o^'protection_suit' then
 
				put('protection_suit', 'tower_level_2_airlock_cabinet');
 
				remove('protection_suit', pl);
 
				return translate_now("tower_locale", 'tower_level_2_remove_suit');
 
			end;
 
  obj {
 
    nam = '#walls';
 
    act = translate("tower_locale", 'tower_level_2_airlock_walls');
 
  };
 
  obj {
 
    nam = '#ceiling';
 
    act = translate("tower_locale", 'tower_level_2_airlock_ceiling');
 
  };
 
  obj {
 
    nam = '#lamp';
 
    act = translate("tower_locale", 'tower_level_2_airlock_lamp');
 
  };
 
  obj {
 
    nam = 'tower_level_2_airlock_cabinet';
 
    dsc = translate("tower_locale", 'tower_level_2_airlock_locker_dsc');
 
    act = translate("tower_locale", 'tower_level_2_airlock_locker_act');
 
    used = function(s, o)
 
      if o^'protection_suit' then
 
        put('protection_suit', 'tower_level_2_airlock_cabinet');
 
        remove('protection_suit', pl);
 
        return translate_now("tower_locale", 'tower_level_2_remove_suit');
 
      end;
 
      
 
      return false;
 
		end;
 
	}:with {
 
		obj {
 
			nam = 'protection_suit';
 
			disp = translate("tower_locale", 'protection_suit_disp');
 
			dsc = translate("tower_locale", 'protection_suit_dsc');
 
			tak = translate("tower_locale", 'protection_suit_tak');
 
			inv = function(s)
 
				if here()^'tower_level_2_reactor' then
 
					return translate_now("tower_locale", 'protection_suit_inv_not_here');
 
				else
 
					put('protection_suit', here());
 
					remove('protection_suit', pl)
 
					return translate_now("tower_locale", 'protection_suit_inv_remove');
 
				end;
 
			end;
 
		};
 
	};
 
    end;
 
  }:with {
 
    obj {
 
      nam = 'protection_suit';
 
      disp = translate("tower_locale", 'protection_suit_disp');
 
      dsc = translate("tower_locale", 'protection_suit_dsc');
 
      tak = translate("tower_locale", 'protection_suit_tak');
 
      inv = function(s)
 
        if here()^'tower_level_2_reactor' then
 
          return translate_now("tower_locale", 'protection_suit_inv_not_here');
 
        else
 
          put('protection_suit', here());
 
          remove('protection_suit', pl)
 
          return translate_now("tower_locale", 'protection_suit_inv_remove');
 
        end;
 
      end;
 
    };
 
  };
 
}
 

	
 
room {
 
	theme = 'tower';
 
	nam = 'tower_level_2_reactor';
 
	theme = 'tower';
 
	pic = function(s)
 
		if rods_raised then
 
			if not rods_enriched then
 
				return 'images/tower_level_2_reactor_rods_up.png';
 
			end;
 
			
 
			return 'images/tower_level_2_reactor_rods_enriched.png';
 
		elseif power_on then
 
			return 'images/tower_level_2_reactor_on.png';
 
		else
 
			return 'images/tower_level_2_reactor_off.png';
 
		end;
 
	end;
 
	nofollow = function(s)
 
		if here():from()^'tower_level_2_airlock' then
 
			return translate_now("solarscale_locale", 'follow_refuse') .. ' ' ..translate_now("solarscale_locale", 'follow_refuse_reactor');
 
		else
 
			return true;
 
		end;
 
	end;
 
	disp = translate("tower_locale", 'tower_level_2_reactor_disp');
 
	onenter = function(s)
 
		if not have('protection_suit', pl) then
 
			if solarscale_with_me then
 
  theme = 'tower';
 
  nam = 'tower_level_2_reactor';
 
  theme = 'tower';
 
  pic = function(s)
 
    if rods_raised then
 
      if not rods_enriched then
 
        return 'images/tower_level_2_reactor_rods_up.png';
 
      end;
 
      
 
      return 'images/tower_level_2_reactor_rods_enriched.png';
 
    elseif power_on then
 
      return 'images/tower_level_2_reactor_on.png';
 
    else
 
      return 'images/tower_level_2_reactor_off.png';
 
    end;
 
  end;
 
  nofollow = function(s)
 
    if here():from()^'tower_level_2_airlock' then
 
      return translate_now("solarscale_locale", 'follow_refuse') .. ' ' ..translate_now("solarscale_locale", 'follow_refuse_reactor');
 
    else
 
      return true;
 
    end;
 
  end;
 
  disp = translate("tower_locale", 'tower_level_2_reactor_disp');
 
  onenter = function(s)
 
    if not have('protection_suit', pl) then
 
      if solarscale_with_me then
 
        p(translate_now("tower_locale", 'tower_level_2_reactor_enter_solarscale'));
 
				return false;
 
			else
 
        return false;
 
      else
 
        if not irradiated then
 
          load_sounds('irradiated');
 
          sounds['irradiated']:play();
 
        end;
 
				irradiated = true;
 
				return translate_now("tower_locale", 'tower_level_2_reactor_enter_alone');
 
			end;
 
		end;
 
	end;
 
	way = {
 
		path {translate("tower_locale", 'transition_airlock'), 'tower_level_2_airlock'};
 
	};
 
        irradiated = true;
 
        return translate_now("tower_locale", 'tower_level_2_reactor_enter_alone');
 
      end;
 
    end;
 
  end;
 
  way = {
 
    path {translate("tower_locale", 'transition_airlock'), 'tower_level_2_airlock'};
 
  };
 
}: with {
 
	obj {
 
		nam = '#reactor_rods';
 
		dsc = function(s)
 
			if rods_raised then
 
				return translate_now("tower_locale", 'tower_level_2_reactor_rods_dsc_raised');
 
			else
 
				return translate_now("tower_locale", 'tower_level_2_reactor_rods_dsc_lowered');
 
			end;
 
		end;
 
		act = function(s)
 
			if rods_raised then
 
				return translate_now("tower_locale", 'tower_level_2_reactor_rods_act_raised');
 
			else
 
				return translate_now("tower_locale", 'tower_level_2_reactor_rods_act_lowered');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'potion_enrichment' and rods_raised then
 
				remove('potion_enrichment', pl);
 
				rods_enriched = true;
 
				return translate_now("tower_locale", 'tower_level_2_reactor_rods_used');
 
			else
 
				return false;
 
			end;
 
		end;
 
	}
 
  obj {
 
    nam = '#reactor_rods';
 
    dsc = function(s)
 
      if rods_raised then
 
        return translate_now("tower_locale", 'tower_level_2_reactor_rods_dsc_raised');
 
      else
 
        return translate_now("tower_locale", 'tower_level_2_reactor_rods_dsc_lowered');
 
      end;
 
    end;
 
    act = function(s)
 
      if rods_raised then
 
        return translate_now("tower_locale", 'tower_level_2_reactor_rods_act_raised');
 
      else
 
        return translate_now("tower_locale", 'tower_level_2_reactor_rods_act_lowered');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'potion_enrichment' and rods_raised then
 
        remove('potion_enrichment', pl);
 
        rods_enriched = true;
 
        return translate_now("tower_locale", 'tower_level_2_reactor_rods_used');
 
      else
 
        return false;
 
      end;
 
    end;
 
  }
 
}
 

	
 
room {
 
	theme = 'tower';
 
	nam = 'tower_level_1_room_2';
 
	disp = translate("tower_locale", 'tower_level_1_room_2_disp');
 
	pic = 'images/tower_level_1_room_2.png';
 
	decor = translate("tower_locale", 'tower_level_1_room_2_decor');
 
	way = {
 
		path {translate("tower_locale", 'transition_upstairs'), 'tower_level_2_room_2'};
 
		path {'level_1_main_room', translate("tower_locale", 'transition_dining_room'), 'tower_level_1'}:disable();
 
	};
 
  theme = 'tower';
 
  nam = 'tower_level_1_room_2';
 
  disp = translate("tower_locale", 'tower_level_1_room_2_disp');
 
  pic = 'images/tower_level_1_room_2.png';
 
  decor = translate("tower_locale", 'tower_level_1_room_2_decor');
 
  way = {
 
    path {translate("tower_locale", 'transition_upstairs'), 'tower_level_2_room_2'};
 
    path {'level_1_main_room', translate("tower_locale", 'transition_dining_room'), 'tower_level_1'}:disable();
 
  };
 
}: with {
 
	obj {
 
		nam = '#kitchen_sink';
 
		act = translate("tower_locale", 'tower_level_1_room_2_kitchen_sink');
 
		used = function(s, o)
 
			if o ^ 'kettle' then
 
				if o.state == 0 then
 
					o.state = 1;
 
					return translate_now("tower_locale", 'tower_level_1_room_2_kitchen_sink_used_water');
 
				else
 
					return translate_now("tower_locale", 'tower_level_1_room_2_kitchen_sink_used_full');
 
				end;
 
  obj {
 
    nam = '#kitchen_sink';
 
    act = translate("tower_locale", 'tower_level_1_room_2_kitchen_sink');
 
    used = function(s, o)
 
      if o ^ 'kettle' then
 
        if o.state == 0 then
 
          o.state = 1;
 
          return translate_now("tower_locale", 'tower_level_1_room_2_kitchen_sink_used_water');
 
        else
 
          return translate_now("tower_locale", 'tower_level_1_room_2_kitchen_sink_used_full');
 
        end;
 
      else
 
        return false;
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#tabletop';
 
		act = translate("tower_locale", 'tower_level_1_room_2_tabletop');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#tabletop';
 
    act = translate("tower_locale", 'tower_level_1_room_2_tabletop');
 
    used = function(s, o)
 
      if o^'cups' then
 
        remove('cups', me());
 
@@ -3130,12 +3143,12 @@ room {
 
      
 
      return false;
 
    end;
 
	};
 
	obj {
 
		state = 0;
 
		nam = '#cabinets1';
 
		act = function(s)
 
			if solarscale_with_me and s.state == 0 then
 
  };
 
  obj {
 
    state = 0;
 
    nam = '#cabinets1';
 
    act = function(s)
 
      if solarscale_with_me and s.state == 0 then
 
        if not _'solarscale_ally'.tea_asked then
 
          _'solarscale_ally'.tea_found = true;
 
          return translate_now("tower_locale", 'tower_level_1_room_2_cabinets1_act_tea_ask');
 
@@ -3145,645 +3158,247 @@ room {
 
          take('teapot');
 
          return translate_now("tower_locale", 'tower_level_1_room_2_cabinets1_act_tea_and_teapot');
 
        end;
 
			end;
 
		
 
			return translate_now("tower_locale", 'tower_level_1_room_2_cabinets_act_empty');
 
		end;
 
	};
 
	obj {
 
		state = 0;
 
		nam = '#cabinets2';
 
		act = function(s)
 
			if s.state < 3 then
 
				if s.state == 0 then
 
					s.state = 1;
 
					take('password_note');
 
					return translate_now("tower_locale", 'tower_level_1_room_2_cabinets2_act_note');
 
				elseif _'solarscale_ally'.tea_asked then
 
					if s.state == 1 then
 
						s.state = 2;
 
      end;
 
    
 
      return translate_now("tower_locale", 'tower_level_1_room_2_cabinets_act_empty');
 
    end;
 
  };
 
  obj {
 
    state = 0;
 
    nam = '#cabinets2';
 
    act = function(s)
 
      if s.state < 3 then
 
        if s.state == 0 then
 
          s.state = 1;
 
          take('password_note');
 
          return translate_now("tower_locale", 'tower_level_1_room_2_cabinets2_act_note');
 
        elseif _'solarscale_ally'.tea_asked then
 
          if s.state == 1 then
 
            s.state = 2;
 
            take('cups');  
 
						return translate_now("tower_locale", 'tower_level_1_room_2_cabinets2_act_cups');
 
					end;
 
				end;
 
			end;
 
			return translate_now("tower_locale", 'tower_level_1_room_2_cabinets_act_empty');
 
		end;
 
	};
 
	obj {
 
		nam = '#fridge';
 
		act = translate("tower_locale", 'tower_level_1_room_2_fridge');
 
	};
 
	obj {
 
		nam = '#stove';
 
		act = translate("tower_locale", 'tower_level_1_room_2_stove_act');
 
		used = function(s, o)
 
			if o ^ 'kettle' then
 
				if power_on then
 
					if o.state == 0 then
 
						return translate_now("tower_locale", 'kettle_boil_empty');
 
					elseif o.state == 2 then
 
						return translate_now("tower_locale", 'tower_level_1_room_2_stove_used_hot');
 
					else
 
						o.state = 2;
 
						return translate_now("tower_locale", 'tower_level_1_room_2_stove_used_teapot');
 
					end;
 
				else
 
					return translate_now("tower_locale", 'tower_level_1_room_2_stove_used_power');
 
				end;
 
            return translate_now("tower_locale", 'tower_level_1_room_2_cabinets2_act_cups');
 
          end;
 
        end;
 
      end;
 
      return translate_now("tower_locale", 'tower_level_1_room_2_cabinets_act_empty');
 
    end;
 
  };
 
  obj {
 
    nam = '#fridge';
 
    act = translate("tower_locale", 'tower_level_1_room_2_fridge');
 
  };
 
  obj {
 
    nam = '#stove';
 
    act = translate("tower_locale", 'tower_level_1_room_2_stove_act');
 
    used = function(s, o)
 
      if o ^ 'kettle' then
 
        if power_on then
 
          if o.state == 0 then
 
            return translate_now("tower_locale", 'kettle_boil_empty');
 
          elseif o.state == 2 then
 
            return translate_now("tower_locale", 'tower_level_1_room_2_stove_used_hot');
 
          else
 
            o.state = 2;
 
            return translate_now("tower_locale", 'tower_level_1_room_2_stove_used_teapot');
 
          end;
 
        else
 
          return translate_now("tower_locale", 'tower_level_1_room_2_stove_used_power');
 
        end;
 
      else
 
        return false;
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = 'silver_fork';
 
		disp = translate("tower_locale", 'silver_fork_disp');
 
		disp2 = translate("tower_locale", 'silver_fork_disp2');
 
		disp3 = translate("tower_locale", 'silver_fork_disp3');
 
		inv = translate("tower_locale", 'silver_fork_inv');
 
		dsc = translate("tower_locale", 'silver_fork_dsc');
 
		tak = translate("tower_locale", 'silver_fork_tak');
 
	};
 
	obj {
 
		state = 0;
 
		nam = '#door';
 
		dsc = translate("tower_locale", 'tower_level_1_room_2_door_dsc');
 
		act = function(s)
 
			if s.state == 0 then
 
				return translate_now("tower_locale", 'tower_level_1_room_2_door_act_locked');
 
			else
 
				return translate_now("tower_locale", 'tower_level_1_room_2_door_act_open');
 
			end;
 
		end;
 
		used = function(s, o)
 
			if o^'kitchen_key' then
 
				s.state = 1;
 
				remove('kitchen_key', pl);
 
				_'level_1_main_room':enable();
 
				_'level_1_next_room':enable();
 
				return translate_now("tower_locale", 'tower_level_1_room_2_door_used');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = 'silver_fork';
 
    disp = translate("tower_locale", 'silver_fork_disp');
 
    disp2 = translate("tower_locale", 'silver_fork_disp2');
 
    disp3 = translate("tower_locale", 'silver_fork_disp3');
 
    inv = translate("tower_locale", 'silver_fork_inv');
 
    dsc = translate("tower_locale", 'silver_fork_dsc');
 
    tak = translate("tower_locale", 'silver_fork_tak');
 
  };
 
  obj {
 
    state = 0;
 
    nam = '#door';
 
    dsc = translate("tower_locale", 'tower_level_1_room_2_door_dsc');
 
    act = function(s)
 
      if s.state == 0 then
 
        return translate_now("tower_locale", 'tower_level_1_room_2_door_act_locked');
 
      else
 
        return translate_now("tower_locale", 'tower_level_1_room_2_door_act_open');
 
      end;
 
    end;
 
    used = function(s, o)
 
      if o^'kitchen_key' then
 
        s.state = 1;
 
        remove('kitchen_key', pl);
 
        _'level_1_main_room':enable();
 
        _'level_1_next_room':enable();
 
        return translate_now("tower_locale", 'tower_level_1_room_2_door_used');
 
      else
 
        return false;
 
			end;
 
		end;
 
	};
 
	obj {
 
		key_taken = false;
 
		nam = '#hook';
 
		dsc = function(s)
 
			if s.key_taken then
 
				 return translate_now("tower_locale", 'tower_level_1_room_2_hook_dsc_empty');
 
			else
 
				return translate_now("tower_locale", 'tower_level_1_room_2_hook_dsc_key');
 
			end;
 
		end;
 
		act = function(s)
 
			if s.key_taken then
 
				return translate_now("tower_locale", 'tower_level_1_room_2_hook_act_empty');
 
			else
 
				take('kitchen_key');
 
				s.key_taken = true;
 
				return translate_now("tower_locale", 'tower_level_1_room_2_hook_act_key');
 
			end;
 
		end;
 
	};
 
      end;
 
    end;
 
  };
 
  obj {
 
    key_taken = false;
 
    nam = '#hook';
 
    dsc = function(s)
 
      if s.key_taken then
 
         return translate_now("tower_locale", 'tower_level_1_room_2_hook_dsc_empty');
 
      else
 
        return translate_now("tower_locale", 'tower_level_1_room_2_hook_dsc_key');
 
      end;
 
    end;
 
    act = function(s)
 
      if s.key_taken then
 
        return translate_now("tower_locale", 'tower_level_1_room_2_hook_act_empty');
 
      else
 
        take('kitchen_key');
 
        s.key_taken = true;
 
        return translate_now("tower_locale", 'tower_level_1_room_2_hook_act_key');
 
      end;
 
    end;
 
  };
 
  'kettle';
 
}
 

	
 
obj {
 
	nam = 'kitchen_key';
 
	disp = translate("tower_locale", 'kitchen_key_disp');
 
	disp2 = translate("tower_locale", 'kitchen_key_disp2');
 
	disp3 = translate("tower_locale", 'kitchen_key_disp3');
 
	inv = translate("tower_locale", 'kitchen_key_inv');
 
  nam = 'kitchen_key';
 
  disp = translate("tower_locale", 'kitchen_key_disp');
 
  disp2 = translate("tower_locale", 'kitchen_key_disp2');
 
  disp3 = translate("tower_locale", 'kitchen_key_disp3');
 
  inv = translate("tower_locale", 'kitchen_key_inv');
 
};
 

	
 
obj {
 
	nam = 'part_box';
 
	disp = translate("tower_locale", 'part_box_disp');
 
	disp2 = translate("tower_locale", 'part_box_disp2');
 
	disp3 = translate("tower_locale", 'part_box_disp3');
 
	inv = function(s)
 
		walkin('part_box_inside');
 
	end;
 
	used = function(s, o)
 
		if o.part then
 
			remove(o, pl);
 
			put(o, 'part_box_inside');
 
			return translate_now("tower_locale", 'part_box_used');
 
		end;
 
  nam = 'part_box';
 
  disp = translate("tower_locale", 'part_box_disp');
 
  disp2 = translate("tower_locale", 'part_box_disp2');
 
  disp3 = translate("tower_locale", 'part_box_disp3');
 
  inv = function(s)
 
    walkin('part_box_inside');
 
  end;
 
  used = function(s, o)
 
    if o.part then
 
      remove(o, pl);
 
      put(o, 'part_box_inside');
 
      return translate_now("tower_locale", 'part_box_used');
 
    end;
 
    
 
    return false;
 
	end;
 
	dsc = translate("tower_locale", 'part_box_dsc');
 
	tak = translate("tower_locale", 'part_box_tak');
 
  end;
 
  dsc = translate("tower_locale", 'part_box_dsc');
 
  tak = translate("tower_locale", 'part_box_tak');
 
}:disable();
 

	
 
room {
 
	nam = 'part_box_inside';
 
	theme = 'tower';
 
	nofollow = true;
 
	pic = function(s)
 
  nam = 'part_box_inside';
 
  theme = 'tower';
 
  nofollow = true;
 
  pic = function(s)
 
    if from() then
 
      return std.call(from(), 'pic');
 
    else
 
      return
 
    end;
 
	end;
 
	disp = translate("tower_locale", 'part_box_disp');
 
	dsc = translate("tower_locale", 'part_box_inside_dsc');
 
	way = {
 
		path {translate("common_locale", 'back'), function(s) return here():from() end;};
 
	}
 
  end;
 
  disp = translate("tower_locale", 'part_box_disp');
 
  dsc = translate("tower_locale", 'part_box_inside_dsc');
 
  way = {
 
    path {translate("common_locale", 'back'), function(s) return here():from() end;};
 
  }
 
}:with {
 
	'cax-rkt-i2sb',
 
	'cax-rkt-i3sb',
 
	'cax-rst-i2sb',
 
	'cax-rst-i3sb',
 
	'cvx-rst-i2sb',
 
	'cvx-rst-i4sb',
 
	'cvx-rdt-i2sb',
 
	'crx-rst-i3sb',
 
	'crx-rdt-i2sb',
 
	'crx-rdt-i3sb',
 

	
 
	'cpu20-cax-2mhz',
 
	'cpu40-cax-4mhz',
 
	'mcpu50-cvx-5mhz',
 
	'mcpu70-cvx-7mhz_2',
 
	'rcpu100-crx-10mhz',
 
	'rcpu200-crx-20mhz',
 
	'xcpu100-cxx-100mhz',
 

	
 
	'rkt-m20-2mb',
 
	'rkt-m40-4mb',
 
	'rst-m8-8mb',
 
	'rst-m16-16mb_2',
 
	'rdt-m32-32mb',
 
	'rdt-m64-64mb',
 

	
 
	'tva-rx2',
 
	'gva-rx2',
 
	'gva-rx4',
 

	
 
	'fna-200-20mbs',
 
	'fna-100-10mbs_2',
 
	'fna-50-5mbs',
 

	
 
	'kbc-s_2',
 
	'kbc-r',
 
	'kbc-p'
 
}
 
  'cax-rkt-i2sb',
 
  'cax-rkt-i3sb',
 
  'cax-rst-i2sb',
 
  'cax-rst-i3sb',
 
  'cvx-rst-i2sb',
 
  'cvx-rst-i4sb',
 
  'cvx-rdt-i2sb',
 
  'crx-rst-i3sb',
 
  'crx-rdt-i2sb',
 
  'crx-rdt-i3sb',
 

	
 
room {
 
	nam = 'terminal_manual';
 
	theme = 'tower';
 
	pic = function(s)
 
		if power_on then
 
			return 'images/tower_level_4_room_2_light.png';
 
		else
 
			return 'images/tower_level_4_room_2_dark.png';
 
		end;
 
	end;
 
	nofollow = true;
 
	disp = translate("tower_locale", 'terminal_manual_disp');
 
	dsc = translate("tower_locale", 'terminal_manual_dsc');
 
	way = {
 
		path {translate("common_locale", 'back'), 'tower_level_4_room_2'};
 
	}
 
}
 
  'cpu20-cax-2mhz',
 
  'cpu40-cax-4mhz',
 
  'mcpu50-cvx-5mhz',
 
  'mcpu70-cvx-7mhz_2',
 
  'rcpu100-crx-10mhz',
 
  'rcpu200-crx-20mhz',
 
  'xcpu100-cxx-100mhz',
 

	
 
room {
 
	nam = 'service_manual';
 
	theme = 'tower';
 
	nofollow = true;
 
	disp = translate("tower_locale", 'service_manual_disp');
 
	pic = function(s)
 
		if power_on then
 
			return 'images/tower_level_4_room_2_light.png';
 
		else
 
			return 'images/tower_level_4_room_2_dark.png';
 
		end;
 
	end;
 
	dsc = translate("tower_locale", 'service_manual_dsc');
 
	way = {
 
		path {translate("common_locale", 'back'), 'terminal_manual'};
 
	}
 
}
 
  'rkt-m20-2mb',
 
  'rkt-m40-4mb',
 
  'rst-m8-8mb',
 
  'rst-m16-16mb_2',
 
  'rdt-m32-32mb',
 
  'rdt-m64-64mb',
 

	
 
room {
 
	nam = 'troubleshooting_manual';
 
	theme = 'tower';
 
	nofollow = true;
 
	pic = function(s)
 
		if power_on then
 
			return 'images/tower_level_4_room_2_light.png';
 
		else
 
			return 'images/tower_level_4_room_2_dark.png';
 
		end;
 
	end;
 
	disp = translate("tower_locale", 'troubleshooting_manual_disp');
 
	dsc = translate("tower_locale", 'troubleshooting_manual_dsc');
 
	way = {
 
		path {translate("common_locale", 'back'), 'terminal_manual'};
 
	}
 
  'tva-rx2',
 
  'gva-rx2',
 
  'gva-rx4',
 

	
 
  'fna-200-20mbs',
 
  'fna-100-10mbs_2',
 
  'fna-50-5mbs',
 

	
 
  'kbc-s_2',
 
  'kbc-r',
 
  'kbc-p'
 
}
 

	
 
room {
 
  {
 
    ticks = 0;
 
    ram = 0;
 
  };
 
	nam = 'terminal_boot';
 
	disp = '';
 
  nosave = true;
 
  noautosave = true;
 
	nofollow = true;
 
	noinv = true;
 
	nofading = true;
 
	network = false;
 
	graphical = false;
 
	theme = 'terminal';
 
	themeInit = function(s)
 
		timer:set(25);
 
    
 
    local scale = diretheme.get_scale();
 
		local width, height = diretheme.get_scaled_screen();
 
    
 
    local rc = 0;
 
		if s.graphical then
 
      local animx = math.max(math.floor((width - 640) / 2) + 20, 20) * scale;
 
      local animy = math.max(height - 734, 26) * scale;
 
      
 
      if height < 540 then
 
        animy = animy - 19 * scale;
 
      end;
 
			D {'logo', 'img', get_sprite('images/terminal/pc_anim.png'), x = animx, y = animy, w=64 * scale, h=64 * scale, frames = 24, z = 1, delay=175, speed=175, animated=true, background=true, process=function(d)
 
				if d.frame_nr == 8 and rc < 2 then
 
					d.frame_nr = 0;
 
					rc = rc + 1;
 
				elseif d.frame_nr == 9 then
 
					rc = 0;
 
				end;
 
			end};
 
		end;
 
    
 
    local x = math.floor((width - 800) / 2);
 
		
 
		local y = height - 193;
 
		if y < 564 then
 
			y = 564;
 
		end;
 
		
 
		local top = height - 193;
 
		if height < 540 then
 
      top = top + 20;
 
  nam = 'terminal_manual';
 
  theme = 'tower';
 
  pic = function(s)
 
    if power_on then
 
      return 'images/tower_level_4_room_2_light.png';
 
    else
 
      return 'images/tower_level_4_room_2_dark.png';
 
    end;
 

	
 
		local delta = math.ceil((y - top) / 8) * scale;
 
		top = top * scale;
 
		
 
    DS {'keyboard', 'img', 'images/terminal/keyboard.png', x = x - 116, y = y, w=1036, h=191, z=0, speed=25, process=function(d)
 
			if s.network and s.ticks >= 128 and delta > 0 then
 
				d.y = d.y - delta;
 
				delta = delta - scale;
 
				if d.y < top then
 
				   d.y = top;
 
           delta = 0;
 
				end;
 
      else
 
        return true;
 
			end;
 
		end};
 
	end;
 
	onenter = function(s)
 
		s.ticks = 0;
 
		s.ram = 0;
 
    local d = getscreen(s.graphical);
 
    d:drop_all();
 
    
 
		stop_sound();
 
	end;
 
	onexit = function(s)
 
		D {'logo'};
 
		D {'keyboard'};
 
		D {'terminal_screen'};
 
	end;
 
	timer = function(s)
 
		if s.ticks ~= 33 then
 
			s.ticks = s.ticks + 1;
 
		else
 
			local ram = lookup('#ram', _'system_unit').device;
 

	
 
			s.ram = s.ram + ram.size * 16;
 
			if s.ram > ram.size * 1024 then
 
				s.ram = ram.size * 1024;
 
				s.ticks = s.ticks + 1;
 
			end;
 
		end;
 
		if s.network then
 
			if s.ticks == 128 then
 
				D {'logo'};
 
			end;
 
			if s.ticks >= 156 then
 
				walk('terminal');
 
			end;
 
		else
 
			if s.ticks >= 300 then
 
				walk('tower_level_4_room_2');
 
        return;
 
			end;
 
      if s.ticks > 112 then
 
        return false;
 
      end;
 
		end;
 
		
 
		s:makescreen();
 
    
 
    return false;
 
	end;
 
	dsc = '';
 
	txt = {};
 
	makescreen = function(s)
 
		local d = getscreen(s.graphical and s.ticks < 128);
 
		if s.ticks < 128 then
 
			local motherboard = lookup('#motherboard', _'system_unit').device;
 
			local cpu = lookup('#cpu', _'system_unit').device;
 
			local ram = lookup('#ram', _'system_unit').device;
 
			
 
			if s.ticks == 1 then
 
				d:insert_line('TOWER BIOS 1.0');
 
			end;
 

	
 
			if s.ticks == 8 then
 
				d:insert_line(translate_now("terminal_locale", 'motherboard') .. ' : ' .. motherboard.name);
 
			end;
 

	
 
			if s.ticks == 16 then
 
				d:insert_line(translate_now("terminal_locale", 'cpu') .. ' : ' .. cpu.name .. ' @ ' .. cpu.speed .. '.0' .. translate_now("terminal_locale", 'mhz'));
 
			end;
 

	
 
			if s.ticks == 24 then
 
				d:insert_line(translate_now("terminal_locale", 'ram') .. ' : '.. ram.name);
 
			end;
 

	
 
			if s.ticks == 32 then
 
				d:insert_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'))
 
			end;
 

	
 
			if s.ticks == 33 then
 
				d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'))
 
			end;
 

	
 
			if s.ticks == 34 then
 
				d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'));
 
			end;
 

	
 
			if s.ticks == 40 then
 
				d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes') .. ' OK');
 
				d:insert_line(' ');
 
			end;
 

	
 
			if s.ticks == 48 then
 
				d:insert_line(translate_now("terminal_locale", 'keyboard') .. ' : ');
 
			end;
 

	
 
			if s.ticks == 56 then
 
				d:replace_line(translate_now("terminal_locale", 'keyboard') .. ' : OK')
 
			end;
 

	
 
			if s.ticks == 64 then
 
				d:insert_line(translate_now("terminal_locale", 'disk') .. ' : ');
 
			end;
 

	
 
			if s.ticks == 72 then
 
				d:replace_line(translate_now("terminal_locale", 'disk') .. ' : ' .. translate_now("terminal_locale", 'missing'));
 
			end;
 

	
 
			if s.ticks == 80 then
 
				d:insert_line(translate_now("terminal_locale", 'network') .. ' : ');
 
			end;
 

	
 
			if s.ticks == 88 then
 
				if s.network then
 
					d:replace_line(translate_now("terminal_locale", 'network') .. ' : OK');
 
				else
 
					d:replace_line(translate_now("terminal_locale", 'network') .. ' : ' .. translate_now("terminal_locale", 'missing'));
 
				end;
 
				d:insert_line(' ');
 
			end;
 

	
 
			if s.ticks == 104 then
 
				d:insert_line(translate_now("terminal_locale", 'boot_from'));
 
			end;
 

	
 
			if s.network then
 
				if s.ticks == 112 then
 
					d:replace_line(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'network_2'));
 
				end;
 

	
 
				if s.ticks == 120 then
 
					d:replace_line(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'network_2') .. '...');
 
				end;
 
			else
 
				if s.ticks == 112 then
 
					d:replace_line(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'no_device'));
 
				end;
 
			end;
 
		elseif s.ticks == 128 then
 
			d:drop_all();
 
			d:insert_line(translate_now("terminal_locale", 'tower_os_line_1'));
 
			d:insert_line(' ');
 
		else
 
			if s.ticks == 136 then
 
				d:insert_line(translate_now("terminal_locale", 'tower_os_line_2'));
 
				d:insert_line(' ');
 
			end;
 

	
 
			if s.ticks == 144 then
 
				d:insert_line(translate_now("terminal_locale", 'tower_os_line_3'));
 
				d:insert_line(' ');
 
			end;
 
		end;
 
	end;
 
  end;
 
  nofollow = true;
 
  disp = translate("tower_locale", 'terminal_manual_disp');
 
  dsc = translate("tower_locale", 'terminal_manual_dsc');
 
  way = {
 
    path {translate("common_locale", 'back'), 'tower_level_4_room_2'};
 
  }
 
}
 

	
 
room {
 
  {
 
    ticks = 0;
 
    ram = 0;
 
  };
 
	nam = 'terminal_boot_failure';
 
	theme = 'terminal';
 
	disp = '';
 
	noinv = true;
 
	nofading = true;
 
	nofollow = true;
 
	graphical = false;
 
  nosave = true;
 
  noautosave = true;
 
	themeInit = function(s)
 
		timer:set(25);
 
    
 
    local scale = diretheme.get_scale();
 
		local width, height = diretheme.get_scaled_screen();
 
    
 
    local rc = 0;
 
		if s.graphical then
 
			local animx = math.max(math.floor((width - 640) / 2) + 20, 20) * scale;
 
      local animy = math.max(height - 734, 26) * scale;
 
      
 
      if height < 540 then
 
        animy = animy - 19 * scale;
 
      end;
 
			D {'logo', 'img', get_sprite('images/terminal/pc_anim.png'), x = animx, y = animy, w=64 * scale, h=64 * scale, frames = 24, z = 1, delay = 175, speed = 175, animated=true, background=true, process=function(d)
 
				if d.frame_nr == 8 and rc < 2 then
 
					d.frame_nr = 0;
 
					rc = rc + 1;
 
				elseif d.frame_nr == 9 then
 
					rc = 0;
 
				end;
 
			end};
 
		end;
 

	
 
		local x = math.floor((width - 800) / 2);
 
		
 
		local y = height - 193;
 
		if height < 540 then
 
      y = y + 20;
 
  nam = 'service_manual';
 
  theme = 'tower';
 
  nofollow = true;
 
  disp = translate("tower_locale", 'service_manual_disp');
 
  pic = function(s)
 
    if power_on then
 
      return 'images/tower_level_4_room_2_light.png';
 
    else
 
      return 'images/tower_level_4_room_2_dark.png';
 
    end;
 
		
 
		DS {'keyboard', 'img', 'images/terminal/keyboard.png', x = x - 116, y = y, w=1036, h=191, z=0};
 
	end;
 
	onenter = function(s)
 
		s.graphical = _('terminal_boot').graphical;    
 
		s.ticks = 0;
 
		s.ram = 0;
 
    local d = getscreen(s.graphical);
 
    d:drop_all();
 
    
 
		stop_sound();
 
	end;
 
	onexit = function(s)    
 
    enableSmoke('images/endings/tower_ruin.png');
 

	
 
		D {'terminal_screen'};
 
		D {'keyboard'};
 
		D {'logo'};
 
	end;
 
	timer = function(s)
 
		if s.ticks ~= 33 then
 
			s.ticks = s.ticks + 1;
 
		else
 
			local ram = lookup('#ram', _'system_unit').device;
 

	
 
			s.ram = s.ram + ram.size * 16;
 
			if s.ram > ram.size * 1024 then
 
				s.ram = ram.size * 1024;
 
				s.ticks = s.ticks + 1;
 
			end;
 
		end;
 

	
 
		if s.ticks == 128 then
 
			D {'logo'};
 
		end;
 
		if s.ticks >= 200 then
 
			walk('ending_formatted');
 
			return;
 
		end;
 
  end;
 
  dsc = translate("tower_locale", 'service_manual_dsc');
 
  way = {
 
    path {translate("common_locale", 'back'), 'terminal_manual'};
 
  }
 
}
 

	
 
		s:makescreen();
 
    
 
    return false;
 
	end;
 
	dsc = '';
 
	txt = '';
 
	makescreen = function(s)
 
		local d = getscreen(s.graphical and s.ticks < 128);
 
		if s.ticks < 128 then
 
			local motherboard = lookup('#motherboard', _'system_unit').device;
 
			local cpu = lookup('#cpu', _'system_unit').device;
 
			local ram = lookup('#ram', _'system_unit').device;
 

	
 
			if s.ticks == 1 then
 
				d:insert_line('TOWER BIOS 1.0');
 
			end;
 

	
 
			if s.ticks == 8 then
 
				d:insert_line(translate_now("terminal_locale", 'motherboard') .. ' : ' .. motherboard.name);
 
			end;
 

	
 
			if s.ticks == 16 then
 
				d:insert_line(translate_now("terminal_locale", 'cpu') .. ' : ' .. cpu.name .. ' @ ' .. cpu.speed .. '.0' .. translate_now("terminal_locale", 'mhz'));
 
			end;
 

	
 
			if s.ticks == 24 then
 
				d:insert_line(translate_now("terminal_locale", 'ram') .. ' : '.. ram.name);
 
			end;
 

	
 
			if s.ticks == 32 then
 
				d:insert_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'))
 
			end;
 

	
 
			if s.ticks == 33 then
 
				d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'))
 
			end;
 

	
 
			if s.ticks == 34 then
 
				d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes'));
 
			end;
 

	
 
			if s.ticks == 40 then
 
				d:replace_line(tostring(s.ram) .. translate_now("terminal_locale", 'kilobytes') .. ' OK');
 
				d:insert_line(' ');
 
			end;
 

	
 
			if s.ticks == 48 then
 
				d:insert_line(translate_now("terminal_locale", 'keyboard') .. ' : ');
 
			end;
 

	
 
if s.ticks == 56 then
 
				d:replace_line(translate_now("terminal_locale", 'keyboard') .. ' : OK')
 
			end;
 

	
 
			if s.ticks == 64 then
 
				d:insert_line(translate_now("terminal_locale", 'disk') .. ' : ');
 
			end;
 

	
 
			if s.ticks == 72 then
 
				d:replace_line(translate_now("terminal_locale", 'disk') .. ' : ' .. translate_now("terminal_locale", 'missing'));
 
			end;
 

	
 
			if s.ticks == 80 then
 
				d:insert_line(translate_now("terminal_locale", 'network') .. ' : ');
 
			end;
 

	
 
			if s.ticks == 88 then
 
				if s.network then
 
					d:replace_line(translate_now("terminal_locale", 'network') .. ' : OK');
 
				else
 
					d:replace_line(translate_now("terminal_locale", 'network') .. ' : ' .. translate_now("terminal_locale", 'missing'));
 
				end;
 
				d:insert_line(' ');
 
			end;
 

	
 
			if s.ticks == 104 then
 
				d:insert_line(translate_now("terminal_locale", 'boot_from'));
 
			end;
 

	
 

	
 
			if s.ticks == 112 then
 
				d:replace_line(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'network_2'));
 
			end;
 

	
 
			if s.ticks == 120 then
 
				d:replace_line(translate_now("terminal_locale", 'boot_from') .. ' ' .. translate_now("terminal_locale", 'network_2') .. '...');
 
			end;
 
		else
 
			-- pr [[No bootable medium found]];
 
			d:drop_all();
 
			d:insert_line(translate_now("terminal_locale", 'no_bootable_medium_found'));
 
		end;
 
	end;
 
room {
 
  nam = 'troubleshooting_manual';
 
  theme = 'tower';
 
  nofollow = true;
 
  pic = function(s)
 
    if power_on then
 
      return 'images/tower_level_4_room_2_light.png';
 
    else
 
      return 'images/tower_level_4_room_2_dark.png';
 
    end;
 
  end;
 
  disp = translate("tower_locale", 'troubleshooting_manual_disp');
 
  dsc = translate("tower_locale", 'troubleshooting_manual_dsc');
 
  way = {
 
    path {translate("common_locale", 'back'), 'terminal_manual'};
 
  }
 
}
translation/en.lua
Show inline comments
 
@@ -11,7 +11,7 @@ set_locale_data {
 
    key_does_not_fit = 'The key does not fit.'
 
  },
 
  link_locale = {
 
		copied = 'Copied',
 
    copied = 'Copied',
 
  },
 
  main_locale = {
 
    empty_act = "I don't know what to do with this.",
 
@@ -33,6 +33,7 @@ set_locale_data {
 
    credits_music = 'Music',
 
    credits_sounds = 'Sounds',
 
    credits_thanks = 'Thank you for playing our game!',
 
    credits_translation = 'Translation',
 
    cursor_scale = 'Cursor Size',
 
    disable = 'Disable',
 
    enable = 'Enable',
 
@@ -49,6 +50,7 @@ set_locale_data {
 
    normal = 'Normal',
 
    padding = 'Padding',
 
    system_settings = 'System Settings',
 
    simplified_animation = 'Simplified Animation',
 
    text_alignment = 'Text Alignment',
 
    text_alignment_justify = 'Justify',
 
    text_alignment_left = 'Left',
 
@@ -158,10 +160,10 @@ set_locale_data {
 
    tutorial_map_hint_leave_treasury = 'Return to the main hall and go to the study from there.',
 
    tutorial_map_inv = 'An ancient map of a small plot of land. A careful cross marks some settlement. I spent centuries looking for this place with no results.',
 
    tutorial_start = 'Welcome!',
 
    tutorial_start_decor = [[				</i>
 
    tutorial_start_decor = [[        
 
      Welcome to the game of "A Dragon and the Tower". This section will get you acquainted with the game and teach you how to play it. ^
 
			The game consists of rooms, each of them has a title and a description. Besides that, a room can contain objects you can interact with. ^
 
			This is also a room. It is titled "Welcome!" and you are reading it's description right now. 
 
      The game consists of rooms, each of them has a title and a description. Besides that, a room can contain objects you can interact with. ^
 
      This is also a room. It is titled "Welcome!" and you are reading it's description right now. 
 
    ]],
 
    tutorial_start_decor_hint = 'We invite you to play a small prologue to A Dragon and the Tower. We will mark instructions and comments with the bold font. Press "Continue" to begin the prologue.',
 
    tutorial_study = 'Lair, Study',
translation/eo.lua
Show inline comments
 
new file 100644
 
--[[
 
  Author: arbtttrn6
 
  Status: In Progress
 
]]
 
set_locale_data {
 
  common_locale = {
 
    back = 'Reen',
 
    continue = 'Daŭrigi',
 
    quotes = '"%1"',
 
    dlg_keep_silent = '[Silenti]',
 
    key_does_not_fit = 'Ŝlosilo ne konvenas.',
 
  },
 
  link_locale = {
 
  copied = 'Kopiita',
 
  },
 
  main_locale = {
 
    empty_act = 'Mi ne konas, kion fari kun ĉi tio.',
 
    empty_inv = 'Ĉi tio estas aĵo. Ĝi ekzistas.',
 
    empty_use_1 = 'Ĉi tio tiamaniere ne funkcias.',
 
    empty_use_2 = 'Ŝajnas, tiel ne sukcesos.',
 
    empty_use_3 = 'Bezone provi ion alian.',
 
    empty_use_4 = 'Ŝajnas, ĉi tio ne funkcios.',
 
    empty_use_5 = 'Ĉi tio ĉi tie ne konvenas.',
 
  },
 
  menu_locale = {
 
    auto_option = 'Mem',
 
    credits_art = 'Grafiko',
 
    credits_author = 'Aŭtoro de ludo',
 
    credits_closed_beta = 'Ferma testo',
 
    credits_engine = 'Ludmotoro',
 
    credits_engine_author = 'Petro Kosih',
 
    credits_fonts = 'Tiparoj',
 
    credits_music = 'Muziko',
 
    credits_sounds = 'Sonoj',
 
    credits_thanks = 'Dankon, ke vi ludas nian ludon!',
 
    credits_translation = 'Traduko',
 
    cursor_scale = 'Skalo de kursoro',
 
    disable = 'Elŝalti',
 
    enable = 'Ŝalti',
 
    extended = 'Granda',
 
    font_scale = 'Skalo de tiparo',
 
    graphic_scale = 'Skalo de grafiko',
 
    interval = 'Literĉena interspaco',
 
    intro = [[Miaj paŝoj laŭte resonas sub volboj de antikvaj kavernoj. Malebenaj ombroj dancas en tremanta magia lumo. En mano mi prenas fragmenton de karto, zorge gardata el nememoreblaj tempoj. Elrulinte antikvan rulaĵon, mi atente ĉirkaŭrigardas skribitajn sur ĝi signojn: arbaron, montaran ĉenon, vojon kaj signitan per kruco vilaĝon. Finfine mi povis difini, kie estas ĉi tio. En vojon!^
 
      Mia korpo disfluas en nebulo kaj revenas en homa aspekto. En rapida irado mi iras al malgranda pordo estanta en unu el muroj. En ĉambro estas nenio, krom ŝtona tablo kaj staranta sur ĝi tekkomputilo -- aĵo, tute necesa en nia tempo ja por drako.^
 
      Bona kartografia programo kaj ĝuste formulita informmendo kreas miraklojn -- jam post iom minutoj mi elflugas el kaverno en mia vera aspekto, etendinte flugilojn renkonte al vento.^
 
      Baldaŭ mi konos, kio atendas min en ĉi vilaĝo!]],
 
    inventory_scale = 'Skalo de inventara tiparo',
 
    language = 'Lingvo',
 
    normal = 'Ordinara',
 
    padding = 'Alineo',
 
    system_settings = 'Sistemaj agordoj',
 
    simplified_animation = 'Plisimpligita animacio';
 
    text_alignment = 'Alkadrigo de teksto',
 
    text_alignment_justify = 'Laŭ larĝo',
 
    text_alignment_left = 'Laŭ maldekstro',
 
    text_width = 'Larĝeco de teksto',
 
    use_text_input = 'Uzi tekstan enigon',
 
    warning = 'Averto',
 
    theme_warning = 'La ludo Drako kaj Turo postulas, ke agordo "propraj etosoj de ludoj" estos ŝaltota. Ĝi ne funkcios sen ĉi agordo. Bonvolu, ŝanĝu agordojn kaj relanĉu aŭ ŝarĝu ludon.',
 
    resolution_warning = 'La ludo Drako kaj Turo postulas distingivon ne malpli ol 640x480. Ludo ne funkcios bone laŭ pli malgranda distingivo. Bonvolu, rigardu, ke viaj agordoj estas seneraraj kaj via komputilo apogas ĉi distingivon, post kio relanĉu aŭ ŝarĝu ludon el sistema menuo (premu esc).',
 
  },
 
  terminal_locale = {
 
    boot_from = 'Ŝargado de',
 
    cpu = 'CPU',
 
    disk = 'Durdisko',
 
    keyboard = 'Klavaro',
 
    kilobytes = 'KB',
 
    mhz = 'MHco',
 
    missing = 'Malinstalita',
 
    motherboard = 'Sistemo',
 
    network = 'Reto',
 
    network_2 = 'reton', -- accusative case
 
    no_bootable_medium_found = 'Ŝargilo malatinga',
 
    no_device = 'ne estas',
 
    ram = 'Memoro',
 
    tower_os_line_1 = 'Lanĉo TOWER OS 1.0...',
 
    tower_os_line_2 = 'TOWER OS Versio 1.0',
 
    tower_os_line_3 = "Enigu 'HELP' por ricevi liston de atingaj operacioj",
 
    -- cat command
 
    cat_line_1 = 'Miaŭ',
 
    cat_line_2 = 'Katoj ĉi tie ne estas',
 
    cat_line_3 = 'Sekreta kata nivelo ne ekzistas',
 
    -- head or tail commands
 
    head_line_1 = 'Ĉi tio estas via, ne mia',
 
    head_line_2 = 'Mi ne havas, sed vi?',
 
    -- more and less commands
 
    more_line_1 = 'Nek pli nek malpli',
 
    -- Lines below are used when player is entering Unix commands instead of DOS ones and are kind of joke/Easter egg
 
    unix_line_1 = 'Mi ne estas Unix',
 
    unix_line_2 = 'Mi ke, similas al Unix por vi?',
 
    unix_line_3 = 'Hoj, kion vi faras?',
 
    unix_line_4 = "Verŝajne vi volis skribi 'format c:'?",
 
    
 
    command_already_started = 'Jam estas lanĉita',
 
    connect_comment = 'REM CONNECT.EXE - Elŝaltis mi por atingo al komandlinio',
 
    critical_failure = 'Sistema eraro: Dosiero ne trovita',
 
    crypt_invalid_key = 'Malvera dosiero de ŝlosilo',
 
    crypt_key_locked = 'Dosiero de ŝlosilo estas gardata de pasvorto',
 
    crypt_key_unset = 'Ŝlosilo ne estas skribita en agorddosiero. Skribu',
 
    crypt_unencrypted = 'Dosiero neĉifrita',
 
    crypt_usage = [[Apliko: CRYPT [dosiero] [dosiero de ŝlosilo]^Deĉifri ĉifritan dosieron]],
 
    invalid_password = 'Malsukcesis deĉifri ŝlosilon. Malvera pasvorto',
 
    invalid_password_2 = 'Malvera pasvorto',
 
    hello_txt = [[Saluton, kara amiko!^Mi provizore elŝaltis bazan ŝelon, CONNECT.EXE.^Simple lanĉu ĝin, por eniri en sistemon.^Plue, kiam ci komprenos konzolon, ci povos^ree ŝalti ĝin.^Pasvorto de baza interfaco estas en DOCS dosierujo en dosiero^PASSWORD.TXT. Certe, ĝi estas ĉifrita.]],
 
    help_cd = 'CD - Ŝanĝi dosierujon',
 
    help_dir = 'DIR - Eligi enhavon de kuranta dosierujo',
 
    help_disk = 'X: - Ŝanĝi diskon al X',
 
    help_connect = 'CONNECT - Konekti sin al baza interfaco de turo',
 
    help_format = 'FORMAT - Formati diskon',
 
    help_help = 'HELP - Montri ĉi informaĵon',
 
    help_print = 'PRINT - Eligi enhavon de teksta dosiero',
 
    help_exit = 'EXIT - Elŝalti konzolon',
 
    help_com_exe = [[Vi povas lanĉi dosierojn .COM kaj .EXE, almontrinte vojon al ili kiel^nomo de komando]],
 
    print_no_file = 'Eraro: Maleble eligi neestantan dosieron',
 
    print_usage = [[Apliko: PRINT [dosiernomo]^Eligi enhavon de teksta dosiero]],
 
    -- If possible, keep phrases below as close to your language MS-DOS translation
 
    -- Also keep lines shorter than 60 characters
 
    bad_command = 'Malvera komanda aŭ dosiera nomo',
 
    binary_data = 'Eraro: Maleble eligi duumajn datumojn',
 
    cd_invalid_directory = "Malvera vojo: '%path%'",
 
    cd_usage = 'Uzo: CD [vojo]',
 
    format_invalid_device = 'Malvera ilo',
 
    format_usage = [[Apliko: FORMAT [disko]^Formati diskon^Singardu: Datumoj neniigotaj]],
 
    formatting_complete = 'Formatado sukcesis',
 
    operation_cancelled = 'Operacio estas nuligita',
 
    query_formatting = 'Formatado:',
 
    query_password = 'Pasvorto:',
 
    query_type_yes = "Enigu 'Yes' por verigi:",
 
  },
 
  tutorial_locale = {
 
    tutorial_box = 'Skatolo',
 
    tutorial_box_hint = 'Por malfermi skatolon per ŝlosilo, uzu ŝlosilo al skatolo. Klaku ŝlosilon, kaj poste skatolon.',
 
    tutorial_box_inv = 'Malgranda skatolo, fermita per seruro',
 
    tutorial_box_used = 'Mi malfermas skatolon kaj prenas el ĝi mapon.',
 
    tutorial_box_used_hint = 'Ĉirkaŭrigardu mapon, por daŭrigi.',
 
    tutorial_disk = 'Disketo kun mapoj',
 
    tutorial_disk_inv = 'Kartografia programo, aĉetita de mi antaŭ iom tagoj. Ĝi havas progresajn povojn de serĉo kompare kun antaŭa versio. Mi esperas, ke ĝi helpos al mi en miaj serĉadoj.',
 
    tutorial_end = 'Gratulojn!',
 
    tutorial_end_decor = 'Mi ingas disketon kaj ŝaltas tekkomputilon. Lanĉinte kartografian programon, mi komencas serĉadon de necesa loko. Ĝuste formulita informmendo kreas miraklojn, kaj jam post iom minutoj mi elflugas el kaverno en mia vera aspekto, etendinte flugilojn renkonte al vento.',
 
    tutorial_end_decor_hint = 'Gratulojn! Vi sukcese finis lernadon kaj povas komenci ĉefan ludon. Estu preta agi kaj pensi mem. Helpiloj plu ne estos.',
 
    tutorial_key = 'Ŝlosilo',
 
    tutorial_key_inv = 'Malgranda ŝlosilo de skatolo. Skatolo devas esti ie en trezorejo.',
 
    tutorial_key_inv_look_for_box = 'Provu trovi skatolon por daŭrigi. Memoru, ke vi povas ree ĉirkaŭrigardi objektojn.',
 
    tutorial_lair = 'Kuŝejo, ĉefa halo',
 
    tutorial_lair_caves_act = 'Mi serĉis ĉi kavernajn reton antaŭ iom jarcentojn. Parto de pasejoj mi devis larĝigi, sed en alio mi konservis iliajn naturajn formojn.',
 
    tutorial_lair_caves_act_hint = 'Klaku objektojn por interago kun ili. Iajn objektojn vi povas preni kun vi kaj uzi, aliajn -- nur ĉirkaŭrigardi.',
 
    tutorial_lair_decor_1 = 'Mia kuŝejo konsistas el si reto el iom {#caves|kavernoj}',
 
    tutorial_lair_decor_2 = 'Nun mi estas en plej granda el ili. Malebenaj muroj kaj altaj ŝtonaj volboj prilumitaj de suno, lumo de kiu libere eniĝas tra granda {#exit|truo en plafono}.',
 
    tutorial_lair_decor_hint_caves = 'Premu prilumitan tekston por ĉirkaŭrigardi kavernojn',
 
    tutorial_lair_decor_hint_study = 'Transiru en kabineton por daŭrigi.',
 
    tutorial_lair_decor_hint_treasury = 'Aparte de ĉefa teksto estas transiraj ligiloj. Nun por vi atingeblaj estas transiroj "En trezorejon" kaj "En kabineton". Transiru en trezorejon por daŭrigi.',
 
    tutorial_lair_enter_disk = 'Al vi necese serĉi disketon kun kartografia programo, por daŭrigi.',
 
    tutorial_lair_enter_start = 'Mi vekiĝas kaj malfermas miajn okulojn. Rapide ĉirkaŭrigardinte kuŝejon, mi komencas transformiĝi. Mia korpo disfluas en griza fumo kaj revenas ree, jam en homan aspekton.',
 
    tutorial_lair_enter_treasury = 'Mi ankoraŭ ne finis miajn farojn ĉi tie.',
 
    tutorial_lair_exit_act = 'Mi kreis ĉi grandan truon por libere forflugi kaj reveni en mian kuŝejon. Certe, ĉi tio ne estas unua eliro el mia hejmo.',
 
    tutorial_map = 'Mapo',
 
    tutorial_map_hint_find_disk = 'Serĉu en trezorejo disketon kun kartografia programo.',
 
    tutorial_map_hint_go_to_study = 'Pasu en kabineton por daŭrigi.',
 
    tutorial_map_hint_leave_treasury = 'Revenu en ĉefan halon kaj pasu de tie en kabineton.',
 
    tutorial_map_inv = 'Antikva mapo de malgranda tera peco. Glata kruca signo montras ian vilaĝon. Mi mortigis jarcentojn por malsukcesaj serĉadoj de ĉi loko.',
 
    tutorial_start = 'Bonvenon!',
 
    tutorial_start_decor = [[        Bonvenon en ludon "Drako kaj Turo". Ĉi sekcio prezentos vin al ĉi ludo kaj lernigos ludi ĝin. ^
 
        Ludo konsistas el ĉambroj, kie ĉiu havas nomon kaj priskribon. Krom tio, en ĉambro povas esti objektoj, kun kiuj vi povas interagi. ^
 
        Ĉi loko ankaŭ estas ĉambro. Ĝi nomiĝas "Bonvenon!", kaj ĝian priskribon vi nun legas.
 
      ]],
 
    tutorial_start_decor_hint = 'Ni aldiras al vi ekludi malgrandan prologon al Drako kaj Turo. Per dika tiparo ni markos instrukciojn kaj komentojn. Premu "Daŭrigi", por komenci prologon.',
 
    tutorial_study = 'Kuŝejo, kabineto',
 
    tutorial_study_decor = 'Malgranda ronda kaverneto plimalpli da tri metroj laŭ alteco kaj ne pli tri metroj en diametro. Ĉe muro mi lokis tablon, sur kiu nun estas {#laptop|tekkomputilo}. Aliris tempo koni, kie estas ĉi loko.',
 
    tutorial_study_decor_hint = 'Por fini lernadon, uzu disketon kun mapoj al tekkomputilo. Por ĉi premu per unu fojo aĵon en inventaro, kaj poste premu aĵon en ĉambro.',
 
    tutorial_study_enter = 'Mi malbezonas ĉi tien.',
 
    tutorial_study_enter_hint = 'Ne ĉiam agoj de via rolulo estos sukcesaj. Atente legu tekstojn, por kompreni, kial ludo ne permesas al vi fari unun aŭ alian agon.',
 
    tutorial_study_laptop_act = 'Tekkomputilo, aĉetita de mi antaŭ iom jaroj. En ĝi ne estas novmodan diskingon por laserdiskoj, kaj ĝi ne estas multe produktiva laŭ nunaj mezuroj, sed por miaj bezonoj ĝi sufiĉas al mi.',
 
    tutorial_to_game = 'Komenci ludon',
 
    tutorial_to_main_hall = 'En ĉefan halon',
 
    tutorial_to_main_menu = 'En ĉefan menuon',
 
    tutorial_to_study = 'En kabineton',
 
    tutorial_to_treasury = 'En trezorejon',
 
    tutorial_treasury = 'Kuŝejo, trezorejo',
 
    tutorial_treasury_books = 'Libra kolekto, kolektita de mi por jarcentoj de vivado en ĉi tiu mondo.',
 
    tutorial_treasury_chests_act_box = 'En unu el kofroj mi trovas malgrandan skatolon.',
 
    tutorial_treasury_chests_act_default = 'Miaj trezoroj!',
 
    tutorial_treasury_chests_act_key = 'Sur unu el kofroj estas malgranda ŝlosilo. Mi prenas ĝin.',
 
    tutorial_treasury_chests_act_key_hint = 'Vi prenis ŝlosilon kaj ĝi aperis en inventaro. Ĉirkaŭrigardu ĝin. Por ĉi klaku ĝin per du fojo.',
 
    tutorial_treasury_decor = 'Ĉi tie mi gardas plej grandvalorajn el havataj de mi aĵoj. Laŭ muroj estas bretaroj, en kiuj estas diversaj {#items|aĵoj}. En centro de halo estas iom grandaj {#chests|kofroj}.',
 
    tutorial_treasury_decor_hint_leave = 'Por daŭrigi, eliru el trezorejo.',
 
    tutorial_treasury_decor_hint_map = 'Por atingi sukceson en ludo, vi devos atente legi tekstojn kaj ĉirkaŭrigardi lokoj, en kiu vi estas. Provu serĉi mapon.',
 
    tutorial_treasury_disks = 'Normaj 3.5 kaj 5.25 colaj disketoj kun programoj por mia tekkomputilo.',
 
    tutorial_treasury_disks_default = 'Ja al mi, al drako, necese iri antaŭen laŭ tempo.',
 
    tutorial_treasury_disks_found = 'Mi facile trovas inter ĝi serĉatan.',
 
    tutorial_treasury_disks_hint = 'Tempo por uzi serĉatajn aĵojn. Eliru el trezorejo.',
 
    tutorial_treasury_items_act = 'Mi rapide ĉirkaŭrigardas bretarojn, plenigitajn de ĉiaspecaj aĵoj: {#books|de libroj}, {#scrolls|de rulaĵoj}, {#records|de gramofondiskoj}, {#disks|de disketoj}, {#paintings|de bildoj} kaj ankaŭ de multe da io.',
 
    tutorial_treasury_no_enter = 'Mi ne havas farojn tie.',
 
    tutorial_treasury_paintings = 'Precipe ĉi tio estas replikoj de plej interesaj al mi laboroj.',
 
    tutorial_treasury_records = 'Relative antaŭnelonga inventaĵo, tamen ricevinte larĝan uzadon. Mi kolektis iom plej interesajn rikordojn por mi.',
 
    tutorial_treasury_scrolls = 'Rulaĵoj kun diversaj skribaĵoj de ĉi tiu mondo. Ĉi tie ilin ne estas multe -- multajn aĵojn mi malsukcesis ricevi.',
 
    tutorial_treasury_scrolls_no_map = 'Mi ne vidas inter ili necesan mapon al mi.',
 
  },
 
  forest_locale = {
 
    above_crater = 'Super kratero',
 
    above_crater_crater = 'Iam en nememoreblaj tempoj ĉi tie falis grandega meteorŝtono. Post pasinta tempo kratero sukcesis kovriĝi per arbaro, sed planedo ankoraŭ ne kuracis ĉi teruran cikatron sur sia faco.',
 
    above_crater_decor = 'Mi flugas super grandega {#glade|kratero}, perdita inter montoj. En kratera centro estas alta {#tower|turo}, sed mi ne povas tie alteriĝi pro {#trees|arboj}. Mi rimarkas malgrandan {#glade|kampeton} en iom centaj metroj de turo.',
 
    above_crater_enter = 'Mi flugas en ĉielon, jam en flugado finante transformiĝadon. Miaj fortaj flugiloj levas min super tero.',
 
    above_crater_glade = 'Malgranda kampo estas proksimo de kratera centro. Se mi alteriĝos ĉi tie kaj transformiĝos, do sen malfacilo aliros al turo.',
 
    above_crater_tower = 'Turo el nigra ŝtono altiĝas super arbaro, estante en centro de giganta kratero. Tura bazo prezentas regulan sesangulon. Ĝi staras strikte vertikale, ĉirkaŭita de arbaro, kiu kvazaŭ ne rimarkas ĝian estanton.',
 
    above_crater_trees = 'Arbaroj estas maloftaj, por permesi al sunan lumstriojn atingi teron, sed alteriĝi inter ili ĝis nun estas probleme.',
 
    above_forest = 'Super arbaro',
 
    above_forest_decor = 'Iafoje svingante per flugiloj, mi flugas super estanta sube {#thicket|arbara densejo}. En okcidento mi vidas {mountains|montaran ĉenon}, irantan suden kaj norden ĝis horizonto. Kiel maldika strio serpentas sube malnova asfalta {#road|vojo}. Laŭ ĝi iras lineoj de {#powerlines|elektrodratoj}. Malmulte apud de vojo mi povas vidi malgrandan {#glade|arbarkampon}. Malvarma {wind|venteto} karesas skvamon, kaj hela somera {sun|suno} flugas tra maldikaj {clouds|cirusoj}.',
 
    above_forest_decor_village = 'Vilaĝon, kiun mi serĉas, devas esti ie ĉi tie.',
 
    above_forest_enter = 'Rapide svinginte per flugiloj, mi saltas de tero kaj flugas supren en ĉielon.',
 
    above_forest_glade_act = 'Malgranda kampeto, kovrita de floroj kaj herboj.',
 
    above_forest_glade_act_first = 'Bona loko por ripozi.',
 
    above_forest_powerlines_act = 'Turoj instalitaj laŭ vojo en egalaj distanco inter ili. Inter ili etenditaj estas dikaj multvoltaj dratoj.',
 
    above_forest_road_act = 'Rompita asfalto memorigas sekiĝinta riverujo. Vojo dezerta, kvazaŭ ĉi loko antaŭlonge forlasita de homoj.',
 
    above_forest_road_act_village = 'Kion se min atendas nur senvivaj fenestroj de senhavaj domoj?',
 
    above_forest_thicket_act = 'Antikvaj arbaroj kiel verda tapiŝo kovras teron. Arbaj altaĵoj apenaŭ balanciĝas de facila venteto. Ja ĉi tie, en alto de iom centaj metroj, mi sentas facilan odoron de pingoj.',
 
    above_near_village_decor = 'Flugilojn portas min super arbara {#road|vojo}. Mi traflugis dek kilometrojn, sed, ŝajnas, ŝanĝiĝis nenio -- sube ĉio same estas senranda {#thicket|arbara densejo}, kaj {mountains|montara ĉeno} okcidente daŭrigas iri foren. Norde, ĉe horizonto, mi rimarkas malgrandan {#village|vilaĝon}.',
 
    above_near_village_enter = 'Mian korpon tegas nebulo kaj post momento en vojo jam staras ne sennoma migrulo, sed potenca drako. Svinginte per flugiloj, mi restigas teron malproksime sube.',
 
    above_near_village_road = 'Vojo aspektas kiel antaŭlonge neuzata. Asfalto en multaj lokoj estas rompita, kaj tra ĝi en diversaj lokoj trabatiĝas verdaj trunketoj.',
 
    above_near_village_thicket = 'Ŝajnas, arbaro estas senranda. Facila venteto balancas arbajn altaĵojn, altigante densan pinglan bonodoron, senteblan ja ĉi tie, en alto de iom cent metroj.',
 
    above_near_village_village = 'De ĉi tie mi povas vidi tavernon kaj urbodomon en centro de vilaĝo. Ĉirkaŭ ili estas dometoj dronantaj en verdaĵo.',
 
    above_village = 'Super vilaĝo',
 
    above_village_decor = 'Super mi same flugas {clouds|cirusoj}, apenaŭ kovrante per si {sun|sunon}, kaj sube estas senranda maro de {#thicket|arbarbo}, kadrita okcidente de {mountains|montara ĉeno}. Malnova asfalta {#road|vojo} iras en {#village|vilaĝon}, kiu estas sub mi.',
 
    above_village_road = 'Certe, lokano malofte uzas ĉi vojon. Vojo estas senhava kaj asfalto ne ricevas riparon.',
 
    above_village_thicket = 'Densa pingla arbaro kiel ringo ĉirkaŭas malgrandas vilaĝon, malsukcese provante formanĝi ĝin.',
 
    above_village_village = 'De ĉi tie mi povas vidi dronantan en verdaĵo vilaĝon. En ĝia centro estas placo, apud kiu estas urbodomo kaj taverno. Norde de vilaĝo estas librarejo.',
 
    above_west = 'Ocidente de vilaĝo',
 
    above_west_crater = 'Grandega kratero, havas dek kilometrojn en diametro. Rigardante kreskantan ene malofta arbareto, kratero estas kreita certe antaŭlonge. En ĝia centro mi vidas nigran turon.',
 
    above_west_decor = '{#village|Vilaĝo} restis malproksime en oriento. Sub mi flugas akutaj {#mountaintops|altaĵoj} kaj ŝtonaj {#mountains|flankoj}, kovritaj de rokaĵoj, kaj fore en okcidento mi vidas grandegan {#crater|krateron}. Lumaj strioj de hela somera {sun|suno}, eniĝantaj tra maldikaj {clouds|cirusoj}, falas sur mia skvamo, varmante ĝin.',
 
    above_west_mountains = 'De ĉi tie mi povas ĉirkaŭrigardi montarajn pintojn. Iaj el ili vere estas altaj, por tuŝi nubojn, nur parto el ili estas kovrita de brilanta neĝo. Multaj montarajn pintojn estas el si ne pli ol glataj ŝtonoj, kiujn provas sinteni malmultenombraj junaj abloj.',
 
    above_west_mountainslopes = 'Krutaj rokaj flankoj ŝajnas senvivaj. Nur maloftaj arboj aŭdacas lanĉi siajn radikojn en ĉi ŝtonaj grandegojn, kiu antaŭĵetiĝis al ĉielo.',
 
    above_west_mountaintops = 'Montaj altaĵoj direktitaj supren, kvazaŭ pintingoj de lancoj. Multa parto el ili -- estas el si ne pli ol glataj ŝtonoj, sen plantaro, sed plej altaj estas kovritaj de brilanta neĝo, kiu brilas en helaj lumaj strioj de somera suno.',
 
    above_west_village = 'De ĉi tie mi ankoraŭ povas vidi plej grandajn domojn de vilaĝo: urbodomon, tavernon kaj librarejon. El taverna fumtubo leviĝas apenaŭ rimarkata fumeto, kaj en ĝia perono sidas junulino.',
 
    box_disp = 'Malnova skatolo',
 
    box_disp2 = 'malnova skatolo',
 
    box_disp3 = 'malnovan skatolon',
 
    box_dsc = 'Sur tablo estas belartigita {skatolo}.',
 
    box_inv = 'Tre malnova skatolo. Mi povas nur konjekti, kio kaŝiĝas ene. Sur skatola fundo estas gravurita ringo kun ŝtono.',
 
    box_inv_known = 'Ŝajnas, ke mi ie vidis ĝin.',
 
    box_inv_take_lock = 'Mi demetas seruron de skatolo.',
 
    box_inv_without_lock = 'Malnova skatolo. Sur ĝia fundo estas gravurita ringo kun ŝtono.',
 
    box_tak = 'Mi prenas skatolon.',
 
    box_used_key_failed = 'Pro longa tempo seruro rustiĝis kaj nun ŝlosilon maleble turni en ĝi.',
 
    box_used_key_oil = 'Mi gutigas oleon en seruron. Ĉi tio sufiĉas por lubriki meĥanizmon kaj devigi ĝin funkcii.',
 
    box_used_key_oil2 = 'Seruro jam estas lubrikita.',
 
    box_used_key_success = 'Ŝlosilo ne sen malfacilaĵo turniĝas kaj seruro malfermiĝas. Ene estas malgranda rulaĵo. Disvolvinte ĝin, mi komprenas, ke ĉi tio estas mapo. Mi prenas rulaĵon.',
 
    clouds = 'Cirusoj, traigataj de sunluma lanco, malrapide naĝas super mi, obeante aerajn fluojn.',
 
    common_dlg_greet = 'Bontagon. Mi unu fojo estas en via vilaĝo.',
 
    common_dlg_places = 'Vi konas iajn lokajn vidindaĵojn?',
 
    common_dlg_bye = 'Ĝis revido.',
 
    crater_near_tower = 'Kratero, ĉe eniro de turo',
 
    crater_near_tower_decor = 'Vojo elirigas min al nigra ene truo estanta en unu el muroj de {#tower|turo}, kiu estas konstruita el nekonata, por mi, nigra materialo. {#grass|Herbo} estas tuj apud la ĝia bazo. Disĵetemaj branĉaroj de {#trees|arboj} preskaŭ plene fermas per si ĉielon. Lumstrioj de {#sun|suno} trabatas foliaron kaj, falante sur herbon, vojon kaj murojn de turo, kreas originalan ornamaĵon.',
 
    crater_near_tower_grass = 'Densa verda herbo estas ĉie en ĉi arbaro.',
 
    crater_near_tower_sun = 'Hela somera suno prilumas per siaj lumstrioj arbaron.',
 
    crater_near_tower_tower = 'Bazo de turo havas formon de regula sesangulo. Malkompreneble, laŭ kiom profunde ĝi malsuprenas en teron. Malbrila faco laŭ palpe estas malvarma kaj glata kiel vitro. Mi ne vidas kaj ne sentas konektaĵojn, kvazaŭ turo estas eltranĉita el unueca peco de rokaĵo. Ĝiaj muroj suprenas, kaj ĝia alto estas kaŝita trans arbaj branĉaroj.',
 
    crater_near_tower_trees = 'Arboj estas tuj apud la turo. Ili, devas esti, kreskis ĉi tie jam post ĝia apero.',
 
    flower = 'Floro',
 
    flower_inv = 'Malgranda, sed tre bela floro kun ĉiel-blukoloraj maldikaj etendaj petaloj.',
 
    forest_glade = 'Kampeto',
 
    forest_glade_birds = 'Ie en profundo de arbaro mi aŭdas kantado de birdaj aro, sed mi vidas neniom proksime.',
 
    forest_glade_decor = 'Mi staras inter malgranda kampeto, kiu ĉirkaŭita de {#thicket|arbara} muro. Ĉi tie estas silento kaj kvieto. Mi aŭdas nur foliaran susuron kaj kantadon de {#birds|birdoj}. Facila venteto apenaŭ videble por okuloj balancas {#thicket|arbarajn} altaĵojn. Smerald-verda {#grass|herbo} atingas miajn kalkanojn.',
 
    forest_glade_enter = 'Mi alteriĝas sur malgranda kampeto en arbaro. Ĉi tie malbezone kaŝiĝi, tial mi restas en mia vera aspekto.',
 
    forest_glade_flowers = 'Ĉi tie floras multe da belaj floroj.',
 
    forest_glade_flowers_first = 'Mian atenton prenas neordinaraj floroj kun ĉiel-blukoloraj maldikaj etendaj petaloj, vegetantaj en kampeta rando. Mi deŝiras unun floron kaj prenas kun mi. Malmulte magion kaj ĝi jam neniam velkos.',
 
    forest_glade_grass = 'Alta densa herbo kovras tutan kampeton. Por homo ĝi estus laŭ lumbo, sed por mi apenaŭ atingas kalkanojn. Ĉi tie kaj tie mi rimarkas malgrandajn arojn de {#flowers|floroj}, kaŝitaj en ĝi.',
 
    forest_glade_thicket = 'Arboj ĉirkaŭas kampeton kvazaŭ muro, kvazaŭ atentaj gardistoj, gardantaj pacon de ĉi loko.',
 
    forester_dlg_disp = 'Arbaristo',
 
    forester_dlg_enter = 'Barba, vila viro, de sendifinebla aĝo, sidas en divano, trae rigardante miajn okulojn. Vestinta li en drelikaj anorako kaj pantalonoj kaj, verŝajne, ne havas problemojn pri varmego.',
 
    forester_dlg_farewell_response = 'Arbaristo ĝisrevidas kun mi: "Revidos".',
 
    forester_dlg_greet_response = 'Arbaristo neatendite ŝanĝas vizaĝon -- en liaj okuloj brulas gaja fajrero kaj, ŝajnas, ke sub lia barbo kaŝiĝas rideto: "Bonvolu, ni ĉiam ĝojas al gastoj!"',
 
    forester_dlg_pie = '[Doni framban kukon al arbaristo] Mi alportas kukon. Povas mi preni ŝnuron?',
 
    forester_dlg_pie_response = 'Arbaristo prenas de vi kukon kaj, demordis malmulte, diras: "Prenu".',
 
    forester_dlg_places_response = 'Arbaristo nepensante respondas: "Oni diras, ke tiela kolekto de libroj, kiel en nia librarejo, estas nenie plu".',
 
    forester_dlg_rope = 'Povas mi preni vian ŝnuron?',
 
    forester_dlg_rope_response = 'Arbaristo penseme gratas lian barbon kaj proponas: "Mi en lasta semajno malamikiĝis kun tavernisto, kaj nun li rifuzas vendi ion krom pano kaj akvo. Plezure mi interŝanĝos rulon de ŝnuro kontraŭ paco de framba kuko".',
 
    foresters_hut = 'Hejmo de arbaristo',
 
    foresters_hut_chairs = 'Malnovaj lignaj seĝoj, verŝajne kreitaj de loka majstro. Simplaj, sed firmaj kaj solidaj. Tiaj servos multaj jaroj.',
 
    foresters_hut_cupboard = 'Povas esti, ĉi ŝranko aĝas multajn jarojn. Bronzaj ansoj estas kovritaj de patino, kaj sur sekiĝinta pordeto mi vidas iom profundajn krevaĵojn.',
 
    foresters_hut_decor = 'Senrigarde al hela suna tago, ene de arbarista domo regas mallumo. Kontraŭ enirejo estas granda mola {#sofa|divano}. En angulo estas granda solida {#cupboard|ŝranko}, kaj ĉe fenestro estas {#table|tablo}, kovrita de tablokovrilo, kun iom {#chairs|seĝoj} ĉirkaŭ. Sur la tablo estas {#radio|radioricevilo}.',
 
    foresters_hut_enter = 'Enirinte en nelumigita ĉambro, mi apenaŭ ne demetas okulvitrojn por aperi min en vera aspekto. Kutimiĝinte al mallumo, mi ĉirkaŭrigardas.',
 
    foresters_hut_forester = 'Sur divano sidas {arbaristo}, rigardante min.',
 
    foresters_hut_forester_pie = 'Mi ne povas simple doni lin kukon. Necese aliri kaj ekparoli.',
 
    foresters_hut_not_interested = 'Mi ne pensas, ke al li ĉi tio estas interesa.',
 
    foresters_hut_radio = 'Malnova radioricevilo. Tiajn oni ĉesis produkti antaŭ du dek jaroj. Verŝajne, ĝi nun belege funkcias. Lampeto de energio brulas, sed laŭtnivelo estas minimumita.',
 
    foresters_hut_rope = 'Sur ŝranko kuŝas {ŝnura rulo}.',
 
    foresters_hut_rope_disp = 'Ŝnuro',
 
    foresters_hut_rope_inv = 'Rulo de firma ŝnuro.',
 
    foresters_hut_rope_not_taken = 'Mastro estos malkontenta, se mi prenos ĉi tion sen permeso.',
 
    foresters_hut_rope_taken = 'Mi prenas ŝnuron.',
 
    foresters_hut_sofa = 'Antikva divano kun senkolorigita kaj debatita ledo dum nun logas per hejma komforto.',
 
    foresters_hut_table = 'Masiva kverka tablo kovrita de malnova senkolora tablokovrilo kun floraj ornamaĵoj kaj iaj volutoj.',
 
    hidden_key_disp = 'Ŝlosilo',
 
    hidden_key_disp2 = 'ŝlosilo',
 
    hidden_key_disp3 = 'ŝlosilon',
 
    hidden_key_inv = 'Malnova metala ŝlosilo, eltrovita de mi en puto.',
 
    inside_crater_glade = 'Kratero, kampeto',
 
    inside_crater_glade_crater = 'Estante ĉi tie, preskaŭ en centro de grandega truo, mi vidas nenion, kio kontrastigus ĉi arbaron kaj teron kontraŭ aliajn, kiujn mi vidis.',
 
    inside_crater_glade_decor = 'Malgranda ronda kampeto meze de malofta folia {#forest|arbaro}. En ĝia centro estas grandega maljuna {#oak|kverko}, havanta grandan branĉaron. Smeralda verda {#grass|herbo} tuŝas mian zonon. Nekonate de iu kreita {#path|vojo} iras al {#tower|turo} estanta en centro de {#crater|kratero}.',
 
    inside_crater_glade_forest = 'En ombro de grandbranĉaraj ulmoj kaj belaj fagoj ludas sciuroj, leporoj kaj aliaj malgrandaj bestetoj. El malproksimo aŭdataj estas frapado de pego kaj kantado de birdoj.',
 
    inside_crater_glade_grass = 'Malkultura herbo estas alta, moderigata de neniu kaj nenio.',
 
    inside_crater_glade_oak = 'Grandega arbo estas tuj en centro de kampo. Aero bruetas en ĝiaj branĉoj, kovritaj de densa verda foliaro. En granda kavo dormas gufo.',
 
    inside_crater_glade_on_enter = 'Ankoraŭ tuŝinte teron, mi komencas transformiĝon. Kovrita de nebulo, mia korpo rapidas suben. Post momento mi estas en kampo en homa aspekto. Miaj okuloj radias helan lumon, sed mi ne devas kaŝiĝi -- okulvitroj estas kun mi en brustpoŝo.',
 
    inside_crater_glade_path = 'Iu ĝuste piedpremis en densa herbo mallarĝan vojon, kiu montras tuj al turo.',
 
    inside_crater_glade_tower = 'Turo el nigra ŝtono altiĝas super arbaro, kvazaŭ lumturo, estas instalita por ĉiu, kiu aliris ĉi tien.',
 
    inside_crater_path = 'Kratero, vojo',
 
    inside_crater_path_crater = 'Ja estante ĉi tie, ĉe centro de grandega kratero, mi vidas neniajn spuroj de falo -- vetero kaj arbaro faras sian laboron kaj laŭ leĝo sanigas grandegan cikatron sur korpo de Tero.',
 
    inside_crater_path_decor = 'Mallarĝa vojo, piedpremita en densa {#grass|herbo}, montras al centro de {#crater|kratero}. Suna lumo trabatas tra foliaro, kreante interesan ornamaĵon el obmbroj ĉie: sur branĉoj de {#trees|arboj}, sur herbo kaj vojo. Malproksime, antaŭe, estas videbla {#tower|turo}.',
 
    inside_crater_path_exit = 'Mi daŭrigas mian vojon, ne parolinte kun drakino. Ŝi etendas siajn flugilojn kaj forflugas.',
 
    inside_crater_path_grass = 'Ĉi tie, senigita de sunluma troaĵoj, herbo estas multoble malalta, ol en kampo. Sed ĝi ankaŭ estas intense smeraldkolora.',
 
    inside_crater_path_stump = 'Proksime de mi estas grandega {rokaĵo}.',
 
    inside_crater_path_stump_act = 'Rokaĵo en sia duono estas en tero. Verŝajne, ĝi estas ĉi tie tro antaŭlonge. Devas esti, ĉi tio estas unu el grandaj rompopecoj, aperintaj ĉi tie post apero de kratero.',
 
    inside_crater_path_stump_with_solarscale = 'Proksime de mi estas grandega {rokaĵo}, sur kiu lokiĝis malgranda ora {solarscale|drakino}.',
 
    inside_crater_path_tower = 'Nigra alta konstruaĵo, altiĝanta super arbarbo, apenaŭ kaŝita de densa foliaro por mia rigardo.',
 
    inside_crater_path_trees = 'Altaj arboj kun grandegaj branĉaroj apenaŭ balanciĝas de aero. En kunplektaĵoj de radikoj kreas siajn loĝejojn malgrandega animalaro, kaj sur branĉoj sidas ĉiaspecaj birdoj.',
 
    inside_well = 'En puto',
 
    inside_well_decor = 'Mi estas en profundo de puto. Ĝia ena parto kovrita de ŝtono. Ĉi tie regas mallumo kaj mi devas demeti okulvitrojn, por bone vidi. Malgraŭ tio, ke puto antaŭlonge estas sekiĝinta, ĉi tie ankoraŭ estas tro malseke.',
 
    inside_well_enter = 'Mi ne pensas, ke mi povos eliri, se eksaltos enen.',
 
    inside_well_loose_rock = 'Mian rigardon altiras {unu el ŝtonoj}, forte elstaranta el masonaĵo.',
 
    inside_well_loose_rock_act = 'Mi facile elprenas ŝtonon. Sub ĝi, en malgranda kavo, estas kaŝit metala ŝlosileto. Estas mirinda, sed malsekeco preskaŭ ne damaĝis ĝin.',
 
    leave_books_message = 'Al mi malnecesas ĉi libroj, plej bone restigi ilin ĉi tie.',
 
    librarian_dlg = 'Librarejisto',
 
    librarian_dlg_bye_response = 'Maljunulo kapklinadas: "Bonon".',
 
    librarian_dlg_enter = 'Antaŭ mi staras maljuna homo en malnova malhel-griza kostumo. Sur lia kolo estas malhel-blua kravato-papilio. El lia brustopoŝo elstaras peco de zorge gladita poŝtuko. Sur montra fingro mi rimarkas ringon kun juvelŝtono. Interese estas, kiel ĝi aperis en tia forgesita loko? En maldekstra mano li tenas dikegan libron, nomon de kiu mi, bedaŭrinde, ne vidas. Sur librarejista nazo estas okulvitroj kun korna kadro. Lia mentono glate rizita, kaj mallonga hararo estas griza. Grizaj okuloj kviete rigardas min, kaj buŝo malmulte malfermita en amika rideto.',
 
    librarian_dlg_greet_response = 'Viro respekte kapklinadas kaj diras: "Bonvenon! Kion helpon modesta librarejisto povas doni al vi?"',
 
    librarian_dlg_library = 'Via librarejo estas plej granda, kiun mi vidis. Kiel vi povis kolekti tiom da libroj?',
 
    librarian_dlg_library_old = 'Ĉi domo aspektas tro malnova, kiel antaŭlonge ĝi estis konstruita?',
 
    librarian_dlg_library_old_response = 'Librarejisto ridetas, eniĝante en siajn memoraĵojn: "Tro antaŭlonge, mia avo rakontis pri tio, kiel en juneco li pasigis ĉi tie tagojn kaj semajnojn, legante pri malproksimaj vojaĝoj kaj danĝeraj aventuroj..."',
 
    librarian_dlg_library_response = 'Librarejisto respondas: "Ĉi tio estas faro de multaj generacioj. De tie ĉi atingi civilizon estas malfacile. Multaj de ĉi libroj estas alportigitaj ĉi tien de vojaĝantoj, aliajn kolektis miaj antaŭloj. Ĉiuokaze, ne maloportuniĝu preni ajnan el ili. Ĉefa estas -- ne forgesu redoni".',
 
    librarian_dlg_places_response = 'Librarejisto ŝultrumas: "Mi ne pensas, ke ĉi tie estas kion rigardi".',
 
    librarian_dlg_ring = 'De kie vi havas ringon?',
 
    librarian_dlg_ring_look = 'Ĉu povas mi rigardi vian ringon?',
 
    librarian_dlg_ring_look_response = 'Librarejisto, ne dirante eĉ unu vorton, demetas ringon de sia fingro kaj etendas al mi. Mi atente ĉirkaŭrigardas juvelon. Sur ĝia ena flanko estas gravurita skribaĵo: "Ŝlosilo estas tie, kie estas akvo". Mi redonas ringon al mastro kaj li metas ĝin reen.', -- Please take note that the engraved words are also used in `village_well_act_key` key
 
    librarian_dlg_ring_response = 'Maljunulo montras al mi sian ringon. Mi ĉirkaŭrigardas juvelartaĵon. Ora ringo, plibeligita de skulptartaĵo, inkrustita de granda smeraldo -- ĉirkaŭ kvar milimetroj en diametro. Formetis sian manon, li diras: "Ĉi ringo gardiĝas ĉi tie de nememoreblaj tempoj. Al mi donis ĝin mia antaŭulo, kaj mi donos ĝin al tiu, kiu gardos ĉi librarejon post mi.".',
 
    library = 'Librarejo',
 
    library_chairs = 'Komfortaj molaj seĝoj, destinitaj al alirantoj.',
 
    library_decor = 'Ena spaco de librarejo prezentas vastan halon, plena de {library_shelves|librobretaroj}. Inter ili estas komfortaj {#tables|tabloj} kun estantaj apud ili {#chairs|apogseĝoj} kaj {#lamps|lampoj}. {#windows|Fenestroj} en domo estas malmulte kaj prefero donita estas al artefarita lumado. Al muro ĉe enirejo estas instalita malgranda {#library_notice|tabuleto}.',
 
    library_hidden_room = 'Librarejo, sekreta ĉambro',
 
    library_hidden_room_decor = 'Ĉi librarejon projektis iu talenta. Mi povus troiri domon tien kaj ĉi tien, ĉirkaŭrigardi, mezuri ĉiun angulon, sed ne scius, ke ĉi tie estas kaŝita ĉi ĉambro. Ĉi tie estas nenio krom malgranda {#table|tablo}.',
 
    library_hidden_room_table = 'Malgranda ronda tablo kun bronza piedo, kiela estas sama, kiel aliaj en ĉi librarejo.',
 
    library_lamps = 'Apid ĉiu apogseĝo estas lampo kun verda konustrunka lampŝirmilo. Nun ili estas elŝaltitaj -- tage lumo sufiĉas ja el malmultaj fenestroj, kaj alirantoj krom mi ne estas.',
 
    library_librarian = 'En halo iras maljuna {homo} kun libro en manoj.',
 
    library_librarian_used_box = 'Verŝajne, estas senco demandi, antaŭ doni tion al lia mano.',
 
    library_librarian_used_other = 'Mi ne pensas, ke ĉi tio povos interesa al li.',
 
    library_notice_inside_decor = [[        Malnova metala tabuleto enhavas liston de reguloj por uzado de librarejo:^
 
        1. Vi povas preni ajnajn librojn. Ĉiuj prenitaj libroj vi devas redoni mem aŭ iu devas fari ĉi tion anstataŭ vi. ^
 
        2. Vi povas alporti ajnan libron kaj restigi ĝin ĉi tie.^
 
        3. Vi povas mem meti libron en loko, uzante dismetan tabelon aŭ transdoni ĝin al librarejisto.^
 
        4. En limoj de breto dismetu librojn laŭ alfabeta ordo.^
 
        Ĉirkaŭ vorto "alfabeta" en lasta regulo mi rimarkas preskaŭ forviŝiĝintajn spurojn de malnova farbo, kvazaŭ iam ĝi estis kolormarkita.
 
      ]],
 
    library_shelf_book_disp = 'Historio de la Mondo, volumo %number%',
 
    library_shelf_book_inv = 'Tre malnova eldono la unu el plej disvastigita libro pri tutmonda historio.',
 
    library_shelf_book_tak = 'Mi prenas libron el breto.',
 
    library_shelf_puzzle_shelf_act = 'Sur glata breta ligno estas elĉizita vorto "%word%".',
 
    library_shelf_puzzle_shelf_multiple = 'En {shelf|breto} estas iom da libroj:',
 
    library_shelf_puzzle_shelf_none = '{shelf|Breto} estas senhava.',
 
    library_shelf_puzzle_shelf_single = 'En {shelf|breto} estas libro:',
 
    library_shelf_puzzle_used_book = 'Mi metas libron en breton.',
 
    library_shelf_puzzle_used_book_success = 'Librobreto turniĝas, malfermante trairejon al iam kaŝita ejo.',
 
    library_shelves_act = 'Nun mi sen malfacileco trovas tiun {library_the_shelf|breton}.',
 
    library_shelves_act_first = 'Mi longe vagas en labirinto de bretoj kaj librobretoj. Mi murdigus monaton nur por tio, por konatiĝi nomojn de kolektitaj ĉi tie libroj. Estas interese, de kie en ĉi forgesita loko estas tiaj trezoroj? Fine, mi haltas ĉe {library_the_shelf|unu el bretoj}.',
 
    library_tables = 'Malgrandaj rondaj tabloj kun bronzaj piedoj estas helpeme instalitaj laŭ halo.',
 
    library_the_shelf_act = 'Por unua rigardo, breto estas malrimarkinda. Nur ĉirkaŭrigardinte ĝin, mi komprenas, kio prenis mian atenton -- sur glata faco estas elĉizita vorto "%word%". Ĉi tio certe havas ian sencon.',
 
    library_windows = 'Aeraj flavgrizaj kurtenoj sur grandaj puraj fenestroj estas disfalditaj. Norde kaj oriente mi vidas nur senrandan arbaron. Trans arboj okcidente estas montaro. Trans fenestroj sude estas vidaĵo al vilaĝo.',
 
    lock = 'Seruro',
 
    lock_disp2 = 'seruro',
 
    lock_disp3 = 'seruron',
 
    lock_inv = 'Malgranda metala seruro, tre malnova kaj rusta.',
 
    maid_dlg = 'Junulino',
 
    maid_dlg_bye = 'Mi ekiros.',
 
    maid_dlg_bye_response = 'Junulino kapjesas, aere ridinte.',
 
    maid_dlg_enter = 'Junulino sidas en taverna perono. Ŝia longa kaŝtankolora hararo falas sur ŝultro, brunaj okuloj rigardas ien for. Anguletoj de ŝia buŝo levetitaj en aera rideto. Ŝi vestinta en simpla blua robo.';
 
    maid_dlg_enter_with_flower = 'Kiam mi aliras, ŝi transportas ŝian rigardon al mi kaj varme ridetas al mi.',
 
    maid_dlg_enter_no_flower = 'Kiam mi aliras, ŝi transportas ŝian rigardon al mi kaj afable, sed malmulte malgaje ridetas. Ŝiaj maldikaj palaj manoj kuŝas sur rando de ŝia robo nemovante.',
 
    maid_dlg_flower = '[Doni foron al junulino] Jen, prenu.',
 
    maid_dlg_flower_agree = 'Konsentite.',
 
    maid_dlg_flower_agree_response = 'Junulino ridetas: "Bone".',
 
    maid_dlg_flower_response = 'Junulino lumiĝis. Varme ridetis al vi, ŝi diras: "Dankon!"',
 
    maid_dlg_flower_think = 'Mi devas ekpensi.',
 
    maid_dlg_flower_think_response = 'Junulino movas ŝultron: "Kiel vi volas. Kuko vere estas tre bongusta".',
 
    maid_dlg_greet_response = 'Junulino konfuze respondas, rigardante min: "Pardonu, mi vin ne rimarkis. Mi helpos per kio povos".',
 
    maid_dlg_no_money = 'Mi ne havas monojn kun mi.',
 
    maid_dlg_no_money_response = [[Junulino mire demandas: "Kiel ja vi ĉi tien aliris?"^Malerte pensinte, ŝi proponas: "Vi konas, mi donos al vi kukon, se vi faros mian malgrandan volon. Multon mi ne petas, simple... - Ŝi faras malertan paŭzon, -- alportu al mi floron el nia arbaro. Ordinare min kuniras arbaristo kaj mi kolektas ilin kiom mi volas, sed nuntempe mi ambaŭ estas tre okupataj. Kion vi diros?"]],
 
    maid_dlg_pie = 'Vi povas alporti al mi pecon de framba kuko?',
 
    maid_dlg_pie_ask = 'Bone, mi diros lin.',
 
    maid_dlg_pie_ask_response = 'Junulino silente rigardas min.',
 
    maid_dlg_pie_fail_response = 'Junulino ridas: "Nia kuko tiel konata estas, ke homoj alvenas el malproksimaj landoj, por provi ĝin! Ĉu kial al vi ne peti mian patron?"',
 
    maid_dlg_pie_response = 'Junulino rapide leviĝas el loko kaj kun vortoj "Nun mi revenos!" forkuras en tavernon. Post da iom minutoj ŝi revenas kun peco da agrablege bonodoranta framba kuko.',
 
    maid_dlg_places_like = 'Jes, al mi plaĉas.',
 
    maid_dlg_places_like_response = 'Junulino daŭrigas: "En nia arbaro vegetas tre belaj floroj. Pli frue mi iris kun arbaristo kaj kolektis bukedon por mi, sed en ĉi jaro mi ne havas tempon -- necese helpi al mia patro en taverno". Ŝi malĝoje sopirĝemas.',
 
    maid_dlg_places_response = 'Demando gvidas junulinon al perplekso. Ŝi ruĝas kaj silentas, ne konante, kion respondi. Post iom da tempo ŝi demandas: "Ĉi tie estas bone, ĉu vere?"',
 
    maid_dlg_silent_response = 'Junulino demandas: "Tiel kion vi volis?"',
 
    maid_dlg_tavern = 'Vi laboras en taverno?',
 
    maid_dlg_tavern_response = 'Junulino silente kapjesas.',
 
    map_disp = 'Mapo',
 
    map_disp2 = 'mapo',
 
    map_disp3 = 'mapon',
 
    map_inv = 'Tro malnova mapo, montranta lokon en montaroj, okcidente de vilaĝo. Ĉi tio estas malproksime -- dek minutoj da flugado.',
 
    mountains = 'Montara ĉeno tranĉas arbaran tapiŝon okcidente de mi. Maloftaj arboj malespere sintenas ŝtonajn flankojn, kvazaŭ volante vivigi ĉi grandegan vundon.',
 
    near_village = 'Sude de vilaĝo',
 
    near_village_decor = 'Mi staras sur malnova asfalta {#road|vojo} ie inter antikva {#forest|arbaro}. En iom kilometroj norde de mi estas malgranda {#village|vilaĝo}. Hela somera {sun_transformed|suno} trabatas tra flugantaj alte en ĉielo {clouds|nuboj}.',
 
    near_village_enter = 'Mi facile alteriĝas. Apenaŭ miaj piedoj tuŝas teron, mi komencas transformiĝi. Korpo mia disfluas en nebulo, kiu baldaŭ revenas en aspekto de ordinara homo. Brulajn en hela fajro okulojn mi antaŭvidante kaŝas per malhelaj okulvitroj.',
 
    near_village_forest = 'Facila venteto balancas altaĵojn de arboj, estantaj laŭ vojaj flankoj, disportante bonodoron de pingla arbaro.',
 
    near_village_road = 'Griza malebena asfalto, de ĉiu forgesita vojo, kovrita de multaj rompaĵoj.',
 
    near_village_village = 'Zorgataj trabaj dometoj de lokanoj dronas en verdaĵo. De ĉi tie mi vidas estantajn en vilaĝa centro grandajn urbodomon kaj tavernon.',
 
    old_map_disp = 'Malnova mapo',
 
    old_map_disp2 = 'malnova mapo',
 
    old_map_disp3 = 'Malnovan mapon',
 
    old_map_inv = 'Antikva mapo, kiu algvidis min en ĉi landojn.',
 
    old_map_inv_not_visited = 'Montoj, arbaroj, ja vojo preskaŭ estas en samaj lokoj. Ie ĉi tie devas esti vilaĝo, kiu markita per kruco.',
 
    old_map_inv_visited = 'Montoj, arbaroj, markita vilaĝo per kruco, ja vojo preskaŭ estas en sama loko.',
 
    old_map_inv_visited_village = 'Restis kompreni, kio estas tia speciala en ĉi vilaĝo.',
 
    raspberry_pie = 'Framba kuko',
 
    raspberry_pie_inv = 'Mi inhalas ravan bonodoron de freŝa framba kuko. Malplezure, mi ne povas ĝin manĝi, sed mi certe revenos ĉi tien iam por peco por mi.',
 
    sun = 'Varmaj lumoj de suno agrable varmigas mian skvamon, trabatante maldikajn cirusojn.',
 
    sun_transformed = 'Varmaj lumoj de suno trabatas maldikajn cirusojn kaj kovras ĉion ĉirkaŭ per ora lumo.',
 
    tavern = 'Vilaĝo, taverno',
 
    tavern_cauldron = 'Bonodora rostaĵo bobelas en marmito -- ĉi tien ankoraŭ ne aliris nuntempaj gasaj aŭ elektraj   forneloj, kaj, povas esti mastro simple preferas kuiri laŭ ĝisnuna tempo.',
 
    tavern_decor = 'Vasta taverna halo renkontas kun varmo kaj komforto min. Ejo plena de suna lumo, interniĝanta tra multaj {#windows|fenestroj}, estantaj en trabaj {#walls|muroj}. Ĉie estas solidaj lignaj {#tables|tabloj}, al miro bone kreitaj. De plafono malsuprenpendas elektraj {#lights|lustroj}. Super {#fireplace|fajrujo}, en malproksima flanko, pendas {#cauldron|marmito}, de kiu leviĝas bonodoro.',
 
    tavern_fireplace = 'Senrigarde varmegan someran tagon, en fajrujo brulas fajro.',
 
    tavern_keeper = 'Trans purigita ĝis brilo la verŝotablo enuas {tavernisto}.',
 
    tavern_lights = 'Lampoj sub maldikaj plastaj lampŝirmiloj nun estas malŝaltitaj.',
 
    tavern_tables = 'Firmaj multepezaj tabloj, ĉiu estas por tri-kvar homoj, estas kovritaj de neĝ-blankaj tablokovriloj.',
 
    tavern_walls = 'Trabaj muroj de taverno kreas varman antikvan atmosferon kaj komforton.',
 
    tavern_windows = 'Grandaj fenestroj facile traigas lumon en ejon. Hel-verdaj kurtenoj, pendantaj sur ĉiuj fenestroj, estas malfermitaj.',
 
    tavernkeeper_dlg = 'Tavernisto',
 
    tavernkeeper_dlg_bye_response = 'Tavernisto vigle respondas: "Eniru ree!"',
 
    tavernkeeper_dlg_enter = 'Trans verŝotablo mi vidas obezan viron kun densa nigra barbo. Lia mallumaj okuloj gajete rigardas min. Li laŭte demandas: "Kion vi volas, gasto kara?"',
 
    tavernkeeper_dlg_greet_response = 'Tavernisto ridetas kaj ofertas: "Bonvenon! En mia taverno vi ĉiam povas halti por tranokti kaj ne restos sen sata varma vespermanĝo!"',
 
    tavernkeeper_dlg_money = 'Dankon, sed mi ne havas monojn kun mi.',
 
    tavernkeeper_dlg_money_response = 'Tavernisto ŝultrumas: "Senpage ni ne priservas".',
 
    tavernkeeper_dlg_pie = 'Mi povas aĉeti framban kukon?',
 
    tavernkeeper_dlg_pie_2 = 'Bedaŭrindde, nun mi ne havas ĉe mi monojn. Ni povas interkonsenti?',
 
    tavernkeeper_dlg_pie_response = 'Tavernisto tiriĝas al kuko kun vortoj: "Cent kvindek da moneroj kaj ĝi estas via!"',
 
    tavernkeeper_dlg_pie_response_2 = 'Tavernisto revenas al loko kaj diras: "Tiel malsukcesas. Kuko estas vendata nur por monoj".',
 
    tavernkeeper_dlg_places_response = 'Tavernisto respondas: "Nepre provu nian framban kukon! Mi asertas, vi manĝis nenion bongusta!"',
 
    townhall = 'Urbodomo',
 
    townhall_cabinet = 'Apud enirejo estas malgranda solida {kredenco}, sur kiu estas {record_player|gramofono}, muzikas nekonatan al mi melodion.',
 
    townhall_cabinet_act = 'Ene de kredenco mi trovas iom da gramofonaj {records|diskoj} kaj ĉelon kun {parts|riparaĵoj}.',
 
    townhall_cabinet_act_oil = 'Ene de kredenco mi trovas iom da gramofonaj {records|diskoj}, ĉelon kun{parts|riparaĵoj} kaj {oil|flakonon kun maŝina oleo}.',
 
    townhall_cabinet_oil = 'Flakono kun oleo',
 
    townhall_cabinet_oil_inv = 'Flakono preskaŭ plena da maŝina oleo.',
 
    townhall_cabinet_oil_tak = 'Mi prenas flakonon kun oleo.',
 
    townhall_cabinet_parts = 'Riparaĵoj por gramofono, zorge enjugitaj laŭ malgrandaj ĉeloj kaj pakoj.',
 
    townhall_cabinet_record_player = 'Gramofono estas en ideala stato, senrigarde grandan aĝon. Malnova tropremita disko tre krakas, sed muziko plaĉas al mi. Bedaŭrinde ĝi estas malkonata al mi.',
 
    townhall_cabinet_records = 'Iom da gramofondiskoj. Muzikistoj kaj kantoj estas nekonataj al mi.',
 
    townhall_cabinet_used_oil = 'Mi redonas flakonon.',
 
    townhall_ceiling = 'Alta plafono kaŝiĝas en mallumo, tamen al mi, kun mia draka rigardo, ne estas malfacile rigardi ĝian bone prilaboritajn ebenajn tabulojn.',
 
    townhall_chairs = 'Simplaj, sed solidaj seĝoj tiom estas malnovaj, kiel alia meblo ĉi tie. Mi ne havas dubojn, ke ili servos multe jarojn.',
 
    townhall_chandelier = 'Origitaj konzolo kaj kornetoj tenas lampojn kaj aron de pendaĵoj, beligantaj lustrojn. Nun ili estas elŝaltitaj, sed nur bruligota lumo, kaj fajrerantaj rebriloj fajros, respeguligante de kristalo kaj refraktante en ĝi.',
 
    townhall_curtains = 'Malfarbigitaj kurtenoj estas fermitaj, haltigante lumon al ĉambro. Malnova ŝtofo konservas sian densecon kaj firmecon.',
 
    townhall_decor = 'Mi staras en granda halo de urbodomo. En {#ceiling|plafono} estas iom da grandaj kristalaj {#chandelier|lustroj}. Nun en ejo regas tenebro -– {#curtains|kurtenoj} estas fermitaj kaj tra ili trabatas malmulte da lumo. En hala centro estas grandega kverka {#table|tablo}, laŭ kiu perimetro estas masivaj {#chairs|seĝoj}. En apogseĝo fore de tablo dormas maljuna {#head|viro}. ',
 
    townhall_head = 'Ne estas ia ajn senco veki lin -- estu dormas.',
 
    townhall_onexit = 'Mi pensas, ke al lokanoj ne plaĉos, se mi ŝtelos ilian aĵojn. Oleon necese redoni.',
 
    townhall_table = 'Sur polurita faco de tablo estas vidataj multaj grataĵoj, kreitaj de vizitantoj post multaj jaroj. Masiva kaj peza, ĝi staras kiel enverŝita kaj servos ankaŭ multajn jarojn.',
 
    transition_along_the_path = 'Laŭ vojeto',
 
    transition_away_from_bookstand = 'Deiri de bretaro',
 
    transition_east = 'Orienten',
 
    transition_east_to_the_village = 'Orienten, al vilaĝo',
 
    transition_fly = 'Flugi',
 
    transition_inside_hut = 'En hejmon de arbaristo',
 
    transition_inside_library = 'En librarejon',
 
    transition_inside_tavern = 'En tavernon',
 
    transition_inside_tower = 'En turon',
 
    transition_inside_town_hall = 'En urbodomon',
 
    transition_inside_well = 'En puton',
 
    transition_land = 'Alteriĝi',
 
    transition_north_along_road = 'Norden, laŭ vojo',
 
    transition_north_to_library = 'Norden, al librarejo',
 
    transition_north_to_the_townhall = 'Norden, al urbodomo',
 
    transition_north_to_the_village = 'Norden, al vilaĝo',
 
    transition_out = 'Elen',
 
    transition_south_along_road = 'Suden, laŭ vojo',
 
    transition_south_to_hut = 'Suden, al hejmo de arbaristo',
 
    transition_south_to_the_forest = 'Suden, en arbaron',
 
    transition_south_to_town_hall = 'Suden, al urbodono',
 
    transition_to_glade = 'Al kampeto',
 
    transition_to_hidden_room = 'En sekretan ĉambron',
 
    transition_to_main_hall = 'En ĉefan halon',
 
    transition_to_tower = 'Al turo',
 
    transition_up = 'Supren',
 
    transition_west = 'Okcidenten',
 
    transition_west_to_the_crater = 'Okcidenten, al kratero',
 
    village_all_decor = 'Tra maldikaj {clouds|cirusoj} trabatas helaj lumstrioj de somera {sun_transformed|suno}.',
 
    village_center = 'Vilaĝo, centro',
 
    village_center_decor = 'Mi staras sur malgranda placo antaŭ vilaĝa {#townhall|urbodomo}. En alia flanko de placo estas {#tavern|taverno}. Norde mi vidas ian grandan unuetaĝan {#library|domon}.',
 
    village_center_library = 'De ĉi tie mi povas elpendaĵon de librarejo.',
 
    village_center_music = 'Mi haltas, por aŭdi aŭdatan el urbodomo muzikon. Nekonata muziko sonas tre plaĉe.',
 
    village_center_tavern = 'Taverno ne cedas al urbodomon nek laŭ aĝo, nek laŭ solideco. El ĝia fumtubo eliras malvidebla fumeto.',
 
    village_center_townhall = 'Duetaĝa urbodomo -- estas unu el plej grandaj kaj malnovaj domoj en vilaĝo. Grandan parton de fasado havas grandegaj duetaĝaj fenestroj. Elene de domo aŭdata {#music|muziko}.',
 
    village_maid_act_no_dlg = 'Al mi nenio necesas de ŝi.',
 
    village_maid_dsc = 'En perono de taverno sidas {junulino}.',
 
    village_maid_flower = 'En sia mano ŝi tenas belan floron kun ĉiel-bluaj petaloj.',
 
    village_maid_used_flower = 'Plej bone komence aliri kaj ekparoli.',
 
    village_maid_used_other = 'Mi ne pensas, ke ĉi tio estos interesa al ŝi.',
 
    village_no_way_alone = 'Al lokanoj ne plaĉos, se inter ilia vilaĝo neatendite alteriĝos drako.',
 
    village_no_way_solarscale = 'Al lokanoj ne plaĉos, se inter ilia vilaĝo neatendite alteriĝos du drakoj.',
 
    village_north = 'Vilaĝo, nordo',
 
    village_north_decor = 'Mi estas norde de {#village|vilaĝo}. Mallarĝa {#road|vojo} alvenas al {#library|librarejo}, estanta en vilaĝa nordo. Trans ĝi mi vidas nur senliman {#forest|arbaron} kaj alnordirantan {#mountains|montaron}.',
 
    village_north_forest = 'Arbaro komenciĝas tuj trans librarejo. Ĉi tie arboj estas maloftaj ol en nordo, kie densaĵo estas tute malirebla. Aero estas plena de pinglo, kaj de ĉiuj flankoj aŭdebla kantado de birdoj.',
 
    village_north_library = 'Alta kaj vasta, la domo enspacas sub ĝi grandegan libraron. Senrigarde grandan aĝon, ĝi konserviĝis ideale, danke al bona zorgo. Larĝaj duklapaj pordoj estas apenaŭmalfermitaj, invitante gastojn.',
 
    village_north_mountains = 'Granda parto de la montaro estas kaŝita de mia rigardo per arboj. De tie ĉi mi vidas nur iom da plej altaj pintoj.',
 
    village_north_road = 'Asfalto ĉi tie estas plej rompiĝita ol en aliaj lokoj. Ie tra rompaĵoj trabatas maldikaj trunketoj de la herbo.',
 
    village_north_village = 'Vilaĝo, estiginta sude de mi, aspektas dormema -- flegitaj dometoj estas kaŝitaj en foliaro, vojetoj inter ili estas senhavaj. Nur en perono de taverno mi vidas solan junulinon en blua robo.',
 
    village_south = 'Vilaĝo, sudo',
 
    village_south_car = 'Ĉi aŭto, devas esti, aĝas ne malpli iom dek jarojn -- modelo tre malnova, karoserio en iaj lokoj estas refarbita, ie estas vidataj malgrandaj malebenaĵoj. Sed aŭto ne havas ja spuron de rusto, speguloj kaj lumĵetiloj estas funkcieblaj, frunta vitro estas pura.',
 
    village_south_decor = 'Mi staras sur {#road|vojo} en suda part de {#village|vilaĝo}. Nemalproksime estas {#foresters_hut_out|dometo} de arbaristo. Ĉe enirejo estas parkita malnova {#foresters_car|ŝarĝaŭto}. Lumstrioj de {sun_transformed|suno}, trabatantaj tra maldikaj {clouds|nuboj}, kovras ĉion ĉirkaŭe per ora lumo.',
 
    village_south_hut = 'Solida ligna domo, nigriĝinta de tempo kaj malmulte kurbiĝinta, sed tamen estas solida. Se estos necesa zorgo, domo estos ankoraŭ multaj dek jaroj.',
 
    village_south_road = 'Al mi, kiu kutimiĝis al ebena planko de miaj kavernoj, tre nekutime iri laŭ malnova rompita asfalto. Tie kaj ĉi tie tra krevaĵoj en ĝi trabatiĝas maldikaj trunketoj de juna herbo.',
 
    village_south_village = 'Zorgataj lignaj dometoj de lokanoj dronas en verdaĵo. De ĉi tie mi vidas estantajn en vilaĝa centro urbodomon kaj tavernon. El fumtubo de taverno leviĝas maldika fumstrieto.',
 
    village_unvisited = 'Vilaĝo certe ne estas forlasita.',
 
    village_well_act = 'Malnova sekiĝita puto.',
 
    village_well_act_key = 'Kiam mi vidas puton, al mia kapo aliras vortoj "ŝlosilo estas tie, kie estas akvo", gravuritaj sur ringo. Estu akvo ĉi tie antaŭlonge ne estas, ĉi momento nur faciligas problemon.',
 
    village_well_dsc = 'En centro de placo estas {puto}.',
 
    village_well_dsc_rope = 'Ĉirkaŭ unu el elstaranta ŝtono fiksita estas ŝnuro, kuŝigita en puta profundo.',
 
    village_well_used = 'Mi ligas ŝnuron al elstaranta ŝtono. Laŭ ŝnuro mi povos eliri el puto.',
 
    wind = 'Facila venteto blovas de oriento, portante volatan malvarmeton. Ĝia mola spirado apenaŭ balancas arbajn altaĵojn kaj devigas maldikajn nubojn naĝi okcidenten.',
 
  },
 
  solarscale_locale = {
 
    disp = 'Sunskvamet',
 
    first_dlg_about_map = '[Rakonti pri mapo] Ĉi tio estas longa historio...',
 
    first_dlg_about_map_1 = 'Rezultas ĉi tio.',
 
    first_dlg_about_map_1_response = 'Sunskvamet kapjesas: "Nu, mi deziras al vi sukcesojn en serĉadojn".',
 
    first_dlg_about_map_2 = 'Tio, kion mi serĉas, devas esti en ĉi kratero.',
 
    first_dlg_about_map_3 = 'Povas esti, vi povas helpi al mi?',
 
    first_dlg_about_map_3_response = 'Sunskvamet ree ridetas: "Jes". Malmulte pensinte, ŝi daŭrigas: "Mi pensas, ke necese komenci de turo el stranga ŝtono. Mi ne povis eniri, sed povas esti, vi povos. Simple sekvu laŭ ĉi vojeto".',
 
    first_dlg_about_map_response = 'Sunskvamet penseme diras: "Estas kurioza. Tiel vi ja ne konas, kion serĉas?"',
 
    first_dlg_dragon = 'Mi ne atendis ekvidi drakon. Kiel vi trovis vin ĉi tie?',
 
    first_dlg_dragon_admit = 'De vi nenion kaŝi. Jes, tiel estas.',
 
    first_dlg_dragon_admit_response = 'Sunskvamet kapjesas: "Neniam pensis, ke mi renkontos iun el samgentanoj! Ja ne tuj mi komprenis, kiu vi estas! Tiel kio alvenis vin ĉi tie?"',
 
    first_dlg_dragon_decline = 'Vi eraras.',
 
    first_dlg_dragon_decline_response = 'Sunskvamet ruze rigardas, vi komprenas, ke ŝi vidas vin trae: "Estu estos laŭ vi. Tiel kiel vi ĉi tie trovis vin?"',
 
    first_dlg_dragon_question = 'Kial vi tiel ekpensis?',
 
    first_dlg_dragon_question_response = 'Sunskvamet, ridetinte, respondas: "Ĉi tio ne estas simpla por kaŝi de alia drako. Sed kiel vi trovis vin ĉi tie?"',
 
    first_dlg_dragon_response = 'Sunskvamet respondas: "Mi revenas hejmen post longa vojaĝo. Simple haltis ripozi ĉi tien". Subite, ŝi haltas mire: "Viaj okuloj! Ja vi ankaŭ estas drako, jes?"',
 
    first_dlg_enter = 'Drakino kun orbrilantaj skvametoj kaj radiantaj hellumon smeraldoj la okuloj, sidas sur ŝtono, apenaŭ ferminte buŝon kun du ordoj de glataj brilantaj dentoj. Ŝiaj flugiloj estas falditaj trans dorso, kaj manoj -- krucigitaj laŭ brusto. Ŝi afable rigardas min. Ŝia alteco estas apud unu metro -- evidente, ŝi estas el draka specio de malgranda grando. Drakino ne formetas de mi sian rigardon, ridetante: "Bontagon, vojaĝanto. Mia nomo estas Sunskvamet. Kio alvenis vin en ĉi landojn?"',
 
    first_dlg_tower = 'Rakontu plien pri turo.',
 
    first_dlg_tower_bye_no_time = 'Mi petas pardonon, sed mi ne havas tempon paroli.',
 
    first_dlg_tower_bye_response = [[Sunskvamet leviĝas aeren kaj adiaŭas: "Nu, mi tiam daŭrigos mian vojon. Ĉion bonan al vi".^ Drakino forflugas, restante mian solan.]],
 
    first_dlg_tower_bye_thanks = 'Mi dankas pro helpon. Mi devas iri.',
 
    first_dlg_tower_join = 'Mi volas aliri al turo. Vi ne volas kuniri min?',
 
    first_dlg_tower_join_1 = 'Ja vi ne volas daŭrigi farojn kun turo?',
 
    first_dlg_tower_join_2 = 'Al mi ne estos senbezona via helpo.',
 
    first_dlg_tower_join_3 = 'Mi pensis, ke al ni, al drakoj, necese esti kune.',
 
    first_dlg_tower_join_response_2 = 'Sunskvamet ŝultrumas: "Mi ne volus ĉi tie prokrastiĝi".',
 
    first_dlg_tower_join_response_fail = 'Sunskvamet penseme rigardas min kaj diskrete respondas: "Verŝajne mi preferos daŭrigi mian vojon".',
 
    first_dlg_tower_join_response_fail_1 = 'Sunskvamet penseme rigardas al turon.',
 
    first_dlg_tower_join_response_fail_3 = 'Sunskvamet penseme rigardas min.',
 
    first_dlg_tower_join_response_success_1 = 'Sunskvamet leviĝas aeren kaj respondas: "Kial ne? Mi nenien rapidas".',
 
    first_dlg_tower_join_response_success_3 = 'Sunskvamet leviĝas aeren kaj respondas: "Jes, vi estas prava. Antaŭen!"',
 
    first_dlg_tower_response = 'Sunskvamet daŭrigas diri: "La turo aspektas kiel eltranĉita el tuta ŝtono, mi ne povis trovi neniom truojn kaj elstaraĵojn. Mi ja ne estas certa, ke ĉi tio ne estas peco de ŝtono".',
 
    first_dlg_unusual = 'Vi ne vidis apud nenion neordinaran?',
 
    first_dlg_unusual_response = 'Sunskvamet levigas flugilojn kaj penseme tuŝas sian mentonon: "Mi ne povas rememori nenion interesan... Krom la turo el stranga ŝtono. Mi ne povis eniri, sed povas esti, vi povos. Simple sekvu laŭ ĉi vojeto".',
 
    follow_refuse = 'Sunskvamet rifuzas sekvi min.';
 
    follow_refuse_village = 'Kun vortoj: "Mi ne povas ŝanĝi formon kaj ne pensas, ke lokanoj estos feliĉaj min vidi. Mi atendos vin ĉi tie", -- ŝi sidiĝas sur herbo apude.';
 
    follow_refuse_reactor = 'Kun vortoj: "Ĉi tie ĉion faros vi. Ĉi tie ne estas ŝirmkostumo por mi", -- ŝi elflugas en administran ĉambron.';
 
    solarscale_accept_help = 'Jes.',
 
    solarscale_ally_above_crater_life = 'Egalis kun mi, Sunskvamet mire demandas: "Kien ni flugas?"',
 
    solarscale_ally_above_village = 'Mi turniĝas al Sunskvamet flugilsvinganta malantaŭ mi. Ŝi informas: "Al ni, drakoj, plej bone estos ne aperi al homoj en vera aspekto. Ek ni ne prokrastos ĉi tie".',
 
    solarscale_ally_ask_tea = 'Ĉu vi volas trinki teon?',
 
    solarscale_ally_ask_tea_response = 'Sunskvamet pakjesas, ridetante: "Ne rifuzos".',
 
    solarscale_ally_dlg_about_tower_1_1 = 'Mi plene konsentas kun vi, ĉi loko estas belega.',
 
    solarscale_ally_dlg_about_tower_1_2 = 'Ek ni ĉirkaŭrigardos ĉion, antaŭ rezultigado.',
 
    solarscale_ally_dlg_about_tower_1_3 = 'Al ni necese esti singardemaj, ni ne konas kia estas ĉi loko.',
 
    solarscale_ally_dlg_about_tower_1_4 = 'Mi ne konas, kion diri.',
 
    solarscale_ally_dlg_above_crater_1 = 'Mi volas ankoraŭ unu foje ĉirkaŭrigardi ĉirkaŭaĵojn.',
 
    solarscale_ally_dlg_above_crater_1_response = 'Sunskvamet kapjesas: "Bone, ek flugi!"',
 
    solarscale_ally_dlg_above_crater_2 = 'Vi ne havas paciencon eniri?',
 
    solarscale_ally_dlg_above_crater_2_response = 'Sunskvamet respondas: "Certe! Ni ne konas kiel longe pordoj malfermotaj!"',
 
    solarscale_ally_dlg_above_crater_3 = 'Vi ne havas paciencon reveni?',
 
    solarscale_ally_dlg_above_crater_3_response = 'Sunskvamet ekkrias: "Certe! Povas esti vi povos trovi enirejon aŭ ekvidi ion, kion mi ne rimarkis".',
 
    solarscale_ally_dlg_above_crater_enter = 'Sunskvamet mire rigardas min kaj demandas: "Ĉu kial ni ne iros en turon?"',
 
    solarscale_ally_dlg_after_tower = 'Kion vi faros?',
 
    solarscale_ally_dlg_after_tower_1 = 'Mi revenos hejmen.',  -- Full meaning is "I will return home"
 
    solarscale_ally_dlg_after_tower_1_response = 'Sunskvamet kapjesas: "Ni povus renkonti iam ĉi tie, se vi ne estas kontraŭ?"',
 
    solarscale_ally_dlg_after_tower_2_response = 'Sunskvamet respondas: "Vi povas ekflugi kun mi".',
 
    solarscale_ally_dlg_after_tower_3 = 'Mi restos ĉi tie.',
 
    solarscale_ally_dlg_after_tower_3_response = 'Sunskvamet kapjesas: "Tiam mi vizitos vin, se vi ne estas kontraŭ?"',
 
    solarscale_ally_dlg_after_tower_response = 'Sunskvamet ŝultrumas: "Post la turo? Mi volus esti hejme -- miaj vojaĝoj malmulte estas longaj kaj mi volas kvieton. Sed vi?"',
 
    solarscale_ally_dlg_connection = 'Al mi ŝajnas, ke mi instalis ian ligon kun ĉi turo.',
 
    solarscale_ally_dlg_connection_1 = 'Mi aŭdas ĝian voĉon, ĝi parolas "Bonvenon en hejmon".',
 
    solarscale_ally_dlg_connection_1_1 = 'Ĉi tio estas tio, kion mi sentas ĉi tie.',
 
    solarscale_ally_dlg_connection_1_1_response = 'Sunskvamet kapjesas: "Tiam ni devas daŭrigi".',
 
    solarscale_ally_dlg_connection_1_2 = 'Nun estas frue paroli pri tio.',
 
    solarscale_ally_dlg_connection_1_2_response = 'Sunskvamet kapjesas: "Bone, ek moviĝi pluen".',
 
    solarscale_ally_dlg_connection_1_3 = 'Al mi ĉi tio ne plaĉas.',
 
    solarscale_ally_dlg_connection_1_3_response = 'Sunskvamet peneseme ŝultrumas: "Ĉiuokaze, ek daŭrigi".',
 
    solarscale_ally_dlg_connection_1_response = 'Sunskvamet penseme gratas sian mentonon: "Kaj kion vi pensas?"',
 
    solarscale_ally_dlg_connection_2 = 'Nun mi ne konas.',
 
    solarscale_ally_dlg_connection_2_response = 'Sunskvamet kapjesas: "Ni povas diskuti ĉi tion poste".',
 
    solarscale_ally_dlg_connection_response = 'Sunskvamet kun intereso rigardas min: "Interese, kion vi sentas?"',
 
    solarscale_ally_dlg_end = '[Finigi dialogon]',
 
    solarscale_ally_dlg_enter_back_to_tower_1 = 'Sunskvamet entuziasme ekkrias: "Ek revenos en turon!"',
 
    solarscale_ally_dlg_enter_back_to_tower_2 = 'Sunskvamet diskrete aludas: "Povas esti ni devas reveni al turo?"',
 
    solarscale_ally_dlg_enter_back_to_tower_3 = 'Sunskvamet ekkrias: "Mi ne havas paciencon eniri en turon!"',
 
    solarscale_ally_dlg_know_tower = 'Kiel vi ekkonis pri turo?',
 
    solarscale_ally_dlg_know_tower_1 = '[Diri pri mapo]',
 
    solarscale_ally_dlg_know_tower_1_response = 'Sunskvamet penseme diras: "Mira estas, ke vi ne konis pri la turo". Poste ŝi ekkrias: "Ni devas espori ĝin!"',
 
    solarscale_ally_dlg_know_tower_2_response = 'Sunskvamet ekkrias: "Ni devas esplori ĝin!"',
 
    solarscale_ally_dlg_know_tower_response_not_visited = 'Sunskvamet respondas: "Hazarde. Mian atenton prenis la kratero kaj mi decidis esplori ĝin. Certe mi decidis komenci de centro, kie mi trovis turon. Eniri mi ne povis, tial decidis ĉirkaŭrigardi, tiel mi renkontis vin".',
 
    solarscale_ally_dlg_know_tower_response_visited = 'Sunskvamet respondas: "Hazarde. Mian atenton prenis la kratero kaj mi decidis esplori ĝin. Certe mi decidis komenci de centro, kie mi trovis turon. Eniri mi ne povis, tial decidis ĉirkaŭrigardi, tiel mi renkontis vin. Mi ne konas, kial la pordo malfermiĝis, kiam ni revenis".',
 
    solarscale_ally_dlg_level_1_1 = 'Vi havas ideojn, kiel malfermi ĉi pordon?',
 
    solarscale_ally_dlg_level_1_1_response = 'Sunskvamet penseme diras: "Nun mi ne konas. Necese ĉion atente ĉirkaŭrigardi".',
 
    solarscale_ally_dlg_level_1_2_agree_response = 'Sunskvamet prenas skatolon kaj atente ĉirkaŭrigardas, antaŭ reveni al mi. Fine ŝi diras: "Kvar ŝlosilingoj... Verŝajne, ŝlosiloj devas esti ie ĉi tie".',
 
    solarscale_ally_dlg_level_1_2_response = 'Sunskvamet alflugas al mi: "Ĉu povas mi rigardi skatolon, kiun vi nun prenis?"',
 
    solarscale_ally_dlg_level_1_3_1 = 'Ne, ĉi ŝlosiloj ne estas por ĉi pordo.',
 
    solarscale_ally_dlg_level_1_3_1_or_2_response = '"Ili ĉi tie por io. Necese serci plej atente", -- penseme informas drakino.',
 
    solarscale_ally_dlg_level_1_3_2 = 'Ni supozos, ke ne konvenas.',
 
    solarscale_ally_dlg_level_1_3_3 = 'Mi ne provis.',
 
    solarscale_ally_dlg_level_1_3_3_response = 'Sunskvamet penseme respondas: "Necese provi... Kvankam ĉi tio estas tro simple..."',
 
    solarscale_ally_dlg_level_1_3_response = 'Sunskvamet demandas: "Vi certas, ke nek unu el ŝlosiloj ne konvenas al la pordo?"',
 
    solarscale_ally_dlg_level_1_4_1_1_response = 'Drakino iom da tempo estas senmova, pensante, post komencas fingrumi ŝlosilojn. Ekkriinte "Aha!" -- Ŝi ingas ŝlosilon post ŝlosilo en ŝlosilingojn, kaj skatolo disfalas en siaj manoj. Ene de skatolo estas malgranda arĝenta ŝlosileto. Sunskvamet donas ĝin al mi kun vortoj: "Provu malfermi pordon per ĝi".',
 
    solarscale_ally_dlg_level_1_4_1_no_help_response = 'Sunskvamet silente redonas aĵojn al mi.',
 
    solarscale_ally_dlg_level_1_4_1_response = 'Sunskvamet prenas aĵojn de vi kaj metas ilin sur tablo.',
 
    solarscale_ally_dlg_level_1_4_1_response_positive = 'Malmulte pensinte, ŝi diras: "Verŝajne, mi havas ideon. Permesu provi?"',
 
    solarscale_ally_dlg_level_1_4_1_response_negative = 'Malmulte pensinte, ŝi rezultigas: "Verŝajne, mi ne povas helpi al vi".',
 
    solarscale_ally_dlg_level_1_4_response = 'Sunskvamet alflugas al mi kaj demandas: "Ĉu povas mi rigardi?" ',
 
    solarscale_ally_dlg_level_2_1 = 'Vi absorbiĝas alkemion?',
 
    solarscale_ally_dlg_level_2_1_1 = 'Domaĝe, al mi ne malhelpos via helpo.',
 
    solarscale_ally_dlg_level_2_1_1_response = 'Sunskvamet falis okulojn: "Mi esperas, ke povos esti utila en alia".',
 
    solarscale_ally_dlg_level_2_1_response = 'Sunskvamet kun domaĝo respondas: "Mi malmultan konas pri tio".',
 
    solarscale_ally_dlg_level_3_1 = 'Vi havas ian ajn pensaĵojn pri tia enigmo?',
 
    solarscale_ally_dlg_level_3_1_1_response = 'Sunskvamet prenas pecojn kaj malrapide, unu post alia, metas ilin en ingojn. Aera klako permesas kompreni al ni, ke pordo al sekva etaĝo de turo estas malfermita.',
 
    solarscale_ally_dlg_level_3_1_response = 'Sunskvamet kapjesas: "Jes, estas ideo. Permesu provi??"',
 
    solarscale_ally_dlg_level_3_1_response_negative = 'Sunskvamet negas: "Mi ne havas ideojn".',
 
    solarscale_ally_dlg_level_4_1_1 = '[Permesi al Sunskvamet fari ĉion mem]',
 
    solarscale_ally_dlg_level_4_1_1_response = 'Sunskvamet sekve bruligas kandelojn. En mallumo unu post alia sonas notoj, kaj poste akra ventopuŝo malfermas pordon en malproksimo de ĉambro.',
 
    solarscale_ally_dlg_level_4_1_response = 'Sunskvamet penseme diras: "Jes, mi pensas ke mi povas helpi".',
 
    solarscale_ally_dlg_level_4_1_response_negative = 'Sunskvamet negas: "Bedaŭrinde, mi ne povas helpi".',
 
    solarscale_ally_dlg_level_4_room_2_1 = 'Ŝaltu!',
 
    solarscale_ally_dlg_level_4_room_2_1_1 = '[Aliri al konzolo] Bonege, rigardos.',
 
    solarscale_ally_dlg_level_4_room_2_1_2 = 'Vi povos ripari ĝin?',
 
    solarscale_ally_dlg_level_4_room_2_1_2_1 = 'Jes, certe.',
 
    solarscale_ally_dlg_level_4_room_2_1_2_1_response = 'Sunskvamet kutime dismuntas komputilon kaj, rigardinte en instrukcion, ŝanĝas rompitajn detalaĵojn al novajn. Fininte, ŝi muntas ĝin. "Rigardu! Verŝajne, mi ja ekpovis malmulte plibonigi ĝin!"',
 
    solarscale_ally_dlg_level_4_room_2_1_2_2 = 'Dankon, sed mi provos mem.',
 
    solarscale_ally_dlg_level_4_room_2_1_2_3 = 'Kiel vi pensas, kie ili povas esti?',
 
    solarscale_ally_dlg_level_4_room_2_1_2_3_response = 'Sunskvamet  respondas: "En suba etaĝo estis tenejo, verŝajne. Estas senco komenci serĉadon de tie".',
 
    solarscale_ally_dlg_level_4_room_2_1_2_response = 'Sunskvamet rigardas ĉelon kun riparaĵojn kaj, malmulte fosinte ĝin, diras: "Mi pensas, ke sukcesos. Permesu?"',
 
    solarscale_ally_dlg_level_4_room_2_1_2_response_negative = 'Sunskvamet kun bedaŭro diras: "Mi ne pensas, ke povos helpi. Mi neniam renkontis komputilojn de ĉi tipo".',
 
    solarscale_ally_dlg_level_4_room_2_1_2_response_no_parts = 'Sunskvamet penseme diras: "Nur se ni trovos rezervajn riparaĵojn".',
 
    solarscale_ally_dlg_level_4_room_2_1_response_fixed = 'Drakino, rigardinte vidigilon, diras: "Funkcias!"',
 
    solarscale_ally_dlg_level_4_room_2_1_response_issue = 'Trafoliuminte instrukcion, drakino konstatas: "Verŝajne, ne funkcias %broken%. Necese serĉi ŝanĝaĵon".';
 
    -- One of the following will be inserted into the %broken% variable above
 
    solarscale_ally_dlg_level_4_room_2_1_response_cpu = 'centra procesoro',
 
    solarscale_ally_dlg_level_4_room_2_1_response_keyboard = 'klavara kontrolilo',
 
    solarscale_ally_dlg_level_4_room_2_1_response_motherboard = 'baza plato',
 
    solarscale_ally_dlg_level_4_room_2_1_response_network = 'reta karto".',
 
    solarscale_ally_dlg_level_4_room_2_1_response_ram = 'operacia memoro',
 
    solarscale_ally_dlg_level_4_room_2_1_response_video = 'grafika karto',
 
    solarscale_ally_dlg_level_4_room_2_1_response_turnon = 'Sunskvamet ŝaltas komputilon.',
 
    solarscale_ally_dlg_level_4_room_2_3 = 'Kion ni povas fari?',
 
    solarscale_ally_dlg_level_4_room_2_3_response = 'Sunskvamet ŝultrumas: "De tie ĉi, mi pensas, nenion. Ek ni rigardu aliajn ejojn".',
 
    solarscale_ally_dlg_light = 'Vi havas ion por lumi?',
 
    solarscale_ally_dlg_light_agree = 'Jes, se al vi ne estos malfacila.',
 
    solarscale_ally_dlg_light_agree_response = '"Ne malfacilos", -- respondas ridetante Sunskvamet kaj fingroklakas. Ejo pleniĝas malfortan lumon.',
 
    solarscale_ally_dlg_light_response = 'Sunskvamet entuziasme respondas: "Estas unu proviza truko, provi?"',
 
    solarscale_ally_dlg_light_response_negative = 'Sunskvamet kun bedaŭro diras: "Bedaŭrinde, ne".',
 
    solarscale_ally_dlg_not_now = 'Ne nun.',
 
    solarscale_ally_follow_life = 'Sunskvamet sekvas min.',
 
    solarscale_ally_follows = 'Post mia dorso {Sunskvamet} svingas flugilojn.',
 
    solarscale_ally_glade = '{Sunskvamet} malrapide promenas laŭ kampo, admirante naturon. Tempo post tempo zorge deŝiras ian el floroj kaj kuŝigas en sian sakon.',
 
    solarscale_ally_glade_answer = 'Sunskvamet respondas: "Ne, mi ne flugis ĉi tie. Bela loko, mi volas rigardi ĝin en proksimo".',
 
    solarscale_ally_glade_enter = 'Rimarkinte mian rigardon, ŝi klarkigas: "Mi kolektas ekzemplerojn por mia kolekto". Kaj post ŝi aldonas: "Tre bela oko. Al mi plaĉas esti ĉi tie".',  -- This is appended to `solarscale_ally_glade`, with replaced { and } characters
 
    solarscale_ally_glade_left = 'Sunskvamet ĵetas adiaŭan rigardon al kampo kaj deflugas aeren sekvante min.',
 
    solarscale_ally_glade_life = 'Sunskvamet malleviĝas al tero sekvante min. Herbo ĉi tie preskaŭ kaŝas drakinon de mia rigardo.',
 
    solarscale_ally_glade_question = 'Vi konas ĉi lokon?',
 
    solarscale_ally_glade_suggestion = 'Sunskvamet rapide ĉirkaŭrigardas ĉirkaŭon. Ŝian rigardon prenis kampeto sube: "Mi volus alteriĝi ĉi tien, vi ne estas kontraŭ?"',
 
    solarscale_ally_level_3_2 = 'Sunskvamet plendas: "En ĉi mallumo mi nenion vidas! Necese alporti lumon".',
 
    solarscale_ally_near_tower = 'Sunskvamet ripetas, dirante al mi: "Rapide, ĝis trairejo estas malfermita!"',
 
    solarscale_ally_near_tower_life = 'Apenaŭ rimarkinte malfermitan trairejon, Sunskvamet saltas al ĝi, kaj haltinte antaŭ trairejo, diras al mi: "Rapide, ĝis ĝi ne fermos!"',
 
    solarscale_ally_no_help = 'Dankon, do mi provos mem.',
 
    solarscale_ally_outside = '{Sunskvamet} flugas sekvante min.',
 
    solarscale_ally_reject_help = 'Dankon, sed mi plej bone provos mem.',
 
    solarscale_ally_terminal = 'Sunskvamet ĉirkaŭrigardas klavaron de konzolo.',
 
    solarscale_ally_terminal_try = 'Sunskvamet demandas: "Ni provos ŝalti?"',
 
    solarscale_ally_tower_first_enter = 'Sunskvamet kun ravo rigardas min: "Ĉi turo nekredebla! Mi neniam vidis ion similan. Kion vi pensas?"',
 
    solarscale_ally_tower_level_1_life = 'Enfluginte en halon, Sunskvamet flugas al plafono kaj, malmulte turbinte, revenas al mi.',
 
    solarscale_ally_tower_level_1_room_2 = '{Sunskvamet} sidas sur tablo, rigardante min.',
 
    solarscale_ally_tower_level_1_room_2_life = 'Sunskvamet alteriĝas al tablo, ĉirkaŭrigardante.',
 
    solarscale_ally_tower_level_2 = '{Sunskvamet} sekvas min, ŝia rigardo flugas laŭ ĉambro.',
 
    solarscale_ally_tower_level_2_life = 'Sunskvamet enflugas en ejon kaj tuj haltas, larĝe malferminte okulojn. El ŝia buŝo eliras nur kvieta "Vau!"',
 
    solarscale_ally_tower_level_2_room_2 = '{Sunskvamet} sekvas min.',
 
    solarscale_ally_tower_level_2_room_2_life = 'Sunskvamet alflugas al mi.',
 
    solarscale_ally_tower_level_3 = '{Sunskvamet} penseme ĉirkaŭiras tablon. ',
 
    solarscale_ally_tower_level_3_life = 'Rapide ĉirkaŭrigardinte ejon, Sunskvamet rapidas al tablo. Malmulte girinte en aero, ŝi alteriĝas sur tablo.',
 
    solarscale_ally_tower_level_3_room_2_dark = 'Mi kun malfacilo difenecigas {Sunskvameton} en mallumo.',
 
    solarscale_ally_tower_level_3_room_2_life = '"Oh, mallumaĉo!" -- Aŭdas mi sonoran voĉon de Sunskvamet.',
 
    solarscale_ally_tower_level_3_room_2_lit = '{Sunskvamet} pendas super bretaroj, apud plafono.',
 
    solarscale_ally_tower_level_4 = '{Sunskvamet} staras sur planko, apud de tablo kun kandeloj.',
 
    solarscale_ally_tower_level_4_life = 'Enflugante en ĉambron, Sunskvamet tuj alteriĝas apud la tablo.',
 
    solarscale_ally_tower_level_4_room_2 = '{Sunskvamet} sidas sur la tablo kun komputilo.',
 
    solarscale_ally_tower_level_4_room_2_life = 'Enflugante en ejon, Sunskvamet enmomente haltas, ĉirkaŭrigardante, post kio alteriĝas sur tablo apud komputilo.',
 
    solarscale_dlg_enter_generic_1 = 'Sunskvamet kun rideto rigardas min.',
 
    solarscale_dlg_enter_generic_2 = 'Sunskvamet demandeme rigardas min.',
 
    solarscale_dlg_enter_generic_3 = 'Sunskvamet mallaŭte demandas: "Ĉu povas mi helpi per io?"',
 
    solarscale_do_you_have_any_ideas = 'Ĉu havas vi ideon, kion ni devas fari?',
 
    solarscale_don_t_know = 'Mi ne konas.',
 
    solarscale_let_me_try = 'Komence mi provos mem.',
 
    solarscale_let_me_try_2 = 'Nu, do mi provos mem.',
 
    solarscale_nods_in_agreement = 'Sunskvamet kapjesas.',
 
    solarscale_nods_silently = 'Sunskvamet silente kapjesas.',
 
    solarscale_pass_box = 'Doni skatalon al Sunskvamet',
 
    solarscale_pass_items_level_1 = 'Doni skatolon, ŝlosilojn kaj letereton al Sunskvamet',
 
    solarscale_used = 'Plej bone estos simple paroli.',
 
    tea_end = 'Ni finigas teumadon silente, estante en propraj pensadoj. Finite, mi redonas manĝilaron kaj teon reen kaj ni revenas al esploro de turo.',
 
    tea_q1_darkness = 'Mallumo.',  -- Who built the tower
 
    tea_q1_dragons = 'Drakoj.',  -- Who built the tower
 
    tea_q1_i = 'Mi.',  -- Who built the tower
 
    tea_q1_response_1 = 'Sunskvamet ŝultrumas: "Sed por kio ĝi estas ĉi tie?"',
 
    tea_q1_response_1_tower_accepts = 'Sunskvamet ŝultrumas: "Sed ĝi akceptas vin... Sed por kio ĝi estas ĉi tie?"',
 
    tea_q1_response_dragons = 'Sunskvamet penseme diras: "Verŝajne. Sed mi konas neniun krom nin..." -- Malmulte silentinte, ŝi demandas: "Sed por kio ĝi estas ĉi tie?"',
 
    tea_q1_response_i = 'Sunskvamet mire rigardas min kaj mallaŭte demandas: "Por kio?"',
 
    tea_q2_itself = 'Por nenio. Ĝi simple estas.',  -- For whom the tower was built
 
    tea_q2_me = 'Por mi.',  -- For whom the tower was built
 
    tea_q2_us = 'Por ni.',  -- For whom the tower was built
 
    tea_q2_other_dragons_1 = 'Malmulte silentinte, ŝi demandas: "Do vi pensas, ke en ĉi mondo estas pli drakoj?"',
 
    tea_q2_other_dragons_2 = 'Malmulte silentinte, ŝi demandas: "Kiel vi pensas, en ĉi mondo estas pli drakoj?"',
 
    tea_q2_r1 = 'Sunskvamet ŝultrumas.',
 
    tea_q2_r2 = 'Sunskvamet ŝultrumas: "Verŝajne, tiel estas".',
 
    tea_q2_r3 = 'Sunskvamet penseme rigardas plafonon.',
 
    tea_q3_alone = 'Ne, ni estas solaj.',  -- Are there other dragons in this world?
 
    tea_q3_exist = 'Certe estas.',  -- Are there other dragons in this world?
 
    tea_q3_know_nothing = 'Se estas, do mi konas nenion pri ili.',  -- Are there other dragons in this world?
 
    tea_q3_thought_alone = 'Antaŭ renkonto kun vi, mi pensas, ke mi estas sola.',  -- Are there other dragons in this world?
 
    tea_q3_don_t_know_final = 'Mi vere ne konas.',
 
    tea_q3_r1 = 'Sunskvamet penseme diras: "Verŝajne, ni estas solaj".',
 
    tea_q3_r2 = 'Sunskvamet ŝultrumas: "Eble, sed mi neniun vidis".',  -- Speaking about other dragons
 
    tea_q3_r_don_t_know = 'Sunskvamet ŝultrumas kaj fintrinkas teon. Mi sekvas ŝin kaj redonas manĝilaron kaj teon reen. Estas tempo por reveni al esplorado de turo.',
 
    tea_q3_r_try_again = 'Sunskvamet atente rigardas min kaj redemandas: "Sed, supozu?"',
 
    
 
    tea_start = 'Mi verŝas teon, prenas tason kaj per gesto invitas Sunskvameton aliĝi. Drakino faras unu gluton kaj demandas: "Kiel vi pensas, kiu kreis ĉi turon?"',
 
  },
 
  tower_locale = {
 
    alchemy_book_dlg_disp = 'Alĥemia libro',
 
    alchemy_book_dlg_enter = 'Antaŭ mi estas malfermita al tabelo de enhavo la libro de alĥemiaj receptoj. Iaj el ili prenas mian rigardon.',
 
    alchemy_book_dlg_leave = '[Deiri de libro]',
 
    alchemy_book_dlg_light = 'Lumo',
 
    alchemy_book_dlg_light_response = [[Konsisto: Kandelo, vitro, %catalyst%. ^Herbaĵo rapide elvaporiĝas. Efekto daŭras de unu ĝis tri horoj.]],  -- disp2(nominative, lowercase) is used for catalyst
 
    alchemy_book_dlg_open = 'Malfermado',
 
    alchemy_book_dlg_open_response = [[Konsisto: ŝlosilo, seruro, %catalyst%. ^Herbaĵo elverŝi en seruro, kion necese malfermi.]],  -- disp2(nominative, lowercase) is used for catalyst
 
    alchemy_book_dlg_rich = 'Pliriĉigo',
 
    alchemy_book_dlg_rich_response = [[Konsisto: altvalora metalo, gemo, %catalyst%. ^Eltrinku ĉi herbaĵon kaj vi pliriĉiĝos. Singardu, estas radioaktiva!]],  -- disp2(nominative, lowercase) is used for catalyst
 
    blue_catalyst_disp = 'Blua katalizilo',
 
    blue_catalyst_disp2 = 'blua katalizilo',
 
    blue_catalyst_disp3 = 'bluan katalizilon',
 
    blue_catalyst_dsc = 'En unu el bretoj estas {provtubo kun blua fluaĵo}.',
 
    blue_catalyst_inv = 'Provtubo kun blua fluaĵo, subskribita per vorto "Katalizilo".',
 
    green_catalyst_disp = 'Verda katalizilo',
 
    green_catalyst_disp2 = 'verda katalizilo',
 
    green_catalyst_disp3 = 'verdan katalizilon',
 
    green_catalyst_dsc = 'En unu el bretoj estas {provtubo kun verda fluaĵo}.',
 
    green_catalyst_inv = 'Provtubo kun verda fluaĵo, subskribita per vorto "Katalizilo".',
 
    purple_catalyst_disp = 'Violkolora katalizilo',
 
    purple_catalyst_disp2 = 'violkolora katalizilo',
 
    purple_catalyst_disp3 = 'violkoloran katalizilon',
 
    purple_catalyst_dsc = 'En eunu el bretoj estas {provtubo kun violkolora fluaĵo}.',
 
    purple_catalyst_inv = 'Provtubo kun violkolora fluaĵo, subskribita per vorto "Katalizilo".',
 
    red_catalyst_disp = 'Ruĝa katalizilo',
 
    red_catalyst_disp2 = 'ruĝa katalizilo',
 
    red_catalyst_disp3 = 'ruĝan katalizilon',
 
    red_catalyst_dsc = 'En unu el bretoj estas {provtubo kun ruĝa fluaĵo}.',
 
    red_catalyst_inv = 'Provtubo kun ruĝa fluaĵo, subskribita per vorto "Katalizilo',
 
    turquoise_catalyst_disp = 'Turkisa katalizilo',
 
    turquoise_catalyst_disp2 = 'turkisa katalizilo',
 
    turquoise_catalyst_disp3 = 'turkisan katalizilon',
 
    turquoise_catalyst_dsc = 'En unu el bretoj estas {provtubo kun turkisa fluaĵo}.',
 
    turquoise_catalyst_inv = 'Provtubo kun turkisa fluaĵo, subskribita per vorto "Katalizilo".',
 
    yellow_catalyst_disp = 'Flava katalizilo',
 
    yellow_catalyst_disp2 = 'flava katalizilo',
 
    yellow_catalyst_disp3 = 'flavan katalizilon',
 
    yellow_catalyst_dsc = 'En unu el ŝranketoj estas {provtubo kun flava fluaĵo}.',
 
    yellow_catalyst_inv = 'Provtubo kun flava fluaĵo, subskribita per vorto "Katalizilo".',
 
    candle_disp = 'Kandelo',
 
    candle_disp2 = 'kandelo',
 
    candle_disp3 = 'kandelon',
 
    candle_inv = 'Malgranda kandelo el malhela blanka vakso. En ĝi ĉio estas ordinara.',
 
    catalyst_tak = 'Mi prenas provtubon. Sur ĝi gluita papera ero kun surskribo "Katalizilo".',
 
    cauldron_inside_disp = 'Marmito',
 
    cauldron_inside_enter_many_items = 'En marmito nun estas:',
 
    cauldron_inside_enter_potion = 'En marmito estas pretita %potion%.',  -- %potion% is in nominative, lowercase
 
    cauldron_inside_enter_single_item = 'En marmito nun estas %item%.',  -- %item% is in nominative, lowercase
 
    cauldron_inside_enter_water = 'Marmito plena de bolanta akvo.',
 
    cauldron_inside_leave = '[Deiri de marmito]',
 
    cauldron_inside_take_items = '[Preni ĉion el marmito]',
 
    cauldron_inside_take_potion = '[Preni herbaĵon]',
 
    cauldron_inside_take_potion_response = 'Mi prenas herbaĵon en provtubon.',
 
    cups_disp = 'Tasoj',
 
    cups_dsc = 'Sur tablo estas du malgrandaj porcelanaj {tasoj}, plibeligitaj per arĝentaj floroj.',
 
    cups_inv_act = 'Du malgrandaj porcelanaj tasoj, plibeligitaj per arĝentaj floroj.',
 
    cups_kettle = 'Mi volas teon, sed ne akvon.',
 
    cups_no_need = 'Ni jam eltrinkis teon.',
 
    cups_no_tea = 'Komence necese fari teon.',
 
    cups_should_be_placed = 'Tasojn plej bone necese meti sur ian facon.',
 
    emerald_disp = 'Smeraldo',
 
    emerald_disp2 = 'smeraldo',
 
    emerald_disp3 = 'smeraldon',
 
    emerald_inv = 'Malgranda, belege farita smeraldo. Tre bela.',
 
    figure_common_inv = 'Tre detale farita, ĝi instalita sur sesangela bazo el sama metalo.';
 
    figure_knight_disp = 'Kavalira figuro',
 
    figure_knight_disp2 = 'kavalira figuro',
 
    figure_knight_disp3 = 'kavaliran figuron',
 
    figure_knight_inv = 'Figuro de kavaliro, kiu staras, subteniĝante sur grandega glavo. Farita el nekonata por mi arĝenta metalo.',
 
    figure_lion_disp = 'Leona figuro',
 
    figure_lion_disp2 = 'leona figuro',
 
    figure_lion_disp3 = 'leonan figuron',
 
    figure_lion_inv = 'Figuro de leono, kiu fiere ĉirkaŭrigardas siajn posedaĵojn. Farita el nekonata por mi arĝenta metalo.',
 
    figure_tiger_disp = 'Tigra figuro',
 
    figure_tiger_disp2 = 'tigra figuro',
 
    figure_tiger_disp3 = 'tigran figuron',
 
    figure_tiger_inv = 'Figuro de tigro, stariĝinta vostajn piedegojn, farita el nekonata por mi arĝenta metalo.',
 
    figure_tower_disp = 'Tura figuro',
 
    figure_tower_disp2 = 'tura figuro',
 
    figure_tower_disp3 = 'turan figuron',
 
    figure_tower_inv = 'Figuro de alta sesangela turo -- malgrandigita kopio de turo, en kiu mi nun estas. Farita el nekonata por mi arĝenta metalo.',
 
    figure_wolf_disp = 'Lupa figuro',
 
    figure_wolf_disp2 = 'lupa figuro',
 
    figure_wolf_disp3 = 'lupan figuron',
 
    figure_wolf_inv = 'Figuro de lupo, kiu blekas lunon, farita el nekonata por mi arĝenta metalo.',
 
    flask_disp = 'Flakono',
 
    flask_disp2 = 'flakono',
 
    flask_disp3 = 'flakonon',
 
    flask_inv = 'Malgranda vitra flakono, nun estas malplena.',
 
    inside_box_decor = 'Malgranda arba skatolo, plibeligita per maldikaj arĝentaj ornamaĵoj. En unu el edro mi vidas kadritan per arĝento nombrilon kun ciferoj: %numbers%. Sub nombrilo estas kvar da ŝlosilingoj.',
 
    inside_box_keyhole_1_empty = '{Unua ŝlosilingo} estas malplena.',
 
    inside_box_keyhole_1_key = 'En unua ŝlosilingo estas enigita {%key%}.',  -- Ensure that {%key%} is not the first word in the sentence, as it will be lower-case, it will also be in nominative case
 
    inside_box_keyhole_2_empty = '{Dua ŝlosilingo} estas malplena.',
 
    inside_box_keyhole_2_key = 'En dua ŝlosilingo estas enigita {%key%}.',  -- Ensure that {%key%} is not the first word in the sentence, as it will be lower-case, it will also be in nominative case
 
    inside_box_keyhole_3_empty = '{Tria ŝlosilingo} estas malplena.',
 
    inside_box_keyhole_3_key = 'En tria ŝlosilingo estas enigita {%key%}.',  -- Ensure that {%key%} is not the first word in the sentence, as it will be lower-case, it will also be in nominative case
 
    inside_box_keyhole_4_empty = '{Kvara ŝlosilingo} estas malplena.',
 
    inside_box_keyhole_4_key = 'En kvara ŝlosilingo estas enigita {%key%}.',  -- Ensure that {%key%} is not the first word in the sentence, as it will be lower-case, it will also be in nominative case
 
    inside_box_keyhole_act_empty = 'Malgranda ŝlosilingo.',
 
    inside_box_keyhole_act_key = 'Mi prenas %key% el ŝlosilingo.',
 
    inside_box_keyhole_used_has_key = 'En ŝlosilingo jam estas ŝlosilo.',
 
    inside_box_keyhole_used_insert_key = 'Mi enigas %key% en ŝlosilingo kaj turnigas ĝin. Nombro en nombrilo ŝanĝiĝas.',
 
    inside_box_keyhole_used_open = 'En ĉelo io klakas kaj ĝi malfermiĝas. Ene mi trovas malgrandan arĝentan ŝlosilon.',
 
    kettle_boil_empty = 'Sensence boligi malplenan tekruĉon.',
 
    kettle_disp = 'Tekruĉo',
 
    kettle_disp2 = 'tekruĉo',
 
    kettle_disp3 = 'tekruĉon',
 
    kettle_disp_hot_water = 'Tekruĉo kun bolaĵo',
 
    kettle_disp_water = 'Tekruĉo kun akvo',
 
    kettle_dsc = 'Sur la tabol estas {tekruĉo}.',
 
    kettle_inv = 'Ordinara metala tekruĉo.',
 
    kettle_inv_empty = 'Nun ĝi estas malplena.',
 
    kettle_inv_hot_water = 'Nun ĝi estas plenigita de bolaĵo.',
 
    kettle_inv_water = 'Nun ĝi estas plena de malvarma akvo.',
 
    kettle_tak = 'Mi prenas tekruĉon.',
 
    kettle_tak_no = 'Ĉi tio al mi malnecesas.',
 
    kitchen_key_disp = 'Fera ŝlosilo',
 
    kitchen_key_disp2 = 'fera ŝlosilo',
 
    kitchen_key_disp3 = 'feran ŝlosilon',
 
    kitchen_key_inv = 'Malgranda fera ŝlosilo. Ĝia kapo plibeligita per ĉiza ornamaĵo.',
 
    part_box_disp = 'Ĉelo kun rezervaĵoj',
 
    part_box_disp2 = 'ĉelo kun rezervaĵoj',
 
    part_box_disp3 = 'ĉelon kun rezervaĵoj',
 
    part_box_dsc = 'En unu el bretoj estas {ĉelo} kun rezervaj platoj por komputilo.',
 
    part_box_inside_dsc = 'Granda ĉelo, ene ĝi mi vidas detalaĵojn:',
 
    part_box_tak = 'Mi rapide ĉirkaŭrigardas platojn. Nenio estas markita de konata produktisto al mi. Pri difino de platoj mi povas supozi nur laŭ konektiloj en ili. Mi prenas ĉelon.',
 
    part_box_used = 'Mi kuŝigas detalon en ĉelon.',
 
    password_note_disp = 'Letereto',
 
    password_note_disp2 = 'letereto',
 
    password_note_disp3 = 'letereton',
 
    password_note_inv = 'En letereto estas skribita nur: "%password%". Mi ree ekkonas propran skribmanieron!',
 
    potion_enrichment_disp = 'Pliriĉiga herbaĵo',
 
    potion_enrichment_disp2 = 'pliriĉiga herbaĵo',
 
    potion_enrichment_disp3 = 'pliriĉigan herbaĵon',
 
    potion_enrichment_inv = 'Kreita de mi la pliriĉiga herbaĵo brilas kvazaŭ rela oro. Kiam mi skuas provtubon, do mi aŭdas sonoradon de moneroj.',
 
    potion_light_disp = 'Herbaĵo de lumo',
 
    potion_light_disp2 = 'herbaĵo de lumo',
 
    potion_light_disp3 = 'herbaĵon de lumo',
 
    potion_light_inv = 'Kreita de mi herbaĵo de lumo tute estas pura kaj donas aeran aromon de freŝeco, kiel aero post la fulmotondro.',
 
    potion_light_inv_used = 'Mi malfermas flakonon kun herbaĵo de lumo kaj elverŝas fluaĵon en aeron. Ĝi en momento iĝas al luma vaporo, kiu plenigas ĉion ĉirkaŭ.',
 
    potion_open_disp = 'Herbaĵo de malfermado',
 
    potion_open_disp2 = 'herbaĵo de malfermado',
 
    potion_open_disp3 = 'herbaĵon de malfermado',
 
    potion_open_inv = 'Kreita de mi herbaĵo de malfermado odoras de rusta metalo kaj havas maldolĉan flavruĝa-grizan koloron. Provtubo estas varma.',
 
    protection_suit_disp = 'Kontraŭradia kostumo',
 
    protection_suit_dsc = 'En ĝi estas arĝenta {kontraŭradia kostumo}.',
 
    protection_suit_inv_not_here = 'Mi ne demetos kontraŭradian kostumon ĉi tie. Malsekure.',
 
    protection_suit_inv_remove = 'Mi demetas kontraŭradian kostumon.',
 
    protection_suit_tak = 'Mi metas kontraŭradian kostumon.',
 
    reactor_control_panel_diagnostic = '[Diagnostiko]',
 
    reactor_control_panel_diagnostic_resp_1 = 'Mi premas butonon por diagnostiko kaj post iom da tempo en ekrano estiĝas rezultojn:',
 
    reactor_control_panel_diagnostic_resp_2 = 'Temperaturo de reakciujo estas bonorda.',
 
    reactor_control_panel_diagnostic_resp_3 = 'Aŭtomata sistemo de administro estas bonorda.',
 
    reactor_control_panel_diagnostic_resp_4 = 'Mana sistemo de administro estas bonorda.',
 
    reactor_control_panel_diagnostic_resp_performance = 'Kapacitio:',
 
    reactor_control_panel_diagnostic_resp_rods_bad = 'Brulaĵaj trunkoj postulas anstataŭigon. Ŝaltita reĝimo de energiŝparo.',
 
    reactor_control_panel_diagnostic_resp_rods_ok = 'Brulaĵaj trunkoj estas bonordaj.',
 
    reactor_control_panel_diagnostic_resp_rods_up = 'Brulaĵaj trunkoj estas levitaj. Diagnostiko estas malebla. Ŝaltita reĝimo de energiŝparo.',
 
    reactor_control_panel_disp = 'Stirpanelo de reakciujo',
 
    reactor_control_panel_enter = 'Antaŭ mi estas stirpanelo de reakciujo. En malgranda alfabet-cifera ekrano estiĝas skribo: "Enigu komandon".',
 
    reactor_control_panel_leave = '[Deiri de stirpanelo]',
 
    reactor_control_panel_lower_rods = '[Enprofundigi brulaĵajn trunkojn]',
 
    reactor_control_panel_raise_rods = '[Eltiri brulaĵajn trunkojn]',
 
    reactor_control_panel_rods_response = 'El reakciuja kamerao estas aŭdata glata rumoro, bone dampita de dikaj muroj.',
 
    service_manual_disp = 'Flego kaj riparo',
 
    service_manual_dsc = [[En ordinaraj okazoj la flego malnecesas, tamen al vi necesos anstataŭigi konsistojn de konzolo al plej rendimentaj. ^
 
        Grave: Antaŭ ia ajn operacioj, elŝaltu konzolon de energio!^
 

	
 
        Anstataŭigo de ĉefa plato: ^
 
        -- Vi povas uzi ia ajn ĉefan platon de formato DTMB1^
 
        -- Antaŭ anstataŭigado de ĉefa plato elŝaltu ĉiujn ilojn de ĝi^
 
        -- Demetu ĉiujn ŝraŭbojn, kiuj tenas ĉefan platon (vd. aldonon 6)^
 
        -- Demetu ĉefan platon^
 
        -- Instalu novan platon anstataŭ kurantan^
 
        -- Metu ŝraŭbojn por ene de korpo (vd. aldonon 6)^
 
        -- Instalu kongruajn procesoron, memoron, klavaron, videoadaptilon kaj retadaptilon^
 

	
 
        Anstataŭigo de procesoro:^
 
        -- Demetu malnovan procesoron^
 
        -- Instalu novan procesoron^
 
        Grave: Al kuranta tempo la ĉefaj platoj de formato DTMB1 eldoniĝas kun konektiloj de bazaj procesoroj CAX, CVX kaj CRX. Estas dorsflanka kongrueco de platoj kun malnovaj procesoroj, tiamaniere:^
 
        -- Procesoron CAX eble instali en platojn kun konektiloj CAX, CVX kaj CRX^
 
        -- Procesoron CVX eble instali en platojn kun konektiloj CVX kaj CRX^
 
        -- Procesoron CRX eble instali en platojn kun konektilo CRX^
 

	
 
        Anstataŭigo de operacia memoro:^
 
        -- Demetu malnovan kromaĵon de memoro^
 
        -- Instalu novan kromaĵon de memoro^
 
        Grave: Al kuranta tempo la ĉefaj platoj de formato DTMB1 eldoniĝas kun konektiloj de memorkromaĵoj RKT, RST, RDT. Estas dorsflanka kongrueco de platoj kun malnovaj memorkromaĵoj, tiamaniere:^
 
        -- Memoron RKT eble instali en platojn kun konektiloj RKT, RST kaj RDT^
 
        -- Memoron RST eble instali en platojn kun konektiloj RST kaj RDT^
 
        -- Memoron RDT eble instali en platojn kun konektilo RDT^
 

	
 
        Anstataŭigo kromaĵaj iloj:^
 
        -- Demetu malnovan ilon^
 
        -- Instalu novan ilon^
 
        Al kuranta tempo la ĉefaj platoj de formato DTMB1 eldoniĝas kun konektiloj ISV, vi povas uzi nur ISB-kongruajn ilojn kun ĉi platoj.^
 

	
 
        Markoj de kongruaj iloj:^
 
        1. Ĉefaj platoj^
 
        Ĉefaj platoj de formato DTMB1 havas markon de tipo <CP>-<Memoro>-I<Kvanto de konektiloj>SB. Ekzemplo:
 
        CAX-RKT-I2SB -- ĉefa plato por procesoro CAX, subtenanta RKT memoron kaj havanta du konektilojn por aldonaj iloj.^
 
        2. Procesoroj^
 
        Procesoro ordinare havas markon <X>CPU<Indekso>-<Konektilo>-<Taktofrekvenco>, kie X -- litero, signifanta generacion de CP. Generacio de CP ne influas al kongrueco kun ĉefa plato.
 
        Ekzemplo: MCPU50-CVX-5MHz -- procesoroj de M generacio kun taktofrekvenco 5mHz kaj kun CVX konektilo.^
 
        3. Memoro^
 
        Memoro ordinare havas markon <Konektilo>-M<Indekso>-<Grando>. Ekzemplo: RST-M8-VMB -- kromaĵo kun grando de 8 megabajtoj por RST konektilo.^
 
        4. Videoadaptiloj^
 
        Al kuranta tempo ekzistas du videoadaptilaj tipoj por konzoloj TETS-1: serio TVA estas adaptilo kun ebleco nur teksta enigado, serio GVA -- adaptilo kun ebleco grafika enigado.^
 
        5. Retaj adaptiloj^
 
        Retaj adaptiloj por konzoloj TETS-1 havas markon FNA-<Indekso>-<Rapideco>.^
 
        6. Klavara kromaĵo^
 
        Klavarkromaĵoj por konzoloj TETS-1 havas markon KBC-<Generacio>.
 
      ]],
 
    silver_fork_disp = 'Arĝenta forko',
 
    silver_fork_disp2 = 'arĝenta forko',
 
    silver_fork_disp3 = 'arĝentan forkon',
 
    silver_fork_dsc = 'Sur unu el tabloj estas de iu forgesita {arĝenta forko}.',
 
    silver_fork_inv = 'Belforma arĝenta forko. Verŝajne, malmultekosta.',
 
    silver_fork_tak = 'Interese, kial ĝin oni ne formetis en ŝrankon. Mi prenas forkon.',
 
    system_unit_check_1_long_1_short_1_long = 'Mi aŭdas sonan sinsekvon: unu longan, unu mallongan kaj unu longan.',
 
    system_unit_check_1_long_2_short = 'Mi aŭdas sonan sinsekvon: unu longan kaj du mallongajn.',
 
    system_unit_check_1_short_2_long = 'Mi aŭdas sonan sekvon: unu mallongan kaj du longajn.',
 
    system_unit_check_3_long = 'Mi aŭdas sonan sinsekvon: tri longajn.',
 
    system_unit_check_fail = 'Ventolilo en energibloko bruas, sed ekrano ne ŝaltiĝas.',
 
    system_unit_check_network_fail = 'Komence komputilon, verŝajne, ŝaltiĝis bone, sed poste estiĝis mesaĝo pri malekzista ŝarĝilo.',
 
    system_unit_check_no_sound = 'Mi aŭdas neniom signalojn.',
 
    system_unit_check_turn_on = 'Mi ŝaltas komputilon.',
 
    system_unit_decor = 'Mi rigardas enen de sistembloko kaj ĉirkaŭrigardas instalitajn en ĝi ilojn. Malfacile mi difinas, kie estas operacia memoro, procesoro, kromaĵplatoj. Markojn de kromaĵoj kaj tipojn de konektiloj mi ne vidis ele ĉi turo.',
 
    system_unit_disp = 'Sistembloko',
 
    teabox_disp = 'Ĉelo kun teo',
 
    teabox_inv = 'Metala ĉelo, plenigita de aromaj folioj de nigra teo.',
 
    teapot_disp = 'Tekruĉo',
 
    teapot_inv_empty = 'Neĝkolora porcelana tekruĉo, plibeligita per ornamaĵoj el arĝentaj floroj.',
 
    teapot_inv_leaves = 'Neĝkolora porcelana tekruĉo, plibeligita per ornamaĵoj el arĝentaj floroj. Ene estas teaj folioj.',
 
    teapot_inv_tea = 'Neĝkolora porcelana tekruĉo, plibeligita per ornamaĵoj el arĝentaj floroj. Plena de freŝa teo.',
 
    teapot_used_already = 'Tekruĉo jam estas plena.',
 
    teapot_used_already_tea = 'En tekruĉo jam sufiĉe da folioj.',
 
    teapot_used_cold_water = 'En malvarma akvo teo ne estos.',
 
    teapot_used_empty_kettle = 'Kion mi volas verŝi el malplena tekruĉo?',
 
    teapot_used_filled = 'Mi verŝas akvon en tekruĉon. Teo estas preta!',
 
    teapot_used_no_tea = 'Komence necese enigi teajn foliojn.',
 
    teapot_used_tea_added = 'Mi enigas malmulte da folioj en tekruĉon.',
 
    terminal_manual_disp = 'Gvidilo de uzulo de TETS-1 konzolo',
 
    terminal_manual_dsc = [[Tabelo de enhavo:^
 
        1. Kompleto de livero^
 
        2. Konektado^
 
        3. Uzado^
 
        4. {@walk service_manual|Flego kaj riparo}^
 
        5. {@walk troubleshooting_manual|Solvo de problemoj}^
 
      ]],
 
    tool_box_disp = 'Ŝraŭbturnilaro',
 
    tool_box_disp2 = 'ŝraŭbturnilaro',
 
    tool_box_disp3 = 'ŝraŭbturnilaron',
 
    tool_box_dsc = 'En unu el bretoj mi vidas ĉelon kun {ŝraŭbturnilaro}.',
 
    tool_box_inv = 'Ŝraŭbturnilaro por elektroniko. Nenie sur ĉelo estas neniaj markon pri produktisto. Tamen ŝraŭbturniloj estas tre kvalitaj kaj aspektas kiel novaj.',
 
    tower_2_door_act_closed = 'Pordo kreita el sama materialo kiel muroj. Nun ĝi estas fermita. Mi rimarkas en ĝi malgrandan ŝlosilingon, kadritan per arĝento.',
 
    tower_2_door_act_open = 'Pordo kreita el sama materialo kiel muroj. Nun ĝi estas malfermita. Trans ĝi mi vidas ŝtuparon el sama nigra ŝtono.',
 
    tower_2_door_dsc_closed = 'Masiva {pordo} baras trairejon al aliaj ejoj de turo.',
 
    tower_2_door_dsc_open = 'Masiva {pordo} estas malfermita. Trans ĝi estas {#stairwell|ŝtuparo} al sekva etaĝo de la turo.',
 
    tower_2_door_used_potion = 'Mi elverŝas herbaĵon en seruron kaj lastan en momento manĝas rusto. Vojo liberigita.',
 
    tower_accept_1_walls = 'Malvarmaj kaj senvivaj muroj ŝajnas fremda por ĉi mondo. Nur unu tuŝo al ĉi glata, memoriganta vitron, faco -- vokas nevolan tremon de mi.',
 
    tower_accept_2_walls = 'Muroj faritaj el nekonata ŝtono al mi. Sur platoj estas neniom spuroj de tempo -- nek unu grataĵo, nek unu spliton. Ĉi glata kaj malvarma faco memorigas vitron al mi.',
 
    tower_accept_3_walls = 'Solidaj nigraj muroj ŝajnas nedetrueblaj. Ja mem la tempo ne havas potencon super ili.',
 
    tower_blue_key_disp = 'Blua ŝlosilo',
 
    tower_blue_key_disp2 = 'blua ŝlosilo',
 
    tower_blue_key_disp3 = 'bluan ŝlosilon',
 
    tower_blue_key_inv = 'Malgranda ŝlosilo el blua metalo.',
 
    tower_candelabra_dsc = 'Belforma kandelabro por sep kandeloj.',
 
    tower_candelabra_enter = 'Apenaŭ mia rigardo falas al kandelabro, kiel en mallumo sonoras sona sinsekvo:',
 
    tower_candle_1 = 'Bruligi unuan kandelon',
 
    tower_candle_2 = 'Bruligi duan kandelon',
 
    tower_candle_3 = 'Bruligi trian kandelon',
 
    tower_candle_4 = 'Bruligi kvaran kandelon',
 
    tower_candle_5 = 'Bruligi kvinan kandelon',
 
    tower_candle_6 = 'Bruligi sesan kandelon',
 
    tower_candle_7 = 'Bruligi sepan kandelon',
 
    tower_gold_key_disp = 'Ora ŝlosilo',
 
    tower_gold_key_disp2 = 'ora ŝlosilo',
 
    tower_gold_key_disp3 = 'oran ŝlosilon',
 
    tower_gold_key_inv = 'Malgranda ŝlosilo el ora metalo.',
 
    tower_green_key_disp = 'Verda ŝlosilo',
 
    tower_green_key_disp2 = 'verda ŝlosilo',
 
    tower_green_key_disp3 = 'verdan ŝlosilon',
 
    tower_green_key_inv = 'Malgranda ŝlosilo el verda metalo.',
 
    tower_hint_1_disp = 'Papereto',
 
    tower_hint_1_inv = 'Malgranda papereto, sur kiu skribita nombro %target%. Almire, sed ĝi estas skribita per mia skribmaniero!',
 
    tower_level_1_box_disp = 'Skatolo',
 
    tower_level_1_box_dsc = 'Sur unu el tabloj estas malgranda plibeligita per arĝento {la skatolo}.',
 
    tower_level_1_box_inv = 'Mi jam ĉirkaŭrigardas skatolon.',
 
    tower_level_1_box_tak = 'Mi prenas skatolon. Sub ĝi mi trovas malgrandan papereton. Mi prenas ĝin.',
 
    tower_level_1_candelabra = 'Belformaj arĝentaj kandelabroj estas tute similaj. Sur ĉiu el ili estas instalitaj po tri kandeloj, donantaj malfortan trembrilan lumon, vere malsufiĉan por prilumi halon.',
 
    tower_candelabra_candle_missing = 'Unu el kandeloj ne estas.',
 
    tower_candelabra_candle_taken = 'Malmulte pensinte, mi prenas unu el kandeloj.',
 
    tower_level_1_candelabra_keys = 'Mi rimarkas ŝlosilaron, kuŝantan apud unu el kandelabroj.',
 
    tower_level_1_ceiling = 'Nigra volba plafono estas kaŝita en mallumo. Ĝis ĝi estas ĉirkaŭ kvin metroj -- estas alta por homo, sed malsufiĉe por mia vera aspekto.',
 
    tower_level_1_chairs = 'Malnovaj seĝoj kun ĉizitaj dorsoj aspektas samtempe masivaj kaj belformaj.',
 
    tower_level_1_decor = 'Turo renkontas min per premanta mallumo kaj malvarmo. Nigraj {tower_walls|muroj} kaj {#ceiling|plafono} de halo dronas en mallumo. En la halo estas kvar grandegaj {#tables|tabloj}, kovritaj de blankaj tablotukoj. Sur ĉiu estas po tri belaj arĝentaj {#candelabra|kandelabroj}. Ĉe tabloj estas metitaj masivaj arbaj {#chairs|seĝoj}.',
 
    tower_level_1_disp = 'Turo, unua etaĝo',
 
    tower_level_1_door_act_closed = 'Pordo fermita. Mi rimarkas en ĝi malgrandan ŝlosilingon, kadritan per arĝento.',
 
    tower_level_1_door_act_open = 'Pordo malfermita, trans ĝi mi vidas ŝtuparon, faritan el sama materialo kiel turaj muroj.',
 
    tower_level_1_door_closed = 'Masiva {pordo} el sama materialo kiel muroj, baras trairejon al aliaj ejoj de la turo.',
 
    tower_level_1_door_open = 'Masiva {pordo} el sama materialo kiel muroj, estas malfermita. Trans ĝi estas {#stairwell|ŝtuparo} al sekva etaĝo de la turo.',
 
    tower_level_1_door_use_correct_key = 'Mi enigas ŝlosilon en ŝlogilingon. Seruro funkcias ideale, kaj ŝlosilo turniĝas tre aere. Pordo malfermiĝas sen forto, malfermante trairejon al sekva etaĝo.',
 
    tower_level_1_keys = 'Apud unu el kandelabroj kuŝas {ŝlosilaro}.',
 
    tower_level_1_keys_take = 'Mi prenas ŝlosilaron.',
 
    tower_level_1_kitchen_door = 'En unu el muroj estas {pordo}.',
 
    tower_level_1_kitchen_door_act_closed = 'Malrimarkema arba pordo. Ĝi fermita. Mi vidas neniom solvoj por malfermi ĝin.',
 
    tower_level_1_kitchen_door_act_open = 'Pordo estas malmulte malfermita.',
 
    tower_level_1_kitchen_door_used_key = 'Ĉi tie ne estas ingo por enigi ŝlosilon.',
 
    tower_level_1_kitchen_door_used_potion = 'Ĉi tie ne estas seruro, por elverŝi en ĝi herbaĵon.',
 
    tower_level_1_room_2_cabinets1_act_tea_and_teapot = 'Mi prenas ĉelon de teo el ŝranko. Kaj tie troviĝas malgranda porcelana tekruĉo. Mi prenas ĝin.',
 
    tower_level_1_room_2_cabinets1_act_tea_ask = 'En unu el ŝrankoj mi trovas ĉelon de teo. Interese, ĉu volas Sunskvamet fari malgrandan teumadon?',
 
    tower_level_1_room_2_cabinets2_act_cups = 'En unu el ŝrankoj mi trovas du malgrandaj porcelanaj tasoj. Mi prenas ilin.',
 
    tower_level_1_room_2_cabinets2_act_note = 'En unu el ŝrankoj mi trovas letereton restigitan de iu. Mi prenas ĝin.',
 
    tower_level_1_room_2_cabinets_act_empty = 'En ŝrankoj estas nur manĝilaro.',
 
    tower_level_1_room_2_decor = 'Laŭ perimetro de ĉi vasta ĉambro situas mallarĝa {#tabletop|tablo} el nigra ŝtono, sub kiu situas ĉiaspecaj {#cabinets1|ŝrankoj}. Super tablo estas muntitaj {#cabinets2|ŝrankoj}. En angulo estas malnova {#fridge|malvarmigujo}. En kontraŭa angulo estas elektra {#stove|fornelo}. Apud la fornelo estas {#kitchen_sink|lavujo}. En ejo regas sama silenta kaj komforta mallumo, kiel en aliaj turaj ejoj.',
 
    tower_level_1_room_2_disp = 'Turo, kuirejo',
 
    tower_level_1_room_2_door_act_locked = 'Pordo fermita. Ornamaĵo plibeligas feron de seruro.',
 
    tower_level_1_room_2_door_act_open = 'Trans malfermita pordo mi vidas manĝejon de la turo.',
 
    tower_level_1_room_2_door_dsc = 'En unu el muroj estas malgranda arba {pordo}.',
 
    tower_level_1_room_2_door_used = 'Mi malfermas pordon per ŝlosilo.',
 
    tower_level_1_room_2_fridge = 'Tiaj malvarmigujoj estis en 60-j jaroj. Sed ĉi aspektas tiel, kvazaŭ hieraŭ ellasita de ĉenstablo. Enrigardinte enen, mi trovas malplenajn bretojn.',
 
    tower_level_1_room_2_hook_act_empty = 'Sur hoketo nenio estas.',
 
    tower_level_1_room_2_hook_act_key = 'Mi prenas ŝlosilon.',
 
    tower_level_1_room_2_hook_dsc_empty = 'Apud la pordo en muro estas metita malgranda kupra {hoketo}.',
 
    tower_level_1_room_2_hook_dsc_key = 'Sur la kupra hoketo, apud pordo, pendas {fera ŝlosilo}.',
 
    tower_level_1_room_2_kitchen_sink = 'Polurita faco de ŝtona lavujo, instalita en tablo, briletas en lumo de elektraj lampoj.',
 
    tower_level_1_room_2_kitchen_sink_used_full = 'Tekruĉo jam estas plena.',
 
    tower_level_1_room_2_kitchen_sink_used_water = 'Mi verŝas akvon en tekruĉon.',
 
    tower_level_1_room_2_put_cups = 'Mi metas tasojn sur la tablo.',
 
    tower_level_1_room_2_stove_act = 'Elektra fornlo kun kvar kuirplatoj kun elektra bakujo. Kun siaj elektraj elementoj ĝi aspektas tro moderna por ĉi loko.',
 
    tower_level_1_room_2_stove_used_hot = 'Akvo en tekruĉo jam varma.',
 
    tower_level_1_room_2_stove_used_power = 'Sen elektreco nenio sukcesos.',
 
    tower_level_1_room_2_stove_used_teapot = 'Mi metas tekruĉon sur la plato kaj post iom minutoj la akvo en ĝi bolas.',
 
    tower_level_1_room_2_tabletop = 'Tablo farita el sama materialo kiel muroj. Solideco de ĉi malvarma kaj glata ŝtono ne vokas dubojn.',
 
    tower_level_1_stairwell = 'Larĝa ŝtuparo el nigra glata ŝtono, gvidanta al sekva etaĝo de la turo.',
 
    tower_level_1_tables = 'Masivaj tabloj el nigra arbo estas kovritaj de blankaj tablotukoj, kudritaj per arĝento. Polvo sur tabloj ne estas, kvazaŭ ilin oni kovris antaŭnelonge. Ĉe ĉiuj tablo eble sidigi iom dekoj da homoj.',
 
    tower_level_1_tables_box = 'Sur unu el tabloj estas skatolo.',
 
    tower_level_2_airlock_ceiling = 'Plumba plafono estas en alto ĉirkaŭ du metroj. Metalo forte malaltigas nivelon de radieco ene, tamen ne blokas ĝin plene. Plej bone ne esti ĉi tie longe.',
 
    tower_level_2_airlock_decor = 'Plumbaj {#walls|muroj} de ĉi ejo estas destinitaj por defendo de estantaj en ĝi kontraŭ forta radia radiado. En {#ceiling|plafono} estas sola {#lamp|lampo}, donanta malfortan ruĝan lumon. Mi pensas, ke malnecese esti ĉi tie longe.',
 
    tower_level_2_airlock_disp = 'Turo, kluzo',
 
    tower_level_2_airlock_lamp = 'Akcidentluma lampo, sama kiel en administrejo.',
 
    tower_level_2_airlock_locker_act = 'Surskribaĵo sur la ŝranko diras, ke lasta estas distingita por gardo de kontraŭradia kostumo.',
 
    tower_level_2_airlock_locker_dsc = 'Ĉe unu el muroj estas instalita malgranda plumba {ŝranko}.',
 
    tower_level_2_remove_suit = 'Mi demetas kontraŭradian kostumon kaj restigas ĝin en ŝrankon.',
 
    tower_level_2_airlock_walls = 'Metalo, el kiu faritaj ĉi muroj, forte malaltigas nivelon de radieco ene, tamen ne blokas ĝin plene. Plej bone ne esti ĉi tie longe.',
 
    tower_level_2_book = 'Sur unu el tabloj estas malfermita {libro}.',
 
    tower_level_2_cabinet_vials = 'En unu el ŝrankoj mi trovas du provtubojn kun koloraj fluaĵoj.',
 
    tower_level_2_cabinets = 'Granda parto de ŝrankoj havas nenion interesan, senrigarde aliajn alĥemiajn ilojn.',
 
    tower_level_2_cannot_be_thrown = 'Neporkio ĉi tion fari.',
 
    tower_level_2_cauldron_used = 'Mi metas %item% en marmiton.',
 
    tower_level_2_decor = 'Dua etaĝo de la turo prezentis alĥemian laborejon. Laŭ {tower_walls|muroj} estas {#tables|tabloj} kaj {#racks|bretoj}. Super iaj tabloj pendas {#cabinets|ŝrankoj}. En hala centro estas instalita grandega {tower_cauldron|marmito}, sub kiu brulas {#fire|fajro}.',
 
    tower_level_2_disp = 'Turo, dua etaĝo',
 
    tower_level_2_fire = 'Hela fajro, verŝajne, tute ne varmigas. Lumo de ĝi apenaŭ elpenas mallumon, kiu plenas halon.',
 
    tower_level_2_key_disp = 'Arĝenta ŝlosilo',
 
    tower_level_2_key_dsc = 'Malgranda arĝenta ŝlosilo kun belforma ĉizita kapo.',
 
    tower_level_2_potion_in_the_cauldron = 'Herbaĵo en marmito jam estas preta.',
 
    tower_level_2_potion_ready = 'Herbaĵo estas preta!',
 
    tower_level_2_rack_vials = 'En unu el bretoj mi trovas du provtubojn kun koloraj fluaĵoj.',
 
    tower_level_2_racks = 'Solidaj arbaj bretoj estas plena de provtuboj. Grandaj el ili estas malplenaj.',
 
    tower_level_2_reactor_disp = 'Turo, reakciujo',
 
    tower_level_2_reactor_enter_alone = 'Aero ĉi tie odoras ozonon, kaj sur la lango sensiĝas malpeza metala saporo.',
 
    tower_level_2_reactor_enter_solarscale = 'Sunskvamet baras vojon al mi. "Mi vin tien ne traigu sen kontraŭradia kostumo. Ĉi tio danĝera", -- konstatas ŝi.',
 
    tower_level_2_reactor_rods_act_lowered = 'Necese levi trunkojn, por mi povos ilin ĉirkaŭrigardi.',
 
    tower_level_2_reactor_rods_act_raised = 'Longaj metala trunkoj. Devas esti, ene de ili estas brulaĵaj elementoj por funkciado de reakciujo. Mi ne povas taksi ilian staton per okuloj.',
 
    tower_level_2_reactor_rods_dsc_lowered = '{Brulaĵaj trunkoj} de reakciujo nun estas profundigitaj.',
 
    tower_level_2_reactor_rods_dsc_raised = '{Brulaĵaj trunkoj} de reakciujo nun estas levitaj kaj mi povas atingi ilin.',
 
    tower_level_2_reactor_rods_used = 'Mi elverŝas herbaĵon sur brulaĵan trunkon. Nenio ŝanĝiĝis.',
 
    tower_level_2_room_2_ceiling = 'Plafono ĉi tie estas neordinare malalta -- mi ja povas tuŝi ĝin. Ĝi estas sama malvarma kaj glata kiel muroj.',
 
    tower_level_2_room_2_control_panel_dsc = 'Apud la pordo estas {stirpanelo}.',
 
    tower_level_2_room_2_decor = 'Malgrandega ĉambro. Ŝtonaj {tower_walls|muroj}, {#floor|planko} kaj {#ceiling|plafono} estas samaj kiel en aliaj ĉambroj.',
 
    tower_level_2_room_2_decor_nopower = 'En plafono brulas ruĝaj {#emergency_lamps|lampoj} de akcidenta lumo.',
 
    tower_level_2_room_2_decor_power = 'Iom {#lamps|lampoj} en plafono donas helan blankan lumon.',
 
    tower_level_2_room_2_disp = 'Turo, administrejo',
 
    tower_level_2_room_2_emergency_lamps = 'En malforta lumo de akcidentaj lampoj, la turo ŝajnas plej enigma kaj malvera.',
 
    tower_level_2_room_2_floor = 'Glataj ŝtonaj platoj estas en ideala stato, kiel ĉie en ĉi turo.',
 
    tower_level_2_room_2_lamps = 'Iom lampoj de taga lumo estas en plafono.',
 
    tower_level_2_room_2_next_door_act_closed = 'Mi movas klinkon kaj malfermas pordon.',
 
    tower_level_2_room_2_next_door_act_open = 'Tro malfermita pordo mi vidas alĥemian laborejon.',
 
    tower_level_2_room_2_next_door_dsc_closed = 'En muro estanta kontraŭ stirpanelo, estas malgranda ŝtona {pordo}, fermita per klinko.',
 
    tower_level_2_room_2_next_door_dsc_open = 'En muro estanta kontraŭ stirpanelo, estas malgranda ŝtona {pordo}.',
 
    tower_level_2_room_2_reactor_door_act = 'Peza kaj tre dika pordo.',
 
    tower_level_2_room_2_reactor_door_dsc = 'En unu el muroj de la ĉambro situas ortangula {pordo} kun la signo de radia danĝero.',
 
    tower_level_2_table_vials = 'Sur unu el tabloj mi rimarkas du provtuboj kun koloraj fluaĵoj.',
 
    tower_level_2_tables = 'Pezaj tabloj el nigra ŝtono silentas sur solidaj piedoj. Tabloj estas plenaj de ĉiaspecaj alĥemiaj iloj.',
 
    tower_level_3_bookshelves = 'Mi kuras per rigardo librojn. Multaj el ili estas tre malnovaj, iaj el ili estas skribitaj en nekonataj al mi lingvoj. Ĉi tie estas artaĵoj kaj laboroj de filozofoj kaj sciencistoj de diversaj epokoj.',
 
    tower_level_3_decor = 'Tria etaĝo aspektas kiel ies kabineto. En la ĉambro regas komforta mallumo. Laŭ unu el {tower_walls|muroj} estas instalitaj {#bookshelves|librobretoj}, kaj en kontraŭa muro estas metita brulanta {#fireplace|kameno}. Apud ĝi estas malnova {#rockchair|rulseĝo}. Masiva arba {tower_level_3_table|tablo} situas en ĉambra centro.',
 
    tower_level_3_disp = 'Turo, tria etaĝo',
 
    tower_level_3_door_act_locked = 'Pordo fermita. Mi vidas neniajn truojn.',
 
    tower_level_3_door_act_open = 'Pordo malfermita. Trans ĝi mi vidas {#stairwell|ŝtuparon}, kreitan el sama nigra ŝtono kiel muroj de la turo.',
 
    tower_level_3_door_dsc_locked = 'Masiva {pordo} el sama materialo kiel muroj, fermita.',
 
    tower_level_3_door_dsc_open = 'Masiva {pordo} el sama materialo kiel muroj, malfermita. Trans ĝi estas {#stairwell|ŝtuparo} al sekva etaĝo de la turo.',
 
    tower_level_3_fireplace = 'Senrigarde brulantan fajron en kameno, en ejo regas mallumo kaj malvarmo. Briletantaj sur muroj la ombroj de la fajro malstreĉas kaj kvietigas.',
 
    tower_level_3_hidden_door_act = 'Mi ne rimarkus ĉi pordon, se ne konus, ke ĝi estas tie.',
 
    tower_level_3_hidden_door_dsc = 'Trans unu el librobretoj kaŝiĝas malgranda {pordo}.',
 
    tower_level_3_hint = [[Sur la tablo mi rimarkas tekston:^
 
Ilin estas kvin, kaj kiu havas propran koloron: blankan, helruĝan, lazuran, verdan kaj nigran.^
 
Al kvir donita tempo: tagmezo, meznokto, mateniĝo kaj sunsubiro, kvina - ekster tempo.^
 
Al kvir donita sezono: aŭtuno, somero, printempo kaj vintro, kvina - ekster tempo.^
 
Al kvir donitaj lunoj: kreskanta, plena, foriranta kaj nova, kvina - ekster tempo.^
 
Kvir al kvina, en centro estanta, rigardas.^
 
Nordokcidente estas loko de plena luno. Landoj de nova, verda - kontraŭ ĝi.^
 
Tigro en tagmezo vagas laŭ landoj propraj.^
 
Vintro ne estas en sudo, sed ne oriente. Printempo ne estas en okcidento.^
 
Turo - ekster tempo, nur koloron ĝi havas.^
 
Lupo en meznokto ĉirkaŭiras landojn propgrajn, tiu kiu someron havas - kontraŭ li.^
 
Luno foriras norde, blanka sunsubiro estanta sude.^
 
Nigra - en la centro, ĉirkaŭita de mateniĝo, sunsubiro, meznokto kaj tagmezo.^
 
Leono helruĝa printempan mateniĝon prezentas.]],
 
    tower_level_3_rockchair = 'Malnova rulseĝo el kverko kun mola gobelena kovrilo. Seĝo estas en bonega stato -- ne havas grataĵojn kaj aspetas kiel nova.',
 
    tower_level_3_room_2_ceiling = 'Sur nigra ŝtona plafono estas instalitaj lampoj, sed nun ili ne lumas.',
 
    tower_level_3_room_2_ceiling_power = 'Sur nigra ŝtona plafono estas instalitaj lampoj, lumantaj helan blankan lumon.',
 
    tower_level_3_room_2_darkness = 'Ĉi tie estas tre mallume, por vidi ion.',
 
    tower_level_3_room_2_darkness_used_candle = 'Kandelo apenaŭ forpelas mallumon. Necesita io plej forta, por bone orientiĝi ĉi tie.',
 
    tower_level_3_room_2_decor_dark = 'Ejo prezentas grandegan tenejon. En {#darkness|mallumo} mi povas ekvidi nur iom {#shelves|bretoj}. Apud mi esas {#ladder|ŝtuparo}, gvidanta supren.',
 
    tower_level_3_room_2_decor_lit = 'Ejo prezentas grandegan tenejon. Apud mi estas {#ladder|ŝtuparo}, gvidanta supren. Sama {#ladder_down|ŝtuparo}, sed gvidanta malsupren, estas apude. {#floor|Planko} ĉi tie estas sama kiel en aliaj ejoj de la turo. {#walls|Muroj} de ĉi tie apenaŭ vidataj, kaŝitaj de {#shelves|bretaroj}. {#ceiling|Plafono} de la halo situas en kvinmetra alto.',
 
    tower_level_3_room_2_disp = 'Turo, Tenejo',
 
    tower_level_3_room_2_door_act_open = 'Mi movas riglilon. Nun vojo liberigita. Pordo gvidas al kabineto, estanta en tria etaĝo de la turo.',
 
    tower_level_3_room_2_door_act_opened = 'Trans malfermita pordo mi vidas kabineton.',
 
    tower_level_3_room_2_door_dsc_closed = 'En unu el muroj estas malgranda {pordo}, farmita per riglilo.',
 
    tower_level_3_room_2_door_dsc_opened = 'En unu el muroj estas malgranda {pordo}.',
 
    tower_level_3_room_2_floor = 'Glataj ŝtonaj platoj estas eltranĉitaj kun grandega ĝusteco kaj aspektas tiel, kvazaŭ ilin tuj ĉi tien oni kuŝigis.',
 
    tower_level_3_room_2_ladder_down = 'Solida metala ŝtuparo foriras vertikale malsupren al sekva etaĝo de la turo.',
 
    tower_level_3_room_2_ladder_up = 'Solida metala ŝtuparo foriras vertikale supren al sekva etaĝo de la turo.',
 
    tower_level_3_room_2_shelves_act_first = 'Mi ĉirkaŭrigardas bretarojn en serĉado de io interesa. Mi prenas de bretoj malgrandan smeraldon kaj ŝraŭbturnilaron. Krom alian mi rimarkas ĉelon, plenan de rezervaj platoj por la komputilo.',
 
    tower_level_3_room_2_shelves_act_second = 'Mi jam vidas nenion utilan por nuna tempo.',
 
    tower_level_3_room_2_walls = 'Mi estas certa, ke se povos atingi muron, do vidos saman glatan facon de nigra ŝtono kiel ĉie.',
 
    tower_level_3_table_deepening_act_empty = 'Malgranda sesangula ingo.',
 
    tower_level_3_table_deepening_act_full = 'Mi prenas %item% el ingo.',  -- %item% is in accusative, lowercase
 
    -- %location% is untranslated and is one of the markings: NW, NE, SE, SW in both keys below
 
    tower_level_3_table_deepening_dsc_empty = [[{Ingo %location%} estas malplena.]],
 
    tower_level_3_table_deepening_dsc_full = [[En ingo %location% estas {%item%}.]],  -- %item% is in nominative, lowercase
 
    tower_level_3_table_deepening_used_fit = 'Mi enigas %item% en ingon.',  -- %item% is in accusative, lowercase
 
    tower_level_3_table_deepening_used_full = 'En ingo jam estas %item%.',  -- %item% is in nominative, lowercase
 
    tower_level_3_table_deepening_used_open = 'Aera klako donas kompreni al mi, ke pordo al sekva etaĝo de la turo estas malfermita.',
 
    tower_level_3_table_decor = 'Grandega tablo prenas grandegan parton en ĉambra centro. Polurita faco briletas en kamena lumo. En tabla faco estas kvin sesangulaj ingoj, kvar el kiu estas markitaj laŭ flankoj de la mondo:: NW, NE, SE, SW, kaj unua, en centro, restigita sen la marko.',
 
    tower_level_3_table_decor_unsolved = 'Laŭ tabla perimetro per mana skribmaniero estas tranĉita ia {#hint|skribaĵo}.';
 
    tower_level_3_table_decor_solved = 'Laŭ tabla perimetro per mana skribmaniero estas tranĉita ia skribaĵo.',
 
    tower_level_3_table_in_figures_act = 'Mi prenas figurojn de la tablo.',
 
    tower_level_3_table_in_figures_dsc = [[Sur ĝi estas {kvin da figuroj} el arĝenta metalo.]],
 
    tower_level_3_table_middle_deepening_dsc_empty = [[{Centra ingo} estas malplena.]],
 
    tower_level_3_table_middle_deepening_dsc_full = [[En centra ingo estas {%item%}.]],  -- %item% is in nominative, lowercase
 
    tower_level_4_bed = 'Grandega lito kovrita de neĝblanka littuko, kudrita per arĝento. Apud litkapo kuŝas granda kuseno en blanka kusensako. Por la homo ĉi lito estas tre vasta, sed ĝi tre malgranda por la drako... Kaj drakoj ne dormas en litoj...',
 
    tower_level_4_candle_act_blow = 'Ia aero, estiĝinta el nenie, estingas bruligitajn kandelojn.',
 
    tower_level_4_candle_act_lit = 'Mi bruligas kandelon. De ie sonas noto %note%.',
 
    tower_level_4_candle_act_open = 'Pordo en malproksima ĉambra rando malfermiĝas pro akra aero.',
 
    tower_level_4_candle_act_sequence = 'En mallumo sonas sonsinsekvo:',
 
    tower_level_4_chandelier_act = 'Belforma arĝenta kandelabro por sep kandeloj. Nun ili ne brulas.',
 
    tower_level_4_decor = 'Mi estas en vasta ĉambro. Kiel en aliaj turaj ejoj, nigraj {tower_walls|muroj} ne havas fenestrojn. En ĉambra centro estas vasta {#bed|lito} kun peza baldakeno el densa nigra ŝtofo, plibeligita per arĝentaj fadenoj. Apud la lito estas malgranda ronda  {#table|tablo} kun arĝenta {#candelabra|kandelabro}.',
 
    tower_level_4_disp = 'Turo, kvara etaĝo',
 
    tower_level_4_door_act_locked = 'Pordo fermita. Mi vidas neniom solvoj malfermi ĝin.',
 
    tower_level_4_door_act_open = 'Pordo malfermita. Trans ĝi mi vidas vastan halon, plenigitan per altaj bretaroj kun serviloj.',
 
    tower_level_4_door_dsc_locked = 'En malproksima muro situas malgranda arba {pordo}.',
 
    tower_level_4_door_dsc_open = 'Arba {pordo} estas malfermita en malproksima rando de la halo.',
 
    tower_level_4_room_2_armchair = 'Komforta malnova seĝo kun radoj. Aspektas kiel nova.',
 
    tower_level_4_room_2_computer_act = 'Komputila aspekto memorigas pri komenco de 80-j jaroj. Diskingoj ne estas. Emblemo "TETS-1" sur sistembloko nenion diras al mi. Energiaj dratoj kaj dratoj de loka reto foriras ien sub la planko. Sur sistembloko estas malgranda {#monitor|monitoro}. Nun komputilo estas elŝaltita -- elektreco ne estas.',
 
    tower_level_4_room_2_computer_used_assemble = 'Mi instalas korpon reen kaj konektas ĉiujn necesitajn dratojn.',
 
    tower_level_4_room_2_computer_used_disassemble = 'Mi elŝaltas ĉiujn dratojn kaj, demetinte iom ŝraŭbojn, demetas kovrilon de korpo.',
 
    tower_level_4_room_2_decor = 'Laŭ hala muroj estas instalitaj stativoj kun {#servers|serviloj}. En hala centro estas masiva arba {#table|tablo}, sur kiu estas malnova {#computer|komputilo}. Antaŭ tablo estas peza malnova {#armchair|seĝo}. Apude tablo estas {#ladder|ŝtuparo}, iranta al malsupraj etaĝoj de la turo.',
 
    tower_level_4_room_2_disp = 'Turo, servilejo',
 
    tower_level_4_room_2_ladder = 'Solida metala ŝtuparo estas metita ĉi tie kaj foriras vertikale malsupren.',
 
    tower_level_4_room_2_monitor = 'Malgranda vidigilo kun elektro-radia tubo. Ekrana diagonalo estas ĉirkaŭ 8 coloj, dekstre de ĝi mi vidas iloj por kontrolo de heleco kaj kontrasteco.',
 
    tower_level_4_room_2_servers = 'Centoj, se ne miloj, de serviloj. Mi ne konas, por kio ili estas ĉi tie. Nun ili senergiaj.',
 
    tower_level_4_room_2_servers_powered = 'Centoj, se ne miloj, de serviloj. Mi ne konas, por kio ili estas ĉi tie. Glata rumoro de funkciantaj ventoliloj kaj aereco de durdiskoj priparolas pri funkciado de maŝinoj. Briletantaj lampetoj montras agojn, estantaj en ili.',
 
    tower_level_4_room_2_table = 'Solida kverka tablo kun masivaj ĉizaj piedoj. Sur polurita faco estas neniom grataĵoj. Grandan parton de la tablo tenas komputilo. Apud la klavaro estas {#manual|libro}.',
 
    tower_level_4_table = 'Malgranda tablo el luksa nigra arbo subteniĝas per sola masiva piedo.',
 
    tower_red_key_disp = 'Ruĝa ŝlosilo',
 
    tower_red_key_disp2 = 'ruĝa ŝlosilo',
 
    tower_red_key_disp3 = 'ruĝan ŝlosilon',
 
    tower_red_key_inv = 'Malgranda ŝlosilo el ruĝa metalo.',
 
    transition_airlock = 'En kluzon',
 
    transition_control = 'En administrejon',
 
    transition_dining_room = 'En manĝejon',
 
    transition_door = 'En pordon',
 
    transition_downstairs = 'Malsupren',
 
    transition_lab = 'En laborejon',
 
    transition_leave = 'Eliri el turo',
 
    transition_reactor = 'En reakciujan kameraon',
 
    transition_room = 'En apudan ĉambron',
 
    transition_study = 'En kabineton',
 
    transition_upstairs = 'Supren',
 
    troubleshooting_manual_disp = 'Solvo de problemoj',
 
    troubleshooting_manual_dsc = [[        Problemo: OS ne startas. Ne estas bildo en ekrano. Ne estas sona signalo^
 
        Kaŭzo: Energia malekzisto aŭ difekteco de ĉefa plato^
 
        Solvo: ^
 
        1. Kontrolu energion^
 
        2. Anstataŭigu ĉefan platon^
 
        Problemo: OS ne startas. Ne estas bildo en ekrano. Sonaj signaloj: longa-mallonga-longa^
 
        Kaŭzo: difekteco aŭ malekzisto de centra procesoro^
 
        Solvo: ^
 
        1. Instalu aŭ anstataŭigu centran procesoron^
 
        Problemo: OS ne startas. Ne estas bildo en ekrano. Sonaj signaloj: mallonga-longa-longa^
 
        Kaŭzo: Difekteco aŭ malekzisto de operacia memoro^
 
        Solvo: ^
 
        1. Instalu aŭ anstataŭigu operacian memoron^
 
        Problemo: OS ne startas. Ne estas bildo en ekrano. Sonaj signaloj: longa-mallonga-longa^
 
        Kaŭzo: Difekteco aŭ malekzisto de videoadaptilo^
 
        Solvo: ^
 
        1. Instalu aŭ anstataŭigu videoadaptilon^
 
        Problemo: OS ne startas. Ne estas bildo en ekrano. Sonaj signaloj: longa-longa-longa^
 
        Kaŭzo: Difekteco aŭ malekzisto de klavarkromaĵo^
 
        Solvo: ^
 
        1.  Instalu aŭ anstataŭigu klavarkromaĵon^
 
        Problemo: OS ne startas. Mesaĝo en ekrano: "Starto de malekzistas"^
 
        Kaŭzo: Malekzisto de kongrua ŝargilo^
 
        Solvo: ^
 
        1. Instalu kongruan ŝargilon (ekzemple, retadaptilon de FNA serio)^
 
      ]],
 
    walls_dlg_enter = 'Apenaŭ mi tuŝas glatan ŝtonon de muroj, kiel en mia konscio sonoras velura ina voĉo: "Bonvenon hejmen". Mi forigas manon.',
 
    walls_dlg_enter_solarscale = 'Sunskvamet alflugas kaj tuŝinte mian ŝultron, demandas: "Ĉio orde?"',
 
    walls_dlg_p1 = 'Jes, al mi bone estas.',
 
    walls_dlg_p1_r = 'Sunskvamet atente rigardas miajn okulojn. Malalta voĉo, aŭdita de mi, ne similas sonoran kaj helan parolon de drakino, sed krom ni apud neniu estas. Do ĉi tio estas la turo?',
 
    walls_dlg_p2 = 'Vi ion diris?',
 
    walls_dlg_p2_r = '"Ne, certe ne" -- respondas drakino. Mi sensacas kiom malalta voĉo, aŭdita de mi, ne similas al sonora kaj hela parolo de drakino. Do ĉi tio estas la turo?',
 
    walls_dlg_p3 = 'Ne povus vi tuŝi muron?',
 
    walls_dlg_p3_r = 'Sunskvamet, ŝultruminte, tuŝas muron kaj tuj forigas manon. Larĝe malferminte siajn okulojn, ŝi flustras: "Mi ankaŭ ĉi tion aŭdis!"',
 
    walls_dlg_p4 = '[Tuŝi muron ankoraŭfoje]',
 
    walls_dlg_p4_r = 'Mi ree tuŝas nigrajn murojn, sed nenio okazas. Mire, sed mi ne sentas antaŭan malkomforton, male, tuŝo kvietigas kaj donas certecon.',
 
    walls_dlg_p5 = '[Deiri]',
 
    walls_dlg_p5_r = 'Mi deiras de muro, malkomprenante.',
 
    walls_dlg_p6 = 'Kiu estas ĉi tie?',
 
    walls_dlg_p6_r = 'Neniu respondas. Mi dum iom tempo aŭdas silenton de turo. Malvarmeta duonmallumo kvietigas kaj logas.',
 
  },
 
  parts_locale = {
 
    component_not_set = 'Ne estas',
 
    cpu = 'Procesoro',
 
    cpu_installed = 'Mi instalas procesoron.',
 
    cpu_needs_removal = 'Komence necese formeti instalitan procesoron.',
 
    cpu_not_fit = 'Procesoro ne konvenas.',
 
    cpu_inv_from_box = 'Procesoro %model%, elprenita el skatolo por rezervaĵoj.',
 
    cpu_inv_from_computer = 'Procesoro %model%, elprenita el komputilo.',
 
    cpu_tak = 'Mi prenas procesoron %model%.',
 
    cpu_title = 'Procesoro %model%',
 
    device_installed = 'Mi instlas karton.',
 
    device_needs_removal = 'Komence necese formeti instalitan karton.',
 
    keyboard_controller_inv_from_box = 'Klavarkontrolilo %model%, elprenita el skatolo por rezervaĵoj.',
 
    keyboard_controller_inv_from_computer = 'Klavarkontrolilo %model%, elprenita el komputilo.',
 
    keyboard_controller_tak = 'Mi prenas klavarontrolilon %model%.',
 
    keyboard_controller_title = 'Klavarkontrolilo %model%',
 
    motherboard = 'Ĉefkarto',
 
    motherboard_installed = 'Mi instalas ĉefkarton.',
 
    motherboard_needs_removal = 'Komence necese formeti instalitan karton.',
 
    motherboard_not_taken = 'Komence necese elŝalti ĉiujn ilojn.',
 
    motherboard_inv_from_box = 'Ĉefkarto %model%, elprenita el skatolo por rezervaĵoj.',
 
    motherboard_inv_from_computer = 'Ĉefkarto %model%, elprenita el komputilo.',
 
    motherboard_tak = 'Mi prenas ĉefkarton %model%.',
 
    motherboard_title = 'Ĉefkarto %model%',
 
    network_adapter_inv_from_box = 'Retkarto %model%, elprenita el skatolo por rezervaĵo.',
 
    network_adapter_inv_from_computer = 'Retkarto %model%, elprenita el komputilo.',
 
    network_adapter_tak = 'Mi prenas retkarton %model%.',
 
    network_adapter_title = 'Retkarto %model%',
 
    ram = 'Ĉefmemoro',
 
    ram_installed = 'Mi instalas memoron.',
 
    ram_needs_removal = 'Komence necese formeti instalitan memoron.',
 
    ram_not_fit = 'Memoro ne konvenas.',
 
    ram_inv_from_box = 'Memorkromaĵo %model%, elprenita el skatolo por rezervaĵoj.',
 
    ram_inv_from_computer = 'Memorkromaĵo %model%, elprenita el komputilo.',
 
    ram_tak = 'Mi prenas memorkromaĵon %model%.',
 
    ram_title = 'Memorkromaĵo %model%',
 
    slot = 'Aldonĉelo',
 
    videocard_inv_from_box = 'Bildigilo %model%, elprenita el skatolo por rezervaĵoj.',
 
    videocard_inv_from_computer = 'Bildigilo %model%, elprenita el komputilo.',
 
    videocard_tak = 'Mi prenas bildigilon %model%.',
 
    videocard_title = 'Bildigilo %model%',
 
  },
 
  note_locale = {
 
    note_a = 'La',
 
    note_b = 'Si',
 
    note_c = 'Do',
 
    note_d = 'Re',
 
    note_e = 'Mi',
 
    note_f = 'Fa',
 
    note_g = 'Sol',
 
  },
 
  ending_locale = {
 
    ending_dissolving_tower_solarscale = 'Sur unu el randaltaĵaro de kratero sidas ora drakino. Ŝia skvamo brilas de sunlumstrioj, kaj smerald-verdaj okuloj rigardas krateran centron, malrapide malaperantan turon en aero.',
 
    ending_dissolving_tower_solarscale_alt = 'Drakino teriĝas sur unu el randaltaĵaro de kratero. Ŝia skvamo brilas de sunlumstrioj, kaj smerald-verdaj okuloj rigardas krateran centron, malrapide malaperantan turon en aero.',
 
    ending_solarscale_flight = 'Sunskvamet kun ravo rigardas min kaj malaperantajn murojn de turo. Ĉirkaŭflugis, ŝi revenas kaj atendas miajn sekvajn decidojn.',
 
    ending_solarscale_pre = 'Aera tuŝo distras min de konzolo. Mi turniĝas. Sunskvamet adiaŭdiras: "Mi devas foriri. Mi esperas, ke plu renkontiĝos!"',
 
    ending_welcome = 'En konscia mia sonas aera, kvieta kaj, verŝajne, antaŭlonge konata voĉo: "Bonvenon hejmen". Muroj komencas malaperiĝi, malfermante vidaĵon al senlimaj spacoj de la universo.',
 
    formatted_2 = 'Jarcento post jarcento mi revenas al ĉi loko, sed trovas nenion, krom forgesitajn de ĉiuj fragmentojn de nigra ŝtono.',
 
    formatted_alone = 'Mi deiras komputilon kaj en ĉi momento sentas malteneblan ŝanĝon, okazinta en turo. La mondo ĉirkaŭ mi komenciĝis malaperi kaj baldaŭ mi trovis sin en arbaro. Ĉie estas fragmentoj de nigra ŝtono, tuj konsistiginta turon, kvankam koni ĝin en ili estus malfacile. Suspirinte, mi etendas flugilojn kaj startas hejmen.',
 
    formatted_solarscale = 'Mi deiras komputilon kaj en ĉi momento sentas malteneblan ŝanĝon, okazinta en turo. La mondo ĉirkaŭ ni komenciĝis malaperi kaj baldaŭ ni trovis sin en arbaro. Ĉie estas fragmentoj de nigra ŝtono, tuj konsistiginta turon, kvankam koni ĝin en ili estus malfacile. Interrigardis kun Sunskvamet, ni adiaŭas kaj startas laŭ propra vojo.',
 
    game_end = 'Fino de la ludo',
 
    irradiated = 'De tiaj tempoj kiam mi forlasis turon, min ne restigas stranga sento, kvazaŭ miaj tagoj forflugas -- mia magio malfortiĝas kaj flugiloj jam ne povas teni min.',
 
    left_part_1 = 'Mallumo ĉirkaŭ mi estigas sentebla, kvazaŭ turo komencas rifuzi min. Mi trairas pordon, kaj masiva ŝtona plato malleviĝas, por jarcentoj fermante vojon enen.',
 
    left_part_1_solarscale = 'Sunskvamet penseme rigardas min kaj turon. Iom da tempo ni zorge esploras ĝin ĉirkaŭe, sed finfine, malesperinte, startas ĉiu laŭ propra vojo.',
 
    left_part_2 = 'Jarcento post jarcento mi revenas al ĉi loko, sed glata nigra ŝtono ankaŭ estas malatingebla por mi.',
 
    left_state_1 = 'Mi faras paŝon al porda flanko, sed io haltigas min. Kion fari, se dua ŝanco ne estos?',
 
    left_state_2 = 'Mi daŭrigas movi al elirejo. En mia kapo aperas bildo de tura pordo, kiu fermiĝas post mi.',
 
    left_state_3 = 'Mi daŭrigas movi al elirejo de turo, aero kvazaŭ densiĝas antaŭ mi, ne dezirante min ellasi.',
 
    show_menu = 'En ĉefan menuon',
 
    solarscale_lost = 'Kaj ne povas mi trovi Sunskvameton -- kiom mi ne provis, mi ĝis nun ne povis eltrovi neniajn spurojn de belega drakino.',
 
    thank_you_for_playing = 'Dankon pro ludo',
 
    true_solarscale_convince_level_1 = 'Sunskvamet haltas en pensaĵojn.',
 
    true_solarscale_convince_level_2 = 'Sunskvamet nedesideme rigardas min.',
 
    true_solarscale_convince_level_3 = 'Sunskvamet silente rigardas min.',
 
    true_solarscale_convince_level_4 = 'Sunskvamet jesas kaj laŭ certo diras: "Bone, mi kun vi".',
 
    true_solarscale_dlg_1 = '[Kapti Sunskvametan manon]',
 
    true_solarscale_dlg_1_response = 'Mi aŭdas voĉon en mia kapo: "Restigu ŝin. Ŝi havas sian vojon". Pro miro mi diskaptas manon. Ĉi estas sufiĉe, por drakino forflugis.',
 
    true_solarscale_dlg_2 = 'Vi ne volas resti?',
 
    true_solarscale_dlg_2_response = '"Mi ne povas, mi havas farojn hejme" -- kviete respondas drakino. En ŝia voĉo estas maldecidemo.',
 
    true_solarscale_dlg_3 = 'Al vi ne estas interese, kio estos plu?',
 
    true_solarscale_dlg_4 = 'Se vi foriros nun, do ni ne intervidos plu.',
 
    true_solarscale_dlg_5 = 'Ĉi turo estas nia hejmo.',
 
    true_solarscale_dlg_6 = 'Vi ne povas foriri nun, turo malfermiĝis kaj por vi.',
 
    true_solarscale_dlg_7 = 'Al vi ne ŝajnas, ke ni ne estas malbona? Al mi estos malfacile sen vi.',
 
    true_solarscale_dlg_8 = 'Pripensu, kiom plu belegaj lokoj nin atendas.',
 
    true_solarscale_dlg_end = 'Nu, mi ne prenos vin. Ĝis novaj revidoj.',
 
    true_solarscale_dlg_end_response = 'Sunskvamet lasas fali sian kapon kaj, kviete dirinte: "Ĝis revido", forlasas ejon.',
 
    true_solarscale_dlg_enter = 'En ĉi momento mi sentas aeran tuŝon, redonanta min al realo. Mi turniĝas. Sunskvamet diras adiaŭvortojn: "Estas mia tempo por foriro. Esperas, ke mi plu intervidos".',
 
    true_solarscale_leaving = 'Mi ja ne palpebrumas, kiel Sunskvamet forlasas turon. Verŝajne, mi vidas per miaj okuloj, kiel drakino elflugas tra embrazuro en unua etaĝo kaj peza ŝtona plato malleviĝas post ŝi.',
 
    true_solarscale_outside_part_2 = 'Kiam turo plene malaperis, drakino etindas siajn maldikajn brilajn flugilojn kaj flugas en ĉielon.',
 
    true_solarscale_stays = 'Mia percepto ŝanĝiĝas. Mi kvazaŭ vidas el flanko, kiel turo malaperas en aero, portante nin trans limoj de kutima mondo. Sunskvamet mire haltis apud mi, rigardante okazanton kaj atendante miajn sekvajn decidojn.',
 
    true_step_1 = 'Mi iras al alto kaj laŭpenso donas komandon al starto. Antaŭ mia rigardo aperis senlima universo. Ĉiuj vojoj kaj mondoj estas malfermitaj antaŭ mi. Laŭ mia volo mi povas trovi sin en ajna loko en ajna tempo.',
 
    true_step_1_alone = 'Komence min mirigas, kiel forte turo reagas min, sed baldaŭ mi kutimiĝas al tio, ke ĉio necesata ĉiam estas sub mia mano.',
 
    true_step_1_solarscale = 'Komence min mirigas, kiel forte turo reagas nin, sed baldaŭ mi kutimiĝas al tio, ke ĉio necesata ĉiam estas sub mia mano. Ankaŭ tiel Sunskvamet ĉiam estas en apuda ĉambro kun mi.',
 
    true_step_2_alone = 'Jarmilo post jarmilo mi vojaĝas laŭ universoj kaj epokaj, kolektante ilian heredaĵon. Baldaŭ tempo kaj spaco ĉesas havi por mi kian ajnan valoron.',
 
    true_step_2_irradiated = 'Jarmilo post jarmilo mi vojaĝas laŭ universoj kaj epokoj, kolektante ilian heredaĵon. Malgraŭ ĉi tion, stranga sento ne donas kvieton al mi -- kvazaŭ tagoj miaj malrapide forflugas kaj vojaĝo mia ne estos eterna.',
 
    true_step_2_solarscale = 'Jarmilo post jarmilo ni vojaĝas laŭ universoj kaj epokoj, kolektante ilian heredaĵon. Baldaŭ tempo kaj spaco ĉesas havi por ni kian ajnan valoron.',
 
  },
 
}
translation/ru.lua
Show inline comments
 
@@ -11,7 +11,7 @@ set_locale_data {
 
    key_does_not_fit = 'Ключ не подходит.'
 
  },
 
  link_locale = {
 
		copied = 'Скопировано',
 
    copied = 'Скопировано',
 
  },
 
  main_locale = {
 
    empty_act = 'Я не знаю, что с этим сделать.',
 
@@ -33,6 +33,7 @@ set_locale_data {
 
    credits_music = 'Музыка',
 
    credits_sounds = 'Звуки',
 
    credits_thanks = 'Спасибо, что играете в нашу игру!',
 
    credits_translation = 'Перевод',
 
    cursor_scale = 'Размер курсора',
 
    disable = 'Отключить',
 
    enable = 'Включить',
 
@@ -49,6 +50,7 @@ set_locale_data {
 
    normal = 'Обычный',
 
    padding = 'Отступ',
 
    system_settings = 'Системные настройки',
 
    simplified_animation = 'Упрощенная анимация',
 
    text_alignment = 'Выравнивание текста',
 
    text_alignment_justify = 'По ширине',
 
    text_alignment_left = 'По левому краю',
 
@@ -158,10 +160,10 @@ set_locale_data {
 
    tutorial_map_hint_leave_treasury = 'Вернитесь в главный зал и перейдите оттуда в кабинет.',
 
    tutorial_map_inv = 'Старинная карта небольшого участка земли. Аккуратная отметка в виде креста указывает на какое-то поселение. Я потратил столетия на безуспешные поиски этого места.',
 
    tutorial_start = 'Добро пожаловать!',
 
    tutorial_start_decor = [[				Добро пожаловать в игру "Дракон и Башня". Этот раздел познакомит вас с игрой и научит в нее играть. ^
 
    tutorial_start_decor = [[        Добро пожаловать в игру "Дракон и Башня". Этот раздел познакомит вас с игрой и научит в нее играть. ^
 
        Игра состоит из комнат, у каждой из которых есть название и описание. Кроме того, в комнате могут находиться объекты, с которыми вы можете взаимодействовать. ^
 
        Это тоже комната. Она называется "Добро пожаловать!", а описание ее вы сейчас читаете.
 
			]],
 
      ]],
 
    tutorial_start_decor_hint = 'Мы предлагаем вам сыграть в небольшой пролог к Дракону и Башне. Жирным шрифтом мы будем выделять инструкции и комментарии. Нажмите "Продолжить", чтобы начать пролог.',
 
    tutorial_study = 'Логово, кабинет',
 
    tutorial_study_decor = 'Небольшая круглая пещерка около трех метров высотой и не более трех в диаметре. У стены я поместил стол, на котором сейчас покоится {#laptop|ноутбук}. Настало время узнать, где же находится это место.',
tutorial.lua
Show inline comments
 
obj {
 
	nam = 'tutorial_key';
 
	disp = translate("tutorial_locale", 'tutorial_key');
 
	inv = function(s)
 
		pr(translate_now("tutorial_locale", 'tutorial_key_inv') .. '^');
 
		if have('tutorial_box') then
 
			pr(fmt.b(translate_now("tutorial_locale", 'tutorial_box_hint')));
 
		else
 
			pr(fmt.b(translate_now("tutorial_locale", 'tutorial_key_inv_look_for_box')));
 
		end;
 
	end;
 
  nam = 'tutorial_key';
 
  disp = translate("tutorial_locale", 'tutorial_key');
 
  inv = function(s)
 
    pr(translate_now("tutorial_locale", 'tutorial_key_inv') .. '^');
 
    if have('tutorial_box') then
 
      pr(fmt.b(translate_now("tutorial_locale", 'tutorial_box_hint')));
 
    else
 
      pr(fmt.b(translate_now("tutorial_locale", 'tutorial_key_inv_look_for_box')));
 
    end;
 
  end;
 
}
 

	
 
obj {
 
	nam = 'tutorial_disk';
 
	disp = translate("tutorial_locale", 'tutorial_disk');
 
	inv =  translate("tutorial_locale", 'tutorial_disk_inv');
 
  nam = 'tutorial_disk';
 
  disp = translate("tutorial_locale", 'tutorial_disk');
 
  inv =  translate("tutorial_locale", 'tutorial_disk_inv');
 
};
 

	
 
obj {
 
	nam = 'tutorial_box';
 
	disp = translate("tutorial_locale", 'tutorial_box');
 
	inv = function(s)
 
		return translate_now("tutorial_locale", 'tutorial_box_inv') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_box_hint'));
 
	end;
 
	used = function(s, o)
 
		if o ^ 'tutorial_key' then
 
			take('tutorial_map');
 
			remove('tutorial_box', pl);
 
			remove('tutorial_key', pl);
 
			return translate_now("tutorial_locale", 'tutorial_box_used') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_box_used_hint'));
 
		end;
 
	end;
 
  nam = 'tutorial_box';
 
  disp = translate("tutorial_locale", 'tutorial_box');
 
  inv = function(s)
 
    return translate_now("tutorial_locale", 'tutorial_box_inv') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_box_hint'));
 
  end;
 
  used = function(s, o)
 
    if o ^ 'tutorial_key' then
 
      take('tutorial_map');
 
      remove('tutorial_box', pl);
 
      remove('tutorial_key', pl);
 
      return translate_now("tutorial_locale", 'tutorial_box_used') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_box_used_hint'));
 
    end;
 
  end;
 
};
 

	
 
obj {
 
	nam = 'tutorial_map';
 
	disp = translate("tutorial_locale", 'tutorial_map');
 
	inv = function(s)
 
		pr(translate_now("tutorial_locale", 'tutorial_map_inv'));
 
		if here() ^ 'tutorial_treasury' then
 
			if have('tutorial_disk') then
 
				pr(fmt.b("^" .. translate_now("tutorial_locale", 'tutorial_map_hint_leave_treasury')));
 
			else
 
				pr(fmt.b("^" .. translate_now("tutorial_locale", 'tutorial_map_hint_find_disk')));
 
			end;
 
		elseif here() ^ 'tutorial_lair' then
 
			pr(fmt.b("^" .. translate_now("tutorial_locale", 'tutorial_map_hint_go_to_study')));
 
		end;
 
	end;
 
  nam = 'tutorial_map';
 
  disp = translate("tutorial_locale", 'tutorial_map');
 
  inv = function(s)
 
    pr(translate_now("tutorial_locale", 'tutorial_map_inv'));
 
    if here() ^ 'tutorial_treasury' then
 
      if have('tutorial_disk') then
 
        pr(fmt.b("^" .. translate_now("tutorial_locale", 'tutorial_map_hint_leave_treasury')));
 
      else
 
        pr(fmt.b("^" .. translate_now("tutorial_locale", 'tutorial_map_hint_find_disk')));
 
      end;
 
    elseif here() ^ 'tutorial_lair' then
 
      pr(fmt.b("^" .. translate_now("tutorial_locale", 'tutorial_map_hint_go_to_study')));
 
    end;
 
  end;
 
};
 

	
 
room {
 
	nam = 'tutorial_start';
 
	disp = translate("tutorial_locale", 'tutorial_start');
 
	theme = 'main';
 
	pic = 'images/main_theme/stub.png';
 
	enter = function(s)
 
  nam = 'tutorial_start';
 
  disp = translate("tutorial_locale", 'tutorial_start');
 
  theme = 'main';
 
  pic = 'images/main_theme/stub.png';
 
  enter = function(s)
 
    -- reset tutorial
 
      _('tutorial_lair').state = 0;
 
      _('tutorial_treasury').state = 0;
 
      lookup('#chests', 'tutorial_treasury').state = 0;
 
      lookup('#disks', 'tutorial_treasury').state = 0;
 
      
 
		if here():from()^'intro_start' or here():from()^'intro_settings' or here():from()^'intro_info' then
 
			stop_menu();
 
		end;
 
		snd.music('sound/bgm_forest.ogg');
 
	end;
 
	decor = function(s)
 
		return translate_now("tutorial_locale", 'tutorial_start_decor') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_start_decor_hint'));
 
	end;
 
	way = {
 
		path {translate("common_locale", "back"), 'main'};
 
		path {translate("common_locale", "continue"), 'tutorial_lair'};
 
	};
 
    if here():from()^'intro_start' or here():from()^'intro_settings' or here():from()^'intro_info' then
 
      stop_menu();
 
    end;
 
    snd.music('sound/bgm_forest.ogg');
 
  end;
 
  decor = function(s)
 
    return translate_now("tutorial_locale", 'tutorial_start_decor') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_start_decor_hint'));
 
  end;
 
  way = {
 
    path {translate("common_locale", "back"), 'main'};
 
    path {translate("common_locale", "continue"), 'tutorial_lair'};
 
  };
 
}
 

	
 
room {
 
	state = 0;
 
	nam = 'tutorial_lair';
 
	disp = translate("tutorial_locale", 'tutorial_lair');
 
	theme = 'main';
 
	pic = 'images/main_theme/stub.png';
 
	decor = function(s)
 
		pr(translate_now("tutorial_locale", 'tutorial_lair_decor_1'));
 
		
 
		if s.state == 0 then
 
			pr(fmt.b(' (' .. translate_now("tutorial_locale", 'tutorial_lair_decor_hint_caves') .. ')'));
 
		end;
 
		
 
		pn(". " .. translate_now("tutorial_locale", 'tutorial_lair_decor_2'));
 
		
 
		if s.state == 1 then
 
			if not have('tutorial_disk') then
 
				pr(fmt.b(translate_now("tutorial_locale", 'tutorial_lair_decor_hint_treasury')));
 
			else
 
				pr(fmt.b(translate_now("tutorial_locale", 'tutorial_lair_decor_hint_study')));
 
			end;
 
		end;
 
	end;
 
	onenter = function(s, f)
 
		if f ^ 'tutorial_start' then
 
			pr(translate_now("tutorial_locale", 'tutorial_lair_enter_start'));
 
		elseif f ^ 'tutorial_treasury' and not have('tutorial_disk') then
 
			pr(translate_now("tutorial_locale", 'tutorial_lair_enter_treasury'));
 
				
 
			if have('tutorial_map') and not have('tutorial_disk') then
 
				pr(fmt.b('^' .. translate_now("tutorial_locale", "tutorial_lair_enter_disk")));
 
			end;
 
			return false;
 
		end;
 
	end;
 
	way = {
 
		path {translate("tutorial_locale", "tutorial_to_treasury"), 'tutorial_treasury'};
 
		path {translate("tutorial_locale", "tutorial_to_study"), 'tutorial_cabinet'};
 
	};
 
  state = 0;
 
  nam = 'tutorial_lair';
 
  disp = translate("tutorial_locale", 'tutorial_lair');
 
  theme = 'main';
 
  pic = 'images/main_theme/stub.png';
 
  decor = function(s)
 
    pr(translate_now("tutorial_locale", 'tutorial_lair_decor_1'));
 
    
 
    if s.state == 0 then
 
      pr(fmt.b(' (' .. translate_now("tutorial_locale", 'tutorial_lair_decor_hint_caves') .. ')'));
 
    end;
 
    
 
    pn(". " .. translate_now("tutorial_locale", 'tutorial_lair_decor_2'));
 
    
 
    if s.state == 1 then
 
      if not have('tutorial_disk') then
 
        pr(fmt.b(translate_now("tutorial_locale", 'tutorial_lair_decor_hint_treasury')));
 
      else
 
        pr(fmt.b(translate_now("tutorial_locale", 'tutorial_lair_decor_hint_study')));
 
      end;
 
    end;
 
  end;
 
  onenter = function(s, f)
 
    if f ^ 'tutorial_start' then
 
      pr(translate_now("tutorial_locale", 'tutorial_lair_enter_start'));
 
    elseif f ^ 'tutorial_treasury' and not have('tutorial_disk') then
 
      pr(translate_now("tutorial_locale", 'tutorial_lair_enter_treasury'));
 
        
 
      if have('tutorial_map') and not have('tutorial_disk') then
 
        pr(fmt.b('^' .. translate_now("tutorial_locale", "tutorial_lair_enter_disk")));
 
      end;
 
      return false;
 
    end;
 
  end;
 
  way = {
 
    path {translate("tutorial_locale", "tutorial_to_treasury"), 'tutorial_treasury'};
 
    path {translate("tutorial_locale", "tutorial_to_study"), 'tutorial_cabinet'};
 
  };
 
}:with {
 
	obj {
 
		nam = '#caves';
 
		act = function(s)
 
			pr (translate_now("tutorial_locale", 'tutorial_lair_caves_act') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_lair_caves_act_hint')));
 
			here().state = 1;
 
		end;
 
	};
 
	obj {
 
		nam = '#exit';
 
		act = translate("tutorial_locale", 'tutorial_lair_exit_act');
 
	};
 
  obj {
 
    nam = '#caves';
 
    act = function(s)
 
      pr (translate_now("tutorial_locale", 'tutorial_lair_caves_act') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_lair_caves_act_hint')));
 
      here().state = 1;
 
    end;
 
  };
 
  obj {
 
    nam = '#exit';
 
    act = translate("tutorial_locale", 'tutorial_lair_exit_act');
 
  };
 
}
 

	
 
room {
 
	state = 0;
 
	nam = 'tutorial_treasury';
 
	disp = translate("tutorial_locale", 'tutorial_treasury');
 
	theme = 'main';
 
	pic = 'images/main_theme/stub.png';
 
	onenter = function(s)
 
		if have('tutorial_disk') then
 
			pr(translate_now("tutorial_locale", 'tutorial_treasury_no_enter'));
 
			return false;
 
		end;
 
	end;
 
	decor = function(s)
 
		p(translate_now("tutorial_locale", 'tutorial_treasury_decor'));
 
		if not have('tutorial_map') then
 
			pr(fmt.b(translate_now("tutorial_locale", 'tutorial_treasury_decor_hint_map')));
 
		elseif have('tutorial_disk') then
 
			pr(fmt.b(translate_now("tutorial_locale", 'tutorial_treasury_decor_hint_leave')));
 
		end;
 
		
 
	end;
 
	way = {
 
		path {translate("tutorial_locale", "tutorial_to_main_hall"), 'tutorial_lair'};
 
	}
 
  state = 0;
 
  nam = 'tutorial_treasury';
 
  disp = translate("tutorial_locale", 'tutorial_treasury');
 
  theme = 'main';
 
  pic = 'images/main_theme/stub.png';
 
  onenter = function(s)
 
    if have('tutorial_disk') then
 
      pr(translate_now("tutorial_locale", 'tutorial_treasury_no_enter'));
 
      return false;
 
    end;
 
  end;
 
  decor = function(s)
 
    p(translate_now("tutorial_locale", 'tutorial_treasury_decor'));
 
    if not have('tutorial_map') then
 
      pr(fmt.b(translate_now("tutorial_locale", 'tutorial_treasury_decor_hint_map')));
 
    elseif have('tutorial_disk') then
 
      pr(fmt.b(translate_now("tutorial_locale", 'tutorial_treasury_decor_hint_leave')));
 
    end;
 
    
 
  end;
 
  way = {
 
    path {translate("tutorial_locale", "tutorial_to_main_hall"), 'tutorial_lair'};
 
  }
 
}:with {
 
	obj {
 
		nam = '#items';
 
		act = translate("tutorial_locale", 'tutorial_treasury_items_act');
 
	};
 
	obj {
 
		state = 0;
 
		nam = '#chests';
 
		act = function(s)
 
			if s.state == 0 then
 
				s.state = 1;
 
				take('tutorial_key');
 
				return translate_now("tutorial_locale", 'tutorial_treasury_chests_act_key') .. "^" .. fmt.b(translate_now("tutorial_locale", 'tutorial_treasury_chests_act_key_hint'));
 
			elseif s.state == 1 then
 
				s.state = 2;
 
				take('tutorial_box');
 
				return translate_now("tutorial_locale", 'tutorial_treasury_chests_act_box');
 
			else
 
				return translate_now("tutorial_locale", 'tutorial_treasury_chests_act_default');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#books';
 
		act = translate("tutorial_locale", 'tutorial_treasury_books');
 
	};
 
	obj {
 
		nam = '#scrolls';
 
		act = function(s)
 
			pr(translate_now("tutorial_locale", 'tutorial_treasury_scrolls'));
 
		
 
			if not have('tutorial_map') then
 
				return translate_now("tutorial_locale", 'tutorial_treasury_scrolls_no_map');
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#records';
 
		act = translate("tutorial_locale", 'tutorial_treasury_records');
 
	};
 
	obj {
 
		state = 0;
 
		nam = '#disks';
 
		act = function(s)
 
			pr(translate_now("tutorial_locale", 'tutorial_treasury_disks'));
 
			if s.state == 1 or not have('tutorial_map') then
 
				pr(translate_now("tutorial_locale", 'tutorial_treasury_disks_default'));
 
			else
 
				s.state = 1;
 
				take('tutorial_disk');
 
				pr(translate_now("tutorial_locale", 'tutorial_treasury_disks_found') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_treasury_disks_hint')));
 
			end;
 
		end;
 
	};
 
	obj {
 
		nam = '#paintings';
 
		act = translate("tutorial_locale", 'tutorial_treasury_paintings');
 
	};
 
  obj {
 
    nam = '#items';
 
    act = translate("tutorial_locale", 'tutorial_treasury_items_act');
 
  };
 
  obj {
 
    state = 0;
 
    nam = '#chests';
 
    act = function(s)
 
      if s.state == 0 then
 
        s.state = 1;
 
        take('tutorial_key');
 
        return translate_now("tutorial_locale", 'tutorial_treasury_chests_act_key') .. "^" .. fmt.b(translate_now("tutorial_locale", 'tutorial_treasury_chests_act_key_hint'));
 
      elseif s.state == 1 then
 
        s.state = 2;
 
        take('tutorial_box');
 
        return translate_now("tutorial_locale", 'tutorial_treasury_chests_act_box');
 
      else
 
        return translate_now("tutorial_locale", 'tutorial_treasury_chests_act_default');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#books';
 
    act = translate("tutorial_locale", 'tutorial_treasury_books');
 
  };
 
  obj {
 
    nam = '#scrolls';
 
    act = function(s)
 
      pr(translate_now("tutorial_locale", 'tutorial_treasury_scrolls'));
 
    
 
      if not have('tutorial_map') then
 
        return translate_now("tutorial_locale", 'tutorial_treasury_scrolls_no_map');
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#records';
 
    act = translate("tutorial_locale", 'tutorial_treasury_records');
 
  };
 
  obj {
 
    state = 0;
 
    nam = '#disks';
 
    act = function(s)
 
      pr(translate_now("tutorial_locale", 'tutorial_treasury_disks'));
 
      if s.state == 1 or not have('tutorial_map') then
 
        pr(translate_now("tutorial_locale", 'tutorial_treasury_disks_default'));
 
      else
 
        s.state = 1;
 
        take('tutorial_disk');
 
        pr(translate_now("tutorial_locale", 'tutorial_treasury_disks_found') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_treasury_disks_hint')));
 
      end;
 
    end;
 
  };
 
  obj {
 
    nam = '#paintings';
 
    act = translate("tutorial_locale", 'tutorial_treasury_paintings');
 
  };
 
}
 

	
 
room {
 
	nam = 'tutorial_cabinet';
 
	disp = translate("tutorial_locale", 'tutorial_study');
 
	theme = 'main';
 
	pic = 'images/main_theme/stub.png';
 
	onenter = function(s)
 
		if not have('tutorial_disk') then
 
			pr(translate_now("tutorial_locale", 'tutorial_study_enter') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_study_enter_hint')));
 
			return false;
 
		end;
 
	end;
 
	decor = function(s)
 
		return translate_now("tutorial_locale", 'tutorial_study_decor') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_study_decor_hint'));
 
	end;
 
  nam = 'tutorial_cabinet';
 
  disp = translate("tutorial_locale", 'tutorial_study');
 
  theme = 'main';
 
  pic = 'images/main_theme/stub.png';
 
  onenter = function(s)
 
    if not have('tutorial_disk') then
 
      pr(translate_now("tutorial_locale", 'tutorial_study_enter') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_study_enter_hint')));
 
      return false;
 
    end;
 
  end;
 
  decor = function(s)
 
    return translate_now("tutorial_locale", 'tutorial_study_decor') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_study_decor_hint'));
 
  end;
 
}: with {
 
	obj {
 
		nam = '#laptop';
 
		act = translate("tutorial_locale", 'tutorial_study_laptop_act');
 
		used = function(s, o)
 
			if o ^ 'tutorial_disk' then
 
				remove('tutorial_disk');
 
				remove('tutorial_map');
 
				walk('tutorial_end');
 
			end;
 
		end;
 
	};
 
  obj {
 
    nam = '#laptop';
 
    act = translate("tutorial_locale", 'tutorial_study_laptop_act');
 
    used = function(s, o)
 
      if o ^ 'tutorial_disk' then
 
        remove('tutorial_disk');
 
        remove('tutorial_map');
 
        walk('tutorial_end');
 
      end;
 
    end;
 
  };
 
}
 

	
 
room {
 
	nam = 'tutorial_end';
 
	disp = translate("tutorial_locale", 'tutorial_end');
 
	theme = 'main';
 
	pic = 'images/main_theme/stub.png';
 
	decor =  function(s)
 
		return translate_now("tutorial_locale", 'tutorial_end_decor') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_end_decor_hint'));
 
	end;
 
	way = {
 
		path {translate("tutorial_locale", 'tutorial_to_main_menu'), 'main'};
 
		path {translate("tutorial_locale", 'tutorial_to_game'), 'above_forest'};
 
	}
 
  nam = 'tutorial_end';
 
  disp = translate("tutorial_locale", 'tutorial_end');
 
  theme = 'main';
 
  pic = 'images/main_theme/stub.png';
 
  decor =  function(s)
 
    return translate_now("tutorial_locale", 'tutorial_end_decor') .. '^' .. fmt.b(translate_now("tutorial_locale", 'tutorial_end_decor_hint'));
 
  end;
 
  way = {
 
    path {translate("tutorial_locale", 'tutorial_to_main_menu'), 'main'};
 
    path {translate("tutorial_locale", 'tutorial_to_game'), 'above_forest'};
 
  }
 
}