/*
* Date: 11/28/2005
* Time: 11:03 PM
*
* Copyright 2005, Static Boy Productions
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text.RegularExpressions;
using Jessie.Utils;
using Jessie.TTY;
namespace Jessie.GameState
{
///
/// Description of jtbvGameLevel.
///
public class jtbvGameLevel
{
public const int MAP_WIDTH = 80;
public const int MAP_HEIGHT = 21;
// include unknowns because they might be doors
// don't include unknowns because they might not be doors
//GRID_TERRAIN = (OPEN_DOOR,)
public jtbvMapSpace[,] map = new jtbvMapSpace[MAP_WIDTH, MAP_HEIGHT];
public jtbvGameLevel()
{
ResetMap();
}
public void ResetMap()
{
for (int x = 0; x < MAP_WIDTH; x++)
{
for (int y = 0; y < MAP_HEIGHT; y++)
{
map[x,y] = new jtbvMapSpace(this, x, y);
}
}
}
public jtbvMapSpace this[Point cursor]
{
get {
if ((cursor.X >= 0) && (cursor.Y >= 0) && (cursor.X < MAP_WIDTH) && (cursor.Y < MAP_HEIGHT))
return map[cursor.X, cursor.Y];
else
return null;
}
set {
map[cursor.X, cursor.Y] = value;
}
}
public jtbvMapSpace this[int x, int y]
{
get {
return map[x, y];
}
set {
map[x, y] = value;
}
}
public string GetViewStr()
{
string retVal = "";
for (int y = 0; y < MAP_HEIGHT; y++)
{
for (int x = 0; x < MAP_WIDTH; x++)
{
retVal += this[x,y].GetDrawTile();
//retVal += SearchStatus[x, y];
}
retVal += "\r\n";
}
return retVal;
}
public void UseMsgData(jtbvReceivedMessage msg, jtbvGameState gameState)
{
Point cursor = msg.CursorLoc;
jtbvLog.WriteFile("MapProcess.log", "Using message: " + msg.ToString());
cursor.Y -= 2;
for (int cnt = 0; cnt < msg.Text.Length; cnt++)
{
if ((cursor.X >= 0) && (cursor.Y >= 0) && (cursor.X < MAP_WIDTH) && (cursor.Y < MAP_HEIGHT))
{
this[cursor].UseAppearanceData(msg.Text[cnt]);
}
cursor.X++;
}
}
public void UseQueryResult(char sym, string desc)
{
// Groups[0] is the whole string
// Groups[1] is the symbol
// Groups[2] is the part inside the ()
if (InquireLocAppearance == sym.ToString())
this[InquireLoc].UseQueryResult(sym, desc);
else
jtbvLog.WriteFile("Inquiries.log", "ERROR! Query result does not match what was originally thought to be requested!");
}
///
/// This is the point that the last inquiry took place on.
///
public Point InquireLoc;
public string InquireLocAppearance;
public void RequestMoreInfo(Point cursor)
{
// TODO: Implement RequestMoreInfo()
Point tmp = cursor;
//tmp.Y += 2;
if (!this.Curiosities.Contains(tmp))
{
this.Curiosities.Add(tmp);
}
}
public System.Collections.Generic.List Curiosities = new List();
public void ResetSearched ()
{
foreach (jtbvMapSpace space in this.map)
space.SearchStatus = 0;
}
public int GetDanger(Point loc)
{
int retVal = 0;
if (this[loc] != null)
{
foreach (jtbvMapSpace curr in this[loc].AdjacentSquares)
{
retVal += curr.Danger;
}
}
else
{
Console.WriteLine("Error! Loc = " + loc.ToString());
}
jtbvLog.WriteFile("Danger.log", "The danger of the point " + loc.ToString() + " is " + retVal.ToString());
return retVal;
}
public Point GetAdjacentEnemy(Point loc)
{
Point retVal = loc;
if (this[loc] != null)
foreach (jtbvMapSpace curr in this[loc].AdjacentSquares)
{
if (curr.Danger > 0)
retVal = curr.Loc;
}
return retVal;
}
public Point GetAdjacentClosedDoor(Point loc)
{
Point retVal = loc;
if (this[loc] != null)
foreach (jtbvMapSpace curr in this[loc].AdjacentSquares)
{
if ((curr.Tile == jtbvTile.CLOSED_DOOR) ||
(curr.Tile == jtbvTile.LOCKED_DOOR))
retVal = curr.Loc;
}
return retVal;
}
public bool DownStairsKnown()
{
bool retVal = false;
if (this.FindFeature(jtbvTile.STAIRCASE_DOWN) != null)
{
jtbvLog.WriteFile("Descend.log", "Down stairs are known!");
retVal = true;
}
else
{
jtbvLog.WriteFile("Descend.log", "Down stairs are not known!");
}
return retVal;
}
public bool PointWithinBounds(Point toPoint)
{
return ((toPoint.X >= 0) && (toPoint.Y >= 0) && (toPoint.X < MAP_WIDTH) && (toPoint.Y < MAP_HEIGHT));
}
public string GoToFeature(jtbvGameState state, jtbvTile targetFeature)
{
string retVal = "";
jtbvMapSpace targetSpace = FindFeature(targetFeature);
if (targetSpace != null)
{
retVal = GoTo(state, targetSpace);
}
return retVal;
}
public jtbvMapSpace FindFeature(jtbvTile targetFeature)
{
jtbvMapSpace retVal = null;
foreach (jtbvMapSpace curr in this.map)
if (curr.Tile == targetFeature)
retVal = curr;
return retVal;
}
// **********************
// **** PATH FINDING ****
// **********************
public string GoTo(jtbvGameState state, jtbvMapSpace toPoint)
{
string retVal = "";
List path = PathFind(this[state.Player.Loc], toPoint);
if (this[state.Player.Loc] == toPoint)
{
retVal = ".";
}
else if (path != null)
{
jtbvMapSpace nextMove = path[0];
jtbvUtils.GetDirectionFromPoint(state.Player.Loc, nextMove.Loc);
}
return retVal;
}
public List PathFind(jtbvMapSpace fromPoint, jtbvMapSpace toPoint)
{
this.ResetPathCrumbs();
List currentTargets = fromPoint.AdjacentSquares;
List> Paths = new List>();
List InitialPath = new List();
InitialPath.Add(fromPoint);
Paths.Add(InitialPath);
int cnt = 0;
while (cnt < 3000) // Don't go insane on the looping -- if we get stuck, break out.
{
cnt++;
Paths.Sort(new ComparePaths()); // Sort the paths so that the shortest paths are first.
List> NextPaths = new List>();
foreach (List path in Paths)
{
jtbvMapSpace lastPoint = (jtbvMapSpace) path[0];
List tmpTargets = lastPoint.AdjacentSquares;
tmpTargets = GleanTargets(tmpTargets, lastPoint); // Remove targets that are impassible
if (tmpTargets.Count != 0)
{
foreach (jtbvMapSpace target in tmpTargets)
{
if (target.BreadCrumb == false)
{
target.BreadCrumb = true;
List tmpPath = new List(path);
tmpPath.Insert(0, target);
if (target == toPoint)
{ // Yay! We found it!
return tmpPath;
}
// If we didn't find it, we simply add this path to our list of paths to explore next time.
NextPaths.Add ( tmpPath );
}
}
}
}
Paths = NextPaths;
}
return null;
}
public jtbvMapSpace GetExploreSquare(jtbvGameState state, bool IncludeWalls)
{
jtbvMapSpace retVal = this[state.Player.Loc];
if (this.PointWithinBounds(state.Player.Loc))
{
List path = FindExplorableTarget(this[state.Player.Loc], IncludeWalls);
if (path != null)
{
jtbvMapSpace nextMove;
if (path.Count >= 2)
{
nextMove = (jtbvMapSpace) path[path.Count - 2];
}
else
{
nextMove = this[state.Player.Loc];
}
retVal = nextMove;
}
}
return retVal;
}
public List FindExplorableTarget(jtbvMapSpace fromPoint, bool IncludeWalls)
{
this.ResetPathCrumbs();
List currentTargets = fromPoint.AdjacentSquares;
List> Paths = new List>();
List InitialPath = new List();
InitialPath.Add(fromPoint);
Paths.Add(InitialPath);
int cnt = 0;
while (cnt < 3000) // Don't go insane on the looping -- if we get stuck, break out.
{
cnt++;
Paths.Sort(new ComparePaths()); // Sort the paths so that the shortest paths are first.
List> NextPaths = new List>();
foreach (List path in Paths)
{
jtbvMapSpace lastPoint = (jtbvMapSpace) path[0];
List tmpTargets = lastPoint.AdjacentSquares;
tmpTargets = GleanTargets(tmpTargets, lastPoint); // Remove targets that are impassible
if (tmpTargets.Count != 0)
{
foreach (jtbvMapSpace target in tmpTargets)
{
if (target.BreadCrumb == false)
{
target.BreadCrumb = true;
List tmpPath = new List(path);
tmpPath.Insert(0, target);
foreach (jtbvMapSpace space in target.AdjacentSquares)
{
if ((space.Tile == jtbvTile.UNEXPLORED) && (space.SearchStatus == 0))
{
// Yay! We found one!
return tmpPath;
}
else if (IncludeWalls && (space.Tile == jtbvTile.WALL) && (space.SearchStatus == 0))
{
// Yay! We found one!
return tmpPath;
}
}
NextPaths.Add ( tmpPath );
}
}
}
}
Paths = NextPaths;
}
return null;
}
private List GleanTargets(List currentTargets, jtbvMapSpace fromSquare)
{
List newTargets = new List();
for (int cnt=0; cnt < currentTargets.Count; cnt++)
{
jtbvMapSpace target = (jtbvMapSpace) currentTargets[cnt];
if ((target.IsPassable()) && (!newTargets.Contains(target)))
{
if (((target.Tile != jtbvTile.OPEN_DOOR) && (fromSquare.Tile != jtbvTile.OPEN_DOOR)
&& (target.Tile != jtbvTile.UNKNOWN) && (fromSquare.Tile != jtbvTile.UNKNOWN)
&& (target.Tile != jtbvTile.UNEXPLORED) && (fromSquare.Tile != jtbvTile.UNEXPLORED))
|| jtbvUtils.PointsAreSquared(target, fromSquare))
{
newTargets.Add(target);
}
}
}
return newTargets;
}
// Just like Hansel and Gretel left bread crumbs, so do we. This is the way the birds come and pick the crumbs up again.
private void ResetPathCrumbs()
{
foreach (jtbvMapSpace space in this.map)
{
space.BreadCrumb = false;
}
}
public static int GetTravelCost(List path)
{
int retVal = 0;
foreach (jtbvMapSpace pt in path)
{
retVal += pt.GetTravelCost();
}
return retVal;
}
public bool IsExplored (jtbvGameState state)
{
bool retVal = true;
if (this.GetExploreSquare(state, false) != state.CurrDlvl[state.Player.Loc])
retVal = false;
return retVal;
// for( int x = 0; x < MAP_WIDTH; x++)
// {
// for( int y = 0; y < MAP_HEIGHT; y++)
// {
// if (this[x, y].IsPassable())
// {
// if (this[x, y].Tile != jtbvTile.UNEXPLORED)
// {
// foreach (jtbvMapSpace target in this[x, y].AdjacentSquares/ {
// if ((target.Tile == jtbvTile.UNEXPLORED) && (target.SearchStatus == 0))
// {
// return false;
// }
// }
// }
// }
// }
// }
// return retVal;
//
// }
}
}
public class ComparePaths : IComparer>
{
public ComparePaths()
{
}
public int Compare (List first, List second)
{
List x = first as List;
List y = second as List;
if ((x != null) && (y != null))
{
// kludge way to get the level. :-\
int xCost = jtbvGameLevel.GetTravelCost(x);
int yCost = jtbvGameLevel.GetTravelCost(y);
return (xCost - yCost);
}
else
{
return 0;
}
}
}
}