diff --git a/source/ai.f90 b/source/ai.f90 new file mode 100644 index 0000000..af9ef49 --- /dev/null +++ b/source/ai.f90 @@ -0,0 +1,7 @@ +subroutine fairy_synchronize (level) + + implicit none + integer, intent (in) :: level + write (*, '(a)', advance='no') "Heyo Fortran!" + +end subroutine fairy_synchronize diff --git a/source/attribute.adb b/source/attribute.adb new file mode 100644 index 0000000..c8aea5f --- /dev/null +++ b/source/attribute.adb @@ -0,0 +1,16 @@ +with core, attribute; + +use attribute; + +package body attribute is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + procedure draw (value : in codex; x, y : in integer) is + begin + null; + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end attribute; diff --git a/source/attribute.ads b/source/attribute.ads new file mode 100644 index 0000000..da00136 --- /dev/null +++ b/source/attribute.ads @@ -0,0 +1,38 @@ +with core; + +package attribute is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type codex is ( + attack, defense, power, knowledge + ); + + ------------------------------------------------------------------------------------------ + + subtype base_limit is natural range 0 .. 12; + + type information is + record + name : core.short_string; + base : base_limit; + end record; + + type trait_array is array (codex) of information; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + ("Attack ", 0), + ("Defense ", 0), + ("Power ", 0), + ("Knowledge ", 0) + ); + + ------------------------------------------------------------------------------------------ + + procedure draw (value : in codex; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end attribute; diff --git a/source/construction.adb b/source/construction.adb new file mode 100644 index 0000000..a88edcf --- /dev/null +++ b/source/construction.adb @@ -0,0 +1,39 @@ +with core, menu, effect, resource, faction, construction; + +use construction; + +package body construction is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type sprite_array is array (codex) of core.sprite; + + ------------------------------------------------------------------------------------------ + + sprite : sprite_array; + + ------------------------------------------------------------------------------------------ + + procedure configure is + begin + for index in codex + loop + declare + folder : constant string := core.lowercase (faction.codex'image (trait (index).kind)); + file : constant string := core.lowercase (codex'image (index)); + begin + sprite (index) := core.load_sprite ("sprite/construction/" & folder & "/" & file & ".png", trait (index).frames, 1); + end; + end loop; + end configure; + + ------------------------------------------------------------------------------------------ + + procedure draw (index : in codex; x, y : in integer) is + begin + core.move (sprite (index), x, y, trait (index).frames, 1); + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end construction; diff --git a/source/construction.ads b/source/construction.ads new file mode 100644 index 0000000..b0725bf --- /dev/null +++ b/source/construction.ads @@ -0,0 +1,158 @@ +with core, menu, effect, resource, faction; + +package construction is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type codex is ( + boar_glen, enchanters_hollow, hovel, nomad_tent, rogue_cavern, thatched_hut, + trolls_bridge, crystalized_cave, frozen_cliffs, magic_forest, pyramid, sulfurous_lair, + treetop_tower, + -- + guardhouse, watchtower, griffin_tower, barracks, monastery, training_grounds, + holy_portal, + -- + goblin_shed, wolf_pen, orc_tower, ogre_fort, cliff_nest, cyclops_cave, + behemoth_lair, + -- + imp_crucible, hall_of_sins, kennels, demon_gate, hell_hole, fire_lake, + forsaken_palace, + -- + workshop, parapet, golem_factory, mage_tower, altar_of_wishes, golden_pavilion, + cloud_temple, + -- + little_lantern, air_shrine, water_shrine, fire_shrine, earth_shrine, magic_shrine, + flamewhirl, + -- + cursed_shrine, graveyard, tomb_of_souls, estate, mausoleum, hall_of_darkness, + bone_vault, + -- + centaur_stables, dwarf_cottage, homestead, enchanted_spring, dendroid_arches, unicorn_glades, + dragon_cliffs, + -- + gnoll_hut, lizard_den, dragonfly_hive, basilisk_pit, gorgon_lair, wyvern_nest, + hydra_pond, + -- + warren, harpy_loft, pillar_of_eyes, chappel_of_voice, labyrinth, manticore_lair, + dragon_cave + ); + + ------------------------------------------------------------------------------------------ + + subtype grade_limit is natural range 0 .. 3; + subtype level_limit is natural range 0 .. 6; + + type information is + record + name : core.short_string; + kind : faction.codex; + level : level_limit; + grade : grade_limit; + price : resource.value; + frames : integer; + evoke : effect.codex; + show : menu.codex; + end record; + + type trait_array is array (codex) of information; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + -- Remove me later... Lv Gr Gold Wd Mr Or Sl Cr Gm + ("Boar Glen ", faction.neutral, 1, 1, ( 90, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Enchanter's Hollow ", faction.neutral, 1, 1, (120, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Hovel ", faction.neutral, 2, 1, (180, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Nomad Tent ", faction.neutral, 3, 1, (240, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Rogue Cavern ", faction.neutral, 3, 1, (180, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Thatched Hut ", faction.neutral, 4, 1, (300, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Troll's Bridge ", faction.neutral, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Crystalized Cave ", faction.neutral, 1, 1, ( 90, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Frozen Cliffs ", faction.neutral, 1, 1, (120, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Magic Forest ", faction.neutral, 2, 1, (180, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Pyramid ", faction.neutral, 3, 1, (240, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Sulfurous Lair ", faction.neutral, 3, 1, (180, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Treetop Tower ", faction.neutral, 4, 1, (300, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + -- + ("Guardhouse ", faction.castle, 1, 1, ( 90, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Watchtower ", faction.castle, 1, 1, (120, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Griffin Tower ", faction.castle, 2, 1, (180, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Barracks ", faction.castle, 3, 1, (240, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Monastery ", faction.castle, 3, 1, (180, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Training Grounds ", faction.castle, 4, 1, (300, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Holy Portal ", faction.castle, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + -- + ("Goblin Shed ", faction.stronghold, 1, 1, ( 90, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Wolf Pen ", faction.stronghold, 1, 1, (120, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Orc Tower ", faction.stronghold, 2, 1, (180, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Ogre Fort ", faction.stronghold, 3, 1, (240, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Cliff Nest ", faction.stronghold, 3, 1, (180, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Cyclops Cave ", faction.stronghold, 4, 1, (300, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Behemoth Lair ", faction.stronghold, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + -- + ("Imp Crucible ", faction.inferno, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Hall of Sins ", faction.inferno, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Kennels ", faction.inferno, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Demon Gate ", faction.inferno, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Hell Hole ", faction.inferno, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Fire Lake ", faction.inferno, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Forsaken Palace ", faction.inferno, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + -- + ("Workshop ", faction.tower, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Parapet ", faction.tower, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Golem Factory ", faction.tower, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Mage Tower ", faction.tower, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Altar of Wishes ", faction.tower, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Golden Pavilion ", faction.tower, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Cloud Temple ", faction.tower, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + -- + ("Little Lantern ", faction.conflux, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Air Shrine ", faction.conflux, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Water Shrine ", faction.conflux, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Fire Shrine ", faction.conflux, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Earth Shrine ", faction.conflux, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Magic Shrine ", faction.conflux, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Flamewhirl ", faction.conflux, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + -- + ("Cursed Shrine ", faction.necropolis, 1, 1, ( 90, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Graveyard ", faction.necropolis, 1, 1, (120, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Tomb of Souls ", faction.necropolis, 2, 1, (180, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Estate ", faction.necropolis, 3, 1, (240, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Mausoleum ", faction.necropolis, 3, 1, (180, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Hall of Darkness ", faction.necropolis, 4, 1, (300, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Bone Vault ", faction.necropolis, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + -- + ("Centaur Stables ", faction.rampart, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Dwarf Cottage ", faction.rampart, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Homestead ", faction.rampart, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Enchanted Spring ", faction.rampart, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Dendroid Arches ", faction.rampart, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Unicorn Glades ", faction.rampart, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Dragon Cliffs ", faction.rampart, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + -- + ("Gnoll Hut ", faction.fortress, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Lizard Den ", faction.fortress, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Dragonfly Hive ", faction.fortress, 5, 1, (360, 0, 0, 0, 0, 0, 0), 3, effect.none, menu.none), + ("Basilisk Pit ", faction.fortress, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Gorgon Lair ", faction.fortress, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Wyvern Next ", faction.fortress, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Hydra Pond ", faction.fortress, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + -- + ("Warren ", faction.dungeon, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Harpy Loft ", faction.dungeon, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Pillar of Eyes ", faction.dungeon, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Chappel of Voice ", faction.dungeon, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Labyrinth ", faction.dungeon, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Manticore Lair ", faction.dungeon, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none), + ("Dragon Cave ", faction.dungeon, 5, 1, (360, 0, 0, 0, 0, 0, 0), 1, effect.none, menu.none) + ); + + ------------------------------------------------------------------------------------------ + + procedure configure; + + procedure draw (index : in codex; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end construction; diff --git a/source/core.adb b/source/core.adb new file mode 100644 index 0000000..466f252 --- /dev/null +++ b/source/core.adb @@ -0,0 +1,166 @@ +with core; + +use core; + +package body core is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + function flip_coin return integer is + begin + return (random_integer (0, 1)); + end flip_coin; + + ------------------------------------------------------------------------------------------ + + function roll_dice return integer is + begin + return (random_integer (1, 6)); + end roll_dice; + + ------------------------------------------------------------------------------------------ + + function by_chance (chance : in integer) return integer is + begin + return (random_integer (0, 100) mod chance); + end by_chance; + + ------------------------------------------------------------------------------------------ + + function sigmoid (value : in boolean) return integer is + begin + return (if value then -1 else 1); + end sigmoid; + + ------------------------------------------------------------------------------------------ + + function c_string (ada_string : string) return string is + begin + return (ada_string & character'val (0)); + end c_string; + + ------------------------------------------------------------------------------------------ + + function load_sprite (file_path : in string; frames, states : in integer) return sprite is + this : sprite; + begin + this.index := import_sprite (c_string (file_path)); + this.width := sprite_width (this.index) / states; + this.height := sprite_height (this.index) / frames; + this.frames := frames; + this.states := states; + -- + return this; + end load_sprite; + + ------------------------------------------------------------------------------------------ + + procedure crop (data : in sprite; x, y, u, v, width, height : in integer) is + begin + render_sprite (data.index, x, y, u, v, width, height); + end crop; + + ------------------------------------------------------------------------------------------ + + procedure draw (data : in sprite; x, y : in integer) is + begin + render_sprite (data.index, x, y, 0, 0, data.width, data.height); + end draw; + + ------------------------------------------------------------------------------------------ + + procedure move (data : in sprite; x, y, frame, state : in integer) is + begin + render_sprite (data.index, x, y, state * data.width, (animation_time mod frame) * data.height, data.width, data.height); + end move; + + ------------------------------------------------------------------------------------------ + + procedure write (text : in string; x, y : in integer) is + begin + null; + end write; + + ------------------------------------------------------------------------------------------ + + procedure hexagonal_grid (x, y, width, height : in integer; fill : in boolean) is + crop_width : constant integer := width mod hexagon_grid_sprite.width; + crop_height : constant integer := height mod hexagon_grid_sprite.height; + use_sprite : constant sprite := (if fill then hexagon_fill_sprite else hexagon_grid_sprite); + --~u, v : integer; + begin + for move_y in 0 .. height / hexagon_grid_sprite.height - 1 + loop + for move_x in 0 .. width / hexagon_grid_sprite.width - 1 + loop + --~u := hexagon_grid_sprite.width * codex'pos (map.terrain) * 4; + --~v := hexagon_grid_sprite.height * map.block (move_x, move_y); + -- + draw (use_sprite, x + move_x * hexagon_grid_sprite.width, y + move_y * hexagon_grid_sprite.height); + end loop; + -- + --~u := 0; + --~v := hexagon_grid_sprite.height * map.block (width / hexagon_grid_sprite.width, move_y); + -- + crop (use_sprite, x + width - crop_width, y + move_y * hexagon_grid_sprite.height, 0, 0, crop_width, hexagon_grid_sprite.height); + end loop; + -- + for move_x in 0 .. width / hexagon_grid_sprite.width - 1 + loop + --~u := 0; + --~v := hexagon_grid_sprite.height * map.block (move_x, height / hexagon_grid_sprite.height); + -- + crop (use_sprite, x + move_x * hexagon_grid_sprite.width, y + height - crop_height, 0, 0, hexagon_grid_sprite.width, crop_height); + end loop; + -- + --~u := 0; + --~v := hexagon_grid_sprite.height * map.block (width / hexagon_grid_sprite.width, height / hexagon_grid_sprite.height); + -- + crop (use_sprite, x + width - crop_width, y + height - crop_height, 0, 0, crop_width, crop_height); + --~begin + --~for y in 0 .. window_height / 48 + --~loop + --~for x in 0 .. window_width / 32 + --~loop + --~draw ((if fill then hexagon_fill_sprite else hexagon_grid_sprite), x * hexagon_grid_sprite.width, y * hexagon_grid_sprite.height); + --~end loop; + --~end loop; + end hexagonal_grid; + + ------------------------------------------------------------------------------------------ + + function lowercase (text : in string) return string is + result : string (1 .. text'length); + begin + for index in text'range + loop + if text (index) in 'A' .. 'Z' then + result (index) := character'val (character'pos (text (index)) + 32); + else + result (index) := text (index); + end if; + end loop; + -- + return result; + end lowercase; + + ------------------------------------------------------------------------------------------ + + function uppercase (text : in string) return string is + result : string (1 .. text'length); + begin + for index in text'range + loop + if text (index) in 'a' .. 'z' then + result (index) := character'val (character'pos (text (index)) - 32); + else + result (index) := text (index); + end if; + end loop; + -- + return result; + end uppercase; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end core; diff --git a/source/core.ads b/source/core.ads new file mode 100644 index 0000000..a8ea816 --- /dev/null +++ b/source/core.ads @@ -0,0 +1,107 @@ +with ada.text_io, ada.strings, interfaces.c; +use ada.text_io, ada.strings, interfaces.c; + +package core is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type signal_code is ( + signal_none, signal_space, signal_zero, signal_one, signal_two, signal_three, + signal_four, signal_five, signal_six, signal_seven, signal_eight, signal_nine, + signal_a, signal_b, signal_c, signal_d, signal_e, signal_f, + signal_g, signal_h, signal_i, signal_j, signal_k, signal_l, + signal_m, signal_n, signal_o, signal_p, signal_q, signal_r, + signal_s, signal_t, signal_u, signal_v, signal_w, signal_x, + signal_y, signal_z, signal_grave, signal_escape, signal_enter, signal_tab, + signal_backspace, signal_right, signal_left, signal_down, signal_up, signal_kp_0, + signal_kp_1, signal_kp_2, signal_kp_3, signal_kp_4, signal_kp_5, signal_kp_6, + signal_kp_7, signal_kp_8, signal_kp_9, signal_kp_subtract, signal_kp_add, signal_left_shift, + signal_left_control + ); + + subtype short_string is string (1 .. 24); + subtype long_string is string (1 .. 160); + + type sprite is + record + index, width, height, frames, states : integer; + end record; + + type vector_2 is + record + x, y : integer; + end record; + + ------------------------------------------------------------------------------------------ + + -- C + + cursor_x : integer with import => true, convention => c; + cursor_y : integer with import => true, convention => c; + cursor_mode : integer with import => true, convention => c; + signal_mode : integer with import => true, convention => c; + engine_active : boolean with import => true, convention => c; + + ------------------------------------------------------------------------------------------ + + base : constant natural := 32; + gameplay_framerate : constant natural := 60; + animation_framerate : constant natural := 6; + + global_time : natural := 0; + gameplay_time : natural := 0; + animation_time : natural := 0; + + hexagon_grid_sprite : sprite; + hexagon_fill_sprite : sprite; + + camera : vector_2 := (0, 0); + + ------------------------------------------------------------------------------------------ + + -- C + + function random_integer (minimum, maximum : in integer) return integer with import => true, convention => c; + + procedure engine_configure with import => true, convention => c; + procedure engine_synchronize with import => true, convention => c; + + function window_width return integer with import => true, convention => c; + function window_height return integer with import => true, convention => c; + + procedure render_sprite (sprite, x, y, u, v, width, height : in integer) with import => true, convention => c; + procedure render_string (text : in string; x, y, colour : in integer; monospace : in boolean) with import => true, convention => c; + + function import_sprite (file_path : in string) return integer with import => true, convention => c; + function sprite_width (index : in integer) return integer with import => true, convention => c; + function sprite_height (index : in integer) return integer with import => true, convention => c; + + ------------------------------------------------------------------------------------------ + + -- Fortran + + procedure fairy_synchronize (level : in integer) with import => true, convention => fortran; + + ------------------------------------------------------------------------------------------ + + function flip_coin return integer; + function roll_dice return integer; + function by_chance (chance : in integer) return integer; + function sigmoid (value : in boolean) return integer; + function c_string (ada_string : in string) return string; + + function load_sprite (file_path : in string; frames, states : in integer) return sprite; + + procedure crop (data : in sprite; x, y, u, v, width, height : in integer); + procedure draw (data : in sprite; x, y : in integer); + procedure move (data : in sprite; x, y, frame, state : in integer); + procedure write (text : in string; x, y : in integer); + + procedure hexagonal_grid (x, y, width, height : in integer; fill : in boolean); + + function lowercase (text : in string) return string; + function uppercase (text : in string) return string; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end core; diff --git a/source/deity.adb b/source/deity.adb new file mode 100644 index 0000000..6312293 --- /dev/null +++ b/source/deity.adb @@ -0,0 +1,20 @@ +with core, deity; + +use deity; + +package body deity is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + sprite : core.sprite; + + ------------------------------------------------------------------------------------------ + + procedure draw (value : in codex; x, y : in integer) is + begin + null; + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end deity; diff --git a/source/deity.ads b/source/deity.ads new file mode 100644 index 0000000..61bef59 --- /dev/null +++ b/source/deity.ads @@ -0,0 +1,47 @@ +with core; + +package deity is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type codex is ( + svarog, dabog, svetovid, gozag, ru, xom, + sheigarath, ornhul, khuganagoth, vel_sheina, deigehen, geazhul + ); + + ------------------------------------------------------------------------------------------ + + subtype piety_limit is natural range -30 .. 30; + + type information is + record + name : core.short_string; + base : piety_limit; + end record; + + type trait_array is array (codex) of information; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + ("Svarog the Lawful ", 3), -- Serbia + ("Dabog the Lonely ", -3), + ("Svetovid the Awakened ", 0), + ("Gozag the Impoverished ", 0), -- DCSS + ("Ru the Forgotten ", -3), + ("Xom the Chaotical ", 3), + ("Sheigarath the Dark ", -3), -- Gea + ("Ornhul the Frozen ", 0), + ("Khuganagoth the Hungry ", -3), + ("Vel-Sheina the Joyful ", 3), + ("Deigehen the Chained ", 0), + ("Geazhul the Awakened ", 3) + ); + + ------------------------------------------------------------------------------------------ + + procedure draw (value : in codex; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end deity; diff --git a/source/effect.adb b/source/effect.adb new file mode 100644 index 0000000..3718963 --- /dev/null +++ b/source/effect.adb @@ -0,0 +1,20 @@ +with core, effect; + +use effect; + +package body effect is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + sprite : core.sprite; + + ------------------------------------------------------------------------------------------ + + procedure draw (value : in codex; x, y : in integer) is + begin + null; + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end effect; diff --git a/source/effect.ads b/source/effect.ads new file mode 100644 index 0000000..295fe2f --- /dev/null +++ b/source/effect.ads @@ -0,0 +1,34 @@ +with core; + +package effect is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type codex is ( + none, one + ); + + ------------------------------------------------------------------------------------------ + + type information is + record + name : core.short_string; + make : boolean; + end record; + + type trait_array is array (codex) of information; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + ("- ", true), + ("- ", true) + ); + + ------------------------------------------------------------------------------------------ + + procedure draw (value : in codex; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end effect; diff --git a/source/faction.adb b/source/faction.adb new file mode 100644 index 0000000..311caf1 --- /dev/null +++ b/source/faction.adb @@ -0,0 +1,16 @@ +with core, attribute, skill, resource, faction; + +use faction; + +package body faction is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + procedure draw (value : in codex; x, y : in integer) is + begin + null; + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end faction; diff --git a/source/faction.ads b/source/faction.ads new file mode 100644 index 0000000..c316592 --- /dev/null +++ b/source/faction.ads @@ -0,0 +1,45 @@ +with core, attribute, skill, resource; + +package faction is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type codex is ( + neutral, castle, stronghold, inferno, tower, conflux, + necropolis, rampart, fortress, dungeon + ); + + ------------------------------------------------------------------------------------------ + + type information is + record + name : core.short_string; + attribute_bonus : attribute.codex; + skill_bonus : skill.codex; + resource_bonus : resource.codex; + end record; + + type trait_array is array (codex) of information; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + ("Neutral ", attribute.attack, skill.tactics, resource.gold), + ("Castle ", attribute.attack, skill.archery, resource.ore), + ("Stronghold ", attribute.defense, skill.offense, resource.wood), + ("Inferno ", attribute.power, skill.fire_magic, resource.mercury), + ("Tower ", attribute.knowledge, skill.intelligence, resource.gem), + ("Conflux ", attribute.knowledge, skill.sorcery, resource.gem), + ("Necropolis ", attribute.attack, skill.necromancy, resource.sulfur), + ("Rampart ", attribute.defense, skill.scouting, resource.crystal), + ("Fortress ", attribute.defense, skill.resistance, resource.mercury), + ("Dungeon ", attribute.power, skill.archery, resource.ore) + ); + + ------------------------------------------------------------------------------------------ + + procedure draw (value : in codex; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end faction; diff --git a/source/item.adb b/source/item.adb new file mode 100644 index 0000000..7246558 --- /dev/null +++ b/source/item.adb @@ -0,0 +1,40 @@ +with core, item; + +use item; + +package body item is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type sprite_array is array (codex) of core.sprite; + + ------------------------------------------------------------------------------------------ + + sprite : sprite_array; + + ------------------------------------------------------------------------------------------ + + procedure configure is + begin + for index in codex + loop + --~declare + --~folder : constant string := core.lowercase (school'image (trait (index).kind)); + --~file : constant string := core.lowercase (codex'image (index)); + --~begin + --~icon (index) := core.load_sprite ("sprite/ui/item/" & folder & "/" & file & ".png", 1, 1); + --~end; + sprite (index) := core.load_sprite ("sprite/ui/item/" & core.lowercase (codex'image (index)) & ".png", 1, 1); + end loop; + end configure; + + ------------------------------------------------------------------------------------------ + + procedure draw (index : in codex; x, y : in integer) is + begin + core.draw (sprite (index), x, y); + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end item; diff --git a/source/item.ads b/source/item.ads new file mode 100644 index 0000000..d9e8d0a --- /dev/null +++ b/source/item.ads @@ -0,0 +1,199 @@ +with core, effect; + +package item is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type slot is ( + main_hand, off_hand, head, chest, neck, full_body, + finger, feet, hands, bag + ); + + type codex is ( + admirals_hat, ambassadors_sash, undertakers_amulet, angel_feather_arrows, angelic_alliance, angel_wings, + armageddons_blade, armor_of_the_damned, armor_of_wonder, arms_of_legion, badge_of_courage, bird_of_perception, + blackshard, boots_of_levitation, boots_of_polarity, boots_of_speed, elven_bow, sharpshooters_bow, + unicorns_string, brimstone_armour, wooden_breastplate, gnolls_buckler, cape_of_conjuring, cape_of_velocity, + cards_of_prophecy, celestial_necklace, centaurs_axe, charm_of_mana, balanced_cloak, clover_of_fortune, + collar_of_conjuring, cornucopia, crest_of_valor, crown_of_dragontooth, crown_of_magician, dead_mans_boots, + diplomats_ring, dragonbone_greaves, dragon_scale_armor, dragon_scale_shield, dragon_wing_tabard, elixir_of_life, + emblem_of_cognizance, endless_bag_of_gold, endless_purse_of_gold, endless_sack_of_gold, equestrians_gloves, everflowing_crystal, + vial_of_mercury, ring_of_sulfur, interference_choker, glyph_of_gallantry, golden_bow, greater_gnolls_flail, + head_of_legion, hellstorm_helmet, helm_of_chaos, helm_of_heavens, helm_of_the_alabaster, evil_hour, + cart_of_lumber, cart_of_ore, ladybird_of_luck, legs_of_legion, shield_of_courage, loins_of_legion, + mystic_orb_of_mana, dragonteeth_necklace, ocean_guidance, necklace_of_swiftness, ogres_club_of_havoc, orb_of_driving_rain, + orb_of_inhibition, orb_of_silt, orb_of_hell_tempest, orb_of_the_firmament, orb_of_vulnerability, pendant_of_courage, + pendant_of_death, pendant_of_dispassion, pendant_of_free_will, pendant_of_holiness, pendant_of_life, pendant_of_negativity, + pendant_of_renderer, pendant_of_memory, dragon_father_armour, quiet_eye, recanters_cloak, flammenwerfer, + rib_cage, ring_of_conjuring, ring_of_infinite_gems, ring_of_life, ring_of_the_magi, ring_of_the_wayfarer, + ring_of_vitality, sandals_of_the_saint, basilisk_chestplate, sea_captains_hat, sentinels_shield, shackles_of_war, + fortrans_shield, oakenshield, undead_shield, skull_helmet, speculum, spellbinders_hat, + sphere_of_permanence, spirit_of_oppression, spyglass, statesmans_medal, statue_of_legion, cs_ring, + stoic_watchman, counterpoise, sword_of_hellfire, adas_claymore, talisman_of_mana, targ, + thunder_helmet, titans_cuirass, titans_gladius, titans_thunder, tome_of_air, tome_of_earth, + tome_of_fire, tome_of_water, torso_of_legion, cyclops_tunic, vampires_cowl, vial_of_dragon_blood, + vial_of_lifeblood, wizards_well + ); + + ------------------------------------------------------------------------------------------ + + subtype level_limit is natural range 0 .. 3; + + type information is + record + name : core.short_string; + kind : slot; + level : level_limit; + evoke : effect.codex; + end record; + + type trait_array is array (codex) of information; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + ("Admiral's Hat ", head, 0, effect.none), + ("Ambassador's Sash ", full_body, 0, effect.none), + ("Undertaker's Amulet ", neck, 1, effect.none), + ("Angel Feather Arrows ", bag, 1, effect.none), + ("Angelic Alliance ", main_hand, 2, effect.none), + ("Angel Wings ", full_body, 2, effect.none), + ("Armageddon's Blade ", main_hand, 3, effect.none), + ("Armor of The Damned ", chest, 3, effect.none), + ("Armor of Wonder ", chest, 0, effect.none), + ("Arms of Legion ", bag, 0, effect.none), + ("Badge of Courage ", bag, 1, effect.none), + ("Bird of Perception ", bag, 1, effect.none), + ("Blackshard ", main_hand, 2, effect.none), + ("Boot's of Levitation ", feet, 2, effect.none), + ("Boot's of Polarity ", feet, 3, effect.none), + ("Boot's of Speed ", feet, 3, effect.none), + ("Elven Bow ", off_hand, 0, effect.none), + ("Sharpshooter's Bow ", off_hand, 0, effect.none), + ("Unicorn's String ", bag, 1, effect.none), + ("Brimstone Armour ", chest, 1, effect.none), + ("Wooden Breastplate ", chest, 2, effect.none), + ("Gnoll's Buckler ", off_hand, 2, effect.none), + ("Cape of Conjuring ", full_body, 3, effect.none), + ("Cape of Velocity ", full_body, 3, effect.none), + ("Card's of Prophecy ", bag, 0, effect.none), + ("Celestial Necklace ", neck, 0, effect.none), + ("Centaur's Axe ", main_hand, 1, effect.none), + ("Charm of Mana ", neck, 1, effect.none), + ("Balanced Cloak ", full_body, 2, effect.none), + ("Clover of Fortune ", bag, 2, effect.none), + ("Collar of Conjuring ", neck, 3, effect.none), + ("Cornucopia ", bag, 3, effect.none), + ("Crest of Valor ", bag, 0, effect.none), + ("Crown of Dragontooth ", head, 0, effect.none), + ("Crown of Magician ", head, 1, effect.none), + ("Dead Man's Boots ", feet, 1, effect.none), + ("Diplomat's Ring ", finger, 2, effect.none), + ("Dragonbone Greaves ", feet, 2, effect.none), + ("Dragon Scale Armor ", chest, 3, effect.none), + ("Dragon Scale Shield ", off_hand, 3, effect.none), + ("Dragon Wing Tabard ", full_body, 0, effect.none), + ("Elixir of Life ", bag, 0, effect.none), + ("Emblem of Cognizance ", neck, 1, effect.none), + ("Endles's Bag of Gold ", bag, 1, effect.none), + ("Endles's Purse of Gold ", bag, 2, effect.none), + ("Endles's Sack of Gold ", bag, 2, effect.none), + ("Equestrian's Gloves ", hands, 3, effect.none), + ("Everflowing Crystal ", full_body, 3, effect.none), + ("Vial of Mercury ", bag, 0, effect.none), + ("Ring of Sulfur ", finger, 0, effect.none), + ("Interference Choker ", neck, 1, effect.none), + ("Glyph of Gallantry ", bag, 1, effect.none), + ("Golden Bow ", off_hand, 2, effect.none), + ("Greater Gnoll's Flail ", main_hand, 2, effect.none), + ("Head of Legion ", bag, 3, effect.none), + ("Hellstorm Helmet ", head, 3, effect.none), + ("Helm of Chaos ", head, 0, effect.none), + ("Helm of Heavens ", head, 0, effect.none), + ("Helm of The Alabaster ", head, 1, effect.none), + ("Evil Hour ", bag, 1, effect.none), + ("Cart of Lumber ", bag, 2, effect.none), + ("Cart of Ore ", bag, 2, effect.none), + ("Ladybird of Luck ", bag, 3, effect.none), + ("Leg's of Legion ", bag, 3, effect.none), + ("Shield of Courage ", off_hand, 0, effect.none), + ("Loin's of Legion ", bag, 0, effect.none), + ("Mystic Orb of Mana ", neck, 0, effect.none), + ("Dragonteeth Necklace ", neck, 0, effect.none), + ("Ocean Guidance ", neck, 0, effect.none), + ("Necklace of Swiftness ", neck, 0, effect.none), + ("Ogre's Club of Havoc ", main_hand, 0, effect.none), + ("Orb of Driving Rain ", bag, 0, effect.none), + ("Orb of Inhibition ", bag, 1, effect.none), + ("Orb of Silt ", bag, 1, effect.none), + ("Orb of Hell Tempest ", bag, 1, effect.none), + ("Orb of The Firmament ", bag, 1, effect.none), + ("Orb of Vulnerability ", bag, 1, effect.none), + ("Pendant of Courage ", neck, 1, effect.none), + ("Pendant of Death ", neck, 1, effect.none), + ("Pendant of Dispassion ", neck, 1, effect.none), + ("Pendant of Free Will ", neck, 2, effect.none), + ("Pendant of Holiness ", neck, 2, effect.none), + ("Pendant of Life ", neck, 2, effect.none), + ("Pendant of Negativity ", neck, 2, effect.none), + ("Pendant of Renderer ", neck, 2, effect.none), + ("Pendant of Memory ", neck, 2, effect.none), + ("Dragon Father Armour ", chest, 2, effect.none), + ("Quiet Eye ", finger, 2, effect.none), + ("Recanter's Cloak ", full_body, 3, effect.none), + ("Flammenwerfer ", main_hand, 3, effect.none), + ("Rib Cage ", chest, 3, effect.none), + ("Ring of Conjuring ", finger, 3, effect.none), + ("Ring of Infinite Gems ", finger, 3, effect.none), + ("Ring of Life ", finger, 3, effect.none), + ("Ring of The Magi ", finger, 3, effect.none), + ("Ring of The Wayfarer ", finger, 3, effect.none), + ("Ring of Vitality ", finger, 3, effect.none), + ("Sandal's of The Saint ", feet, 3, effect.none), + ("Basilisk Chestplate ", chest, 3, effect.none), + ("Sea Captain's Hat ", head, 3, effect.none), + ("Sentinel's Shield ", off_hand, 3, effect.none), + ("Shackle's of War ", hands, 3, effect.none), + ("Fortran's Shield ", off_hand, 3, effect.none), + ("Oakenshield ", off_hand, 3, effect.none), + ("Undead Shield ", off_hand, 3, effect.none), + ("Skull Helmet ", head, 3, effect.none), + ("Speculum ", bag, 3, effect.none), + ("Spellbinder's Hat ", head, 3, effect.none), + ("Sphere of Permanence ", bag, 3, effect.none), + ("Spirit of Oppression ", bag, 3, effect.none), + ("Spyglass ", bag, 3, effect.none), + ("Statesman's Medal ", neck, 3, effect.none), + ("Statue of Legion ", bag, 3, effect.none), + ("C's Ring ", finger, 3, effect.none), + ("Stoic Watchman ", bag, 3, effect.none), + ("Counterpoise ", full_body, 3, effect.none), + ("Sword of Hellfire ", main_hand, 3, effect.none), + ("Ada's Claymore ", main_hand, 3, effect.none), + ("Talisman of Mana ", bag, 3, effect.none), + ("Targ ", off_hand, 3, effect.none), + ("Thunder Helmet ", head, 3, effect.none), + ("Titan's Cuirass ", chest, 3, effect.none), + ("Titan's Gladius ", main_hand, 3, effect.none), + ("Titan's Thunder ", main_hand, 3, effect.none), + ("Tome of Air ", bag, 3, effect.none), + ("Tome of Earth ", bag, 3, effect.none), + ("Tome of Fire ", bag, 3, effect.none), + ("Tome of Water ", bag, 3, effect.none), + ("Torso of Legion ", bag, 3, effect.none), + ("Cyclop's Tunic ", chest, 3, effect.none), + ("Vampire's Cowl ", full_body, 3, effect.none), + ("Vial of Dragon Blood ", bag, 3, effect.none), + ("Vial of Lifeblood ", bag, 3, effect.none), + ("Wizard's Well ", bag, 3, effect.none) + ); + + ------------------------------------------------------------------------------------------ + + procedure configure; + + procedure draw (index : in codex; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end item; diff --git a/source/magic.adb b/source/magic.adb new file mode 100644 index 0000000..c1f33ec --- /dev/null +++ b/source/magic.adb @@ -0,0 +1,41 @@ +with core, ui, menu, effect, magic; + +use magic; + +package body magic is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type sprite_array is array (codex) of core.sprite; + + ------------------------------------------------------------------------------------------ + + icon : sprite_array; + + ------------------------------------------------------------------------------------------ + + procedure configure is + begin + for index in codex + loop + declare + folder : constant string := core.lowercase (school'image (trait (index).kind)); + file : constant string := core.lowercase (codex'image (index)); + begin + icon (index) := core.load_sprite ("sprite/ui/magic/" & folder & "/" & file & ".png", 1, 1); + end; + end loop; + end configure; + + ------------------------------------------------------------------------------------------ + + procedure draw (index : in codex; x, y : in integer) is + offset : constant integer := 16; + begin + ui.draw_frame (x, y, icon (index).width + offset, icon (index).height + offset); + core.draw (icon (index), x + offset / 2, y + offset / 2); + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end magic; diff --git a/source/magic.ads b/source/magic.ads new file mode 100644 index 0000000..5796818 --- /dev/null +++ b/source/magic.ads @@ -0,0 +1,139 @@ +with core, effect; + +package magic is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type school is ( + neutral, air, dark, earth, fire, light, + prime, water + ); + + type codex is ( + -- Neutral + magic_arrow, chain_magic_arrow, + -- Air + blow_away, chain_lightning, grounded, lightning, storm_arrows, storm_winds, + summon_air_elemental, thunderclap, + -- Dark + agony_mass, agony, despair_mass, despair, life_drain_mass, life_drain, + purge, summon_dark_elemental, terror, weakness_mass, weakness, + -- Earth + earthquake, erosion, petrification, poison_cloud, regeneration_mass, regeneration, + rockwalls, stone_skin_mass, stone_skin, summon_earth_elemental, + -- Fire + determination_mass, determination, fireball, fire_bolt, fire_shield, fire_storm, + frenzy, immolation, inner_fire_mass, inner_fire, summon_fire_elemental, + -- Light + blindness, celestial_armor_mass, celestial_armor, heal_mass, heal, purify, + retribution_heal, retribution_mana, retribution_shot, summon_light_elemental, sunburst, + -- Prime + dispel_magic_mass, dispel_magic, disruption, haste_mass, haste, implosion, + mana_drain, slow_mass, slow, teleport, time_statis, + -- Water + blizzard, eternal_winter, frozen_ground, ice_armor_mass, ice_armor, ice_bolt, + ice_breaker, ice_wall, summon_water_elemental, winter_circle + ); + + ------------------------------------------------------------------------------------------ + + subtype level_limit is natural range 0 .. 6; + + type information is + record + name : core.short_string; + kind : school; + level : level_limit; + evoke : effect.codex; + end record; + + type trait_array is array (codex) of information; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + ("Magic Arrow ", neutral, 0, effect.none), + ("Chain Magic Arrow ", neutral, 0, effect.none), + ("Blow Away ", air, 0, effect.none), + ("Chain Lightning ", air, 0, effect.none), + ("Grounded ", air, 0, effect.none), + ("Lightning ", air, 0, effect.none), + ("Storm Arrows ", air, 0, effect.none), + ("Storm Winds ", air, 0, effect.none), + ("Summon Air Elemental ", air, 0, effect.none), + ("Thunderclap ", air, 0, effect.none), + ("Agony Mass ", dark, 0, effect.none), + ("Agony ", dark, 0, effect.none), + ("Despair Mass ", dark, 0, effect.none), + ("Despair ", dark, 0, effect.none), + ("Life Drain Mass ", dark, 0, effect.none), + ("Life Drain ", dark, 0, effect.none), + ("Purge ", dark, 0, effect.none), + ("Summon Dark Elemental ", dark, 0, effect.none), + ("Terror ", dark, 0, effect.none), + ("Weakness Mass ", dark, 0, effect.none), + ("Weakness ", dark, 0, effect.none), + ("Earthquake ", earth, 0, effect.none), + ("Erosion ", earth, 0, effect.none), + ("Petrification ", earth, 0, effect.none), + ("Poison Cloud ", earth, 0, effect.none), + ("Regeneration Mass ", earth, 0, effect.none), + ("Regeneration ", earth, 0, effect.none), + ("Rockwalls ", earth, 0, effect.none), + ("Stone Skin Mass ", earth, 0, effect.none), + ("Stone Skin ", earth, 0, effect.none), + ("Summon Earth Elemental ", earth, 0, effect.none), + ("Determination Mass ", fire, 0, effect.none), + ("Determination ", fire, 0, effect.none), + ("Fireball ", fire, 0, effect.none), + ("Fire Bolt ", fire, 0, effect.none), + ("Fire Shield ", fire, 0, effect.none), + ("Fire Storm ", fire, 0, effect.none), + ("Frenzy ", fire, 0, effect.none), + ("Immolation ", fire, 0, effect.none), + ("Inner Fire Mass ", fire, 0, effect.none), + ("Inner Fire ", fire, 0, effect.none), + ("Summon Fire Elemental ", fire, 0, effect.none), + ("Blindness ", light, 0, effect.none), + ("Celestial Armor Mass ", light, 0, effect.none), + ("Celestial Armor ", light, 0, effect.none), + ("Heal Mass ", light, 0, effect.none), + ("Heal ", light, 0, effect.none), + ("Purify ", light, 0, effect.none), + ("Retribution Heal ", light, 0, effect.none), + ("Retribution Mana ", light, 0, effect.none), + ("Retribution Shot ", light, 0, effect.none), + ("Summon Light Elemental ", light, 0, effect.none), + ("Sunburst ", light, 0, effect.none), + ("Dispel Magic Mass ", prime, 0, effect.none), + ("Dispel Magic ", prime, 0, effect.none), + ("Disruption ", prime, 0, effect.none), + ("Haste Mass ", prime, 0, effect.none), + ("Haste ", prime, 0, effect.none), + ("Implosion ", prime, 0, effect.none), + ("Mana Drain ", prime, 0, effect.none), + ("Slow Mass ", prime, 0, effect.none), + ("Slow ", prime, 0, effect.none), + ("Teleport ", prime, 0, effect.none), + ("Time Statis ", prime, 0, effect.none), + ("Blizzard ", water, 0, effect.none), + ("Eternal Winter ", water, 0, effect.none), + ("Frozen Ground ", water, 0, effect.none), + ("Ice Armor Mass ", water, 0, effect.none), + ("Ice Armor ", water, 0, effect.none), + ("Ice Bolt ", water, 0, effect.none), + ("Ice Breaker ", water, 0, effect.none), + ("Ice Wall ", water, 0, effect.none), + ("Summon Water Elemental ", water, 0, effect.none), + ("Winter Circle ", water, 0, effect.none) + ); + + ------------------------------------------------------------------------------------------ + + procedure configure; + + procedure draw (index : in codex; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end magic; diff --git a/source/main.adb b/source/main.adb new file mode 100644 index 0000000..ddb4624 --- /dev/null +++ b/source/main.adb @@ -0,0 +1,150 @@ +with ada.text_io; +use ada.text_io; + +with core, ui, menu, effect, attribute, skill, resource, faction, might, magic, item, unit, construction, world; + +procedure main is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + --~world_active : world.codex := world.ashland; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + -- Ognjen Milan Robovic + -- Richard Martin Stallman + -- Eric Steven Raymond + -- Linus Benedict Torvalds + -- + -- Ada Augusta King + -- Marina Ann Hantzis + +begin + + core.engine_configure; + + core.hexagon_grid_sprite := core.load_sprite ("sprite/ui/hexagon_grid_tile.png", 1, 1); + core.hexagon_fill_sprite := core.load_sprite ("sprite/ui/hexagon_fill_tile.png", 1, 1); + + --~attribute.sprite := core.load_sprite ("sprite/ui/attribute.png", 1, 1); + --~skill.sprite := core.load_sprite ("sprite/ui/skill.png", 1, 1); + --~resource.sprite := core.load_sprite ("sprite/ui/resource.png", 1, 1); + --~magic.sprite := core.load_sprite ("sprite/ui/magic.png", 1, 1); + --~item.sprite := core.load_sprite ("sprite/ui/item.png", 1, 1); + + ui.configure; + might.configure; + magic.configure; + item.configure; + unit.configure; + construction.configure; + world.configure; + + core.fairy_synchronize (6); -- CALLING SUBROUTINE DEFINED IN FORTRAN + + world.make (world.rough, 80, 40); + + gameplay: loop + exit when core.engine_active = false; + -- + core.global_time := core.global_time + 1; + -- + core.global_time := core.global_time mod (core.gameplay_framerate * core.animation_framerate); + core.gameplay_time := core.global_time mod (core.gameplay_framerate); + core.animation_time := core.global_time / (core.gameplay_framerate / core.animation_framerate); + -- + delay duration (1.0 / 60.0); + -- + core.engine_synchronize; + -- + --~if core.cursor_mode = 1 then + --~world_active := world.codex'val ((world.codex'pos (world_active) + 1) mod 6); + --~delay duration (0.333); + --~end if; + --~world.render (world_active, 0, 0); + -- + world.draw (24, 24, core.window_width - 480 - 48, core.window_height - 48, core.cursor_mode = 2); + -- + ui.active := ui.steam; + if core.signal_mode = core.signal_code'pos (core.signal_left) then core.camera.x := core.camera.x - 1; end if; + if core.signal_mode = core.signal_code'pos (core.signal_right) then core.camera.x := core.camera.x + 1; end if; + if core.signal_mode = core.signal_code'pos (core.signal_up) then core.camera.y := core.camera.y - 1; end if; + if core.signal_mode = core.signal_code'pos (core.signal_down) then core.camera.y := core.camera.y + 1; end if; + if core.cursor_mode = 3 then + --~ui.active := ui.style'val (ui.style'pos (ui.active) mod 4); + --~case ui.active is + --~when ui.default => ui.active := ui.gothic; + --~when ui.gothic => ui.active := ui.yd; + --~when ui.yd => ui.active := ui.default; + --~end case; + ui.active := ui.default; + --~ui.active := ui.steam; + end if; + -- + --~for this in might.codex + --~loop + --~might.draw (this, 112 * (might.codex'pos (this) / 7) + 64, 112 * (might.codex'pos (this) mod 7) + 64); + --~end loop; + -- + --~unit.render (unit.angel, unit.attack, 300, 300); + --~unit.render (unit.arch_angel, unit.moving, 600, 300); + -- + --~for this in unit.goblin .. unit.ancient_behemoth + --~loop + --~for anim in unit.animation + --~loop + --~unit.draw (this, anim, 80 * (unit.codex'pos (this) mod 14) + 40, 64 * unit.animation'pos (anim) + 40); + --~end loop; + --~end loop; + -- + --~for this in unit.pikeman .. unit.ghost_dragon + --~loop + --~unit.render (this, unit.idle, 96 * (unit.codex'pos (this) / 7) + 32, 96 * (unit.codex'pos (this) mod 7) + 32); + --~end loop; + -- + --~for this in construction.codex + --~loop + --~construction.draw (this, 128 * (construction.codex'pos (this) mod 12) + 32, 128 * (construction.codex'pos (this) / 12) + 32); + --~end loop; + -- + --~attribute.render (attribute.defense, 0, 100); + --~skill.render (skill.archery, 1, 100, 100); + --~skill.render (skill.tactics, 2, 200, 100); + --~skill.render (skill.fire_magic, 3, 300, 100); + --~resource.render (resource.mercury, 400, 100); + -- + --~core.animate_sprite (test, 700, 100, (64, 64, 0, 0), 10); + -- + --~menu.render (menu.attribute_list, 1200, 400, 0, 0); + --~menu.render (menu.skill_list, 400, 400, 0, 0); + -- + ui.draw_menu (0, 0, core.window_width - 480, core.window_height, false); + ui.draw_tiny_menu (core.window_width - 480, 0, 480, core.window_height, true); + -- + --~for this in magic.blow_away .. magic.thunderclap loop magic.draw (this, 112 * (magic.codex'pos (this) - magic.codex'pos (magic.chain_magic_arrow)) - 60, 112 * 0 + 64); end loop; + --~for this in magic.agony_mass .. magic.weakness loop magic.draw (this, 112 * (magic.codex'pos (this) - magic.codex'pos (magic.thunderclap)) - 60, 112 * 1 + 64); end loop; + --~for this in magic.earthquake .. magic.summon_earth_elemental loop magic.draw (this, 112 * (magic.codex'pos (this) - magic.codex'pos (magic.weakness)) - 60, 112 * 2 + 64); end loop; + --~for this in magic.determination_mass .. magic.summon_fire_elemental loop magic.draw (this, 112 * (magic.codex'pos (this) - magic.codex'pos (magic.summon_earth_elemental)) - 60, 112 * 3 + 64); end loop; + --~for this in magic.blindness .. magic.sunburst loop magic.draw (this, 112 * (magic.codex'pos (this) - magic.codex'pos (magic.summon_fire_elemental)) - 60, 112 * 4 + 64); end loop; + --~for this in magic.dispel_magic_mass .. magic.time_statis loop magic.draw (this, 112 * (magic.codex'pos (this) - magic.codex'pos (magic.sunburst)) - 60, 112 * 5 + 64); end loop; + --~for this in magic.blizzard .. magic.winter_circle loop magic.draw (this, 112 * (magic.codex'pos (this) - magic.codex'pos (magic.time_statis)) - 60, 112 * 6 + 64); end loop; + -- + for index in item.codex loop item.draw (index, 32 * (item.codex'pos (index) / 10) + 32, 32 * (item.codex'pos (index) mod 10) + 32); end loop; + -- + core.render_string (core.c_string ("X :" & integer'image (core.cursor_x)), 1352, 32, 16#CCCCCC#, false); + core.render_string (core.c_string ("Y :" & integer'image (core.cursor_y)), 1352, 64, 16#CCCCCC#, false); + core.render_string (core.c_string ("T :" & integer'image (core.cursor_mode)), 1352, 96, 16#CCCCCC#, false); + core.render_string (core.c_string ("M :" & core.signal_code'image (core.signal_code'val (core.signal_mode))), 1352, 128, 16#CCCCCC#, false); + core.render_string (core.c_string ("U :" & integer'image (core.camera.x)), 1352, 160, 16#CCCCCC#, false); + core.render_string (core.c_string ("V :" & integer'image (core.camera.y)), 1352, 192, 16#CCCCCC#, false); + -- + --~ui.draw_tiny_menu (400, 400, 400, 400, true); + --~menu.draw_menu (200, 100, 400, 200, true); + --~menu.draw_tiny_menu (800, 200, 400, 200, true); + -- + --~menu.draw_background (menu.main_background, 96, 96, 288, 128); + --~menu.draw_background (menu.main_background, 96, 300, 200, 100); + --~menu.draw_background (menu.main_background, 96, 450, 96, 96); + end loop gameplay; + +end main; diff --git a/source/makefile b/source/makefile new file mode 100644 index 0000000..30cd196 --- /dev/null +++ b/source/makefile @@ -0,0 +1,23 @@ +.POSIX: + +default: + gfortran -fPIC -Wall -Wextra -Ofast -fno-underscoring -fstack-check -c -o ai.o ai.f90 + gcc -g -ansi -Wall -Wextra -Wpedantic -Ofast -fstack-check -c -fPIC -o system.o system.c + # + gnatmake -O3 -fstack-check -c main.adb + gnatbind main.ali + gcc -g -ansi -Wall -Wextra -Wpedantic -Ofast -fstack-check -c -fPIC -o raylib.o raylib.c + gnatlink main.ali system.o raylib.o ai.o -o mam_raylib -lraylib -lc -lgfortran + mv mam_raylib ../mam_raylib + # +#~ gnatmake -O3 -fstack-check -c main.adb +#~ gnatbind main.ali +#~ gcc -g -ansi -Wall -Wextra -Wpedantic -Ofast -fstack-check -c -fPIC -o sdl2.o sdl2.c +#~ gnatlink main.ali system.o sdl2.o ai.o -o mam_sdl2 -lc -lgfortran -lSDL2 -lSDL2_image +#~ mv mam_sdl2 ../mam_sdl2 + # +#~ gnatmake -O3 -fstack-check -c main.adb +#~ gnatbind main.ali +#~ gcc -g -ansi -Wall -Wextra -Wpedantic -Ofast -fstack-check -c -fPIC -o xcb.o xcb.c +#~ gnatlink main.ali system.o xcb.o ai.o -o mam_xcb -lc -lgfortran -lpng -lxcb -lxcb-image +#~ mv mam_xcb ../mam_xcb diff --git a/source/menu.adb b/source/menu.adb new file mode 100644 index 0000000..fc56c31 --- /dev/null +++ b/source/menu.adb @@ -0,0 +1,21 @@ +with core, menu; + +use menu; + +package body menu is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + procedure configure is + begin + null; + end configure; + + procedure draw (value : in codex; x, y : in integer) is + begin + null; + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end menu; diff --git a/source/menu.ads b/source/menu.ads new file mode 100644 index 0000000..f851b00 --- /dev/null +++ b/source/menu.ads @@ -0,0 +1,19 @@ +with core; + +package menu is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type codex is ( + none + ); + + ------------------------------------------------------------------------------------------ + + procedure configure; + + procedure draw (value : in codex; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end menu; diff --git a/source/might.adb b/source/might.adb new file mode 100644 index 0000000..37f562a --- /dev/null +++ b/source/might.adb @@ -0,0 +1,41 @@ +with core, ui, menu, effect, might; + +use might; + +package body might is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type sprite_array is array (codex) of core.sprite; + + ------------------------------------------------------------------------------------------ + + icon : sprite_array; + + ------------------------------------------------------------------------------------------ + + procedure configure is + begin + for index in codex + loop + declare + folder : constant string := core.lowercase (school'image (trait (index).kind)); + file : constant string := core.lowercase (codex'image (index)); + begin + icon (index) := core.load_sprite ("sprite/ui/might/" & folder & "/" & file & ".png", 1, 1); + end; + end loop; + end configure; + + ------------------------------------------------------------------------------------------ + + procedure draw (value : in codex; x, y : in integer) is + offset : constant integer := 16; + begin + ui.draw_frame (x, y, icon (value).width + offset, icon (value).height + offset); + core.draw (icon (value), x + offset / 2, y + offset / 2); + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end might; diff --git a/source/might.ads b/source/might.ads new file mode 100644 index 0000000..c15f5ab --- /dev/null +++ b/source/might.ads @@ -0,0 +1,124 @@ +with core, effect; + +package might is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type school is ( + neutral, archery, defense, economy, education, logistics, + offense, tactics + ); + + type codex is ( + -- Neutral + -- Archery + cover, evasive_maneuvers, focused_fire, magic_ammunition, piercing_bolt, precision, + retreat, taunt, + -- Defense + charismatic_leader, counterstrike, double_counterstrike, resilience, revenge, shield_of_the_virtue, + stand_your_ground_mass, stand_your_ground, toughness, + -- Economy + banker, destroyer, leadership, lumber, manager, merchant, + miner, plunderer, snatch, + -- Education + alchemist, architect, ballistics, chosen_one, diplomacy, economist, + general, mentor, siege_master, + -- Logistics + explorer, navigation, observer, orientation, pathfinder, scout, + spy, trust_the_plan, + -- Offense + assailant, battle_march, cleave, flawless_attack, giant_slayer, heroic_charge, + parry, pressed_attack, rampage, + -- Tactics + ambush, commander, crippling_traps, diving_attack, heroism_mass, heroism, + intimidation, reinforcements + ); + + ------------------------------------------------------------------------------------------ + + subtype level_limit is natural range 0 .. 6; + + type information is + record + name : core.short_string; + kind : school; + level : level_limit; + evoke : effect.codex; + end record; + + type trait_array is array (codex) of information; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + ("Cover ", archery, 0, effect.none), + ("Evasive Maneuvers ", archery, 0, effect.none), + ("Focused Fire ", archery, 0, effect.none), + ("Magic Ammunition ", archery, 0, effect.none), + ("Piercing Bolt ", archery, 0, effect.none), + ("Precision ", archery, 0, effect.none), + ("Retreat ", archery, 0, effect.none), + ("Taunt ", archery, 0, effect.none), + ("Charismatic Leader ", defense, 0, effect.none), + ("Counterstrike ", defense, 0, effect.none), + ("Double Counterstrike ", defense, 0, effect.none), + ("Resilience ", defense, 0, effect.none), + ("Revenge ", defense, 0, effect.none), + ("Shield Of The Virtue ", defense, 0, effect.none), + ("Stand Your Ground Mass ", defense, 0, effect.none), + ("Stand Your Ground ", defense, 0, effect.none), + ("Toughness ", defense, 0, effect.none), + ("Banker ", economy, 0, effect.none), + ("Destroyer ", economy, 0, effect.none), + ("Leadership ", economy, 0, effect.none), + ("Lumber ", economy, 0, effect.none), + ("Manager ", economy, 0, effect.none), + ("Merchant ", economy, 0, effect.none), + ("Miner ", economy, 0, effect.none), + ("Plunderer ", economy, 0, effect.none), + ("Snatch ", economy, 0, effect.none), + ("Alchemist ", education, 0, effect.none), + ("Architect ", education, 0, effect.none), + ("Ballistics ", education, 0, effect.none), + ("Chosen One ", education, 0, effect.none), + ("Diplomacy ", education, 0, effect.none), + ("Economist ", education, 0, effect.none), + ("General ", education, 0, effect.none), + ("Mentor ", education, 0, effect.none), + ("Siege Master ", education, 0, effect.none), + ("Explorer ", logistics, 0, effect.none), + ("Navigation ", logistics, 0, effect.none), + ("Observer ", logistics, 0, effect.none), + ("Orientation ", logistics, 0, effect.none), + ("Pathfinder ", logistics, 0, effect.none), + ("Scout ", logistics, 0, effect.none), + ("Spy ", logistics, 0, effect.none), + ("Trust The Plan ", logistics, 0, effect.none), + ("Assailant ", offense, 0, effect.none), + ("Battle March ", offense, 0, effect.none), + ("Cleave ", offense, 0, effect.none), + ("Flawless Attack ", offense, 0, effect.none), + ("Giant Slayer ", offense, 0, effect.none), + ("Heroic Charge ", offense, 0, effect.none), + ("Parry ", offense, 0, effect.none), + ("Pressed Attack ", offense, 0, effect.none), + ("Rampage ", offense, 0, effect.none), + ("Ambush ", tactics, 0, effect.none), + ("Commander ", tactics, 0, effect.none), + ("Crippling Traps ", tactics, 0, effect.none), + ("Diving Attack ", tactics, 0, effect.none), + ("Heroism Mass ", tactics, 0, effect.none), + ("Heroism ", tactics, 0, effect.none), + ("Intimidation ", tactics, 0, effect.none), + ("Reinforcements ", tactics, 0, effect.none) + ); + + ------------------------------------------------------------------------------------------ + + procedure configure; + + procedure draw (value : in codex; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end might; diff --git a/source/raylib.c b/source/raylib.c new file mode 100644 index 0000000..a69fadf --- /dev/null +++ b/source/raylib.c @@ -0,0 +1,196 @@ +#include +#include +#include +#include + +enum { + signal_none, signal_space, signal_zero, signal_one, signal_two, signal_three, + signal_four, signal_five, signal_six, signal_seven, signal_eight, signal_nine, + signal_a, signal_b, signal_c, signal_d, signal_e, signal_f, + signal_g, signal_h, signal_i, signal_j, signal_k, signal_l, + signal_m, signal_n, signal_o, signal_p, signal_q, signal_r, + signal_s, signal_t, signal_u, signal_v, signal_w, signal_x, + signal_y, signal_z, signal_grave, signal_escape, signal_enter, signal_tab, + signal_backspace, signal_right, signal_left, signal_down, signal_up, signal_kp_0, + signal_kp_1, signal_kp_2, signal_kp_3, signal_kp_4, signal_kp_5, signal_kp_6, + signal_kp_7, signal_kp_8, signal_kp_9, signal_kp_subtract, signal_kp_add, signal_left_shift, + signal_left_control, signal_count +}; + +static Texture2D * render_texture; +static int render_texture_count = 0; + +static Font font = { 0 }; +static Font mono = { 0 }; +static Color tint = { 255, 255, 255, 255 }; +static Vector2 dump = { 0, 0 }; + +static void no_logging (int msgType, const char * text, va_list args) { + (void) msgType; + (void) text; + (void) args; + + return; +} + +static void render_clean_up (void) { + free (render_texture); + + CloseWindow (); +} + +extern int cursor_x; +extern int cursor_y; +extern int cursor_mode; +extern int signal_mode; + +extern int engine_active; + +extern int window_width (void); +extern int window_height (void); + +extern void render_sprite (int sprite, int x, int y, int u, int v, int width, int height); +extern void render_string (char * string, int x, int y, int colour, char monospace); + +extern void engine_configure (void); +extern void engine_synchronize (void); + +extern int import_sprite (char * path); +extern int sprite_width (int index); +extern int sprite_height (int index); + +int cursor_x = 0; +int cursor_y = 0; +int cursor_mode = 0; +int signal_mode = 0; + +int engine_active = 0; + +int window_width (void) { return (GetScreenWidth ()); } +int window_height (void) { return (GetScreenHeight ()); } + +void render_sprite (int sprite, int x, int y, int u, int v, int width, int height) { + Rectangle source, destination; + + source.x = u; + source.y = v; + source.width = width; + source.height = height; + + destination.x = x; + destination.y = y; + destination.width = (width < 0) ? -width : width; + destination.height = (height < 0) ? -height : height; + + DrawTexturePro (render_texture [sprite], source, destination, dump, 0.0, tint); +} + +void render_string (char * string, int x, int y, int colour, char monospace) { + Vector2 position = { 4, 4 }; + Color new_tint = { 255, 255, 255, 255 }; + + position.x += x; + position.y += y; + + new_tint.r = ((colour & 0XFF0000) >> 16) % 256; + new_tint.g = ((colour & 0X00FF00) >> 8) % 256; + new_tint.b = ((colour & 0X0000FF) >> 0) % 256; + + DrawTextPro ((monospace != 0) ? mono : font, string, position, dump, 0.0, 24, 6, new_tint); +} + +void engine_configure (void) { + engine_active = 1; + + SetTraceLogCallback (no_logging); + InitWindow (1800, 900, "Chads of Might & Magic"); + SetTargetFPS (60); + + font = LoadFont ("sprite/font/gothic.ttf"); + mono = LoadFont ("sprite/font/mono.ttf"); + + atexit (render_clean_up); +} + +void engine_synchronize (void) { + int signal = signal_none; + + Color background = { 50, 60, 70, 100 }; + + EndDrawing (); + + if (WindowShouldClose ()) { + engine_active = 0; + } + + cursor_x = GetMouseX (); + cursor_y = GetMouseY (); + + if (IsMouseButtonPressed (MOUSE_BUTTON_LEFT)) { cursor_mode = 1; } + if (IsMouseButtonPressed (MOUSE_BUTTON_RIGHT)) { cursor_mode = 2; } + if (IsMouseButtonPressed (MOUSE_BUTTON_MIDDLE)) { cursor_mode = 3; } + if (IsMouseButtonReleased (MOUSE_BUTTON_LEFT)) { cursor_mode = 0; } + if (IsMouseButtonReleased (MOUSE_BUTTON_RIGHT)) { cursor_mode = 0; } + if (IsMouseButtonReleased (MOUSE_BUTTON_MIDDLE)) { cursor_mode = 0; } + + signal = GetKeyPressed (); + + switch (signal) { + case KEY_NULL: signal_mode = signal_none; break; + case KEY_SPACE: signal_mode = signal_space; break; + case KEY_GRAVE: signal_mode = signal_grave; break; + case KEY_LEFT_SHIFT: signal_mode = signal_left_shift; break; + case KEY_LEFT_CONTROL: signal_mode = signal_left_control; break; + case KEY_KP_SUBTRACT: signal_mode = signal_kp_subtract; break; + case KEY_KP_ADD: signal_mode = signal_kp_add; break; + case KEY_ESCAPE: signal_mode = signal_escape; break; + case KEY_ENTER: signal_mode = signal_enter; break; + case KEY_TAB: signal_mode = signal_tab; break; + case KEY_BACKSPACE: signal_mode = signal_backspace; break; + case KEY_RIGHT: signal_mode = signal_right; break; + case KEY_LEFT: signal_mode = signal_left; break; + case KEY_DOWN: signal_mode = signal_down; break; + case KEY_UP: signal_mode = signal_up; break; + default: { + if ((signal >= KEY_ZERO) && (signal <= KEY_NINE)) { + signal_mode = signal - KEY_ZERO + signal_zero; + } else if ((signal >= KEY_KP_0) && (signal <= KEY_KP_9)) { + signal_mode = signal - KEY_KP_0 + signal_kp_0; + } else if ((signal >= KEY_A) && (signal <= KEY_Z)) { + signal_mode = signal - KEY_A + signal_a; + } else { + signal_mode = signal_none; + } + } + } + + BeginDrawing (); + + ClearBackground (background); +} + +int import_sprite (char * path) { + ++render_texture_count; + + render_texture = realloc (render_texture, (unsigned long int) render_texture_count * sizeof (* render_texture)); + + render_texture [render_texture_count - 1] = LoadTexture (path); + + if ((render_texture [render_texture_count - 1].width == 0) || (render_texture [render_texture_count - 1].height == 0)) { + printf ("\033[1;31m%3i : '%60s' := %3i, %3i;\033[0m\n", + render_texture_count - 1, + path, + render_texture [render_texture_count - 1].width, + render_texture [render_texture_count - 1].height); + } + + return (render_texture_count - 1); +} + +int sprite_width (int index) { + return (render_texture [index].width); +} + +int sprite_height (int index) { + return (render_texture [index].height); +} diff --git a/source/resource.adb b/source/resource.adb new file mode 100644 index 0000000..ae0dbd7 --- /dev/null +++ b/source/resource.adb @@ -0,0 +1,16 @@ +with core, resource; + +use resource; + +package body resource is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + procedure draw (index : in codex; x, y : in integer) is + begin + null; + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end resource; diff --git a/source/resource.ads b/source/resource.ads new file mode 100644 index 0000000..44ee162 --- /dev/null +++ b/source/resource.ads @@ -0,0 +1,43 @@ +with core; + +package resource is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type codex is ( + gold, wood, mercury, ore, sulfur, crystal, + gem + ); + + ------------------------------------------------------------------------------------------ + + subtype base_limit is natural range 0 .. 144; + + type information is + record + name : core.short_string; + base : base_limit; + end record; + + type trait_array is array (codex) of information; + type value is array (codex) of natural; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + ("Gold ", 1), + ("Wood ", 3), + ("Mercury ", 11), + ("Ore ", 7), + ("Sulfur ", 13), + ("Crystal ", 17), + ("Gem ", 19) + ); + + ------------------------------------------------------------------------------------------ + + procedure draw (index : in codex; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end resource; diff --git a/source/sdl2.c b/source/sdl2.c new file mode 100644 index 0000000..f2024b5 --- /dev/null +++ b/source/sdl2.c @@ -0,0 +1,181 @@ +#include +#include +#include +#include + +static SDL_Texture * * render_texture; +static int render_texture_count = 0; + +static SDL_Window * window; +static SDL_Renderer * renderer; +static SDL_Texture * font; +static SDL_Texture * mono; + +static void render_clean_up (void) { + int i; + + for (i = 0; i < render_texture_count; ++i) { + SDL_DestroyTexture (render_texture [i]); + } + + free (render_texture); + + SDL_DestroyTexture (font); + SDL_DestroyTexture (mono); + + SDL_DestroyRenderer (renderer); + SDL_DestroyWindow (window); + + SDL_Quit (); +} + +extern int signal_x; +extern int signal_y; +extern int cursor_mode; +extern int signal_mode; + +extern int engine_active; + +extern int window_width (void); +extern int window_height (void); + +extern void render_sprite (int sprite, int x, int y, int u, int v, int width, int height); +extern void render_string (char * string, int x, int y, int colour, char monospace); + +extern void engine_configure (void); +extern void engine_synchronize (void); + +extern int import_sprite (char * path); +extern int sprite_width (int index); +extern int sprite_height (int index); + +int signal_x = 0; +int signal_y = 0; +int cursor_mode = 0; +int signal_mode = 0; + +int engine_active = 0; + +int window_width (void) { int width = 0; SDL_GetWindowSize (window, & width, NULL); return (width); } +int window_height (void) { int height = 0; SDL_GetWindowSize (window, NULL, & height); return (height); } + +void render_sprite (int sprite, int x, int y, int u, int v, int width, int height) { + SDL_Rect source, destination; + + source.x = u; + source.y = v; + source.w = width; + source.h = height; + + destination.x = x; + destination.y = y; + destination.w = (width < 0) ? -width : width; + destination.h = (height < 0) ? -height : height; + + SDL_RenderCopy (renderer, render_texture [sprite], & source, & destination); +} + +void render_string (char * string, int x, int y, int colour, char monospace) { + int i; + + (void) colour; + + for (i = 0; string [i] != '\0'; ++i) { + SDL_Rect source, destination; + + source.x = (string [i] - 32) / 8 * 9; + source.y = (string [i] - 32) % 8 * 18; + source.w = 9; + source.h = 18; + + destination.x = x + 7 + 9 * i; + destination.y = y + 7; + destination.w = 9; + destination.h = 18; + + SDL_RenderCopy (renderer, (monospace != 0) ? mono : font, & source, & destination); + } +} + +void engine_configure (void) { + engine_active = 1; + + SDL_Init (SDL_INIT_VIDEO); + + window = SDL_CreateWindow ("Chads of Might & Magic", 0, 0, 1800, 900, 0); + renderer = SDL_CreateRenderer (window, -1, SDL_RENDERER_ACCELERATED); + + font = IMG_LoadTexture (renderer, "sprite/font/font.png"); + mono = IMG_LoadTexture (renderer, "sprite/font/mono.png"); + + atexit (render_clean_up); +} + +void engine_synchronize (void) { + SDL_Event event; + + SDL_RenderPresent (renderer); + + SDL_GetMouseState (& signal_x, & signal_y); + + SDL_PollEvent (& event); + + switch (event.type) { + case SDL_QUIT: + engine_active = 0; + break; + case SDL_MOUSEBUTTONDOWN: + if (event.button.button == SDL_BUTTON_LEFT) cursor_mode = 1; + if (event.button.button == SDL_BUTTON_RIGHT) cursor_mode = 2; + if (event.button.button == SDL_BUTTON_MIDDLE) cursor_mode = 3; + break; + case SDL_MOUSEBUTTONUP: + cursor_mode = 0; + break; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_UP: signal_mode = 1; break; + case SDLK_DOWN: signal_mode = 2; break; + case SDLK_LEFT: signal_mode = 3; break; + case SDLK_RIGHT: signal_mode = 4; break; + case SDLK_ESCAPE: engine_active = 0; break; + default: signal_mode = 0; break; + } + break; + case SDL_KEYUP: + cursor_mode = 0; + break; + default: + break; + } + + signal_mode = 0; + + SDL_RenderClear (renderer); +} + +int import_sprite (char * path) { + ++render_texture_count; + + render_texture = realloc (render_texture, (unsigned long int) render_texture_count * sizeof (* render_texture)); + + render_texture [render_texture_count - 1] = IMG_LoadTexture (renderer, path); + + if (render_texture [render_texture_count - 1] == NULL) { + printf ("\033[1;31m%3i : '%60s';\033[0m\n", render_texture_count - 1, path); + } + + return (render_texture_count - 1); +} + +int sprite_width (int index) { + int width = 0; + SDL_QueryTexture (render_texture [index], NULL, NULL, & width, NULL); + return (width); +} + +int sprite_height (int index) { + int height = 0; + SDL_QueryTexture (render_texture [index], NULL, NULL, NULL, & height); + return (height); +} diff --git a/source/skill.adb b/source/skill.adb new file mode 100644 index 0000000..823baa6 --- /dev/null +++ b/source/skill.adb @@ -0,0 +1,16 @@ +with core, skill; + +use skill; + +package body skill is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + procedure draw (index : in codex; level : in level_limit; x, y : in integer) is + begin + null; + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end skill; diff --git a/source/skill.ads b/source/skill.ads new file mode 100644 index 0000000..a0c7693 --- /dev/null +++ b/source/skill.ads @@ -0,0 +1,63 @@ +with core; + +package skill is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type codex is ( + archery, offense, armourer, resistance, tactics, first_aid, + logistics, path_finding, navigation, scouting, leadership, scholar, + fire_magic, water_magic, air_magic, earth_magic, mysticism, necromancy, + sorcery, wisdom, intelligence, learning, diplomacy, estates + ); + + ------------------------------------------------------------------------------------------ + + subtype base_limit is natural range 0 .. 3; + subtype level_limit is natural range 0 .. 3; + + type information is + record + name : core.short_string; + base : base_limit; + level : level_limit; + end record; + + type trait_array is array (codex) of information; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + ("Archery ", 0, 0), + ("Offense ", 0, 0), + ("Armourer ", 0, 0), + ("Resistance ", 0, 0), + ("Tactics ", 0, 0), + ("First Aid ", 0, 0), + ("Logistics ", 0, 0), + ("Path Finding ", 0, 0), + ("Navigation ", 0, 0), + ("Scouting ", 0, 0), + ("Leadership ", 0, 0), + ("Scholar ", 0, 0), + ("Fire Magic ", 0, 0), + ("Water Magic ", 0, 0), + ("Air Magic ", 0, 0), + ("Earth Magic ", 0, 0), + ("Mysticism ", 0, 0), + ("Necromancy ", 0, 0), + ("Sorcery ", 0, 0), + ("Wisdom ", 0, 0), + ("Intelligence ", 0, 0), + ("Learning ", 0, 0), + ("Diplomacy ", 0, 0), + ("Estates ", 0, 0) + ); + + ------------------------------------------------------------------------------------------ + + procedure draw (index : in codex; level : in level_limit; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end skill; diff --git a/source/system.c b/source/system.c new file mode 100644 index 0000000..fc09149 --- /dev/null +++ b/source/system.c @@ -0,0 +1,837 @@ +#ifndef null +#define null ((void *) 0) +#endif + +enum { + false, + true +}; + +enum { + file_type_text, file_type_common_assembly, file_type_flat_assembly, file_type_gnu_assembly, + file_type_netwide_assembly, file_type_yet_another_assembly, file_type_c_source, file_type_c_header, + file_type_ada_body, file_type_ada_specification, file_type_cpp_source, file_type_cpp_header, + file_type_count +}; + +enum { + effect_normal, effect_bold, effect_italic, effect_underline, effect_blink, effect_reverse, + effect_count +}; + +enum { + colour_grey, colour_red, colour_green, colour_yellow, colour_blue, colour_pink, colour_cyan, colour_white, + colour_count +}; + +enum { + character_null, character_start_header, character_start_text, character_end_text, + character_end_transmission, character_enquiry, character_acknowledge, character_bell, + character_backspace, character_tab_horizontal, character_line_feed, character_tab_vertical, + character_form_feed, character_carriage_return, character_shift_out, character_shift_in, + character_data_link_escape, character_device_control_1, character_device_control_2, character_device_control_3, + character_device_control_4, character_not_acknowledge, character_synchronous_idle, character_end_transmission_block, + character_cancel, character_end_medium, character_substitute, character_escape, + character_file_separator, character_group_separator, character_record_separator, character_unit_separator +}; + +enum { + signal_none, + signal_any, + signal_a, signal_b, signal_c, signal_d, signal_e, signal_f, signal_g, signal_h, + signal_i, signal_j, signal_k, signal_l, signal_m, signal_n, signal_o, signal_p, + signal_q, signal_r, signal_s, signal_t, signal_u, signal_v, signal_w, signal_x, + signal_y, signal_z, signal_0, signal_1, signal_2, signal_3, signal_4, signal_5, + signal_6, signal_7, signal_8, signal_9, signal_escape, signal_tabulator, signal_return, signal_new_line, + signal_slash, signal_backslash, signal_quote, signal_backquote, signal_space, signal_backspace, signal_dot, signal_comma, + signal_cite, signal_caps_lock, signal_l_bracket, signal_r_bracket, signal_minus, signal_equal, + signal_count +}; + +static void in (void * data, int size); +static void out (void * data, int size); + +extern void echo (char * data); + +extern void fatal_failure (int condition, char * message); + +extern void limit (int * value, int minimum, int maximum); + +extern void * allocate (int size); +extern void * reallocate (void * data, int size); +extern void * deallocate (void * data); + +extern int file_open (char * name, int mode); +extern int file_close (int file); +extern void file_read (int file, void * data, int size); +extern void file_write (int file, void * data, int size); +extern int file_seek (int file, int whence); +extern int file_size (char * name); +extern int file_type (char * name); +extern void * file_record (char * name); +extern char * file_import (char * name); +extern void file_export (char * name, void * data); + +extern void file_list_import (char * name); +extern void file_list_export (char * name); +extern void file_list_insert_character (char character, int position); +extern void file_list_remove_character (int position); +extern void file_list_delete (void); + +extern int character_compare_array (char character, char * character_array); + +extern int character_count (char * string, char this, int from, int to, char stop); + +extern int string_length (char * string); + +extern char * string_reverse_limit (char * string, int limit); +extern char * string_reverse (char * string); + +extern char * string_delete (char * string, int length); + +extern int string_compare (char * string_0, char * string_1); +extern char * string_copy (char * string_0, char * string_1); +extern char * string_concatenate (char * string_0, char * string_1); + +extern int string_compare_limit (char * string_0, char * string_1, int limit); +extern char * string_copy_limit (char * string_0, char * string_1, int limit); +extern char * string_concatenate_limit (char * string_0, char * string_1, int limit); + +extern char * string_realign (char * string, int amount, char character); + +extern void terminal_clear (void); +extern void terminal_colour (int colour, int effect); +extern void terminal_cancel (void); +extern void terminal_show_cursor (int show); + +extern char * number_to_string (int number); +extern char * format_to_string (int number, int sigmoid, int base, int amount, char character); + +extern int random_integer (int minimum, int maximum); + +extern int syntax_define (int enrange, int derange, char * begin, char * end, char escape, int colour, int effect); + +extern int syntax_select (char * string, int * length); + +#include +#include +#include + +static int file_list_active = 0; +static int file_list_count = 0; +static int * file_list_mark = null; +static int * file_list_size = null; +static char * * file_list_name = null; +static char * * file_list_data = null; + +static int syntax_count = 0; +static int syntax_active = false; +static int * syntax_enrange = null; +static int * syntax_derange = null; +static char * * syntax_begin = null; +static char * * syntax_end = null; +static char * syntax_escape = null; +static int * syntax_colour = null; +static int * syntax_effect = null; + +void in (void * data, int size) { + fatal_failure (data == null, "in: Failed to read from standard input, data is null pointer."); + fatal_failure (size == 0, "in: Failed to read from standard input, size is zero."); + + (void) read (STDIN_FILENO, data, (unsigned long int) size); +} + +void out (void * data, int size) { + fatal_failure (data == null, "out: Failed to write to standard output, data is null pointer."); + fatal_failure (size == 0, "out: Failed to write to standard output, size is zero."); + + (void) write (STDOUT_FILENO, data, (unsigned long int) size); +} + +void echo (char * data) { + if (data == null) { + return; + } + + out (data, string_length (data)); +} + +void fatal_failure (int condition, char * message) { + if (condition != 0) { + echo ("[\033[1;31mExiting\033[0m] "); + echo (message); + echo ("\n"); + + exit (EXIT_FAILURE); + } +} + +void limit (int * value, int minimum, int maximum) { + if ( value == null ) { return; } + if (* value <= minimum) { * value = minimum; } + if (* value >= maximum) { * value = maximum; } +} + +void * allocate (int size) { + char * data = null; + + if (size <= 0) { + return (null); + } + + data = calloc ((unsigned long int) size, sizeof (* data)); + + fatal_failure (data == null, "standard : allocate : Failed to allocate memory, internal function 'calloc' returned null pointer."); + + return ((void *) data); +} + +void * reallocate (void * data, int size) { + if (size <= 0) { + return (data); + } + + data = realloc (data, (unsigned long int) size); + + fatal_failure (data == null, "standard : reallocate: Failed to reallocate memory, internal function 'realloc' returned null pointer."); + + /* Set new data to 0. */ + + return (data); +} + +void * deallocate (void * data) { + if (data != null) { + free (data); + } + + return (null); +} + +int file_open (char * name, int mode) { + int descriptor = -1; + + fatal_failure (name == null, "file_open: Failed to open file, name is null pointer."); + + descriptor = open (name, mode); + + fatal_failure (descriptor == -1, "file_open: Failed to open file, function open returned invalid descriptor."); + + return (descriptor); +} + +int file_close (int file) { + fatal_failure (file == -1, "file_close: Failed to close file, invalid file descriptor."); + fatal_failure (close (file) == -1, "file_close: Failed to close file, function close returned invalid code."); + + return (-1); +} + +void file_read (int file, void * data, int size) { + fatal_failure (file == -1, "file_read: Failed to read from file, invalid descriptor."); + fatal_failure (data == null, "file_read: Failed to read from file, data is null pointer."); + fatal_failure (size == 0, "file_read: Failed to read from file, size is zero."); + + (void) read (file, data, (unsigned long int) size); +} + +void file_write (int file, void * data, int size) { + fatal_failure (file == -1, "file_write: Failed to write to file, invalid descriptor."); + fatal_failure (data == null, "file_write: Failed to write to file, data is null pointer."); + fatal_failure (size == 0, "file_write: Failed to write to file, size is zero."); + + (void) write (file, data, (unsigned long int) size); +} + +int file_seek (int file, int whence) { + fatal_failure (file == -1, "file_seek: Failed to seek in file, invalid descriptor."); + + return ((int) lseek (file, 0, whence)); +} + +int file_size (char * name) { + int size = -1; + int file = -1; + + file = file_open (name, O_RDONLY); + + size = lseek (file, 0, SEEK_END); + + fatal_failure (size == -1, "file_size: Failed to get size of file, invalid file size."); + + file = file_close (file); + + return (size); +} + +int file_type (char * name) { + char * file_type_data [file_type_count] = { + ".txt", ".s", ".fasm", ".gasm", ".nasm", ".yasm", ".c", ".h", + ".adb", ".ads", ".cpp", ".hpp" + }; + + int type = 0; + + while (* name != '.') { + ++name; + } + + for (type = 0; type != file_type_count; ++type) { + if (string_compare (name, file_type_data [type]) != 0) { + return (type); + } + } + + return (-1); +} + +void * file_record (char * name) { + int file = -1; + int size = -1; + char * data = null; + + fatal_failure (name == null, "file_import: Failed to import file, name is null pointer."); + + file = file_open (name, O_RDONLY); + size = file_size (name); + data = allocate (size); + + file_read (file, data, size); + + file = file_close (file); + + return (data); +} + +char * file_import (char * name) { + int file = -1; + int size = -1; + char * data = null; + + fatal_failure (name == null, "file_import: Failed to import file, name is null pointer."); + + file = file_open (name, O_RDONLY); + size = file_size (name) + 1; + data = allocate (size); + + file_read (file, data, size - 1); + + data [size - 1] = '\0'; + + file = file_close (file); + + return (data); +} + +void file_export (char * name, void * data) { + (void) name; + (void) data; +} + +void file_list_import (char * name) { + fatal_failure (name == null, "file_list_import: Failed to import file, name is null pointer."); + + ++file_list_count; + + file_list_active = file_list_count - 1; + + file_list_mark = reallocate (file_list_mark, (int) sizeof (* file_list_mark) * file_list_count); + file_list_size = reallocate (file_list_size, (int) sizeof (* file_list_size) * file_list_count); + file_list_name = reallocate (file_list_name, (int) sizeof (* file_list_name) * file_list_count); + file_list_data = reallocate (file_list_data, (int) sizeof (* file_list_data) * file_list_count); + + file_list_mark [file_list_active] = -1; + file_list_size [file_list_active] = -1; + file_list_name [file_list_active] = null; + file_list_data [file_list_active] = null; + + file_list_name [file_list_active] = allocate (string_length (name) + 1); + + (void) string_copy_limit (file_list_name [file_list_active], name, string_length (name) + 1); + + file_list_mark [file_list_active] = open (name, O_RDWR); + + fatal_failure (file_list_mark [file_list_active] == -1, "file_list_import: Failed to open file, function open returned invalid descriptor."); + + file_list_size [file_list_active] = (int) lseek (file_list_mark [file_list_active], 0, SEEK_END) + 1; + + (void) lseek (file_list_mark [file_list_active], 0, SEEK_SET); + + file_list_data [file_list_active] = allocate (file_list_size [file_list_active]); + + (void) read (file_list_mark [file_list_active], file_list_data [file_list_active], (unsigned long int) (file_list_size [file_list_active] - 1)); + + close (file_list_mark [file_list_active]); + + file_list_data [file_list_active] [file_list_size [file_list_active] - 1] = '\0'; +} + +void file_list_export (char * name) { + fatal_failure (name == null, "file_list_export: Failed to export file, name is null pointer."); + + file_list_mark [file_list_active] = open (name, O_WRONLY | O_CREAT | O_TRUNC); + + (void) write (file_list_mark [file_list_active], file_list_data [file_list_active], (unsigned long int) file_list_size [file_list_active]); + + close (file_list_mark [file_list_active]); +} + +void file_list_insert_character (char character, int position) { + int offset; + + ++file_list_size [file_list_active]; + + if (file_list_size [file_list_active] < string_length (file_list_data [file_list_active])) { + file_list_data [file_list_active] = reallocate (file_list_data [file_list_active], file_list_size [file_list_active]); + } + + file_list_data [file_list_active] = reallocate (file_list_data [file_list_active], file_list_size [file_list_active]); + + for (offset = file_list_size [file_list_active] - 1; offset != position; --offset) { + file_list_data [file_list_active] [offset] = file_list_data [file_list_active] [offset - 1]; + } + + file_list_data [file_list_active] [position] = character; +} + +void file_list_remove_character (int position) { + int offset; + + if (position == 0) { + return; + } + + --file_list_size [file_list_active]; + + for (offset = position - 1; offset != file_list_size [file_list_active] - 1; ++offset) { + file_list_data [file_list_active] [offset] = file_list_data [file_list_active] [offset + 1]; + } + + file_list_data [file_list_active] [offset] = '\0'; +} + +void file_list_delete (void) { + int i; + + for (i = 0; i != file_list_count; ++i) { + file_list_name [i] = deallocate (file_list_name [i]); + file_list_data [i] = deallocate (file_list_data [i]); + } + + file_list_mark = deallocate (file_list_mark); + file_list_size = deallocate (file_list_size); + file_list_name = deallocate (file_list_name); + file_list_data = deallocate (file_list_data); +} + +int character_compare_array (char character, char * character_array) { + int i = 0; + + do { + if (character == character_array [i]) { + return (1); + } + } while (++i != string_length (character_array)); + + return (0); +} + +int character_count (char * string, char this, int from, int to, char stop) { + int count; + + for (count = 0; (from != to) && (string [from] != stop); from += ((to < from) ? -1 : 1)) { + count += (int) ((string [from] == this) || (this == '\0')); + } + + return (count); +} + +int string_length (char * string) { + int length; + + if (string == null) { + return (0); + } + + for (length = 0; string [length] != '\0'; ++length); + + return (length); +} + +char * string_reverse_limit (char * string, int limit) { + int i; + + fatal_failure (string == null, "string_reverse: String is null pointer."); + + for (i = 0; i < limit / 2; ++i) { + char temporary = string [i]; + string [i] = string [limit - 1 - i]; + string [limit - 1 - i] = temporary; + } + + return (string); +} + +char * string_reverse (char * string) { + return (string_reverse_limit (string, string_length (string))); +} + +char * string_delete (char * string, int length) { + int i; + + if ((string == null) || (length <= 0)) { + return (string); + } + + for (i = 0; i != length; ++i) { + string [i] = '\0'; + } + + return (string); +} + +int string_compare (char * string_0, char * string_1) { + int i = 0; + + fatal_failure (string_0 == null, "string_compare: Destination string is null pointer."); + fatal_failure (string_1 == null, "string_compare: Source string is null pointer."); + + for (i = 0; (string_0 [i] != '\0') && (string_1 [i] != '\0'); ++i) { + if (string_0 [i] != string_1 [i]) { + return (0); + } + } + + return (1); +} + +char * string_copy (char * string_0, char * string_1) { + int i = 0; + + fatal_failure (string_0 == null, "string_copy: Destination string is null pointer."); + fatal_failure (string_1 == null, "string_copy: Source string is null pointer."); + + for (i = 0; i != string_length (string_1) + 1; ++i) { + string_0 [i] = string_1 [i]; + } + + return (string_0); +} + +char * string_concatenate (char * string_0, char * string_1) { + fatal_failure (string_0 == null, "string_concatenate: Destination string is null pointer."); + fatal_failure (string_1 == null, "string_concatenate: Source string is null pointer."); + + string_0 += string_length (string_0); + + while (* string_1 != '\0') { + * string_0++ = * string_1++; + /*++string_0; + ++string_1;*/ + } + + * string_0 = '\0'; + + return (string_0); +} + +int string_compare_limit (char * string_0, char * string_1, int limit) { + int i = 0; + + fatal_failure (string_0 == null, "string_compare_limit: Destination string is null pointer."); + fatal_failure (string_1 == null, "string_compare_limit: Source string is null pointer."); + + for (i = 0; i != limit; ++i) { + if (string_0 [i] != string_1 [i]) { + return (0); + } + } + + return (1); +} + +char * string_copy_limit (char * string_0, char * string_1, int limit) { + int i = 0; + + fatal_failure (string_0 == null, "string_copy_limit: Destination string is null pointer."); + fatal_failure (string_1 == null, "string_copy_limit: Source string is null pointer."); + + if (limit <= 0) { + return (string_0); + } + + for (i = 0; i != limit; ++i) { + string_0 [i] = string_1 [i]; + } + + return (string_0); +} + +char * string_concatenate_limit (char * string_0, char * string_1, int limit) { + int i = 0; + int length_0 = 0; + int length_1 = 0; + + fatal_failure (string_0 == null, "string_concatenate_limit: Destination string is null pointer."); + fatal_failure (string_1 == null, "string_concatenate_limit: Source string is null pointer."); + + if (limit <= 0) { + return (string_0); + } + + length_0 = string_length (string_0); + length_1 = string_length (string_1); + + for (i = 0; (i != length_1) && (i != limit); ++i) { + string_0 [length_0 + i] = string_1 [i]; + } + + return (string_0); +} + +char * string_realign (char * string, int amount, char character) { + int offset, length; + + length = string_length (string); + + for (offset = 0; offset != length; ++offset) { + string [amount - offset - 1] = string [length - offset - 1]; + } + + for (offset = 0; offset != amount - length; ++offset) { + string [offset] = character; + } + + string [amount] = '\0'; + + return (string); +} + +void terminal_clear (void) { + echo ("\033[2J\033[H"); +} + +void terminal_colour (int colour, int effect) { + char format [8] = "\033[ ;3 m"; + + format [2] = (char) (effect % effect_count) + '0'; + format [5] = (char) (colour % colour_count) + '0'; + + echo (format); +} + +void terminal_cancel (void) { + echo ("\033[0m"); +} + +void terminal_show_cursor (int show) { + if (show != 0) { + echo ("\033[?25h"); + } else { + echo ("\033[?25l"); + } +} + +char * number_to_string (int number) { + int i, sigmoid; + + static char string [32]; + + string_delete (string, 32); + + if (number == 0) { + string [0] = '0'; + string [1] = '\0'; + return (string); + } + + if (number < 0) { + number *= -1; + sigmoid = 1; + } else { + sigmoid = 0; + } + + for (i = (string [0] == '-'); number != 0; ++i) { + string [i] = (char) (number % 10) + '0'; + number /= 10; + } + + if (sigmoid != 0) { + string [i] = '-'; + ++i; + } + + string [i] = '\0'; + + string_reverse (string); + + return (string); +} + +char * format_to_string (int number, int sigmoid, int base, int amount, char character) { + int i; + + static char string [32]; + + string_delete (string, 32); + + if (number == 0) { + string [0] = '0'; + string [1] = '\0'; + + string_realign (string, amount, character); + + return (string); + } + + if (number < 0) { + number *= -1; + } + + for (i = (string [0] == '-'); number != 0; ++i) { + string [i] = "0123456789ABCDEF" [number % base]; + number /= base; + } + + if (sigmoid != 0) { + string [i] = '-'; + ++i; + } + + string [i] = '\0'; + + string_reverse (string); + + string_realign (string, amount, character); + + return (string); +} + +static void syntax_delete (void) { + int offset; + + if (syntax_active == false) { + return; + } + + for (offset = 0; offset < syntax_count; ++offset) { + syntax_begin [offset] = deallocate (syntax_begin [offset]); + syntax_end [offset] = deallocate (syntax_end [offset]); + } + + syntax_enrange = deallocate (syntax_enrange); + syntax_derange = deallocate (syntax_derange); + syntax_begin = deallocate (syntax_begin); + syntax_end = deallocate (syntax_end); + syntax_escape = deallocate (syntax_escape); + syntax_colour = deallocate (syntax_colour); + syntax_effect = deallocate (syntax_effect); + + syntax_active = false; + syntax_count = 0; +} + +int random_integer (int minimum, int maximum) { + return (((int) rand () % (maximum - minimum + 1)) + minimum); +} + +int syntax_define (int enrange, int derange, char * begin, char * end, char escape, int colour, int effect) { + if (syntax_active == false) { + syntax_active = true; + + atexit (syntax_delete); + } + + fatal_failure (begin == null, "syntax_define: Begin string is null pointer."); + fatal_failure (end == null, "syntax_define: End string is null pointer."); + + ++syntax_count; + + syntax_enrange = reallocate (syntax_enrange, syntax_count * (int) sizeof (* syntax_enrange)); + syntax_derange = reallocate (syntax_derange, syntax_count * (int) sizeof (* syntax_derange)); + syntax_begin = reallocate (syntax_begin, syntax_count * (int) sizeof (* syntax_begin)); + syntax_end = reallocate (syntax_end, syntax_count * (int) sizeof (* syntax_end)); + syntax_escape = reallocate (syntax_escape, syntax_count * (int) sizeof (* syntax_escape)); + syntax_colour = reallocate (syntax_colour, syntax_count * (int) sizeof (* syntax_colour)); + syntax_effect = reallocate (syntax_effect, syntax_count * (int) sizeof (* syntax_effect)); + + syntax_begin [syntax_count - 1] = allocate ((string_length (begin) + 1) * (int) sizeof (* * syntax_begin)); + syntax_end [syntax_count - 1] = allocate ((string_length (end) + 1) * (int) sizeof (* * syntax_end)); + + syntax_enrange [syntax_count - 1] = enrange; + syntax_derange [syntax_count - 1] = derange; + syntax_escape [syntax_count - 1] = escape; + syntax_colour [syntax_count - 1] = colour; + syntax_effect [syntax_count - 1] = effect; + + string_copy (syntax_begin [syntax_count - 1], begin); + string_copy (syntax_end [syntax_count - 1], end); + + return (syntax_count - 1); +} + +int syntax_select (char * string, int * length) { + int offset, subset, select; + + fatal_failure (syntax_active == false, "syntax_select: Syntax is not active."); + fatal_failure (string == null, "syntax_select: String is null."); + fatal_failure (length == null, "syntax_select: Length is null."); + + for (select = offset = 0; select != syntax_count; ++select) { + if (syntax_enrange [select] == false) { + if (syntax_derange [select] == false) { + if (string_compare_limit (string, syntax_begin [select], string_length (syntax_begin [select])) == true) { + break; + } + } else { + if ((string_compare_limit (string, syntax_begin [select], string_length (syntax_begin [select])) == true) + && (character_compare_array (string [offset + string_length (syntax_begin [select])], syntax_end [select]) == true)) { + break; + } + } + } else { + for (subset = 0; subset != string_length (syntax_begin [select]); ++subset) { + if (string [offset] == syntax_begin [select] [subset]) { + goto selected; + } + } + } + } + + selected: + + if (select >= syntax_count) { + * length = 1; + + return (syntax_count); + } + + for (offset = 1; string [offset - 1] != '\0'; ++offset) { + if (string [offset] == syntax_escape [select]) { + ++offset; + continue; + } + + if (syntax_derange [select] == false) { + if (string_compare_limit (& string [offset], syntax_end [select], string_length (syntax_end [select])) == true) { + * length = offset + string_length (syntax_end [select]); + return (select); + } + } else { + subset = 0; + if (string_compare (syntax_end [select], "") == false) { + break; + } do { + if (string [offset] == syntax_end [select] [subset]) { + * length = offset; + goto finished; + } + } while (++subset != string_length (syntax_end [select])); + } + } + + finished: + + return (select); +} diff --git a/source/ui.adb b/source/ui.adb new file mode 100644 index 0000000..99fb316 --- /dev/null +++ b/source/ui.adb @@ -0,0 +1,188 @@ +--~with core, attribute, skill, menu; +with core, ui; + +use ui; + +package body ui is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type sprite_array is array (style, codex) of core.sprite; + + ------------------------------------------------------------------------------------------ + + sprite : sprite_array; + + ------------------------------------------------------------------------------------------ + + procedure configure is + procedure load_ui (index : in style; folder_path : in string) is + begin + for this in codex + loop + sprite (index, this) := core.load_sprite ("sprite/ui/style/" & core.lowercase (folder_path & codex'image (this)) & ".png", 1, 1); + end loop; + end load_ui; + begin + load_ui (default, "default/"); + --~load_ui (gothic, "heroes/"); + load_ui (gothic, "gothic/"); + load_ui (yd, "yd/"); + load_ui (steam, "steam/"); + --~load_ui (gothic, "diablo/"); + -- + active := default; + end configure; + + ------------------------------------------------------------------------------------------ + + procedure draw (index : in codex; x, y : in integer) is + begin + core.draw (sprite (active, index), x, y); + end draw; + + ------------------------------------------------------------------------------------------ + + procedure crop (index : in codex; x, y, u, v, width, height : in integer) is + begin + core.crop (sprite (active, index), x, y, u, v, width, height); + end crop; + + ------------------------------------------------------------------------------------------ + + procedure draw_horizontally (index : in codex; x, y, width : in integer) is + begin + for move in 0 .. width / sprite (active, index).width - 1 + loop + draw (index, x + move * sprite (active, index).width, y); + end loop; + -- + crop (index, x + (width / sprite (active, index).width) * sprite (active, index).width, y, 0, 0, width mod sprite (active, index).width, sprite (active, index).height); + end draw_horizontally; + + ------------------------------------------------------------------------------------------ + + procedure draw_vertically (index : in codex; x, y, height : in integer) is + begin + for move in 0 .. height / sprite (active, index).height - 1 + loop + draw (index, x, y + move * sprite (active, index).height); + end loop; + -- + crop (index, x, y + (height / sprite (active, index).height) * sprite (active, index).height, 0, 0, sprite (active, index).width, height mod sprite (active, index).height); + end draw_vertically; + + ------------------------------------------------------------------------------------------ + + procedure draw_background (index : in codex; x, y, width, height : in integer) is + crop_width : integer := width mod sprite (active, index).width; + crop_height : integer := height mod sprite (active, index).height; + begin + for move_y in 0 .. height / sprite (active, index).height - 1 + loop + for move_x in 0 .. width / sprite (active, index).width - 1 + loop + draw (index, x + move_x * sprite (active, index).width, y + move_y * sprite (active, index).height); + end loop; + -- + crop (index, x + width - crop_width, y + move_y * sprite (active, index).height, 0, 0, crop_width, sprite (active, index).height); + end loop; + -- + for move_x in 0 .. width / sprite (active, index).width - 1 + loop + crop (index, x + move_x * sprite (active, index).width, y + height - crop_height, 0, 0, sprite (active, index).width, crop_height); + end loop; + -- + crop (index, x + width - crop_width, y + height - crop_height, 0, 0, crop_width, crop_height); + end draw_background; + + ------------------------------------------------------------------------------------------ + + procedure draw_frame (x, y, width, height : in integer) is + offset_x : constant integer := sprite (active, frame_middle).width; + offset_y : constant integer := sprite (active, frame_middle).height; + begin + draw_background (frame_middle, x + offset_x, y + offset_y, width - 2 * offset_x, height - 2 * offset_y); + -- + draw_horizontally (frame_upper, x + offset_x, y, width - 2 * offset_x); + draw_horizontally (frame_lower, x + offset_x, y + height - offset_y, width - 2 * offset_x); + draw_vertically (frame_left, x, y + offset_y, height - 2 * offset_y); + draw_vertically (frame_right, x + width - offset_x, y + offset_y, height - 2 * offset_y); + -- + draw (frame_upper_left, x, y); + draw (frame_upper_right, x + width - sprite (active, frame_upper_right).width, y); + draw (frame_lower_left, x, y + height - sprite (active, frame_lower_left).height); + draw (frame_lower_right, x + width - sprite (active, frame_lower_right).width, y + height - sprite (active, frame_lower_right).height); + end draw_frame; + + ------------------------------------------------------------------------------------------ + + procedure draw_menu (x, y, width, height : in integer; background : in boolean) is + offset : constant integer := sprite (active, none).width; + begin + if width < sprite (active, corner_upper_left).width + sprite (active, corner_upper_right).width + or width < sprite (active, corner_lower_left).width + sprite (active, corner_lower_right).width + or height < sprite (active, corner_upper_left).height + sprite (active, corner_lower_left).height + or height < sprite (active, corner_upper_right).height + sprite (active, corner_lower_right).height + then return; + end if; + -- + if background then + draw_background (main_background, x + offset, y + offset, width - 2 * offset, height - 2 * offset); + end if; + -- + declare + upper : constant integer := width - sprite (active, corner_upper_left).width - sprite (active, corner_upper_right).width; + lower : constant integer := width - sprite (active, corner_lower_left).width - sprite (active, corner_lower_right).width; + left : constant integer := height - sprite (active, corner_upper_left).height - sprite (active, corner_lower_left).height; + right : constant integer := height - sprite (active, corner_upper_right).height - sprite (active, corner_lower_right).height; + begin + draw_horizontally (border_upper, x + sprite (active, corner_upper_left).width, y, upper); + draw_horizontally (border_lower, x + sprite (active, corner_lower_left).width, y + height - sprite (active, border_lower).height, lower); + draw_vertically (border_left, x, y + sprite (active, corner_upper_left).height, left); + draw_vertically (border_right, x + width - sprite (active, border_right).width, y + sprite (active, corner_upper_right).height, right); + end; + -- + draw (corner_upper_left, x, y); + draw (corner_upper_right, x + width - sprite (active, corner_upper_right).width, y); + draw (corner_lower_left, x, y + height - sprite (active, corner_lower_left).height); + draw (corner_lower_right, x + width - sprite (active, corner_lower_right).width, y + height - sprite (active, corner_lower_right).height); + end draw_menu; + + ------------------------------------------------------------------------------------------ + + procedure draw_tiny_menu (x, y, width, height : in integer; background : in boolean) is + offset : constant integer := sprite (active, none).width; + begin + if width < sprite (active, tiny_corner_upper_left).width + sprite (active, tiny_corner_upper_right).width + or width < sprite (active, tiny_corner_lower_left).width + sprite (active, tiny_corner_lower_right).width + or height < sprite (active, tiny_corner_upper_left).height + sprite (active, tiny_corner_lower_left).height + or height < sprite (active, tiny_corner_upper_right).height + sprite (active, tiny_corner_lower_right).height + then return; + end if; + -- + if background then + draw_background (main_background, x + offset, y + offset, width - 2 * offset, height - 2 * offset); + end if; + -- + declare + upper : constant integer := width - sprite (active, tiny_corner_upper_left).width - sprite (active, tiny_corner_upper_right).width; + lower : constant integer := width - sprite (active, tiny_corner_lower_left).width - sprite (active, tiny_corner_lower_right).width; + left : constant integer := height - sprite (active, tiny_corner_upper_left).height - sprite (active, tiny_corner_lower_left).height; + right : constant integer := height - sprite (active, tiny_corner_upper_right).height - sprite (active, tiny_corner_lower_right).height; + begin + draw_horizontally (tiny_border_upper, x + sprite (active, tiny_corner_upper_left).width, y, upper); + draw_horizontally (tiny_border_lower, x + sprite (active, tiny_corner_lower_left).width, y + height - sprite (active, tiny_border_lower).height, lower); + draw_vertically (tiny_border_left, x, y + sprite (active, tiny_corner_upper_left).height, left); + draw_vertically (tiny_border_right, x + width - sprite (active, tiny_border_right).width, y + sprite (active, tiny_corner_upper_right).height, right); + end; + -- + draw (tiny_corner_upper_left, x, y); + draw (tiny_corner_upper_right, x + width - sprite (active, tiny_corner_upper_right).width, y); + draw (tiny_corner_lower_left, x, y + height - sprite (active, tiny_corner_lower_left).height); + draw (tiny_corner_lower_right, x + width - sprite (active, tiny_corner_lower_right).width, y + height - sprite (active, tiny_corner_lower_right).height); + end draw_tiny_menu; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end ui; diff --git a/source/ui.ads b/source/ui.ads new file mode 100644 index 0000000..6a80af9 --- /dev/null +++ b/source/ui.ads @@ -0,0 +1,42 @@ +with core; + +package ui is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type style is ( + default, gothic, yd, steam + ); + + type codex is ( + none, + main_background, + corner_upper_left, corner_upper_right, corner_lower_left, corner_lower_right, + tiny_corner_upper_left, tiny_corner_upper_right, tiny_corner_lower_left, tiny_corner_lower_right, + border_upper, border_lower, border_left, border_right, + tiny_border_upper, tiny_border_lower, tiny_border_left, tiny_border_right, + frame_upper_left, frame_upper, frame_upper_right, + frame_left, frame_middle, frame_right, + frame_lower_left, frame_lower, frame_lower_right + ); + + ------------------------------------------------------------------------------------------ + + active : style; + + ------------------------------------------------------------------------------------------ + + procedure configure; + + procedure draw (index : in codex; x, y : in integer); + + procedure draw_background (index : in codex; x, y, width, height : in integer); + + procedure draw_frame (x, y, width, height : in integer); + + procedure draw_menu (x, y, width, height : in integer; background : in boolean); + procedure draw_tiny_menu (x, y, width, height : in integer; background : in boolean); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end ui; diff --git a/source/unit.adb b/source/unit.adb new file mode 100644 index 0000000..5e7c5c3 --- /dev/null +++ b/source/unit.adb @@ -0,0 +1,38 @@ +with core, effect, faction, unit; + +use unit; + +package body unit is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type sprite_array is array (codex) of core.sprite; + + sprite : sprite_array; + icon : sprite_array; + + ------------------------------------------------------------------------------------------ + + procedure configure is + begin + for index in codex + loop + declare + folder : constant string := core.lowercase (faction.codex'image (trait (index).kind)); + file : constant string := core.lowercase (codex'image (index)); + begin + sprite (index) := core.load_sprite ("sprite/unit/" & folder & "/" & file & ".png", 6, 6); + end; + end loop; + end configure; + + ------------------------------------------------------------------------------------------ + + procedure draw (index : in codex; state : in animation; x, y : in integer) is + begin + core.move (sprite (index), x, y, 6, animation'pos (state)); + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end unit; diff --git a/source/unit.ads b/source/unit.ads new file mode 100644 index 0000000..40ab37a --- /dev/null +++ b/source/unit.ads @@ -0,0 +1,236 @@ +with core, effect, faction; + +package unit is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type animation is ( + idle, wounded, dead, moving, toggle_moving, attack + ); + + type codex is ( + azure_dragon, boar, crystal_dragon, diamond_golem, enchanter, faerie_dragon, + gold_golem, halfing, mummy, nomad, peasant, rogue, + rust_dragon, sharpshooter, troll, + -- + pikeman, halberdier, archer, marksman, griffin, royal_griffin, + swordsman, crusader, monk, zealot, cavalier, champion, + angel, arch_angel, + -- + goblin, hobgoblin, wolf_rider, wolf_raider, orc, orc_chieftain, + ogre, ogre_magi, roc, thunderbird, cyclops, cyclops_king, + behemoth, ancient_behemoth, + -- + imp, familiar, gog, magog, hell_hound, cerberus, + demon, horned_demon, pit_fiend, pit_lord, efreeti, efreet_sultan, + devil, arch_devil, + -- + gremlin, master_gremlin, stone_gargoyle, obisidian_gargoyle, stone_golem, iron_golem, + mage, arch_mage, geany, master_geany, naga, naga_queen, + giant, titan, + -- + pixie, spirit, air_elemental, storm_elemental, water_elemental, ice_elemental, + fire_elemental, energy_elemental, earth_elemental, magma_elemental, psychic_elemental, magic_elemental, + fire_bird, phoenix, + -- + skeleton, skeleton_warrior, walking_dead, zombie, wight, wraith, + vampire, vampire_lord, lich, power_lich, black_knight, dread_knight, + bone_dragon, ghost_dragon, + -- + centaur, centaur_captain, dwarf, battle_dwarf, wood_elf, grand_elf, + pegasus, silver_pegasus, dendroid_guard, dendroid_soldier, unicorn, war_unicorn, + green_dragon, gold_dragon, + -- + gnoll, gnoll_marauder, lizardman, lizard_warrior, serpentfly, dragonfly, + basilisk, greater_basilisk, gorgon, mighty_gorgon, wyvern, wyvern_monarch, + hydra, chaos_hydra, + -- + troglodyte, infernal_troglodyte, harpy, harpy_hag, evil_eye, beholder, + medusa, medusa_queen, minotaur, minotaur_king, manticore, scorpicore, + red_dragon, black_dragon + ); + + ------------------------------------------------------------------------------------------ + + subtype level_limit is natural range 1 .. 6; + subtype health_limit is natural range 1 .. 12; + subtype damage_limit is natural range 1 .. 12; + subtype growth_limit is natural range 1 .. 12; + + type information is + record + name : core.short_string; + kind : faction.codex; + level : level_limit; + health : health_limit; + damage : damage_limit; + growth : growth_limit; + evoke : effect.codex; + end record; + + type trait_array is array (codex) of information; + + ------------------------------------------------------------------------------------------ + + trait : constant trait_array := ( + ("Azure Dragon ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Boar ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Crystal Dragon ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Diamond Golem ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Enchanter ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Faerie Dragon ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Gold Golem ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Halfing ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Mummy ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Nomad ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Peasant ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Rogue ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Rust Dragon ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Sharpshooter ", faction.neutral, 1, 2, 1, 9, effect.none), + ("Troll ", faction.neutral, 1, 2, 1, 9, effect.none), + -- + ("Pikeman ", faction.castle, 1, 2, 1, 9, effect.none), + ("Halberdier ", faction.castle, 1, 3, 2, 9, effect.none), + ("Archer ", faction.castle, 1, 1, 1, 7, effect.none), + ("Crossbowman ", faction.castle, 1, 2, 2, 7, effect.none), + ("Griffin ", faction.castle, 2, 3, 2, 4, effect.none), + ("Royal Griffin ", faction.castle, 2, 4, 3, 4, effect.none), + ("Swordsman ", faction.castle, 3, 2, 3, 5, effect.none), + ("Crusader ", faction.castle, 3, 3, 4, 5, effect.none), + ("Monk ", faction.castle, 3, 2, 5, 3, effect.none), + ("Zealot ", faction.castle, 3, 3, 6, 3, effect.none), + ("Cavalier ", faction.castle, 4, 6, 7, 2, effect.none), + ("Champion ", faction.castle, 4, 8, 8, 2, effect.none), + ("Angel ", faction.castle, 5, 8, 9, 1, effect.none), + ("Arch-Angel ", faction.castle, 5, 10, 10, 1, effect.none), + -- + ("Goblin ", faction.stronghold, 1, 2, 1, 9, effect.none), + ("Hobgoblin ", faction.stronghold, 1, 3, 2, 9, effect.none), + ("Wolf Rider ", faction.stronghold, 1, 1, 1, 7, effect.none), + ("Wolf Raider ", faction.stronghold, 1, 2, 2, 7, effect.none), + ("Orc ", faction.stronghold, 2, 3, 2, 4, effect.none), + ("Orc Chieftain ", faction.stronghold, 2, 4, 3, 4, effect.none), + ("Orge ", faction.stronghold, 3, 2, 3, 5, effect.none), + ("Ogre Magi ", faction.stronghold, 3, 3, 4, 5, effect.none), + ("Roc ", faction.stronghold, 3, 2, 5, 3, effect.none), + ("Thunderbird ", faction.stronghold, 3, 3, 6, 3, effect.none), + ("Cyclops ", faction.stronghold, 4, 6, 7, 2, effect.none), + ("Cyclops King ", faction.stronghold, 4, 8, 8, 2, effect.none), + ("Behemoth ", faction.stronghold, 5, 8, 9, 1, effect.none), + ("Ancient Behemoth ", faction.stronghold, 5, 10, 10, 1, effect.none), + -- + ("Imp ", faction.inferno, 1, 2, 1, 9, effect.none), + ("Familiar ", faction.inferno, 1, 3, 2, 9, effect.none), + ("Gog ", faction.inferno, 1, 1, 1, 7, effect.none), + ("Magog ", faction.inferno, 1, 2, 2, 7, effect.none), + ("Hell Hound ", faction.inferno, 2, 3, 2, 4, effect.none), + ("Cerberus ", faction.inferno, 2, 4, 3, 4, effect.none), + ("Demon ", faction.inferno, 3, 2, 3, 5, effect.none), + ("Horned Demon ", faction.inferno, 3, 3, 4, 5, effect.none), + ("Pit Fiend ", faction.inferno, 3, 2, 5, 3, effect.none), + ("Pit Lord ", faction.inferno, 3, 3, 6, 3, effect.none), + ("Efreeti ", faction.inferno, 4, 6, 7, 2, effect.none), + ("Efreet Sultan ", faction.inferno, 4, 8, 8, 2, effect.none), + ("Devil ", faction.inferno, 5, 8, 9, 1, effect.none), + ("Arch Devil ", faction.inferno, 5, 10, 10, 1, effect.none), + -- + ("Gremlin ", faction.tower, 1, 2, 1, 9, effect.none), + ("Master Gremlin ", faction.tower, 1, 3, 2, 9, effect.none), + ("Stone Gargoyle ", faction.tower, 1, 1, 1, 7, effect.none), + ("Obisidian Gargoyle ", faction.tower, 1, 2, 2, 7, effect.none), + ("Stone Golem ", faction.tower, 2, 3, 2, 4, effect.none), + ("Iron Golem ", faction.tower, 2, 4, 3, 4, effect.none), + ("Mage ", faction.tower, 3, 2, 3, 5, effect.none), + ("Arch Mage ", faction.tower, 3, 3, 4, 5, effect.none), + ("Geany ", faction.tower, 3, 2, 5, 3, effect.none), + ("Master Geany ", faction.tower, 3, 3, 6, 3, effect.none), + ("Naga ", faction.tower, 4, 6, 7, 2, effect.none), + ("Naga Queen ", faction.tower, 4, 8, 8, 2, effect.none), + ("Giant ", faction.tower, 5, 8, 9, 1, effect.none), + ("Titan ", faction.tower, 5, 10, 10, 1, effect.none), + -- + ("Pixie ", faction.conflux, 1, 2, 1, 9, effect.none), + ("Spirit ", faction.conflux, 1, 3, 2, 9, effect.none), + ("Air Elemental ", faction.conflux, 1, 1, 1, 7, effect.none), + ("Storm Elemental ", faction.conflux, 1, 2, 2, 7, effect.none), + ("Water Elemental ", faction.conflux, 2, 3, 2, 4, effect.none), + ("Ice Elemental ", faction.conflux, 2, 4, 3, 4, effect.none), + ("Fire Elemental ", faction.conflux, 3, 2, 3, 5, effect.none), + ("Energy Elemental ", faction.conflux, 3, 3, 4, 5, effect.none), + ("Earth Elemental ", faction.conflux, 3, 2, 5, 3, effect.none), + ("Magma Elemental ", faction.conflux, 3, 3, 6, 3, effect.none), + ("Psychic Elemental ", faction.conflux, 4, 6, 7, 2, effect.none), + ("Magic Elemental ", faction.conflux, 4, 8, 8, 2, effect.none), + ("Fire Bird ", faction.conflux, 5, 8, 9, 1, effect.none), + ("Phoenix ", faction.conflux, 5, 10, 10, 1, effect.none), + -- + ("Skeleton ", faction.necropolis, 1, 2, 1, 9, effect.none), + ("Skeleton Warrior ", faction.necropolis, 1, 3, 2, 9, effect.none), + ("Walking Dead ", faction.necropolis, 1, 1, 1, 7, effect.none), + ("Zombie ", faction.necropolis, 1, 2, 2, 7, effect.none), + ("Wight ", faction.necropolis, 2, 3, 2, 4, effect.none), + ("Wraith ", faction.necropolis, 2, 4, 3, 4, effect.none), + ("Vampire ", faction.necropolis, 3, 2, 3, 5, effect.none), + ("Vampire Lord ", faction.necropolis, 3, 3, 4, 5, effect.none), + ("Lich ", faction.necropolis, 3, 2, 5, 3, effect.none), + ("Power Lich ", faction.necropolis, 3, 3, 6, 3, effect.none), + ("Black Knight ", faction.necropolis, 4, 6, 7, 2, effect.none), + ("Dread Knight ", faction.necropolis, 4, 8, 8, 2, effect.none), + ("Bone Dragon ", faction.necropolis, 5, 8, 9, 1, effect.none), + ("Ghost Dragon ", faction.necropolis, 5, 10, 10, 1, effect.none), + -- + ("Centaur ", faction.rampart, 1, 2, 1, 9, effect.none), + ("Centaur Captain ", faction.rampart, 1, 3, 2, 9, effect.none), + ("Dwarf ", faction.rampart, 1, 1, 1, 7, effect.none), + ("Battle Dwarf ", faction.rampart, 1, 2, 2, 7, effect.none), + ("Wood Elf ", faction.rampart, 2, 3, 2, 4, effect.none), + ("Grand Elf ", faction.rampart, 2, 4, 3, 4, effect.none), + ("Pegasus ", faction.rampart, 3, 2, 3, 5, effect.none), + ("Silver Pegasus ", faction.rampart, 3, 3, 4, 5, effect.none), + ("Dendroid Guard ", faction.rampart, 3, 2, 5, 3, effect.none), + ("Dendroid Soldier ", faction.rampart, 3, 3, 6, 3, effect.none), + ("Unicorn ", faction.rampart, 4, 6, 7, 2, effect.none), + ("War Unicorn ", faction.rampart, 4, 8, 8, 2, effect.none), + ("Green Dragon ", faction.rampart, 5, 8, 9, 1, effect.none), + ("Gold Dragon ", faction.rampart, 5, 10, 10, 1, effect.none), + -- + ("Gnoll ", faction.fortress, 1, 2, 1, 9, effect.none), + ("Gnoll Marauder ", faction.fortress, 1, 3, 2, 9, effect.none), + ("Lizardman ", faction.fortress, 1, 1, 1, 7, effect.none), + ("Lizard Warrior ", faction.fortress, 1, 2, 2, 7, effect.none), + ("Serpentfly ", faction.fortress, 2, 3, 2, 4, effect.none), + ("Dragonfly ", faction.fortress, 2, 4, 3, 4, effect.none), + ("Basilisk ", faction.fortress, 3, 2, 3, 5, effect.none), + ("Greater Basilisk ", faction.fortress, 3, 3, 4, 5, effect.none), + ("Gorgon ", faction.fortress, 3, 2, 5, 3, effect.none), + ("Mighty Gorgon ", faction.fortress, 3, 3, 6, 3, effect.none), + ("Wyvern ", faction.fortress, 4, 6, 7, 2, effect.none), + ("Wyvern Monarch ", faction.fortress, 4, 8, 8, 2, effect.none), + ("Hydra ", faction.fortress, 5, 8, 9, 1, effect.none), + ("Chaos Hydra ", faction.fortress, 5, 10, 10, 1, effect.none), + -- + ("Troglodyte ", faction.dungeon, 1, 2, 1, 9, effect.none), + ("Infernal Troglodyte ", faction.dungeon, 1, 3, 2, 9, effect.none), + ("Harpy ", faction.dungeon, 1, 1, 1, 7, effect.none), + ("Harpy Hag ", faction.dungeon, 1, 2, 2, 7, effect.none), + ("Evil Eye ", faction.dungeon, 2, 3, 2, 4, effect.none), + ("Beholder ", faction.dungeon, 2, 4, 3, 4, effect.none), + ("Medusa ", faction.dungeon, 3, 2, 3, 5, effect.none), + ("Medusa Queen ", faction.dungeon, 3, 3, 4, 5, effect.none), + ("Minotaur ", faction.dungeon, 3, 2, 5, 3, effect.none), + ("Minotaur King ", faction.dungeon, 3, 3, 6, 3, effect.none), + ("Manticore ", faction.dungeon, 4, 6, 7, 2, effect.none), + ("Scorpicore ", faction.dungeon, 4, 8, 8, 2, effect.none), + ("Red Dragon ", faction.dungeon, 5, 8, 9, 1, effect.none), + ("Black Dragon ", faction.dungeon, 5, 10, 10, 1, effect.none) + ); + + ------------------------------------------------------------------------------------------ + + procedure configure; + + procedure draw (index : in codex; state : in animation; x, y : in integer); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end unit; diff --git a/source/world.adb b/source/world.adb new file mode 100644 index 0000000..10aa103 --- /dev/null +++ b/source/world.adb @@ -0,0 +1,153 @@ +with ada.strings.fixed; +with core, menu, resource, item, unit, construction; + +use world; + +package body world is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type entity is + record + index, x, y : integer; + end record; + + type block_array is array (natural range <>, natural range <>) of integer; + type entity_array is array (natural range <>) of entity; + + type information is + record + terrain : codex; + width : natural; + height : natural; + block : access block_array; + landmark : access entity_array; + construction : access entity_array; + end record; + + type sprite_array is array (natural range <>) of core.sprite; + + type world_array is array (natural range <>) of access information; + + type limit_array is array (codex) of integer; + + type landmark_sprite_array is array (codex) of access sprite_array; + + ------------------------------------------------------------------------------------------ + + blocks : core.sprite; + landmarks : landmark_sprite_array := (others => null); + map : information; + + limit : constant limit_array := (29, 64, 70, 94, 51, 94); + + ------------------------------------------------------------------------------------------ + + procedure configure is + begin + blocks := core.load_sprite ("sprite/world/terrain/terrain.png", 1, 1); + -- + for index in codex + loop + landmarks (index) := new sprite_array (0 .. limit (index)); + for value in 0 .. limit (index) + loop + declare + folder : constant string := core.lowercase (codex'image (index)); + file : constant string := ada.strings.fixed.trim (integer'image (value), ada.strings.left); + begin + landmarks (index) (value) := core.load_sprite ("sprite/world/landmark/" & folder & "/" & file & ".png", 1, 1); + end; + end loop; + end loop; + end configure; + + ------------------------------------------------------------------------------------------ + + procedure make (index : in codex; width, height : in natural) is + begin + map.terrain := index; + map.width := width; + map.height := height; + map.block := new block_array (0 .. width - 1, 0 .. height - 1); + map.landmark := new entity_array (0 .. 24); + map.construction := new entity_array (0 .. 11); + -- + for x in 0 .. width - 1 + loop + for y in 0 .. height - 1 + loop + map.block (x, y) := core.random_integer (0, 23); + end loop; + end loop; + -- + for object in 0 .. 24 + loop + map.landmark (object).index := core.random_integer (0, limit (index)); + map.landmark (object).x := core.base * core.random_integer (1, map.width - 1); + map.landmark (object).y := core.base * core.random_integer (1, map.height - 1); + end loop; + -- + for object in 0 .. 11 + loop + map.construction (object).index := core.random_integer (0, construction.codex'pos (construction.codex'last)); + map.construction (object).x := core.base * core.random_integer (1, map.width - 1); + map.construction (object).y := core.base * core.random_integer (1, map.height - 1); + end loop; + end make; + + ------------------------------------------------------------------------------------------ + + procedure draw (x, y, width, height : in integer; show_grid : in boolean) is + crop_width : constant integer := width mod core.base; + crop_height : constant integer := height mod core.base; + u, v : integer; + begin + for move_y in 0 .. height / core.base - 1 + loop + for move_x in 0 .. width / core.base - 1 + loop + u := core.base * codex'pos (map.terrain) * 4; + v := core.base * map.block (move_x, move_y); + -- + core.crop (blocks, x + move_x * core.base, y + move_y * core.base, u, v, core.base, core.base); + end loop; + -- + u := core.base * codex'pos (map.terrain) * 4; + v := core.base * map.block (width / core.base, move_y); + -- + core.crop (blocks, x + width - crop_width, y + move_y * core.base, u, v, crop_width, core.base); + end loop; + -- + for move_x in 0 .. width / core.base - 1 + loop + u := core.base * codex'pos (map.terrain) * 4; + v := core.base * map.block (move_x, height / core.base); + -- + core.crop (blocks, x + move_x * core.base, y + height - crop_height, u, v, core.base, crop_height); + end loop; + -- + u := core.base * codex'pos (map.terrain) * 4; + v := core.base * map.block (width / core.base, height / core.base); + -- + core.crop (blocks, x + width - crop_width, y + height - crop_height, u, v, crop_width, crop_height); + -- + for object in 0 .. 24 + loop + core.draw (landmarks (map.terrain) (map.landmark (object).index), map.landmark (object).x, map.landmark (object).y); + end loop; + -- + if show_grid then + core.hexagonal_grid (x, y, width, height, false); + core.hexagonal_grid (x, y, width, height, true); + end if; + -- + for object in 0 .. 11 + loop + construction.draw (construction.codex'val (map.construction (object).index), map.construction (object).x, map.construction (object).y); + end loop; + end draw; + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end world; diff --git a/source/world.ads b/source/world.ads new file mode 100644 index 0000000..7586bcc --- /dev/null +++ b/source/world.ads @@ -0,0 +1,21 @@ +with core, menu, resource, item, unit, construction; + +package world is + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + type codex is ( + ash, cave, grass, rough, snow, swamp + ); + + ------------------------------------------------------------------------------------------ + + procedure configure; + + procedure make (index : in codex; width, height : in natural); + + procedure draw (x, y, width, height : in integer; show_grid : in boolean); + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +end world; diff --git a/source/xcb.c b/source/xcb.c new file mode 100644 index 0000000..586ef5a --- /dev/null +++ b/source/xcb.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define FONT_WIDTH ( 9) +#define FONT_HEIGHT (18) + +static unsigned int * * render_texture = NULL; +static int * render_texture_w = NULL; +static int * render_texture_h = NULL; +static int render_texture_count = 0; + +static unsigned int * font = NULL; +static unsigned int * mono = NULL; + +static int screen_width = 1800; +static int screen_height = 900; + +static xcb_window_t window = 0; +static xcb_gcontext_t context = 0; +static xcb_pixmap_t pixmap = 0; +static xcb_connection_t * connection = NULL; +static xcb_screen_t * screen = NULL; +static xcb_image_t * image = NULL; +static unsigned int * framebuffer = NULL; + +static unsigned int * import_png (char * path, int * w, int * h) { + unsigned int buffer [1024*1024] = { 0 }; + unsigned int * data = NULL; + png_image temporary = { 0 }; + temporary.version = PNG_IMAGE_VERSION; + if (! png_image_begin_read_from_file (& temporary, path)) printf ("PNG: image begin read from file fuck up!\n"); + temporary.format = PNG_FORMAT_BGRA; + if (! png_image_finish_read (& temporary, NULL, buffer, 0, NULL)) printf ("PNG: image finish read fuck up!\n"); + if (w != NULL) * w = temporary.width; + if (h != NULL) * h = temporary.height; + if (buffer == NULL) printf ("PNG: empty buffer fuck up!\n"); + png_image_free (& temporary); + data = calloc (temporary.width * temporary.height, sizeof (* data)); + if (data == NULL) printf ("PNG: empty data fuck up!\n"); + memcpy (data, buffer, temporary.width * temporary.height * sizeof (* data)); + return (data); +} + +static void render_clean_up (void) { + int i; + + printf ("Deinitializing graphical components...\n"); + + for (i = 0; i < render_texture_count; ++i) + free (render_texture [i]); + + free (render_texture); + + free (font); + free (mono); + + xcb_free_gc (connection, context); + + xcb_free_pixmap (connection, pixmap); + + xcb_destroy_window (connection, window); + + xcb_disconnect (connection); +} + +extern int signal_x; +extern int signal_y; +extern int cursor_mode; +extern int signal_mode; + +extern int engine_active; + +extern int window_width (void); +extern int window_height (void); + +extern void render_sprite (int sprite, int x, int y, int u, int v, int width, int height); +extern void render_string (char * string, int x, int y, int colour, char monospace); + +extern void engine_configure (void); +extern void engine_synchronize (void); + +extern int sprite_import (char * path); +extern int sprite_width (int index); +extern int sprite_height (int index); + +int signal_x = 0; +int signal_y = 0; +int cursor_mode = 0; +int signal_mode = 0; + +int engine_active = 0; + +int window_width (void) { return (screen_width); } +int window_height (void) { return (screen_height); } + +void render_sprite (int sprite, int x, int y, int u, int v, int width, int height) { + int sprite_x, sprite_y; + + width = (width < 0) ? -width : width; + height = (height < 0) ? -height : height; + + if ((x < 0) || (y < 0) + || (x > window_width () - width) || (y > window_height () - height)) { + return; + } + + for (sprite_y = 0; sprite_y < height; ++sprite_y) { + for (sprite_x = 0; sprite_x < width; ++sprite_x) { + int o = (sprite_y + y) * window_width () + (sprite_x + x); + int s = (sprite_y + v) * sprite_width (sprite) + (sprite_x + u); + framebuffer [o] = ((render_texture [sprite] [s] & 0XFF000000) < 0X04) ? + framebuffer [o] : render_texture [sprite] [s]; + } + } +} + +void render_string (char * string, int x, int y, int colour, char monospace) { + /*Vector2 position = { 4, 4 }; + Color new_tint = { 255, 255, 255, 255 }; + + position.x += x; + position.y += y; + + new_tint.r = ((colour & 0XFF0000) >> 16) % 256; + new_tint.g = ((colour & 0X00FF00) >> 8) % 256; + new_tint.b = ((colour & 0X0000FF) >> 0) % 256; + + DrawTextPro ((monospace != 0) ? mono : font, string, position, dump, 0.0, 24, 6, new_tint); + */ + (void) string; + (void) x; + (void) y; + (void) colour; + (void) monospace; +} + +void engine_configure (void) { + unsigned int values [2] = { + 0, + XCB_EVENT_MASK_NO_EVENT | + XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_RESIZE_REDIRECT | + XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_KEY_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_POINTER_MOTION + }; + + engine_active = 1; + + printf ("Initializing graphical components...\n"); + + font = import_png ("sprite/font/font.png", NULL, NULL); + mono = import_png ("sprite/font/mono.png", NULL, NULL); + + connection = xcb_connect (NULL, NULL); + + screen = xcb_setup_roots_iterator (xcb_get_setup (connection)) . data; + + values [0] = screen -> black_pixel; + + window = xcb_generate_id (connection); + context = xcb_generate_id (connection); + pixmap = xcb_generate_id (connection); + + xcb_create_window (connection, screen -> root_depth, window, screen -> root, 0, 0, (uint16_t) window_width (), (uint16_t) window_height (), 10, + XCB_WINDOW_CLASS_INPUT_OUTPUT, screen -> root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, values); + + xcb_map_window (connection, window); + + xcb_change_property (connection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, + sizeof ("-- Chads of Might & Magic --"), "-- Chads of Might & Magic --"); + + xcb_create_pixmap (connection, screen -> root_depth, pixmap, window, (uint16_t) window_width (), (uint16_t) window_height ()); + + xcb_create_gc (connection, context, pixmap, 0, NULL); + + xcb_flush (connection); + + atexit (render_clean_up); +} + +void engine_synchronize (void) { + xcb_generic_event_t * event = NULL; + + if (framebuffer != NULL) { + image = xcb_image_create_native (connection, (uint16_t) screen_width, (uint16_t) screen_height, XCB_IMAGE_FORMAT_Z_PIXMAP, screen -> root_depth, + framebuffer, (uint32_t) (screen_width * screen_height * (int32_t) sizeof (* framebuffer)), (uint8_t *) framebuffer); + + xcb_image_put (connection, pixmap, context, image, 0, 0, 0); + + xcb_image_destroy (image); + + xcb_copy_area (connection, pixmap, window, context, 0, 0, 0, 0, (uint16_t) screen_width, (uint16_t) screen_height); + } + + event = xcb_wait_for_event (connection); + + if (event == NULL) { + return; + } else if ((event->response_type & 127) == XCB_EXPOSE) { + xcb_flush (connection); + } else if ((event->response_type & 127) == XCB_KEY_PRESS) { + printf ("Key: %i\n", ((xcb_key_press_event_t *) event)->detail); + switch (((xcb_key_press_event_t *) event)->detail) { + case 24: engine_active = 0; break; + case 25: cursor_mode = 4; break; + case 26: cursor_mode = 5; break; + case 27: cursor_mode = 6; break; + case 28: cursor_mode = 7; break; + default: break; + } + } else if ((event->response_type & 127) == XCB_BUTTON_PRESS) { + xcb_button_press_event_t * button_press_event = (xcb_button_press_event_t *) event; + cursor_mode = button_press_event->detail; + } else if ((event->response_type & 127) == XCB_MOTION_NOTIFY) { + xcb_motion_notify_event_t * button_press_event = (xcb_motion_notify_event_t *) event; + signal_x = button_press_event->event_x; + signal_y = button_press_event->event_y; + } + + free (event); + + framebuffer = calloc ((size_t) (screen_width * screen_height), sizeof (* framebuffer)); + + signal_mode = 0; +} + +int import_sprite (char * path) { + ++render_texture_count; + + render_texture = realloc (render_texture, (unsigned long int) render_texture_count * sizeof (* render_texture)); + render_texture_w = realloc (render_texture_w, (unsigned long int) render_texture_count * sizeof (* render_texture_w)); + render_texture_h = realloc (render_texture_h, (unsigned long int) render_texture_count * sizeof (* render_texture_h)); + + render_texture [render_texture_count - 1] = import_png (path, & render_texture_w [render_texture_count - 1], & render_texture_h [render_texture_count - 1]); + + if (render_texture [render_texture_count - 1] == NULL) { + printf ("\033[1;31m%3i : '%60s';\033[0m\n", render_texture_count - 1, path); + } + + return (render_texture_count - 1); +} + +int sprite_width (int index) { + return (render_texture_w [index]); +} + +int sprite_height (int index) { + return (render_texture_h [index]); +}