Swamp Slogger
Posts: 174
Joined: Thursday, 15th November 2012, 02:12
Implementing Zig proposal from Wiki
- can monsters use portal projectile if so which spell slot? also slots for blinking? See code -- alas it seems they cannot
- how/where is the ziggurat code called?
- what is the difference between you.depth and env.absdepth0?
- how to disable cTele on a floor? using lua for this
- how to waken monsters (other than with noise)? set using BEH_WANDER
- how to make * | and "good scrolls" items? also using lua
Differences from ziggurat.lua
C++
(eventually) more types of layout
glass windows/wall to see outside (still todo: lightening and birds ect.)
Xom and Chei floors (WiP)
Mutagenic floor (don't kill me)
no same floors per zig -32 different floors
monster weights slightly different
Still Todo
-hd pool --done
-loot chamber for slime floors -- using lua
-copy the hexagon , circle and ellipse floor generators --using lua
- Code:
/**
* @file
* @brief The dungeon builder for Ziggurats.
**/
#include "AppHdr.h"
#include "lua.h"
#include "coordit.h"
#include "dungeon.h"
#include "items.h"
#include "mapmark.h"
#include "maps.h"
#include "mgen_data.h"
#include "misc.h"
#include "mon-place.h"
#include "mon-pick.h"
#include "colour.h"
#include "terrain.h"
#include "dlua.h"
#include "cluautil.h"
#include "l_defs.h"
enum zig_floor_t
{
//elemental
ZIGF_AIR,
ZIGF_EARTH,
ZIGF_FIRE,
ZIGF_ICE,
//location
ZIGF_ORC,
ZIGF_ELF,
ZIGF_DWARF,
ZIGF_LAIR,
ZIGF_SHOAL,
ZIGF_SNAKE,
ZIGF_SPIDER,
ZIGF_SWAMP,
ZIGF_SLIME,
ZIGF_VAULTS,
ZIGF_FOREST,
ZIGF_CRYPT,
ZIGF_TOMB,
ZIGF_GEHENNA,
ZIGF_COCYTIS,
ZIGF_DIS,
ZIGF_TARTARUS,
ZIGF_ABYSS,
ZIGF_ZOT,
ZIGF_PAN,
//monster sets
ZIGF_DRACONIAN,
ZIGF_DRAGON,
ZIGF_RANGED,
ZIGF_GIANT,
ZIGF_HOLY,
ZIGF_MUTAGENIC,
//gods not (necessarily) represented in the above
ZIGF_XOM,
ZIGF_CHEI,
// ZIGF_FEDHAS,
// ZIGF_NEMELEX,
// ZIGF_OKAWARU,
NUM_ZIGF
};
static struct {
zig_floor_t floor;
int tot_weights;
level_id lid;
int lid_wieght;
int orig_hd_pool;
int hdpool;
bool chamber;// slime foors
bool genawake;
} _floors[27];
static bool water;
static int current_floor;//0-26
static int eccentricity;//0-100
static int tod; // 1 == halo, 0 == nothing, -1 == night (umbra,gloom?)
static int _mon_weights[MAX_MONS_ALLOC];
static void _random_xom_mons( coord_def at, bool awake);
static void _chei_mons(monster* mon);
static void _loot(coord_def at );
static zig_floor_t _random_floor_for_level()
{
int i;
bool done;
do
{
done = true;
i = random2(NUM_ZIGF);
for (int j=0; j<current_floor; j++) {
done = done && (_floors[i].floor != i);
}
} while (!done);
return _floors[current_floor].floor = (zig_floor_t)i;
};
static const char* zigf2string(zig_floor_t floor)
{
switch (floor) {
case ZIGF_AIR:
return "Air";
case ZIGF_ABYSS:
return "Abyss";
case ZIGF_CHEI:
return "Chei";
case ZIGF_COCYTIS:
return "Coc";
case ZIGF_CRYPT:
return "Crypt";
case ZIGF_DIS:
return "Dis";
case ZIGF_DRACONIAN:
return "Drac";
case ZIGF_DRAGON:
return "Dragon";
case ZIGF_DWARF:
return "Dwarf";
case ZIGF_EARTH:
return "Earth";
case ZIGF_ELF:
return "Elf";
case ZIGF_FIRE:
return "Fire";
case ZIGF_FOREST:
return "Forest";
case ZIGF_GEHENNA:
return "Geh";
case ZIGF_GIANT:
return "Giant";
case ZIGF_HOLY:
return "Holy";
case ZIGF_ICE:
return "Ice";
case ZIGF_LAIR:
return "Lair";
case ZIGF_MUTAGENIC:
return "Mut";
case ZIGF_ORC:
return "Orc";
case ZIGF_PAN:
return "Pan";
case ZIGF_RANGED:
return "Range";
case ZIGF_SHOAL:
return "Shoal";
case ZIGF_SLIME:
return "Slime";
case ZIGF_SNAKE:
return "Snake";
case ZIGF_SPIDER:
return "Spider";
case ZIGF_SWAMP:
return "Swamp";
case ZIGF_TARTARUS:
return "Tar";
case ZIGF_TOMB:
return "Tomb";
case ZIGF_VAULTS:
return "Vault";
case ZIGF_XOM:
return "Xom";
case ZIGF_ZOT:
return "Zot";
break;
default:
return "";
break;
}
};
LUARET1( zig_floor_type , string, zigf2string(_floors[current_floor].floor));
vector<coord_def> build_isos_tri ( int level, int windows, bool mirrored);
LUAFN(zig_dump)
{
dprf("Dumping zig info:");
for (int i = 0 ; i < 27; i++)
{
dprf("--------------------------------");
dprf("Floor: %d",i);
dprf("Floor type: %s",zigf2string(_floors[i].floor));
if (_floors[i].lid_wieght)
dprf("Weight for native branch %d", _floors[i].lid_wieght);
dprf("Total weight %d", _floors[i].lid_wieght + _floors[i].tot_weights);
dprf("Hd pool of %d",_floors[i].orig_hd_pool );
dprf("Hd left in pool %d", _floors[i].hdpool);
if (_floors[i].genawake)
dprf("Monster generated awake");
if (_floors[i].chamber)
dprf("Generated a loot chamber");
}
return 1;
}
LUARET1(zig_tod, number , tod);
LUARET1(zig_exc, number , eccentricity);
LUAFN(zig_set_level)
{
current_floor = luaL_checknumber(ls, 1);
return 1;
}
LUAFN(zig_init)
{
current_floor = env.absdepth0;
for (int i=0; i < MAX_MONS_ALLOC; i++) {
_mon_weights[i] = 0;
if (current_floor == 0 ){
_floors[i].floor = NUM_ZIGF;
_floors[i].chamber = false;
}
}
if (current_floor == 0)
{
water = coinflip();
eccentricity = random2(101);
tod = random2(3)-1;
}
_floors[current_floor].lid = level_id(NUM_BRANCHES);
zig_floor_t type = _random_floor_for_level();
_floors[current_floor].genawake = current_floor > 4 + random2(21);
bool noctele = current_floor > 6 + random2(19);
/*if (noctele)
//Todo: moredirect
dlua.callfn("dgn.change_level_flags", "no_tele_control");
*/
int area = 30 + (current_floor +18) * current_floor;
_floors[current_floor].hdpool = _floors[current_floor].orig_hd_pool = you.depth * (you.depth +8);
#define emaw(a,b,c) env.mons_alloc[a] = (monster_type) b;\
_mon_weights[a] = c;\
_floors[current_floor].tot_weights +=c
#define natives( weight ,place ) \
_floors[current_floor].lid_wieght= weight;\
_floors[current_floor].lid = level_id::parse_level_id(place)
switch (type)
{
case ZIGF_AIR:
emaw(0, MONS_INSUBSTANTIAL_WISP ,10);
emaw(1, MONS_AIR_ELEMENTAL ,10);
emaw(2, MONS_VAPOUR ,10);
emaw(3, MONS_TITAN ,10);
emaw(4, MONS_STORM_DRAGON ,10);
emaw(5, MONS_ELECTRIC_GOLEM ,10);
emaw(6, MONS_SPRIGGAN_AIR_MAGE ,10);
break;
case ZIGF_EARTH:
emaw(0, MONS_EARTH_ELEMENTAL ,10);
emaw(1, MONS_CRYSTAL_GOLEM ,10);
emaw(2, MONS_GARGOYLE ,10);
emaw(3, MONS_GOLEM ,10);
emaw(4, MONS_STONE_GIANT ,10);
emaw(5, MONS_STONE_GOLEM ,10);
emaw(6, MONS_METAL_GARGOYLE ,10);
emaw(7, MONS_MOLTEN_GARGOYLE ,10);
emaw(8, MONS_IRON_GOLEM ,10);
emaw(9, MONS_IRON_DRAGON ,10);
emaw(10, MONS_IRON_TROLL ,10);
emaw(11, MONS_QUICKSILVER_DRAGON ,10);
break;
case ZIGF_FIRE:
emaw(0, MONS_FIRE_ELEMENTAL ,10);
emaw(1, MONS_FIRE_DRAKE ,10);
emaw(2, MONS_HELL_HOUND ,10);
emaw(3, MONS_EFREET ,10);
emaw(4, MONS_DRAGON ,10);
emaw(5, MONS_FIRE_GIANT ,10);
emaw(6, MONS_ORB_OF_FIRE ,10);
break;
case ZIGF_ICE:
emaw(0, MONS_ICE_BEAST ,10);
emaw(1, MONS_POLAR_BEAR ,10);
emaw(2, MONS_FREEZING_WRAITH ,10);
emaw(3, MONS_ICE_DRAGON ,10);
emaw(4, MONS_FROST_GIANT ,10);
emaw(5, MONS_ICE_DEVIL ,10);
emaw(6, MONS_ICE_FIEND ,10);
emaw(7, MONS_SIMULACRUM ,20);
emaw(8, MONS_BLIZZARD_DEMON ,10);
break;
case ZIGF_ORC:
natives(310 - 10* you.depth, "Orc:$");
emaw(0, MONS_ORC_WARLORD ,10);
emaw(1, MONS_ORC_HIGH_PRIEST , 5);
emaw(2, MONS_ORC_KNIGHT ,10);
emaw(3, MONS_ORC_SORCERER , 5);
emaw(4, MONS_STONE_GIANT ,10);
emaw(5, MONS_MOTH_OF_WRATH, max(0, you.depth - 20));
break;
case ZIGF_ELF:
natives(300 - 10*you.depth, "Elf:$");
emaw(0, MONS_DEEP_ELF_SORCERER ,10);
emaw(1, MONS_DEEP_ELF_BLADEMASTER ,10);
emaw(2, MONS_DEEP_ELF_MASTER_ARCHER ,10);
emaw(3, MONS_DEEP_ELF_ANNIHILATOR ,10);
emaw(4, MONS_DEEP_ELF_DEMONOLOGIST ,10);
emaw(5, MONS_DEEP_ELF_DEATH_MAGE ,10);
emaw(6, MONS_DEEP_ELF_HIGH_PRIEST ,10);
break;
case ZIGF_DWARF:
//natives(10 ,"Dwarf:$");
emaw(0, MONS_DEEP_DWARF_SCION ,10);
emaw(1, MONS_DEEP_DWARF_NECROMANCER ,10);
emaw(2, MONS_DEEP_DWARF_BERSERKER ,10);
emaw(3, MONS_DEEP_DWARF ,20);
emaw(4, MONS_DEEP_DWARF_ARTIFICER ,10);
emaw(5, MONS_DEEP_DWARF_DEATH_KNIGHT ,10);
emaw(6, MONS_UNBORN_DEEP_DWARF ,10);
break;
case ZIGF_LAIR:
natives(85, "Lair:$");
emaw(0, MONS_CATOBLEPAS ,6);
emaw(1, MONS_DIRE_ELEPHANT ,6);
emaw(2, MONS_HELLEPHANT ,3);
break;
case ZIGF_SHOAL:
natives(125, "Shoal:$");
emaw(0, MONS_MERFOLK_AQUAMANCER ,15);
emaw(1, MONS_MERFOLK_IMPALER , 4);
break;
case ZIGF_SNAKE:
natives(90, "Snake:$");
emaw(0, MONS_GREATER_NAGA ,5);
emaw(1, MONS_GUARDIAN_SERPENT ,5);
break;
case ZIGF_SPIDER:
natives(110, "Spider:$");
emaw(0, MONS_GHOST_MOTH ,15);
emaw(1, MONS_RED_WASP ,10);
emaw(2, MONS_ORB_SPIDER ,10);
emaw(3, MONS_MOTH_OF_SUPPRESSION , 5);
break;
case ZIGF_SWAMP:
natives(120, "Swamp:$");
emaw(0, MONS_HYDRA ,10);
emaw(1, MONS_SWAMP_DRAGON ,10);
emaw(2, MONS_GREEN_DEATH , 6);
emaw(3, MONS_DEATH_DRAKE , 4);
break;
case ZIGF_SLIME:
natives(10, "Slime:$");
_floors[current_floor].chamber = true;
break;
case ZIGF_VAULTS:
natives(60, "Vaults:$");
emaw(0, MONS_ANCIENT_LICH, max(0 , you.depth - 12));
break;
case ZIGF_FOREST:
natives(180, "Forest:$");
emaw(0, MONS_SATYR ,10);
emaw(1, MONS_TENGU_REAVER , 5);
emaw(2, MONS_SPRIGGAN_DEFENDER, 5);
break;
case ZIGF_CRYPT:
natives(180, "Crypt:$");
emaw(0, MONS_VAMPIRE_KNIGHT ,14);
emaw(1, MONS_LICH , 3);
emaw(2, MONS_UNBORN_DEEP_DWARF, 2);
emaw(3, MONS_CURSE_TOE , 1);
break;
case ZIGF_TOMB:
natives(200, "Tomb:$");
emaw(0,MONS_GREATER_MUMMY , you.depth +5);
break;
case ZIGF_GEHENNA:
natives(460, "Geh:$");
emaw(0, MONS_BRIMSTONE_FIEND ,10);
emaw(1, MONS_BALRUG ,30);
break;
case ZIGF_COCYTIS:
natives(460, "Coc:$");
emaw(0, MONS_ICE_FIEND ,10);
emaw(1, MONS_BLIZZARD_DEMON ,30);
break;
case ZIGF_DIS:
natives(460, "Dis:$");
emaw(0, MONS_HELL_SENTINEL ,10);
emaw(1, MONS_IRON_DRAGON ,20);
emaw(2, MONS_DANCING_WEAPON ,10);
break;
case ZIGF_TARTARUS:
natives(460, "Tar:$");
emaw(0, MONS_SHADOW_FIEND ,10);
emaw(1, MONS_SHADOW_DEMON ,20);
emaw(2, MONS_CURSE_TOE ,10);
break;
case ZIGF_ABYSS:
natives(10, "Abyss");
break;
case ZIGF_ZOT:
natives(10, "Zot:$");
break;
case ZIGF_PAN:
natives(45, "Pan");
emaw(0, MONS_PANDEMONIUM_LORD , max(0, you.depth -5 ));
case ZIGF_DRACONIAN:
// see zig_mons(coord_def,bool)
break;
case ZIGF_DRAGON:
emaw(0, MONS_SWAMP_DRAKE , 5);
emaw(1, MONS_FIRE_DRAKE , 5);
emaw(2, MONS_DEATH_DRAKE ,10);
emaw(3, MONS_STEAM_DRAGON , 5);
emaw(4, MONS_SWAMP_DRAGON ,10);
emaw(5, MONS_DRAGON ,10);
emaw(6, MONS_ICE_DRAGON ,10);
emaw(7, MONS_STORM_DRAGON ,10);
emaw(8, MONS_IRON_DRAGON ,10);
emaw(9, MONS_SHADOW_DRAGON ,10);
emaw(10, MONS_QUICKSILVER_DRAGON ,10);
emaw(11, MONS_GOLDEN_DRAGON ,10);
emaw(12, MONS_MOTTLED_DRAGON ,10);
emaw(13, MONS_WYVERN ,10);
emaw(14, MONS_HYDRA ,10);
break;
case ZIGF_RANGED:
emaw(0, MONS_CENTAUR ,10);
emaw(1, MONS_YAKTAUR ,10);
emaw(3, MONS_CENTAUR_WARRIOR ,10);
emaw(4, MONS_YAKTAUR_CAPTAIN ,10);
emaw(5, MONS_CYCLOPS ,10);
emaw(6, MONS_STONE_GIANT ,10);
emaw(7, MONS_MERFOLK_JAVELINEER ,10);
emaw(8, MONS_DEEP_ELF_MASTER_ARCHER ,10);
break;
case ZIGF_GIANT:
emaw(0, MONS_HILL_GIANT ,10);
emaw(1, MONS_CYCLOPS ,10);
emaw(2, MONS_STONE_GIANT ,10);
emaw(3, MONS_FIRE_GIANT ,10);
emaw(4, MONS_FROST_GIANT ,10);
emaw(5, MONS_ETTIN ,10);
emaw(6, MONS_TITAN ,10);
break;
case ZIGF_HOLY:
emaw(0, MONS_DAEVA ,10);
emaw(1, MONS_ANGEL ,10);
emaw(2, MONS_CHERUB ,10);
emaw(3, MONS_PEARL_DRAGON ,10);
emaw(4, MONS_OPHAN ,10);
emaw(5, MONS_APIS ,10);
emaw(6, MONS_PALADIN ,10);
emaw(7, MONS_PHOENIX , 5);
emaw(8, MONS_SILVER_STAR , 5);
emaw(9, MONS_SERAPH , 3);
break;
case ZIGF_MUTAGENIC:
emaw(0, MONS_POLYMOTH ,10);
emaw(1, MONS_NEQOXEC ,10);
emaw(2, MONS_CACODEMON ,10);
emaw(3, MONS_SHINING_EYE ,10);
emaw(4, MONS_SHAPESHIFTER ,20);
emaw(5, MONS_GLOWING_SHAPESHIFTER ,20);
emaw(6, MONS_UGLY_THING ,10);
emaw(7, MONS_VERY_UGLY_THING ,10);
emaw(8, MONS_GUARDIAN_SERPENT ,10);
emaw(9, MONS_WRETCHED_STAR , 4);
break;
case ZIGF_XOM:
// for the sake of a non emaw weighting
// doesn't matter where
//see _xom_mons for the rest
natives(80 , "D:1");
emaw(0, MONS_SHAPESHIFTER ,10);
emaw(1, MONS_GLOWING_SHAPESHIFTER ,10);
emaw(2, MONS_UGLY_THING ,10);
emaw(3, MONS_VERY_UGLY_THING ,10);
emaw(4, MONS_KILLER_KLOWN ,10);
break;
case ZIGF_CHEI:
//all these have haste stripped in _chei_mons
emaw(0, MONS_ELEPHANT_SLUG ,10);
emaw(1, MONS_GREATER_NAGA ,10);
emaw(2, MONS_CYCLOPS ,10);
emaw(3, MONS_CRYSTAL_GOLEM ,10);
emaw(4, MONS_NAGA_MAGE ,10);
emaw(5, MONS_BOULDER_BEETLE ,10);
emaw(6, MONS_SATYR ,10);
emaw(7, MONS_YAKTAUR_CAPTAIN ,10);
emaw(8, MONS_DEEP_TROLL_EARTH_MAGE ,10);
emaw(9, MONS_VAMPIRE_MAGE ,10);
emaw(10, MONS_ANCIENT_LICH , 5);
emaw(11, MONS_GARGOYLE , 5);
emaw(12, MONS_SPHINX , 5);
emaw(13, MONS_GUARDIAN_MUMMY ,10);
break;
/*
case ZIGF_FEDHAS:
break;
case ZIGF_NEMELEX:
break;
case ZIGF_OKAWARU:
break;
*/
case NUM_ZIGF:
default:
//die?
break;
};
#undef natives
#undef emaw
/*vector<coord_def> (*build)(int , int , bool )
= random_choose_weighted(1, &build_isos_tri,
0, &build_equi_tri,
0, &build_gold_rect,
-1);
vector<coord_def> loot_and_mons = build(current_floor,random2(4),current_floor % 2);
for (int i =0; i< loot_and_mons.size(); i++)
{
//zig_monster( loot_and_mons[i], awake);
//_loot(loot_and_mons[i]);
}
mprf("hd pool for floor %d:%d",current_floor,_floors[current_floor].hdpool);
*/
return 1;
}
LUARET1(zig_surrounds, string, water ? "water" : "lava");
LUAFN(zig_monster)
{
coord_def at = coord_def(luaL_checkint(ls, 1),luaL_checkint(ls, 2));
const bool awake = _floors[current_floor].genawake;
monster_type mon = MONS_0;
bool xom_retype = false;
bool pool_adjusted;
const int lidw = _floors[current_floor].lid_wieght;
if (x_chance_in_y(lidw ,lidw +_floors[current_floor].tot_weights ))
{
mon = pick_monster(_floors[current_floor].lid);
xom_retype = true;
}
else if (_floors[current_floor].floor == ZIGF_DRACONIAN)
mon = random_draconian_monster_species();
//XXX: there has to be a better way to do this
else
{
#define weight(a) _mon_weights[(a)],env.mons_alloc[(a)]
#define aweights(a) weight(a) , weight(a+1),weight(a+2),weight(a+3)
mon = random_choose_weighted(aweights(0),
aweights(4),
aweights(8),
aweights(12),
aweights(16),
-1);
#undef aweights
#undef weight
}
ASSERT(mon != MONS_0);
mgen_data mg(mon);
if (_floors[current_floor].lid.branch != NUM_BRANCHES)
{
mg.place = _floors[current_floor].lid;
}
monster * mons;
mg.pos = at;
mg.flags |= MG_FORCE_PLACE;
if (awake)
mg.behaviour = BEH_WANDER;
else
mg.behaviour = BEH_SLEEP;
if (_floors[current_floor].floor == ZIGF_XOM && xom_retype)
{
_random_xom_mons( at, awake);
}
else
{
if (mg.hd > _floors[current_floor].hdpool)
{
lua_pushboolean(ls, 0);
return 1;
}
mons = place_monster(mg, true,false);
}
if (_floors[current_floor].floor == ZIGF_CHEI)
{
_chei_mons(mons);
pool_adjusted = true;
}
if (!pool_adjusted)
_floors[current_floor].hdpool -= mons->hit_dice;
lua_pushboolean(ls, 1);
return 1;
}
// Todo: add Chimeras!!!! (and Xom effects)
void _random_xom_mons( coord_def at, bool awake)
{
monster_type newmon = pick_monster_no_rarity(
//Todo: add more branches and weight properly
random_choose_weighted(10, BRANCH_MAIN_DUNGEON,
10, BRANCH_PANDEMONIUM,
-1));
mgen_data mg(newmon);
monster* mon;
mg.pos = at;
//invert hd
//Todo: better inversion
//hd 3 OoF anyone? how about hd 33 rat with forestorm?
if (coinflip())
mg.hd = max(3, 30-mg.hd);
if (one_chance_in(5))
{
mg.hd += random2(5);
}
//Don't exceed the hd pool for this floor
mg.hd = min(mg.hd , _floors[current_floor].hdpool);
mg.flags |= MG_FORCE_PLACE;
if (awake)
mg.behaviour = BEH_WANDER;
else
mg.behaviour = BEH_SLEEP;
mon = place_monster(mg, true,false);
mon->god = GOD_XOM;
int num_spells = 0;
if (!mon->flags & M_FAKE_SPELLS)
{
for (int i=0; i<6; i++)
{
if (mon->spells[i] != SPELL_NO_SPELL && mon->spells[i]!= SPELL_MELEE)
num_spells++;
}
}
//Todo: add more random spell appropriate for
// -Xom
// -Correct spell slot
//*storm is currently a place holder
static const spell_type X1[]=
{
SPELL_FIRE_STORM,
SPELL_MAGIC_DART,
SPELL_LEHUDIBS_CRYSTAL_SPEAR,
SPELL_THROW_FROST,
SPELL_CHAIN_LIGHTNING,
SPELL_BOLT_OF_INACCURACY
};
static const spell_type X2[]=
{
SPELL_ICE_STORM,
};
static const spell_type X3[]=
{
SPELL_SHATTER,
};
static const spell_type X4[]=
{
SPELL_TORNADO,
};
static const spell_type X5[]=
{
SPELL_TOMB_OF_DOROKLOHE,
};
static const spell_type X6[]=
{
SPELL_SUMMON_BUTTERFLIES,
};
static const spell_type* Xom_spells[6]=
{
(spell_type*)&X1,
(spell_type*)&X2,
(spell_type*)&X3,
(spell_type*)&X4,
(spell_type*)&X5,
(spell_type*)&X6,
};
if (coinflip())
{
num_spells = 6 - num_spells;
for (int i=0; i<6; i++)
{
if (x_chance_in_y(num_spells , 6))
mon->spells[i] = RANDOM_ELEMENT(Xom_spells[i]);
}
mon->flags |= M_SPELLCASTER;
}
//Todo: Set more flags?
if (one_chance_in(10))
{
mon->flags |= M_INVIS;
}
if (one_chance_in(10))
{
mon->flags |= M_SEE_INVIS;
}
if (one_chance_in(10))
{
mon->flags |= M_BATTY;
}
//Todo: meddle with resists
//brimstone fiend with rF-?
//Xom roars with laughter
//swap AC/ev
if (coinflip())
{
int tmp = mon->ac;
mon->ac = mon->ev;
mon->ev = tmp;
}
}
void _chei_mons(monster * mon)
{
_floors[current_floor].hdpool -= mon->hit_dice;
int mod =2 + random2(4);
mon->speed -= mod;
mon->speed = max(mon->speed, 3);//3?
mon->hit_dice += mod - 1;
mon->hit_dice= max(mon->hit_dice, 33);
// should be interesting when monsters get invocations
// need to disable slouch or make it affect only you and your allies
// also limit the (ab)use of step from time
mon->god = GOD_CHEIBRIADOS;
if (mon->can_use_spells() )
{
for (int i=0; i<6; i++)
{
if (mon->spells[i] == SPELL_HASTE)
mon->spells[i] = mon->is_fighter() ? SPELL_BLINK_CLOSE :
mon->is_archer() ? SPELL_BLINK_AWAY :
SPELL_CONTROLLED_BLINK;
else if (mon->spells[i] == SPELL_HASTE_OTHER)
mon->spells[i] = coinflip() ? SPELL_SLOW
: SPELL_MIGHT_OTHER;
if (mon->is_archer() && i == 4 //4? Correct slot
&& one_chance_in(3)) //Too nasty?
{
mon->spells[i] = SPELL_PORTAL_PROJECTILE;
}
if (i==3 && // 3?
(mon->spells[i]== SPELL_NO_SPELL ||
mon->spells[i] ==SPELL_MELEE )
&& one_chance_in(3))
{
mon->spells[i] = SPELL_BLINK_CLOSE;
}
}
}
}
vector<coord_def> build_isos_tri(int level, int windows, bool mirrored)
{
coord_def top = coord_def( (GXM-1)/2 - ((GXM-1)/2)*level/27, GYM/2);
if (mirrored)
top = coord_def(GXM,0) - top;
const int baseline = GXM -top.x;
const int height = level* 3 -1;
const int width = level * 2;
bool last_window = false;
vector<coord_def> ret;
int minx,maxx;
for (int i = 0; i < GXM; i++)
{
for (int j = 0; j < GYM; j++)
{
//if it's outside the triangle
//below the base or above the top
if ((mirrored &&
((i < baseline -1 || i > top.x +1)
//in between the base and top but still outside
|| abs(j-35) +1 > i *width/height))
||
((i > baseline +1 || i < top.x -1)
|| abs(j-GYM/2) +1 > i *width/height))
{
grd[i][j] = water ? DNGN_DEEP_WATER : DNGN_LAVA;
env.pgrid[i][j] |= FPROP_NO_TELE_INTO;
//Todo: sunlight/nighttime (halo and umbra)
//Todo: birds and lightning
}
//else if it's on the border
else if ((mirrored && (i *width/height > abs(j-GYM/2) - 1
&& i *width/height < abs(j-GYM/2) + 1))
||
((GXM-i) *width/height > abs(j-GYM/2) - 1 &&
(GXM-i) *width/height < abs(j-GYM) + 1))
{
//clump windows together
if ((last_window && coinflip())
|| one_chance_in(windows+1))
{
last_window = true;
grd[i][j] = DNGN_CLEAR_PERMAROCK_WALL;
}
else
{
last_window = false;
grd[i][j] = DNGN_PERMAROCK_WALL;
}
}
//else it's inside
else
{
grd[i][j] = DNGN_FLOOR;
if (j < minx)
minx = j;
else if (j > maxx)
maxx = j;
//if (i,j) is on the two rows next to the base line
// here be loot and monsters
if (i - baseline >0 && i-baseline < 3)
ret.push_back(coord_def(i,j));
}
if (i==0 || j==0 || i== GXM || j== GYM)
{
grd[i][j] = water ? DNGN_OPEN_SEA : DNGN_LAVA_SEA;
}
}
}
grd(top) = DNGN_STONE_ARCH;
grd[baseline +1][GYM/2] = DNGN_STONE_STAIRS_DOWN_I;
ASSERT(minx!=maxx);
//TODO: Portal to next zig floor
//grd[baseline +(mirrored ? 1:-1)][minx] = level == 26 ? DNGN_FLOOR : DNGN_PORTAL_ZIGGURAT;
//grd[baseline +(mirrored ? 1:-1)][maxx] = level == 26 ? DNGN_FLOOR : DNGN_?
return ret;
}
static const struct luaL_reg zig_dlib[] =
{
{"exc" , zig_exc },
{"tod" , zig_tod },
{"set_level" , zig_set_level },
{"dump" , zig_dump },
{"surrounds" , zig_surrounds },
{"floor_type", zig_floor_type },
{"monster" , zig_monster },
{"init" , zig_init },
{NULL,NULL}
};
void dluaopen_zig(lua_State *ls)
{
luaL_openlib(ls, "zig", zig_dlib, 0);
}