diff --git a/autoload/rogue/const.lua b/autoload/rogue/const.lua new file mode 100644 index 0000000..56658af --- /dev/null +++ b/autoload/rogue/const.lua @@ -0,0 +1,441 @@ +local g = Rogue -- alias + +g.print_enum = {} + +-- g.dungeon +g.NOTHING = 0 +g.OBJECT = 1 +g.MONSTER = 2 +g.STAIRS = 3 +g.HORWALL = 4 +g.VERTWALL = 5 +g.DOOR = 6 +g.FLOOR = 7 +g.TUNNEL = 8 +g.TRAP = 9 +g.HIDDEN = 10 +g.dungeon_desc = { + [g.NOTHING] = "NOTHING", + [g.OBJECT] = "OBJECT", + [g.MONSTER] = "MONSTER", + [g.STAIRS] = "STAIRS", + [g.HORWALL] = "HORWALL", + [g.VERTWALL] = "VERTWALL", + [g.DOOR] = "DOOR", + [g.FLOOR] = "FLOOR", + [g.TUNNEL] = "TUNNEL", + [g.TRAP] = "TRAP", + [g.HIDDEN] = "HIDDEN", +} + +-- what_is +g.GOLD = 1 +g.FOOD = 2 +g.ARMOR = 3 +g.WEAPON = 4 +g.SCROL = 5 +g.POTION = 6 +g.WAND = 7 +g.RING = 8 +g.AMULET = 9 +g.print_enum.what_is = { + [g.GOLD] = "GOLD", + [g.FOOD] = "FOOD", + [g.ARMOR] = "ARMOR", + [g.WEAPON] = "WEAPON", + [g.SCROL] = "SCROL", + [g.POTION] = "POTION", + [g.WAND] = "WAND", + [g.RING] = "RING", + [g.AMULET] = "AMULET", +} +g.ALL_OBJECTS = { + [g.GOLD] = true, + [g.FOOD] = true, + [g.ARMOR] = true, + [g.WEAPON] = true, + [g.SCROL] = true, + [g.POTION] = true, + [g.WAND] = true, + [g.RING] = true, + [g.AMULET] = true, +} + +-- which_kind +g.LEATHER = 0 +g.RINGMAIL = 1 +g.SCALE = 2 +g.CHAIN = 3 +g.BANDED = 4 +g.SPLINT = 5 +g.PLATE = 6 +g.ARMORS = 7 +g.print_enum.which_kind_armor = { + [g.LEATHER] = "LEATHER", + [g.RINGMAIL] = "RINGMAIL", + [g.SCALE] = "SCALE", + [g.CHAIN] = "CHAIN", + [g.BANDED] = "BANDED", + [g.SPLINT] = "SPLINT", + [g.PLATE] = "PLATE", + [g.ARMORS] = "ARMORS", +} + +g.BOW = 0 +g.DART = 1 +g.ARROW = 2 +g.DAGGER = 3 +g.SHURIKEN = 4 +g.MACE = 5 +g.LONG_SWORD = 6 +g.TWO_HANDED_SWORD = 7 +g.WEAPONS = 8 +g.print_enum.which_kind_weapon = { + [g.BOW] = "BOW", + [g.DART] = "DART", + [g.ARROW] = "ARROW", + [g.DAGGER] = "DAGGER", + [g.SHURIKEN] = "SHURIKEN", + [g.MACE] = "MACE", + [g.LONG_SWORD] = "LONG_SWORD", + [g.TWO_HANDED_SWORD] = "TWO_HANDED_SWORD", + [g.WEAPONS] = "WEAPONS", +} + +g.MAX_PACK_COUNT = 24 + +g.PROTECT_ARMOR = 0 +g.HOLD_MONSTER = 1 +g.ENCH_WEAPON = 2 +g.ENCH_ARMOR = 3 +g.IDENTIFY = 4 +g.TELEPORT = 5 +g.SLEEP = 6 +g.SCARE_MONSTER = 7 +g.REMOVE_CURSE = 8 +g.CREATE_MONSTER = 9 +g.AGGRAVATE_MONSTER = 10 +g.MAGIC_MAPPING = 11 +g.SCROLS = 12 +g.print_enum.which_kind_scroll = { + [g.PROTECT_ARMOR] = "PROTECT_ARMOR", + [g.HOLD_MONSTER] = "HOLD_MONSTER", + [g.ENCH_WEAPON] = "ENCH_WEAPON", + [g.ENCH_ARMOR] = "ENCH_ARMOR", + [g.IDENTIFY] = "IDENTIFY", + [g.TELEPORT] = "TELEPORT", + [g.SLEEP] = "SLEEP", + [g.SCARE_MONSTER] = "SCARE_MONSTER", + [g.REMOVE_CURSE] = "REMOVE_CURSE", + [g.CREATE_MONSTER] = "CREATE_MONSTER", + [g.AGGRAVATE_MONSTER] = "AGGRAVATE_MONSTER", + [g.MAGIC_MAPPING] = "MAGIC_MAPPING", + [g.SCROLS] = "SCROLS", +} + +g.INCREASE_STRENGTH = 0 +g.RESTORE_STRENGTH = 1 +g.HEALING = 2 +g.EXTRA_HEALING = 3 +g.POISON = 4 +g.RAISE_LEVEL = 5 +g.BLINDNESS = 6 +g.HALLUCINATION = 7 +g.DETECT_MONSTER = 8 +g.DETECT_OBJECTS = 9 +g.CONFUSION = 10 +g.LEVITATION = 11 +g.HASTE_SELF = 12 +g.SEE_INVISIBLE = 13 +g.POTIONS = 14 +g.print_enum.which_kind_potion = { + [g.INCREASE_STRENGTH] = "INCREASE_STRENGTH", + [g.RESTORE_STRENGTH] = "RESTORE_STRENGTH", + [g.HEALING] = "HEALING", + [g.EXTRA_HEALING] = "EXTRA_HEALING", + [g.POISON] = "POISON", + [g.RAISE_LEVEL] = "RAISE_LEVEL", + [g.BLINDNESS] = "BLINDNESS", + [g.HALLUCINATION] = "HALLUCINATION", + [g.DETECT_MONSTER] = "DETECT_MONSTER", + [g.DETECT_OBJECTS] = "DETECT_OBJECTS", + [g.CONFUSION] = "CONFUSION", + [g.LEVITATION] = "LEVITATION", + [g.HASTE_SELF] = "HASTE_SELF", + [g.SEE_INVISIBLE] = "SEE_INVISIBLE", + [g.POTIONS] = "POTIONS", +} + +g.TELE_AWAY = 0 +g.SLOW_MONSTER = 1 +g.CONFUSE_MONSTER = 2 +g.INVISIBILITY = 3 +g.POLYMORPH = 4 +g.HASTE_MONSTER = 5 +g.PUT_TO_SLEEP = 6 +g.MAGIC_MISSILE = 7 +g.CANCELLATION = 8 +g.DO_NOTHING = 9 +g.WANDS = 10 +g.print_enum.which_kind_wand = { + [g.TELE_AWAY] = "TELE_AWAY", + [g.SLOW_MONSTER] = "SLOW_MONSTER", + [g.CONFUSE_MONSTER] = "CONFUSE_MONSTER", + [g.INVISIBILITY] = "INVISIBILITY", + [g.POLYMORPH] = "POLYMORPH", + [g.HASTE_MONSTER] = "HASTE_MONSTER", + [g.PUT_TO_SLEEP] = "PUT_TO_SLEEP", + [g.MAGIC_MISSILE] = "MAGIC_MISSILE", + [g.CANCELLATION] = "CANCELLATION", + [g.DO_NOTHING] = "DO_NOTHING", + [g.WANDS] = "WANDS", +} + +g.STEALTH = 0 +g.R_TELEPORT = 1 +g.REGENERATION = 2 +g.SLOW_DIGEST = 3 +g.ADD_STRENGTH = 4 +g.SUSTAIN_STRENGTH = 5 +g.DEXTERITY = 6 +g.ADORNMENT = 7 +g.R_SEE_INVISIBLE = 8 +g.MAINTAIN_ARMOR = 9 +g.SEARCHING = 10 +g.RINGS = 11 +g.print_enum.which_kind_ring = { + [g.STEALTH] = "STEALTH", + [g.R_TELEPORT] = "R_TELEPORT", + [g.REGENERATION] = "REGENERATION", + [g.SLOW_DIGEST] = "SLOW_DIGEST", + [g.ADD_STRENGTH] = "ADD_STRENGTH", + [g.SUSTAIN_STRENGTH] = "SUSTAIN_STRENGTH", + [g.DEXTERITY] = "DEXTERITY", + [g.ADORNMENT] = "ADORNMENT", + [g.R_SEE_INVISIBLE] = "R_SEE_INVISIBLE", + [g.MAINTAIN_ARMOR] = "MAINTAIN_ARMOR", + [g.SEARCHING] = "SEARCHING", + [g.RINGS] = "RINGS", +} + +g.RATION = 0 +g.FRUIT = 1 +g.print_enum.which_kind_food = { + [g.RATION] = "RATION", + [g.FRUIT] = "FRUIT", +} + +-- in_use_flags +g.NOT_USED = 0 +g.BEING_WIELDED = 1 +g.BEING_WORN = 2 +g.ON_LEFT_HAND = 3 +g.ON_RIGHT_HAND = 4 +g.print_enum.in_use_flags = { + [g.NOT_USED] = "NOT_USED", + [g.BEING_WIELDED] = "BEING_WIELDED", + [g.BEING_WORN] = "BEING_WORN", + [g.ON_LEFT_HAND] = "ON_LEFT_HAND", + [g.ON_RIGHT_HAND] = "ON_RIGHT_HAND", +} +function g.ON_EITHER_HAND(in_use_flags) + if in_use_flags == g.ON_LEFT_HAND or + in_use_flags == g.ON_RIGHT_HAND then + return true + else + return false + end +end +function g.BEING_USED(in_use_flags) + if in_use_flags == g.BEING_WIELDED or + in_use_flags == g.BEING_WORN or + in_use_flags == g.ON_LEFT_HAND or + in_use_flags == g.ON_RIGHT_HAND then + return true + else + return false + end +end + +-- trap_type +g.NO_TRAP = -1 +g.TRAP_DOOR = 0 +g.BEAR_TRAP = 1 +g.TELE_TRAP = 2 +g.DART_TRAP = 3 +g.SLEEPING_GAS_TRAP = 4 +g.RUST_TRAP = 5 +g.TRAPS = 6 + +g.STEALTH_FACTOR = 3 +g.R_TELE_PERCENT = 8 + +g.UNIDENTIFIED = 0 +g.IDENTIFIED = 1 +g.CALLED = 2 + +g.DROWS = 24 +g.DCOLS = 80 +g.MAX_TITLE_LENGTH = 30 +g.MAXSYLLABLES = 40 +g.MAX_METAL = 14 +g.WAND_MATERIALS = 30 +g.GEMS = 14 + +g.GOLD_PERCENT = 46 + +g.INIT_HP = 12 + +g.MAXROOMS = 9 +g.BIG_ROOM = 10 +g.NO_ROOM = -1 + +g.PASSAGE = -3 + +g.AMULET_LEVEL = 26 + +-- is_room +g.R_NOTHING = 1 +g.R_ROOM = 2 +g.R_MAZE = 3 +g.R_DEADEND = 4 +g.R_CROSS = 5 +g.print_enum.is_room = { + [g.R_NOTHING] = "R_NOTHING", + [g.R_ROOM] = "R_ROOM", + [g.R_MAZE] = "R_MAZE", + [g.R_DEADEND] = "R_DEADEND", + [g.R_CROSS] = "R_CROSS", +} + +g.MAX_EXP_LEVEL = 21 +g.MAX_EXP = 9999999 +g.MAX_GOLD = 900000 +g.MAX_ARMOR = 99 +g.MAX_HP = 800 +g.MAX_STRENGTH = 99 +g.LAST_DUNGEON = 99 + + +g.PARTY_TIME = 10 + +g.MAX_TRAPS = 10 + +g.HIDE_PERCENT = 12 + +g.MONSTERS = 26 + +-- m_flags +g.HASTED = 1 +g.SLOWED = 2 +g.INVISIBLE = 3 +g.ASLEEP = 4 +g.WAKENS = 5 +g.WANDERS = 6 +g.FLIES = 7 +g.FLITS = 8 +g.CAN_FLIT = 9 +g.CONFUSED = 10 +g.RUSTS = 11 +g.HOLDS = 12 +g.FREEZES = 13 +g.STEALS_GOLD = 14 +g.STEALS_ITEM = 15 +g.STINGS = 16 +g.DRAINS_LIFE = 17 +g.DROPS_LEVEL = 18 +g.SEEKS_GOLD = 19 +g.FREEZING_ROGUE = 20 +g.RUST_VANISHED = 21 +g.CONFUSES = 22 +g.IMITATES = 23 +g.FLAMES = 24 +g.STATIONARY = 25 +g.NAPPING = 26 +g.ALREADY_MOVED = 27 +g.m_flags_desc = { + [g.HASTED] = "HASTED", + [g.SLOWED] = "SLOWED", + [g.INVISIBLE] = "INVISIBLE", + [g.ASLEEP] = "ASLEEP", + [g.WAKENS] = "WAKENS", + [g.WANDERS] = "WANDERS", + [g.FLIES] = "FLIES", + [g.FLITS] = "FLITS", + [g.CAN_FLIT] = "CAN_FLIT", + [g.CONFUSED] = "CONFUSED", + [g.RUSTS] = "RUSTS", + [g.HOLDS] = "HOLDS", + [g.FREEZES] = "FREEZES", + [g.STEALS_GOLD] = "STEALS_GOLD", + [g.STEALS_ITEM] = "STEALS_ITEM", + [g.STINGS] = "STINGS", + [g.DRAINS_LIFE] = "DRAINS_LIFE", + [g.DROPS_LEVEL] = "DROPS_LEVEL", + [g.SEEKS_GOLD] = "SEEKS_GOLD", + [g.FREEZING_ROGUE] = "FREEZING_ROGUE", + [g.RUST_VANISHED] = "RUST_VANISHED", + [g.CONFUSES] = "CONFUSES", + [g.IMITATES] = "IMITATES", + [g.FLAMES] = "FLAMES", + [g.STATIONARY] = "STATIONARY", + [g.NAPPING] = "NAPPING", + [g.ALREADY_MOVED] = "ALREADY_MOVED", +} +function g.SPECIAL_HIT(m_flags) + for k, v in pairs(m_flags) do + if k == g.RUSTS or + k == g.HOLDS or + k == g.FREEZES or + k == g.STEALS_GOLD or + k == g.STEALS_ITEM or + k == g.STINGS or + k == g.DRAINS_LIFE or + k == g.DROPS_LEVEL then + return true + end + end + return false +end + +g.WAKE_PERCENT = 45 +g.FLIT_PERCENT = 33 +g.PARTY_WAKE_PERCENT = 75 + +-- killed_by other +g.HYPOTHERMIA = 1 +g.STARVATION = 2 +g.POISON_DART = 3 +g.QUIT = 4 +g.WIN = 5 + +-- dir +g.UPWARD = 0 +g.UPRIGHT = 1 +g.RIGHT = 2 +g.RIGHTDOWN = 3 +g.DOWN = 4 +g.DOWNLEFT = 5 +g.LEFT = 6 +g.LEFTUP = 7 +g.DIRS = 8 + +g.ROW1 = 7 +g.ROW2 = 15 + +g.COL1 = 26 +g.COL2 = 52 + +g.MOVED = 0 +g.MOVE_FAILED = -1 +g.STOPPED_ON_SOMETHING = -2 +g.CANCEL = 'ESC' +g.LIST = '*' + +g.HUNGRY = 300 +g.WEAK = 150 +g.FAINT = 20 +g.STARVE = 0 + +g.MIN_ROW = 1 + diff --git a/autoload/rogue/curses.lua b/autoload/rogue/curses.lua new file mode 100644 index 0000000..442ca49 --- /dev/null +++ b/autoload/rogue/curses.lua @@ -0,0 +1,129 @@ +local g = Rogue -- alias + +g.COLOR = true + +g.update_flag = false + +g.dungeon = {} +local dungeon_buffer = {} +local dungeon_str_buffer = {} +local last_row_str = {} +local last_print_area = '' +g.descs = {} +g.screen = {} + +function g.init_curses() + for i = 0, g.DROWS-1 do + g.dungeon[i] = {} + dungeon_buffer[i] = {} + dungeon_str_buffer[i] = {} + dungeon_str_buffer[i].col = 0 + dungeon_str_buffer[i].str = '' + last_row_str[i] = '' + g.descs[i] = '' + g.screen[i] = '' + for j = 0, g.DCOLS-1 do + g.dungeon[i][j] = {} + dungeon_buffer[i][j] = ' ' + end + end +end + +local function dungeon_row(row) + return table.concat(dungeon_buffer[row], '', 0, g.DCOLS-1) +end + +function g.dungeon_buffer_concat() + local t = {} + for i = 0, g.DROWS-1 do + table.insert(t, dungeon_row(i) .. ';') + end + return table.concat(t) +end + +function g.dungeon_buffer_restore(str) + local t = g.split(str, ';') + for i, v in ipairs(t) do + for j = 1, #v do + dungeon_buffer[i-1][j-1] = string.char(v:byte(j)) + end + end +end + +function g.clear() + for i = 0, g.DROWS-1 do + for j = 0, g.DCOLS-1 do + dungeon_buffer[i][j] = ' ' + end + g.mvaddstr(i, 0, '') + end + g.refresh() +end + +function g.mvinch(row, col) + return dungeon_buffer[row][col] +end + +function g.mvaddch(row, col, ch) + dungeon_buffer[row][col] = ch +end + +function g.mvaddstr(row, col, str) + dungeon_str_buffer[row].col = col + dungeon_str_buffer[row].str = str +end + +function g.refresh() + if vim then + vim.command("normal gg") + end + local update = false + local done_redraw = false + for i = 0, g.DROWS-1 do + local row_str + if dungeon_str_buffer[i].str == '' then + row_str = dungeon_row(i) + else + row_str = dungeon_row(i):sub(1, dungeon_str_buffer[i].col) + end + if vim then + if i == g.DROWS-1 and vim.eval("&lines") == g.DROWS then + row_str = row_str .. dungeon_str_buffer[i].str + if g.update_flag or row_str ~= last_print_area then + vim.command("redraw") + print((vim.eval("has('gui_running')") ~= 0 and '' or ' ') .. row_str) + vim.command("redrawstatus") + last_print_area = row_str + done_redraw = true + end + else + if g.update_flag and i == 0 and vim.eval("&lines") > g.DROWS then + print(' ') + end + if dungeon_str_buffer[i].str ~= '' then + if g.COLOR then + row_str = row_str .. '$$' .. dungeon_str_buffer[i].str + else + row_str = row_str .. dungeon_str_buffer[i].str + row_str = row_str:gsub('%(%w%(', '') + end + end + if g.update_flag or row_str ~= last_row_str[i] then + local cmd_str + cmd_str = 'call setline(' .. tostring(i + 1) .. ', "' .. row_str .. '")' + vim.command(cmd_str) + last_row_str[i] = row_str + update = true + end + end + else + row_str = row_str .. dungeon_str_buffer[i].str + print(row_str) + end + g.screen[i] = row_str:gsub("%$%$", ""):gsub("%(%w%(", ""):gsub('\\\\', '\\') + end + g.update_flag = false + if update and not done_redraw then + vim.command("redraw") + end +end diff --git a/autoload/rogue/debug.lua b/autoload/rogue/debug.lua new file mode 100644 index 0000000..2a2fae7 --- /dev/null +++ b/autoload/rogue/debug.lua @@ -0,0 +1,310 @@ +local g = Rogue -- alias + +g.DEBUG = true +-- g.COVERAGE = true + +local debug_log_file = nil +local debug_log_file_name = 'rogue_vim.log' + +local cov_data + +function g.printf(fmt, ...) + if not g.DEBUG then + return + end + if vim then + print(string.format(fmt, ...)) + else + io.write(string.format(fmt, ...)) + end +end + +function g.msgbox(fmt, ...) + if not g.DEBUG or not vim then + return + end + vim.eval("confirm('" .. string.format(fmt, ...) .. "')") +end + +function g.log(fmt, ...) + if not g.DEBUG then + return false + end + if not debug_log_file then + if not g.log_open() then + return false + end + end + debug_log_file:write(string.format(fmt, ...)) + debug_log_file:flush() + return true +end + +function g.log_open() + if not g.DEBUG then + return false + end + if not debug_log_file then + local err + debug_log_file, err = io.open(g.game_dir .. debug_log_file_name, "a") + if debug_log_file then + g.log("\n[%s]\n", os.date()) + return true + else + g.printf("%s\n", err) + return false + end + end + return true +end + +function g.log_close() + if not g.DEBUG then + return + end + if debug_log_file then + debug_log_file:close() + debug_log_file = nil + end +end + +function g.log_remove() + g.log_close() + local ret, err = os.remove(g.game_dir .. debug_log_file_name) + if not ret then + return false + end + return true +end + +local function get_local_var(level, name) + local i = 1 + local lname, lval + repeat + lname, lval = debug.getlocal(level + 1, i) + if lname == name then + return lval, i + end + i = i + 1 + until lname == nil + return nil, -1 +end + +local function get_upvalue(level, name) + local func = debug.getinfo(level + 1).func + local i = 1 + local lname, lval + repeat + local lname, lval = debug.getupvalue(func, i) + if lname == name then + return lval, i + end + i = i + 1 + until lname == nil + return nil, -1 +end + +local function get_local_or_upvalue(level, name) + local lval, i = get_local_var(level + 1, name) + if i ~= -1 then + return lval, i, true + end + lval, i = get_upvalue(level + 1, name) + return lval, i, false +end + +local function p(obj_str, log_flag, level, hex_flag) + local lval, i = get_local_or_upvalue(level + 1, obj_str) + local output + if i ~= -1 then + output = "local " .. obj_str .. " = " .. g.dump(lval, hex_flag) + else + local obj = assert(g.loadstring('return ' .. obj_str))() + output = obj_str .. " = " .. g.dump(obj, hex_flag) + end + + for k, v in pairs(g.print_enum) do + output = output:gsub("(" .. k .. " = )(%d+),", function(s1, s2) + local str = v[tonumber(s2)] + if not str then + str = '?' + end + return s1 .. s2 .. ", -- " .. str + end) + end + + if log_flag then + g.log("%s\n", output) + else + g.printf("%s\n", output) + end +end + +function g.p(obj_str, log_flag, hex_flag) + p(obj_str, log_flag, 2, hex_flag) +end + +local function print_all_local_variables(log_flag, level) + level = level + 1 + local i = 1 + while true do + local lname, lval = debug.getlocal(level, i) + if lname == nil then + break + end + if type(lval) ~= 'function' then + p(lname, log_flag, level) + end + i = i + 1 + end + local func = debug.getinfo(level).func + i = 1 + while true do + local lname, lval = debug.getupvalue(func, i) + if lname == nil then + break + end + if type(lval) ~= 'function' and not(lname == 'g' and lval == Rogue) then + p(lname, log_flag, level) + end + i = i + 1 + end +end + +function g.breakpoint(log_flag) + if not g.DEBUG or not vim then + return + end + local level = 2 + local prompt = '\n'..g.__FILE_LINE__(level)..'\n'..'Breakpoint: ' + while true do + local input = vim.eval('input("'..prompt..'", "", "tag")') + if input == '' then + break + end + g.printf(" \n") + local idx = input:find('=') + if idx then + -- set value + local obj = input:sub(1, idx-1) + obj = obj:gsub(' ', '') + local lval, i, is_local = get_local_or_upvalue(level, obj) + if i ~= -1 then + local val = input:sub(idx+1) + local new_val = assert(g.loadstring('return ' .. val))() + if is_local then + debug.setlocal(level, i, new_val) + else + local func = debug.getinfo(level).func + debug.setupvalue(func, i, new_val) + end + else + assert(g.loadstring(input))() + end + else + -- get value + if log_flag then + g.log("%s\n", prompt .. input) + end + if input == 'local' then + print_all_local_variables(log_flag, level) + else + p(input, log_flag, level) + end + end + end + g.print_stats(true) +end + +function g.__FILE_LINE__(level) + if not level then + level = 2 + else + level = level + 1 + end + return string.gsub(debug.getinfo(level, 'S').source, '^@', '') .. ':' .. + debug.getinfo(level, 'l').currentline +end + +function g.log_screen() + for i = 0, g.DROWS-1 do + g.log("%s\n", g.screen[i]) + end +end + +function g.error_handler(e) + if e == g.EXIT_SUCCESS then + g.clear_stats() + return e + end + g.cov_suspend() + g.log("%s\n", debug.traceback(e)) + g.log_screen() + print_all_local_variables(true, 2) + g.p("Rogue", true) + g.cov_resume() + return e +end + +local function cov_hook(event, line) + local s = string.gsub(debug.getinfo(2, 'S').source, '^@', '') + if not s:find("%.lua$") then + return + end + if not cov_data[s] then + cov_data[s] = {} + cov_data[s].src = {} + end + if not cov_data[s][line] then + cov_data[s][line] = 1 + else + cov_data[s][line] = cov_data[s][line] + 1 + end +end + +function g.cov_start() + if not g.COVERAGE then + return + end + cov_data = {} + debug.sethook(cov_hook, "l") +end + +function g.cov_stop() + if not g.COVERAGE then + return + end + debug.sethook() + for k, v in pairs(cov_data) do + g.log("%s\n", k) + local i = 1 + for line in io.lines(k) do + v.src[i] = line + i = i + 1 + end + for idx, line in ipairs(v.src) do + if not v[idx] then + g.log(string.rep(' ', 9) .. ':') + else + g.log("%9d:", v[idx]) + end + g.log("%5d:", idx) + g.log("%s\n", line) + end + end +end + +function g.cov_suspend() + if not g.COVERAGE then + return + end + debug.sethook() +end + +function g.cov_resume() + if not g.COVERAGE then + return + end + debug.sethook(cov_hook, "l") +end + diff --git a/autoload/rogue/hit.lua b/autoload/rogue/hit.lua new file mode 100644 index 0000000..4242e9f --- /dev/null +++ b/autoload/rogue/hit.lua @@ -0,0 +1,311 @@ +local g = Rogue -- alias + +g.hit_message = '' +local fight_monster = nil + +local function rogue_damage(d, monster) + if d >= g.rogue.hp_current then + g.rogue.hp_current = 0 + g.print_stats() + g.killed_by(monster, 0) + -- NOTREACHED + end + g.rogue.hp_current = g.rogue.hp_current - d + g.print_stats() +end + +function g.mon_hit(monster, other, flame) + local damage, hit_chance + if fight_monster and monster ~= fight_monster then + fight_monster = nil + end + monster.trow = g.NO_ROOM + if g.cur_level >= (g.AMULET_LEVEL * 2) then + hit_chance = 100 + else + hit_chance = monster.m_hit_chance + hit_chance = hit_chance - (((2 * g.rogue.exp) + (2 * g.ring_exp)) - g.r_rings) + end + if g.wizard then + hit_chance = g.int_div(hit_chance, 2) + end + if not fight_monster then + g.interrupted = true + end + local mn = g.mon_name(monster) + + if other then + hit_chance = hit_chance - ((g.rogue.exp + g.ring_exp) - g.r_rings) + end + + if not g.rand_percent(hit_chance) then + if not fight_monster then + g.hit_message = g.hit_message .. string.format(g.mesg[18], (other and other or mn)) + g.message(g.hit_message, true) + g.hit_message = '' + end + return + end + if not fight_monster then + if other then + g.hit_message = g.hit_message .. + string.format(g.mesg[19], other, g.mesg[20]) + else + g.hit_message = g.hit_message .. + string.format(g.mesg[19], mn, g.mesg[21]) + end + g.message(g.hit_message, true) + g.hit_message = '' + end + if not monster.m_flags[g.STATIONARY] then + damage = g.get_damage(monster.m_damage, true) + if other then + if flame then + damage = damage - g.get_armor_class(g.rogue.armor) + if damage < 0 then + damage = 1 + end + end + end + local minus + if g.cur_level >= (g.AMULET_LEVEL * 2) then + minus = (g.AMULET_LEVEL * 2) - g.cur_level + else + minus = g.get_armor_class(g.rogue.armor) * 3 + minus = g.int_div(minus * damage, 100) + end + damage = damage - minus + else + damage = monster.stationary_damage + monster.stationary_damage = monster.stationary_damage + 1 + end + if g.wizard then + damage = g.int_div(damage, 3) + end + if damage > 0 then + rogue_damage(damage, monster) + end + if g.SPECIAL_HIT(monster.m_flags) then + g.special_hit(monster) + end +end + +function g.rogue_hit(monster, force_hit) + if not monster then + return + end + if g.check_imitator(monster) then + return + end + local hit_chance = force_hit and 100 or g.get_hit_chance(g.rogue.weapon) + + if g.wizard then + hit_chance = hit_chance * 2 + end + if not g.rand_percent(hit_chance) then + if not fight_monster then + g.hit_message = string.format(g.mesg[22], g.nick_name) + end + -- goto RET + g.check_gold_seeker(monster) + g.wake_up(monster) + return + end + local damage = g.get_weapon_damage(g.rogue.weapon) + if g.wizard then + damage = damage * 3 + end + if g.mon_damage(monster, damage) then -- still alive? + if not fight_monster then + g.hit_message = string.format(g.mesg[23], g.nick_name) + end + end + -- ::RET:: + g.check_gold_seeker(monster) + g.wake_up(monster) +end + +function g.get_damage(ds, r) + local t = g.get_number(ds) + local total = 0 + for i, v in ipairs(t) do + local n = v[1] + local d = v[2] + for j = 1, n do + if r then + total = total + g.get_rand(1, d) + else + total = total + d + end + end + end + return total +end + +local function get_w_damage(obj) + if not obj or obj.what_is ~= g.WEAPON then + return -1 + end + local t = g.get_number(obj.damage) + local to_hit = t[1][1] + obj.hit_enchant + local damage = t[1][2] + obj.d_enchant + + local new_damage = string.format("%dd%d", to_hit, damage) + + return g.get_damage(new_damage, true) +end + +function g.get_number(s) + local ret = {} + local t = g.split(s, '/') + for i, v in ipairs(t) do + local t1 = g.split(v, 'd') + local t2 = {} + for j, x in ipairs(t1) do + table.insert(t2, tonumber(x)) + end + table.insert(ret, t2) + end + return ret +end + +local function to_hit(obj) + if not obj then + return 1 + end + return g.get_number(obj.damage)[1][1] + obj.hit_enchant +end + +local function damage_for_strength() + local sa = { 14, 17, 18, 20, 21, 30, 9999 } + local ra = { 1, 3, 4, 5, 6, 7, 8 } + local strength = g.rogue.str_current + g.add_strength + if strength <= 6 then + return strength - 5 + end + for i = 1, #sa do + if strength <= sa[i] then + return ra[i] + end + end + return ra[#ra] +end + +function g.mon_damage(monster, damage) + monster.hp_to_kill = monster.hp_to_kill - damage + if monster.hp_to_kill > 0 then + return true + end + local row = monster.row + local col = monster.col + g.dungeon[row][col][g.MONSTER] = nil + g.mvaddch(row, col, g.get_dungeon_char(row, col)) + + fight_monster = nil + g.cough_up(monster) + local mn = g.mon_name(monster) + g.hit_message = g.hit_message .. string.format(g.mesg[24], mn) + g.message(g.hit_message, true) + g.hit_message = '' + g.add_exp(monster.kill_exp, true) + g.take_from_pack(monster, g.level_monsters) + + if monster.m_flags[g.HOLDS] then + g.being_held = false + end + g.free_object(monster) + return false +end + +function g.fight(to_the_death) + local ch = g.get_direction() + if ch == g.CANCEL then + return + end + local row = g.rogue.row + local col = g.rogue.col + row, col = g.get_dir_rc(ch, row, col, false) + + local c = g.mvinch(row, col) + if not c:find('^[A-Z]$') or + not g.can_move(g.rogue.row, g.rogue.col, row, col) then + g.message(g.mesg[25]) + return + end + fight_monster = g.object_at(g.level_monsters, row, col) + if not fight_monster then + return + end + local possible_damage + if not fight_monster.m_flags[g.STATIONARY] then + possible_damage = g.int_div((g.get_damage(fight_monster.m_damage, false) * 2), 3) + else + possible_damage = fight_monster.stationary_damage - 1 + end + while fight_monster do + g.one_move_rogue(ch, false) + if (not to_the_death and (g.rogue.hp_current <= possible_damage)) or + g.interrupted or not g.dungeon[row][col][g.MONSTER] then + fight_monster = nil + else + local monster = g.object_at(g.level_monsters, row, col) + if monster ~= fight_monster then + fight_monster = nil + end + end + end +end + +function g.get_dir_rc(dir, row, col, allow_off_screen) + if dir == 'h' then + if allow_off_screen or (col > 0) then + col = col - 1 + end + elseif dir == 'j' then + if allow_off_screen or (row < g.DROWS-2) then + row = row + 1 + end + elseif dir == 'k' then + if allow_off_screen or (row > g.MIN_ROW) then + row = row - 1 + end + elseif dir == 'l' then + if allow_off_screen or (col < g.DCOLS-1) then + col = col + 1 + end + elseif dir == 'y' then + if allow_off_screen or (row > g.MIN_ROW and col > 0) then + row = row - 1 + col = col - 1 + end + elseif dir == 'u' then + if allow_off_screen or (row > g.MIN_ROW and col < g.DCOLS-1) then + row = row - 1 + col = col + 1 + end + elseif dir == 'n' then + if allow_off_screen or (row < g.DROWS-2 and col < g.DCOLS-1) then + row = row + 1 + col = col + 1 + end + elseif dir == 'b' then + if allow_off_screen or (row < g.DROWS-2 and col > 0) then + row = row + 1 + col = col - 1 + end + end + + return row, col +end + +function g.get_hit_chance(weapon) + local hit_chance = 40 + 3 * to_hit(weapon) + hit_chance = hit_chance + (((2 * g.rogue.exp) + (2 * g.ring_exp)) - g.r_rings) + return hit_chance +end + +function g.get_weapon_damage(weapon) + local damage = get_w_damage(weapon) + damage_for_strength() + damage = damage + g.int_div((((g.rogue.exp + g.ring_exp) - g.r_rings) + 1), 2) + return damage +end diff --git a/autoload/rogue/init.lua b/autoload/rogue/init.lua new file mode 100644 index 0000000..c3aae25 --- /dev/null +++ b/autoload/rogue/init.lua @@ -0,0 +1,215 @@ +local g = Rogue -- alias + +g.nick_name = '' +g.score_only = false +g.save_is_interactive = true +g.show_skull = true +g.ask_quit = true +g.pass_go = true +g.do_restore = false + +local rest_file = nil + +local function set_nick_name() + g.nick_name = g.get_vim_variable("g:rogue#name") + if type(g.nick_name) == 'string' and g.nick_name ~= '' then + return + end + g.nick_name = os.getenv('FIGHTER') + if g.nick_name then + return + end + g.nick_name = os.getenv('USER') + if g.nick_name then + return + end + g.nick_name = os.getenv('USERNAME') + if g.nick_name then + return + end + local default_name = g.mesg[542] + if vim then + g.nick_name = vim.eval('inputdialog("'..g.mesg[13]..' ", "'..default_name..'")') + if g.nick_name == '' then + g.nick_name = default_name + end + else + g.nick_name = default_name + end +end + +local function do_args(args) + for i = 1, #args do + if args[i] == '' then + break + elseif args[i] == '-s' then + g.score_only = true + break + elseif args[i] == '-r' then + g.do_restore = true + elseif args[i] == '--resume' then + -- failed to resume + g.message(g.mesg[543]) + break + else + rest_file = args[i] + break + end + end +end + +local function do_opts() + local save_file = g.get_vim_variable("g:rogue#file") + if type(save_file) == 'string' and save_file ~= '' then + g.save_file = save_file + end + local color = g.get_vim_variable("g:rogue#color") + if type(color) == 'number' then + if color ~= 0 then + g.COLOR = true + else + g.COLOR = false + end + end + local jump = g.get_vim_variable("g:rogue#jump") + if type(jump) == 'number' then + if jump ~= 0 then + g.jump = true + else + g.jump = false + end + end + local passgo = g.get_vim_variable("g:rogue#passgo") + if type(passgo) == 'number' then + if passgo ~= 0 then + g.pass_go = true + else + g.pass_go = false + end + end + local tombstone = g.get_vim_variable("g:rogue#tombstone") + if type(tombstone) == 'number' then + if tombstone ~= 0 then + g.show_skull = true + else + g.show_skull = false + end + end + local fruit = g.get_vim_variable("g:rogue#fruit") + if type(fruit) == 'string' and fruit ~= '' then + g.fruit = fruit + end +end + +local function player_init() + g.rogue.pack.next_object = nil + + local obj + obj = g.alloc_object() + g.get_food(obj, true) + g.add_to_pack(obj, g.rogue.pack, true) + obj.desc = g.get_desc(obj) + + -- initial armor + obj = g.alloc_object() + obj.what_is = g.ARMOR + obj.which_kind = g.RINGMAIL + obj.which_kind_armor = obj.which_kind + obj.class = g.RINGMAIL+2 + obj.is_protected = false + obj.d_enchant = 1 + g.add_to_pack(obj, g.rogue.pack, true) + g.do_wear(obj) + obj.desc = g.get_desc(obj) + + -- initial weapons + obj = g.alloc_object() + obj.what_is = g.WEAPON + obj.which_kind = g.MACE + obj.which_kind_weapon = obj.which_kind + obj.damage = "2d3" + obj.hit_enchant = 1 + obj.d_enchant = 1 + obj.identified = true + g.add_to_pack(obj, g.rogue.pack, true) + g.do_wield(obj) + obj.desc = g.get_desc(obj) + + obj = g.alloc_object() + obj.what_is = g.WEAPON + obj.which_kind = g.BOW + obj.which_kind_weapon = obj.which_kind + obj.damage = "1d2" + obj.hit_enchant = 1 + obj.d_enchant = 0 + obj.identified = true + g.add_to_pack(obj, g.rogue.pack, true) + obj.desc = g.get_desc(obj) + + obj = g.alloc_object() + obj.what_is = g.WEAPON + obj.which_kind = g.ARROW + obj.which_kind_weapon = obj.which_kind + obj.quantity = g.get_rand(25, 35) + obj.damage = "1d2" + obj.hit_enchant = 0 + obj.d_enchant = 0 + obj.identified = true + g.add_to_pack(obj, g.rogue.pack, true) + obj.desc = g.get_desc(obj) +end + +function g.init(args) + do_opts() + + if g.suspended then + -- resume + g.suspended = false + g.print_stats(true) + return true + end + + g.init_curses() + + do_args(args) + if g.score_only then + g.message('') + print('') + g.put_scores(nil, 0) + -- NOTREACHED + end + + g.srrandom(os.time()) + + g.init_invent() + g.init_level() + g.init_monster() + g.init_move() + g.init_object() + g.init_pack() + g.init_ring() + g.init_room() + g.init_spechit() + g.init_trap() + g.init_use() + + if g.do_restore and g.save_file ~= '' then + rest_file = g.save_file + end + if rest_file then + if g.restore(rest_file) then + return true + end + end + set_nick_name() + g.mix_colors() + g.get_wand_and_ring_materials() + g.make_scroll_titles() + g.level_objects.next_object = nil + g.level_monsters.next_object = nil + player_init() + g.party_counter = g.get_rand(1, g.PARTY_TIME) + g.ring_stats(false) + g.print_stats(true) + return false +end diff --git a/autoload/rogue/invent.lua b/autoload/rogue/invent.lua new file mode 100644 index 0000000..c8ba08a --- /dev/null +++ b/autoload/rogue/invent.lua @@ -0,0 +1,561 @@ +local g = Rogue -- alias + +g.is_wood = {} + +local wand_materials = {} +local gems = {} +local syllables = {} + +function g.init_invent() + wand_materials = { + [0] = + g.mesg[410], g.mesg[411], g.mesg[412], g.mesg[413], g.mesg[414], g.mesg[415], + g.mesg[416], g.mesg[417], g.mesg[418], g.mesg[419], g.mesg[420], g.mesg[421], + g.mesg[422], g.mesg[423], g.mesg[424], g.mesg[425], g.mesg[426], g.mesg[427], + g.mesg[428], g.mesg[429], g.mesg[430], g.mesg[431], g.mesg[432], g.mesg[433], + g.mesg[434], g.mesg[435], g.mesg[436], g.mesg[437], g.mesg[438], g.mesg[439] + } + + gems = { + [0] = + g.mesg[440], g.mesg[441], g.mesg[442], g.mesg[443], g.mesg[444], g.mesg[445], + g.mesg[446], g.mesg[447], g.mesg[448], g.mesg[449], g.mesg[450], g.mesg[451], + g.mesg[452], g.mesg[453] + } + + syllables = { + [0] = + g.mesg[454], g.mesg[455], g.mesg[456], g.mesg[457], g.mesg[458], g.mesg[459], + g.mesg[460], g.mesg[461], g.mesg[462], g.mesg[463], g.mesg[464], g.mesg[465], + g.mesg[466], g.mesg[467], g.mesg[468], g.mesg[469], g.mesg[470], g.mesg[471], + g.mesg[472], g.mesg[473], g.mesg[474], g.mesg[475], g.mesg[476], g.mesg[477], + g.mesg[478], g.mesg[479], g.mesg[480], g.mesg[481], g.mesg[482], g.mesg[483], + g.mesg[484], g.mesg[485], g.mesg[486], g.mesg[487], g.mesg[488], g.mesg[489], + g.mesg[490], g.mesg[491], g.mesg[492], g.mesg[493] + } +end + + +local function Protected(obj) + return obj.what_is == g.ARMOR and obj.is_protected +end + +function g.inventory(pack, mask) + local row + local col + local msg = ' ' .. g.mesg[494] + if g.JAPAN then + msg = ' ' .. msg + end + local len = g.strwidth(msg) + + local obj = pack.next_object + if not obj then + g.message(g.mesg[26]) + return + end + + if type(mask) == 'number' then + mask = { [mask] = true } + end + + repeat + -- ::nextpage:: + local nextpg = false + local i = 0 + local maxlen = len + while obj and i < g.DROWS - 2 do + if mask[obj.what_is] then + g.descs[i] = ' ' .. obj.ichar .. (Protected(obj) and '}' or ')') .. + ' ' .. g.get_desc(obj, false) + local n = g.strwidth(g.descs[i]) + if n > maxlen then + maxlen = n + end + i = i + 1 + end + obj = obj.next_object + end + g.descs[i] = msg + i = i + 1 + + if i == 0 then + return + end + + col = g.DCOLS - (maxlen + 2 + 1) + for row = 0, i-1 do + g.mvaddstr(row, col, g.descs[row]) + end + g.refresh() + g.wait_for_ack() + for row = 0, g.DROWS-2 do + g.mvaddstr(row, 0, '') + end + + if obj then + -- goto nextpage + nextpg = true + end + until not nextpg +end + +function g.mix_colors() + for i = 0, g.POTIONS-1 do + g.id_potions[i].title = g.po_color[i] + end + for i = 0, g.POTIONS-1 do + local j = g.get_rand(i, g.POTIONS - 1) + g.id_potions[i].title, g.id_potions[j].title = + g.id_potions[j].title, g.id_potions[i].title + end +end + +function g.make_scroll_titles() + for i = 0, g.SCROLS-1 do + local sylls = g.get_rand(2, 5) + g.id_scrolls[i].title = g.mesg[535] + local len = g.strwidth(g.id_scrolls[i].title) + for j = 0, sylls-1 do + local s = g.get_rand(1, g.MAXSYLLABLES-1) + local n = g.strwidth(syllables[s]) + if len + n - 1 >= g.MAX_TITLE_LENGTH - 2 then + break + end + g.id_scrolls[i].title = g.id_scrolls[i].title .. syllables[s] + len = len + n + end + g.id_scrolls[i].title = g.id_scrolls[i].title:gsub(" $", "") + g.id_scrolls[i].title = g.id_scrolls[i].title .. g.mesg[536] + end +end + +local function get_desc_ANA(obj) + if obj.in_use_flags == g.BEING_WIELDED then + return g.mesg[35] + elseif obj.in_use_flags == g.BEING_WORN then + return g.mesg[36] + elseif obj.in_use_flags == g.ON_LEFT_HAND then + return g.mesg[37] + elseif obj.in_use_flags == g.ON_RIGHT_HAND then + return g.mesg[38] + else + return '' + end +end + +local function capitalize(str, capitalized) + if capitalized then + return str:upper():sub(1, 1) .. str:sub(2) + else + return str:lower():sub(1, 1) .. str:sub(2) + end +end + +function g.get_desc(obj, capitalized) + local desc = '' + if obj.what_is == g.AMULET then + desc = g.mesg[27] + if g.English and not capitalized then + desc = capitalize(desc, false) + end + return desc + end + local item_name = g.name_of(obj) + if g.JAPAN then + if obj.what_is == g.GOLD then + desc = g.znum(obj.quantity) + desc = desc .. g.mesg[28] + return desc + end + if obj.what_is == g.WEAPON and obj.quantity > 1 then + desc = g.znum(obj.quantity) + desc = desc .. g.mesg[29] + elseif obj.what_is == g.FOOD then + desc = g.znum(obj.quantity) + desc = desc .. ((obj.which_kind == g.RATION) and g.mesg[30] or g.mesg[31]) + desc = desc .. item_name + -- goto ANA + desc = desc .. get_desc_ANA(obj) + return desc + elseif obj.what_is ~= g.ARMOR and obj.quantity > 1 then + desc = g.znum(obj.quantity) + desc = desc .. g.mesg[32] + end + else + if obj.what_is == g.GOLD then + desc = string.format(g.mesg[28], obj.quantity) + return desc + end + if obj.what_is ~= g.ARMOR then + if g.English and obj.quantity == 1 then + desc = capitalize("a ", capitalized) + else + desc = string.format(g.mesg[29], obj.quantity) + end + end + if obj.what_is == g.FOOD then + if obj.which_kind == g.RATION then + if g.English and obj.quantity == 1 then + desc = capitalize(g.mesg[32], capitalized) + else + desc = string.format(g.mesg[30], obj.quantity) + end + else + if g.English and obj.quantity == 1 then + desc = capitalize("a ", capitalized) + else + desc = string.format(g.mesg[29], obj.quantity) + end + end + desc = desc .. item_name + -- goto ANA + desc = desc .. get_desc_ANA(obj) + return desc + end + end + local id_table = g.get_id_table(obj) + + local goto_CHECK_flag = nil + local goto_ID_flag = nil + local goto_CALL_flag = nil + if g.wizard then + -- goto ID + goto_ID_flag = true + elseif obj.what_is == g.WEAPON or obj.what_is == g.ARMOR + or obj.what_is == g.WAND or obj.what_is == g.RING then + -- goto CHECK + goto_CHECK_flag = true + end + + local id_status = id_table[obj.which_kind].id_status + if not goto_ID_flag and (goto_CHECK_flag or id_status == g.UNIDENTIFIED) then + -- ::CHECK:: + goto_CHECK_flag = true + if obj.what_is == g.SCROL then + if g.JAPAN then + desc = desc .. id_table[obj.which_kind].title .. g.mesg[33] .. item_name + else + desc = desc .. item_name .. g.mesg[33] .. id_table[obj.which_kind].title + end + elseif obj.what_is == g.POTION then + desc = desc .. id_table[obj.which_kind].title .. item_name + elseif obj.what_is == g.WAND or obj.what_is == g.RING then + if obj.identified or (id_status == g.IDENTIFIED) then + -- goto ID + goto_ID_flag = true + elseif id_status == g.CALLED then + -- goto CALL + goto_CALL_flag = true + else + desc = desc .. id_table[obj.which_kind].title .. item_name + end + elseif obj.what_is == g.ARMOR then + if obj.identified then + -- goto ID + goto_ID_flag = true + else + desc = desc .. id_table[obj.which_kind].title + end + elseif obj.what_is == g.WEAPON then + if obj.identified then + -- goto ID + goto_ID_flag = true + else + desc = desc .. g.name_of(obj) + end + end + end + if goto_ID_flag or (not goto_CHECK_flag and id_status == g.IDENTIFIED) then + -- ::ID:: + if obj.what_is == g.SCROL or obj.what_is == g.POTION then + if g.JAPAN then + desc = desc .. id_table[obj.which_kind].real .. item_name + else + desc = desc .. item_name .. id_table[obj.which_kind].real + end + elseif obj.what_is == g.RING then + if g.JAPAN then + desc = desc .. id_table[obj.which_kind].real + end + if g.wizard or obj.identified then + if obj.which_kind == g.DEXTERITY or obj.which_kind == g.ADD_STRENGTH then + desc = desc .. g.mesg[537] .. g.znum(obj.class, true) .. g.mesg[538] + end + end + desc = desc .. item_name + if not g.JAPAN then + desc = desc .. id_table[obj.which_kind].real + end + elseif obj.what_is == g.WAND then + if g.JAPAN then + desc = desc .. id_table[obj.which_kind].real .. item_name + else + desc = desc .. item_name .. id_table[obj.which_kind].real + end + if g.wizard or obj.identified then + desc = desc .. g.mesg[539] .. g.znum(obj.class) .. g.mesg[540] + end + elseif obj.what_is == g.ARMOR then + desc = desc .. g.mesg[537] .. g.znum(obj.d_enchant, true) .. g.mesg[538] + desc = desc .. id_table[obj.which_kind].title + desc = desc .. g.mesg[539] .. g.znum(g.get_armor_class(obj)) .. g.mesg[540] + elseif obj.what_is == g.WEAPON then + desc = desc .. g.mesg[537] .. g.znum(obj.hit_enchant, true) + desc = desc .. g.mesg[541] .. g.znum(obj.d_enchant, true) .. g.mesg[538] + desc = desc .. g.name_of(obj) + end + elseif goto_CALL_flag or (not goto_CHECK_flag and id_status == g.CALLED) then + -- ::CALL:: + if obj.what_is == g.SCROL or obj.what_is == g.POTION or + obj.what_is == g.WAND or obj.what_is == g.RING then + if g.JAPAN then + desc = desc .. id_table[obj.which_kind].title .. g.mesg[34] .. item_name + else + desc = desc .. item_name .. g.mesg[34] .. id_table[obj.which_kind].title + end + end + end + -- ::ANA:: + desc = desc .. get_desc_ANA(obj) + return desc +end + +function g.get_wand_and_ring_materials() + local j + local used = {} + for i = 0, g.WANDS-1 do + repeat + j = g.get_rand(0, g.WAND_MATERIALS-1) + until not used[j] + used[j] = true + g.id_wands[i].title = wand_materials[j] .. g.mesg[39] + g.is_wood[i] = (j > g.MAX_METAL) + end + used = {} + for i = 0, g.RINGS-1 do + repeat + j = g.get_rand(0, g.GEMS-1) + until not used[j] + used[j] = true + g.id_rings[i].title = gems[j] .. g.mesg[40] + end +end + +function g.single_inv(ichar) + local ch = (ichar and ichar or g.pack_letter(g.mesg[41], g.ALL_OBJECTS)) + + if ch == g.CANCEL then + return + end + local obj = g.get_letter_object(ch) + if not obj then + g.message(g.mesg[41]) + return + end + local desc = ch + desc = desc .. ((obj.what_is == g.ARMOR and obj.is_protected) and '}' or ')') + desc = desc .. ' ' + desc = desc .. g.get_desc(obj, true) + g.message(desc) +end + +function g.get_id_table(obj) + if obj.what_is == g.SCROL then + return g.id_scrolls + elseif obj.what_is == g.POTION then + return g.id_potions + elseif obj.what_is == g.WAND then + return g.id_wands + elseif obj.what_is == g.RING then + return g.id_rings + elseif obj.what_is == g.WEAPON then + return g.id_weapons + elseif obj.what_is == g.ARMOR then + return g.id_armors + end + return nil +end + +function g.inv_weapon() + if g.rogue.weapon then + g.single_inv(g.rogue.weapon.ichar) + else + g.message(g.mesg[43]) + end +end + +function g.inv_armor() + if g.rogue.armor then + g.single_inv(g.rogue.armor.ichar) + else + g.message(g.mesg[44]) + end +end + +function g.discovered() + local msg = ' ' .. g.mesg[494] + if g.JAPAN then + msg = ' ' .. msg + end + local len = g.strwidth(msg) + + g.message(g.mesg[45]) + local ch + while true do + ch = g.rgetchar() + if ch == g.CANCEL then + g.check_message() + return + elseif string.find('?!=/*', ch, 1, true) then + g.check_message() + break + else + g.sound_bell() + end + end + + local found = {} + local dobj = { + { type = g.SCROL, ch = '?', max = g.SCROLS, name = g.mesg[3], id = g.id_scrolls }, + { type = g.POTION, ch = '!', max = g.POTIONS, name = g.mesg[4], id = g.id_potions }, + { type = g.WAND, ch = '/', max = g.WANDS, name = g.mesg[5], id = g.id_wands }, + { type = g.RING, ch = '=', max = g.RINGS, name = g.mesg[8], id = g.id_rings }, + } + local dlist = {} + local dp = {} + + for idx, op in ipairs(dobj) do + if ch == op.ch or ch == '*' then + for i = 0, op.max - 1 do + local j = op.id[i].id_status + if j == g.IDENTIFIED or j == g.CALLED then + dp.type = op.type + dp.no = i + dp.name = op.name + if g.wizard or j == g.IDENTIFIED then + dp.real = op.id[i].real + dp.sub = "" + else + dp.real = op.id[i].title + dp.sub = g.mesg[34] + end + + if not g.JAPAN then + if op.type == g.WAND and g.is_wood[i] then + dp.name = g.mesg[6] + end + end + found[op.type] = true + table.insert(dlist, dp) + dp = {} + end + end + if not found[op.type] then + dp.type = op.type + dp.no = -1 + dp.name = op.name + if g.English then + -- add "s" of the plural + dp.name = dp.name:gsub(" ", "s ") + end + table.insert(dlist, dp) + dp = {} + end + dp.type = 0 + table.insert(dlist, dp) + dp = {} + end + end + + if g.table_is_empty(found) then + g.message(g.mesg[46]) + return + end + + local d_idx = 1 + dp = dlist[d_idx] + repeat + -- ::nextpage:: + local nextpg = false + local i = 0 + local maxlen = len + while d_idx <= #dlist and i < g.DROWS - 2 do + if dp.type == 0 then + g.descs[i] = " " + elseif dp.no < 0 then + g.descs[i] = string.format(g.mesg[47], dp.name) + else + if g.JAPAN then + g.descs[i] = " " .. dp.real .. dp.sub .. dp.name + elseif g.English then + g.descs[i] = " " .. capitalize(dp.name, true) .. dp.real + else + g.descs[i] = " " .. dp.name .. dp.real + end + end + local n = g.strwidth(g.descs[i]) + if n > maxlen then + maxlen = n + end + i = i + 1 + d_idx = d_idx + 1 + dp = dlist[d_idx] + end + + if i == 0 or i == 1 and g.descs[0] == "" then + -- can be here only in 2nd pass (exactly one page) + return + end + + g.descs[i] = msg + i = i + 1 + + local col = g.DCOLS - (maxlen + 2 + 1) + for row = 0, i-1 do + g.mvaddstr(row, col, g.descs[row]) + end + g.refresh() + g.wait_for_ack() + for row = 0, g.DROWS-2 do + g.mvaddstr(row, 0, '') + end + + if d_idx <= #dlist then + -- goto nextpage + nextpg = true + end + until not nextpg +end + +function g.znum(n, plus) + local z_num_list = { + [0] = g.mesg[523], + [1] = g.mesg[524], + [2] = g.mesg[525], + [3] = g.mesg[526], + [4] = g.mesg[527], + [5] = g.mesg[528], + [6] = g.mesg[529], + [7] = g.mesg[530], + [8] = g.mesg[531], + [9] = g.mesg[532], + } + local z_num_plus = g.mesg[533] + local z_num_minus = g.mesg[534] + + local str = '' + if plus and n >= 0 then + str = str .. z_num_plus + end + local tmp = string.format("%d", n) + for i = 1, #tmp do + local c = tmp:sub(i, i) + if c == '-' then + str = str .. z_num_minus + else + str = str .. z_num_list[tonumber(c)] + end + end + return str +end diff --git a/autoload/rogue/level.lua b/autoload/rogue/level.lua new file mode 100644 index 0000000..d3fdf29 --- /dev/null +++ b/autoload/rogue/level.lua @@ -0,0 +1,765 @@ +local g = Rogue -- alias + +g.cur_level = 0 +g.max_level = 1 +g.cur_room = 0 +g.new_level_message = nil +g.party_room = 0 +g.level_points = {} + +local r_de = 0 +local random_rooms = { [0] = 3, 7, 5, 2, 0, 6, 1, 4, 8 } + +function g.init_level() + g.cur_room = g.NO_ROOM + g.party_room = g.NO_ROOM + g.level_points = { + [0] = 10, + 20, + 40, + 80, + 160, + 320, + 640, + 1300, + 2600, + 5200, + 10000, + 20000, + 40000, + 80000, + 160000, + 320000, + 1000000, + 3333333, + 6666666, + g.MAX_EXP, + 99900000 + } +end + +local function make_room(rn, r1, r2, r3) + local left_col = 0 + local right_col = 0 + local top_row = 0 + local bottom_row = 0 + local width = 0 + local height = 0 + local row_offset = 0 + local col_offset = 0 + local ch = 0 + local goto_B = false + local goto_END = false + if rn == g.BIG_ROOM then + top_row = g.get_rand(g.MIN_ROW, g.MIN_ROW+5) + bottom_row = g.get_rand(g.DROWS-7, g.DROWS-2) + left_col = g.get_rand(0, 10) + right_col = g.get_rand(g.DCOLS-11, g.DCOLS-2) + rn = 0 + goto_B = true + -- goto B + end + if not goto_B then + local mod_rn = rn % 3 + if mod_rn == 0 then + left_col = 0 + right_col = g.COL1-1 + elseif mod_rn == 1 then + left_col = g.COL1+1 + right_col = g.COL2-1 + elseif mod_rn == 2 then + left_col = g.COL2+1 + right_col = g.DCOLS-2 + end + local div_rn = g.int_div(rn, 3) + if div_rn == 0 then + top_row = g.MIN_ROW + bottom_row = g.ROW1-1 + elseif div_rn == 1 then + top_row = g.ROW1+1 + bottom_row = g.ROW2-1 + elseif div_rn == 2 then + top_row = g.ROW2+1 + bottom_row = g.DROWS - 2 + end + height = g.get_rand(4, (bottom_row-top_row+1)) + width = g.get_rand(7, (right_col-left_col-2)) + + row_offset = g.get_rand(0, ((bottom_row-top_row)-height+1)) + col_offset = g.get_rand(0, ((right_col-left_col)-width+1)) + + top_row = top_row + row_offset + bottom_row = top_row + height - 1 + + left_col = left_col + col_offset + right_col = left_col + width - 1 + + if (rn ~= r1) and (rn ~= r2) and (rn ~= r3) and g.rand_percent(40) then + goto_END = true + -- goto END + end + end + -- ::B:: + if not goto_END then + g.rooms[rn].is_room = g.R_ROOM + for i = top_row, bottom_row do + for j = left_col, right_col do + if i == top_row or i == bottom_row then + ch = g.HORWALL + elseif j == left_col or j == right_col then + ch = g.VERTWALL + else + ch = g.FLOOR + end + g.dungeon[i][j] = {} + g.dungeon[i][j][ch] = g.dungeon_desc[ch] + end + end + end + -- ::END:: + g.rooms[rn].top_row = top_row + g.rooms[rn].bottom_row = bottom_row + g.rooms[rn].left_col = left_col + g.rooms[rn].right_col = right_col +end + + +local function same_row(room1, room2) + return g.int_div(room1, 3) == g.int_div(room2, 3) +end + +local function same_col(room1, room2) + return (room1 % 3) == (room2 % 3) +end + +local function put_door(rm, dir) + local row = 0 + local col = 0 + + local wall_width = (rm.is_room == g.R_MAZE) and 0 or 1 + + if dir == g.UPWARD or dir == g.DOWN then + row = (dir == g.UPWARD) and rm.top_row or rm.bottom_row + repeat + col = g.get_rand(rm.left_col+wall_width, rm.right_col-wall_width) + until (g.dungeon[row][col][g.HORWALL] or g.dungeon[row][col][g.TUNNEL]) + elseif dir == g.RIGHT or dir == g.LEFT then + col = (dir == g.LEFT) and rm.left_col or rm.right_col + repeat + row = g.get_rand(rm.top_row+wall_width, rm.bottom_row-wall_width) + until (g.dungeon[row][col][g.VERTWALL] or g.dungeon[row][col][g.TUNNEL]) + end + if rm.is_room == g.R_ROOM then + g.dungeon[row][col] = {} + g.dungeon[row][col][g.DOOR] = g.dungeon_desc[g.DOOR] + end + if (g.cur_level > 2) and g.rand_percent(g.HIDE_PERCENT) then + g.dungeon[row][col][g.HIDDEN] = g.dungeon_desc[g.HIDDEN] + end + rm.doors[g.int_div(dir, 2)].door_row = row + rm.doors[g.int_div(dir, 2)].door_col = col + + return row, col +end + +local function hide_boxed_passage(row1, col1, row2, col2, n) + local row = 0 + local col = 0 + local row_cut = 0 + local col_cut = 0 + local h = 0 + local w = 0 + + if g.cur_level > 2 then + if row1 > row2 then + row1, row2 = row2, row1 + end + if col1 > col2 then + col1, col2 = col2, col1 + end + h = row2 - row1 + w = col2 - col1 + + if (w >= 5) or (h >= 5) then + row_cut = (h >= 2) and 1 or 0 + col_cut = (w >= 2) and 1 or 0 + + for i = 0, n-1 do + for j = 0, 9 do + row = g.get_rand(row1 + row_cut, row2 - row_cut) + col = g.get_rand(col1 + col_cut, col2 - col_cut) + if g.dungeon[row][col][g.TUNNEL] then + g.dungeon[row][col][g.HIDDEN] = g.dungeon_desc[g.HIDDEN] + break + end + end + end + end + end +end + +local function draw_simple_passage(row1, col1, row2, col2, dir) + local middle = 0 + + if dir == g.LEFT or dir == g.RIGHT then + if col1 > col2 then + row1, row2 = row2, row1 + col1, col2 = col2, col1 + end + middle = g.get_rand(col1+1, col2-1) + for i = col1+1, middle-1 do + g.dungeon[row1][i] = {} + g.dungeon[row1][i][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + end + if row1 > row2 then + for i = row1, row2+1, -1 do + g.dungeon[i][middle] = {} + g.dungeon[i][middle][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + end + else + for i = row1, row2-1 do + g.dungeon[i][middle] = {} + g.dungeon[i][middle][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + end + end + for i = middle, col2-1 do + g.dungeon[row2][i] = {} + g.dungeon[row2][i][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + end + else + if row1 > row2 then + row1, row2 = row2, row1 + col1, col2 = col2, col1 + end + middle = g.get_rand(row1+1, row2-1) + for i = row1+1, middle-1 do + g.dungeon[i][col1] = {} + g.dungeon[i][col1][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + end + if col1 > col2 then + for i = col1, col2+1, -1 do + g.dungeon[middle][i] = {} + g.dungeon[middle][i][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + end + else + for i = col1, col2-1 do + g.dungeon[middle][i] = {} + g.dungeon[middle][i][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + end + end + for i = middle, row2-1 do + g.dungeon[i][col2] = {} + g.dungeon[i][col2][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + end + end + if g.rand_percent(g.HIDE_PERCENT) then + hide_boxed_passage(row1, col1, row2, col2, 1) + end +end + +local function connect_rooms(room1, room2) + local row1 = 0 + local col1 = 0 + local row2 = 0 + local col2 = 0 + local dir = 0 + local rev = 0 + + if (not (g.rooms[room1].is_room == g.R_ROOM or g.rooms[room1].is_room == g.R_MAZE)) or + (not (g.rooms[room2].is_room == g.R_ROOM or g.rooms[room2].is_room == g.R_MAZE)) then + return false + end + if same_row(room1, room2) then + if g.rooms[room1].left_col > g.rooms[room2].right_col then + dir = g.LEFT + rev = g.RIGHT + else + dir = g.RIGHT + rev = g.LEFT + end + elseif same_col(room1, room2) then + if g.rooms[room1].top_row > g.rooms[room2].bottom_row then + dir = g.UPWARD + rev = g.DOWN + else + dir = g.DOWN + rev = g.UPWARD + end + else + return false + end + row1, col1 = put_door(g.rooms[room1], dir) + row2, col2 = put_door(g.rooms[room2], rev) + + repeat + draw_simple_passage(row1, col1, row2, col2, dir) + until not g.rand_percent(4) + + local dp = g.rooms[room1].doors[g.int_div(dir, 2)] + dp.oth_room = room2 + dp.oth_row = row2 + dp.oth_col = col2 + + dp = g.rooms[room2].doors[g.int_div(((dir+4)%g.DIRS), 2)] + dp.oth_room = room1 + dp.oth_row = row1 + dp.oth_col = col1 + return true +end + +function g.clear_level() + for i = 0, g.MAXROOMS-1 do + g.rooms[i].is_room = g.R_NOTHING + for j = 0, 3 do + g.rooms[i].doors[j].oth_room = g.NO_ROOM + end + end + for i = 0, g.MAX_TRAPS-1 do + g.traps[i].trap_type = g.NO_TRAP + end + for i = 0, g.DROWS-1 do + for j = 0, g.DCOLS-1 do + g.dungeon[i][j] = {} + end + end + g.detect_monster = false + g.see_invisible = false + g.being_held = false + g.bear_trap = 0 + g.party_room = g.NO_ROOM + g.rogue.row = -1 + g.rogue.col = -1 + g.clear() +end + +local function make_maze(r, c, tr, br, lc, rc) + local dirs = {} + dirs[0] = g.UPWARD + dirs[1] = g.DOWN + dirs[2] = g.LEFT + dirs[3] = g.RIGHT + + g.dungeon[r][c] = {} + g.dungeon[r][c][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + + if g.rand_percent(33) then + for i = 0, 9 do + local t1 = g.get_rand(0, 3) + local t2 = g.get_rand(0, 3) + + dirs[t1], dirs[t2] = dirs[t2], dirs[t1] + end + end + for i = 0, 3 do + if dirs[i] == g.UPWARD then + if ((r-1) >= tr) and + (not g.dungeon[r-1][c][g.TUNNEL]) and + (not g.dungeon[r-1][c-1][g.TUNNEL]) and + (not g.dungeon[r-1][c+1][g.TUNNEL]) and + (not g.dungeon[r-2][c][g.TUNNEL]) then + make_maze((r-1), c, tr, br, lc, rc) + end + elseif dirs[i] == g.DOWN then + if ((r+1) <= br) and + (not g.dungeon[r+1][c][g.TUNNEL]) and + (not g.dungeon[r+1][c-1][g.TUNNEL]) and + (not g.dungeon[r+1][c+1][g.TUNNEL]) and + (not g.dungeon[r+2][c][g.TUNNEL]) then + make_maze((r+1), c, tr, br, lc, rc) + end + elseif dirs[i] == g.LEFT then + if ((c-1) >= lc) and + (c-2 >= 0) and -- fixed original bug: access dungeon[r][-1] + (not g.dungeon[r][c-1][g.TUNNEL]) and + (not g.dungeon[r-1][c-1][g.TUNNEL]) and + (not g.dungeon[r+1][c-1][g.TUNNEL]) and + (not g.dungeon[r][c-2][g.TUNNEL]) then + make_maze(r, (c-1), tr, br, lc, rc) + end + elseif dirs[i] == g.RIGHT then + if ((c+1) <= rc) and + (not g.dungeon[r][c+1][g.TUNNEL]) and + (not g.dungeon[r-1][c+1][g.TUNNEL]) and + (not g.dungeon[r+1][c+1][g.TUNNEL]) and + (not g.dungeon[r][c+2][g.TUNNEL]) then + make_maze(r, (c+1), tr, br, lc, rc) + end + end + end +end + +local function add_mazes() + if g.cur_level > 1 then + local start = g.get_rand(0, g.MAXROOMS-1) + local maze_percent = g.int_div((g.cur_level * 5), 4) + + if g.cur_level > 15 then + maze_percent = maze_percent + g.cur_level + end + for i = 0, g.MAXROOMS-1 do + local j = ((start + i) % g.MAXROOMS) + if g.rooms[j].is_room == g.R_NOTHING then + if g.rand_percent(maze_percent) then + g.rooms[j].is_room = g.R_MAZE + make_maze(g.get_rand(g.rooms[j].top_row+1, g.rooms[j].bottom_row-1), + g.get_rand(g.rooms[j].left_col+1, g.rooms[j].right_col-1), + g.rooms[j].top_row, g.rooms[j].bottom_row, + g.rooms[j].left_col, g.rooms[j].right_col) + hide_boxed_passage(g.rooms[j].top_row, g.rooms[j].left_col, + g.rooms[j].bottom_row, g.rooms[j].right_col, + g.get_rand(0, 2)) + end + end + end + end +end + +local function mix_random_rooms() + for i = 0, g.MAXROOMS-1 do + local j = g.get_rand(i, g.MAXROOMS - 1) + random_rooms[i], random_rooms[j] = random_rooms[j], random_rooms[i] + end +end + +local function mask_room(rn, mask) + local row = 0 + local col = 0 + + for i = g.rooms[rn].top_row, g.rooms[rn].bottom_row do + for j = g.rooms[rn].left_col, g.rooms[rn].right_col do + if g.dungeon[i][j][mask] then + row = i + col = j + return true, row, col + end + end + end + return false, row, col +end + +local function recursive_deadend(rn, offsets, srow, scol) + local de = 0 + local drow = 0 + local dcol = 0 + local tunnel_dir = 0 + + g.rooms[rn].is_room = g.R_DEADEND + g.dungeon[srow][scol] = {} + g.dungeon[srow][scol][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + + for i = 0, 3 do + de = rn + offsets[i] + if ((de < 0) or (de >= g.MAXROOMS)) or + (not (same_row(rn, de) or same_col(rn, de))) then + -- continue + else + if not (g.rooms[de].is_room == g.R_NOTHING) then + -- continue + else + drow = g.int_div(g.rooms[de].top_row + g.rooms[de].bottom_row, 2) + dcol = g.int_div(g.rooms[de].left_col + g.rooms[de].right_col, 2) + if same_row( rn, de) then + tunnel_dir = (g.rooms[rn].left_col < g.rooms[de].left_col) and g.RIGHT or g.LEFT + else + tunnel_dir = (g.rooms[rn].top_row < g.rooms[de].top_row) and g.DOWN or g.UPWARD + end + draw_simple_passage(srow, scol, drow, dcol, tunnel_dir) + r_de = de + recursive_deadend(de, offsets, drow, dcol) + end + end + end +end + +local function fill_it(rn, do_rec_de) + local tunnel_dir = 0 + local door_dir = 0 + local drow = 0 + local dcol = 0 + local target_room = 0 + local rooms_found = 0 + local srow = 0 + local scol = 0 + local did_this = false + local offsets = {} + offsets[0] = -1 + offsets[1] = 1 + offsets[2] = 3 + offsets[3] = -3 + + for i = 0, 9 do + srow = g.get_rand(0, 3) + scol = g.get_rand(0, 3) + local t = offsets[srow] + offsets[srow] = offsets[scol] + offsets[scol] = t + end + for i = 0, 3 do + target_room = rn + offsets[i] + if (target_room < 0 or target_room >= g.MAXROOMS) or + (not (same_row(rn, target_room) or same_col(rn, target_room))) or + (not (g.rooms[target_room].is_room == g.R_ROOM or g.rooms[target_room].is_room == g.R_MAZE)) then + -- continue + else + if same_row(rn, target_room) then + tunnel_dir = (g.rooms[rn].left_col < g.rooms[target_room].left_col) and g.RIGHT or g.LEFT + else + tunnel_dir = (g.rooms[rn].top_row < g.rooms[target_room].top_row) and g.DOWN or g.UPWARD + end + door_dir = ((tunnel_dir + 4) % g.DIRS) + if g.rooms[target_room].doors[g.int_div(door_dir, 2)].oth_room ~= g.NO_ROOM then + -- continue + else + local mask_room_ret = false + local tmp_srow = 0 + local tmp_scol = 0 + mask_room_ret, tmp_srow, tmp_scol = mask_room(rn, g.TUNNEL) + if mask_room_ret then + srow = tmp_srow + scol = tmp_scol + end + if ((not do_rec_de) or did_this) or (not mask_room_ret) then + srow = g.int_div(g.rooms[rn].top_row + g.rooms[rn].bottom_row, 2) + scol = g.int_div(g.rooms[rn].left_col + g.rooms[rn].right_col, 2) + end + drow, dcol = put_door(g.rooms[target_room], door_dir) + rooms_found = rooms_found + 1 + draw_simple_passage(srow, scol, drow, dcol, tunnel_dir) + g.rooms[rn].is_room = g.R_DEADEND + g.dungeon[srow][scol] = {} + g.dungeon[srow][scol][g.TUNNEL] = g.dungeon_desc[g.TUNNEL] + + local continue_flag = false + if (i < 3) and (not did_this) then + did_this = true + if g.coin_toss() then + continue_flag = true + end + end + if (rooms_found < 2) and do_rec_de then + recursive_deadend(rn, offsets, srow, scol) + end + if not continue_flag then + break + end + end + end + end +end + +local function fill_out_level() + mix_random_rooms() + + r_de = g.NO_ROOM + + for i = 0, g.MAXROOMS-1 do + local rn = random_rooms[i] + if g.rooms[rn].is_room == g.R_NOTHING or + (g.rooms[rn].is_room == g.R_CROSS and g.coin_toss()) then + fill_it(rn, 1) + end + end + if r_de ~= g.NO_ROOM then + fill_it(r_de, 0) + end +end + +function g.make_level() + if g.cur_level < g.LAST_DUNGEON then + g.cur_level = g.cur_level + 1 + end + if g.cur_level > g.max_level then + g.max_level = g.cur_level + end + local must_exist1 = g.get_rand(0, 2) + local must_exist2 = 0 + local must_exist3 = 0 + local vertical = g.coin_toss() + if vertical then + must_exist2 = must_exist1 + 3 + must_exist3 = must_exist2 + 3 + else + must_exist1 = must_exist1 * 3 + must_exist2 = must_exist1 + 1 + must_exist3 = must_exist2 + 1 + end + local big_room = ((g.cur_level == g.party_counter) and g.rand_percent(1)) + if big_room then + make_room(g.BIG_ROOM, 0, 0, 0) + else + for i = 0, g.MAXROOMS-1 do + make_room(i, must_exist1, must_exist2, must_exist3) + end + end + if not big_room then + add_mazes() + + mix_random_rooms() + + for j = 0, g.MAXROOMS-1 do + local i = random_rooms[j] + + if i < g.MAXROOMS - 1 then + connect_rooms(i, i + 1) + end + if i < g.MAXROOMS - 3 then + connect_rooms(i, i + 3) + end + if i < g.MAXROOMS - 2 then + if g.rooms[i + 1].is_room == g.R_NOTHING and + (i + 1 ~= 4 or vertical) then + if connect_rooms(i, i + 2) then + g.rooms[i + 1].is_room = g.R_CROSS + end + end + end + if i < g.MAXROOMS - 6 then + if g.rooms[i + 3].is_room == g.R_NOTHING and + (i + 3 ~= 4 or vertical) then + if connect_rooms(i, i + 6) then + g.rooms[i + 3].is_room = g.R_CROSS + end + end + end + if g.is_all_connected() then + break + end + end + fill_out_level() + end + if (not g.has_amulet()) and (g.cur_level >= g.AMULET_LEVEL) then + g.put_amulet() + end +end + +function g.put_player(nr) + local rn = nr + local misses = 0 + local row + local col + + while (misses < 2) and (rn == nr) do + row, col = g.gr_row_col({[g.FLOOR]=true, [g.TUNNEL]=true, [g.OBJECT]=true, [g.STAIRS]=true}) + rn = g.get_room_number(row, col) + + misses = misses + 1 + end + g.rogue.row = row + g.rogue.col = col + + if g.dungeon[g.rogue.row][g.rogue.col][g.TUNNEL] then + g.cur_room = g.PASSAGE + else + g.cur_room = rn + end + if g.cur_room ~= g.PASSAGE then + g.light_up_room(g.cur_room) + else + g.light_passage(g.rogue.row, g.rogue.col) + end + g.wake_room(g.get_room_number(g.rogue.row, g.rogue.col), true, g.rogue.row, g.rogue.col) + + if g.new_level_message then + g.message(g.new_level_message) + g.new_level_message = nil + end + g.mvaddch(g.rogue.row, g.rogue.col, g.rogue.fchar) +end + +function g.drop_check() + if g.wizard then + return true + end + if g.dungeon[g.rogue.row][g.rogue.col][g.STAIRS] then + if g.levitate > 0 then + g.message(g.mesg[48]) + return false + end + return true + end + g.message(g.mesg[49]) + return false +end + +function g.check_up() + if not g.wizard then + if not g.dungeon[g.rogue.row][g.rogue.col][g.STAIRS] then + g.message(g.mesg[50]) + return false + end + if not g.has_amulet() then + g.message(g.mesg[51]) + return false + end + end + g.new_level_message = g.mesg[52] + if g.cur_level == 1 then + g.win() + -- NOTREACHED + else + g.cur_level = g.cur_level - 2 + return true + end + return false +end + +local function get_exp_level(e) + local i = 0 + while i < g.MAX_EXP_LEVEL - 1 do + if g.level_points[i] > e then + break + end + i = i + 1 + end + return i + 1 +end + +function g.add_exp(e, promotion) + g.rogue.exp_points = g.rogue.exp_points + e + if g.rogue.exp_points < g.level_points[g.rogue.exp-1] then + g.print_stats() + return + end + local new_exp = get_exp_level(g.rogue.exp_points) + if g.rogue.exp_points > g.MAX_EXP then + g.rogue.exp_points = g.MAX_EXP + 1 + end + for i = g.rogue.exp + 1, new_exp do + if g.JAPAN then + g.message(string.format(g.mesg[53], g.znum(i))) + else + g.message(string.format(g.mesg[53], i)) + end + if promotion then + local hp = g.hp_raise() + g.rogue.hp_current = g.rogue.hp_current + hp + g.rogue.hp_max = g.rogue.hp_max + hp + end + g.rogue.exp = i + g.print_stats() + end +end + +function g.hp_raise() + if g.wizard then + return 10 + else + return g.get_rand(3, 10) + end +end + +function g.show_average_hp() + local real_average = 0 + local effective_average = 0 + + if g.rogue.exp ~= 1 then + real_average = g.int_div(((g.rogue.hp_max - g.extra_hp - g.INIT_HP) + g.less_hp) + * 100, (g.rogue.exp - 1)) + effective_average = g.int_div((g.rogue.hp_max - g.INIT_HP) + * 100, (g.rogue.exp - 1)) + end + g.message(string.format(g.mesg[54], + g.int_div(real_average, 100), (real_average % 100), + g.int_div(effective_average, 100), (effective_average % 100), + g.extra_hp, g.less_hp)) +end diff --git a/autoload/rogue/main.lua b/autoload/rogue/main.lua new file mode 100644 index 0000000..60745b7 --- /dev/null +++ b/autoload/rogue/main.lua @@ -0,0 +1,203 @@ + +local original_global_data = {} +for k, v in pairs(_G) do + original_global_data[k] = tostring(v) +end + +Rogue = {} +local g = Rogue -- alias + +g.version = '1.0' + +-- Checks added global data is Rogue only +local function check_global() + local added_global_data = {} + for k, v in pairs(_G) do + if not original_global_data[k] then + added_global_data[k] = tostring(v) + end + end + g.p("original_global_data", true) + g.p("added_global_data", true) +end + +local function init_dirs() + g.home_dir = os.getenv('HOME') + if not g.home_dir then + g.home_dir = os.getenv('USERPROFILE') + if not g.home_dir then + g.home_dir = '.' + end + end + g.home_dir = g.home_dir:gsub('\\', '/') + + g.game_dir = g.get_vim_variable("g:rogue#directory") + if type(g.game_dir) ~= 'string' or g.game_dir == '' then + g.game_dir = g.home_dir + else + g.game_dir = g.game_dir:gsub('\\', '/') + g.game_dir = g.game_dir:gsub('~', g.home_dir) + end + + if string.char(g.home_dir:byte(#g.home_dir)) ~= '/' then + g.home_dir = g.home_dir .. '/' + end + if string.char(g.game_dir:byte(#g.game_dir)) ~= '/' then + g.game_dir = g.game_dir .. '/' + end +end + +g.mesg = {} +g.JAPAN = true + +local function read_mesg_file(fname) + local mesg_file = io.open(fname, "r") + if not mesg_file then + return false + end + for line in mesg_file:lines() do + local num, msg = line:match('^(%d+)%s*"([^"]*)"') + if num then + num = tonumber(num) + if not g.mesg[num] then + g.mesg[num] = msg + end + end + end + mesg_file:close() + return true +end + +local function read_mesg() + g.mesg = {} + + local file_dir = g.get_vim_variable("s:FILE_DIR") + local mesg_fname = g.get_vim_variable("g:rogue#message") + if type(mesg_fname) == 'string' and mesg_fname ~= '' then + mesg_fname = g.expand_fname(mesg_fname, file_dir) + read_mesg_file(mesg_fname) + end + + local japanese = g.get_vim_variable("g:rogue#japanese") + local lang = g.get_vim_variable("v:lang") + if type(japanese) == 'number' then + if japanese ~= 0 then + g.JAPAN = true + else + g.JAPAN = false + end + elseif lang:match('ja') then + g.JAPAN = true + else + g.JAPAN = false + end + local default_f + if g.JAPAN then + default_f = 'mesg' + else + default_f = 'mesg_E' + end + + local ret = read_mesg_file(file_dir .. default_f) + if not ret then + return false + end + + if not g.JAPAN and g.mesg[1]:find("English") then + g.English = true + end + + if vim then + g.save_encoding = vim.eval('s:save_encoding') + if vim.eval('&encoding') ~= g.save_encoding then + g.needs_iconv = true + for k, v in pairs(g.mesg) do + g.mesg[k] = g.iconv_from_utf8(v) + end + vim.command('let &encoding = s:save_encoding') + end + end + return true +end + +local function main() + if not read_mesg() then + print("Cannot open message file") + return + end + if vim then + if vim.eval("&columns") < g.DCOLS or vim.eval("&lines") < g.DROWS then + vim.eval('confirm("' .. g.mesg[14] .. '")') + return + end + end + local first = true + g.update_flag = true + + local args = g.split(g.get_vim_variable('s:args'), ' ') + if g.init(args) then + -- restored game + first = false + g.refresh() + g.play_level() + end + + while true do + g.free_stuff(g.level_objects) + g.free_stuff(g.level_monsters) + g.clear_level() + g.make_level() + g.put_objects() + g.put_stairs() + g.add_traps() + g.put_mons() + g.put_player(g.party_room) + g.print_stats() + if first then + g.message(string.format(g.mesg[10], g.nick_name)) + first = false + end + g.refresh() + g.play_level() + end +end + +function g.main() + init_dirs() + g.cov_start() + local ret, err = xpcall(main, g.error_handler) + g.cov_stop() + -- check_global() + g.log_close() + if not ret and err ~= g.EXIT_SUCCESS then + error(err) + end +end + +if not vim then + require 'const' + require 'curses' + require 'debug' + require 'hit' + require 'init' + require 'invent' + require 'level' + require 'message' + require 'monster' + require 'move' + require 'object' + require 'pack' + require 'play' + require 'random' + require 'ring' + require 'room' + require 'save' + require 'score' + require 'spechit' + require 'throw' + require 'trap' + require 'use' + require 'util' + require 'zap' + g.main() +end diff --git a/autoload/rogue/mesg b/autoload/rogue/mesg new file mode 100644 index 0000000..7df683d --- /dev/null +++ b/autoload/rogue/mesg @@ -0,0 +1,723 @@ + ローグ メッセージファイル + +文字コードは UTF-8 である必要があります。 +エスケープシーケンスなどのコントロールコードを含めることはできません。 +文字列の長さは最大 79 バイトです。 +メッセージファイルのフォーマットは、 +メッセージ番号 "メッセージ" +で、このフォーマット以外の部分はすべてコメントとして読み飛ばされます。 + + +メッセージのバージョン(play.c) +1 "Message Japanese version (by ohta@src.ricoh.co.jp)" +持ち物の種類 +2 "食糧" +3 "巻き物" +4 "水薬" +5 "つえ" +6 "" "staff " +7 "よろい" +8 "指輪" +9 "魔除け" +file: main.c +10 "やあ、%s。 運命の洞窟へようこそ..." + +file: init.c +--More-- (now only in message.c) +11 "[続く]" +byebye_string: quit from interrupt +12 "それでは、またね。" +init() +pen name 'pn' is NULL or longer than 30 +13 "おたく、いったい誰なの?" +screen too small (UNIX) +14 "ごめん! 画面の大きさは最低24×80なんだ。" +onintr() +15 "割り込みがあった。" +option ('o' command) +16 "好きな果物" +env_get_value +17 "メモリーが足りません。 ゲームを終了します。" + +file: hit.c +mon_hit() 怪物の攻撃 +18 "%sの攻撃はそれた。 " +19 "%s%sは命中した。 " +20 "" +21 "の攻撃" +rogue_hit() プレイヤーの攻撃 +22 "%sの攻撃はそれた。 " +23 "%sの攻撃は命中した。 " +mon_damage() +24 "%sを倒した。 " +fight() +25 "その方向には怪物がいない。" + +file: invent.c +inventory() +26 "持ちものは、1つも持っていない。" +get_desc() +27 "イェンダーの魔除け" +28 "個の金塊" +29 "本の" +30 "袋の" (食糧) +31 "個の" (こけもも) +32 "つの" (その他の持ちもの) +33 "という" (巻き物) +34 "と呼ぶ" (巻き物、水薬、杖、指輪) (discoverd() でも) +35 "(使っている)" (武器を) +36 "(着ている)" (よろいを) +37 "(左手)" (指輪) +38 "(右手)" +get_wand_and_ring_materials() +39 "の" (杖の材質: ...'の'杖) +40 "の" (指輪の材質: ...'の'指輪) +single_inv() +41 "調べる持ちものの種類は?" +42 "それは持っていない。" +inv_armor_weapon() +43 "武器は使っていない。" +44 "よろいは着ていない。" +discoverd() +45 "どの種類のものですか?" +46 "知っているものは、何もない。" +47 " (知っている%sはない)" + +file: level.c +drop_check() +48 "降りられない!" +49 "降りる階段がない。" +check_up() +50 "登る階段がない。" +51 "階段は何者かの手によってふさがれている。" +52 "胃袋をねじ切られるような気分がした。" +add_exp() +53 "レベル%sへようこそ。" "Welcome to level %d" 英語のときは %d +show_average_hp() +54 "基本上昇率: %d.%02d, 実効上昇率: %d.%02d (!: %d, V: %d)" + +file: message.c +get_direction() +55 "方角は?" "Direction?" +print_stats() +56 "階: " (4バイト, 英語の時は7文字) +57 "金塊: " (6バイト) +58 "体力: " (6バイト, 英語の時は4文字) +59 "強さ: " (6バイト, 英語の時は5文字) +60 "守備: " (6バイト, 英語の時は5文字) +61 "経験: " (6バイト, 英語の時は5文字) +get_status_line() +62 "階: 金塊: 体力: 強さ: 守備: 経験: " (日本語の時のみ) +monster.c +mon_name() +63 "何者か" +create_monster() +64 "遠くから、かすかな怒りの叫びが聞こえる。" +aggravate() +65 "どこからか、かん高いうなり声が聞こえてくる。" + +file: move.c +toplevel +66 "ようやく体が自由になった。" +one_move_rogue() +67 "怪物につかまえられて、逃げられない。" +68 "熊のわなが、なかなかはずれない。" +69 "を手に入れた。" +70 "の上にいる。" "Moved onto " +check_hunger() +71 "空腹" (4バイトまで、英語では6文字まで) +72 "空腹になってきた。" +73 "飢餓" (4バイトまで、英語では6文字まで) +74 "空腹のせいで力がなくなってきた。" +75 "瀕死" (4バイトまで、英語では6文字まで) +76 "空腹で、もう死にそうだ。" +77 "空腹で、目がくらくらする。" +reg_move() +78 "ようやく地面に足がついた。" +79 "素早くなる薬の効き目がなくなった。" + +file: object.c +name_of() +80 "???" (バグ対策?) +new_object_for_wizard() +81 "これ以上は物を持てない。" +82 "どんなものですか?" +83 "%sの種類は?" +84 "武器" weapon + +file: pack.c +toplevel +85 "呪われているので、それはできない!" +pick_up() +86 "拾いあげたとたん、巻き物はちりになってしまった。" +87 "もうこれ以上、物は持てない。" +drop() +88 "そこには、すでに何かが置かれている。" +89 "落とす物を持っていない。" +90 "落とす物は?" +91 "それは持っていない。" +92 "を落とした。" "Dropped " +pack_letter() +93 "それは1つも持っていない。" +take_off() +94 "を脱いだ。" "Was wearing " +95 "よろいを着ていない。" +wear() +96 "他のよろいを着ている。" +97 "どのよろいを?" +98 "それは持っていない。" +99 "それはよろいではない。" +100 "を身につけた。" "Wearing " +wield() +101 "どの武器を?" +102 "それは持っていない。" +103 "%sを武器にすることはできない。" +104 "よろい" +105 "指輪" +106 "その武器はもう使っている。" +107 "に持ちかえた。" "Wielding " +call_it() +108 "呼び名をつけるものは?" +109 "それは持っていない。" +110 "それには呼び名をつけることができない。" +111 "呼び名は?" +kick_into_pack() +112 "ここには、何もない。" +113 "拾うことができない!" +114 "を手に入れた。 " +file: play.c +toplevel +115 "コマンドが違います。" + +ヘルプメッセージ +116 "? ヘルプを表示する > 階段を降りる" +117 "/ 画面の文字が表すものを表示 < 階段を登る" +118 "h, j, k, l 左、下、上、右に進む . その場で休む" +119 "y, u, b, n 左上、右上、左下、右下に進む , 足元のものを拾う" +120 "<方角> 何かにぶつかるまで進む s わなや隠しとびらを探す" +121 "<方角> 何かを見つけるまで進む i 持ちものを見る" +122 "f<方角> やられそうになるまで戦う I 1つの持ちものを見る" +123 "F<方角> どちらかが倒れるまで戦う q 水薬を飲む" +124 "t<方角> 物を投げる r 巻き物を読む" +125 "m<方角> 落ちているものの上に乗る e 食べ物を食べる" +126 "z<方角> つえを振りかざす w 武器を手に持つ" +127 "^<方角> わなの種類を調べる W よろいを着る" +128 "P 最後のメッセージを再表示する T よろいを脱ぐ" +129 "R 画面を描き直す P 指輪をはめる" +130 "D 画面をファイルに書き出す R 指輪をはずす" +131 " コマンドを中止する d 持ちものを落とす" +132 "a 直前のコマンドを繰り返す c 持ちものに呼び名を付ける" +133 "D 今まで何を発見したかを表示 ) 現在の武器を見る" +134 "S ゲームをセーブして終了する ] 現在のよろいを見る" +135 "Q ゲームを中止する = 現在の指輪を見る" +136 "v バージョン情報を表示する @ プレイヤー行を描き直す" +137 "! シェルコマンドを実行する o オプションの表示・設定" + +文字の説明 +138 "プレイヤー" +139 "部屋の床" +140 "部屋の壁" +141 "部屋の壁" +142 "部屋のドア" +143 "部屋と部屋をむすぶ通路" +144 "隣の階への階段" +145 "隠されたわな" +146 "金塊" +147 "食糧" +148 "よろいかたびら" +149 "武器" +150 "巻き物" +151 "水薬" +152 "魔法の杖" +153 "魔法の指輪" +154 "イェンダーの魔除け" + +155 "どんな文字ですか?" + +dosshell() +MS-DOS, HUMAN +156 "[ exit コマンドでローグに戻ります ]" "[ \"exit\" コマンドでローグに戻ります ]" + "[ Type \"exit\" to return to rogue. ]" \ は使えない +UNIX +157 "[ シェルを終了するとローグに戻ります ]""[ Exit shell to return to rogue. ]" + +file: ring.c +toplevel +158 "左手(L)、それとも右手(R)?" +159 "そちらの手には指輪をしていない。" +put_on_ring() +160 "すでに両手に指輪をしている。" +161 "どの指輪を?" +162 "それは持っていない。" +163 "それは指輪ではない。" +164 "その指輪はもう手にはめている。" +165 "そちらの手にはもう指輪をしている。" +do_put_on() +166 "をはずした。" "Removed " +inv_rings() +167 "指輪ははめていない。" + +file: score.c +killed_by() + " この長さが最大 " +168 "寒さにより" to 172 (英語では ... of/from) +169 "飢えにより" to 173 +170 "毒矢により" to 174 +171 "逃亡により" to 175 +172 "死す" +173 "死す" +174 "死す" +175 "行方不明" + +176 "と戦いて死す" killed by a + +177 "安らかに" REST +178 "眠れ" IN +179 "" PEACE (日本語では未使用) +180 "$" (日本語) "%ld Au" (英語) +181 "。 所持金は$" %ld gold + +182 "おめでとう! 君はようやく太陽の光のもとにたどりつき、" +183 "そして、運命の洞窟から生きて戻った勇者の一人となった。" +184 "君は故郷へ帰り、持ち帰った宝物を売って大金を手に入れ、" +185 "それからは平安に遊び暮らしたということである‥‥。 " + +put_scores() +186 "得点ファイルがオープンできません。" +187 "最 高 得 点" "Top Ten Scores" + TOPSCO でないときは "最 高 得 点 者" "Top Ten Rogueists" +188 "順位 得点 名前" +insert_score() +189 "魔除けを手に、" with Amulet +190 "地下" +191 "階にて" +192 "寒さにより死す" died of hypothermia +193 "飢えにより死す" died of starvation +194 "毒矢により死す" killed by a dart +195 "逃亡す" quit +196 "運命の洞窟より生きて帰りたる勇者" a total winner +197 "と戦いて死す" killed by +sell_pack() +198 " 価格 持ちもの" Value Item +sf_error() +199 "得点ファイルが正しくありません。" +file: spechit.c +toplevel +200 "ほのお" +rust() +201 "水ごけの湿り気はすぐに消え去った。" +202 "よろいはさびてしまった!" +freeze() +203 "体が凍りついて、動けない!" +steal_gold() +204 "金塊を盗まれた!" +steal_item() +205 "を盗まれた!" She stole +check_imitator() +206 "おっと、こいつは%sだ!" +sting() +207 "%sに噛まれて、毒にやられた!" +drain_life() +208 "強さが減ってしまった!" +m_confuse() +209 "%sににらまれ、頭が混乱してしまった!" + +file: throw.c +throw() +210 "投げる武器は?" +211 "それは持っていない。" +throw_at_monster() +212 "%s" The %s +213 "はそれた。 " misses. +214 "は命中した。 " +flop_weapon() +215 "%sは地面に落ちると、どこかに消えてしまった。" + +file: trap.c +わなの情報はここに集めました。 +toplevel +216 "落し穴のわな" +217 "急に床がくずれ、足元から落ちてしまった!" +218 "熊のわな" +219 "熊のわなにつかまった!" +220 "テレポートのわな" +221 "テレポートしてしまった!" +222 "毒矢のわな" +223 "小さな投げ矢が飛んできて、肩にささった!" +224 "催眠ガスのわな" +225 "不思議なもやにつつまれ、眠り込んでしまった!" +226 "水のわな" +227 "頭の上から大量の水が降ってきた!" + +trap_player() +228 "危うく、わなにはまるところだった。" +id_trap() +229 "その方向には、わながない。" + +file: use.c +toplevel +230 "不思議な気分におそわれたが、すぐに消えていった。" +quaff() +231 "飲む水薬は?" "Quaff what?" +232 "それは持っていない。" +233 "それは水薬ではない。" +234 "何だか、力がわいてくるぞ!" +235 "これはうまい! からだがポカポカしてきた。" +236 "気分がよくなった!" +237 "とても気分がよくなった!" +238 "この水薬は毒だった!" +239 "ふにゃ? 何もかもが虹色にみえるなあ?" +240 "何だか酔っぱらいみたいな気分だ!" +241 "あれ? ここはどこ? 私はだれ?" +242 "体が宙に浮いてしまった!" +243 "体が素早く動くようになった!" +244 "う~む、%sジュースのような味がする。" +read_scroll() +245 "読む巻き物は?" Read what? +246 "それは持っていない。" +247 "それは巻き物ではない。" +248 "遠くから、狂ったような笑い声が聞こえてくる。" +249 "手に持った%sが、ほんの少し%s輝きに包まれた。" Your %sglow%s %sfor a moment +250 "何だか、手がむずむずする。" (武器を持っていない時) +251 "着ているよろいが、ほんの少し%s輝きに包まれた。" Your armor glows %sfor a moment +252 "何だか、体がむずむずする。" (よろいを着ていない時) +253 "これは持ちものを調べる巻き物だった。" +254 "知らないうちに眠り込んでしまった。" +255 "着ているよろいは、輝く金色の光に守られた。" +256 "何だか、顔がむずむずする。" (よろいを着ていない時) +257 "ふっと、誰かに見つめられているような気がした。" +258 "ふっと、女神の手に包まれているような気がした。" (幻覚を起こしている時) +259 "おや、この巻き物には地図が書いてある!" +idntfy() +260 "調べる持ちものは?" +261 "それは持っていない。" +eat() +262 "食べる物は?" +263 "それは持っていない。" +264 "それは食べられない。" +265 "う~む、まったりとしていて、それでいてこくがある。" +266 "ああ、おいしかった。" +267 "おや、なんて甘い%sだ。" +268 "げげっ、まずい!" +hold_monster() +269 "急に、体から力が抜けていくような気がした。" +270 "怪物は動けなくなった!" +271 "怪物どもは動けなくなった!" +unhallucinate() +272 "やっと、あたりの景色が元どおりになった。" +unblind() +273 "暗闇のとばりが上がってゆく。" +go_blind() +274 "深い暗闇のとばりがあたりをおおってゆく。" +get_ehch_color() +275 "青い" (着ているよろい、ほんの少し...輝きに包まれた。) +uncunfuse() +276 "ふたたび、景色が虹色に見えてきた。" +277 "ようやく、頭がはっきりしてきた。" + +file: zap.c +zapp() +278 "振りかざすつえは?" +279 "それは持っていない。" +280 "それを振りかざすことはできない。" +281 "しかし、何も起こらなかった。" (回数オーバー) +zap_monster() +282 "しかし、何も起こらなかった。" (役に立たない杖) + +怪物 +307 "水ごけの怪物" +308 "大こうもり" +309 "ケンタウロス" +310 "ドラゴン" +311 "大うずら" +312 "はえとりぐさ" +313 "翼ライオン" +314 "小鬼" +315 "氷の怪物" +316 "巨大トカゲ" +317 "大はやぶさ" +318 "金持ち妖精" +319 "メデューサ" +320 "ニンフ" +321 "欲ばり鬼" +322 "幽霊" +323 "大つのじか" +324 "がらがらへび" +325 "へび" +326 "巨人" +327 "一角獣" +328 "バンパイア" +329 "死霊" +330 "物まねの怪物" +331 "雪男" +332 "ゾンビ" + +果物 +333 "こけもも" + +水薬の色 +334 "青い" +335 "赤い" +336 "緑の" +337 "灰色の" +338 "茶色の" +339 "透明な" +340 "ピンクの" +341 "白い" +342 "紫の" +343 "黒い" +344 "黄色い" +345 "水色の" +346 "ぶどう色の" +347 "オレンジ色の" + +水薬の種類 +348 "強さが増す" +349 "強さが元にもどる" +350 "体力が回復する" +351 "体力がとても回復する" +352 "毒の" +353 "経験が増す" +354 "目が見えなくなる" +355 "幻覚をおこす" +356 "遠くの怪物がわかる" +357 "遠くのものがわかる" +358 "頭が混乱する" +359 "空中に浮きあがる" +360 "素早くなる" +361 "見えないものが見える" + +巻き物の種類 +362 "よろいを守る" +363 "怪物を封じこめる" +364 "武器に魔法をかける" +365 "よろいに魔法をかける" +366 "持ちものの種類がわかる" +367 "テレポートする" +368 "眠りにおちる" +369 "怪物を近寄せない" +370 "のろいを解く" +371 "怪物を作りだす" +372 "怪物を怒らせる" +373 "魔法の地図の" + +武器の種類 +374 "弓" +375 "投げ矢" +376 "矢" +377 "短剣" +378 "手裏剣" +379 "ほこ" +380 "長い剣" +381 "大きな剣" + +よろいの種類 +382 "革のよろい" +383 "かたびら" +384 "うろこのよろい" +385 "鎖かたびら" +386 "帯金のよろい" +387 "延金のよろい" +388 "鋼鉄のよろい" + +杖の種類 +389 "怪物を遠くに飛ばす" +390 "怪物を遅くする" +391 "怪物を混乱させる" +392 "怪物を見えなくする" +393 "ほかの怪物にする" +394 "怪物を素早くする" +395 "眠らせる" +396 "魔法のミサイルの" +397 "魔力を封じる" +398 "役に立たない" + +指輪の種類 +399 "身を隠す" +400 "テレポートする" +401 "体力が復活する" +402 "食べものが長持ちする" +403 "強さが増す" +404 "強さが減らない" +405 "機敏になる" +406 "飾りものの" +407 "見えないものが見える" +408 "よろいが丈夫になる" +409 "隠れたものを見つける" + +杖の材質 +410 "鋼鉄" +411 "青銅" +412 "金" +413 "銀" +414 "銅" +415 "ニッケル" +416 "コバルト" +417 "すず" +418 "鉄" +419 "マグネシウム" +420 "クロム" +421 "石炭" +422 "プラチナ" +423 "シリコン" +424 "チタン" +425 "チーク" +426 "樫" +427 "桜" +428 "白樺" +429 "松" +430 "杉" +431 "アメリカ杉" +432 "バルサ" +433 "象牙やし" +434 "胡桃" +435 "楓" +436 "マホガニー" +437 "楡" +438 "やし" +439 "柿" + +指輪の材質 +440 "ダイヤ" +441 "アクアマリン" +442 "るり" +443 "ルビー" +444 "エメラルド" +445 "サファイア" +446 "紫水晶" +447 "水晶" +448 "虎目石" +449 "オパール" +450 "めのう" +451 "トルコ石" +452 "真珠" +453 "ざくろ石" + +巻き物の音節 +454 "ぶん " +455 "に " +456 "とす " +457 "ら " +458 "ぽみ " +459 "ぷ " +460 "どん " +461 "せろ " +462 "い " +463 "か " +464 "そろ " +465 "む " +466 "ろお " +467 "わ " +468 "おふ " +469 "ろん " +470 "わっと " +471 "ぴお " +472 "ぽんぽ " +473 "どどら " +474 "ひゅ " +475 "よふ " +476 "ぽた " +477 "るん " +478 "ばび " +479 "ろろり " +480 "ずず " +481 "ぐり " +482 "こも " +483 "きき " +484 "およ " +485 "いむ " +486 "にゃあ " +487 "うー " +488 "ぐふる " +489 "こぴ " +490 "すーる " +491 "ぽろん " +492 "みーる " +493 "ぽきし " + + +rogue_sで分離されていなかったメッセージ + +file: play.c +toplevel +494 "=スペースを押してください=" "--Press space to continue--" + +file: score.c +quit() +495 "ゲームを終了してよいのですか?" "Really quit?" +killed_by() +496 "。" + +file: zap.c +wizardize() +497 "もはや、魔法使いではない。" "Not wizard anymore" +498 "魔法使いの合言葉は?" "Wizard's password:" +499 "ようこそ、魔法使いよ!" "Welcome, mighty wizard!" +500 "そんな合言葉、知らないね。" "Sorry" + +file: save.c +save_game() +501 "セーブするファイル名は?" "File name?" +502 "ゲームのセーブを中止しました。" "Game not saved" +save_into_file() +503 "セーブファイルにアクセスできません。" "Problem accessing the save file" +restore() +504 "ファイルがオープンできませんでした。" "Cannot open file" +505 "ファイルはリンクされています。" "File has link" +506 "セーブファイルの持ち主が違います。" "You're not the original player" +507 "これは元のセーブファイルではありません。" "Sorry, saved game is not in the same file" +508 "ファイル中によけいな文字があります。" "Extra characters in file" +509 "ファイルが変更されています。" "Sorry, file has been touched" +510 "ファイルを消すことができません。" "Cannot delete file" +r_read() +511 "ファイルが読めません。" "Read() failed, don't know why" +r_write() +512 "ファイルに書けません。" "Write() failed, don't know why" + +file: object.c +alloc_object() +513 "メモリーが足りません。 ゲームをセーブします。" "Cannot allocate object, saving game" + +file: init.c +toplevel +514 "終了するかどうか確認をとる" "Ask whether quit or not on quit signal" +515 "移動中の表示を行わない" "Show position only at end of run" +516 "通路の角で止まらずに進む" "Follow turnings in passageways" +517 "ゲーム終了時に墓標を表示する" "Print out tombstone and score when killed" +518 "キャラクターをカラーで表示する" "Show characters in map with color" +519 "セーブファイル名" "Save filename" +520 "ニックネーム" "Your nickname" +521 "ゲームディレクトリー名" "Game directory name" +522 "キャラクターの表示色マッピング" "Color mapping for characters" + +file: invent.c +znum() +523 "0" +524 "1" +525 "2" +526 "3" +527 "4" +528 "5" +529 "6" +530 "7" +531 "8" +532 "9" +533 "+" +534 "-" +make_scroll_titles() +535 "「" "'" +536 "」" "' " +get_desc() +537 "(" +538 ")" +539 "[" +540 "]" +541 "," + +file: machdep.c +md_gln() +542 "戦士" "Fighter" + +file: init.c +do_args() +543 "再開できませんでした。" "Cannot resume" diff --git a/autoload/rogue/mesg_E b/autoload/rogue/mesg_E new file mode 100644 index 0000000..a3c81cb --- /dev/null +++ b/autoload/rogue/mesg_E @@ -0,0 +1,722 @@ + Rogue message file + +The character code needs to be UTF-8. +Control codes, such as an escape sequence, cannot be included. +The maximum length of a string is 79 bytes. +The message file format is: +MessageNumber "Message" +The other parts are skipped as comments. + +Message Version(play.c) +1 "Message English version" +kind of item +2 "food " "食糧" +3 "scroll " "巻き物" +4 "potion " "水薬" +5 "wand " "つえ" +6 "staff " "" +7 "armor " "よろい" +8 "ring " "指輪" +9 "amlet " "魔除け" +file: main.c +10 "Hello %s, welcome to the Dungeons of Doom..." "やあ、%s。 運命の洞窟へようこそ..." + +file: init.c +--More-- (now only in message.c) +11 "--More--" "[続く]" +byebye_string: quit from interrupt +12 "Okay, bye bye!" "それでは、またね。" +init() +pen name 'pn' is NULL or longer than 30 +13 "Hey! Who are you?" "おたく、いったい誰なの?" +screen too small (UNIX) +14 "Must be played on 24x80 screen" "ごめん! 画面の大きさは最低24×80なんだ。" +onintr() +15 "Interrupt" "割り込みがあった。" +option ('o' command) +16 "Your favorite fruit" "好きな果物" +env_get_value +17 "Cannot alloc() memory" "メモリーが足りません。 ゲームを終了します。" + +file: hit.c +mon_hit() 怪物の攻撃 +18 "The %s misses" "%sの攻撃はそれた。 " +19 "The %s hit" "%s%sは命中した。 " +20 "" +21 "" "の攻撃" +rogue_hit() プレイヤーの攻撃 +22 "You miss. " "%sの攻撃はそれた。 " +23 "You hit. " "%sの攻撃は命中した。 " +mon_damage() +24 "Defeated the %s" "%sを倒した。 " +fight() +25 "I see no monster there" "その方向には怪物がいない。" + +file: invent.c +inventory() +26 "Your pack is empty" "持ちものは、1つも持っていない。" +get_desc() +27 "The Amulet of Yendor " "イェンダーの魔除け" +28 "%d pieces of gold" "個の金塊" +29 "%d " (よろい以外のもの) "本の" +30 "%d rations of " "袋の" (食糧) +31 "Some " (1袋のとき) "個の" (こけもも) +32 "some " (1袋のとき) "つの" (その他の持ちもの) +33 "titled " "という" (巻き物) +34 "called " (discoverd()では使われない) "と呼ぶ" (巻き物、水薬、杖、指輪) (discoverd() でも) +35 "(weapon in hand)" "(使っている)" (武器を) +36 "(being worn)" "(着ている)" (よろいを) +37 "(on left hand)" "(左手)" (指輪) +38 "(on right hand)" "(右手)" +get_wand_and_ring_materials() +39 "" not used "の" (杖の材質: ...'の'杖) +40 "" not used "の" (指輪の材質: ...'の'指輪) +single_inv() +41 "Inventory what?" "調べる持ちものの種類は?" +42 "No such item." "それは持っていない。" +inv_armor_weapon() +43 "Not wielding anything" "武器は使っていない。" +44 "Not wearing anything" "よろいは着ていない。" +discoverd() +45 "What type?" "どの種類のものですか?" +46 "Nothing discovered" "知っているものは、何もない。" +47 " Nothing about %s" " (知っている%sはない)" + +file: level.c +drop_check() +48 "You're floating in the air!" "降りられない!" +49 "I see no way down" "降りる階段がない。" +check_up() +50 "I see no way up" "登る階段がない。" +51 "Your way is magically blocked" "階段は何者かの手によってふさがれている。" +52 "You feel a wrenching sensation in your gut" "胃袋をねじ切られるような気分がした。" +add_exp() +53 "Welcome to level %d" 英語のときは %d "レベル%sへようこそ。" +show_average_hp() +54 "R-Hp: %d.%02d, E-Hp: %d.%02d (!: %d, V: %d)" "基本上昇率: %d.%02d, 実効上昇率: %d.%02d (!: %d, V: %d)" + +file: message.c +get_direction() +55 "Direction?" "方角は?" +print_stats() +56 "Level: " "階: " (4バイト, 英語の時は7文字) +57 "Gold: " "金塊: " (6バイト) +58 "Hp: " "体力: " (6バイト, 英語の時は4文字) +59 "Str: " "強さ: " (6バイト, 英語の時は5文字) +60 "Arm: " "守備: " (6バイト, 英語の時は5文字) +61 "Exp: " "経験: " (6バイト, 英語の時は5文字) +get_status_line() +62 "" "階: 金塊: 体力: 強さ: 守備: 経験: " (日本語の時のみ) +monster.c +mon_name() +63 "something" "何者か" +create_monster() +64 "You hear a faint cry of anguish in the distance" "遠くから、かすかな怒りの叫びが聞こえる。" +aggravate() +65 "You hear a high pitched humming noise" "どこからか、かん高いうなり声が聞こえてくる。" + +file: move.c +toplevel +66 "You can move again" "ようやく体が自由になった。" +one_move_rogue() +67 "You are being held" "怪物につかまえられて、逃げられない。" +68 "You are still stuck in the bear trap" "熊のわなが、なかなかはずれない。" +69 "" (英語では無意味) "を手に入れた。" +70 "Moved onto " "の上にいる。" +check_hunger() +71 "Hungry" "空腹" (4バイトまで、英語では6文字まで) +72 "Hungry" "空腹になってきた。" +73 "Weak" "飢餓" (4バイトまで、英語では6文字まで) +74 "Weak" "空腹のせいで力がなくなってきた。" +75 "Faint" "瀕死" (4バイトまで、英語では6文字まで) +76 "Faint" "空腹で、もう死にそうだ。" +77 "You faint" "空腹で、目がくらくらする。" +reg_move() +78 "You float gently to the ground" "ようやく地面に足がついた。" +79 "You feel yourself slowing down" "素早くなる薬の効き目がなくなった。" + +file: object.c +name_of() +80 "unknown " "???" (バグ対策?) +new_object_for_wizard() +81 "Pack full" "これ以上は物を持てない。" +82 "Type of object?" "どんなものですか?" +83 "Which kind of %s?" "%sの種類は?" +84 "weapon" "武器" + +file: pack.c +toplevel +85 "You can't, it appears to be cursed" "呪われているので、それはできない!" +pick_up() +86 "The scroll turns to dust as you pick it up" "拾いあげたとたん、巻き物はちりになってしまった。" +87 "Pack too full" "もうこれ以上、物は持てない。" +drop() +88 "There's already something there""そこには、すでに何かが置かれている。" +89 "You have nothing to drop" "落とす物を持っていない。" +90 "Drop what?" "落とす物は?" +91 "No such item." "それは持っていない。" +92 "Dropped " "を落とした。" +pack_letter() +93 "Nothing appropriate" "それは1つも持っていない。" +take_off() +94 "Was wearing " "を脱いだ。" +95 "Not wearing any" "よろいを着ていない。" +wear() +96 "You're already wearing some" "他のよろいを着ている。" +97 "Wear what?" "どのよろいを?" +98 "No such item." "それは持っていない。" +99 "You can't wear that" "それはよろいではない。" +100 "Wearing " "を身につけた。" +wield() +101 "Wield what?" "どの武器を?" +102 "No such item." "それは持っていない。" +103 "You can't wield %s" "%sを武器にすることはできない。" +104 "armor" "よろい" +105 "rings" "指輪" +106 "In use" "その武器はもう使っている。" +107 "Wielding " "に持ちかえた。" +call_it() +108 "Call what?" "呼び名をつけるものは?" +109 "No such item." "それは持っていない。" +110 "Surely you already know what that's called" "それには呼び名をつけることができない。" +111 "Call it:" "呼び名は?" +kick_into_pack() +112 "Nothing here" "ここには、何もない。" +113 "You're floating in the air!" "拾うことができない!" +114 "" (英語では無意味) "を手に入れた。 " +file: play.c +toplevel +115 "Unknown command" "コマンドが違います。" + +help() +116 "? print help > go down a staircase" +117 "/ identify object < go up a staircase" +118 "h, j, k, l left, down, up, left . rest for a turn" +119 "y, u, b, n move diagonally , pick something up" +120 " run that way s search trap/secret door" +121 " run till adjacent i inventory" +122 "f fight till death or near death I inventory single item" +123 "F fight till either of you dies q quaff potion" +124 "t throw something r read scroll" +125 "m move onto without picking up e eat food" +126 "z zap a wand in a direction w wield a weapon" +127 "^ identify trap type W wear armor" +128 "P repeat last message T take armor off" +129 "R redraw screen P put on ring" +130 "D save screen to file R remove ring" +131 " cancel command d drop object" +132 "a repeat last command c call object" +133 "D recall what's been discovered ) print current weapon" +134 "S save game ] print current armor" +135 "Q quit = print current rings" +136 "v print version information @ print current stats" +137 "! shell escape o examine/set options" + +identify() +138 "You" +139 "floor of a room" +140 "wall of a room" +141 "wall of a room" +142 "door" +143 "passage" +144 "staircase" +145 "secret trap" +146 "a pile or pot of gold" +147 "food ration" +148 "an armor" +149 "a weapon" +150 "a scroll" +151 "a potion" +152 "a wand or a staff" +153 "a ring" +154 "the Amulet of Yendor" + +155 "Which character?" "どんな文字ですか?" + +dosshell() +MS-DOS, HUMAN +156 "[ Type exit to return to rogue. ]""[ \"exit\" コマンドでローグに戻ります ]" + "[ Type \"exit\" to return to rogue. ]" \ は使えない +UNIX +157 "[ Exit shell to return to rogue. ]""[ シェルを終了するとローグに戻ります ]" + +file: ring.c +toplevel +158 "Left or right hand?" "左手(L)、それとも右手(R)?" +159 "There's no ring on that hand" "そちらの手には指輪をしていない。" +put_on_ring() +160 "Wearing two rings already" "すでに両手に指輪をしている。" +161 "Put on what?" "どの指輪を?" +162 "No such item." "それは持っていない。" +163 "That's not a ring" "それは指輪ではない。" +164 "That ring is already being worn""その指輪はもう手にはめている。" +165 "There's already a ring on that hand""そちらの手にはもう指輪をしている。" +do_put_on() +166 "Removed " "をはずした。" +inv_rings() +167 "Not wearing any rings" "指輪ははめていない。" + +file: score.c +killed_by() + " この長さが最大 " +168 "Died of" "寒さにより" to 172 (英語では ... of/from) +169 "Died of" "飢えにより" to 173 +170 "Killed by a" "毒矢により" to 174 +171 "Quit" "逃亡により" to 175 +172 "hypothermia" "死す" +173 "starvation" "死す" +174 "dart" "死す" +175 "" "行方不明" + +176 "killed by a" "と戦いて死す" + +177 " REST " "安らかに" +178 " IN " "眠れ" +179 "PEACE " "" (日本語では未使用) +180 "%ld Au" (英語) "$" (日本語) +181 " with %ld gold" "。 所持金は$" + +182 " Congratulations, you have made it to the light of day! " +183 "You have joined the elite ranks of those who have escaped the " +184 "Dungeons of Doom alive. You journey home and sell all your " +185 "loot at a great profit and are admitted to the Fighters' Guild." + +put_scores() +186 "Cannot read/create score file" "得点ファイルがオープンできません。" +187 "Top Ten Scores" "最 高 得 点" + TOPSCO でないときは "Top Ten Rogueists" "最 高 得 点 者" +188 "Rank Score Name" "順位 得点 名前" +insert_score() +189 "with Amulet" "魔除けを手に、" +190 " on level %d " "地下" +191 "" (英語では無意味)"階にて" +192 "died of hypothermia" "寒さにより死す" +193 "died of starvation" "飢えにより死す" +194 "killed by a dart" "毒矢により死す" +195 "quit" "逃亡す" +196 "a total winner" "運命の洞窟より生きて帰りたる勇者" +197 "killed by " "と戦いて死す" +sell_pack() +198 "Value Item" " 価格 持ちもの" +sf_error() +199 "Sorry, score file is out of order" "得点ファイルが正しくありません。" +file: spechit.c +toplevel +200 "flame" "ほのお" +rust() +201 "The rust vanishes instantly" "水ごけの湿り気はすぐに消え去った。" +202 "Your armor weakens" "よろいはさびてしまった!" +freeze() +203 "You are frozen" "体が凍りついて、動けない!" +steal_gold() +204 "Your purse feels lighter" "金塊を盗まれた!" +steal_item() +205 "She stole " "を盗まれた!" +check_imitator() +206 "Wait, that's a %s!" "おっと、こいつは%sだ!" +sting() +207 "The %s's bite has weakened you" "%sに噛まれて、毒にやられた!" +drain_life() +208 "You feel weaker" "強さが減ってしまった!" +m_confuse() +209 "The gaze of the %s has confused you" "%sににらまれ、頭が混乱してしまった!" + +file: throw.c +throw() +210 "Throw what?" "投げる武器は?" +211 "No such item." "それは持っていない。" +throw_at_monster() +212 "The %s" "%s" +213 "misses. " "はそれた。 " +214 "hit. " "は命中した。 " +flop_weapon() +215 "The %svanishes as it hits the ground" "%sは地面に落ちると、どこかに消えてしまった。" + +file: trap.c +わなの情報はここに集めました。 +toplevel +216 "trap door" +217 "You fell down a trap" +218 "bear trap" +219 "You are caught in a bear trap" +220 "teleport trap" +221 "Teleport" +222 "poison dart trap" +223 "A small dart just hit you in the shoulder" +224 "sleeping gas trap" +225 "A strange white mist envelopes you and you fall asleep" +226 "rust trap" +227 "A gush of water hits you on the head" + +trap_player() +228 "The trap failed" "危うく、わなにはまるところだった。" +id_trap() +229 "No trap there" "その方向には、わながない。" + +file: use.c +toplevel +230 "You have a strange feeling for a moment, then it passes" "不思議な気分におそわれたが、すぐに消えていった。" +quaff() +231 "Quaff what?" "飲む水薬は?" +232 "No such item." "それは持っていない。" +233 "You can't drink that" "それは水薬ではない。" +234 "You feel stronger now, what bulging muscles!" "何だか、力がわいてくるぞ!" +235 "This tastes great, you feel warm all over" "これはうまい! からだがポカポカしてきた。" +236 "You begin to feel better" "気分がよくなった!" +237 "You begin to feel much better" "とても気分がよくなった!" +238 "You feel very sick now" "この水薬は毒だった!" +239 "Oh wow, everything seems so cosmic!" "ふにゃ? 何もかもが虹色にみえるなあ?" +240 "What a trippy feeling" "何だか酔っぱらいみたいな気分だ!" +241 "Wait, what's going on here. Huh? What? Who?" "あれ? ここはどこ? 私はだれ?" +242 "You start to float in the air" "体が宙に浮いてしまった!" +243 "You feel yourself moving much faster" "体が素早く動くようになった!" +244 "Hmm, this potion tastes like %sjuice" "う~む、%sジュースのような味がする。" +read_scroll() +245 "Read what?" "読む巻き物は?" +246 "No such item." "それは持っていない。" +247 "You can't read that" "それは巻き物ではない。" +248 "You hear a maniacal laughter in the distance" "遠くから、狂ったような笑い声が聞こえてくる。" +249 "Your %sglow%s %sfor a moment" "手に持った%sが、ほんの少し%s輝きに包まれた。" +250 "Your hands tingle""何だか、手がむずむずする。" (武器を持っていない時) +251 "Your armor glows %sfor a moment" "着ているよろいが、ほんの少し%s輝きに包まれた。" +252 "Your skin crawls" "何だか、体がむずむずする。" (よろいを着ていない時) +253 "This is a scroll of identify" "これは持ちものを調べる巻き物だった。" +254 "You fall asleep" "知らないうちに眠り込んでしまった。" +255 "Your armor is covered by a shimmering gold shield" "着ているよろいは、輝く金色の光に守られた。" +256 "Your acne seems to have disappeared" "何だか、顔がむずむずする。" (よろいを着ていない時) +257 "You feel as though someone is watching over you" "ふっと、誰かに見つめられているような気がした。" +258 "You feel in touch with the universal oneness" "ふっと、女神の手に包まれているような気がした。" (幻覚を起こしている時) +259 "This scroll seems to have a map on it" "おや、この巻き物には地図が書いてある!" +idntfy() +260 "What would you like to identify?" "調べる持ちものは?" +261 "No such item, try again" "それは持っていない。" +eat() +262 "Eat what?" "食べる物は?" +263 "No such item." "それは持っていない。" +264 "You can't eat that" "それは食べられない。" +265 "Yum, that tasted good" (英語版にはこれはない) "う~む、まったりとしていて、それでいてこくがある。" +266 "Yum, that tasted good" "ああ、おいしかった。" +267 "My, that was a yummy %s" "おや、なんて甘い%sだ。" +268 "Yuk, that food tasted awful" "げげっ、まずい!" +hold_monster() +269 "You feel a strange sense of loss" "急に、体から力が抜けていくような気がした。" +270 "The monster freezes" "怪物は動けなくなった!" +271 "The monsters around you freeze" "怪物どもは動けなくなった!" +unhallucinate() +272 "Everything looks SO boring now" "やっと、あたりの景色が元どおりになった。" +unblind() +273 "The veil of darkness lifts" "暗闇のとばりが上がってゆく。" +go_blind() +274 "A cloak of darkness falls around you" "深い暗闇のとばりがあたりをおおってゆく。" +get_ehch_color() +275 "blue " "青い" (着ているよろい、ほんの少し...輝きに包まれた。) +uncunfuse() +276 "You feel less trippy now" "ふたたび、景色が虹色に見えてきた。" +277 "You feel less confused now" "ようやく、頭がはっきりしてきた。" + +file: zap.c +zapp() +278 "Zap with what?" "振りかざすつえは?" +279 "No such item." "それは持っていない。" +280 "You can't zap with that" "それを振りかざすことはできない。" +281 "Nothing happens" "しかし、何も起こらなかった。" (回数オーバー) +zap_monster() +282 "Nothing happens" "しかし、何も起こらなかった。" (役に立たない杖) + +monsters +307 "aquator" +308 "bat" +309 "centaur" +310 "dragon" +311 "emu" +312 "venus flytrap" +313 "griffin" +314 "hobgoblin" +315 "ice monster" +316 "jabberwock" +317 "kestrel" +318 "leprechaun" +319 "medusa" +320 "nymph" +321 "orc" +322 "phantom" +323 "quagga" +324 "rattlesnake" +325 "snake" +326 "troll" +327 "black unicorn" +328 "vampire" +329 "wraith" +330 "xeroc" +331 "yeti" +332 "zombie" + +fruit +333 "slime-mold " "こけもも" + +color of potion +334 "blue " +335 "red " +336 "green " +337 "grey " +338 "brown " +339 "clear " +340 "pink " +341 "white " +342 "purple " +343 "black " +344 "yellow " +345 "plaid " +346 "burgundy " +347 "beige " + +kind of potion +348 "of increase strength " +349 "of restore strength " +350 "of healing " +351 "of extra healing " +352 "of poison " +353 "of raise level " +354 "of blindness " +355 "of hallucination " +356 "of detect monster " +357 "of detect things " +358 "of confusion " +359 "of levitation " +360 "of haste self " +361 "of see invisible " + +kind of scroll +362 "of protect armor " +363 "of hold monster " +364 "of enchant weapon " +365 "of enchant armor " +366 "of identify " +367 "of teleportation " +368 "of sleep " +369 "of scare monster " +370 "of remove curse " +371 "of create monster " +372 "of aggravate monster " +373 "of magic mapping " + +kind of weapon +374 "short bow " +375 "darts " +376 "arrows " +377 "daggers " +378 "shurikens " +379 "mace " +380 "long sword " +381 "two handed sword " + +kind of armor +382 "leather armor " +383 "ring mail " +384 "scale mail " +385 "chain mail " +386 "banded mail " +387 "splint mail " +388 "plate mail " + +kind of wand +389 "of teleport away " +390 "of slow monster " +391 "of confuse monster " +392 "of invisibility " +393 "of polymorph " +394 "of haste monster " +395 "of sleep " +396 "of magic missile " +397 "of cancellation " +398 "of do nothing " + +kind of ring +399 "of stealth " +400 "of teleportation " +401 "of regeneration " +402 "of slow digestion " +403 "of add strength " +404 "of sustain strength " +405 "of dexterity " +406 "of adornment " +407 "of see invisible " +408 "of maintain armor " +409 "of searching " + +material of wand +410 "steel " +411 "bronze " +412 "gold " +413 "silver " +414 "copper " +415 "nickel " +416 "cobalt " +417 "tin " +418 "iron " +419 "magnesium " +420 "chrome " +421 "carbon " +422 "platinum " +423 "silicon " +424 "titanium " +425 "teak " +426 "oak " +427 "cherry " +428 "birch " +429 "pine " +430 "cedar " +431 "redwood " +432 "balsa " +433 "ivory " +434 "walnut " +435 "maple " +436 "mahogany " +437 "elm " +438 "palm " +439 "wooden " + +material of ring +440 "diamond " +441 "stibotantalite " +442 "lapis lazuli " +443 "ruby " +444 "emerald " +445 "sapphire " +446 "amethyst " +447 "quartz " +448 "tiger eye " +449 "opal " +450 "agate " +451 "turquoise " +452 "pearl " +453 "garnet " + +syllable of scroll +454 "blech " +455 "foo " +456 "barf " +457 "rech " +458 "bar " +459 "blech " +460 "quo " +461 "bloto " +462 "woh " +463 "caca " +464 "blorp " +465 "erp " +466 "festr " +467 "rot " +468 "slie " +469 "snorf " +470 "iky " +471 "yuky " +472 "ooze " +473 "ah " +474 "bahl " +475 "zep " +476 "druhl " +477 "flem " +478 "behil " +479 "arek " +480 "mep " +481 "zihr " +482 "grit " +483 "kona " +484 "kini " +485 "ichi " +486 "niah " +487 "ogr " +488 "ooh " +489 "ighr " +490 "coph " +491 "swerr " +492 "mihln " +493 "poxi " + + +rogue_sで分離されていなかったメッセージ + +file: play.c +toplevel +494 "--Press space to continue--" "=スペースを押してください=" + +file: score.c +quit() +495 "Really quit?" "ゲームを終了してよいのですか?" +killed_by() +496 "." + +file: zap.c +wizardize() +497 "Not wizard anymore" "もはや、魔法使いではない。" +498 "Wizard's password:" "魔法使いの合言葉は?" +499 "Welcome, mighty wizard!" "ようこそ、魔法使いよ!" +500 "Sorry" "そんな合言葉、知らないね。" + +file: save.c +save_game() +501 "File name?" "セーブするファイル名は?" +502 "Game not saved" "ゲームのセーブを中止しました。" +save_into_file() +503 "Problem accessing the save file" "セーブファイルにアクセスできません。" +restore() +504 "Cannot open file" "ファイルがオープンできませんでした。" +505 "File has link" "ファイルはリンクされています。" +506 "You're not the original player" "セーブファイルの持ち主が違います。" +507 "Sorry, saved game is not in the same file" "これは元のセーブファイルではありません。" +508 "Extra characters in file" "ファイル中によけいな文字があります。" +509 "Sorry, file has been touched" "ファイルが変更されています。" +510 "Cannot delete file" "ファイルを消すことができません。" +r_read() +511 "Read() failed, don't know why" "ファイルが読めません。" +r_write() +512 "Write() failed, don't know why" "ファイルに書けません。" + +file: object.c +alloc_object() +513 "Cannot allocate object, saving game" "メモリーが足りません。 ゲームをセーブします。" + +file: init.c +toplevel +514 "Ask whether quit or not on quit signal" "終了するかどうか確認をとる" +515 "Show position only at end of run" "移動中の表示を行わない" +516 "Follow turnings in passageways" "通路の角で止まらずに進む" +517 "Print out tombstone and score when killed" "ゲーム終了時に墓標を表示する" +518 "Show characters in map with color" "キャラクターをカラーで表示する" +519 "Save filename" "セーブファイル名" +520 "Your nickname" "ニックネーム" +521 "Game directory name" "ゲームディレクトリー名" +522 "Color mapping for characters" "キャラクターの表示色マッピング" + +file: invent.c +znum() +523 "0" +524 "1" +525 "2" +526 "3" +527 "4" +528 "5" +529 "6" +530 "7" +531 "8" +532 "9" +533 "+" +534 "-" +make_scroll_titles() +535 "'" "「" +536 "' " "」" +get_desc() +537 "" +538 " " +539 "[" +540 "] " +541 ", " + +file: machdep.c +md_gln() +542 "Fighter" "戦士" + +file: init.c +do_args() +543 "Cannot resume" "再開できませんでした。" diff --git a/autoload/rogue/message.lua b/autoload/rogue/message.lua new file mode 100644 index 0000000..b8ca2a1 --- /dev/null +++ b/autoload/rogue/message.lua @@ -0,0 +1,211 @@ +local g = Rogue -- alias + +g.msg_cleared = true +g.hunger_str = "" + +local msg_line = "" + +local function save_screen() + local file, err = io.open(g.game_dir .. "rogue_vim.screen", "w") + if not file then + g.sound_bell() + return + end + for i = 0, g.DROWS-1 do + file:write(g.iconv_to_utf8(g.screen[i]) .. "\n") + end + file:close() +end + +function g.rgetchar() + local n + if vim then + n = vim.eval("getchar()") + else + os.execute("stty -echo cbreak") + n = string.byte(io.stdin:read(1)) + os.execute("stty echo -cbreak") + end + local c = '' + if type(n) == 'string' then + if vim then + if n == vim.eval('"\\"') then + c = 'BS' + end + end + elseif type(n) == 'number' then + if n == 0x1B then + c = 'ESC' + elseif 0x01 <= n and n <= 0x1F then + -- CTRL + c = 'CTRL_' .. string.char(n + 0x40) + if c == 'CTRL_M' then + c = 'ENTER' + end + else + if vim then + c = vim.eval("nr2char("..tostring(n)..")") + elseif n <= 0x7E then + c = string.char(n) + end + end + if c == 'CTRL_D' then + save_screen() + c = g.rgetchar() + end + end + return c +end + +function g.message(msg, intrpt) + if not g.save_is_interactive then + return + end + if intrpt then + g.interrupted = true + end + + if not g.msg_cleared then + g.mvaddstr(g.MIN_ROW-1, 0, msg_line .. g.mesg[11]) + g.refresh() + g.wait_for_ack() + g.check_message() + end + msg_line = msg + g.mvaddstr(g.MIN_ROW-1, 0, msg) + g.refresh() + g.msg_cleared = false +end + +function g.remessage() + if msg_line ~= "" then + g.message(msg_line, false) + end +end + +function g.check_message() + if g.msg_cleared then + return + end + g.mvaddstr(g.MIN_ROW-1, 0, ' ') + g.refresh() + g.msg_cleared = true +end + +function g.get_direction() + g.message(g.mesg[55]) + while true do + local dir = g.rgetchar() + if g.is_direction(dir) then + g.check_message() + return dir + end + g.sound_bell() + end +end + +function g.get_input_line(prompt, insert, if_cancelled, add_blank, do_echo) + local buf = '' + local input_list = {} + + for i = 1, #insert do + table.insert(input_list, string.char(insert:byte(i))) + end + + while true do + buf = table.concat(input_list) + if do_echo then + g.mvaddstr(g.MIN_ROW-1, 0, prompt .. ' ' .. buf) + else + g.mvaddstr(g.MIN_ROW-1, 0, prompt) + end + g.refresh() + local ch = g.rgetchar() + if ch == 'ENTER' then + break + elseif ch == g.CANCEL then + buf = '' + break + elseif ch == 'BS' or ch == 'CTRL_H' then + if #input_list > 0 then + table.remove(input_list) + end + elseif ch == 'CTRL_W' then + input_list = {} + elseif ch == '' or ch:find('CTRL_') then + else + table.insert(input_list, ch) + end + end + g.mvaddstr(g.MIN_ROW-1, 0, '') + buf = buf:gsub("^%s*(.-)%s*$", "%1") + + if buf == '' then + g.message(if_cancelled) + elseif add_blank then + buf = buf .. ' ' + end + + return buf +end + +--[[ +Level: 99 Gold: 999999 Hp: 999(999) Str: 99(99) Arm: 99 Exp: 21/9999999 Hungry +階: 99 金塊: 999999 体力: 999(999) 強さ: 99(99) 守備: 99 経験: 21/9999999 空腹 +0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 +--]] + +function g.print_stats(update_flag) + local row = g.DROWS - 1 + + if g.rogue.gold > g.MAX_GOLD then + g.rogue.gold = g.MAX_GOLD + end + + if g.rogue.hp_max > g.MAX_HP then + g.rogue.hp_current = g.rogue.hp_current - (g.rogue.hp_max - g.MAX_HP) + g.rogue.hp_max = g.MAX_HP + end + + if g.rogue.str_max > g.MAX_STRENGTH then + g.rogue.str_current = g.rogue.str_current - (g.rogue.str_max - g.MAX_STRENGTH) + g.rogue.str_max = g.MAX_STRENGTH + end + + if g.rogue.armor and (g.rogue.armor.d_enchant > g.MAX_ARMOR) then + g.rogue.armor.d_enchant = g.MAX_ARMOR + end + + local line = '' + local tmp + tmp = string.format("%d", g.cur_level) + line = line .. g.mesg[56] .. tmp .. string.rep(' ', 3 - #tmp) + tmp = string.format("%d", g.rogue.gold) + line = line .. g.mesg[57] .. tmp .. string.rep(' ', 7 - #tmp) + tmp = string.format("%d(%d)", g.rogue.hp_current, g.rogue.hp_max) + line = line .. g.mesg[58] .. tmp .. string.rep(' ', 9 - #tmp) + tmp = string.format("%d(%d)", g.rogue.str_current + g.add_strength, g.rogue.str_max) + line = line .. g.mesg[59] .. tmp .. string.rep(' ', 7 - #tmp) + tmp = string.format("%d", g.get_armor_class(g.rogue.armor)) + line = line .. g.mesg[60] .. tmp .. string.rep(' ', 3 - #tmp) + tmp = string.format("%d/%d", g.rogue.exp, g.rogue.exp_points) + line = line .. g.mesg[61] .. tmp .. string.rep(' ', 11 - #tmp) + line = line .. g.hunger_str + + g.mvaddstr(row, 0, line) + if update_flag then + g.update_flag = true + end + g.refresh() +end + +function g.clear_stats() + g.mvaddstr(g.DROWS-1, 0, '') + g.refresh() +end + +function g.sound_bell() + if vim then + vim.beep() + end +end diff --git a/autoload/rogue/monster.lua b/autoload/rogue/monster.lua new file mode 100644 index 0000000..495930b --- /dev/null +++ b/autoload/rogue/monster.lua @@ -0,0 +1,811 @@ +local g = Rogue -- alias + +g.level_monsters = {} +g.mon_disappeared = false +g.m_names = {} +g.mon_tab = {} + +local Monster = {} +function Monster.new(m_damage, hp_to_kill, m_char, kill_exp, + first_level, last_level, m_hit_chance, stationary_damage, drop_percent, m_name) + local mon = g.ObjBase.new() + mon.m_flags = {} -- monster flags + mon.m_damage = m_damage -- damage it does + mon.hp_to_kill = hp_to_kill -- hit points to kill + mon.m_char = m_char -- 'A' is for aquatar + mon.kill_exp = kill_exp -- exp for killing it + mon.first_level = first_level -- level starts + mon.last_level = last_level -- level ends + mon.m_hit_chance = m_hit_chance -- chance of hitting you + mon.stationary_damage = stationary_damage -- 'F' damage, 1,2,3... + mon.drop_percent = drop_percent -- item carry/drop % + mon.trail_char = 0 -- room char when g.detect_monster + mon.slowed_toggle = false -- monster slowed toggle + mon.moves_confused = 0 -- how many moves is g.confused + mon.disguise = 0 -- imitator's charactor (?!%: + mon.nap_length = 0 -- sleep from wand of sleep + mon.m_name = m_name -- monster name + return mon +end + +function g.init_monster() + g.m_names = { [0] = + g.mesg[307], g.mesg[308], g.mesg[309], g.mesg[310], g.mesg[311], g.mesg[312], + g.mesg[313], g.mesg[314], g.mesg[315], g.mesg[316], g.mesg[317], g.mesg[318], + g.mesg[319], g.mesg[320], g.mesg[321], g.mesg[322], g.mesg[323], g.mesg[324], + g.mesg[325], g.mesg[326], g.mesg[327], g.mesg[328], g.mesg[329], g.mesg[330], + g.mesg[331], g.mesg[332] + } + g.mon_tab[ 0] = Monster.new("0d0" , 25 , 'A' , 20 , 9 , 18 , 100 , 0 , 0 , g.m_names[ 0]) + g.mon_tab[ 1] = Monster.new("1d3" , 10 , 'B' , 2 , 1 , 8 , 60 , 0 , 0 , g.m_names[ 1]) + g.mon_tab[ 2] = Monster.new("3d3/2d5" , 32 , 'C' , 15 , 7 , 16 , 85 , 0 , 10 , g.m_names[ 2]) + g.mon_tab[ 3] = Monster.new("4d6/4d9" , 145 , 'D' , 5000 , 21 , 126 , 100 , 0 , 90 , g.m_names[ 3]) + g.mon_tab[ 4] = Monster.new("1d3" , 11 , 'E' , 2 , 1 , 7 , 65 , 0 , 0 , g.m_names[ 4]) + g.mon_tab[ 5] = Monster.new("5d5" , 73 , 'F' , 91 , 12 , 126 , 80 , 0 , 0 , g.m_names[ 5]) + g.mon_tab[ 6] = Monster.new("5d5/5d5" , 115 , 'G' , 2000 , 20 , 126 , 85 , 0 , 10 , g.m_names[ 6]) + g.mon_tab[ 7] = Monster.new("1d3/1d2" , 15 , 'H' , 3 , 1 , 10 , 67 , 0 , 0 , g.m_names[ 7]) + g.mon_tab[ 8] = Monster.new("0d0" , 15 , 'I' , 5 , 2 , 11 , 68 , 0 , 0 , g.m_names[ 8]) + g.mon_tab[ 9] = Monster.new("3d10/4d5" , 132 , 'J' , 3000 , 21 , 126 , 100 , 0 , 0 , g.m_names[ 9]) + g.mon_tab[10] = Monster.new("1d4" , 10 , 'K' , 2 , 1 , 6 , 60 , 0 , 0 , g.m_names[10]) + g.mon_tab[11] = Monster.new("0d0" , 25 , 'L' , 21 , 6 , 16 , 75 , 0 , 0 , g.m_names[11]) + g.mon_tab[12] = Monster.new("4d4/3d7" , 97 , 'M' , 250 , 18 , 126 , 85 , 0 , 25 , g.m_names[12]) + g.mon_tab[13] = Monster.new("0d0" , 25 , 'N' , 39 , 10 , 19 , 75 , 0 , 100 , g.m_names[13]) + g.mon_tab[14] = Monster.new("1d6" , 25 , 'O' , 5 , 4 , 13 , 70 , 0 , 10 , g.m_names[14]) + g.mon_tab[15] = Monster.new("5d4" , 76 , 'P' , 120 , 15 , 24 , 80 , 0 , 50 , g.m_names[15]) + g.mon_tab[16] = Monster.new("3d5" , 30 , 'Q' , 20 , 8 , 17 , 78 , 0 , 20 , g.m_names[16]) + g.mon_tab[17] = Monster.new("2d5" , 19 , 'R' , 10 , 3 , 12 , 70 , 0 , 0 , g.m_names[17]) + g.mon_tab[18] = Monster.new("1d3" , 8 , 'S' , 2 , 1 , 9 , 50 , 0 , 0 , g.m_names[18]) + g.mon_tab[19] = Monster.new("4d6/1d4" , 75 , 'T' , 125 , 13 , 22 , 75 , 0 , 33 , g.m_names[19]) + g.mon_tab[20] = Monster.new("4d10" , 90 , 'U' , 200 , 17 , 26 , 85 , 0 , 33 , g.m_names[20]) + g.mon_tab[21] = Monster.new("1d14/1d4" , 55 , 'V' , 350 , 19 , 126 , 85 , 0 , 18 , g.m_names[21]) + g.mon_tab[22] = Monster.new("2d8" , 45 , 'W' , 55 , 14 , 23 , 75 , 0 , 0 , g.m_names[22]) + g.mon_tab[23] = Monster.new("4d6" , 42 , 'X' , 110 , 16 , 25 , 75 , 0 , 0 , g.m_names[23]) + g.mon_tab[24] = Monster.new("3d6" , 35 , 'Y' , 50 , 11 , 20 , 80 , 0 , 20 , g.m_names[24]) + g.mon_tab[25] = Monster.new("1d7" , 21 , 'Z' , 8 , 5 , 14 , 69 , 0 , 0 , g.m_names[25]) + + g.mon_tab[0].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + [g.RUSTS] = g.m_flags_desc[g.RUSTS], + } + g.mon_tab[1].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + [g.FLITS] = g.m_flags_desc[g.FLITS], + } + g.mon_tab[2].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + } + g.mon_tab[3].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.FLAMES] = g.m_flags_desc[g.FLAMES], + } + g.mon_tab[4].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + } + g.mon_tab[5].m_flags = { + [g.HOLDS] = g.m_flags_desc[g.HOLDS], + [g.STATIONARY] = g.m_flags_desc[g.STATIONARY], + } + g.mon_tab[6].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + [g.FLIES] = g.m_flags_desc[g.FLIES], + } + g.mon_tab[7].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + } + g.mon_tab[8].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.FREEZES] = g.m_flags_desc[g.FREEZES], + } + g.mon_tab[9].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + } + g.mon_tab[10].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + [g.FLIES] = g.m_flags_desc[g.FLIES], + } + g.mon_tab[11].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.STEALS_GOLD] = g.m_flags_desc[g.STEALS_GOLD], + } + g.mon_tab[12].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + [g.CONFUSES] = g.m_flags_desc[g.CONFUSES], + } + g.mon_tab[13].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.STEALS_ITEM] = g.m_flags_desc[g.STEALS_ITEM], + } + g.mon_tab[14].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.SEEKS_GOLD] = g.m_flags_desc[g.SEEKS_GOLD], + } + g.mon_tab[15].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.INVISIBLE] = g.m_flags_desc[g.INVISIBLE], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + [g.FLITS] = g.m_flags_desc[g.FLITS], + } + g.mon_tab[16].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + } + g.mon_tab[17].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + [g.STINGS] = g.m_flags_desc[g.STINGS], + } + g.mon_tab[18].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + } + g.mon_tab[19].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + } + g.mon_tab[20].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + } + g.mon_tab[21].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + [g.DRAINS_LIFE] = g.m_flags_desc[g.DRAINS_LIFE], + } + g.mon_tab[22].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + [g.DROPS_LEVEL] = g.m_flags_desc[g.DROPS_LEVEL], + } + g.mon_tab[23].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.IMITATES] = g.m_flags_desc[g.IMITATES], + } + g.mon_tab[24].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + } + g.mon_tab[25].m_flags = { + [g.ASLEEP] = g.m_flags_desc[g.ASLEEP], + [g.WAKENS] = g.m_flags_desc[g.WAKENS], + [g.WANDERS] = g.m_flags_desc[g.WANDERS], + } +end + +local function aim_monster(monster) + local rn = g.get_room_number(monster.row, monster.col) + local r = g.get_rand(0, 12) + + for i = 0, 3 do + local d = (r + i) % 4 + if g.rooms[rn].doors[d].oth_room ~= g.NO_ROOM then + monster.trow = g.rooms[rn].doors[d].door_row + monster.tcol = g.rooms[rn].doors[d].door_col + break + end + end +end + +local function put_m_at(row, col, monster) + monster.row = row + monster.col = col + g.dungeon[row][col][g.MONSTER] = g.dungeon_desc[g.MONSTER] + monster.trail_char = g.mvinch(row, col) + g.add_to_pack(monster, g.level_monsters, false) + aim_monster(monster) +end + +function g.put_mons() + local n = g.get_rand(4, 6) + for i = 1, n do + local monster = g.gr_monster(nil, 0) + if monster.m_flags[g.WANDERS] and g.coin_toss() then + g.wake_up(monster) + end + local row, col = g.gr_row_col({[g.FLOOR]=true, [g.TUNNEL]=true, [g.STAIRS]=true, [g.OBJECT]=true}) + put_m_at(row, col, monster) + end +end + +function g.gr_monster(monster, mn) + if not monster then + monster = {} + while true do + mn = g.get_rand(0, g.MONSTERS-1) + if (g.cur_level >= g.mon_tab[mn].first_level) and + (g.cur_level <= g.mon_tab[mn].last_level) then + break + end + end + end + g.copy_object(monster, g.mon_tab[mn]) + if monster.m_flags[g.IMITATES] then + monster.disguise = g.gr_obj_char() + end + if g.cur_level > (g.AMULET_LEVEL + 2) then + monster.m_flags[g.HASTED] = g.m_flags_desc[g.HASTED] + end + monster.trow = g.NO_ROOM + return monster +end + +local function mtry(monster, row, col) + if g.mon_can_go(monster, row, col) then + g.move_mon_to(monster, row, col) + return true + end + return false +end + +local function move_confused(monster) + if not monster.m_flags[g.ASLEEP] then + monster.moves_confused = monster.moves_confused - 1 + if monster.moves_confused <= 0 then + monster.m_flags[g.CONFUSED] = nil + end + if monster.m_flags[g.STATIONARY] then + return g.coin_toss() + elseif g.rand_percent(15) then + return true + end + local row = monster.row + local col = monster.col + + for i = 0, 8 do + row, col = g.rand_around(i, row, col) + if row == g.rogue.row and col == g.rogue.col then + return false + end + if mtry(monster, row, col) then + return true + end + end + end + return false +end + +function g.mv_mons() + if (g.haste_self % 2) ~= 0 then + return + end + local monster = g.level_monsters.next_object + while monster do + local goto_NM_flag = false + local next_monster = monster.next_object + if monster.m_flags[g.HASTED] then + g.mon_disappeared = false + g.mv_monster(monster, g.rogue.row, g.rogue.col) + if g.mon_disappeared then + -- goto NM + goto_NM_flag = true + end + elseif monster.m_flags[g.SLOWED] then + monster.slowed_toggle = not monster.slowed_toggle + if monster.slowed_toggle then + -- goto NM + goto_NM_flag = true + end + end + if not goto_NM_flag and monster.m_flags[g.CONFUSED] and move_confused(monster) then + -- goto NM + goto_NM_flag = true + end + if not goto_NM_flag then + local flew = false + if monster.m_flags[g.FLIES] and not monster.m_flags[g.NAPPING] + and not g.mon_can_go(monster, g.rogue.row, g.rogue.col) then + flew = true + g.mv_monster(monster, g.rogue.row, g.rogue.col) + end + if not (flew and g.mon_can_go(monster, g.rogue.row, g.rogue.col)) then + g.mv_monster(monster, g.rogue.row, g.rogue.col) + end + end + -- ::NM:: + monster = next_monster + end +end + +local function no_room_for_monster(rn) + for i = g.rooms[rn].top_row+1, g.rooms[rn].bottom_row-1 do + for j = g.rooms[rn].left_col+1, g.rooms[rn].right_col-1 do + if not g.dungeon[i][j][g.MONSTER] then + return false + end + end + end + return true +end + +function g.party_monsters(rn, n) + n = n + n + for i = 0, g.MONSTERS-1 do + g.mon_tab[i].first_level = g.mon_tab[i].first_level - (g.cur_level % 3) + end + for i = 0, n-1 do + if no_room_for_monster(rn) then + break + end + local row, col + local found = false + for j = 0, 249 do + row = g.get_rand(g.rooms[rn].top_row+1, g.rooms[rn].bottom_row-1) + col = g.get_rand(g.rooms[rn].left_col+1, g.rooms[rn].right_col-1) + if not g.dungeon[row][col][g.MONSTER] and + (g.dungeon[row][col][g.FLOOR] or + g.dungeon[row][col][g.TUNNEL])then + found = true + break + end + end + if found then + local monster = g.gr_monster(nil, 0) + if not monster.m_flags[g.IMITATES] then + monster.m_flags[g.WAKENS] = g.m_flags_desc[g.WAKENS] + end + put_m_at(row, col, monster) + end + end + for i = 0, g.MONSTERS-1 do + g.mon_tab[i].first_level = g.mon_tab[i].first_level + (g.cur_level % 3) + end +end + +function g.gmc_row_col(row, col) + local monster = g.object_at(g.level_monsters, row, col) + if monster then + return g.gmc(monster) + end + return '&' -- BUG if this ever happens +end + +function g.gmc(monster) + if (not (g.detect_monster or g.see_invisible or g.r_see_invisible) and + monster.m_flags[g.INVISIBLE]) or g.blind > 0 then + return monster.trail_char + end + if monster.m_flags[g.IMITATES] then + return monster.disguise + end + return monster.m_char +end + +local function flit(monster) + if not g.rand_percent(g.FLIT_PERCENT) then + return false + end + if g.rand_percent(10) then + return false + end + local row = monster.row + local col = monster.col + + for i = 0, 8 do + row, col = g.rand_around(i, row, col) + if row == g.rogue.row and col == g.rogue.col then + -- continue + else + if mtry(monster, row, col) then + return true + end + end + end + return true +end + +function g.mv_monster(monster, row, col) + if monster.m_flags[g.ASLEEP] then + if monster.m_flags[g.NAPPING] then + monster.nap_length = monster.nap_length - 1 + if monster.nap_length <= 0 then + monster.m_flags[g.NAPPING] = nil + monster.m_flags[g.ASLEEP] = nil + end + return + end + if monster.m_flags[g.WAKENS] and + g.rogue_is_around(monster.row, monster.col) and + g.rand_percent(((g.stealthy > 0) and + g.int_div(g.WAKE_PERCENT, (g.STEALTH_FACTOR + g.stealthy)) or + g.WAKE_PERCENT)) then + g.wake_up(monster) + end + return + elseif monster.m_flags[g.ALREADY_MOVED] then + monster.m_flags[g.ALREADY_MOVED] = nil + return + end + if monster.m_flags[g.FLITS] and flit(monster) then + return + end + if monster.m_flags[g.STATIONARY] and + not g.mon_can_go(monster, g.rogue.row, g.rogue.col) then + return + end + if monster.m_flags[g.FREEZING_ROGUE] then + return + end + if monster.m_flags[g.CONFUSES] and g.m_confuse(monster) then + return + end + if g.mon_can_go(monster, g.rogue.row, g.rogue.col) then + g.mon_hit(monster, nil, false) + return + end + if monster.m_flags[g.FLAMES] and g.flame_broil(monster) then + return + end + if monster.m_flags[g.SEEKS_GOLD] and g.seek_gold(monster) then + return + end + if (monster.trow == monster.row) and (monster.tcol == monster.col) then + monster.trow = g.NO_ROOM + elseif monster.trow ~= g.NO_ROOM then + row = monster.trow + col = monster.tcol + end + if monster.row > row then + row = monster.row - 1 + elseif monster.row < row then + row = monster.row + 1 + end + if g.dungeon[row][monster.col][g.DOOR] and + mtry(monster, row, monster.col) then + return + end + if monster.col > col then + col = monster.col - 1 + elseif monster.col < col then + col = monster.col + 1 + end + if g.dungeon[monster.row][col][g.DOOR] and + mtry(monster, monster.row, col) then + return + end + if mtry(monster, row, col) then + return + end + + local tried = {} + for i = 0, 5 do + local n + repeat + n = g.get_rand(0, 5) + until not tried[n] + if n == 0 then + if mtry(monster, row, monster.col - 1) then + break + end + elseif n == 1 then + if mtry(monster, row, monster.col) then + break + end + elseif n == 2 then + if mtry(monster, row, monster.col + 1) then + break + end + elseif n == 3 then + if mtry(monster, monster.row - 1, col) then + break + end + elseif n == 4 then + if mtry(monster, monster.row, col) then + break + end + elseif n == 5 then + if mtry(monster, monster.row + 1, col) then + break + end + end + tried[n] = true + end + + if monster.row == monster.o_row and + monster.col == monster.o_col then + monster.o = monster.o + 1 + if monster.o > 4 then + if monster.trow == g.NO_ROOM and + not g.mon_sees(monster, g.rogue.row, g.rogue.col) then + monster.trow = g.get_rand(1, (g.DROWS - 2)) + monster.tcol = g.get_rand(0, (g.DCOLS - 1)) + else + monster.trow = g.NO_ROOM + monster.o = 0 + end + end + else + monster.o_row = monster.row + monster.o_col = monster.col + monster.o = 0 + end +end + +function g.move_mon_to(monster, row, col) + local mrow = monster.row + local mcol = monster.col + + g.dungeon[mrow][mcol][g.MONSTER] = nil + g.dungeon[row][col][g.MONSTER] = g.dungeon_desc[g.MONSTER] + + local c = g.mvinch(mrow, mcol) + if c:find('^[A-Z]$') then + if not g.detect_monster then + g.mvaddch(mrow, mcol, monster.trail_char) + else + if g.rogue_can_see(mrow, mcol) then + g.mvaddch(mrow, mcol, monster.trail_char) + else + if monster.trail_char == '.' then + monster.trail_char = ' ' + end + g.mvaddch(mrow, mcol, monster.trail_char) + end + end + end + monster.trail_char = g.mvinch(row, col) + if g.blind == 0 and (g.detect_monster or g.rogue_can_see(row, col)) then + if not monster.m_flags[g.INVISIBLE] or + (g.detect_monster or g.see_invisible or g.r_see_invisible) then + g.mvaddch(row, col, g.gmc(monster)) + end + end + if g.dungeon[row][col][g.DOOR] and + g.get_room_number(row, col) ~= g.cur_room and + g.dungeon[mrow][mcol][g.FLOOR] and g.blind == 0 then + g.mvaddch(mrow, mcol, ' ') + end + if g.dungeon[row][col][g.DOOR] then + g.dr_course(monster, g.dungeon[mrow][mcol][g.TUNNEL] and true or false, + row, col) + else + monster.row = row + monster.col = col + end +end + +function g.mon_can_go(monster, row, col) + local dr = monster.row - row + local dc = monster.col - col + if dr >= 2 or dr <= -2 or dc >= 2 or dc <= -2 then + return false + end + if g.table_is_empty(g.dungeon[monster.row][col]) or + g.table_is_empty(g.dungeon[row][monster.col]) or + not g.is_passable(row, col) or + g.dungeon[row][col][g.MONSTER] then + return false + end + if monster.row ~= row and monster.col ~= col and + (g.dungeon[row][col][g.DOOR] or + g.dungeon[monster.row][monster.col][g.DOOR]) then + return false + end + if not (monster.m_flags[g.FLITS] or + monster.m_flags[g.CONFUSED] or + monster.m_flags[g.CAN_FLIT]) and + monster.trow == g.NO_ROOM then + if (monster.row < g.rogue.row and row < monster.row) or + (monster.row > g.rogue.row and row > monster.row) or + (monster.col < g.rogue.col and col < monster.col) or + (monster.col > g.rogue.col and col > monster.col) then + return false + end + end + if g.dungeon[row][col][g.OBJECT] then + local obj = g.object_at(g.level_objects, row, col) + if obj.what_is == g.SCROL and obj.which_kind == g.SCARE_MONSTER then + return false + end + end + return true +end + +function g.wake_up(monster) + if not monster.m_flags[g.NAPPING] then + monster.m_flags[g.ASLEEP] = nil + monster.m_flags[g.IMITATES] = nil + monster.m_flags[g.WAKENS] = nil + end +end + +function g.wake_room(rn, entering, row, col) + local wake_percent = (rn == g.party_room) and g.PARTY_WAKE_PERCENT or g.WAKE_PERCENT + if g.stealthy > 0 then + wake_percent = g.int_div(wake_percent, (g.STEALTH_FACTOR + g.stealthy)) + end + + local monster = g.level_monsters.next_object + + while monster do + local in_room = (rn == g.get_room_number(monster.row, monster.col)) + if in_room then + if entering then + monster.trow = g.NO_ROOM + else + monster.trow = row + monster.tcol = col + end + end + if monster.m_flags[g.WAKENS] and + (rn == g.get_room_number(monster.row, monster.col)) then + if g.rand_percent(wake_percent) then + g.wake_up(monster) + end + end + monster = monster.next_object + end +end + +function g.mon_name(monster) + if g.blind > 0 or + (monster.m_flags[g.INVISIBLE] and + not (g.detect_monster or g.see_invisible or g.r_see_invisible)) then + return g.mesg[63] + end + if g.halluc > 0 then + return g.m_names[g.get_rand(0, 25)] + end + return monster.m_name +end + +function g.rogue_is_around(row, col) + local rdif = row - g.rogue.row + local cdif = col - g.rogue.col + + return ((rdif >= -1) and (rdif <= 1) and (cdif >= -1) and (cdif <= 1)) +end + +function g.wanderer() + local monster + local found = false + for i = 0, 14 do + monster = g.gr_monster(nil, 0) + if not (monster.m_flags[g.WAKENS] or monster.m_flags[g.WANDERS]) then + g.free_object(monster) + else + found = true + break + end + end + if found then + found = false + g.wake_up(monster) + for i = 0, 24 do + local row, col = g.gr_row_col({[g.FLOOR]=true, [g.TUNNEL]=true, [g.STAIRS]=true, [g.OBJECT]=true}) + if not g.rogue_can_see(row, col) then + put_m_at(row, col, monster) + found = true + break + end + end + if not found then + g.free_object(monster) + end + end +end + +function g.show_monsters() + g.detect_monster = true + + if g.blind > 0 then + return + end + local monster = g.level_monsters.next_object + while monster do + g.mvaddch(monster.row, monster.col, monster.m_char) + if monster.m_flags[g.IMITATES] then + monster.m_flags[g.IMITATES] = nil + monster.m_flags[g.WAKENS] = g.m_flags_desc[g.WAKENS] + end + monster = monster.next_object + end +end + +function g.create_monster() + local row, col + local found = false + local r = g.rogue.row + local c = g.rogue.col + + for i = 0, 8 do + r, c = g.rand_around(i, r, c) + row = r + col = c + if (row == g.rogue.row and col == g.rogue.col) or + (row < g.MIN_ROW) or (row > (g.DROWS-2)) or + (col < 0) or (col > (g.DCOLS-1)) then + -- continue + else + if not g.dungeon[row][col][g.MONSTER] and + (g.dungeon[row][col][g.FLOOR] or g.dungeon[row][col][g.TUNNEL] or + g.dungeon[row][col][g.STAIRS] or g.dungeon[row][col][g.DOOR]) then + found = true + break + end + end + end + if found then + local monster = g.gr_monster(nil, 0) + put_m_at(row, col, monster) + g.mvaddch(row, col, g.gmc(monster)) + if monster.m_flags[g.WANDERS] or monster.m_flags[g.WAKENS] then + g.wake_up(monster) + end + else + g.message(g.mesg[64]) + end +end + +function g.rogue_can_see(row, col) + return (g.blind == 0 and + ((g.get_room_number(row, col) == g.cur_room and + g.rooms[g.cur_room].is_room ~= g.R_MAZE) or + g.rogue_is_around(row, col))) +end + +function g.gr_obj_char() + local rs = {'%', '!', '?', ']', '=', '/', ')', ':', '*'} + local r = g.get_rand(1, 9) + return rs[r] +end + +function g.aggravate() + g.message(g.mesg[65]) + local monster = g.level_monsters.next_object + + while monster do + g.wake_up(monster) + monster.m_flags[g.IMITATES] = nil + if g.rogue_can_see(monster.row, monster.col) then + g.mvaddch(monster.row, monster.col, monster.m_char) + end + monster = monster.next_object + end +end + +function g.mon_sees(monster, row, col) + local rn = g.get_room_number(row, col) + if rn ~= g.NO_ROOM and + rn == g.get_room_number(monster.row, monster.col) and + g.rooms[rn].is_room ~= g.R_MAZE then + return true + end + local rdif = row - monster.row + local cdif = col - monster.col + + return ((rdif >= -1) and (rdif <= 1) and (cdif >= -1) and (cdif <= 1)) +end + +function g.mv_aquatars() + local monster = g.level_monsters.next_object + + while monster do + if monster.m_char == 'A' and g.mon_can_go(monster, g.rogue.row, g.rogue.col) then + g.mv_monster(monster, g.rogue.row, g.rogue.col) + monster.m_flags[g.ALREADY_MOVED] = g.m_flags_desc[g.ALREADY_MOVED] + end + monster = monster.next_object + end +end diff --git a/autoload/rogue/move.lua b/autoload/rogue/move.lua new file mode 100644 index 0000000..2db52c9 --- /dev/null +++ b/autoload/rogue/move.lua @@ -0,0 +1,542 @@ +local g = Rogue -- alias + +g.m_moves = 0 +g.you_can_move_again = '' +g.jump = false +local bent_passage +local move_left_cou = 0 + +local heal_exp = -1 +local heal_n = 0 +local heal_c = 0 +local heal_alt = false + +function g.init_move() + g.you_can_move_again = g.mesg[66] +end + +function g.gr_dir() + local idx = g.get_rand(1, 8) + return string.sub("jklhyubn", idx, idx) +end + +function g.one_move_rogue(dirch, pickup) + local r = g.rogue.row + local c = g.rogue.col + bent_passage = false + + if g.confused > 0 then + dirch = g.gr_dir() + end + r, c = g.get_dir_rc(dirch, r, c, true) + local row = r + local col = c + + if not g.can_move(g.rogue.row, g.rogue.col, row, col) then + if (g.cur_room == g.PASSAGE) and (g.blind == 0) and (g.confused == 0) and + (not string.match("yubn", dirch)) then + bent_passage = true + end + return g.MOVE_FAILED + end + if g.being_held or g.bear_trap > 0 then + if not g.dungeon[row][col][g.MONSTER] then + if g.being_held then + g.message(g.mesg[67], true) + else + g.message(g.mesg[68]) + g.reg_move() + end + return g.MOVE_FAILED + end + end + if g.r_teleport then + if g.rand_percent(g.R_TELE_PERCENT) then + g.tele() + return g.STOPPED_ON_SOMETHING + end + end + if g.dungeon[row][col][g.MONSTER] then + g.rogue_hit(g.object_at(g.level_monsters, row, col), false) + g.reg_move() + return g.MOVE_FAILED + end + if g.dungeon[row][col][g.DOOR] then + if g.cur_room == g.PASSAGE then + g.cur_room = g.get_room_number(row, col) + g.light_up_room(g.cur_room) + g.wake_room(g.cur_room, true, row, col) + else + g.light_passage(row, col) + end + elseif g.dungeon[g.rogue.row][g.rogue.col][g.DOOR] and g.dungeon[row][col][g.TUNNEL]then + g.light_passage(row, col) + g.wake_room(g.cur_room, false, g.rogue.row, g.rogue.col) + g.darken_room(g.cur_room) + g.cur_room = g.PASSAGE + elseif g.dungeon[row][col][g.TUNNEL]then + g.light_passage(row, col) + end + + g.mvaddch(g.rogue.row, g.rogue.col, g.get_dungeon_char(g.rogue.row, g.rogue.col)) + g.mvaddch(row, col, g.rogue.fchar) + + if not g.jump then + g.refresh() + end + g.rogue.row = row + g.rogue.col = col + + if g.dungeon[row][col][g.OBJECT] then + if g.levitate > 0 and pickup then + return g.STOPPED_ON_SOMETHING + end + local obj + local desc + if pickup and g.levitate == 0 then + local status + obj, status = g.pick_up(row, col) + if obj then + desc = g.get_desc(obj, true) + if obj.what_is == g.GOLD then + g.free_object(obj) + if g.JAPAN then + desc = desc .. g.mesg[69] + end + -- goto NOT_IN_PACK + g.message(desc, true) + g.reg_move() + return g.STOPPED_ON_SOMETHING + end + elseif not status then + -- goto MVED + if g.reg_move() then + return g.STOPPED_ON_SOMETHING + end + return g.confused > 0 and g.STOPPED_ON_SOMETHING or g.MOVED + else + -- goto MOVE_ON + obj = g.object_at(g.level_objects, row, col) + if g.JAPAN then + desc = g.get_desc(obj, false) + desc = desc .. g.mesg[70] + else + desc = g.mesg[70] + desc = desc .. g.get_desc(obj, false) + end + -- goto NOT_IN_PACK + g.message(desc, true) + g.reg_move() + return g.STOPPED_ON_SOMETHING + end + else + -- ::MOVE_ON:: + obj = g.object_at(g.level_objects, row, col) + if g.JAPAN then + desc = g.get_desc(obj, false) + desc = desc .. g.mesg[70] + else + desc = g.mesg[70] + desc = desc .. g.get_desc(obj, false) + end + -- goto NOT_IN_PACK + g.message(desc, true) + g.reg_move() + return g.STOPPED_ON_SOMETHING + end + if g.JAPAN then + desc = desc .. g.mesg[69] + end + desc = desc .. '(' .. obj.ichar .. ')' + -- ::NOT_IN_PACK:: + g.message(desc, true) + g.reg_move() + return g.STOPPED_ON_SOMETHING + end + if g.dungeon[row][col][g.DOOR] or g.dungeon[row][col][g.STAIRS] or g.dungeon[row][col][g.TRAP] then + if g.levitate == 0 and g.dungeon[row][col][g.TRAP] then + g.trap_player(row, col) + end + g.reg_move() + return g.STOPPED_ON_SOMETHING + end + -- ::MVED:: + if g.reg_move() then -- fainted from hunger + return g.STOPPED_ON_SOMETHING + end + return g.confused > 0 and g.STOPPED_ON_SOMETHING or g.MOVED +end + +local function next_to_something(drow, dcol) + local row + local col + local pass_count = 0 + local s + + if g.confused > 0 then + return true + end + if g.blind > 0 then + return false + end + local i_end = (g.rogue.row < (g.DROWS-2)) and 1 or 0 + local j_end = (g.rogue.col < (g.DCOLS-1)) and 1 or 0 + + for i = ((g.rogue.row > g.MIN_ROW) and -1 or 0), i_end do + for j = ((g.rogue.col > 0) and -1 or 0), j_end do + local continue_flag = false + if (i == 0 and j == 0) or + (g.rogue.row+i == drow and g.rogue.col+j == dcol) then + -- continue + continue_flag = true + else + row = g.rogue.row + i + col = g.rogue.col + j + s = g.dungeon[row][col] + if s[g.HIDDEN] then + -- continue + continue_flag = true + end + end + if not continue_flag then + -- If the rogue used to be right, up, left, down, + -- or right of row, col, and now isn't, + -- then don't stop + if s[g.MONSTER] or s[g.OBJECT] or s[g.STAIRS] then + if (row == drow or col == dcol) and + (not(row == g.rogue.row or col == g.rogue.col)) then + -- continue + continue_flag = true + else + return true + end + end + end + if not continue_flag then + if s[g.TRAP] then + if not s[g.HIDDEN] then + if (row == drow or col == dcol) and + (not(row == g.rogue.row or col == g.rogue.col)) then + -- continue + continue_flag = true + else + return true + end + end + end + end + if not continue_flag then + if ((i - j == 1) or (i - j == -1)) and s[g.TUNNEL] then + pass_count = pass_count + 1 + if pass_count > 1 then + return true + end + end + if s[g.DOOR] and ((i == 0) or (j == 0)) then + return true + end + end + end + end + return false +end + +function g.multiple_move_rogue(dirch) + local row + local col + local m + local n + local ch + local dir + if dirch == 'CTRL_H' or + dirch == 'CTRL_J' or + dirch == 'CTRL_K' or + dirch == 'CTRL_L' or + dirch == 'CTRL_Y' or + dirch == 'CTRL_U' or + dirch == 'CTRL_N' or + dirch == 'CTRL_B' then + dirch = dirch:gsub('CTRL_', ''):lower() + local retry_flag + repeat + -- ::retry:: + retry_flag = false + row = g.rogue.row + col = g.rogue.col + m = g.one_move_rogue(dirch, true) + if m == g.STOPPED_ON_SOMETHING or g.interrupted then + break + end + if m ~= g.MOVE_FAILED then + -- continue + else + if (not g.pass_go) or (not bent_passage) then + break + end + n = 0 + dir = {[0] = 'h', 'j', 'k', 'l'} + for i = 0, 3 do + row = g.rogue.row + col = g.rogue.col + row, col = g.get_dir_rc(dir[i], row, col, true) + if g.is_passable(row, col) and dirch ~= dir[3-i] then + n = n + 1 + ch = dir[i] + end + end + if n == 1 then + dirch = ch + -- goto retry + retry_flag = true + else + break + end + end + until (not retry_flag) and next_to_something(row, col) + elseif dirch == 'H' or + dirch == 'J' or + dirch == 'K' or + dirch == 'L' or + dirch == 'Y' or + dirch == 'U' or + dirch == 'N' or + dirch == 'B' then + dirch = dirch:lower() + while true do + -- ::retry2:: + m = g.one_move_rogue(dirch, true) + if g.interrupted then + break + end + if m == g.MOVED then + -- continue + else + if m ~= g.MOVE_FAILED or (not g.pass_go) or (not bent_passage) then + break + end + n = 0 + dir = {[0] = 'h', 'j', 'k', 'l'} + for i = 0, 3 do + row = g.rogue.row + col = g.rogue.col + row, col = g.get_dir_rc(dir[i], row, col, true) + if g.is_passable(row, col) and dirch ~= dir[3-i] then + n = n + 1 + ch = dir[i] + end + end + if n == 1 then + dirch = ch + -- goto retry2 + else + break + end + end + end + end +end + +function g.can_move(row1, col1, row2, col2) + if not g.is_passable(row2, col2) then + return false + end + if (row1 ~= row2) and (col1 ~= col2) then + if g.dungeon[row1][col1][g.DOOR] or g.dungeon[row2][col2][g.DOOR] + or g.table_is_empty(g.dungeon[row1][col2]) or g.table_is_empty(g.dungeon[row2][col1]) then + return false + end + end + return true +end + +function g.move_onto() + local ch = g.get_direction() + if ch ~= g.CANCEL then + g.one_move_rogue(ch, false) + end +end + +function g.is_direction(c) + if c == g.CANCEL then + return true + end + if string.find('hjklbyun', c) then + return true + end + return false +end + +local function check_hunger(messages_only) + local fainted = false + + if g.rogue.moves_left == g.HUNGRY then + g.hunger_str = g.mesg[71] + g.message(g.mesg[72]) + g.print_stats() + end + if g.rogue.moves_left == g.WEAK then + g.hunger_str = g.mesg[73] + g.message(g.mesg[74], true) + g.print_stats() + end + if g.rogue.moves_left <= g.FAINT then + if g.rogue.moves_left == g.FAINT then + g.hunger_str = g.mesg[75] + g.message(g.mesg[76], true) + g.print_stats() + end + local n = g.get_rand(0, (g.FAINT - g.rogue.moves_left)) + if n > 0 then + fainted = true + if g.rand_percent(40) then + g.rogue.moves_left = g.rogue.moves_left + 1 + end + g.message(g.mesg[77], true) + for i = 1, n do + if g.coin_toss() then + g.mv_mons() + end + end + g.message(g.you_can_move_again, true) + end + end + if messages_only then + return fainted + end + if g.rogue.moves_left <= g.STARVE then + g.killed_by(nil, g.STARVATION) + -- NOTREACHED + end + if g.e_rings == -1 then + g.rogue.moves_left = g.rogue.moves_left - move_left_cou + elseif g.e_rings == 0 then + g.rogue.moves_left = g.rogue.moves_left - 1 + elseif g.e_rings == 1 then + g.rogue.moves_left = g.rogue.moves_left - 1 + check_hunger(true) + g.rogue.moves_left = g.rogue.moves_left - move_left_cou + elseif g.e_rings == 2 then + g.rogue.moves_left = g.rogue.moves_left - 1 + check_hunger(true) + g.rogue.moves_left = g.rogue.moves_left - 1 + end + move_left_cou = 1 + return fainted +end + +function g.is_passable(row, col) + if (row < g.MIN_ROW) or (row > (g.DROWS - 2)) or (col < 0) or (col > (g.DCOLS-1)) then + return false + end + if g.dungeon[row][col][g.HIDDEN] then + return g.dungeon[row][col][g.TRAP] and true or false + end + if g.dungeon[row][col][g.FLOOR] or + g.dungeon[row][col][g.TUNNEL] or + g.dungeon[row][col][g.DOOR] or + g.dungeon[row][col][g.STAIRS] or + g.dungeon[row][col][g.TRAP] then + return true + else + return false + end +end + +local function heal() + local na = { [0] = 0, 20, 18, 17, 14, 13, 10, 9, 8, 7, 4, 3 } + + if g.rogue.hp_current == g.rogue.hp_max then + heal_c = 0 + return + end + if g.rogue.exp ~= heal_exp then + heal_exp = g.rogue.exp + heal_n = (heal_exp < 1 or heal_exp > 11) and 2 or na[heal_exp] + end + heal_c = heal_c + 1 + if heal_c >= heal_n then + heal_c = 0 + g.rogue.hp_current = g.rogue.hp_current + 1 + heal_alt = not heal_alt + if heal_alt then + g.rogue.hp_current = g.rogue.hp_current + 1 + end + g.rogue.hp_current = g.rogue.hp_current + g.regeneration + if g.rogue.hp_current > g.rogue.hp_max then + g.rogue.hp_current = g.rogue.hp_max + end + g.print_stats() + end +end + +function g.reg_move() + local fainted = false + + if (g.rogue.moves_left <= g.HUNGRY) or (g.cur_level >= g.max_level) then + fainted = check_hunger(false) + else + fainted = false + end + + g.mv_mons() + + g.m_moves = g.m_moves + 1 + if g.m_moves >= 120 then + g.m_moves = 0 + g.wanderer() + end + if g.halluc > 0 then + g.halluc = g.halluc - 1 + if g.halluc == 0 then + g.unhallucinate() + else + g.hallucinate() + end + end + if g.blind > 0 then + g.blind = g.blind - 1 + if g.blind == 0 then + g.unblind() + end + end + if g.confused > 0 then + g.confused = g.confused - 1 + if g.confused == 0 then + g.unconfuse() + end + end + if g.bear_trap > 0 then + g.bear_trap = g.bear_trap - 1 + end + if g.levitate > 0 then + g.levitate = g.levitate - 1 + if g.levitate == 0 then + g.message(g.mesg[78], true) + if g.dungeon[g.rogue.row][g.rogue.col][g.TRAP] then + g.trap_player(g.rogue.row, g.rogue.col) + end + end + end + if g.haste_self > 0 then + g.haste_self = g.haste_self - 1 + if g.haste_self == 0 then + g.message(g.mesg[79]) + end + end + heal() + if g.auto_search > 0 then + g.search(g.auto_search, g.auto_search) + end + return fainted +end + +function g.rest(count) + g.interrupted = false + + for i = 1, count do + if g.interrupted then + break + end + g.reg_move() + end +end diff --git a/autoload/rogue/object.lua b/autoload/rogue/object.lua new file mode 100644 index 0000000..7433c2d --- /dev/null +++ b/autoload/rogue/object.lua @@ -0,0 +1,699 @@ +local g = Rogue -- alias + +g.ObjBase = {} +function g.ObjBase.new() + local obj = {} + obj.o_row = 0 -- o is how many times stuck at o_row, o_col + obj.o_col = 0 + obj.o = 0 + obj.row = 0 -- current row, col + obj.col = 0 + obj.trow = 0 -- target row, col + obj.tcol = 0 + obj.what_is = 0 + obj.next_object = nil + return obj +end + +local Object = {} +function Object.new() + local obj = g.ObjBase.new() + obj.damage = 0 + obj.quantity = 0 + obj.ichar = ' ' + obj.is_protected = false + obj.is_cursed = false + obj.class = 0 + obj.identified = false + obj.which_kind = 0 + obj.d_enchant = 0 + obj.quiver = 0 + obj.hit_enchant = 0 + obj.picked_up = false + obj.in_use_flags = g.NOT_USED + return obj +end + +local Fighter = {} +function Fighter.new() + local fighter = {} + fighter.armor = nil + fighter.weapon = nil + fighter.left_ring = nil + fighter.right_ring = nil + fighter.hp_current = g.INIT_HP + fighter.hp_max = g.INIT_HP + fighter.str_current = 16 + fighter.str_max = 16 + fighter.pack = {} + fighter.gold = 0 + fighter.exp = 1 + fighter.exp_points = 0 + fighter.row = 0 + fighter.col = 0 + fighter.fchar = '@' + fighter.moves_left = 1250 + return fighter +end + +g.level_objects = {} +g.rogue = {} +g.foods = 0 +g.party_counter = 0 +g.fruit = '' + +g.po_color = {} +g.id_potions = {} +g.id_scrolls = {} +g.id_weapons = {} +g.id_armors = {} +g.id_wands = {} +g.id_rings = {} + +function g.init_object() + g.rogue = Fighter.new() + g.fruit = g.mesg[333] + g.po_color = { [0] = + g.mesg[334], g.mesg[335], g.mesg[336], g.mesg[337], g.mesg[338], + g.mesg[339], g.mesg[340], g.mesg[341], g.mesg[342], g.mesg[343], + g.mesg[344], g.mesg[345], g.mesg[346], g.mesg[347] + } + g.id_potions = { [0] = + {value=100, title='', real=g.mesg[348], id_status=0}, + {value=250, title='', real=g.mesg[349], id_status=0}, + {value=100, title='', real=g.mesg[350], id_status=0}, + {value=200, title='', real=g.mesg[351], id_status=0}, + {value= 10, title='', real=g.mesg[352], id_status=0}, + {value=300, title='', real=g.mesg[353], id_status=0}, + {value= 10, title='', real=g.mesg[354], id_status=0}, + {value= 25, title='', real=g.mesg[355], id_status=0}, + {value=100, title='', real=g.mesg[356], id_status=0}, + {value=100, title='', real=g.mesg[357], id_status=0}, + {value= 10, title='', real=g.mesg[358], id_status=0}, + {value= 80, title='', real=g.mesg[359], id_status=0}, + {value=150, title='', real=g.mesg[360], id_status=0}, + {value=145, title='', real=g.mesg[361], id_status=0} + } + g.id_scrolls = { [0] = + {value=505, title='', real=g.mesg[362], id_status=0}, + {value=200, title='', real=g.mesg[363], id_status=0}, + {value=235, title='', real=g.mesg[364], id_status=0}, + {value=235, title='', real=g.mesg[365], id_status=0}, + {value=175, title='', real=g.mesg[366], id_status=0}, + {value=190, title='', real=g.mesg[367], id_status=0}, + {value= 25, title='', real=g.mesg[368], id_status=0}, + {value=610, title='', real=g.mesg[369], id_status=0}, + {value=210, title='', real=g.mesg[370], id_status=0}, + {value=100, title='', real=g.mesg[371], id_status=0}, + {value= 25, title='', real=g.mesg[372], id_status=0}, + {value=180, title='', real=g.mesg[373], id_status=0} + } + g.id_weapons = { [0] = + {value=150, title=g.mesg[374], real='', id_status=0}, + {value= 8, title=g.mesg[375], real='', id_status=0}, + {value= 15, title=g.mesg[376], real='', id_status=0}, + {value= 27, title=g.mesg[377], real='', id_status=0}, + {value= 35, title=g.mesg[378], real='', id_status=0}, + {value=360, title=g.mesg[379], real='', id_status=0}, + {value=470, title=g.mesg[380], real='', id_status=0}, + {value=580, title=g.mesg[381], real='', id_status=0} + } + g.id_armors = { [0] = + {value=300, title=g.mesg[382], real='', id_status=(g.UNIDENTIFIED)}, + {value=300, title=g.mesg[383], real='', id_status=(g.UNIDENTIFIED)}, + {value=400, title=g.mesg[384], real='', id_status=(g.UNIDENTIFIED)}, + {value=500, title=g.mesg[385], real='', id_status=(g.UNIDENTIFIED)}, + {value=600, title=g.mesg[386], real='', id_status=(g.UNIDENTIFIED)}, + {value=600, title=g.mesg[387], real='', id_status=(g.UNIDENTIFIED)}, + {value=700, title=g.mesg[388], real='', id_status=(g.UNIDENTIFIED)} + } + g.id_wands = { [0] = + {value= 25, title='', real=g.mesg[389], id_status=0}, + {value= 50, title='', real=g.mesg[390], id_status=0}, + {value= 45, title='', real=g.mesg[391], id_status=0}, + {value= 8, title='', real=g.mesg[392], id_status=0}, + {value= 55, title='', real=g.mesg[393], id_status=0}, + {value= 2, title='', real=g.mesg[394], id_status=0}, + {value= 25, title='', real=g.mesg[395], id_status=0}, + {value= 20, title='', real=g.mesg[396], id_status=0}, + {value= 20, title='', real=g.mesg[397], id_status=0}, + {value= 0, title='', real=g.mesg[398], id_status=0} + } + g.id_rings = { [0] = + {value=250, title='', real=g.mesg[399], id_status=0}, + {value=100, title='', real=g.mesg[400], id_status=0}, + {value=255, title='', real=g.mesg[401], id_status=0}, + {value=295, title='', real=g.mesg[402], id_status=0}, + {value=200, title='', real=g.mesg[403], id_status=0}, + {value=250, title='', real=g.mesg[404], id_status=0}, + {value=250, title='', real=g.mesg[405], id_status=0}, + {value= 25, title='', real=g.mesg[406], id_status=0}, + {value=300, title='', real=g.mesg[407], id_status=0}, + {value=290, title='', real=g.mesg[408], id_status=0}, + {value=270, title='', real=g.mesg[409], id_status=0} + } +end + +local function make_party() + g.party_room = g.gr_room() + + local n = g.rand_percent(99) and g.party_objects(g.party_room) or 11 + if g.rand_percent(99) then + g.party_monsters(g.party_room, n) + end +end + +local function next_party() + local n = g.cur_level + while (n % g.PARTY_TIME) ~= 0 do + n = n + 1 + end + return g.get_rand((n + 1), (n + g.PARTY_TIME)) +end + +local function plant_gold(row, col, is_maze) + local obj = g.alloc_object() + obj.row = row + obj.col = col + obj.what_is = g.GOLD + obj.quantity = g.get_rand((2 * g.cur_level), (16 * g.cur_level)) + if is_maze then + obj.quantity = obj.quantity + g.int_div(obj.quantity, 2) + end + obj.desc = g.get_desc(obj) + g.dungeon[row][col][g.OBJECT] = g.dungeon_desc[g.OBJECT] + g.add_to_pack(obj, g.level_objects, false) +end + +function g.place_at(obj, row, col) + obj.row = row + obj.col = col + g.dungeon[row][col][g.OBJECT] = g.dungeon_desc[g.OBJECT] + g.add_to_pack(obj, g.level_objects, false) +end + +function g.object_at(pack, row, col) + local obj = pack.next_object + while obj and (obj.row ~= row or obj.col ~= col) do + obj = obj.next_object + end + return obj +end + +function g.get_letter_object(ch) + local obj = g.rogue.pack.next_object + + while obj and obj.ichar ~= ch do + obj = obj.next_object + end + return obj +end + +function g.free_stuff(objlist) + g.free_object(objlist) +end + +local function put_gold() + for i = 0, g.MAXROOMS-1 do + local is_maze = (g.rooms[i].is_room == g.R_MAZE) and true or false + local is_room = (g.rooms[i].is_room == g.R_ROOM) and true or false + + if not (is_room or is_maze) then + -- continue + else + if is_maze or g.rand_percent(g.GOLD_PERCENT) then + for j = 0, 49 do + local row = g.get_rand(g.rooms[i].top_row+1, g.rooms[i].bottom_row-1) + local col = g.get_rand(g.rooms[i].left_col+1, g.rooms[i].right_col-1) + if g.dungeon[row][col][g.FLOOR] or + g.dungeon[row][col][g.TUNNEL] then + plant_gold(row, col, is_maze) + break + end + end + end + end + end +end + +local function rand_place(obj) + local row + local col + row, col = g.gr_row_col({[g.FLOOR]=true, [g.TUNNEL]=true}) + g.place_at(obj, row, col) +end + +function g.put_objects() + if g.cur_level < g.max_level then + return + end + local n = g.coin_toss() and g.get_rand(2, 4) or g.get_rand(3, 5) + while g.rand_percent(33) do + n = n + 1 + end + if g.cur_level == g.party_counter then + make_party() + g.party_counter = next_party() + end + for i = 0, n-1 do + local obj = g.gr_object() + rand_place(obj) + end + put_gold() +end + +function g.name_of(obj) + local wa = { + g.SCROL, g.POTION, g.WAND, g.ARMOR, g.RING, g.AMULET + } + local na = { + g.mesg[3], g.mesg[4], g.mesg[5], g.mesg[7], g.mesg[8], g.mesg[9] + } + if not g.JAPAN then + if obj.what_is == g.WAND then + return g.is_wood[obj.which_kind] and g.mesg[6] or g.mesg[5] + end + end + if obj.what_is == g.WEAPON then + if not g.English then + return g.id_weapons[obj.which_kind].title + else + local bf = g.id_weapons[obj.which_kind].title + if obj.which_kind == g.DART or + obj.which_kind == g.ARROW or + obj.which_kind == g.DAGGER or + obj.which_kind == g.SHURIKEN then + if obj.quantity == 1 then + -- remove "s" of the plural + bf = bf:gsub("s ", " ") + end + end + return bf + end + end + if obj.what_is == g.FOOD then + return (obj.which_kind == g.RATION) and g.mesg[2] or g.fruit + end + for i = 1, #wa do + if obj.what_is == wa[i] then + if not g.English then + return na[i] + else + if obj.quantity > 1 then + -- add "s" of the plural + return na[i]:gsub(" ", "s ") + else + return na[i] + end + end + end + end + return g.mesg[80] +end + +local function gr_what_is() + local per = { 30, 60, 64, 74, 83, 88, 91 } + local ret = { + g.SCROL, g.POTION, g.WAND, g.WEAPON, g.ARMOR, g.FOOD, g.RING + } + + local percent = g.get_rand(1, 91) + for i = 1, #per do + if percent <= per[i] then + return ret[i] + end + end +end + +local function gr_scroll(obj) + local per = { + 5, 11, 16, 21, 36, 44, 51, 56, 65, 74, 80, 85 + } + local percent = g.get_rand(0, 85) + obj.what_is = g.SCROL + for i = 1, #per do + if percent <= per[i] then + obj.which_kind = i - 1 + obj.which_kind_scroll = obj.which_kind + return + end + end +end + +local function gr_potion(obj) + local per = { + 10, 20, 30, 40, 50, 55, 65, 75, 85, 95, 105, 110, 114, 118 + } + local percent = g.get_rand(1, 118) + obj.what_is = g.POTION + for i = 1, #per do + if percent <= per[i] then + obj.which_kind = i - 1 + obj.which_kind_potion = obj.which_kind + return + end + end +end + +local function gr_weapon(obj, assign_wk) + local da = { [0] = + "1d1", "1d1", "1d2", "1d3", "1d4", "2d3", "3d4", "4d5" + } + + obj.what_is = g.WEAPON + if assign_wk then + obj.which_kind = g.get_rand(0, g.WEAPONS - 1) + obj.which_kind_weapon = obj.which_kind + end + local i = obj.which_kind + if i == g.ARROW or i == g.DAGGER or i == g.SHURIKEN or i == g.DART then + obj.quantity = g.get_rand(3, 15) + obj.quiver = g.get_rand(0, 126) + else + obj.quantity = 1 + end + obj.hit_enchant = 0 + obj.d_enchant = 0 + + local percent = g.get_rand(1, 96) + local blessing = g.get_rand(1, 3) + + local increment + if percent <= 16 then + increment = 1 + elseif percent <= 32 then + increment = -1 + obj.is_cursed = true + end + if percent <= 32 then + for i = 0, blessing-1 do + if g.coin_toss() then + obj.hit_enchant = obj.hit_enchant + increment + else + obj.d_enchant = obj.d_enchant + increment + end + end + end + obj.damage = da[obj.which_kind] +end + +local function gr_armor(obj, assign_wk) + obj.what_is = g.ARMOR + if assign_wk then + obj.which_kind = g.get_rand(0, g.ARMORS - 1) + obj.which_kind_armor = obj.which_kind + end + obj.class = obj.which_kind + 2 + if obj.which_kind == g.PLATE or obj.which_kind == g.SPLINT then + obj.class = obj.class - 1 + end + obj.is_protected = false + obj.d_enchant = 0 + + local percent = g.get_rand(1, 100) + local blessing = g.get_rand(1, 3) + + if percent <= 16 then + obj.is_cursed = true + obj.d_enchant = obj.d_enchant - blessing + elseif percent <= 32 then + obj.d_enchant = obj.d_enchant + blessing + end +end + +local function gr_wand(obj) + obj.what_is = g.WAND + obj.which_kind = g.get_rand(0, g.WANDS - 1) + obj.which_kind_wand = obj.which_kind + if obj.which_kind == g.MAGIC_MISSILE then + obj.class = g.get_rand(6, 12) + elseif obj.which_kind == g.CANCELLATION then + obj.class = g.get_rand(5, 9) + else + obj.class = g.get_rand(3, 6) + end +end + +function g.get_food(obj, force_ration) + obj.what_is = g.FOOD + + if force_ration or g.rand_percent(80) then + obj.which_kind = g.RATION + else + obj.which_kind = g.FRUIT + end + obj.which_kind_food = obj.which_kind +end + +function g.gr_object() + local obj = g.alloc_object() + if g.foods < g.int_div(g.cur_level, 3) then + obj.what_is = g.FOOD + g.foods = g.foods + 1 + else + obj.what_is = gr_what_is() + end + if obj.what_is == g.SCROL then + gr_scroll(obj) + elseif obj.what_is == g.POTION then + gr_potion(obj) + elseif obj.what_is == g.WEAPON then + gr_weapon(obj, true) + elseif obj.what_is == g.ARMOR then + gr_armor(obj, true) + elseif obj.what_is == g.WAND then + gr_wand(obj) + elseif obj.what_is == g.FOOD then + g.get_food(obj, false) + elseif obj.what_is == g.RING then + g.gr_ring(obj, true) + end + obj.desc = g.get_desc(obj) + return obj +end + +function g.put_stairs() + local row + local col + row, col = g.gr_row_col({ [g.FLOOR]=true, [g.TUNNEL]=true }) + g.dungeon[row][col][g.STAIRS] = g.dungeon_desc[g.STAIRS] +end + +function g.get_armor_class(obj) + if obj then + return obj.class + obj.d_enchant + end + return 0 +end + +function g.alloc_object() + local obj = Object.new() + obj.quantity = 1 + obj.ichar = 'L' + obj.picked_up = false + obj.is_cursed = false + obj.identified = false + obj.damage = "1d1" + return obj +end + +function g.free_object(obj) + obj.next_object = nil +end + +function g.copy_object(dst, src) + for k, v in pairs(src) do + dst[k] = v + end + if src.m_flags then + dst.m_flags = {} + for k, v in pairs(src.m_flags) do + dst.m_flags[k] = v + end + end +end + +function g.show_objects() + local obj = g.level_objects.next_object + local monster + + while obj do + local row = obj.row + local col = obj.col + local rc = g.get_mask_char(obj.what_is) + + if g.dungeon[row][col][g.MONSTER] then + monster = g.object_at(g.level_monsters, row, col) + if monster then + monster.trail_char = rc + end + end + local mc = g.mvinch(row, col) + if (not mc:find('^[A-Z]$')) and + (row ~= g.rogue.row or col ~= g.rogue.col) then + g.mvaddch(row, col, rc) + end + obj = obj.next_object + end + + monster = g.level_monsters.next_object + while monster do + if monster.m_flags[g.IMITATES] then + g.mvaddch(monster.row, monster.col, monster.disguise) + end + monster = monster.next_object + end +end + +function g.put_amulet() + local obj = g.alloc_object() + obj.what_is = g.AMULET + obj.desc = g.get_desc(obj) + rand_place(obj) +end + +local function list_object(obj, max) + local row + local col + local msg = ' ' .. g.mesg[494] + if g.JAPAN then + msg = ' ' .. msg + end + local len = g.strwidth(msg) + local weapon_or_armor = false + local id + if obj.what_is == g.ARMOR then + id = g.id_armors + weapon_or_armor = true + elseif obj.what_is == g.WEAPON then + id = g.id_weapons + weapon_or_armor = true + elseif obj.what_is == g.SCROL then + id = g.id_scrolls + elseif obj.what_is == g.POTION then + id = g.id_potions + elseif obj.what_is == g.WAND then + id = g.id_wands + elseif obj.what_is == g.RING then + id = g.id_rings + else + return + end + + local descs = {} + local maxlen = len + for i = 0, max do + if g.JAPAN then + descs[i] = string.format(" %c) %s%s", i + string.byte('a'), + (weapon_or_armor and id[i].title or id[i].real), + (weapon_or_armor and "" or g.name_of(obj))) + else + descs[i] = string.format(" %c) %s%s", i + string.byte('a'), + (weapon_or_armor and "" or g.name_of(obj)), + (weapon_or_armor and id[i].title or id[i].real)) + end + local n = g.strwidth(g.descs[i]) + if n > maxlen then + maxlen = n + end + end + local m = max + 1 + descs[m] = msg + + col = g.DCOLS - (maxlen + 2 + 1) + for row = 0, m do + g.mvaddstr(row, col, descs[row]) + end + g.refresh() + g.wait_for_ack() + for row = 0, g.DROWS-2 do + g.mvaddstr(row, 0, '') + end +end + +function g.new_object_for_wizard() + if g.pack_count(nil) >= g.MAX_PACK_COUNT then + g.message(g.mesg[81]) + return + end + g.message(g.mesg[82]) + local ch + while true do + ch = g.rgetchar() + if ch == g.CANCEL then + g.check_message() + return + elseif string.find('!?:)]=/,', ch, 1, true) then + g.check_message() + break + else + g.sound_bell() + end + end + + local max = 0 + local obj = g.alloc_object() + if ch == '!' then + obj.what_is = g.POTION + max = g.POTIONS - 1 + elseif ch == '?' then + obj.what_is = g.SCROL + max = g.SCROLS - 1 + elseif ch == ',' then + obj.what_is = g.AMULET + elseif ch == ':' then + g.get_food(obj, false) + elseif ch == ')' then + obj.what_is = g.WEAPON + max = g.WEAPONS - 1 + elseif ch == ']' then + obj.what_is = g.ARMOR + max = g.ARMORS - 1 + elseif ch == '/' then + gr_wand(obj) + max = g.WANDS - 1 + elseif ch == '=' then + obj.what_is = g.RING + max = g.RINGS - 1 + end + + if ch ~= ',' and ch ~= ':' then + local buf = string.format(g.mesg[83], (obj.what_is == g.WEAPON) + and g.mesg[84] or g.name_of(obj)) + while true do + g.message(buf) + while true do + ch = g.rgetchar() + if ch ~= g.LIST and ch ~= g.CANCEL and + string.byte(ch) < string.byte('a') or string.byte(ch) > string.byte('a')+max then + g.sound_bell() + else + break + end + end + if ch == g.LIST then + g.check_message() + list_object(obj, max) + else + break + end + end + g.check_message() + if ch == g.CANCEL then + g.free_object(obj) + return + end + obj.which_kind = string.byte(ch) - string.byte('a') + if obj.what_is == g.RING then + g.gr_ring(obj, false) + end + if obj.what_is == g.ARMOR then + gr_armor(obj, false) + elseif obj.what_is == g.WEAPON then + gr_weapon(obj, false) + end + end + obj.desc = g.get_desc(obj) + g.message(g.get_desc(obj, true)) + g.add_to_pack(obj, g.rogue.pack, true) +end diff --git a/autoload/rogue/pack.lua b/autoload/rogue/pack.lua new file mode 100644 index 0000000..25451a7 --- /dev/null +++ b/autoload/rogue/pack.lua @@ -0,0 +1,459 @@ +local g = Rogue -- alias + +g.curse_message = '' + +function g.init_pack() + g.curse_message = g.mesg[85] +end + +local function check_duplicate(obj, pack) + if not (obj.what_is == g.WEAPON or + obj.what_is == g.FOOD or + obj.what_is == g.SCROL or + obj.what_is == g.POTION) then + return nil + end + if (obj.what_is == g.FOOD) and (obj.which_kind == g.FRUIT) then + return nil + end + local op = pack.next_object + + while op do + if (op.what_is == obj.what_is) and (op.which_kind == obj.which_kind) then + if ((obj.what_is ~= g.WEAPON) or + ((obj.what_is == g.WEAPON) and + ((obj.which_kind == g.ARROW) or + (obj.which_kind == g.DAGGER) or + (obj.which_kind == g.DART) or + (obj.which_kind == g.SHURIKEN)) and + (obj.quiver == op.quiver))) then + op.quantity = op.quantity + obj.quantity + return op + end + end + op = op.next_object + end + return nil +end + +local function next_avail_ichar() + local ichars = {} + local obj = g.rogue.pack.next_object + while obj do + ichars[obj.ichar] = true + obj = obj.next_object + end + for s in string.gmatch("abcdefghijklmnopqrstuvwxyz", "%a") do + if not ichars[s] then + return s + end + end + return '?' +end + +function g.wait_for_ack() + while g.rgetchar() ~= ' ' do + end +end + +local function mask_pack(pack, mask) + if type(mask) == 'number' then + mask = { [mask] = true } + end + while pack.next_object do + pack = pack.next_object + if mask[pack.what_is] then + return true + end + end + return false +end + +local function is_pack_letter(c, mask) + if c == '?' then + return true, g.LIST, g.SCROL + elseif c == '!' then + return true, g.LIST, g.POTION + elseif c == ':' then + return true, g.LIST, g.FOOD + elseif c == ')' then + return true, g.LIST, g.WEAPON + elseif c == ']' then + return true, g.LIST, g.ARMOR + elseif c == '/' then + return true, g.LIST, g.WAND + elseif c == '=' then + return true, g.LIST, g.RING + elseif c == ',' then + return true, g.LIST, g.AMULET + else + return (c:match('^[a-z]$') ~= nil or c == g.CANCEL or c == g.LIST), c, mask + end +end + +function g.pack_letter(prompt, mask) + if type(mask) == 'number' then + mask = { [mask] = true } + end + local tmask = mask + + if not mask_pack(g.rogue.pack, mask) then + g.message(g.mesg[93]) + return g.CANCEL + end + local ch + while true do + g.message(prompt) + + while true do + ch = g.rgetchar() + local ret + ret, ch, mask = is_pack_letter(ch, mask) + if not ret then + g.sound_bell() + else + break + end + end + + if ch == g.LIST then + g.check_message() + g.inventory(g.rogue.pack, mask) + else + break + end + mask = tmask + end + g.check_message() + return ch +end + +function g.add_to_pack(obj, pack, condense) + local op + if condense then + op = check_duplicate(obj, pack) + if op then + g.free_object(obj) + return op + else + obj.ichar = next_avail_ichar() + end + end + op = pack + while op.next_object do + if op.next_object.what_is > obj.what_is then + local p = op.next_object + op.next_object = obj + obj.next_object = p + return obj + end + op = op.next_object + end + op.next_object = obj + obj.next_object = nil + return obj +end + +function g.take_from_pack(obj, pack) + local p = pack + while p.next_object ~= obj do + p = p.next_object + end + p.next_object = p.next_object.next_object +end + +function g.pick_up(row, col) + local obj = g.object_at(g.level_objects, row, col) + local status = true + + if obj.what_is == g.SCROL and obj.which_kind == g.SCARE_MONSTER and obj.picked_up then + g.message(g.mesg[86]) + g.dungeon[row][col][g.OBJECT] = nil + g.vanish(obj, false, g.level_objects) + status = false + if g.id_scrolls[g.SCARE_MONSTER].id_status == g.UNIDENTIFIED then + g.id_scrolls[g.SCARE_MONSTER].id_status = g.IDENTIFIED + end + return nil, status + end + if obj.what_is == g.GOLD then + g.rogue.gold = g.rogue.gold + obj.quantity + g.dungeon[row][col][g.OBJECT] = nil + g.take_from_pack(obj, g.level_objects) + g.print_stats() + return obj, status -- obj will be free_object()ed in one_move_rogue() + end + if g.pack_count(obj) >= g.MAX_PACK_COUNT then + g.message(g.mesg[87], true) + return nil, status + end + g.dungeon[row][col][g.OBJECT] = nil + g.take_from_pack(obj, g.level_objects) + obj = g.add_to_pack(obj, g.rogue.pack, true) + obj.picked_up = true + return obj, status +end + +function g.drop() + if g.dungeon[g.rogue.row][g.rogue.col][g.OBJECT] or + g.dungeon[g.rogue.row][g.rogue.col][g.STAIRS] or + g.dungeon[g.rogue.row][g.rogue.col][g.TRAP] then + g.message(g.mesg[88]) + return + end + if not g.rogue.pack.next_object then + g.message(g.mesg[89]) + return + end + local ch = g.pack_letter(g.mesg[90], g.ALL_OBJECTS) + if ch == g.CANCEL then + return + end + local obj = g.get_letter_object(ch) + if not obj then + g.message(g.mesg[91]) + return + end + if obj.in_use_flags == g.BEING_WIELDED then + if obj.is_cursed then + g.message(g.curse_message) + return + end + g.unwield(g.rogue.weapon) + elseif obj.in_use_flags == g.BEING_WORN then + if obj.is_cursed then + g.message(g.curse_message) + return + end + g.mv_aquatars() + g.unwear(g.rogue.armor) + g.print_stats() + elseif g.ON_EITHER_HAND(obj.in_use_flags) then + if obj.is_cursed then + g.message(g.curse_message) + return + end + g.un_put_on(obj) + end + obj.row = g.rogue.row + obj.col = g.rogue.col + + if obj.quantity > 1 and obj.what_is ~= g.WEAPON then + obj.quantity = obj.quantity - 1 + local new = g.alloc_object() + g.copy_object(new, obj) + new.quantity = 1 + obj = new + else + obj.ichar = 'L' + g.take_from_pack(obj, g.rogue.pack) + end + g.place_at(obj, g.rogue.row, g.rogue.col) + if g.JAPAN then + g.message(g.get_desc(obj) .. g.mesg[92]) + else + g.message(g.mesg[92] .. g.get_desc(obj)) + end + g.reg_move() +end + +function g.take_off() + if g.rogue.armor then + if g.rogue.armor.is_cursed then + g.message(g.curse_message) + else + g.mv_aquatars() + local obj = g.rogue.armor + g.unwear(obj) + if g.JAPAN then + g.message(g.get_desc(obj) .. g.mesg[94]) + else + g.message(g.mesg[94] .. g.get_desc(obj)) + end + g.print_stats() + g.reg_move() + end + else + g.message(g.mesg[95]) + end +end + +function g.wear() + if g.rogue.armor then + g.message(g.mesg[96]) + return + end + local ch = g.pack_letter(g.mesg[97], g.ARMOR) + + if ch == g.CANCEL then + return + end + local obj = g.get_letter_object(ch) + if not obj then + g.message(g.mesg[98]) + return + end + if obj.what_is ~= g.ARMOR then + g.message(g.mesg[99]) + return + end + obj.identified = true + if g.JAPAN then + g.message(g.get_desc(obj) .. g.mesg[100]) + else + g.message(g.mesg[100] .. g.get_desc(obj)) + end + g.do_wear(obj) + g.print_stats() + g.reg_move() +end + +function g.unwear(obj) + if obj then + obj.in_use_flags = g.NOT_USED + end + g.rogue.armor = nil +end + +function g.do_wear(obj) + g.rogue.armor = obj + obj.in_use_flags = g.BEING_WORN + obj.identified = true +end + +function g.wield() + if g.rogue.weapon and g.rogue.weapon.is_cursed then + g.message(g.curse_message) + return + end + local ch = g.pack_letter(g.mesg[101], g.WEAPON) + + if ch == g.CANCEL then + return + end + local obj = g.get_letter_object(ch) + if not obj then + g.message(g.mesg[102]) + return + end + if obj.what_is == g.ARMOR then + g.message(string.format(g.mesg[103], g.mesg[104])) + return + elseif obj.what_is == g.RING then + g.message(string.format(g.mesg[103], g.mesg[105])) + return + end + + if obj.in_use_flags == g.BEING_WIELDED then + g.message(g.mesg[106]) + else + g.unwield(g.rogue.weapon) + if g.JAPAN then + g.message(g.get_desc(obj) .. g.mesg[107]) + else + g.message(g.mesg[107] .. g.get_desc(obj)) + end + g.do_wield(obj) + g.reg_move() + end +end + +function g.do_wield(obj) + g.rogue.weapon = obj + obj.in_use_flags = g.BEING_WIELDED +end + +function g.unwield(obj) + if obj then + obj.in_use_flags = g.NOT_USED + end + g.rogue.weapon = nil +end + +function g.call_it() + local ch = g.pack_letter(g.mesg[108], + {[g.SCROL] = true, [g.POTION] = true, [g.WAND] = true, [g.RING] = true}) + if ch == g.CANCEL then + return + end + local obj = g.get_letter_object(ch) + if not obj then + g.message(g.mesg[109]) + return + end + if not (obj.what_is == g.SCROL or obj.what_is == g.POTION or + obj.what_is == g.WAND or obj.what_is == g.RING) then + g.message(g.mesg[110]) + return + end + local id_table = g.get_id_table(obj) + local buf + if g.JAPAN then + buf = g.get_input_line(g.mesg[111], "", id_table[obj.which_kind].title, false, true) + if string.byte(' ') <= buf:byte(1) and buf:byte(1) <= string.byte('~') then + buf = buf .. ' ' + end + else + buf = g.get_input_line(g.mesg[111], "", id_table[obj.which_kind].title, true, true) + end + if buf ~= '' then + id_table[obj.which_kind].id_status = g.CALLED + id_table[obj.which_kind].title = buf + end +end + +function g.pack_count(new_obj) + local count = 0 + local obj = g.rogue.pack.next_object + + while obj do + if obj.what_is ~= g.WEAPON then + count = count + obj.quantity + elseif not new_obj then + count = count + 1 + elseif ((new_obj.what_is ~= g.WEAPON) or + ((obj.which_kind ~= g.ARROW) and + (obj.which_kind ~= g.DAGGER) and + (obj.which_kind ~= g.DART) and + (obj.which_kind ~= g.SHURIKEN)) or + (new_obj.which_kind ~= obj.which_kind) or + (obj.quiver ~= new_obj.quiver)) then + count = count + 1 + end + obj = obj.next_object + end + return count +end + +function g.has_amulet() + return mask_pack(g.rogue.pack, g.AMULET) +end + +function g.kick_into_pack() + if not g.dungeon[g.rogue.row][g.rogue.col][g.OBJECT] then + g.message(g.mesg[112]) + else + if g.levitate > 0 then + g.message(g.mesg[113]) + return + end + local obj, stat = g.pick_up(g.rogue.row, g.rogue.col) + if obj then + local desc = g.get_desc(obj, true) + if g.JAPAN then + desc = desc .. g.mesg[114] + end + if obj.what_is == g.GOLD then + g.message(desc) + g.free_object(obj) + else + desc = desc .. '(' .. obj.ichar .. ')' + g.message(desc) + end + end + if obj or (not stat) then + g.reg_move() + end + end +end + diff --git a/autoload/rogue/play.lua b/autoload/rogue/play.lua new file mode 100644 index 0000000..a7c5352 --- /dev/null +++ b/autoload/rogue/play.lua @@ -0,0 +1,296 @@ +local g = Rogue -- alias + +g.interrupted = false +g.suspended = false + +local function help() + local help_message = { + g.mesg[116], g.mesg[117], g.mesg[118], g.mesg[119], g.mesg[120], g.mesg[121], + g.mesg[122], g.mesg[123], g.mesg[124], g.mesg[125], g.mesg[126], g.mesg[127], + g.mesg[128], g.mesg[129], g.mesg[130], g.mesg[131], g.mesg[132], g.mesg[133], + g.mesg[134], g.mesg[135], g.mesg[136], g.mesg[137], + " ", + g.mesg[494] + } + + for n = 1, #help_message do + g.mvaddstr(n-1, 0, help_message[n]) + end + g.refresh() + g.wait_for_ack() + + for row = 0, g.DROWS-1 do + g.mvaddstr(row, 0, '') + end + g.print_stats() + g.refresh() +end + +local function identify() + local o_names = { [0] = + g.mesg[138], g.mesg[139], g.mesg[140], g.mesg[141], g.mesg[142], g.mesg[143], + g.mesg[144], g.mesg[145], g.mesg[146], g.mesg[147], g.mesg[148], g.mesg[149], + g.mesg[150], g.mesg[151], g.mesg[152], g.mesg[153], g.mesg[154] + } + + g.message(g.mesg[155]) + local p + local ch + while true do + ch = g.rgetchar() + if ch == g.CANCEL then + g.check_message() + return + elseif ch:find('^[A-Z]$') then + g.check_message() + p = g.m_names[string.byte(ch) - string.byte('A')] + break + elseif ch:find('^[a-z]$') then + g.check_message() + p = g.m_names[string.byte(ch) - string.byte('a')] + break + else + local n = string.find("@.|-+#%^*:])?!/=,", ch, 1, true) + if n then + g.check_message() + p = o_names[n - 1] + break + end + end + g.sound_bell() + end + g.message(string.format("'%s': %s", string.upper(ch), p)) +end + +local function doshell() + if vim then + vim.command("sh") + end +end + +function g.play_level() + local unknown_command = g.mesg[115] + local ch + local cmd = '.' + local oldcmd + local count = 0 + local goto_CH_flag = false + + while true do + if not goto_CH_flag then + g.interrupted = false + if g.hit_message ~= "" then + g.message(g.hit_message, true) + g.hit_message = "" + end + if g.trap_door then + g.trap_door = false + return + end + g.refresh() + + oldcmd = cmd + cmd = g.rgetchar() + ch = cmd + g.check_message() + count = 0 + end + + -- ::CH:: + goto_CH_flag = false + if ch == '.' then + g.rest((count > 0) and count or 1) + elseif ch == 's' then + g.search(((count > 0) and count or 1), false) + elseif ch == 'i' then + g.inventory(g.rogue.pack, g.ALL_OBJECTS) + elseif ch == 'f' then + g.fight(false) + elseif ch == 'F' then + g.fight(true) + elseif ch == 'h' or + ch == 'j' or + ch == 'k' or + ch == 'l' or + ch == 'y' or + ch == 'u' or + ch == 'n' or + ch == 'b' then + g.one_move_rogue(ch, true) + elseif ch == 'H' or + ch == 'J' or + ch == 'K' or + ch == 'L' or + ch == 'Y' or + ch == 'U' or + ch == 'N' or + ch == 'B' or + ch == 'CTRL_H' or ch == 'BS' or + ch == 'CTRL_J' or + ch == 'CTRL_K' or + ch == 'CTRL_L' or + ch == 'CTRL_Y' or + ch == 'CTRL_U' or + ch == 'CTRL_N' or + ch == 'CTRL_B' then + if ch == 'BS' then + ch = 'CTRL_H' + end + g.multiple_move_rogue(ch) + elseif ch == 'e' then + g.eat() + elseif ch == 'q' then + g.quaff() + elseif ch == 'r' then + g.read_scroll() + elseif ch == 'm' then + g.move_onto() + elseif ch == 'd' then + g.drop() + elseif ch == 'P' then + g.put_on_ring() + elseif ch == 'R' then + g.remove_ring() + elseif ch == 'CTRL_P' then + g.remessage() + elseif ch == 'CTRL_W' then + g.wizardize() + elseif ch == '>' then + if g.drop_check() then + return + end + elseif ch == '<' then + if g.check_up() then + return + end + elseif ch == ')' then + g.inv_weapon() + elseif ch == ']' then + g.inv_armor() + elseif ch == '=' then + g.inv_rings() + elseif ch == '^' then + g.id_trap() + elseif ch == 'I' then + g.single_inv(false) + elseif ch == 'T' then + g.take_off() + elseif ch == 'W' then + g.wear() + elseif ch == 'w' then + g.wield() + elseif ch == 'c' then + g.call_it() + elseif ch == 'z' then + g.zapp() + elseif ch == 't' then + g.throw() + elseif ch == 'v' then + g.message("Rogue-clone: Version II. (Tim Stoehr was here), tektronix!zeus!tims ") + g.message("Japanese edition: Ver.1.3a (enhanced by ohta@src.ricoh.co.jp)") + g.message("Ver.1.3aS program bug fix/separate (by brx@kmc.kyoto-u.ac.jp)") + g.message("Porting to Vim plugin: Ver." .. g.version .. " (by katono)") + g.message(g.mesg[1]) -- for message version + elseif ch == 'Q' then + g.quit(false) + elseif ch == '0' or + ch == '1' or + ch == '2' or + ch == '3' or + ch == '4' or + ch == '5' or + ch == '6' or + ch == '7' or + ch == '8' or + ch == '9' then + g.refresh() + repeat + if count < 100 then + count = (10 * count) + tonumber(ch) + end + ch = g.rgetchar() + until not tonumber(ch) + if ch ~= g.CANCEL then + -- goto CH + goto_CH_flag = true + end + elseif ch == ' ' then + elseif ch == 'CTRL_I' then + if g.wizard then + g.inventory(g.level_objects, g.ALL_OBJECTS) + else + g.message(unknown_command) + end + elseif ch == 'CTRL_S' then + if g.wizard then + g.draw_magic_map() + else + g.message(unknown_command) + end + elseif ch == 'CTRL_T' then + if g.wizard then + g.show_traps() + else + g.message(unknown_command) + end + elseif ch == 'CTRL_O' then + if g.wizard then + g.show_objects() + else + g.message(unknown_command) + end + elseif ch == 'CTRL_A' then + g.show_average_hp() + elseif ch == 'CTRL_G' then + if g.wizard then + g.new_object_for_wizard() + else + g.message(unknown_command) + end + elseif ch == 'ENTER' then -- CTRL_M + if g.wizard then + g.show_monsters() + else + g.message(unknown_command) + end + elseif ch == 'S' then + g.save_game() + elseif ch == ',' then + g.kick_into_pack() + elseif ch == 'CTRL_X' then + if g.wizard then + g.draw_magic_map() + g.show_monsters() + g.show_objects() + g.show_traps() + else + g.message(unknown_command) + end + elseif ch == '?' then + help() + elseif ch == '@' or ch == 'CTRL_R' then + g.print_stats(true) + elseif ch == 'D' then + g.discovered() + elseif ch == '/' then + identify() + elseif ch == '!' then + doshell() + elseif ch == 'a' then + cmd = oldcmd + ch = cmd + -- goto CH + goto_CH_flag = true + elseif ch == 'CTRL_Z' then + g.suspended = true + g.exit() + -- NOTREACHED + --[[ + elseif ch == 'CTRL_Q' then + g.breakpoint(true) + --]] + else + g.message(unknown_command) + end + end +end diff --git a/autoload/rogue/random.lua b/autoload/rogue/random.lua new file mode 100644 index 0000000..47ff699 --- /dev/null +++ b/autoload/rogue/random.lua @@ -0,0 +1,108 @@ +local g = Rogue -- alias + +local rntb = { + [0] = 3, 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, + 0xde3b81e0, 0xdf0a6fb5, 0xf103bc02, 0x48f340fb, 0x7449e56b, + 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 0x8c2e680f, 0xeb3d799f, + 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, 0xe369735d, + 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, + 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, + 0x8999220b, 0x27fb47b9 +} + +local fptr = 4 +local rptr = 1 +local state = 1 +local rand_type = 3 +local rand_deg = 31 +local rand_sep = 3 +local end_ptr = 32 + +local function rrandom() + local i + if rand_type == 0 then + -- 1103515245 = 129749 * 8505 + rntb[state] = (((((rntb[state] * 129749) % 0x80000000) * 8505) + 12345)) % 0x80000000 + i = rntb[state] + else + rntb[fptr] = (rntb[fptr] + rntb[rptr]) % 0x100000000 + i = g.int_div(rntb[fptr], 2) % 0x80000000 + fptr = fptr + 1 + if fptr >= end_ptr then + fptr = state + rptr = rptr + 1 + else + rptr = rptr + 1 + if rptr >= end_ptr then + rptr = state + end + end + end + return i +end + +function g.srrandom(x) + rntb[state] = x + if rand_type ~= 0 then + for i = 1, rand_deg-1 do + -- 1103515245 = 129749 * 8505 + rntb[state + i] = ((((rntb[state + i - 1] * 129749) % 0x100000000) * 8505) + 12345) % 0x100000000 + end + fptr = state + rand_sep + rptr = state + for i = 0, (10 * rand_deg)-1 do + rrandom() + end + end +end + +function g.get_rand(x, y) + if x > y then + x, y = y, x + end + local lr = rrandom() + lr = lr % 0x00008000 + local r = lr + r = (r % ((y - x) + 1)) + x + return r +end + +function g.rand_percent(percentage) + return g.get_rand(1, 100) <= percentage +end + +function g.coin_toss() + if (rrandom() % 2) == 0 then + return false + else + return true + end +end + + +--[[ +function g.srrandom(x) + math.randomseed(x) +end + + +function g.get_rand(x, y) + if x > y then + x, y = y, x + end + return math.random(x, y) +end + + +function g.rand_percent(percentage) + return g.get_rand(1, 100) <= percentage +end + +function g.coin_toss() + if (g.get_rand(0, 1) % 2) == 0 then + return false + else + return true + end +end +--]] diff --git a/autoload/rogue/ring.lua b/autoload/rogue/ring.lua new file mode 100644 index 0000000..7c92512 --- /dev/null +++ b/autoload/rogue/ring.lua @@ -0,0 +1,243 @@ +local g = Rogue -- alias + +local left_or_right +local no_ring + +g.stealthy = 0 +g.r_rings = 0 +g.add_strength = 0 +g.e_rings = 0 +g.regeneration = 0 +g.ring_exp = 0 +g.auto_search = 0 + +g.r_teleport = false +g.r_see_invisible = false +g.sustain_strength = false +g.maintain_armor = false + +function g.init_ring() + left_or_right = g.mesg[158] + no_ring = g.mesg[159] +end + +function g.put_on_ring() + if g.r_rings == 2 then + g.message(g.mesg[160]) + return + end + local ch = g.pack_letter(g.mesg[161], g.RING) + if ch == g.CANCEL then + return + end + local ring = g.get_letter_object(ch) + if not ring then + g.message(g.mesg[162]) + return + end + if ring.what_is ~= g.RING then + g.message(g.mesg[163]) + return + end + if g.ON_EITHER_HAND(ring.in_use_flags) then + g.message(g.mesg[164]) + return + end + if g.r_rings == 1 then + ch = g.rogue.left_ring and 'r' or 'l' + else + g.message(left_or_right) + repeat + ch = g.rgetchar() + if ch == 'L' then + ch = 'l' + elseif ch == 'R' then + ch = 'r' + end + until ch == g.CANCEL or ch == 'l' or ch == 'r' or ch == 'ENTER' + end + if ch ~= 'l' and ch ~= 'r' then + g.check_message() + return + end + if ((ch == 'l') and g.rogue.left_ring) or ((ch == 'r') and g.rogue.right_ring) then + g.check_message() + g.message(g.mesg[165]) + return + end + g.do_put_on(ring, (ch == 'l' and true or false)) + g.ring_stats(true) + g.check_message() + g.message(g.get_desc(ring, true)) + g.reg_move() +end + +-- Do not call ring_stats() from within do_put_on(). It will cause +-- serious problems when do_put_on() is called from read_pack() in restore(). +function g.do_put_on(ring, on_left) + if on_left then + ring.in_use_flags = g.ON_LEFT_HAND + g.rogue.left_ring = ring + else + ring.in_use_flags = g.ON_RIGHT_HAND + g.rogue.right_ring = ring + end +end + +function g.remove_ring() + local left = false + local right = false + + if g.r_rings == 0 then + g.inv_rings() + elseif g.rogue.left_ring and not g.rogue.right_ring then + left = true + elseif not g.rogue.left_ring and g.rogue.right_ring then + right = true + else + local ch + g.message(left_or_right) + repeat + ch = g.rgetchar() + if ch == 'L' then + ch = 'l' + elseif ch == 'R' then + ch = 'r' + end + until ch == g.CANCEL or ch == 'l' or ch == 'r' or ch == 'ENTER' + left = (ch == 'l') + right = (ch == 'r') + g.check_message() + end + if left or right then + local ring + if left and g.rogue.left_ring then + ring = g.rogue.left_ring + elseif right and g.rogue.right_ring then + ring = g.rogue.right_ring + else + g.message(no_ring) + end + if ring.is_cursed then + g.message(g.curse_message) + else + g.un_put_on(ring) + local buf + if g.JAPAN then + buf = g.get_desc(ring, false) .. g.mesg[166] + else + buf = g.mesg[166] .. g.get_desc(ring, false) + end + g.message(buf) + g.reg_move() + end + end +end + +function g.un_put_on(ring) + if ring then + if ring.in_use_flags == g.ON_LEFT_HAND then + ring.in_use_flags = g.NOT_USED + g.rogue.left_ring = nil + elseif ring.in_use_flags == g.ON_RIGHT_HAND then + ring.in_use_flags = g.NOT_USED + g.rogue.right_ring = nil + end + end + g.ring_stats(true) +end + +function g.gr_ring(ring, assign_wk) + ring.what_is = g.RING + if assign_wk then + ring.which_kind = g.get_rand(0, g.RINGS - 1) + ring.which_kind_ring = ring.which_kind + end + ring.class = 0 + + if ring.which_kind == g.R_TELEPORT then + ring.is_cursed = true + elseif ring.which_kind == g.ADD_STRENGTH or ring.which_kind == g.DEXTERITY then + repeat + ring.class = g.get_rand(0, 4) - 2 + until ring.class ~= 0 + ring.is_cursed = (ring.class < 0) + elseif ring.which_kind == g.ADORNMENT then + ring.is_cursed = g.coin_toss() + end +end + +function g.inv_rings() + if g.r_rings == 0 then + g.message(g.mesg[167]) + else + if g.rogue.left_ring then + g.message(g.get_desc(g.rogue.left_ring, true)) + end + if g.rogue.right_ring then + g.message(g.get_desc(g.rogue.right_ring, true)) + end + end + --[[ DEBUG + if g.wizard then + g.message(string.format( + "ste %d, r_r %d, e_r %d, r_t %d, s_s %d, a_s %d, reg %d, r_e %d, s_i %d, m_a %d, aus %d", + g.stealthy, g.r_rings, g.e_rings, g.r_teleport and 1 or 0, g.sustain_strength and 1 or 0, + g.add_strength, g.regeneration, g.ring_exp, g.r_see_invisible and 1 or 0, + g.maintain_armor and 1 or 0, g.auto_search)) + end + --]] +end + +function g.ring_stats(pr) + g.stealthy = 0 + g.r_rings = 0 + g.e_rings = 0 + g.r_teleport = false + g.sustain_strength = false + g.add_strength = 0 + g.regeneration = 0 + g.ring_exp = 0 + g.r_see_invisible = false + g.maintain_armor = false + g.auto_search = 0 + + for i = 0, 1 do + local ring + if i == 0 then + ring = g.rogue.left_ring + else + ring = g.rogue.right_ring + end + if ring then + g.r_rings = g.r_rings + 1 + g.e_rings = g.e_rings + 1 + if ring.which_kind == g.STEALTH then + g.stealthy = g.stealthy + 1 + elseif ring.which_kind == g.R_TELEPORT then + g.r_teleport = true + elseif ring.which_kind == g.REGENERATION then + g.regeneration = g.regeneration + 1 + elseif ring.which_kind == g.SLOW_DIGEST then + g.e_rings = g.e_rings - 2 + elseif ring.which_kind == g.ADD_STRENGTH then + g.add_strength = g.add_strength + ring.class + elseif ring.which_kind == g.SUSTAIN_STRENGTH then + g.sustain_strength = true + elseif ring.which_kind == g.DEXTERITY then + g.ring_exp = g.ring_exp + ring.class + elseif ring.which_kind == g.ADORNMENT then + elseif ring.which_kind == g.R_SEE_INVISIBLE then + g.r_see_invisible = true + elseif ring.which_kind == g.MAINTAIN_ARMOR then + g.maintain_armor = true + elseif ring.which_kind == g.SEARCHING then + g.auto_search = g.auto_search + 2 + end + end + end + if pr then + g.print_stats() + g.relight() + end +end diff --git a/autoload/rogue/rogue.vim b/autoload/rogue/rogue.vim new file mode 100644 index 0000000..6b7e15e --- /dev/null +++ b/autoload/rogue/rogue.vim @@ -0,0 +1,93 @@ + +let s:FILE_DIR = fnamemodify(expand(""), ':h') . '/' +let s:FILE_DIR = substitute(s:FILE_DIR, '\\', '/', 'g') +function! rogue#rogue#main(args) + if !has('lua') + echo "Sorry. Rogue.vim needs '+lua'." + return + endif + if a:args !=# '--resume' || luaeval('type(Rogue)') !=# 'table' + \|| luaeval('tostring(Rogue.suspended)') !=# 'true' + execute 'luafile ' . s:FILE_DIR . 'main.lua' + execute 'luafile ' . s:FILE_DIR . 'const.lua' + execute 'luafile ' . s:FILE_DIR . 'curses.lua' + execute 'luafile ' . s:FILE_DIR . 'debug.lua' + execute 'luafile ' . s:FILE_DIR . 'hit.lua' + execute 'luafile ' . s:FILE_DIR . 'init.lua' + execute 'luafile ' . s:FILE_DIR . 'invent.lua' + execute 'luafile ' . s:FILE_DIR . 'level.lua' + execute 'luafile ' . s:FILE_DIR . 'message.lua' + execute 'luafile ' . s:FILE_DIR . 'monster.lua' + execute 'luafile ' . s:FILE_DIR . 'move.lua' + execute 'luafile ' . s:FILE_DIR . 'object.lua' + execute 'luafile ' . s:FILE_DIR . 'pack.lua' + execute 'luafile ' . s:FILE_DIR . 'play.lua' + execute 'luafile ' . s:FILE_DIR . 'random.lua' + execute 'luafile ' . s:FILE_DIR . 'ring.lua' + execute 'luafile ' . s:FILE_DIR . 'room.lua' + execute 'luafile ' . s:FILE_DIR . 'save.lua' + execute 'luafile ' . s:FILE_DIR . 'score.lua' + execute 'luafile ' . s:FILE_DIR . 'spechit.lua' + execute 'luafile ' . s:FILE_DIR . 'throw.lua' + execute 'luafile ' . s:FILE_DIR . 'trap.lua' + execute 'luafile ' . s:FILE_DIR . 'use.lua' + execute 'luafile ' . s:FILE_DIR . 'util.lua' + execute 'luafile ' . s:FILE_DIR . 'zap.lua' + endif + + silent edit `='Rogue-clone II'` + silent only + nohlsearch + setl ts=8 et + setl nonumber + setl norelativenumber + setl nolist + setl buftype=nofile + setl noswapfile + setl bufhidden=wipe + setl nowrap + setl nocursorline + setl nocursorcolumn + setl foldcolumn=0 + setl conceallevel=3 + setl concealcursor=n + let save_cpo = &cpo + let s:save_encoding = &encoding + let save_ruler = &ruler + let save_showmode = &showmode + let save_showcmd = &showcmd + let save_showmatch = &showmatch + let save_cmdheight = &cmdheight + let save_laststatus = &laststatus + let save_more = &more + let save_guicursor = &guicursor + set cpo&vim + let &encoding = 'utf-8' + let &ruler = 0 + let &showmode = 0 + let &showcmd = 0 + let &showmatch = 0 + let &cmdheight = 1 + let &laststatus = 0 + let &more = 0 + let &guicursor = 'a:hor1-Ignore-blinkon0' + if (!exists("g:rogue#color") || g:rogue#color) + setl filetype=rogue + endif + + let s:args = a:args + execute 'lua Rogue.main()' + + let &cpo = save_cpo + let &encoding = s:save_encoding + let &ruler = save_ruler + let &showmode = save_showmode + let &showcmd = save_showcmd + let &showmatch = save_showmatch + let &cmdheight = save_cmdheight + let &laststatus = save_laststatus + let &more = save_more + let &guicursor = save_guicursor + bdelete +endfunction + diff --git a/autoload/rogue/room.lua b/autoload/rogue/room.lua new file mode 100644 index 0000000..e9713dc --- /dev/null +++ b/autoload/rogue/room.lua @@ -0,0 +1,417 @@ +local g = Rogue -- alias + +local Door = {} +function Door.new() + local dr = {} + dr.oth_room = g.NO_ROOM + dr.oth_row = 0 + dr.oth_col = 0 + dr.door_row = 0 + dr.door_col = 0 + return dr +end + +local Room = {} +function Room.new() + local rm = {} + rm.left_col = 0 + rm.top_row = 0 + rm.right_col = 0 + rm.bottom_row = 0 + rm.doors = {} + for i = 0, 3 do + rm.doors[i] = Door.new() + end + rm.is_room = g.R_NOTHING + rm.rooms_visited = false + return rm +end + +g.rooms = {} + +function g.init_room() + for i = 0, g.MAXROOMS-1 do + g.rooms[i] = Room.new() + end +end + +function g.light_up_room(rn) + if g.blind == 0 then + for i = g.rooms[rn].top_row, g.rooms[rn].bottom_row do + for j = g.rooms[rn].left_col, g.rooms[rn].right_col do + if g.dungeon[i][j][g.MONSTER] then + local monster = g.object_at(g.level_monsters, i, j) + if monster then + g.dungeon[monster.row][monster.col][g.MONSTER] = nil + monster.trail_char = + g.get_dungeon_char(monster.row, monster.col) + g.dungeon[monster.row][monster.col][g.MONSTER] = g.dungeon_desc[g.MONSTER] + end + end + g.mvaddch(i, j, g.get_dungeon_char(i, j)) + end + end + g.mvaddch(g.rogue.row, g.rogue.col, g.rogue.fchar) + end +end + +function g.light_passage(row, col) + if g.blind > 0 then + return + end + local i_end = (row < (g.DROWS-2)) and 1 or 0 + local j_end = (col < (g.DCOLS-1)) and 1 or 0 + + for i = ((row > g.MIN_ROW) and -1 or 0), i_end do + for j = ((col > 0) and -1 or 0), j_end do + if g.can_move(row, col, row+i, col+j) then + g.mvaddch(row+i, col+j, g.get_dungeon_char(row+i, col+j)) + end + end + end +end + +function g.darken_room(rn) + for i = g.rooms[rn].top_row + 1, g.rooms[rn].bottom_row-1 do + for j = g.rooms[rn].left_col + 1, g.rooms[rn].right_col-1 do + if g.blind > 0 then + g.mvaddch(i, j, ' ') + else + if not (g.dungeon[i][j][g.OBJECT] or g.dungeon[i][j][g.STAIRS]) and + not (g.detect_monster and g.dungeon[i][j][g.MONSTER]) then + if not g.imitating(i, j) then + g.mvaddch(i, j, ' ') + end + if g.dungeon[i][j][g.TRAP] and not g.dungeon[i][j][g.HIDDEN] then + g.mvaddch(i, j, '^') + end + end + end + end + end +end + +function g.get_dungeon_char(row, col) + local mask = g.dungeon[row][col] + + --[[ + if g.DEBUG then + if mask[g.HIDDEN] then + return 'h' + end + end + --]] + if mask[g.MONSTER] then + return g.gmc_row_col(row, col) + end + if mask[g.OBJECT] then + local obj = g.object_at(g.level_objects, row, col) + return g.get_mask_char(obj.what_is) + end + if mask[g.TUNNEL] or mask[g.STAIRS] or mask[g.HORWALL] or mask[g.VERTWALL] or + mask[g.FLOOR] or mask[g.DOOR] then + if (mask[g.TUNNEL] or mask[g.STAIRS]) and (not (mask[g.HIDDEN])) then + return mask[g.STAIRS] and '%' or '#' + end + if mask[g.HORWALL] then + return '-' + end + if mask[g.VERTWALL] then + return '|' + end + if mask[g.FLOOR] then + if mask[g.TRAP] then + if not g.dungeon[row][col][g.HIDDEN] then + return '^' + end + end + return '.' + end + if mask[g.DOOR] then + if mask[g.HIDDEN] then + if ((col > 0) and g.dungeon[row][col-1][g.HORWALL]) or + ((col < g.DCOLS-1) and g.dungeon[row][col+1][g.HORWALL]) then + return '-' + else + return '|' + end + else + return '+' + end + end + end + return ' ' +end + +function g.get_mask_char(mask) + if mask == g.SCROL then + return '?' + elseif mask == g.POTION then + return '!' + elseif mask == g.GOLD then + return '*' + elseif mask == g.FOOD then + return ':' + elseif mask == g.WAND then + return '/' + elseif mask == g.ARMOR then + return ']' + elseif mask == g.WEAPON then + return ')' + elseif mask == g.RING then + return '=' + elseif mask == g.AMULET then + return ',' + else + return '~' -- unknown, something is wrong + end +end + +local function check_mask(t, m, reverse_flag) + for k, v in pairs(t) do + if reverse_flag then + if not m[k] then + return true + end + else + if m[k] then + return true + end + end + end + return false +end + +function g.gr_row_col(mask) + local rn + local r + local c + + repeat + r = g.get_rand(g.MIN_ROW, g.DROWS-2) + c = g.get_rand(0, g.DCOLS-1) + rn = g.get_room_number(r, c) + until not ( + (rn == g.NO_ROOM) or + (not check_mask(g.dungeon[r][c], mask)) or + (check_mask(g.dungeon[r][c], mask, true)) or + (not (g.rooms[rn].is_room == g.R_ROOM or g.rooms[rn].is_room == g.R_MAZE)) or + (r == g.rogue.row and c == g.rogue.col) + ) + + return r, c +end + +function g.gr_room() + local i + repeat + i = g.get_rand(0, g.MAXROOMS-1) + until (g.rooms[i].is_room == g.R_ROOM or g.rooms[i].is_room == g.R_MAZE) + return i +end + +function g.party_objects(rn) + local nf = 0 + local N = ((g.rooms[rn].bottom_row - g.rooms[rn].top_row) - 1) * + ((g.rooms[rn].right_col - g.rooms[rn].left_col) - 1) + local n = g.get_rand(5, 10) + if n > N then + n = N - 2 + end + for i = 0, n-1 do + local row + local col + local found = false + local j = 0 + while (not found) and (j < 250) do + row = g.get_rand(g.rooms[rn].top_row+1, g.rooms[rn].bottom_row-1) + col = g.get_rand(g.rooms[rn].left_col+1, g.rooms[rn].right_col-1) + if g.dungeon[row][col][g.FLOOR] or g.dungeon[row][col][g.TUNNEL] then + found = true + end + + j = j + 1 + end + if found then + local obj = g.gr_object() + g.place_at(obj, row, col) + nf = nf + 1 + end + end + return nf +end + +function g.get_room_number(row, col) + for i = 0, g.MAXROOMS-1 do + if (row >= g.rooms[i].top_row and row <= g.rooms[i].bottom_row) and + (col >= g.rooms[i].left_col and col <= g.rooms[i].right_col) then + return i + end + end + return g.NO_ROOM +end + +local function visit_rooms(rn) + g.rooms[rn].rooms_visited = true + + for i = 0, 3 do + local oth_rn = g.rooms[rn].doors[i].oth_room + if (oth_rn >= 0) and (not g.rooms[oth_rn].rooms_visited) then + visit_rooms(oth_rn) + end + end +end + +function g.is_all_connected() + local starting_room = 0 + + for i = 0, g.MAXROOMS-1 do + g.rooms[i].rooms_visited = false + if g.rooms[i].is_room == g.R_ROOM or g.rooms[i].is_room == g.R_MAZE then + starting_room = i + end + end + + visit_rooms(starting_room) + + for i = 0, g.MAXROOMS-1 do + if (g.rooms[i].is_room == g.R_ROOM or g.rooms[i].is_room == g.R_MAZE) and + (not g.rooms[i].rooms_visited) then + return false + end + end + return true +end + +function g.draw_magic_map() + for i = 0, g.DROWS-1 do + for j = 0, g.DCOLS-1 do + local s = g.dungeon[i][j] + if s[g.HORWALL] or s[g.VERTWALL] or s[g.DOOR] or s[g.TUNNEL] or s[TRAP] or + s[g.STAIRS] or s[g.MONSTER] then + local ch = g.mvinch(i, j) + if ch == ' ' or ch:find('^[A-Z]$') or s[TRAP] or s[g.HIDDEN] then + local skip = false + local och = ch + g.dungeon[i][j][g.HIDDEN] = nil + if s[g.HORWALL] then + ch = '-' + elseif s[g.VERTWALL] then + ch = '|' + elseif s[g.DOOR] then + ch = '+' + elseif s[g.TRAP] then + ch = '^' + elseif s[g.STAIRS] then + ch = '%' + elseif s[g.TUNNEL] then + ch = '#' + else + skip = true + end + if not skip then + if (not s[g.MONSTER]) or (och == ' ') then + g.mvaddch(i, j, ch) + end + if s[g.MONSTER] then + local monster = g.object_at(g.level_monsters, i, j) + if monster then + monster.trail_char = ch + end + end + end + end + end + end + end +end + +local function get_oth_room(rn, row, col) + local d = -1 + if row == g.rooms[rn].top_row then + d = g.int_div(g.UPWARD, 2) + elseif row == g.rooms[rn].bottom_row then + d = g.int_div(g.DOWN, 2) + elseif col == g.rooms[rn].left_col then + d = g.int_div(g.LEFT, 2) + elseif col == g.rooms[rn].right_col then + d = g.int_div(g.RIGHT, 2) + end + if d ~= -1 and g.rooms[rn].doors[d].oth_room >= 0 then + row = g.rooms[rn].doors[d].oth_row + col = g.rooms[rn].doors[d].oth_col + return true, row, col + end + return false, row, col +end + +function g.dr_course(monster, entering, row, col) + monster.row = row + monster.col = col + + if g.mon_sees(monster, g.rogue.row, g.rogue.col) then + monster.trow = g.NO_ROOM + return + end + local rn = g.get_room_number(row, col) + + if entering then -- entering room + -- look for door to some other room + local r = g.get_rand(0, g.MAXROOMS-1) + for i = 0, g.MAXROOMS-1 do + local rr = (r + i) % g.MAXROOMS + if not (g.rooms[i].is_room == g.R_ROOM or g.rooms[i].is_room == g.R_MAZE) or + (rr == rn) then + else + for k = 0, 3 do + if g.rooms[rr].doors[k].oth_room == rn then + local continue_flag = false + monster.trow = g.rooms[rr].doors[k].oth_row + monster.tcol = g.rooms[rr].doors[k].oth_col + if monster.trow == row and monster.tcol == col then + continue_flag = true + end + if not continue_flag then + return + end + end + end + end + end + -- look for door to dead end + for i = g.rooms[rn].top_row, g.rooms[rn].bottom_row do + for j = g.rooms[rn].left_col, g.rooms[rn].right_col do + if i ~= monster.row and j ~= monster.col and + g.dungeon[i][j][g.DOOR] then + monster.trow = i + monster.tcol = j + return + end + end + end + -- return monster to room that he came from + for i = 0, g.MAXROOMS-1 do + for j = 0, 3 do + if g.rooms[i].doors[j].oth_room == rn then + for k = 0, 3 do + if g.rooms[rn].doors[k].oth_room == i then + monster.trow = g.rooms[rn].doors[k].oth_row + monster.tcol = g.rooms[rn].doors[k].oth_col + return + end + end + end + end + end + -- no place to send monster + monster.trow = -1 + else -- exiting room + local ret, row, col = get_oth_room(rn, row, col) + if not ret then + monster.trow = g.NO_ROOM + else + monster.trow = row + monster.tcol = col + end + end +end diff --git a/autoload/rogue/save.lua b/autoload/rogue/save.lua new file mode 100644 index 0000000..f10f3fd --- /dev/null +++ b/autoload/rogue/save.lua @@ -0,0 +1,165 @@ +local g = Rogue -- alias + +g.save_file = 'rogue_vim.save' + +local function save_into_file(fname) + fname = g.expand_fname(fname, g.game_dir) + local fp = io.open(fname, "w") + if not fp then + g.message(g.mesg[503]) + return + end + + local Rogue_copy = {} + + Rogue_copy.cur_level = g.cur_level + Rogue_copy.max_level = g.max_level + Rogue_copy.hunger_str = g.hunger_str + Rogue_copy.nick_name = g.nick_name + Rogue_copy.home_dir = g.home_dir + Rogue_copy.party_room = g.party_room + Rogue_copy.party_counter = g.party_counter + Rogue_copy.level_monsters = g.level_monsters + Rogue_copy.level_objects = g.level_objects + Rogue_copy.dungeon = g.dungeon + Rogue_copy.foods = g.foods + Rogue_copy.id_potions = g.id_potions + Rogue_copy.id_scrolls = g.id_scrolls + Rogue_copy.id_wands = g.id_wands + Rogue_copy.id_rings = g.id_rings + Rogue_copy.traps = g.traps + Rogue_copy.is_wood = g.is_wood + Rogue_copy.cur_room = g.cur_room + Rogue_copy.rooms = g.rooms + Rogue_copy.being_held = g.being_held + Rogue_copy.bear_trap = g.bear_trap + Rogue_copy.halluc = g.halluc + Rogue_copy.blind = g.blind + Rogue_copy.confused = g.confused + Rogue_copy.levitate = g.levitate + Rogue_copy.haste_self = g.haste_self + Rogue_copy.see_invisible = g.see_invisible + Rogue_copy.detect_monster = g.detect_monster + Rogue_copy.wizard = g.wizard + Rogue_copy.score_only = g.score_only + Rogue_copy.m_moves = g.m_moves + + Rogue_copy.saved_time = os.time() + 10 + Rogue_copy.dungeon_concat = g.dungeon_buffer_concat() + + Rogue_copy.rogue = {} + for k, v in pairs(g.rogue) do + Rogue_copy.rogue[k] = v + end + Rogue_copy.rogue.armor = nil + Rogue_copy.rogue.weapon = nil + Rogue_copy.rogue.left_ring = nil + Rogue_copy.rogue.right_ring = nil + + local buf = g.dump(Rogue_copy) + -- easy compression + buf = buf:gsub('\n *', '') + :gsub(' = ({)', '=%1') + :gsub(' = (")', '=%1') + :gsub(' = (%-?%d)', '=%1') + :gsub(' = (true)', '=%1') + :gsub(' = (false)', '=%1') + :gsub('"NOTHING"', '1') + :gsub('"OBJECT"', '1') + :gsub('"MONSTER"', '1') + :gsub('"STAIRS"', '1') + :gsub('"HORWALL"', '1') + :gsub('"VERTWALL"', '1') + :gsub('"DOOR"', '1') + :gsub('"FLOOR"', '1') + :gsub('"TUNNEL"', '1') + :gsub('"TRAP"', '1') + :gsub('"HIDDEN"', '1') + buf = g.iconv_to_utf8(buf) + + g.xxx(true) + buf = g.xxxx(buf) + local ret = fp:write(buf) + fp:close() + if not ret then + g.message(g.mesg[512]) + return + end + + g.exit() +end + +function g.save_game() + local fname = g.get_input_line(g.mesg[501], g.save_file, g.mesg[502], false, true) + if fname == '' then + return + end + g.check_message() + g.message(fname) + save_into_file(fname) +end + +function g.restore(fname) + fname = g.expand_fname(fname, g.game_dir) + local fp = io.open(fname, "r") + if not fp then + g.message(g.mesg[504]) + return false + end + + local buf = fp:read("*a") + fp:close() + if not buf then + g.message(g.mesg[511]) + return false + end + g.xxx(true) + buf = g.xxxx(buf) + buf = g.iconv_from_utf8(buf) + local Rogue_copy = assert(g.loadstring('return ' .. buf), g.mesg[508])() + + if g.home_dir ~= Rogue_copy.home_dir then + g.message(g.mesg[506]) + return false + end + + local saved_time = Rogue_copy.saved_time + Rogue_copy.saved_time = nil + if saved_time < g.getftime(fname) then + g.message(g.mesg[509]) + return false + end + + if not Rogue_copy.wizard then + local ret = os.remove(fname) + if not ret then + g.message(g.mesg[510]) + return false + end + end + + -- restore Rogue + g.dungeon_buffer_restore(Rogue_copy.dungeon_concat) + Rogue_copy.dungeon_concat = nil + for k, v in pairs(Rogue_copy) do + g[k] = v + end + + local obj = g.rogue.pack.next_object + while obj do + if obj.in_use_flags == g.BEING_WORN then + g.do_wear(obj) + elseif obj.in_use_flags == g.BEING_WIELDED then + g.do_wield(obj) + elseif obj.in_use_flags == g.ON_LEFT_HAND then + g.do_put_on(obj, true) + elseif obj.in_use_flags == g.ON_RIGHT_HAND then + g.do_put_on(obj, false) + end + obj = obj.next_object + end + g.msg_cleared = false + g.ring_stats(false) + g.print_stats(true) + return true +end diff --git a/autoload/rogue/score.lua b/autoload/rogue/score.lua new file mode 100644 index 0000000..5128445 --- /dev/null +++ b/autoload/rogue/score.lua @@ -0,0 +1,421 @@ +local g = Rogue -- alias + +local score_file = 'rogue_vim.scores' + +local xxx_f = 0 +local xxx_s = 0 + +local function center_margin(buf) + return g.int_div((g.DCOLS - g.strwidth(buf:gsub('%(%w%(', ''))), 2) +end + +local function center(row, buf) + g.mvaddstr(row, center_margin(buf), buf) +end + +local function layer(lower, lcol, upper, ucol) + local s1 = lower:sub(1, ucol - lcol) + local s2 = lower:sub(ucol - lcol + 1 + g.strwidth(upper:gsub('%(%w%(', ''))) + return s1 .. upper .. s2 +end + +local function tomb_str(str, xpos, idx, upper) + if upper then + local ucol = center_margin(upper) + str[idx] = layer(str[idx], xpos[idx], upper, ucol) + end + local count = 0 + str[idx], count = str[idx]:gsub('^(%-+)$', '(g(%1(g(') + if count > 0 then + return + end + str[idx], count = str[idx]:gsub('^(_.*_)$', '(g(%1(g(') + if count > 0 then + return + end + str[idx] = str[idx]:gsub('^/', '(g(/(g(') + :gsub('\\\\$', '(g(\\\\(g(') + :gsub('%|', '(g(|(g(') + :gsub('%*', '(y(*(y(') +end + +local function is_vowel(ch) + local c = string.char(ch:byte(1)) + return (c == 'a') or + (c == 'e') or + (c == 'i') or + (c == 'o') or + (c == 'u') +end + +function g.killed_by(monster, other) + local xpos = { + g.int_div(g.DCOLS, 2)-5, + g.int_div(g.DCOLS, 2)-6, + g.int_div(g.DCOLS, 2)-7, + g.int_div(g.DCOLS, 2)-8, + g.int_div(g.DCOLS, 2)-9, + g.int_div(g.DCOLS, 2)-10, + g.int_div(g.DCOLS, 2)-10, + g.int_div(g.DCOLS, 2)-10, + g.int_div(g.DCOLS, 2)-10, + g.int_div(g.DCOLS, 2)-10, + g.int_div(g.DCOLS, 2)-10, + g.int_div(g.DCOLS, 2)-10, + g.int_div(g.DCOLS, 2)-11, + g.int_div(g.DCOLS, 2)-19, + } + local str = { + '----------', + '/ \\\\', + '/ \\\\', + '/ \\\\', + '/ \\\\', + '/ \\\\', + '| |', + '| |', + '| |', + '| |', + '| |', + '| |', + '*| * * * | *', + '________)/\\\\\\\\_//(\\\\/(/\\\\)/\\\\//\\\\/|_)_______' + } + local os1 + local os2 + os1 = { [0] = "", g.mesg[168], g.mesg[169], g.mesg[170], g.mesg[171] } + os2 = { [0] = "", g.mesg[172], g.mesg[173], g.mesg[174], g.mesg[175] } + + if other ~= g.QUIT then + g.rogue.gold = g.int_div((g.rogue.gold * 9), 10) + end + local buf, buf2 + if other ~= 0 then + buf = os1[other] + buf2 = os2[other] + else + if g.JAPAN then + buf = monster.m_name + buf2 = g.mesg[176] + else + buf = g.mesg[176] + buf2 = monster.m_name + if g.English and is_vowel(buf2) then + -- "an" of vowel + buf = buf .. 'n' + end + end + end + if g.show_skull and other ~= g.QUIT then + g.clear() + local inscribed_words + if g.JAPAN then + inscribed_words = { + [4] = '(y(' .. g.mesg[177] .. '(y(', + [5] = '(y(' .. g.mesg[178] .. '(y(', + [7] = g.nick_name, + [8] = g.mesg[180] .. g.znum(g.rogue.gold), + [10] = buf, + [11] = buf2, + [12] = g.znum(tonumber(os.date('%Y'))), + } + else + inscribed_words = { + [4] = '(y(' .. g.mesg[177] .. '(y(', + [5] = '(y(' .. g.mesg[178] .. '(y(', + [6] = '(y(' .. g.mesg[179] .. '(y(', + [8] = g.nick_name, + [9] = string.format(g.mesg[180]:gsub("%%ld", "%%d"), g.rogue.gold), + [10] = buf, + [11] = buf2, + [12] = os.date('%Y'), + } + end + for i = 1, #str do + tomb_str(str, xpos, i, inscribed_words[i]) + g.mvaddstr(i+3-1, xpos[i], str[i]) + end + + g.check_message() + g.message('') + else + if g.JAPAN then + buf = buf .. buf2 + buf = buf .. g.mesg[181] + buf = buf .. g.znum(g.rogue.gold) + buf = buf .. g.mesg[496] + else + buf = buf .. buf2 + buf = buf .. string.format(g.mesg[181]:gsub("%%ld", "%%d"), g.rogue.gold) + end + g.message(buf) + end + g.message('') + g.put_scores(monster, other) +end + +local function mvaddbanner(row, col, ban) + ban = ban:gsub('(#+)', '(G(%1(G(') + g.mvaddstr(row, col, ban) +end + +local function id_all() + for i = 0, g.SCROLS-1 do + g.id_scrolls[i].id_status = g.IDENTIFIED + end + for i = 0, g.WEAPONS-1 do + g.id_weapons[i].id_status = g.IDENTIFIED + end + for i = 0, g.ARMORS-1 do + g.id_armors[i].id_status = g.IDENTIFIED + end + for i = 0, g.WANDS-1 do + g.id_wands[i].id_status = g.IDENTIFIED + end + for i = 0, g.POTIONS-1 do + g.id_potions[i].id_status = g.IDENTIFIED + end +end + +local function get_value(obj) + local wc = obj.which_kind + local what_is = obj.what_is + local val + if what_is == g.WEAPON then + val = g.id_weapons[wc].value + if (wc == g.ARROW) or (wc == g.DAGGER) or (wc == g.SHURIKEN) or (wc == g.DART) then + val = val * obj.quantity + end + val = val + (obj.d_enchant * 85) + (obj.hit_enchant * 85) + elseif what_is == g.ARMOR then + val = g.id_armors[wc].value + (obj.d_enchant * 75) + if obj.is_protected then + val = val + 200 + end + elseif what_is == g.WAND then + val = g.id_wands[wc].value * (obj.class + 1) + elseif what_is == g.SCROL then + val = g.id_scrolls[wc].value * obj.quantity + elseif what_is == g.POTION then + val = g.id_potions[wc].value * obj.quantity + elseif what_is == g.AMULET then + val = 5000 + elseif what_is == g.RING then + val = g.id_rings[wc].value * (obj.class + 1) + end + if val <= 0 then + val = 10 + end + return val +end + +local function sell_pack() + local row = 2 + local obj = g.rogue.pack.next_object + g.clear() + g.mvaddstr(1, 0, g.mesg[198]) + + while obj do + if obj.what_is ~= g.FOOD then + obj.identified = true + local val = get_value(obj) + g.rogue.gold = g.rogue.gold + val + + if row < g.DROWS then + g.mvaddstr(row, 0, string.format("%5d %s", val, g.get_desc(obj, true))) + row = row + 1 + end + end + obj = obj.next_object + end + g.refresh() + if g.rogue.gold > g.MAX_GOLD then + g.rogue.gold = g.MAX_GOLD + end + g.message('') +end + +function g.win() + g.unwield(g.rogue.weapon) -- disarm and relax + g.unwear(g.rogue.armor) + g.un_put_on(g.rogue.left_ring) + g.un_put_on(g.rogue.right_ring) + + g.clear() + local ban = { + '# # # # # ### # # ', + '# # ## ## # # # # ', + '# # ### # # # # # ### #### ### # ### # ', + ' #### # # # # # # # # # # # # # # ', + ' # # # # # # # #### # # ##### # # # ', + '# # # # # ## # # # # # # # # # # ', + ' ### ### ## # # # #### #### ### ### ## # ', + } + for i = 1, 7 do + mvaddbanner(i+5, g.DCOLS/2-30, ban[i]) + end + center(15, '(y(' .. g.mesg[182] .. '(y(') + center(16, '(y(' .. g.mesg[183] .. '(y(') + center(17, '(y(' .. g.mesg[184] .. '(y(') + center(18, '(y(' .. g.mesg[185] .. '(y(') + + g.message('') + g.message('') + id_all() + sell_pack() + g.put_scores(nil, g.WIN) +end + +function g.quit(from_intrpt) + g.check_message() + g.message(g.mesg[495], true) + if g.rgetchar() ~= 'y' then + g.check_message() + return + end + g.check_message() + if from_intrpt then + g.message(g.mesg[12], true) + end + g.killed_by(nil, g.QUIT) + -- NOTREACHED +end + +local function sf_error() + g.message('', true) + g.message(g.mesg[199]) +end + +local function score_line(monster, other) + local buf = string.format(" %6d %s: ", g.rogue.gold, g.nick_name) + if g.JAPAN then + if other ~= g.WIN then + if g.has_amulet() then + buf = buf .. g.mesg[189] + end + buf = buf .. g.mesg[190] + .. g.znum(g.cur_level) + .. g.mesg[191] + end + end + if monster then + if g.JAPAN then + buf = buf .. monster.m_name + .. g.mesg[197] + else + buf = buf .. g.mesg[197] + if is_vowel(monster.m_name) then + buf = buf .. 'an ' + .. monster.m_name + else + buf = buf .. 'a ' + .. monster.m_name + end + end + elseif other == g.HYPOTHERMIA then + buf = buf .. g.mesg[192] + elseif other == g.STARVATION then + buf = buf .. g.mesg[193] + elseif other == g.POISON_DART then + buf = buf .. g.mesg[194] + elseif other == g.QUIT then + buf = buf .. g.mesg[195] + elseif other == g.WIN then + buf = buf .. g.mesg[196] + end + if g.JAPAN then + buf = buf .. g.mesg[496] + else + buf = buf .. string.format(g.mesg[190], g.cur_level) + if other ~= g.WIN and g.has_amulet() then + buf = buf .. g.mesg[189] + end + end + buf = buf .. string.rep(' ', g.DCOLS - 4 - g.strwidth(buf)) + return buf +end + +function g.put_scores(monster, other) + local scores = {} + local file = g.game_dir .. score_file + local fp = io.open(file, "r") + if fp then + local buf = fp:read("*a") + g.xxx(true) + buf = g.xxxx(buf) + buf = g.iconv_from_utf8(buf) + scores = assert(g.loadstring('return ' .. buf), g.mesg[199])() + fp:close() + end + + local MAX_RANK = 10 + local rank = #scores + 1 + if g.score_only then + rank = MAX_RANK + 1 + else + for i = 1, #scores do + if g.rogue.gold > scores[i].score then + rank = i + break + end + end + end + + if rank <= MAX_RANK then + fp = io.open(file, "w") + if not fp then + g.message(g.mesg[186]) + sf_error() + g.exit() + end + table.insert(scores, rank, + {score = g.rogue.gold, line = score_line(monster, other)}) + if #scores > MAX_RANK then + table.remove(scores) + end + local buf = g.dump(scores) + buf = g.iconv_to_utf8(buf) + g.xxx(true) + buf = g.xxxx(buf) + fp:write(buf) + fp:close() + end + + g.clear() + g.mvaddstr(3, (g.JAPAN and 20 or 25), '(y(' .. g.mesg[187] .. '(y(') + g.mvaddstr(6, 0, '(g(' .. g.mesg[188] .. '(g(') + + for i = 1, #scores do + local c = '' + if rank == i then + c = '(C(' + end + g.mvaddstr(i + 7, 0, c .. string.format(" %2d", i) .. scores[i].line .. c) + end + g.refresh() + g.message('') + g.exit() +end + +function g.xxxx(buf) + local ret = '' + for i = 1, #buf do + local c = g.xxx(false) + local x = g.bxor(buf:byte(i), c) + x = x % 0x100 + ret = ret .. string.char(x) + end + return ret +end + +function g.xxx(st) + if st then + xxx_f = 37 + xxx_s = 7 + return 0 + end + local r = ((xxx_f * xxx_s) + 9337) % 8887 + xxx_f = xxx_s + xxx_s = r + return r +end diff --git a/autoload/rogue/spechit.lua b/autoload/rogue/spechit.lua new file mode 100644 index 0000000..3f75681 --- /dev/null +++ b/autoload/rogue/spechit.lua @@ -0,0 +1,444 @@ +local g = Rogue -- alias + +g.less_hp = 0 +local flame_name +g.being_held = false + +function g.init_spechit() + flame_name = g.mesg[200] +end + +local function freeze(monster) + local freeze_percent = 99 + if g.rand_percent(12) then + return + end + freeze_percent = freeze_percent - (g.rogue.str_current + g.int_div(g.rogue.str_current, 2)) + freeze_percent = freeze_percent - ((g.rogue.exp + g.ring_exp) * 4) + freeze_percent = freeze_percent - (g.get_armor_class(g.rogue.armor) * 5) + freeze_percent = freeze_percent - g.int_div(g.rogue.hp_max, 3) + + if freeze_percent > 10 then + monster.m_flags[g.FREEZING_ROGUE] = g.m_flags_desc[g.FREEZING_ROGUE] + g.message(g.mesg[203], true) + local n = g.get_rand(4, 8) + for i = 1, n do + g.mv_mons() + end + if g.rand_percent(freeze_percent) then + for i = 1, 50 do + g.mv_mons() + end + g.killed_by(nil, g.HYPOTHERMIA) + -- NOTREACHED + end + g.message(g.you_can_move_again, true) + monster.m_flags[g.FREEZING_ROGUE] = nil + end +end + +local function disappear(monster) + local row = monster.row + local col = monster.col + + g.dungeon[row][col][g.MONSTER] = nil + if g.rogue_can_see(row, col) then + g.mvaddch(row, col, g.get_dungeon_char(row, col)) + end + g.take_from_pack(monster, g.level_monsters) + g.free_object(monster) + g.mon_disappeared = true +end + +local function steal_gold(monster) + if g.rogue.gold <= 0 or g.rand_percent(10) then + return + end + local amount = g.get_rand((g.cur_level * 10), (g.cur_level * 30)) + if amount > g.rogue.gold then + amount = g.rogue.gold + end + g.rogue.gold = g.rogue.gold - amount + g.message(g.mesg[204]) + g.print_stats() + disappear(monster) +end + +local function steal_item(monster) + if g.rand_percent(15) then + return + end + local obj = g.rogue.pack.next_object + if not obj then + -- goto DSPR + disappear(monster) + return + end + local goto_adornment_flag = false + while obj do + if obj.what_is == g.RING and + obj.which_kind == g.ADORNMENT and + g.ON_EITHER_HAND(obj.in_use_flags) and + not obj.is_cursed then + g.un_put_on(obj) + -- goto adornment + goto_adornment_flag = true + break + end + obj = obj.next_object + end + if not goto_adornment_flag then + local has_something = false + obj = g.rogue.pack.next_object + while obj do + if not g.BEING_USED(obj.in_use_flags) then + has_something = true + break + end + obj = obj.next_object + end + if not has_something then + -- goto DSPR + disappear(monster) + return + end + + local n = g.get_rand(0, g.MAX_PACK_COUNT) + obj = g.rogue.pack.next_object + for i = 0, n do + obj = obj.next_object + while not obj or g.BEING_USED(obj.in_use_flags) do + if not obj then + obj = g.rogue.pack.next_object + else + obj = obj.next_object + end + end + end + end + -- ::adornment:: + local desc = '' + if not g.JAPAN then + desc = g.mesg[205] + end + local t = 0 + if obj.what_is ~= g.WEAPON then + t = obj.quantity + obj.quantity = 1 + end + if g.JAPAN then + desc = g.get_desc(obj, false) .. g.mesg[205] + else + desc = desc .. g.get_desc(obj, false) + end + g.message(desc) + obj.quantity = (obj.what_is ~= g.WEAPON and t or 1) + g.vanish(obj, false, g.rogue.pack) + -- ::DSPR:: + disappear(monster) +end + +local function sting(monster) + if g.rogue.str_current <= 3 or g.sustain_strength then + return + end + local sting_chance = 35 + sting_chance = sting_chance + (6 * (6 - g.get_armor_class(g.rogue.armor))) + if g.rogue.exp + g.ring_exp > 8 then + sting_chance = sting_chance - (6 * ((g.rogue.exp + g.ring_exp) - 8)) + end + if g.rand_percent(sting_chance) then + g.message(string.format(g.mesg[207], g.mon_name(monster))) + g.rogue.str_current = g.rogue.str_current - 1 + g.print_stats() + end +end + +local function drop_level() + if g.rand_percent(80) or g.rogue.exp <= 5 then + return + end + g.rogue.exp_points = g.level_points[g.rogue.exp-2] - g.get_rand(9, 29) + g.rogue.exp = g.rogue.exp - 2 + local hp = g.hp_raise() + g.rogue.hp_current = g.rogue.hp_current - hp + if g.rogue.hp_current <= 0 then + g.rogue.hp_current = 1 + end + g.rogue.hp_max = g.rogue.hp_max - hp + if g.rogue.hp_max <= 0 then + g.rogue.hp_max = 1 + end + g.add_exp(1, false) +end + +local function drain_life() + if g.rand_percent(60) or g.rogue.hp_max <= 30 or g.rogue.hp_current < 10 then + return + end + local n = g.get_rand(1, 3) -- 1 Hp, 2 Str, 3 both + if n ~= 2 or not g.sustain_strength then + g.message(g.mesg[208]) + end + if n ~= 2 then + g.rogue.hp_max = g.rogue.hp_max - 1 + g.rogue.hp_current = g.rogue.hp_current - 1 + g.less_hp = g.less_hp + 1 + end + if n ~= 1 then + if g.rogue.str_current > 3 and not g.sustain_strength then + g.rogue.str_current = g.rogue.str_current - 1 + if g.coin_toss() then + g.rogue.str_max = g.rogue.str_max - 1 + end + end + end + g.print_stats() +end + +function g.special_hit(monster) + if monster.m_flags[g.CONFUSED] and g.rand_percent(66) then + return + end + if monster.m_flags[g.RUSTS] then + g.rust(monster) + end + if monster.m_flags[g.HOLDS] and g.levitate == 0 then + g.being_held = true + end + if monster.m_flags[g.FREEZES] then + freeze(monster) + end + if monster.m_flags[g.STINGS] then + sting(monster) + end + if monster.m_flags[g.DRAINS_LIFE] then + drain_life() + end + if monster.m_flags[g.DROPS_LEVEL] then + drop_level() + end + if monster.m_flags[g.STEALS_GOLD] then + steal_gold(monster) + elseif monster.m_flags[g.STEALS_ITEM] then + steal_item(monster) + end +end + +function g.rust(monster) + if not g.rogue.armor or (g.get_armor_class(g.rogue.armor) <= 1) or + g.rogue.armor.which_kind == g.LEATHER then + return + end + if g.rogue.armor.is_protected or g.maintain_armor then + if monster and not monster.m_flags[g.RUST_VANISHED] then + g.message(g.mesg[201]) + monster.m_flags[g.RUST_VANISHED] = g.m_flags_desc[g.RUST_VANISHED] + end + else + g.rogue.armor.d_enchant = g.rogue.armor.d_enchant - 1 + g.message(g.mesg[202]) + g.print_stats() + end +end + +local function try_to_cough(row, col, obj) + if (row < g.MIN_ROW) or (row > (g.DROWS-2)) or (col < 0) or (col>(g.DCOLS-1)) then + return false + end + local d = g.dungeon[row][col] + if not (d[g.OBJECT] or d[g.STAIRS] or d[g.TRAP]) and + (d[g.TUNNEL] or d[g.FLOOR] or d[g.DOOR]) then + g.place_at(obj, row, col) + if ((row ~= g.rogue.row) or (col ~= g.rogue.col)) and + (not d[g.MONSTER]) then + g.mvaddch(row, col, g.get_dungeon_char(row, col)) + end + return true + end + return false +end + +function g.cough_up(monster) + local obj + if g.cur_level < g.max_level then + return + end + if monster.m_flags[g.STEALS_GOLD] then + obj = g.alloc_object() + obj.what_is = g.GOLD + obj.quantity = g.get_rand((g.cur_level * 15), (g.cur_level * 30)) + else + if not g.rand_percent(monster.drop_percent) then + return + end + obj = g.gr_object() + end + local row = monster.row + local col = monster.col + + for n = 0, 5 do + local i + i = -n + while i <= n do + if try_to_cough(row+n, col+i, obj) then + return + end + if try_to_cough(row-n, col+i, obj) then + return + end + i = i + 1 + end + i = -n + while i <= n do + if try_to_cough(row+i, col-n, obj) then + return + end + if try_to_cough(row+i, col+n, obj) then + return + end + i = i + 1 + end + end + g.free_object(obj) +end + +local function gold_at(row, col) + if g.dungeon[row][col][g.OBJECT] then + local obj = g.object_at(g.level_objects, row, col) + if obj and obj.what_is == g.GOLD then + return true + end + end + return false +end + +function g.seek_gold(monster) + local rn = g.get_room_number(monster.row, monster.col) + if rn < 0 then + return false + end + for i = g.rooms[rn].top_row+1, g.rooms[rn].bottom_row-1 do + for j = g.rooms[rn].left_col+1, g.rooms[rn].right_col-1 do + if gold_at(i, j) and not g.dungeon[i][j][g.MONSTER] then + monster.m_flags[g.CAN_FLIT] = g.m_flags_desc[g.CAN_FLIT] + local s = g.mon_can_go(monster, i, j) + monster.m_flags[g.CAN_FLIT] = nil + if s then + g.move_mon_to(monster, i, j) + monster.m_flags[g.ASLEEP] = g.m_flags_desc[g.ASLEEP] + monster.m_flags[g.WAKENS] = nil + monster.m_flags[g.SEEKS_GOLD] = nil + return true + end + monster.m_flags[g.SEEKS_GOLD] = nil + monster.m_flags[g.CAN_FLIT] = g.m_flags_desc[g.CAN_FLIT] + g.mv_monster(monster, i, j) + monster.m_flags[g.CAN_FLIT] = nil + monster.m_flags[g.SEEKS_GOLD] = g.m_flags_desc[g.SEEKS_GOLD] + return true + end + end + end + return false +end + +function g.check_gold_seeker(monster) + monster.m_flags[g.SEEKS_GOLD] = nil +end + +function g.check_imitator(monster) + if monster.m_flags[g.IMITATES] then + g.wake_up(monster) + if g.blind > 0 then + g.mvaddch(monster.row, monster.col, + g.get_dungeon_char(monster.row, monster.col)) + g.check_message() + g.message(string.format(g.mesg[206], g.mon_name(monster))) + end + return true + end + return false +end + +function g.imitating(row, col) + if g.dungeon[row][col][g.MONSTER] then + local monster = g.object_at(g.level_monsters, row, col) + if monster then + if monster.m_flags[g.IMITATES] then + return true + end + end + end + return false +end + +function g.m_confuse(monster) + if not g.rogue_can_see(monster.row, monster.col) then + return false + end + if g.rand_percent(45) then + monster.m_flags[g.CONFUSES] = nil -- will not confuse the rogue + return false + end + if g.rand_percent(55) then + monster.m_flags[g.CONFUSES] = nil + g.message(string.format(g.mesg[209], g.mon_name(monster))) + g.confuse() + return true + end + return false +end + +local function get_closer(row, col, trow, tcol) + if row < trow then + row = row + 1 + elseif row > trow then + row = row - 1 + end + if col < tcol then + col = col + 1 + elseif col > tcol then + col = col - 1 + end + return row, col +end + +function g.flame_broil(monster) + if not g.mon_sees(monster, g.rogue.row, g.rogue.col) or g.coin_toss() then + return false + end + local row = g.rogue.row - monster.row + local col = g.rogue.col - monster.col + if row < 0 then + row = -row + end + if col < 0 then + col = -col + end + if ((row ~= 0) and (col ~= 0) and (row ~= col)) or ((row > 7) or (col > 7)) then + return false + end + if g.blind == 0 and not g.rogue_is_around(monster.row, monster.col) then + row = monster.row + col = monster.col + row, col = get_closer(row, col, g.rogue.row, g.rogue.col) + repeat + g.mvaddch(row, col, '(R(~(R(') + g.refresh() + row, col = get_closer(row, col, g.rogue.row, g.rogue.col) + g.msleep(50) + until (row == g.rogue.row and col == g.rogue.col) + g.msleep(50) + row = monster.row + col = monster.col + row, col = get_closer(row, col, g.rogue.row, g.rogue.col) + repeat + g.mvaddch(row, col, g.get_dungeon_char(row, col)) + g.refresh() + row, col = get_closer(row, col, g.rogue.row, g.rogue.col) + until (row == g.rogue.row and col == g.rogue.col) + end + g.mon_hit(monster, flame_name, true) + return true +end diff --git a/autoload/rogue/throw.lua b/autoload/rogue/throw.lua new file mode 100644 index 0000000..1e002f1 --- /dev/null +++ b/autoload/rogue/throw.lua @@ -0,0 +1,246 @@ +local g = Rogue -- alias + +local rand_around_pos = {[0] = 8, 7, 1, 3, 4, 5, 2, 6, 0} +local rand_around_row = 0 +local rand_around_col = 0 + +local function potion_monster(monster, kind) + local maxhp = g.mon_tab[string.byte(monster.m_char) - string.byte('A')].hp_to_kill + if kind == g.RESTORE_STRENGTH or + kind == g.LEVITATION or + kind == g.HALLUCINATION or + kind == g.DETECT_MONSTER or + kind == g.DETECT_OBJECTS or + kind == g.SEE_INVISIBLE then + elseif kind == g.EXTRA_HEALING then + monster.hp_to_kill = monster.hp_to_kill + g.int_div(((maxhp - monster.hp_to_kill) * 2), 3) + elseif kind == g.INCREASE_STRENGTH or + kind == g.HEALING or + kind == g.RAISE_LEVEL then + monster.hp_to_kill = monster.hp_to_kill + g.int_div((maxhp - monster.hp_to_kill), 5) + elseif kind == g.POISON then + g.mon_damage(monster, (g.int_div(monster.hp_to_kill, 4) + 1)) + elseif kind == g.BLINDNESS then + monster.m_flags[g.ASLEEP] = g.m_flags_desc[g.ASLEEP] + monster.m_flags[g.WAKENS] = g.m_flags_desc[g.WAKENS] + elseif kind == g.CONFUSION then + monster.m_flags[g.CONFUSED] = g.m_flags_desc[g.CONFUSED] + monster.moves_confused = monster.moves_confused + g.get_rand(12, 22) + elseif kind == g.HASTE_SELF then + if monster.m_flags[g.SLOWED] then + monster.m_flags[g.SLOWED] = nil + else + monster.m_flags[g.HASTED] = g.m_flags_desc[g.HASTED] + end + end +end + +local function throw_at_monster(monster, weapon) + local hit_chance = g.get_hit_chance(weapon) + local damage = g.get_weapon_damage(weapon) + if weapon.which_kind == g.ARROW and + (g.rogue.weapon and g.rogue.weapon.which_kind == g.BOW) then + damage = damage + g.get_weapon_damage(g.rogue.weapon) + damage = g.int_div((damage * 2), 3) + hit_chance = hit_chance + g.int_div(hit_chance, 3) + elseif weapon.in_use_flags == g.BEING_WIELDED and + (weapon.which_kind == g.DAGGER or + weapon.which_kind == g.SHURIKEN or + weapon.which_kind == g.DART) then + damage = g.int_div((damage * 3), 2) + hit_chance = hit_chance + g.int_div(hit_chance, 3) + end + local t = weapon.quantity + weapon.quantity = 1 + g.hit_message = string.format(g.mesg[212], g.name_of(weapon)) + weapon.quantity = t + + if not g.rand_percent(hit_chance) then + g.hit_message = g.hit_message .. g.mesg[213] + return false + end + g.hit_message = g.hit_message .. g.mesg[214] + if weapon.what_is == g.WAND and g.rand_percent(75) then + g.zap_monster(monster, weapon.which_kind) + elseif weapon.what_is == g.POTION then + potion_monster(monster, weapon.which_kind) + else + g.mon_damage(monster, damage) + end + return true +end + +local function get_thrown_at_monster(obj, dir, row, col) + local orow, ocol = row, col + + local ch = g.get_mask_char(obj.what_is) + local i = 0 + while i < 24 do + row, col = g.get_dir_rc(dir, row, col, false) + if g.table_is_empty(g.dungeon[row][col]) or + ((g.dungeon[row][col][g.HORWALL] or + g.dungeon[row][col][g.VERTWALL] or + g.dungeon[row][col][g.HIDDEN]) and + not g.dungeon[row][col][g.TRAP]) then + row, col = orow, ocol + return nil, row, col + end + if i ~= 0 and g.rogue_can_see(orow, ocol) then + g.mvaddch(orow, ocol, g.get_dungeon_char(orow, ocol)) + end + if g.rogue_can_see(row, col) then + if not g.dungeon[row][col][g.MONSTER] then + g.mvaddch(row, col, ch) + end + g.refresh() + end + orow, ocol = row, col + if g.dungeon[row][col][g.MONSTER] then + if not g.imitating(row, col) then + return g.object_at(g.level_monsters, row, col), row, col + end + end + if g.dungeon[row][col][g.TUNNEL] then + i = i + 2 + end + + i = i + 1 + end + return nil, row, col +end + +local function flop_weapon(weapon, row, col) + local i = 0 + local found = false + + while i < 9 do + if not(g.dungeon[row][col][g.OBJECT] or + g.dungeon[row][col][g.STAIRS] or + g.dungeon[row][col][g.HORWALL] or + g.dungeon[row][col][g.VERTWALL] or + g.dungeon[row][col][g.TRAP] or + g.dungeon[row][col][g.HIDDEN]) then + break + end + row, col = g.rand_around(i, row, col) + i = i + 1 + if (row > (g.DROWS-2)) or (row < g.MIN_ROW) or + (col > (g.DCOLS-1)) or (col < 0) or + g.table_is_empty(g.dungeon[row][col]) or + (g.dungeon[row][col][g.OBJECT] or + g.dungeon[row][col][g.STAIRS] or + g.dungeon[row][col][g.HORWALL] or + g.dungeon[row][col][g.VERTWALL] or + g.dungeon[row][col][g.TRAP] or + g.dungeon[row][col][g.HIDDEN]) then + else + found = true + break + end + end + if found or i == 0 then + local new_weapon = g.alloc_object() + g.copy_object(new_weapon, weapon) + new_weapon.in_use_flags = g.NOT_USED + new_weapon.quantity = 1 + new_weapon.ichar = 'L' + g.place_at(new_weapon, row, col) + if g.rogue_can_see(row, col) and (row ~= g.rogue.row or col ~= g.rogue.col) then + local mon = g.dungeon[row][col][g.MONSTER] + g.dungeon[row][col][g.MONSTER] = nil + local dch = g.get_dungeon_char(row, col) + if mon then + local mch = g.mvinch(row, col) + local monster = g.object_at(g.level_monsters, row, col) + if monster then + monster.trail_char = dch + end + if not mch:find('^[A-Z]$') then + g.mvaddch(row, col, dch) + end + else + g.mvaddch(row, col, dch) + end + g.dungeon[row][col][g.MONSTER] = mon + end + else + local t = weapon.quantity + weapon.quantity = 1 + local msg = string.format(g.mesg[215], g.name_of(weapon)) + weapon.quantity = t + g.message(msg) + end +end + +function g.throw() + local dir = g.get_direction() + if dir == g.CANCEL then + return + end + local wch = g.pack_letter(g.mesg[210], g.WEAPON) + if wch == g.CANCEL then + return + end + g.check_message() + + local weapon = g.get_letter_object(wch) + if not weapon then + g.message(g.mesg[211]) + return + end + if g.BEING_USED(weapon.in_use_flags) and weapon.is_cursed then + g.message(g.curse_message) + return + end + local row = g.rogue.row + local col = g.rogue.col + + if weapon.in_use_flags == g.BEING_WIELDED and weapon.quantity <= 1 then + g.unwield(g.rogue.weapon) + elseif weapon.in_use_flags == g.BEING_WORN then + g.mv_aquatars() + g.unwear(g.rogue.armor) + g.print_stats() + elseif g.ON_EITHER_HAND(weapon.in_use_flags) then + g.un_put_on(weapon) + end + local monster + monster, row, col = get_thrown_at_monster(weapon, dir, row, col) + g.mvaddch(g.rogue.row, g.rogue.col, g.rogue.fchar) + g.refresh() + if g.rogue_can_see(row, col) and (row ~= g.rogue.row or col ~= g.rogue.col) then + g.mvaddch(row, col, g.get_dungeon_char(row, col)) + end + if monster then + g.wake_up(monster) + g.check_gold_seeker(monster) + + if not throw_at_monster(monster, weapon) then + flop_weapon(weapon, row, col) + end + else + flop_weapon(weapon, row, col) + end + g.vanish(weapon, true, g.rogue.pack) +end + +function g.rand_around(i, r, c) + local ra = { [0] = 1, 1, -1, -1, 0, 1, 0, -1, 0 } + local ca = { [0] = 1, -1, 1, -1, 1, 0, 0, 0, -1 } + if i == 0 then + rand_around_row = r + rand_around_col = c + local o = g.get_rand(1, 8) + for j = 0, 4 do + local x = g.get_rand(0, 8) % 9 + local y = (x + o) % 9 + local t = rand_around_pos[x] + rand_around_pos[x] = rand_around_pos[y] + rand_around_pos[y] = t + end + end + local j = rand_around_pos[i] % 9 + r = rand_around_row + ra[j] + c = rand_around_col + ca[j] + return r, c +end diff --git a/autoload/rogue/trap.lua b/autoload/rogue/trap.lua new file mode 100644 index 0000000..643203d --- /dev/null +++ b/autoload/rogue/trap.lua @@ -0,0 +1,217 @@ +local g = Rogue -- alias + +local Trap = {} +function Trap.new() + local tr = {} + tr.trap_type = g.NO_TRAP + tr.trap_row = 0 + tr.trap_col = 0 + return tr +end + +g.traps = {} + +g.trap_door = false +g.bear_trap = 0 + +local trap_strings = {} + +local reg_search = false + +function g.init_trap() + for i = 0, g.MAX_TRAPS-1 do + g.traps[i] = Trap.new() + end + trap_strings = { [0] = + g.mesg[216], g.mesg[217], g.mesg[218], g.mesg[219], g.mesg[220], g.mesg[221], + g.mesg[222], g.mesg[223], g.mesg[224], g.mesg[225], g.mesg[226], g.mesg[227] + } +end + +local function trap_at(row, col) + for i = 0, g.MAX_TRAPS-1 do + if g.traps[i].trap_type == g.NO_TRAP then + break + end + if g.traps[i].trap_row == row and g.traps[i].trap_col == col then + return g.traps[i].trap_type + end + end + return g.NO_TRAP +end + +function g.trap_player(row, col) + local t = trap_at(row, col) + if t == g.NO_TRAP then + return + end + g.dungeon[row][col][g.HIDDEN] = nil + if g.rand_percent(g.rogue.exp + g.ring_exp) then + g.message(g.mesg[228], true) + return + end + local str = trap_strings[(t*2)+1] + if t == g.TRAP_DOOR then + g.trap_door = true + g.new_level_message = str + elseif t == g.BEAR_TRAP then + g.message(str, true) + g.bear_trap = g.get_rand(4, 7) + elseif t == g.TELE_TRAP then + g.mvaddch(g.rogue.row, g.rogue.col, '^') + g.tele() + elseif t == g.DART_TRAP then + g.message(str, true) + g.rogue.hp_current = g.rogue.hp_current - g.get_damage("1d6", true) + if g.rogue.hp_current <= 0 then + g.rogue.hp_current = 0 + end + if not g.sustain_strength and g.rand_percent(40) and g.rogue.str_current >= 3 then + g.rogue.str_current = g.rogue.str_current - 1 + end + g.print_stats() + if g.rogue.hp_current <= 0 then + g.killed_by(nil, g.POISON_DART) + -- NOTREACHED + end + elseif t == g.SLEEPING_GAS_TRAP then + g.message(str, true) + g.take_a_nap() + elseif t == g.RUST_TRAP then + g.message(str, true) + g.rust(nil) + end +end + +function g.add_traps() + local n + local tries = 0 + local row, col + + if g.cur_level <= 2 then + n = 0 + elseif g.cur_level <= 7 then + n = g.get_rand(0, 2) + elseif g.cur_level <= 11 then + n = g.get_rand(1, 2) + elseif g.cur_level <= 16 then + n = g.get_rand(2, 3) + elseif g.cur_level <= 21 then + n = g.get_rand(2, 4) + elseif g.cur_level <= (g.AMULET_LEVEL + 2) then + n = g.get_rand(3, 5) + else + n = g.get_rand(5, g.MAX_TRAPS) + end + for i = 0, n-1 do + g.traps[i].trap_type = g.get_rand(0, (g.TRAPS - 1)) + + if i == 0 and g.party_room ~= g.NO_ROOM then + repeat + row = g.get_rand((g.rooms[g.party_room].top_row+1), (g.rooms[g.party_room].bottom_row-1)) + col = g.get_rand((g.rooms[g.party_room].left_col+1), (g.rooms[g.party_room].right_col-1)) + tries = tries + 1 + until not ( + ((g.dungeon[row][col][g.OBJECT] or + g.dungeon[row][col][g.STAIRS] or + g.dungeon[row][col][g.TRAP] or + g.dungeon[row][col][g.TUNNEL]) or + g.table_is_empty(g.dungeon[row][col])) and + (tries < 15)) + if tries >= 15 then + row, col = g.gr_row_col({[g.FLOOR]=true, [g.MONSTER]=true}) + end + else + row, col = g.gr_row_col({[g.FLOOR]=true, [g.MONSTER]=true}) + end + g.traps[i].trap_row = row + g.traps[i].trap_col = col + g.dungeon[row][col][g.TRAP] = g.dungeon_desc[g.TRAP] + g.dungeon[row][col][g.HIDDEN] = g.dungeon_desc[g.HIDDEN] + end +end + +function g.id_trap() + local dir = g.get_direction() + if dir == g.CANCEL then + return + end + local row = g.rogue.row + local col = g.rogue.col + + row, col = g.get_dir_rc(dir, row, col, false) + if g.dungeon[row][col][g.TRAP] and not g.dungeon[row][col][g.HIDDEN] then + local t = trap_at(row, col) + g.message(trap_strings[t*2]) + else + g.message(g.mesg[229]) + end +end + +function g.show_traps() + for i = 0, g.DROWS-1 do + for j = 0, g.DCOLS-1 do + if g.dungeon[i][j][g.TRAP] then + g.mvaddch(i, j, '^') + end + end + end +end + +function g.search(n, is_auto) + local row + local col + local shown = 0 + local found = 0 + + for i = -1, 1 do + for j = -1, 1 do + row = g.rogue.row + i + col = g.rogue.col + j + if (row < g.MIN_ROW) or (row >= g.DROWS-1) or + (col < 0) or (col >= g.DCOLS) then + -- continue + else + if g.dungeon[row][col][g.HIDDEN] then + found = found + 1 + end + end + end + end + for s = 0, n-1 do + for i = -1, 1 do + for j = -1, 1 do + row = g.rogue.row + i + col = g.rogue.col + j + if (row < g.MIN_ROW) or (row >= g.DROWS-1) or + (col < 0) or (col >= g.DCOLS) then + -- continue + else + if g.dungeon[row][col][g.HIDDEN] then + if g.rand_percent(17 + (g.rogue.exp + g.ring_exp)) then + g.dungeon[row][col][g.HIDDEN] = nil + if g.blind == 0 and (row ~= g.rogue.row or + col ~= g.rogue.col) then + g.mvaddch(row, col, g.get_dungeon_char(row, col)) + end + shown = shown + 1 + if g.dungeon[row][col][g.TRAP] then + local t = trap_at(row, col) + g.message(trap_strings[t*2], true) + end + end + end + if (shown == found and found > 0) or g.interrupted then + return + end + end + end + end + if not is_auto then + reg_search = not reg_search + if reg_search then + g.reg_move() + end + end + end +end diff --git a/autoload/rogue/use.lua b/autoload/rogue/use.lua new file mode 100644 index 0000000..7fd513b --- /dev/null +++ b/autoload/rogue/use.lua @@ -0,0 +1,472 @@ +local g = Rogue -- alias + +g.halluc = 0 +g.blind = 0 +g.confused = 0 +g.levitate = 0 +g.haste_self = 0 +g.see_invisible = false +g.extra_hp = 0 +g.detect_monster = false +local strange_feeling = '' + +function g.init_use() + strange_feeling = g.mesg[230] +end + +-- vanish() does NOT handle a quiver of weapons with more than one +-- arrow (or whatever) in the quiver. It will only decrement the count. +function g.vanish(obj, rm, pack) + if obj.quantity > 1 then + obj.quantity = obj.quantity - 1 + else + if obj.in_use_flags == g.BEING_WIELDED then + g.unwield(obj) + elseif obj.in_use_flags == g.BEING_WORN then + g.unwear(obj) + elseif g.ON_EITHER_HAND(obj.in_use_flags) then + g.un_put_on(obj) + end + g.take_from_pack(obj, pack) + g.free_object(obj) + end + if rm then + g.reg_move() + end +end + +local function potion_heal(extra) + g.rogue.hp_current = g.rogue.hp_current + g.rogue.exp + + local ratio = g.int_div(g.rogue.hp_current * 100, g.rogue.hp_max) + + if ratio >= 100 then + g.rogue.hp_max = g.rogue.hp_max + (extra and 2 or 1) + g.extra_hp = g.extra_hp + (extra and 2 or 1) + g.rogue.hp_current = g.rogue.hp_max + elseif ratio >= 90 then + g.rogue.hp_max = g.rogue.hp_max + (extra and 1 or 0) + g.extra_hp = g.extra_hp + (extra and 1 or 0) + g.rogue.hp_current = g.rogue.hp_max + else + if ratio < 33 then + ratio = 33 + end + if extra then + ratio = ratio + ratio + end + local add = g.int_div((ratio * (g.rogue.hp_max - g.rogue.hp_current)), 100) + g.rogue.hp_current = g.rogue.hp_current + add + if g.rogue.hp_current > g.rogue.hp_max then + g.rogue.hp_current = g.rogue.hp_max + end + end + if g.blind > 0 then + g.unblind() + end + if g.confused > 0 and extra then + g.unconfuse() + elseif g.confused > 0 then + g.confused = g.int_div(g.confused, 2) + 1 + end + if g.halluc > 0 and extra then + g.unhallucinate() + elseif g.halluc > 0 then + g.halluc = g.int_div(g.halluc, 2) + 1 + end +end + +local function idntfy() + local ch + local obj + repeat + ch = g.pack_letter(g.mesg[260], g.ALL_OBJECTS) + if ch == g.CANCEL then + return + end + obj = g.get_letter_object(ch) + if not obj then + g.message(g.mesg[261]) + g.message("") + g.check_message() + end + until obj + obj.identified = true + if obj.what_is == g.SCROL or + obj.what_is == g.POTION or + obj.what_is == g.WEAPON or + obj.what_is == g.ARMOR or + obj.what_is == g.WAND or + obj.what_is == g.RING then + local id_table = g.get_id_table(obj) + id_table[obj.which_kind].id_status = g.IDENTIFIED + end + g.message(g.get_desc(obj, true)) +end + +function g.eat() + local ch = g.pack_letter(g.mesg[262], g.FOOD) + if ch == g.CANCEL then + return + end + local obj = g.get_letter_object(ch) + if not obj then + g.message(g.mesg[263]) + return + end + if obj.what_is ~= g.FOOD then + g.message(g.mesg[264]) + return + end + local moves + if obj.which_kind == g.FRUIT or g.rand_percent(60) then + moves = g.get_rand(900, 1100) + if obj.which_kind == g.RATION then + if g.get_rand(1, 10) == 1 then + g.message(g.mesg[265]) + else + g.message(g.mesg[266]) + end + else + g.message(string.format(g.mesg[267], g.fruit)) + end + else + moves = g.get_rand(700, 900) + g.message(g.mesg[268]) + g.add_exp(2, true) + end + g.rogue.moves_left = g.int_div(g.rogue.moves_left, 3) + g.rogue.moves_left = g.rogue.moves_left + moves + g.hunger_str = '' + g.print_stats() + + g.vanish(obj, true, g.rogue.pack) +end + +local function hold_monster() + local mcount = 0 + + for i = -2, 2 do + for j = -2, 2 do + local row = g.rogue.row + i + local col = g.rogue.col + j + if not ((row < g.MIN_ROW) or (row > (g.DROWS-2)) or (col < 0) or (col > (g.DCOLS-1))) then + if g.dungeon[row][col][g.MONSTER] then + local monster = g.object_at(g.level_monsters, row, col) + monster.m_flags[g.ASLEEP] = g.m_flags_desc[g.ASLEEP] + monster.m_flags[g.WAKENS] = nil + mcount = mcount + 1 + end + end + end + end + if mcount == 0 then + g.message(g.mesg[269]) + elseif mcount == 1 then + g.message(g.mesg[270]) + else + g.message(g.mesg[271]) + end +end + +function g.tele() + g.mvaddch(g.rogue.row, g.rogue.col, g.get_dungeon_char(g.rogue.row, g.rogue.col)) + + if g.cur_room >= 0 then + g.darken_room(g.cur_room) + end + g.put_player(g.get_room_number(g.rogue.row, g.rogue.col)) + g.being_held = false + g.bear_trap = 0 +end + +function g.hallucinate() + if g.blind > 0 then + return + end + local obj = g.level_objects.next_object + while obj do + local ch = g.mvinch(obj.row, obj.col) + if not ch:find('^[A-Z]$') and (obj.row ~= g.rogue.row or obj.col ~= g.rogue.col) then + if not string.find(" .#+", ch, 1, true) then + g.mvaddch(obj.row, obj.col, ch) + end + end + obj = obj.next_object + end + + local monster = g.level_monsters.next_object + while monster do + local ch = g.mvinch(monster.row, monster.col) + if ch:find('^[A-Z]$') then + g.mvaddch(monster.row, monster.col, g.mon_tab[g.get_rand(0, 25)].m_char) + end + monster = monster.next_object + end +end + +function g.unhallucinate() + g.halluc = 0 + g.relight() + g.message(g.mesg[272], true) +end + +function g.unblind() + g.blind = 0 + g.message(g.mesg[273], true) + g.relight() + if g.halluc > 0 then + g.hallucinate() + end + if g.detect_monster then + g.show_monsters() + end +end + +function g.relight() + if g.cur_room == g.PASSAGE then + g.light_passage(g.rogue.row, g.rogue.col) + else + g.light_up_room(g.cur_room) + end + g.mvaddch(g.rogue.row, g.rogue.col, g.rogue.fchar) +end + +function g.take_a_nap() + local i = g.get_rand(2, 5) + g.msleep(1000) + while i > 0 do + g.mv_mons() + i = i - 1 + end + g.msleep(1000) + g.message(g.you_can_move_again) +end + +local function go_blind() + if g.blind == 0 then + g.message(g.mesg[274]) + end + g.blind = g.blind + g.get_rand(500, 800) + + if g.detect_monster then + local monster = g.level_monsters.next_object + while monster do + g.mvaddch(monster.row, monster.col, monster.trail_char) + monster = monster.next_object + end + end + if g.cur_room >= 0 then + for i = g.rooms[g.cur_room].top_row + 1, g.rooms[g.cur_room].bottom_row - 1 do + for j = g.rooms[g.cur_room].left_col + 1, g.rooms[g.cur_room].right_col - 1 do + g.mvaddch(i, j, ' ') + end + end + end + g.mvaddch(g.rogue.row, g.rogue.col, g.rogue.fchar) +end + +local function get_ench_color() + if g.halluc > 0 then + return g.id_potions[g.get_rand(0, g.POTIONS-1)].title + end + return g.mesg[275] +end + +function g.confuse() + g.confused = g.confused + g.get_rand(12, 22) +end + +function g.unconfuse() + g.confused = 0 + if g.halluc > 0 then + g.message(g.mesg[276], true) + else + g.message(g.mesg[277], true) + end +end + +local function uncurse_all() + local obj = g.rogue.pack.next_object + + while obj do + obj.is_cursed = false + obj = obj.next_object + end +end + +function g.quaff() + local ch = g.pack_letter(g.mesg[231], g.POTION) + + if ch == g.CANCEL then + return + end + local obj = g.get_letter_object(ch) + if not obj then + g.message(g.mesg[232]) + return + end + if obj.what_is ~= g.POTION then + g.message(g.mesg[233]) + return + end + if obj.which_kind == g.INCREASE_STRENGTH then + g.message(g.mesg[234]) + g.rogue.str_current = g.rogue.str_current + 1 + if g.rogue.str_current > g.rogue.str_max then + g.rogue.str_max = g.rogue.str_current + end + elseif obj.which_kind == g.RESTORE_STRENGTH then + g.rogue.str_current = g.rogue.str_max + g.message(g.mesg[235]) + elseif obj.which_kind == g.HEALING then + g.message(g.mesg[236]) + potion_heal(false) + elseif obj.which_kind == g.EXTRA_HEALING then + g.message(g.mesg[237]) + potion_heal(true) + elseif obj.which_kind == g.POISON then + if not g.sustain_strength then + g.rogue.str_current = g.rogue.str_current - g.get_rand(1, 3) + if g.rogue.str_current < 1 then + g.rogue.str_current = 1 + end + end + g.message(g.mesg[238]) + if g.halluc > 0 then + g.unhallucinate() + end + elseif obj.which_kind == g.RAISE_LEVEL then + g.rogue.exp_points = g.level_points[g.rogue.exp - 1] + g.add_exp(1, true) + elseif obj.which_kind == g.BLINDNESS then + go_blind() + elseif obj.which_kind == g.HALLUCINATION then + g.message(g.mesg[239]) + g.halluc = g.halluc + g.get_rand(500, 800) + elseif obj.which_kind == g.DETECT_MONSTER then + g.show_monsters() + if not g.level_monsters.next_object then + g.message(strange_feeling) + end + elseif obj.which_kind == g.DETECT_OBJECTS then + if g.level_objects.next_object then + if g.blind == 0 then + g.show_objects() + end + else + g.message(strange_feeling) + end + elseif obj.which_kind == g.CONFUSION then + g.message((g.halluc > 0) and g.mesg[240] or g.mesg[241]) + g.confuse() + elseif obj.which_kind == g.LEVITATION then + g.message(g.mesg[242]) + g.levitate = g.levitate + g.get_rand(15, 30) + g.bear_trap = 0 + g.being_held = false + elseif obj.which_kind == g.HASTE_SELF then + g.message(g.mesg[243]) + g.haste_self = g.haste_self + g.get_rand(11, 21) + if (g.haste_self % 2) == 0 then + g.haste_self = g.haste_self + 1 + end + elseif obj.which_kind == g.SEE_INVISIBLE then + g.message(string.format(g.mesg[244], g.fruit)) + if g.blind > 0 then + g.unblind() + end + g.see_invisible = true + g.relight() + end + g.print_stats() + g.id_potions[obj.which_kind].id_status = g.IDENTIFIED + g.vanish(obj, true, g.rogue.pack) +end + +function g.read_scroll() + local ch = g.pack_letter(g.mesg[245], g.SCROL) + + if ch == g.CANCEL then + return + end + local obj = g.get_letter_object(ch) + if not obj then + g.message(g.mesg[246]) + return + end + if obj.what_is ~= g.SCROL then + g.message(g.mesg[247]) + return + end + if obj.which_kind == g.SCARE_MONSTER then + g.message(g.mesg[248]) + elseif obj.which_kind == g.HOLD_MONSTER then + hold_monster() + elseif obj.which_kind == g.ENCH_WEAPON then + if g.rogue.weapon then + if g.rogue.weapon.what_is == g.WEAPON then + local msg + if not g.English then + msg = string.format(g.mesg[249], + g.name_of(g.rogue.weapon), + get_ench_color()) + else + -- add "s" of the third person singular + msg = string.format(g.mesg[249], + g.name_of(g.rogue.weapon), + ((g.rogue.weapon.quantity <= 1) and "s" or ""), + get_ench_color()) + end + g.message(msg) + if g.coin_toss() then + g.rogue.weapon.hit_enchant = g.rogue.weapon.hit_enchant + 1 + else + g.rogue.weapon.d_enchant = g.rogue.weapon.d_enchant + 1 + end + end + g.rogue.weapon.is_cursed = false + else + g.message(g.mesg[250]) + end + elseif obj.which_kind == g.ENCH_ARMOR then + if g.rogue.armor then + g.message(string.format(g.mesg[251], get_ench_color())) + g.rogue.armor.d_enchant = g.rogue.armor.d_enchant + 1 + g.rogue.armor.is_cursed = false + g.print_stats() + else + g.message(g.mesg[252]) + end + elseif obj.which_kind == g.IDENTIFY then + g.message(g.mesg[253]) + obj.identified = true + g.id_scrolls[obj.which_kind].id_status = g.IDENTIFIED + idntfy() + elseif obj.which_kind == g.TELEPORT then + g.tele() + elseif obj.which_kind == g.SLEEP then + g.message(g.mesg[254]) + g.take_a_nap() + elseif obj.which_kind == g.PROTECT_ARMOR then + if g.rogue.armor then + g.message(g.mesg[255]) + g.rogue.armor.is_protected = true + g.rogue.armor.is_cursed = false + else + g.message(g.mesg[256]) + end + elseif obj.which_kind == g.REMOVE_CURSE then + g.message((g.halluc == 0) and g.mesg[257] or g.mesg[258]) + uncurse_all() + elseif obj.which_kind == g.CREATE_MONSTER then + g.create_monster() + elseif obj.which_kind == g.AGGRAVATE_MONSTER then + g.aggravate() + elseif obj.which_kind == g.MAGIC_MAPPING then + g.message(g.mesg[259]) + g.draw_magic_map() + end + g.id_scrolls[obj.which_kind].id_status = g.IDENTIFIED + g.vanish(obj, (obj.which_kind ~= g.SLEEP), g.rogue.pack) +end diff --git a/autoload/rogue/util.lua b/autoload/rogue/util.lua new file mode 100644 index 0000000..97697dd --- /dev/null +++ b/autoload/rogue/util.lua @@ -0,0 +1,208 @@ +local g = Rogue -- alias + +g.loadstring = nil +if _VERSION >= 'Lua 5.2' then + g.loadstring = load +else + g.loadstring = loadstring +end + +g.bxor = nil + +local bit_exists, bit = pcall(require, "bit") +if bit_exists then + g.bxor = bit.bxor +elseif _VERSION >= 'Lua 5.2' then + g.bxor = bit32.bxor +else + g.bxor = function(x, y) + local n = 0 + local ret = 0 + + repeat + local bit_x = x % 2 + local bit_y = y % 2 + if bit_x ~= bit_y then + ret = ret + 2 ^ n + end + x = g.int_div(x, 2) + y = g.int_div(y, 2) + n = n + 1 + until x == 0 and y == 0 + return ret + end +end + +function g.get_vim_variable(var) + if vim then + if vim.eval("exists('" .. var .. "')") ~= 0 then + return vim.eval(var) + end + end + return '' +end + +function g.set_vim_variable(var, value) + if vim then + if type(value) == 'number' then + vim.command('let ' .. var .. ' = ' .. tostring(value)) + elseif type(value) == 'string' then + vim.command('let ' .. var .. ' = "' .. value .. '"') + end + end +end + +local function dump(obj, indent_depth, dumped_table_list, hex_flag) + if not indent_depth then + indent_depth = 0 + end + if not dumped_table_list then + dumped_table_list = {} + end + + local t = type(obj) + local s + if t == 'table' then + local exists = false + for i, v in ipairs(dumped_table_list) do + if v == tostring(obj) then + exists = true + end + end + s = '{' + if exists then + s = s .. ' ... ' + else + table.insert(dumped_table_list, tostring(obj)) + local indent = ' ' + local is_empty = true + for k, v in pairs(obj) do + is_empty = false + s = s .. '\n' .. string.rep(indent, indent_depth + 1) + if type(k) == 'string' then + s = s .. k + else + s = s .. '[' .. k .. ']' + end + s = s .. ' = ' + s = s .. dump(v, indent_depth + 1, dumped_table_list, hex_flag) + s = s .. ',' + end + if not is_empty then + s = s .. '\n' .. string.rep(indent, indent_depth) + end + end + s = s .. '} ' .. tostring(obj) + + if indent_depth == 0 and not s:find('{ ... } table') then + s = s:gsub(' table:[ xX%x]*', '') + end + elseif t == 'string' then + s = '"' .. obj .. '"' + elseif hex_flag and t == 'number' then + s = string.format('0x%x', obj) + else + s = tostring(obj) + end + + return s +end + +function g.dump(obj, hex_flag) + return dump(obj, nil, nil, hex_flag) +end + +function g.int_div(dividend, divisor) + return math.floor(dividend / divisor) +end + +function g.table_is_empty(tbl) + if next(tbl) == nil then + return true + else + return false + end +end + +function g.strwidth(s) + local len + if vim then + len = vim.eval('strwidth("' .. s .. '")') + else + len = #s + end + return len +end + +function g.getftime(fname) + local t + if vim then + t = vim.eval('getftime("' .. fname .. '")') + else + t = -1 + end + return t +end + +function g.split(str, sep) + local ret = {} + while true do + local idx = str:find(sep, 1, true) + if not idx then + table.insert(ret, str) + break + end + if idx == 1 then + str = str:sub(idx + 1) + else + local prev = str:sub(1, idx - 1) + str = str:sub(idx + 1) + table.insert(ret, prev) + end + end + return ret +end + +function g.msleep(n) + if vim then + vim.command('sleep ' .. tostring(n) .. 'm') + end +end + +g.EXIT_SUCCESS = 'g.EXIT_SUCCESS' +function g.exit(e) + local level = 2 + if e == nil then + e = g.EXIT_SUCCESS + end + if e == g.EXIT_SUCCESS then + level = 0 + end + error(e, level) +end + +function g.expand_fname(fname, dir) + fname = fname:gsub('\\', '/') + if string.char(fname:byte(1)) == '~' then + fname = fname:gsub('~/', g.home_dir) + elseif not (fname:find('^/.*') or fname:find('^[A-Za-z]:/.*')) then + fname = dir .. fname + end + return fname +end + +function g.iconv_from_utf8(str) + if g.needs_iconv then + str = str:gsub("'", "''") + str = vim.eval("iconv('" .. str .. "', 'utf-8', s:save_encoding)") + end + return str +end + +function g.iconv_to_utf8(str) + if g.needs_iconv then + str = str:gsub("'", "''") + str = vim.eval("iconv('" .. str .. "', s:save_encoding, 'utf-8')") + end + return str +end diff --git a/autoload/rogue/zap.lua b/autoload/rogue/zap.lua new file mode 100644 index 0000000..2fb7d29 --- /dev/null +++ b/autoload/rogue/zap.lua @@ -0,0 +1,207 @@ +local g = Rogue -- alias + +g.wizard = false + +local wiz_passwd = '\171\068\076\182\092\165\000\219\237\052' + +local function get_zapped_monster(dir, row, col) + while true do + local orow, ocol = row, col + row, col = g.get_dir_rc(dir, row, col, false) + if (row == orow and col == ocol) or + (g.dungeon[row][col][g.HORWALL] or g.dungeon[row][col][g.VERTWALL]) or + g.table_is_empty(g.dungeon[row][col]) then + return nil, row, col + end + if g.dungeon[row][col][g.MONSTER] then + if not g.imitating(row, col) then + return g.object_at(g.level_monsters, row, col), row, col + end + end + end +end + +local function get_missiled_monster(dir, row, col) + local orow, ocol = row, col + local first = true + while true do + row, col = g.get_dir_rc(dir, row, col, false) + if (row == orow and col == ocol) or + (g.dungeon[row][col][g.HORWALL] or g.dungeon[row][col][g.VERTWALL]) or + g.table_is_empty(g.dungeon[row][col]) then + row, col = orow, ocol + return nil, row, col + end + if not first and g.rogue_can_see(orow, ocol) then + g.mvaddch(orow, ocol, g.get_dungeon_char(orow, ocol)) + end + if g.rogue_can_see(row, col) then + -- if not g.dungeon[row][col][g.MONSTER] then + g.mvaddch(row, col, '(r(*(r(') + g.msleep(50) + -- end + g.refresh() + end + if g.dungeon[row][col][g.MONSTER] then + if not g.imitating(row, col) then + return g.object_at(g.level_monsters, row, col), row, col + end + end + first = false + orow, ocol = row, col + end +end + +function g.zapp() + local dir = g.get_direction() + if dir == g.CANCEL then + return + end + local wch = g.pack_letter(g.mesg[278], g.WAND) + if wch == g.CANCEL then + return + end + g.check_message() + + local wand = g.get_letter_object(wch) + if not wand then + g.message(g.mesg[279]) + return + end + if wand.what_is ~= g.WAND then + g.message(g.mesg[280]) + return + end + if wand.class <= 0 then + g.message(g.mesg[281]) + else + wand.class = wand.class - 1 + local row = g.rogue.row + local col = g.rogue.col + local monster + if wand.which_kind == g.MAGIC_MISSILE then + monster, row, col = get_missiled_monster(dir, row, col) + g.mvaddch(g.rogue.row, g.rogue.col, g.rogue.fchar) + g.refresh() + if (row ~= g.rogue.row or col ~= g.rogue.col) and g.rogue_can_see(row, col) then + g.mvaddch(row, col, g.get_dungeon_char(row, col)) + end + else + monster, row, col = get_zapped_monster(dir, row, col) + end + if monster then + g.wake_up(monster) + g.zap_monster(monster, wand.which_kind) + g.relight() + end + end + g.reg_move() +end + +local function tele_away(monster) + if monster.m_flags[g.HOLDS] then + g.being_held = false + end + local row, col = g.gr_row_col({ [g.FLOOR]=true, [g.TUNNEL]=true, [g.STAIRS]=true, [g.OBJECT]=true }) + g.mvaddch(monster.row, monster.col, monster.trail_char) + g.dungeon[monster.row][monster.col][g.MONSTER] = nil + monster.row = row + monster.col = col + g.dungeon[row][col][g.MONSTER] = g.m_flags_desc[g.MONSTER] + monster.trail_char = g.mvinch(row, col) + if g.detect_monster or g.rogue_can_see(row, col) then + g.mvaddch(row, col, g.gmc(monster)) + end +end + +function g.zap_monster(monster, kind) + local row = monster.row + local col = monster.col + + if kind == g.SLOW_MONSTER then + if monster.m_flags[g.HASTED] then + monster.m_flags[g.HASTED] = nil + else + monster.slowed_toggle = false + monster.m_flags[g.SLOWED] = g.m_flags_desc[g.SLOWED] + end + elseif kind == g.HASTE_MONSTER then + if monster.m_flags[g.SLOWED] then + monster.m_flags[g.SLOWED] = nil + else + monster.m_flags[g.HASTED] = g.m_flags_desc[g.HASTED] + end + elseif kind == g.TELE_AWAY then + tele_away(monster) + elseif kind == g.CONFUSE_MONSTER then + monster.m_flags[g.CONFUSED] = g.m_flags_desc[g.CONFUSED] + monster.moves_confused = monster.moves_confused + g.get_rand(12, 22) + elseif kind == g.INVISIBILITY then + monster.m_flags[g.INVISIBLE] = g.m_flags_desc[g.INVISIBLE] + elseif kind == g.POLYMORPH then + if monster.m_flags[g.HOLDS] then + g.being_held = false + end + local nm = monster.next_object + local tc = monster.trail_char + g.gr_monster(monster, g.get_rand(0, g.MONSTER-1)) + monster.row = row + monster.col = col + monster.next_object = nm + monster.trail_char = tc + if not monster.m_flags[g.IMITATES] then + g.wake_up(monster) + end + elseif kind == g.PUT_TO_SLEEP then + monster.m_flags[g.ASLEEP] = g.m_flags_desc[g.ASLEEP] + monster.m_flags[g.NAPPING] = g.m_flags_desc[g.NAPPING] + monster.nap_length = g.get_rand(3, 6) + elseif kind == g.MAGIC_MISSILE then + g.rogue_hit(monster, true) + elseif kind == g.CANCELLATION then + if monster.m_flags[g.HOLDS] then + g.being_held = false + end + if monster.m_flags[g.STEALS_ITEM] then + monster.drop_percent = 0 + end + monster.m_flags[g.FLIES] = nil + monster.m_flags[g.FLITS] = nil + monster.m_flags[g.INVISIBLE] = nil + monster.m_flags[g.FLAMES] = nil + monster.m_flags[g.IMITATES] = nil + monster.m_flags[g.CONFUSES] = nil + monster.m_flags[g.SEEKS_GOLD] = nil + monster.m_flags[g.RUSTS] = nil + monster.m_flags[g.HOLDS] = nil + monster.m_flags[g.FREEZES] = nil + monster.m_flags[g.STEALS_GOLD] = nil + monster.m_flags[g.STEALS_ITEM] = nil + monster.m_flags[g.STINGS] = nil + monster.m_flags[g.DRAINS_LIFE] = nil + monster.m_flags[g.DROPS_LEVEL] = nil + elseif kind == g.DO_NOTHING then + g.message(g.mesg[282]) + end +end + +function g.wizardize() + if g.wizard then + g.wizard = false + g.message(g.mesg[497]) + return + end + local buf = g.get_input_line(g.mesg[498], "", "", false, false) + if buf == '' then + return + end + g.xxx(true) + buf = g.xxxx(buf) + if buf == wiz_passwd then + g.message(g.mesg[499]) + g.wizard = true + g.score_only = true + else + g.message(g.mesg[500]) + end +end diff --git a/plugin/rogue.vim b/plugin/rogue.vim new file mode 100644 index 0000000..5aefa15 --- /dev/null +++ b/plugin/rogue.vim @@ -0,0 +1,4 @@ +command! -nargs=* Rogue call rogue#rogue#main() +command! -nargs=0 RogueScores call rogue#rogue#main('-s') +command! -nargs=? RogueRestore call rogue#rogue#main( == '' ? '-r' : ) +command! -nargs=0 RogueResume call rogue#rogue#main('--resume') diff --git a/syntax/rogue.vim b/syntax/rogue.vim new file mode 100644 index 0000000..305fa8c --- /dev/null +++ b/syntax/rogue.vim @@ -0,0 +1,129 @@ + +scriptencoding utf-8 + +if exists("b:current_syntax") + finish +endif + +syn match rogue_WallH "-" +syn match rogue_WallV "|" +syn match rogue_Door "+" +syn match rogue_Tunnel "#" +syn match rogue_Floor "\." +syn match rogue_Stairs "%" +syn match rogue_Trap "\^" +syn match rogue_Gold "\*" +syn match rogue_Food ":" +syn match rogue_Armor "\]" +syn match rogue_Weapon ")" +syn match rogue_Scrol "?" +syn match rogue_Potion "!" +syn match rogue_Wand "/" +syn match rogue_Ring "=" +syn match rogue_Amulet "," +syn match rogue_Monster "[A-Z]" +syn match rogue_Fighter "@" + +syn match rogue_Message "\$\$.*" contains=rogue_ConcealedMessage,rogue_Red,rogue_Green,rogue_Yellow,rogue_CyanBg,rogue_RedBg,rogue_GreenFill +syn match rogue_ConcealedMessage "\$\$" contained conceal + +syn match rogue_Red "(r(.\{-}(r(" contains=rogue_ConcealedRed +syn match rogue_ConcealedRed "(r(" contained conceal + +syn match rogue_Green "(g(.\{-}(g(" contains=rogue_ConcealedGreen +syn match rogue_ConcealedGreen "(g(" contained conceal + +syn match rogue_Yellow "(y(.\{-}(y(" contains=rogue_ConcealedYellow +syn match rogue_ConcealedYellow "(y(" contained conceal + +syn match rogue_RedBg "(R(.\{-}(R(" contains=rogue_ConcealedRedBg +syn match rogue_ConcealedRedBg "(R(" contained conceal + +syn match rogue_CyanBg "(C(.\{-}(C(" contains=rogue_ConcealedCyanBg +syn match rogue_ConcealedCyanBg "(C(" contained conceal + +syn match rogue_GreenFill "(G(.\{-}(G(" contains=rogue_ConcealedGreenFill +syn match rogue_ConcealedGreenFill "(G(" contained conceal + + +let s:fg = synIDattr(synIDtrans(hlID("rogueWall")), "fg") +if s:fg == '' || s:fg == '-1' + if &background == "dark" + hi rogueWall ctermfg=cyan guifg=cyan + else + hi rogueWall ctermfg=blue guifg=blue + endif +endif +hi def link rogue_WallH rogueWall +hi def link rogue_WallV rogueWall +hi def link rogue_Door rogueWall +hi def link rogue_Tunnel rogueWall + +let s:fg = synIDattr(synIDtrans(hlID("rogueFloor")), "fg") +if s:fg == '' || s:fg == '-1' + if &background == "dark" + hi rogueFloor ctermfg=blue guifg=blue + else + hi rogueFloor ctermfg=gray guifg=gray + endif +endif +hi def link rogue_Floor rogueFloor + +let s:fg = synIDattr(synIDtrans(hlID("rogueItem")), "fg") +if s:fg == '' || s:fg == '-1' + if &background == "dark" + hi rogueItem ctermfg=yellow guifg=yellow + else + hi rogueItem ctermfg=brown guifg=brown + endif +endif +hi def link rogue_Stairs rogueItem +hi def link rogue_Trap rogueItem +hi def link rogue_Gold rogueItem +hi def link rogue_Food rogueItem +hi def link rogue_Armor rogueItem +hi def link rogue_Weapon rogueItem +hi def link rogue_Scrol rogueItem +hi def link rogue_Potion rogueItem +hi def link rogue_Wand rogueItem +hi def link rogue_Ring rogueItem +hi def link rogue_Amulet rogueItem + +let s:fg = synIDattr(synIDtrans(hlID("rogueMonster")), "fg") +if s:fg == '' || s:fg == '-1' + if &background == "dark" + hi rogueMonster ctermfg=magenta guifg=magenta + else + hi rogueMonster ctermfg=red guifg=red + endif +endif +hi def link rogue_Monster rogueMonster + +let s:fg = synIDattr(synIDtrans(hlID("rogueFighter")), "fg") +if s:fg == '' || s:fg == '-1' + if &background == "dark" + hi rogueFighter ctermfg=green guifg=green + else + hi rogueFighter ctermfg=darkgreen guifg=darkgreen + endif +endif +hi def link rogue_Fighter rogueFighter + +hi def link rogue_Message Normal + +if &background == "dark" + hi rogue_Red ctermfg=red guifg=red + hi rogue_Green ctermfg=green guifg=green + hi rogue_Yellow ctermfg=yellow guifg=yellow + hi rogue_GreenFill ctermfg=green ctermbg=green guifg=green guibg=green +else + hi rogue_Red ctermfg=darkred guifg=darkred + hi rogue_Green ctermfg=darkgreen guifg=darkgreen + hi rogue_Yellow ctermfg=brown guifg=brown + hi rogue_GreenFill ctermfg=darkgreen ctermbg=darkgreen guifg=darkgreen guibg=darkgreen +endif +hi rogue_CyanBg ctermfg=red ctermbg=cyan guifg=red guibg=cyan +hi rogue_RedBg ctermbg=red guifg=fg guibg=red + + +let b:current_syntax = "rogue"