Skip to content

Instantly share code, notes, and snippets.

@Ragzouken
Last active March 8, 2016 07:30
Show Gist options
  • Select an option

  • Save Ragzouken/c32eb99e506363a8afdf to your computer and use it in GitHub Desktop.

Select an option

Save Ragzouken/c32eb99e506363a8afdf to your computer and use it in GitHub Desktop.
-- turn based tactics based on
-- upgrades and supply lines
-- config finish
-- ][ ][
-- ,-> switch -> report -.
-- [ ]
-- ^- supply <- action <-'
-- note: don't want to allow
-- parking heli/boat on
-- impassables, but what
-- happens when they are
-- blocked by hidden units?
--
-- "ambush" -> destroyed?
-- just allow it??
-- costs supply to wait on
-- impassable??
-- palettes
fac_pal = {
[0] = {},
{ 8, 10,
2, 9, },
{ 8, 15,
2, 4, },
{ 8, 4,
2, 5, },
}
fog_pal = {
3, 13,
11, 6,
12, 5,
}
function vcl(portrait,
move_gfx,
move_sfx,
movement,
vision)
return {
portrait = portrait,
move_gfx = move_gfx,
move_sfx = move_sfx,
movement = movement,
vision = vision,
}
end
function upgrade(portrait)
return {
portrait = portrait,
movement = 0,
vision = 0,
}
end
v_infantry = vcl(64,36,33,4,2)
v_commando = vcl(66,36,33,4,3)
v_dinghy = vcl(68,36,33,3,2)
v_apc = vcl(70,32,34,6,2)
v_chinook = vcl(72,20,32,8,5)
v_tank = vcl(74,40,34,3,2)
v_commando.supplied = true
u_none = upgrade()
u_binocs = upgrade(96)
u_mortar = upgrade(98)
u_camo = upgrade(100)
u_build = upgrade(102)
u_binocs.vision = 2
function _init()
music(8)
units = {}
supply = {}
cities = {}
timer = 0
viewer = -1
select = o_make()
path = {}
pan_x = 0
pan_y = 0
pan_d = 0
selected = nil
structure = nil
cell_filter = abs
make_unit(0,
1, 2,
v_chinook,
u_binocs)
t = make_unit(0,
5, 5,
v_tank)
phase = "config"
fog_clear(1)
for x=0,63 do
for y=0,63 do
if mget(x, y) == 9 then
city = make_city(x, y)
end
end
end
testcity = cities[1]
add(testcity.units, t)
debug = test
end
function _update()
timer += 1
-- buttons
ok = btnp(4)
done = btnp(4,1)
cancel = btnp(5)
game_input ""
-- camera panning
if pan_d then -- tour
pan_d += 0.005
pan_x = 64 + cos(pan_d) * 88
pan_y = 64 + sin(pan_d) * 88
else -- clamp camera
sx, sy = o_grid(select)
function bound(x)
return x > 104 and -2
or x < 16 and 2
or 0
end
pan_x -= bound(sx - pan_x)
+ pan_x % 2
pan_y -= bound(sy - pan_y)
+ pan_y % 2
end
pan_x = mid(0, 128, pan_x)
pan_y = mid(0, 128, pan_y)
-- animate moving unit
if mover
and timer % 4 == 0 then
d = bite(path)
if d then
sfx(mover.vehicle.move_sfx,
2)
path = unit_move(mover, d)
and path
or {}
else
city = o_get(cities, mover)
if city then
add(city.units, mover)
del(units, mover)
o_del(units, mover)
end
mover.ad, mover = 1
sfx(-1, 2)
end
end
if phase == "action" then
for unit in all(units) do
if unit.owner == viewer then
forradius(unit,
stat_vision(unit),
function(x, y)
fog_reveal(x, y, 1)
end)
end
end
end
end
function game_input()
d = arrow ""
if done
and not selected
and not structure then
if phase=="config"
or phase=="supply"
then
music(26)
phase = "switch"
pan_d = 0
path, selected = {}
viewer = (viewer + 1) % 2
fog_clear(0)
elseif phase == "switch"
then
music(0)
phase, pan_d = "action"
elseif phase == "action" then
sfx(31, 3)
phase = "supply"
for unit in all(units) do
unit.supplied = false
end
for city in all(cities) do
city.supply
= min(18, city.supply+2)
end
end
elseif phase == "action"
or phase == "supply" then
if selected then
cell_filter = fog_check
-- if cursor was moved, add
-- to path but revoke if the
-- shortened path is invalid
if d >= 0 then
o_imove(select, d)
path_add(path, d)
path_short(path)
if not unit_pass(selected, select)
or #path > stat_move(selected)
then
o_imove(select, inv(d))
pop(path)
else
sfx(30, 3)
end
end
-- confirm move or cancel
-- selection
if ok then
sfx(31, 3)
mover, selected = selected
elseif cancel then
sfx(35, 3)
path, selected = {}
end
elseif structure then
if cancel then
sfx(35, 4)
structure = nil
end
else
-- move cursor
-- x4 if cancel held
o_imove(select, d,
btn(5) and 4)
-- bound cursor to map
select.x = mid(select.x,0,31)
select.y = mid(select.y,0,31)
-- ok selects hovered
if ok and hovered then
sfx(30, 3)
if hovered.unit then
selected = hovered
elseif hovered.city then
structure, selected = hovered
end
end
end
end
hovered = o_get(units, select)
or o_get(cities, select)
end
function _draw()
cls ""
camera(pan_x, pan_y)
-- map with fog
pal_map(fog_pal)
map(0,0,0,0,32,32)
pal ""
map(64,0,0,0,32,32)
--
-- range indicator
if selected then
range = unit_range(selected)
flash(5, 13)
for c, pair in pairs(range) do
spr(53, o_grid(pair))
end
pal ""
end
-- cursor line
if selected then
pal(7, 8)
cell_filter = abs
draw_line(selected, path, 8)
end
foreach(supply, supply_draw)
if phase=="action"
or phase=="supply" then
camera(pan_x,
pan_y + pulse(16,0,1))
foreach(units, draw_unit)
camera(pan_x, pan_y)
flash(6, 7)
spr(52, o_grid(select))
pal ""
end
camera ""
if hovered
and fog_check(hovered)
then
rectfill(0, 120, 128, 128, 0)
color(7)
--print("mov "..hovered.move,
-- 1, 122)
end
if phase == "switch" then
prompt("pass to player "
.. (viewer + 1))
elseif phase == "supply" then
prompt "supply armies"
end
-- city ui
if structure then
city = structure
pal ""
rectfill( 0, 8,
128, 82, 0)
pal_map(fac_pal[1])
for i=0,3 do
unit = city.units[i+1]
x = 6 + (i%2) * 43
y = 14 + flr(i/2) * 25
rect(x-2, y-2,
x+34, y+17,
pulse(8, 2, 7))
if unit then
portrait(unit.vehicle,
x, y)
portrait(unit.upgrade,
x+17, y)
end
end
for i=0,7 do
portrait(city.store[i+1],
90 + (i%2) * 17,
12 + flr(i/2) * 17,
106)
end
spend = 4
for i=0,17 do
x = 4 + (i%9) * 9
y = 62 + flr(i/9) * 9
a = i < city.supply
b = i < city.supply - spend
spr(pulse(16, a, b)
and 54 or 55, x, y)
end
end
print(debug, 0, 0)
end
--
function prompt(s)
y = select.y < 30 and 112 or 8
rectfill(8, y,
120, y+7, 0)
color(7)
print(s, 9, y+1)
end
function fog_clear(see)
for x=0,63 do
for y=0,63 do
fog_reveal(x, y, see)
end
end
end
function fog_reveal(x, y, see)
mset(x+64, y, mget(x, y)*see)
end
function fog_check(o)
return mget(o.x+64, o.y) > 0
end
--
-- players
function supply_draw(supply)
flash(7, 6)
draw_line(supply, supply)
end
--
-- units + cities
function make_city(x, y)
city = {
city = true,
x = x,
y = y,
units = {},
store = { v_apc, u_mortar },
supply = 0,
}
add(cities, city)
o_add(cities, city)
return city
end
function make_unit(owner,
x, y,
vehicle,
upgrade)
unit = {
unit = true,
owner = owner,
x = x,
y = y,
at = 0,
ad = 0,
supplied = true,
vehicle = vehicle,
upgrade = upgrade or u_none,
}
add(units, unit)
o_add(units, unit)
return unit
end
function stat_supply(unit)
return unit.supplied
or unit.supplied
or unit.upgrade.supplied
end
function stat_move(unit)
return stat_supply(unit)
and unit.vehicle.movement
+ unit.upgrade.movement
or 0
end
function stat_vision(unit)
return stat_supply(unit)
and unit.vehicle.vision
+ unit.upgrade.vision
or 0
end
function draw_unit(unit)
pal_map(fac_pal[unit.owner])
if not fog_check(unit) then
if unit.owner == viewer then
pal_map(fog_pal)
else
return
end
end
x, y = o_grid(unit)
spr(unit.vehicle.move_gfx
+ unit.ad,
move(x, y,
bxor(unit.ad,1),
max(unit.at-timer,
0) * 2))
end
function portrait(item,
x, y,
back)
if back then
spr(back, x, y, 2, 2)
end
if item and item.portrait then
spr(item.portrait,x,y,2,2)
end
end
function unit_pass(u, o)
tile = mget(pos(o))
wall = fget(tile, 7)
unit = cell_filter(o)
and o_get(units, o)
return (not unit or u == unit)
and not wall
end
function unit_move(unit, d)
cell_filter = abs
if unit_pass(unit,
o_move(unit, d))
then
unit.ad = d
unit.at = timer + 4
o_del(units, unit)
o_imove(unit, d)
o_add(units, unit)
return true
end
end
function unit_range(unit)
dists = {}
check = { select }
found = {}
limit = stat_move(unit)
- #path
repeat
prev = bite(check)
l = o_get(dists, prev, 0) + 1
for d=0,3 do
pair = o_copy(prev)
pair.d = l
o_imove(pair, d)
if l < o_get(dists,
pair,
999)
and l <= limit
and unit_pass(unit, pair)
then
add(check, pair)
o_add(found, pair)
o_add(dists, pair, l)
end
end
until #check == 0
return found
end
--
-- utility
function bite(t)
v = t[1]
del(t, v)
return v
end
function pop(t)
v, t[#t] = t[#t]
return v
end
function flash(a, b)
pal(7, pulse(8, a, b))
end
function pulse(p, a, b)
return timer % p < p/2 and a
or b
end
function o_make(x, y)
return { x = x or 0,
y = y or 0 }
end
function o_coord(o)
return o.x .. "," .. o.y
end
function o_grid(o)
return o.x * 8, o.y * 8
end
function o_add(t, o, v)
t[o] = v or o
t[o_coord(o)] = v or o
end
function o_get(t, o, v)
return t[o_coord(o)] or v
end
function o_del(t, o)
t[o] = nil
t[o_coord(o)] = nil
end
function o_copy(o)
return o_make(pos(o))
end
function pos(o)
return o.x, o.y
end
function inv(d)
return d%2 == 0 and d+1 or d-1
end
function move(x, y, d, l)
l = l or 1
if (d == 0) x -= l
if (d == 1) x += l
if (d == 2) y -= l
if (d == 3) y += l
return x, y
end
function o_move(o, d, l)
return o_make(move(o.x, o.y,
d, l))
end
function o_imove(o, d, l)
o.x, o.y = move(o.x, o.y, d, l)
return pos(o)
end
function arrow()
for i=0,3 do
if (btnp(i)) return i
end
return -1
end
function dist(sx, sy,
ex, ey)
return abs(sx - ex)
+ abs(sy - ey)
end
function forradius(o, r, action)
cx, cy = pos(o)
for x=cx-r,cx+r do
for y=cy-r,cy+r do
d = dist(x, y, cx, cy)
if (d <= r) action(x, y, d)
end
end
end
function pal_map(m)
for i=1,#m,2 do
pal(m[i], m[i+1])
end
end
function draw_line(o, path)
for d in all(path) do
if cell_filter(o) then
spr(48+d, o_grid(o))
end
o = o_move(o, d)
if cell_filter(o) then
spr(48+inv(d), o_grid(o))
end
end
end
function path_add(path, d)
last = path[#path] or -1
if d == inv(last) then
pop(path)
else
add(path, d)
end
end
function path_short(path)
seen = {}
o = o_make()
o_add(seen, o, 1)
for i=1,#path do
o_imove(o, path[i])
j = o_get(seen, o)
if j then
for v=j,#path do
path[v] = nil
end
else
o_add(seen, o, i + 1)
end
end
return seen
end
--
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment