private void MainForm_KeyDown ( object sender, KeyEventArgs e )

{

if ( heroesDead )

return ; // no doing stuff when you're dead!

if ( heroBeingPlaced >= 0 )

{

if ( e . KeyCode == Keys . F )

{

heroBeingPlaced = - 1 ; // cancel

Log . Append ( "Never mind, then." ) ;

}

else

{

// place the hero

var pos = AbsolutePosition . FromKey ( e . KeyCode ) ;

if ( pos == null )

Log . Append ( "Use the numeric keypad to place the " + map . Heroes . CreaturePositions . Values . ElementAt ( heroBeingPlaced ) . Name + " or press F to cancel." ) ;

else

{

if ( newHeroPositions . Keys . Contains ( pos ) )

Log . Append ( "The " + newHeroPositions [ pos ] . Name + " is already in the " + pos . Name + ". Try again or press F to cancel." ) ;

else

{

// set placement

newHeroPositions [ pos ] = map . Heroes . CreaturePositions . Values . ElementAt ( heroBeingPlaced ) ;

// move on to next hero, or be done if last hero was placed

heroBeingPlaced ++;

if ( heroBeingPlaced >= map . Heroes . CreaturePositions . Values . Count )

{

map . Heroes . CreaturePositions . Clear ( ) ;

foreach ( var kvp in newHeroPositions )

map . Heroes . CreaturePositions . Add ( kvp . Key . RelativeTo ( map . Heroes . Facing ) , kvp . Value ) ;

heroBeingPlaced = - 1 ;

Log . Append ( "The heroes rearrange their formation." ) ;

map . Heroes . Act ( map . Tiles [ map . HeroX , map . HeroY ] . Terrain . MovementCost ) ;

map . LetMonstersAct ( ) ;

}

else

Log . Append ( "Please choose a position for the " + map . Heroes . CreaturePositions . Values . ElementAt ( heroBeingPlaced ) . Name + "." ) ;

}

}

}

}

else if ( mode == 's' )

{

if ( heroDoingStuff != null )

{

if ( e . KeyCode == Keys . S )

{

// cancel

mode = ' ' ;

heroDoingStuff = null ;

Log . Append ( "Never mind, then." ) ;

}

else

{

// pick skill

var skillIdx = GetNumberFromKey ( e . KeyCode ) - 1 ;

var skillToUse = heroDoingStuff . Skills . ElementAtOrDefault ( skillIdx ) ;

if ( skillToUse == null )

{

// prompt for skill to use

Log . Append ( "What skill will the " + heroDoingStuff . Name + " use? (press S again to cancel)" ) ;

int skillNum = 0 ;

foreach ( var skill in heroDoingStuff . Skills )

{

skillNum ++;

Log . Append ( skillNum + ": " + skill . Name + " (" + skill . ManaCost + " mana) - " + skill . Description ) ;

}

}

else if ( skillToUse . ManaCost > heroDoingStuff . Mana )

{

// not enough mana, cancel

Log . Append ( "The " + heroDoingStuff . Name + " lacks the mana for " + skillToUse . Name + "!" ) ;

mode = ' ' ;

heroDoingStuff = null ;

Log . Append ( "Never mind, then." ) ;

}

else

{

// use skill

Log . Append ( "The " + heroDoingStuff . Name + " " + skillToUse . Verb + " " + skillToUse . Name + "!" ) ;

int x = map . HeroX + map . Heroes . Facing . DeltaX ;

int y = map . HeroY + map . Heroes . Facing . DeltaY ;

Tile target = null ;

if ( map . CoordsInBounds ( x, y ) )

target = map . Tiles [ x, y ] ;

skillToUse . Use ( heroDoingStuff, map . Heroes , target, map ) ;

// spend mana

heroDoingStuff . Mana -= skillToUse . ManaCost ;

// use time

map . Heroes . Act ( map . Tiles [ map . HeroX , map . HeroY ] . Terrain . MovementCost ) ;

map . LetMonstersAct ( ) ;

// done using skill

mode = ' ' ;

heroDoingStuff = null ;

}

}

}

else

{

if ( e . KeyCode == Keys . S )

{

// cancel

mode = ' ' ;

heroDoingStuff = null ;

Log . Append ( "Never mind, then." ) ;

}

else

{

// pick hero

var heroIdx = GetNumberFromKey ( e . KeyCode ) - 1 ;

heroDoingStuff = map . Heroes . CreaturePositions . Values . ElementAtOrDefault ( heroIdx ) ;

if ( heroDoingStuff == null )

{

// didn't pick a hero

Log . Append ( "Who will use a skill? (press S again to cancel)" ) ;

int heroNum = 0 ;

foreach ( var hero in map . Heroes . CreaturePositions . Values )

{

heroNum ++;

Log . Append ( heroNum + ": " + hero . Name , hero . Color ) ;

}

}

else

{

// prompt for skill to use

Log . Append ( "What skill will the " + heroDoingStuff . Name + " use? (press S again to cancel)" ) ;

int skillNum = 0 ;

foreach ( var skill in heroDoingStuff . Skills )

{

skillNum ++;

Log . Append ( skillNum + ": " + skill . Name + " (" + skill . ManaCost + " mana) - " + skill . Description ) ;

}

}

}

}

}

else if ( mode == 'w' )

{

if ( heroDoingStuff != null )

{

if ( e . KeyCode == Keys . W )

{

// cancel

mode = ' ' ;

heroDoingStuff = null ;

Log . Append ( "Never mind, then." ) ;

}

else

{

// pick weapon

var idx = GetNumberFromKey ( e . KeyCode ) - 1 ;

var available = Weapon . All . Where ( w => w . Hero == heroDoingStuff && w . HasBeenFound ) ;

var weapon = available . ElementAtOrDefault ( idx ) ;

if ( weapon == null )

{

if ( ! available . Any ( ) )

{

// nothing to equip

Log . Append ( "The " + heroDoingStuff . Name + " doesn't have any weapons to equip!" ) ;

mode = ' ' ;

heroDoingStuff = null ;

}

else

{

// prompt for weapon to equip

Log . Append ( "What weapon will the " + heroDoingStuff . Name + " equip? (press W again to cancel)" ) ;

int num = 0 ;

foreach ( var w in available )

{

num ++;

Log . Append ( num + ": " + w . Name + " (" + w . Description + ")" ) ;

}

}

}

else

{

if ( heroDoingStuff . Weapon == weapon )

{

// nothing to do

Log . Append ( "But the " + heroDoingStuff . Name + " has already equipped the " + weapon . Name + "!" ) ; mode = ' ' ;

heroDoingStuff = null ;

}

else

{

// equip weapon

Log . Append ( "The " + heroDoingStuff . Name + " equips the " + weapon . Name + "." ) ;

heroDoingStuff . Weapon = weapon ;

// use time

map . Heroes . Act ( map . Tiles [ map . HeroX , map . HeroY ] . Terrain . MovementCost ) ;

map . LetMonstersAct ( ) ;

// done equipping

mode = ' ' ;

heroDoingStuff = null ;

}

}

}

}

else

{

if ( e . KeyCode == Keys . W )

{

// cancel

mode = ' ' ;

heroDoingStuff = null ;

Log . Append ( "Never mind, then." ) ;

}

else

{

// pick hero

var heroIdx = GetNumberFromKey ( e . KeyCode ) - 1 ;

heroDoingStuff = map . Heroes . CreaturePositions . Values . ElementAtOrDefault ( heroIdx ) ;

if ( heroDoingStuff == null )

{

// didn't pick a hero

Log . Append ( "Who will equip a weapon? (press W again to cancel)" ) ;

int heroNum = 0 ;

foreach ( var hero in map . Heroes . CreaturePositions . Values )

{

heroNum ++;

Log . Append ( heroNum + ": " + hero . Name , hero . Color ) ;

}

}

else

{

var available = Weapon . All . Where ( w => w . Hero == heroDoingStuff && w . HasBeenFound ) ;

if ( ! available . Any ( ) )

{

// nothing to equip

Log . Append ( "The " + heroDoingStuff . Name + " doesn't have any weapons to equip!" ) ;

mode = ' ' ;

heroDoingStuff = null ;

}

else

{

// prompt for weapon to equip

Log . Append ( "What weapon will the " + heroDoingStuff . Name + " equip? (press W again to cancel)" ) ;

int num = 0 ;

foreach ( var w in available )

{

num ++;

Log . Append ( num + ": " + w . Name + " (" + w . Description + ")" ) ;

}

}

}

}

}

}

else if ( mode == 'a' )

{

if ( heroDoingStuff != null )

{

if ( e . KeyCode == Keys . A )

{

// cancel

mode = ' ' ;

heroDoingStuff = null ;

Log . Append ( "Never mind, then." ) ;

}

else

{

// pick armor

var idx = GetNumberFromKey ( e . KeyCode ) - 1 ;

var available = Armor . All . Where ( a => a . Hero == heroDoingStuff && a . HasBeenFound ) ;

var armor = available . ElementAtOrDefault ( idx ) ;

if ( armor == null )

{

if ( ! available . Any ( ) )

{

// nothing to equip

Log . Append ( "The " + heroDoingStuff . Name + " doesn't have any armor to equip!" ) ;

mode = ' ' ;

heroDoingStuff = null ;

}

else

{

// prompt for armor to equip

Log . Append ( "What armor will the " + heroDoingStuff . Name + " equip? (press A again to cancel)" ) ;

int num = 0 ;

foreach ( var a in available )

{

num ++;

Log . Append ( num + ": " + a . Name + " (" + a . Description + ")" ) ;

}

}

}

else

{

if ( heroDoingStuff . Armor == armor )

{

// nothing to do

Log . Append ( "But the " + heroDoingStuff . Name + " has already equipped the " + armor . Name + "!" ) ;

mode = ' ' ;

heroDoingStuff = null ;

}

else

{

// equip armor

Log . Append ( "The " + heroDoingStuff . Name + " equips the " + armor . Name + "." ) ;

heroDoingStuff . Armor = armor ;

// use time

map . Heroes . Act ( map . Tiles [ map . HeroX , map . HeroY ] . Terrain . MovementCost ) ;

map . LetMonstersAct ( ) ;

// done equipping

mode = ' ' ;

heroDoingStuff = null ;

}

}

}

}

else

{

if ( e . KeyCode == Keys . A )

{

// cancel

mode = ' ' ;

heroDoingStuff = null ;

Log . Append ( "Never mind, then." ) ;

}

else

{

// pick hero

var heroIdx = GetNumberFromKey ( e . KeyCode ) - 1 ;

heroDoingStuff = map . Heroes . CreaturePositions . Values . ElementAtOrDefault ( heroIdx ) ;

if ( heroDoingStuff == null )

{

// didn't pick a hero

Log . Append ( "Who will equip armor? (press A again to cancel)" ) ;

int heroNum = 0 ;

foreach ( var hero in map . Heroes . CreaturePositions . Values )

{

heroNum ++;

Log . Append ( heroNum + ": " + hero . Name , hero . Color ) ;

}

}

else

{

var available = Armor . All . Where ( a => a . Hero == heroDoingStuff && a . HasBeenFound ) ;

if ( ! available . Any ( ) )

{

// nothing to equip

Log . Append ( "The " + heroDoingStuff . Name + " doesn't have any armor to equip!" ) ;

mode = ' ' ;

heroDoingStuff = null ;

}

else

{

// prompt for armor to equip

Log . Append ( "What armor will the " + heroDoingStuff . Name + " equip? (press A again to cancel)" ) ;

int num = 0 ;

foreach ( var a in available )

{

num ++;

Log . Append ( num + ": " + a . Name + " (" + a . Description + ")" ) ;

}

}

}

}

}

}

else

{

if ( e . KeyCode == Keys . F )

{

// F: set formation

heroBeingPlaced = 0 ;

newHeroPositions = new Dictionary < AbsolutePosition, Creature > ( ) ;

Log . Append ( "Please choose a position for the " + map . Heroes . CreaturePositions . Values . ElementAt ( heroBeingPlaced ) . Name + "." ) ;

}

else if ( e . KeyCode == Keys . S )

{

// S: use skill

mode = 's' ;

Log . Append ( "Who will use a skill? (press S again to cancel)" ) ;

int heroNum = 0 ;

foreach ( var hero in map . Heroes . CreaturePositions . Values )

{

heroNum ++;

Log . Append ( heroNum + ": " + hero . Name , hero . Color ) ;

}

}

else if ( e . KeyCode == Keys . W )

{

// W: change weapon

mode = 'w' ;

Log . Append ( "Who will change his weapon? (press W again to cancel)" ) ;

int heroNum = 0 ;

foreach ( var hero in map . Heroes . CreaturePositions . Values )

{

heroNum ++;

Log . Append ( heroNum + ": " + hero . Name , hero . Color ) ;

}

}

else if ( e . KeyCode == Keys . A )

{

// W: change weapon

mode = 'a' ;

Log . Append ( "Who will change his armor? (press A again to cancel)" ) ;

int heroNum = 0 ;

foreach ( var hero in map . Heroes . CreaturePositions . Values )

{

heroNum ++;

Log . Append ( heroNum + ": " + hero . Name , hero . Color ) ;

}

}

else if ( e . KeyCode == Keys . D5 || e . KeyCode == Keys . NumPad5 || e . KeyCode == Keys . Clear )

{

// wait a turn

map . Heroes . Act ( map . Tiles [ map . HeroX , map . HeroY ] . Terrain . MovementCost ) ;

map . LetMonstersAct ( ) ;

}

else

{

var dir = Direction . FromKey ( e . KeyCode ) ;

if ( dir != null )

{

// movement

if ( ModifierKeys . HasFlag ( Keys . Shift ) )

{

// shift-arrow moves without rotating (strafe move)

map . Move ( map . Heroes , dir ) ;

}

else

{

// just plain arrow attempts to rotate instead of move if not facing direction of movement

map . MoveOrTurn ( map . Heroes , dir ) ;

}

map . LetMonstersAct ( ) ;

if ( ! map . CoordsInBounds ( map . HeroX , map . HeroY ) )

{

heroesDead = true ;

Log . Append ( "Oh no! The heroes have fallen..." , Color . Red ) ;

}

}

}

}

// see if final boss is dead

if ( ! winner && ! map . Tiles . Cast < Tile > ( ) . Any ( t => t . Formation != null && t . Formation . CreaturePositions . Values . Any ( c => c . Name == MonsterTemplate . ChaosLord . Archetype . Name ) ) )

{

Log . Append ( "Congratulations! The Chaos Lord has been vanquished! The brave heroes can now retire to a life of fame... or they can continue slaying the foul minions that still plague the land!" , Color . Magenta ) ;

winner = true ;

Text = "TriQuest - *WINNER*" ;

}

// see if all monsters are dead

if ( map . Tiles . Cast < Tile > ( ) . All ( t => t . Formation == null || t . Formation == map . Heroes ) )

{

Log . Append ( "Wow! You're really dedicated! You actually managed to slay every last monster! Double congratulations!!! Now go take a well-deserved rest!" , Color . Magenta ) ;

omnicide = true ;

Text = "TriQuest - +*OMNICIDE*+" ;

}

// refresh screen

picMap . Invalidate ( ) ;

picMinimap . Invalidate ( ) ;

BindStatsBoxes ( map . Heroes ) ;

RefreshLog ( ) ;

}

private int GetNumberFromKey ( Keys key )

{

if ( key == Keys . D0 || key == Keys . NumPad0 )

return 0 ;

else if ( key == Keys . D1 || key == Keys . NumPad1 )

return 1 ;

else if ( key == Keys . D2 || key == Keys . NumPad2 )

return 2 ;

else if ( key == Keys . D3 || key == Keys . NumPad3 )

return 3 ;

else if ( key == Keys . D4 || key == Keys . NumPad4 )

return 4 ;

else if ( key == Keys . D5 || key == Keys . NumPad5 )

return 5 ;

else if ( key == Keys . D6 || key == Keys . NumPad6 )

return 6 ;

else if ( key == Keys . D7 || key == Keys . NumPad7 )

return 7 ;

else if ( key == Keys . D8 || key == Keys . NumPad8 )

return 8 ;

else if ( key == Keys . D9 || key == Keys . NumPad9 )

return 9 ;

return - 1 ; // not a number key