Last active
October 23, 2020 02:04
-
-
Save obelisk68/6c9869c0802366cafd614f3ed62be557 to your computer and use it in GitHub Desktop.
StarTrek Game (Ruby)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "curses" | |
class StarTrek | |
class DisplayIO | |
Width = Curses.cols | |
UpperH = 10 | |
def initialize | |
Curses.init_screen | |
Curses.noraw | |
Curses.echo | |
Curses.curs_set(1) #カーソルを表示する | |
@upper = Curses::Window.new(UpperH, Width, 0, 0) | |
@lower = Curses::Window.new(Curses.lines - UpperH, Width, UpperH, 0) | |
@lower.scrollok(true) | |
end | |
attr_reader :lower | |
def refresh | |
@upper.refresh | |
end | |
def long_range_sensor(ary, ship) | |
w = Quadrant::W | |
w.times do |y| | |
@upper.setpos(y, 0) | |
@upper << " " | |
w.times do |x| | |
@upper.setpos(y, x * 4 + 1) | |
@upper << ary[y * w + x] | |
end | |
end | |
x, y = ship.qx, ship.qy | |
@upper.setpos(y, x * 4) | |
@upper << "[" | |
@upper.setpos(y, x * 4 + 4) | |
@upper << "]" | |
end | |
def short_range_sensor(ship) | |
left = 4 * Quadrant::W + 2 | |
Sector::H.times do |y| | |
@upper.setpos(y, left) | |
@upper << ship.sector.field[y].join | |
end | |
@upper.setpos(ship.y, left + ship.x) | |
@upper << "E" | |
end | |
def disp_status(ary) | |
left = 4 * Quadrant::W + 2 + Sector::W + 2 | |
ary.each_with_index do |(name, value), y| | |
@upper.setpos(y, left) | |
@upper << name | |
@upper.setpos(y, left + 11) | |
@upper << value.to_s | |
end | |
end | |
def input(str) | |
@lower << str | |
@lower.getstr | |
end | |
def puts(str) | |
@lower << str.to_s + "\n" | |
end | |
def input_int(message, max) | |
begin | |
i = input(message).to_i | |
end until 1 <= i && i <= max | |
i | |
end | |
def finish | |
Curses.close_screen | |
end | |
end #----- | |
class Quadrant | |
#field, visible | |
W = 8 | |
Num = W * W | |
def initialize | |
enemy = generate(EnemiesNum, 5) | |
base = generate(BaseNum, 1) | |
star = [StarNum] * Num | |
@field = enemy.zip(base, star) | |
lrs_clear | |
end | |
attr_reader :field | |
def generate(num, max) | |
f = Array.new(Num, 0) | |
num.times do | |
begin | |
idx = rand(Num) | |
end until f[idx] <= max | |
f[idx] += 1 | |
end | |
f | |
end | |
def probe(i) | |
@visible[i] = true | |
end | |
def status | |
@field.zip(@visible).map {|sector, v| | |
if v | |
sector.join + " " | |
else | |
"*** " | |
end | |
} | |
end | |
def lrs_clear | |
@visible = Array.new(Num, false) | |
end | |
def enemy_num() @field.map(&:first).sum end | |
end #----- | |
class Sector | |
#ship, field | |
W = H = 8 | |
def initialize(ship) | |
@ship = ship | |
@field = Array.new(H) {Array.new(W) {"."}} | |
@field[@ship.y][@ship.x] = "E" | |
data = @ship.q.field[@ship.q_pos] | |
data.zip(%W(K B *)).each {|n, char| generate(n, char)} | |
end | |
attr_reader :field | |
def generate(n, char) | |
n.times do | |
begin | |
x = rand(W) | |
y = rand(H) | |
end until @field[y][x] == "." | |
@field[y][x] = char | |
end | |
end | |
def enemy_num | |
@ship.q.field[@ship.q_pos].first | |
end | |
end #----- | |
class Ship | |
#q, q_pos, x, y, io, energy, shield, photons, sector | |
include Math | |
Energy = 4000 | |
PhotonMax = 10 | |
def initialize(quadrant, io) | |
@q = quadrant | |
@io = io | |
@energy = Energy | |
@shield = 0 | |
@photons = PhotonMax | |
random_pos | |
end | |
attr_reader :q, :q_pos, :energy, :shield, :photons, :x, :y, :sector | |
def short_move | |
θ, dist = input_move(0) | |
#TODO | |
end | |
def long_move | |
#TODO: 宇宙嵐 | |
θ, dist = input_move(1) | |
x0 = qx * Sector::W + @x + dist * sin(θ) | |
y0 = qy * Sector::H + @y - dist * cos(θ) | |
x0 = (x0 / Sector::W).div(1) | |
y0 = (y0 / Sector::H).div(1) | |
return if x0 == qx && y0 == qy | |
@io.puts("Outer Sector Move") | |
if x0 < 0 || x0 >= Quadrant::W || y0 < 0 || y0 >= Quadrant::W | |
@io.puts(" Out of Range!") | |
random_pos | |
else | |
calc_pos(x0, y0) | |
end | |
end | |
def input_move(i) | |
str = %W(Short Long)[i] | |
@io.puts("\n#{str} Warp") | |
dir = @io.input_int(" direction(1-360):", 360).to_f | |
dist = @io.input_int(" distance(1-100):", 100) | |
[dir / 180 * PI, dist] | |
end | |
def random_pos | |
@q_pos = rand(Quadrant::Num) | |
@q.lrs_clear | |
jump_ship | |
end | |
def calc_pos(x0, y0) | |
@q_pos = y0 * Quadrant::W + x0 | |
jump_ship | |
end | |
def jump_ship | |
@x = rand(Sector::W) | |
@y = rand(Sector::H) | |
@sector = Sector.new(self) | |
probe | |
end | |
def probe | |
[0, -1, 1].repeated_permutation(2) do |dx, dy| | |
x0 = qx + dx | |
y0 = qy + dy | |
next if x0 < 0 || x0 >= Quadrant::W | |
next if y0 < 0 || y0 >= Quadrant::W | |
@q.probe(y0 * Quadrant::W + x0) | |
end | |
end | |
def qx() @q_pos % Quadrant::W end | |
def qy() @q_pos / Quadrant::W end | |
end #----- | |
end | |
class StarTrek | |
EnemiesNum = 25 | |
StarNum = 7 | |
BaseNum = 4 | |
def initialize | |
@io = DisplayIO.new | |
@star_date = 3500 | |
@years_left = EnemiesNum.to_f | |
@quadrant = Quadrant.new | |
@ship = Ship.new(@quadrant, @io) | |
end | |
def main_loop | |
loop do | |
screen_update | |
input_command | |
#enemy_attack | |
#break_down | |
#event(日にちの処理など) | |
#break if end? | |
end | |
finish | |
end | |
def screen_update | |
@io.long_range_sensor(@quadrant.status, @ship) | |
@io.short_range_sensor(@ship) | |
disp_status | |
@io.refresh | |
end | |
def disp_status | |
names = ["STAR DATE", "YEARS LEFT", "QUADRANT", "SECTOR", "ENERGY", | |
"SHIELD", "PHOTONS", "KLINGONS"] | |
values = [@star_date, @years_left, "#{@ship.qx + 1} - #{@ship.qy + 1}", | |
"#{@ship.x + 1} - #{@ship.y + 1}", @ship.energy, @ship.shield, | |
@ship.photons, @quadrant.enemy_num] | |
@io.disp_status(names.zip(values)) | |
end | |
def input_command | |
#TODO: シールド、フェイザー砲、光子魚雷 | |
case @io.input_int("\nCommand?(1:Short Warp, 2:Long Warp) ", 2) | |
when 1 | |
@ship.short_move | |
when 2 | |
@ship.long_move | |
end | |
end | |
def finish() @io.finish end | |
def self.sortie | |
new.main_loop | |
end | |
end | |
StarTrek.sortie | |
#故障:ロングレンジセンサー、ショートレンジセンサー、エンジン(インパルス、ワープ)、シールド、フェイザー砲、光子魚雷 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment