home *** CD-ROM | disk | FTP | other *** search
/ AI Game Programming Wisdom / AIGameProgrammingWisdom.iso / SourceCode / 03 Pathfinding with Astar / 01 Matthews / ase / aseDoc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-07-06  |  11.0 KB  |  475 lines

  1. // aseDoc.cpp : implementation of the CAseDoc class
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "ase.h"
  6.  
  7. #include "nodeview.h"
  8.  
  9. #include "aseDoc.h"
  10. #include "aseView.h"
  11. #include "mainfrm.h"
  12.  
  13. #ifdef _DEBUG
  14. #define new DEBUG_NEW
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18.  
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CAseDoc
  21.  
  22. IMPLEMENT_DYNCREATE(CAseDoc, CDocument)
  23.  
  24. BEGIN_MESSAGE_MAP(CAseDoc, CDocument)
  25.     //{{AFX_MSG_MAP(CAseDoc)
  26.     ON_COMMAND(ID_RUNTOBREAKPOINT, OnRunToBreakpoint)
  27.     ON_UPDATE_COMMAND_UI(ID_RUNTOBREAKPOINT, OnUpdateRunToBreakpoint)
  28.     ON_COMMAND(ID_EXECUTEASTAR, OnExecuteAStar)
  29.     ON_COMMAND(ID_STEPASTAR, OnStepAStar)
  30.     ON_COMMAND(ID_PATHING_ALLOWDIAGONAL, OnPathingAllowDiagonal)
  31.     ON_UPDATE_COMMAND_UI(ID_PATHING_ALLOWDIAGONAL, OnUpdatePathingAllowDiagonal)
  32.     ON_COMMAND(ID_VIEW_AROUTE, OnViewARoute)
  33.     ON_UPDATE_COMMAND_UI(ID_VIEW_AROUTE, OnUpdateViewARoute)
  34.     ON_COMMAND(ID_PATHING_CONTINUOUSUPDATE, OnPathingContinuousUpdate)
  35.     ON_UPDATE_COMMAND_UI(ID_PATHING_CONTINUOUSUPDATE, OnUpdatePathingContinuousUpdate)
  36.     ON_COMMAND(ID_PATHING_RELATIVECOSTING, OnPathingRelativeCosting)
  37.     ON_UPDATE_COMMAND_UI(ID_PATHING_RELATIVECOSTING, OnUpdatePathingRelativeCosting)
  38.     //}}AFX_MSG_MAP
  39.     ON_COMMAND_RANGE(ID_WEIGHT0, ID_ENDPOINT, OnBrushType)    
  40.     ON_UPDATE_COMMAND_UI_RANGE(ID_WEIGHT0, ID_ENDPOINT, OnUpdateUIBrushType)    
  41.     ON_COMMAND_RANGE(ID_PATHING_BREAKPOINTS_POINT, ID_PATHING_BREAKPOINTS_NEWCHILD, OnBreakpointType)    
  42.     ON_UPDATE_COMMAND_UI_RANGE(ID_PATHING_BREAKPOINTS_POINT, ID_PATHING_BREAKPOINTS_NEWCHILD, OnUpdateUIBreakpointType)    
  43. END_MESSAGE_MAP()
  44.  
  45. /////////////////////////////////////////////////////////////////////////////
  46. // CAseDoc construction/destruction
  47.  
  48. CAseDoc::CAseDoc()
  49. {
  50.     memset(m_cBoard, 0, sizeof(m_cBoard));
  51.     m_bAllowDiagonal = true;
  52.     m_bContinualUpdate = false;
  53.     m_uBrushType = 0;
  54.     m_bRelativeCosting = false;
  55. }
  56.  
  57. CAseDoc::~CAseDoc()
  58. {
  59. }
  60.  
  61. BOOL CAseDoc::OnNewDocument()
  62. {
  63.     if (!CDocument::OnNewDocument())
  64.         return FALSE;
  65.  
  66.     memset(m_cBoard, 0, sizeof(m_cBoard));
  67.     m_cStart.x = -1;
  68.     m_cEnd.x = -1;
  69.     m_cBreakpoint.x = -1;
  70.     m_iBreakData = -1;
  71.     m_bStepped = false;
  72.  
  73.     m_cAStar.Reset();
  74.     m_bDrawRoute = false;
  75.  
  76.     return TRUE;
  77. }
  78.  
  79. BOOL CAseDoc::OnOpenDocument(LPCTSTR lpszPathName) 
  80. {
  81.     if (!CDocument::OnOpenDocument(lpszPathName))
  82.         return FALSE;
  83.     
  84.     m_bStepped = false;
  85.     m_cBreakpoint.x = -1;
  86.     m_iBreakData = -1;
  87.     
  88.     m_cAStar.Reset();
  89.     m_bDrawRoute = false;
  90.  
  91.     return TRUE;
  92. }
  93.  
  94.  
  95. /////////////////////////////////////////////////////////////////////////////
  96. // CAseDoc serialization
  97.  
  98. void CAseDoc::Serialize(CArchive& ar)
  99. {
  100.     int x = ASE_BOARDX, y = ASE_BOARDY;
  101.  
  102.     if (ar.IsStoring()) {
  103.         ar << x;
  104.         ar << y;
  105.         ar << m_cStart;
  106.         ar << m_cEnd;
  107.  
  108.         for (int i=0; i<x; i++) {
  109.             for (int j=0; j<y; j++) {
  110.                 ar << m_cBoard[i][j];
  111.             }
  112.         }
  113.     } else {
  114.         ar >> x;
  115.         ar >> y;
  116.         ar >> m_cStart;
  117.         ar >> m_cEnd;
  118.  
  119.         for (int i=0; i<x; i++) {
  120.             for (int j=0; j<y; j++) {
  121.                 ar >> m_cBoard[i][j];
  122.             }
  123.         }
  124.     }
  125. }
  126.  
  127. /////////////////////////////////////////////////////////////////////////////
  128. // CAseDoc diagnostics
  129.  
  130. #ifdef _DEBUG
  131. void CAseDoc::AssertValid() const
  132. {
  133.     CDocument::AssertValid();
  134. }
  135.  
  136. void CAseDoc::Dump(CDumpContext& dc) const
  137. {
  138.     CDocument::Dump(dc);
  139. }
  140. #endif //_DEBUG
  141.  
  142. /////////////////////////////////////////////////////////////////////////////
  143. // CAseDoc commands
  144.  
  145. int CAseDoc::AS_Valid(_asNode *parent, _asNode *node, int data, void *pointer) 
  146. {
  147.     int x = node->x, y = node->y;
  148.     CAseDoc *me = reinterpret_cast<CAseDoc *>(pointer);
  149.  
  150.     if (x < 0 || y < 0 || x >= ASE_BOARDX || y >= ASE_BOARDY) return FALSE;
  151.     if (me->m_cBoard[x][y] == 3) return FALSE;
  152.  
  153.     if (!(me->m_bAllowDiagonal)) {
  154.         int px = parent->x;
  155.         int py = parent->y;
  156.  
  157.         if (px - x != 0 && py - y != 0) return FALSE;
  158.     }
  159.  
  160.     return TRUE;
  161. }
  162.  
  163. int CAseDoc::AS_Cost(_asNode *parent, _asNode *node, int data, void *pointer) 
  164. {
  165.     CAseDoc *me = reinterpret_cast<CAseDoc *>(pointer);
  166.  
  167.     int cost = me->m_cBoard[node->x][node->y]+1;    // Ensure always cost > 1
  168.  
  169.     return cost;
  170. }
  171.  
  172. int CAseDoc::AS_RelativeCost(_asNode *parent, _asNode *node, int data, void *pointer) 
  173. {
  174.     CAseDoc *me = reinterpret_cast<CAseDoc *>(pointer);
  175.  
  176.     int cost = abs(me->m_cBoard[node->x][node->y] - 
  177.                    me->m_cBoard[parent->x][parent->y])+1;
  178.  
  179.     return cost;
  180. }
  181.  
  182. void CAseDoc::NodeAdded(_asNode *node, int data) 
  183. {
  184.     if (m_cBreakpoint.x == -1 && m_iBreakData == -1) return;
  185.  
  186.     if (node->x == m_cBreakpoint.x && node->y == m_cBreakpoint.y) {
  187.         m_bBreakpointHit = true;
  188.         m_pcBreakNode = node;
  189.     } 
  190.     
  191.     if (data == m_iBreakData) {
  192.         m_bBreakpointHit = true;
  193.         m_pcBreakNode = node;
  194.     }
  195. }
  196.  
  197. CNodeView *CAseDoc::GetNodeView()
  198. {
  199.     POSITION pos;
  200.     pos = GetFirstViewPosition();
  201.  
  202.     CNodeView *nv = reinterpret_cast<CNodeView *>(GetNextView(pos));
  203.  
  204.     return nv;
  205. }
  206.  
  207. CAseView *CAseDoc::GetAseView()
  208. {
  209.     CMainFrame* pMfm = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  210.     CAseView *view = reinterpret_cast<CAseView *>(pMfm->GetRightPane());
  211.     
  212.     return view;
  213. }
  214.  
  215. bool CAseDoc::SetupAStar(bool stepped/* = false*/)
  216. {
  217.     if (m_cStart.x == -1 || m_cEnd.x == -1) {
  218.         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);
  219.         return false;
  220.     }
  221.  
  222.     CNodeView *nv = GetNodeView();
  223.     GetAseView()->RemoveHighlight();
  224.  
  225.     m_cAStar.SetRows(ASE_BOARDX);
  226.     m_cAStar.udValid = AS_Valid;
  227.     m_cAStar.udCost = (m_bRelativeCosting) ? AS_RelativeCost : AS_Cost;
  228.     
  229.     m_cAStar.udNotifyList = NULL;
  230.     m_cAStar.udNotifyChild = (m_bContinualUpdate) ? NULL : CNodeView::OnNotifyChild;
  231.  
  232.     m_cAStar.m_pCBData = reinterpret_cast<void *>(this);
  233.     m_cAStar.m_pNCData = reinterpret_cast<void *>(nv);
  234.  
  235.     nv->OnPreAStar();
  236.  
  237.     if (stepped) {
  238.         CTreeCtrl &tree = GetNodeView()->GetTreeCtrl();
  239.         tree.InsertItem("A* Tree", 6, 6);
  240.         tree.InsertItem("Open List", 7, 7);
  241.         tree.InsertItem("Closed List", 8, 8);
  242.  
  243.         m_cAStar.udNotifyList = CNodeView::OnNotifyList;
  244.         m_cAStar.StepInitialize(m_cStart.x, m_cStart.y, m_cEnd.x, m_cEnd.y);
  245.     }
  246.  
  247.     return true;
  248. }
  249.  
  250. void CAseDoc::DrawNode(_asNode *node)
  251. {
  252.     GetAseView()->HighlightNode(node, true);
  253. }
  254.  
  255. void CAseDoc::MessageBox(CString title, CString caption, UINT type)
  256. {
  257.     AfxGetMainWnd()->MessageBox(title, caption, type);
  258. }
  259.  
  260. void CAseDoc::OnBreakpointType(UINT uType)
  261. {
  262.     int type = uType - ID_PATHING_BREAKPOINTS_POINT;
  263.  
  264.     if (type == 0) {
  265.         m_cBreakpoint.x = -1;
  266.         UpdateAllViews(NULL);
  267.     }
  268.  
  269.     m_iBreakData = (type == 0) ? -1 : type;
  270. }
  271.  
  272. void CAseDoc::OnUpdateUIBreakpointType(CCmdUI *pCmdUI)
  273. {
  274.     UINT uID = pCmdUI->m_nID;
  275.  
  276.     if (uID == ID_PATHING_BREAKPOINTS_POINT) {
  277.         pCmdUI->Enable((m_cBreakpoint.x != -1));
  278.         pCmdUI->SetCheck((m_cBreakpoint.x != -1));
  279.         return;
  280.     }
  281.  
  282.     pCmdUI->SetCheck(uID == unsigned(m_iBreakData + ID_PATHING_BREAKPOINTS_POINT));
  283. }
  284.  
  285. void CAseDoc::OnRunToBreakpoint() 
  286. {
  287.     if (!m_bStepped) {
  288.         if (!SetupAStar(true)) return;
  289.  
  290.         m_bDrawRoute = false;
  291.         m_bStepped = true;
  292.  
  293.         m_bBreakpointHit = (m_cBreakpoint == m_cStart) ? true : false;
  294.     } else {
  295.         m_bBreakpointHit = false;
  296.     }
  297.     
  298.     int retval = 1;
  299.     while (!m_bBreakpointHit) {
  300.         retval = m_cAStar.Step();
  301.         GetNodeView()->SortOpen();
  302.  
  303.         if (retval == -1) {
  304.             m_bStepped= false;
  305.             MessageBox("A path could not be found.", "A* Explorer", MB_ICONERROR);
  306.             break;
  307.         } else if (retval == 1) {
  308.             m_bDrawRoute = true;
  309.             m_bStepped = false;
  310.             GetNodeView()->OnPostAStar(m_cAStar.GetBestNode());
  311.             UpdateAllViews(NULL);
  312.  
  313.             MessageBox("Stepping complete. A path has been found.", "A* Explorer", MB_ICONINFORMATION);
  314.             break;
  315.         }
  316.     }
  317.  
  318.     if (m_bBreakpointHit) {
  319.         CString str;
  320.         if (m_iBreakData == -1) {
  321.             str.Format("Breakpoint at (%d,%d) hit.", m_cBreakpoint.x, m_cBreakpoint.y);
  322.         } else {
  323.             str = "The conditional breakpoint has been satisfied in this iteration.";
  324.         }
  325.  
  326.         MessageBox(str, "A* Explorer", MB_ICONSTOP);
  327.  
  328.         CTreeCtrl &tree = GetNodeView()->GetTreeCtrl();
  329.         tree.EnsureVisible(HTREEITEM(m_pcBreakNode->dataptr));
  330.         tree.SelectItem(HTREEITEM(m_pcBreakNode->dataptr));
  331.         tree.Invalidate();
  332.     }
  333. }
  334.  
  335. void CAseDoc::OnUpdateRunToBreakpoint(CCmdUI* pCmdUI) 
  336. {
  337.     pCmdUI->Enable((m_iBreakData != -1 || m_cBreakpoint.x != -1));
  338. }
  339.  
  340. void CAseDoc::OnExecuteAStar() 
  341. {
  342.     if (m_bStepped) {
  343.         int retval;
  344.         while (true) {
  345.             retval = m_cAStar.Step();
  346.             if (retval == -1) {
  347.                 m_bStepped= false;
  348.                 GetNodeView()->SortOpen();
  349.                 MessageBox("A path could not be found.", "A* Explorer", MB_ICONERROR);
  350.                 break;
  351.             } else if (retval == 1) {
  352.                 m_bDrawRoute = true;
  353.                 m_bStepped = false;
  354.                 GetNodeView()->OnPostAStar(m_cAStar.GetBestNode());
  355.                 UpdateAllViews(NULL);
  356.  
  357.                 GetNodeView()->SortOpen();
  358.                 MessageBox("Stepping complete. A path has been found.", "A* Explorer", MB_ICONINFORMATION);
  359.                 break;
  360.             }
  361.         }
  362.  
  363.         return;
  364.     }
  365.  
  366.     if (!SetupAStar()) return;
  367.  
  368.     if (m_cAStar.GeneratePath(m_cStart.x, m_cStart.y, m_cEnd.x, m_cEnd.y)) {
  369.         m_bDrawRoute = true;
  370.         GetNodeView()->OnPostAStar(m_cAStar.GetBestNode());
  371.     } else {
  372.         m_bDrawRoute = false;
  373.  
  374.         MessageBox("A path could not be found.", "A* Explorer", MB_ICONERROR);
  375.     }
  376.  
  377.     UpdateAllViews(NULL);
  378. }
  379.  
  380. void CAseDoc::OnStepAStar() 
  381. {
  382.     if (!m_bStepped) {
  383.         if (!SetupAStar(true)) return;
  384.  
  385.         m_bStepped = true;
  386.         m_bDrawRoute = false;
  387.  
  388.         GetNodeView()->RedrawWindow();
  389.     } else {
  390.         int retval = m_cAStar.Step();
  391.         GetNodeView()->SortOpen();
  392.  
  393.         if (retval == -1) {
  394.             m_bDrawRoute = false;
  395.             m_bStepped = false;
  396.  
  397.             MessageBox("A path could not be found.", "A* Explorer", MB_ICONERROR);
  398.         } else if (retval == 1) {
  399.             m_bDrawRoute = true;
  400.             m_bStepped = false;
  401.  
  402.             GetNodeView()->OnPostAStar(m_cAStar.GetBestNode());
  403.  
  404.             MessageBox("Stepping complete. A path has been found.", "A* Explorer", MB_ICONINFORMATION);
  405.         }
  406.  
  407.         UpdateAllViews(NULL);
  408.     }
  409. }
  410.  
  411. void CAseDoc::OnPathingAllowDiagonal() 
  412. {
  413.     m_bAllowDiagonal = !m_bAllowDiagonal;
  414. }
  415.  
  416. void CAseDoc::OnUpdatePathingAllowDiagonal(CCmdUI* pCmdUI) 
  417. {
  418.     pCmdUI->SetCheck(m_bAllowDiagonal);
  419. }
  420.  
  421. void CAseDoc::OnBrushType(UINT uType)
  422. {
  423.     m_uBrushType = uType - ID_WEIGHT0;
  424.     
  425.     GetAseView()->SetBrushType(m_uBrushType);
  426. }
  427.  
  428. void CAseDoc::OnUpdateUIBrushType(CCmdUI *pCmdUI)
  429. {
  430.     UINT uType = pCmdUI->m_nID;
  431.  
  432.     pCmdUI->SetCheck((m_uBrushType == uType - ID_WEIGHT0));
  433. }
  434.  
  435. void CAseDoc::OnViewARoute() 
  436. {
  437.     m_bDrawRoute = !m_bDrawRoute;
  438.  
  439.     UpdateAllViews(NULL);
  440. }
  441.  
  442. void CAseDoc::OnUpdateViewARoute(CCmdUI* pCmdUI) 
  443. {
  444.     pCmdUI->Enable((m_cAStar.GetBestNode() != NULL));
  445.     pCmdUI->SetCheck(m_bDrawRoute);
  446. }
  447.  
  448. void CAseDoc::OnPathingContinuousUpdate() 
  449. {
  450.     m_bContinualUpdate = !m_bContinualUpdate;
  451. }
  452.  
  453. void CAseDoc::OnUpdatePathingContinuousUpdate(CCmdUI* pCmdUI) 
  454. {
  455.     pCmdUI->SetCheck(m_bContinualUpdate);
  456. }
  457.  
  458. void CAseDoc::NotifyClick()
  459. {
  460.     if (m_bContinualUpdate && m_cStart.x != -1 && m_cEnd.x != -1) {
  461.         m_bStepped = false;
  462.         OnExecuteAStar();
  463.     }
  464. }
  465.  
  466. void CAseDoc::OnPathingRelativeCosting() 
  467. {
  468.     m_bRelativeCosting = !m_bRelativeCosting;
  469. }
  470.  
  471. void CAseDoc::OnUpdatePathingRelativeCosting(CCmdUI* pCmdUI) 
  472. {
  473.     pCmdUI->SetCheck(m_bRelativeCosting);
  474. }
  475.