www.pudn.com > Sterren_ASe_Explorer.rar > aseDoc.cpp
/* Copyright (C) William van der Sterren, 2002. * All rights reserved worldwide. * * This software is provided "as is" without express or implied * warranties. You may freely copy and compile this source into * applications you distribute provided that the copyright text * below is included in the resulting source code, for example: * "Portions Copyright (C) William van der Sterren, 2002" */ /* Copyright (C) James Matthews, 2001. * All rights reserved worldwide. * * This software is provided "as is" without express or implied * warranties. You may freely copy and compile this source into * applications you distribute provided that the copyright text * below is included in the resulting source code, for example: * "Portions Copyright (C) James Matthews, 2001" */ // aseDoc.cpp : implementation of the CAseDoc class // #include "stdafx.h" #include "ase.h" #include "nodeview.h" #include "aseDoc.h" #include "aseView.h" #include "mainfrm.h" #include#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAseDoc IMPLEMENT_DYNCREATE(CAseDoc, CDocument) BEGIN_MESSAGE_MAP(CAseDoc, CDocument) //{{AFX_MSG_MAP(CAseDoc) ON_COMMAND(ID_RUNTOBREAKPOINT, OnRunToBreakpoint) ON_UPDATE_COMMAND_UI(ID_RUNTOBREAKPOINT, OnUpdateRunToBreakpoint) ON_COMMAND(ID_EXECUTEASTAR, OnExecuteAStar) ON_COMMAND(ID_STEPASTAR, OnStepAStar) ON_COMMAND(ID_VIEW_AROUTE, OnViewARoute) ON_UPDATE_COMMAND_UI(ID_VIEW_AROUTE, OnUpdateViewARoute) ON_COMMAND(ID_PATHING_CONTINUOUSUPDATE, OnPathingContinuousUpdate) ON_UPDATE_COMMAND_UI(ID_PATHING_CONTINUOUSUPDATE, OnUpdatePathingContinuousUpdate) ON_COMMAND(ID_VIEW_SEARCHSPACE, OnViewSearchspace) ON_UPDATE_COMMAND_UI(ID_VIEW_SEARCHSPACE, OnUpdateViewSearchspace) //}}AFX_MSG_MAP ON_COMMAND_RANGE(ID_WEIGHT0, ID_ENEMYPOSITION, OnBrushType) ON_UPDATE_COMMAND_UI_RANGE(ID_WEIGHT0, ID_ENEMYPOSITION, OnUpdateUIBrushType) ON_COMMAND_RANGE(ID_PATHING_BREAKPOINTS_POINT, ID_PATHING_BREAKPOINTS_NEWCHILD, OnBreakpointType) ON_UPDATE_COMMAND_UI_RANGE(ID_PATHING_BREAKPOINTS_POINT, ID_PATHING_BREAKPOINTS_NEWCHILD, OnUpdateUIBreakpointType) ON_COMMAND(ID_VIEW_LOF, OnViewLineOfFire) ON_UPDATE_COMMAND_UI(ID_VIEW_LOF, OnUpdateUIViewLineOfFire) ON_COMMAND(ID_VIEW_THREATS, OnViewThreats) ON_UPDATE_COMMAND_UI(ID_VIEW_THREATS, OnUpdateUIViewThreats) ON_COMMAND(ID_THREATCOSTS_DISTANCETOTHREAT, OnThreatDistanceBasedCosts) ON_UPDATE_COMMAND_UI(ID_THREATCOSTS_DISTANCETOTHREAT, OnUpdateUIThreatDistanceBasedCosts) ON_COMMAND(ID_VIEW_APPROX_LOF, OnViewApproximatedLinesOfFire) ON_UPDATE_COMMAND_UI(ID_VIEW_APPROX_LOF, OnUpdateUIViewApproximatedLinesOfFire) ON_COMMAND(ID_THREATCOSTS_THREATCOUNT, OnThreatCountBasedCosts) ON_UPDATE_COMMAND_UI(ID_THREATCOSTS_THREATCOUNT, OnUpdateUIThreatCountBasedCosts) ON_COMMAND(ID_THREATCOSTS_APPROXLUT, OnThreatFromApproxTableCosts) ON_UPDATE_COMMAND_UI(ID_THREATCOSTS_APPROXLUT, OnUpdateUIThreatFromApproxTableCosts) ON_COMMAND_RANGE(ID_MOVEMENT_MANHATTAN, ID_MOVEMENT_DIAGONAL, OnMovementType) ON_UPDATE_COMMAND_UI_RANGE(ID_MOVEMENT_MANHATTAN, ID_MOVEMENT_DIAGONAL, OnUpdateUIMovementType) ON_COMMAND_RANGE(ID_MOVEMENTCOSTS_CELL, ID_MOVEMENTCOSTS_RELATIVE, OnMovementCosts) ON_UPDATE_COMMAND_UI_RANGE(ID_MOVEMENTCOSTS_CELL, ID_MOVEMENTCOSTS_RELATIVE, OnUpdateUIMovementCosts) ON_COMMAND_RANGE(ID_THREATCOSTS_NONE, ID_THREATCOSTS_LOFWITHMEMORY, OnThreatCosts) ON_UPDATE_COMMAND_UI_RANGE(ID_THREATCOSTS_NONE, ID_THREATCOSTS_LOFWITHMEMORY, OnUpdateUIThreatCosts) ON_COMMAND_RANGE(ID_THREATMOVEMENT_0, ID_THREATMOVEMENT_2, OnThreatMovement) ON_UPDATE_COMMAND_UI_RANGE(ID_THREATMOVEMENT_0, ID_THREATMOVEMENT_2, OnUpdateUIThreatMovement) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CAseDoc construction/destruction CAseDoc::CAseDoc() : m_TerrainBoard(ASE_BOARDX, ASE_BOARDY), m_ThreatBoard(ASE_BOARDX, ASE_BOARDY, &m_TerrainBoard), m_SearchSpaceBoard(ASE_BOARDX, ASE_BOARDY, &m_TerrainBoard), m_LOSApproximationBoard(ASE_BOARDX, ASE_BOARDY, &m_TerrainBoard, &m_ThreatBoard), // movement type m_bMovementDiagonal(false), // movement costs m_bMovementCostsVectorBased(false), m_bMovementCostsRelative(false), // threat costs m_bThreatCostsNone(true), m_bThreatCostsSimple(false), m_bThreatLineOfFireWithAimingCosts(false), m_bThreatCountCosts(false), m_bDistanceToThreatCosts(false), m_bThreatCostsFromApproximatedTable(false), // views m_bSearchSpace(true), m_bThreatPositions(true), m_bThreatLinesOfFire(true), m_bDrawApproximatedLinesOfFire(false), m_bDrawRoute(true) { m_bContinualUpdate = false; m_uBrushType = 0; } CAseDoc::~CAseDoc() { } BOOL CAseDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; m_TerrainBoard.Clear(); m_ThreatBoard.Clear(); m_SearchSpaceBoard.Clear(); m_cStart.x = -1; m_cEnd.x = -1; m_cBreakpoint.x = -1; m_iBreakData = -1; m_bStepped = false; m_cAStar.Reset(); m_bDrawRoute = false; return TRUE; } BOOL CAseDoc::OnOpenDocument(LPCTSTR lpszPathName) { if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; m_bStepped = false; m_cBreakpoint.x = -1; m_iBreakData = -1; m_cAStar.Reset(); m_bDrawRoute = false; m_SearchSpaceBoard.Clear(); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CAseDoc serialization void CAseDoc::Serialize(CArchive& ar) { int x = ASE_BOARDX, y = ASE_BOARDY; if (ar.IsStoring()) { ar << x; ar << y; ar << m_cStart; ar << m_cEnd; m_TerrainBoard.WriteBoard(ar); // writes threats after original board, so remain compatible m_ThreatBoard.WriteBoard(ar); } else { ar >> x; ar >> y; ar >> m_cStart; ar >> m_cEnd; m_TerrainBoard.ReadBoard(ar); // reads threats after original board, to remain compatible m_ThreatBoard.Clear(); // test whether any threat data might be included - dirty CFile* file; file = ar.GetFile(); unsigned long bytesAvailable; bytesAvailable = static_cast (file->GetLength() - file->GetPosition()); if ( bytesAvailable > 0 ) { m_ThreatBoard.ReadBoard(ar); } // disable button m_bDrawApproximatedLinesOfFire = false; m_ThreatBoard.InitializeLinesOfFire(); m_LOSApproximationBoard.Clear(); } } void CAseDoc::SetStatusBarText(const char* aText) { CMainFrame* pMfm = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd()); CStatusBar* statusbar = pMfm->GetStatusBar(); statusbar->SetPaneText(0, aText); } ///////////////////////////////////////////////////////////////////////////// // CAseDoc diagnostics #ifdef _DEBUG void CAseDoc::AssertValid() const { CDocument::AssertValid(); } void CAseDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CAseDoc commands int CAseDoc::AS_Valid(_asNode *parent, _asNode *node, int data, void *pointer) { int x = node->GetX(); int y = node->GetY(); CAseDoc *me = reinterpret_cast (pointer); if ( !me->GetTerrainBoard()->IsValidTerrainMove(parent->GetX(), parent->GetY(), x, y) ) return false; // check for invalid diagonal movement if ( !me->DoesUseDiagonalMovement() ) { int px = parent->GetX(); int py = parent->GetY(); return ( ( px == x ) || ( py == y ) ); } else return true; } void CAseDoc::NodeAdded(_asNode *node, int data) { if (m_cBreakpoint.x == -1 && m_iBreakData == -1) return; //! \todo rewrite to single expression if ( node->GetX() == m_cBreakpoint.x && node->GetY() == m_cBreakpoint.y ) { m_bBreakpointHit = true; m_pcBreakNode = node; } if (data == m_iBreakData) { m_bBreakpointHit = true; m_pcBreakNode = node; } } CNodeView *CAseDoc::GetNodeView() { POSITION pos; pos = GetFirstViewPosition(); CNodeView *nv = reinterpret_cast (GetNextView(pos)); return nv; } CAseView *CAseDoc::GetAseView() { CMainFrame* pMfm = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd()); CAseView *view = reinterpret_cast (pMfm->GetRightPane()); return view; } void CAseDoc::SelectMovementCostFunctions() { // set appropriate terrain cost function if ( DoesUseRelativeMovementCosts() ) { m_cAStar.udTerrainCost = ASE_Costs::CellBasedRelativeMovementCosts; m_cAStar.udTerrainHeuristic = ASE_Costs::CellBasedRelativeMovementHeuristic; } else if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udTerrainCost = ASE_Costs::VectorBasedNormalMovementCosts; m_cAStar.udTerrainHeuristic = ASE_Costs::VectorBasedNormalMovementHeuristic; } else // cell based { m_cAStar.udTerrainCost = ASE_Costs::CellBasedNormalMovementCosts; m_cAStar.udTerrainHeuristic = ASE_Costs::CellBasedNormalMovementHeuristic; } } void CAseDoc::SelectThreatCostFunctions() { // no prediction of remaining threat costs const char* pStatusBarText; m_cAStar.udThreatHeuristic = ASE_Costs::ThreatsAnyModeAnyMovementHeuristic; pStatusBarText = "A* search: traditional shortest path"; // select cost function as follows // - approximated lof table // - distance + count // - distance // - count // - no distance, no count // - none // and for each of these categories, distinguish aiming, vector/cell based if ( DoesUseThreatCostsFromApproxTable() ) { if ( DoesUseAimingThreatCosts() ) { if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udThreatCost = ASE_Costs::VectorBasedThreatsApproximateLOFAimingCosts; } else { m_cAStar.udThreatCost = ASE_Costs::CellBasedThreatsApproximateLOFAimingCosts; } pStatusBarText = "A* search: tactical, using costs from approximated small lookup table, taking into account aiming"; } else { if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udThreatCost = ASE_Costs::VectorBasedThreatsApproximateLOFSimpleCosts; } else { m_cAStar.udThreatCost = ASE_Costs::CellBasedThreatsApproximateLOFSimpleCosts; } pStatusBarText = "A* search: tactical, using costs from approximated small lookup table"; } } else if ( ( DoesUseDistanceToThreatCosts() ) && ( DoesUseThreatCountCosts() ) ) { if ( DoesUseAimingThreatCosts() ) { if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udThreatCost = ASE_Costs::VectorBasedDistanceAndCountBasedAimingCosts; } else { m_cAStar.udThreatCost = ASE_Costs::CellBasedDistanceAndCountBasedAimingCosts; } pStatusBarText = "A* search: tactical, using exact distance and threat count costs, taking into account aiming"; } else { if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udThreatCost = ASE_Costs::VectorBasedDistanceAndCountBasedSimpleCosts; } else { m_cAStar.udThreatCost = ASE_Costs::CellBasedDistanceAndCountBasedSimpleCosts; } pStatusBarText = "A* search: tactical, using exact distance and threat count costs"; } } else if ( DoesUseDistanceToThreatCosts() ) { if ( DoesUseAimingThreatCosts() ) { if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udThreatCost = ASE_Costs::VectorBasedDistanceBasedAimingCosts; } else { m_cAStar.udThreatCost = ASE_Costs::CellBasedDistanceBasedAimingCosts; } pStatusBarText = "A* search: tactical, using exact distance to threat costs, taking into account aiming"; } else { if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udThreatCost = ASE_Costs::VectorBasedDistanceBasedSimpleCosts; } else { m_cAStar.udThreatCost = ASE_Costs::CellBasedDistanceBasedSimpleCosts; } pStatusBarText = "A* search: tactical, using exact distance to threat costs"; } } else if ( DoesUseThreatCountCosts() ) { if ( DoesUseAimingThreatCosts() ) { if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udThreatCost = ASE_Costs::VectorBasedCountBasedAimingCosts; } else { m_cAStar.udThreatCost = ASE_Costs::CellBasedCountBasedAimingCosts; } pStatusBarText = "A* search: tactical, using exact threat count costs, taking into account aiming"; } else { if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udThreatCost = ASE_Costs::VectorBasedCountBasedSimpleCosts; } else { m_cAStar.udThreatCost = ASE_Costs::CellBasedCountBasedSimpleCosts; } pStatusBarText = "A* search: tactical, using exact threat count costs"; } } else if ( DoesUseThreatCosts() ) { if ( DoesUseAimingThreatCosts() ) { if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udThreatCost = ASE_Costs::VectorBasedThreatsAimingCosts; } else { m_cAStar.udThreatCost = ASE_Costs::CellBasedThreatsAimingCosts; } pStatusBarText = "A* search: tactical, using exact simple threat line-of-fire costs, taking into account aiming"; } else { if ( DoesUseVectorBasedMovementCosts() ) { m_cAStar.udThreatCost = ASE_Costs::VectorBasedThreatsSimpleCosts; } else { m_cAStar.udThreatCost = ASE_Costs::CellBasedThreatsSimpleCosts; } pStatusBarText = "A* search: tactical, using exact simple threat line-of-fire costs"; } } else { m_cAStar.udThreatCost = ASE_Costs::ThreatsNoCosts; } SetStatusBarText(pStatusBarText); } bool CAseDoc::SetupAStar(bool stepped/* = false*/) { if (m_cStart.x == -1 || m_cEnd.x == -1) { MessageBox("Please ensure that both the start and end points are specified.\nA red and green square denote the start and end points, respectively.", "A* Explorer", MB_ICONERROR); return false; } CNodeView *nv = GetNodeView(); GetAseView()->RemoveHighlight(); assert( m_TerrainBoard.GetNumberOfRows() == ASE_BOARDX ); m_cAStar.SetRows(ASE_BOARDX); m_cAStar.udValid = AS_Valid; ASE_Costs::SetTerrainBoard(GetTerrainBoard()); ASE_Costs::SetThreatBoard(GetThreatBoard()); ASE_Costs::SetLOFApproximationBoard(GetLOSApproximationBoard()); SelectMovementCostFunctions(); SelectThreatCostFunctions(); if ( m_bThreatCostsFromApproximatedTable ) { GetLOSApproximationBoard()->ComputeLinesOfFireApproximation(); } m_cAStar.udNotifyList = CNodeView::OnUpdateList; m_cAStar.udNotifyChild = (m_bContinualUpdate) ? NULL : CNodeView::OnNotifyChild; m_cAStar.m_pCBData = reinterpret_cast (this); m_cAStar.m_pNCData = reinterpret_cast (nv); nv->OnPreAStar(); m_SearchSpaceBoard.Clear(); if (stepped) { CTreeCtrl &tree = GetNodeView()->GetTreeCtrl(); tree.InsertItem("A* Tree", 6, 6); tree.InsertItem("Open List", 7, 7); tree.InsertItem("Closed List", 8, 8); m_cAStar.udNotifyList = CNodeView::OnNotifyList; m_cAStar.StepInitialize(m_cStart.x, m_cStart.y, m_cEnd.x, m_cEnd.y); } return true; } void CAseDoc::DrawNode(_asNode *node) { GetAseView()->HighlightNode(node, true); } void CAseDoc::MessageBox(CString title, CString caption, UINT type) { AfxGetMainWnd()->MessageBox(title, caption, type); } void CAseDoc::OnBreakpointType(UINT uType) { int type = uType - ID_PATHING_BREAKPOINTS_POINT; if (type == 0) { m_cBreakpoint.x = -1; UpdateAllViews(NULL); } m_iBreakData = (type == 0) ? -1 : type; } void CAseDoc::OnUpdateUIBreakpointType(CCmdUI *pCmdUI) { UINT uID = pCmdUI->m_nID; if (uID == ID_PATHING_BREAKPOINTS_POINT) { pCmdUI->Enable((m_cBreakpoint.x != -1)); pCmdUI->SetCheck((m_cBreakpoint.x != -1)); return; } pCmdUI->SetCheck(uID == unsigned(m_iBreakData + ID_PATHING_BREAKPOINTS_POINT)); } void CAseDoc::OnRunToBreakpoint() { if (!m_bStepped) { if (!SetupAStar(true)) return; m_bDrawRoute = false; m_bStepped = true; m_bBreakpointHit = (m_cBreakpoint == m_cStart) ? true : false; } else { m_bBreakpointHit = false; } int retval = 1; while (!m_bBreakpointHit) { retval = m_cAStar.Step(); GetNodeView()->SortOpen(); if (retval == -1) { m_bStepped= false; MessageBox("A path could not be found.", "A* Explorer", MB_ICONERROR); break; } else if (retval == 1) { m_bDrawRoute = true; m_bStepped = false; GetNodeView()->OnPostAStar(m_cAStar.GetBestNode()); UpdateAllViews(NULL); MessageBox("Stepping complete. A path has been found.", "A* Explorer", MB_ICONINFORMATION); break; } } if (m_bBreakpointHit) { CString str; if (m_iBreakData == -1) { str.Format("Breakpoint at (%d,%d) hit.", m_cBreakpoint.x, m_cBreakpoint.y); } else { str = "The conditional breakpoint has been satisfied in this iteration."; } MessageBox(str, "A* Explorer", MB_ICONSTOP); CTreeCtrl &tree = GetNodeView()->GetTreeCtrl(); tree.EnsureVisible(HTREEITEM(m_pcBreakNode->dataptr)); tree.SelectItem(HTREEITEM(m_pcBreakNode->dataptr)); tree.Invalidate(); } } void CAseDoc::OnUpdateRunToBreakpoint(CCmdUI* pCmdUI) { pCmdUI->Enable((m_iBreakData != -1 || m_cBreakpoint.x != -1)); } void CAseDoc::OnExecuteAStar() { if (m_bStepped) { int retval; while (true) { retval = m_cAStar.Step(); if (retval == -1) { m_bStepped= false; GetNodeView()->SortOpen(); MessageBox("A path could not be found.", "A* Explorer", MB_ICONERROR); break; } else if (retval == 1) { m_bDrawRoute = true; m_bStepped = false; GetNodeView()->OnPostAStar(m_cAStar.GetBestNode()); UpdateAllViews(NULL); GetNodeView()->SortOpen(); MessageBox("Stepping complete. A path has been found.", "A* Explorer", MB_ICONINFORMATION); break; } } return; } if (!SetupAStar()) return; if (m_cAStar.GeneratePath(m_cStart.x, m_cStart.y, m_cEnd.x, m_cEnd.y)) { m_bDrawRoute = true; GetNodeView()->OnPostAStar(m_cAStar.GetBestNode()); } else { m_bDrawRoute = false; MessageBox("A path could not be found.", "A* Explorer", MB_ICONERROR); } UpdateAllViews(NULL); } void CAseDoc::OnStepAStar() { if (!m_bStepped) { if (!SetupAStar(true)) return; m_bStepped = true; m_bDrawRoute = false; GetNodeView()->RedrawWindow(); } else { int retval = m_cAStar.Step(); GetNodeView()->SortOpen(); if (retval == -1) { m_bDrawRoute = false; m_bStepped = false; MessageBox("A path could not be found.", "A* Explorer", MB_ICONERROR); } else if (retval == 1) { m_bDrawRoute = true; m_bStepped = false; GetNodeView()->OnPostAStar(m_cAStar.GetBestNode()); MessageBox("Stepping complete. A path has been found.", "A* Explorer", MB_ICONINFORMATION); } UpdateAllViews(NULL); } } void CAseDoc::OnMovementType(UINT uType) { m_bMovementDiagonal = ( uType == ID_MOVEMENT_DIAGONAL ); } void CAseDoc::OnUpdateUIMovementType(CCmdUI* pCmdUI) { UINT uType = pCmdUI->m_nID; pCmdUI->SetCheck( ( ( uType == ID_MOVEMENT_MANHATTAN ) && ( !m_bMovementDiagonal ) ) || ( ( uType == ID_MOVEMENT_DIAGONAL ) && ( m_bMovementDiagonal ) ) ); } void CAseDoc::OnMovementCosts(UINT uCosts) { m_bMovementCostsVectorBased = ( uCosts == ID_MOVEMENTCOSTS_VECTOR ); m_bMovementCostsRelative = ( uCosts == ID_MOVEMENTCOSTS_RELATIVE ); } void CAseDoc::OnUpdateUIMovementCosts(CCmdUI* pCmdUI) { UINT uCosts = pCmdUI->m_nID; pCmdUI->SetCheck( ( ( uCosts == ID_MOVEMENTCOSTS_VECTOR ) && ( m_bMovementCostsVectorBased ) && ( !m_bMovementCostsRelative ) ) || ( ( uCosts == ID_MOVEMENTCOSTS_CELL ) && ( !m_bMovementCostsVectorBased ) && ( !m_bMovementCostsRelative ) ) || ( ( uCosts == ID_MOVEMENTCOSTS_RELATIVE ) && ( m_bMovementCostsRelative ) ) ); } void CAseDoc::OnBrushType(UINT uType) { m_uBrushType = uType - ID_WEIGHT0; GetAseView()->SetBrushType(m_uBrushType); } void CAseDoc::OnUpdateUIBrushType(CCmdUI *pCmdUI) { UINT uType = pCmdUI->m_nID; pCmdUI->SetCheck((m_uBrushType == uType - ID_WEIGHT0)); } void CAseDoc::OnViewARoute() { m_bDrawRoute = !m_bDrawRoute; UpdateAllViews(NULL); } void CAseDoc::OnUpdateViewARoute(CCmdUI* pCmdUI) { pCmdUI->Enable((m_cAStar.GetBestNode() != NULL)); pCmdUI->SetCheck(m_bDrawRoute); } void CAseDoc::OnPathingContinuousUpdate() { m_bContinualUpdate = !m_bContinualUpdate; } void CAseDoc::OnUpdatePathingContinuousUpdate(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_bContinualUpdate); } void CAseDoc::NotifyClick() { if (m_bContinualUpdate && m_cStart.x != -1 && m_cEnd.x != -1) { m_bStepped = false; OnExecuteAStar(); } } void CAseDoc::ListChanges(_asNode *pNode, UINT uChange) { if ( uChange == 1 ) { m_SearchSpaceBoard.MarkAsOpen(pNode->GetX(), pNode->GetY()); } else { assert( uChange == 2 ); m_SearchSpaceBoard.MarkAsClosed(pNode->GetX(), pNode->GetY()); } } void CAseDoc::OnViewSearchspace() { m_bSearchSpace = !m_bSearchSpace; UpdateAllViews(NULL); } void CAseDoc::OnUpdateViewSearchspace(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_bSearchSpace); } void CAseDoc::OnViewLineOfFire() { m_bThreatLinesOfFire = !m_bThreatLinesOfFire; UpdateAllViews(NULL); } void CAseDoc::OnUpdateUIViewLineOfFire(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_bThreatLinesOfFire); } void CAseDoc::OnThreatDistanceBasedCosts() { m_bDistanceToThreatCosts = !m_bDistanceToThreatCosts; SetThreatCostsMode(); m_ThreatBoard.ComputeLinesOfFire(); UpdateAllViews(NULL); } void CAseDoc::OnUpdateUIThreatDistanceBasedCosts(CCmdUI* pCmdUI) { if ( ( m_bThreatCostsFromApproximatedTable ) || ( m_bThreatCostsNone ) ) pCmdUI->Enable(false); else { pCmdUI->Enable(); pCmdUI->SetCheck(m_bDistanceToThreatCosts); } } void CAseDoc::OnThreatCountBasedCosts() { m_bThreatCountCosts = !m_bThreatCountCosts; SetThreatCostsMode(); m_ThreatBoard.ComputeLinesOfFire(); UpdateAllViews(NULL); } void CAseDoc::OnUpdateUIThreatCountBasedCosts(CCmdUI* pCmdUI) { if ( ( m_bThreatCostsFromApproximatedTable ) || ( m_bThreatCostsNone ) ) pCmdUI->Enable(false); else { pCmdUI->Enable(); pCmdUI->SetCheck(m_bThreatCountCosts); } } void CAseDoc::OnThreatFromApproxTableCosts() { m_bThreatCostsFromApproximatedTable = !m_bThreatCostsFromApproximatedTable; if ( m_bThreatCostsFromApproximatedTable ) { m_bThreatCostsNone = false; if ( ( ! m_bThreatCostsSimple ) && ( ! m_bThreatLineOfFireWithAimingCosts ) ) { m_bThreatCostsSimple = true; } } SetThreatCostsMode(); UpdateAllViews(NULL); } void CAseDoc::OnUpdateUIThreatFromApproxTableCosts(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_bThreatCostsFromApproximatedTable); } void CAseDoc::OnViewThreats() { m_bThreatPositions = !m_bThreatPositions; UpdateAllViews(NULL); } void CAseDoc::OnUpdateUIViewThreats(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_bThreatPositions); } void CAseDoc::OnViewApproximatedLinesOfFire() { m_bDrawApproximatedLinesOfFire = !m_bDrawApproximatedLinesOfFire; if ( m_bDrawApproximatedLinesOfFire ) { GetAseView()->DisplayWaitCursor(); GetLOSApproximationBoard()->ComputeLinesOfFireApproximation(); GetAseView()->DisplayDefaultCursor(); } UpdateAllViews(NULL); } void CAseDoc::OnUpdateUIViewApproximatedLinesOfFire(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_bDrawApproximatedLinesOfFire); } void CAseDoc::OnThreatCosts(UINT uCosts) { m_bThreatCostsSimple = ( uCosts == ID_THREATCOSTS_LINEOFFIRE ); m_bThreatLineOfFireWithAimingCosts = ( uCosts == ID_THREATCOSTS_LOFWITHMEMORY ); m_bThreatCostsNone = ( uCosts == ID_THREATCOSTS_NONE ); if ( m_bThreatCostsNone ) { m_bThreatCostsFromApproximatedTable = false; } } void CAseDoc::OnUpdateUIThreatCosts(CCmdUI* pCmdUI) { UINT uCosts = pCmdUI->m_nID; pCmdUI->SetCheck( ( ( uCosts == ID_THREATCOSTS_NONE ) && ( m_bThreatCostsNone ) ) || ( ( uCosts == ID_THREATCOSTS_LINEOFFIRE ) && ( m_bThreatCostsSimple ) ) || ( ( uCosts == ID_THREATCOSTS_LOFWITHMEMORY ) && ( m_bThreatLineOfFireWithAimingCosts ) ) ); } void CAseDoc::OnThreatMovement(UINT uCosts) { unsigned int distance; distance = uCosts - ID_THREATMOVEMENT_0; assert( distance < 3 ); m_ThreatBoard.SetAssumedThreatMovement(distance); m_ThreatBoard.ComputeLinesOfFire(); UpdateAllViews(NULL); } void CAseDoc::OnUpdateUIThreatMovement(CCmdUI* pCmdUI) { UINT uID = pCmdUI->m_nID; pCmdUI->SetCheck( ( ( uID == ID_THREATMOVEMENT_0 ) && ( 0 == m_ThreatBoard.GetAssumedThreatMovement() ) ) || ( ( uID == ID_THREATMOVEMENT_1 ) && ( 1 == m_ThreatBoard.GetAssumedThreatMovement() ) ) || ( ( uID == ID_THREATMOVEMENT_2 ) && ( 2 == m_ThreatBoard.GetAssumedThreatMovement() ) ) ); // disable when using lookup table pCmdUI->Enable(!m_bThreatCostsFromApproximatedTable); } void CAseDoc::SetThreatCostsMode() { if ( m_bThreatCountCosts && m_bDistanceToThreatCosts ) { m_ThreatBoard.SetRiskModus(ASE_ThreatBoard::eMinLineOfFireCountAndDistance); } else if ( m_bThreatCountCosts ) { m_ThreatBoard.SetRiskModus(ASE_ThreatBoard::eMinLineOfFireCount); } else if ( m_bDistanceToThreatCosts ) { m_ThreatBoard.SetRiskModus(ASE_ThreatBoard::eMinLineOfFireDistance); } else { m_ThreatBoard.SetRiskModus(ASE_ThreatBoard::eAnyLineOfFire); } }