void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile) { if (!tile) return; dtPolyRef base = getPolyRefBase(tile); // Base off-mesh connection start points. for (int i = 0; i < tile->header->offMeshConCount; ++i) { dtOffMeshConnection* con = &tile->offMeshCons[i]; dtPoly* poly = &tile->polys[con->poly]; const float ext[3] = { con->rad, tile->header->walkableClimb, con->rad }; // Find polygon to connect to. const float* p = &con->pos[0]; // First vertex float nearestPt[3]; dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt); if (!ref) continue; // findNearestPoly may return too optimistic results, further check to make sure. if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(con->rad)) continue; // Make sure the location is on current mesh. float* v = &tile->verts[poly->verts[0]*3]; dtVcopy(v, nearestPt); // Link off-mesh connection to target poly. unsigned int idx = allocLink(tile); if (idx != DT_NULL_LINK) { dtLink* link = &tile->links[idx]; link->ref = ref; link->edge = (unsigned char)0; link->side = 0xff; link->bmin = link->bmax = 0; // Add to linked list. link->next = poly->firstLink; poly->firstLink = idx; } // Start end-point is always connect back to off-mesh connection. unsigned int tidx = allocLink(tile); if (tidx != DT_NULL_LINK) { const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); dtPoly* landPoly = &tile->polys[landPolyIdx]; dtLink* link = &tile->links[tidx]; link->ref = base | (dtPolyRef)(con->poly); link->edge = 0xff; link->side = 0xff; link->bmin = link->bmax = 0; // Add to linked list. link->next = landPoly->firstLink; landPoly->firstLink = tidx; } } }
void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side) { if (!tile) return; // Connect border links. for (int i = 0; i < tile->header->polyCount; ++i) { dtPoly* poly = &tile->polys[i]; // Create new links. unsigned short m = DT_EXT_LINK | (unsigned short)side; const int nv = poly->vertCount; for (int j = 0; j < nv; ++j) { // Skip edges which do not point to the right side. if (poly->neis[j] != m) continue; // Create new links const float* va = &tile->verts[poly->verts[j]*3]; const float* vb = &tile->verts[poly->verts[(j+1) % nv]*3]; dtPolyRef nei[4]; float neia[4*2]; int nnei = findConnectingPolys(va,vb, target, dtOppositeTile(side), nei,neia,4); for (int k = 0; k < nnei; ++k) { unsigned int idx = allocLink(tile); if (idx != DT_NULL_LINK) { dtLink* link = &tile->links[idx]; link->ref = nei[k]; link->edge = (unsigned char)j; link->side = (unsigned char)side; link->next = poly->firstLink; poly->firstLink = idx; // Compress portal limits to a byte value. if (side == 0 || side == 4) { float tmin = (neia[k*2+0]-va[2]) / (vb[2]-va[2]); float tmax = (neia[k*2+1]-va[2]) / (vb[2]-va[2]); if (tmin > tmax) dtSwap(tmin,tmax); link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f); link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f); } else if (side == 2 || side == 6) { float tmin = (neia[k*2+0]-va[0]) / (vb[0]-va[0]); float tmax = (neia[k*2+1]-va[0]) / (vb[0]-va[0]); if (tmin > tmax) dtSwap(tmin,tmax); link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f); link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f); } } } } } }
int main() { freopen("t.in", "r", stdin); scanf("%s%s", str1, str2); int n1 = strlen(str1), n2 = strlen(str2); Link *head = allocLink('('), *now = head; for(int i = 0; i < n1; i ++) { Link *next = allocLink(str1[i] - 'A' + 'a'); now->next = next; now = next; } now->next = allocLink(')'); now = head->next; int expandCnt = 0; for(int i = 0; i < n2; i ++) { if(now->ch == ')') { printf("NO\n"); return 0; } if((now->ch == 'a' && str2[i] == 'B') || (now->ch == 'b' && str2[i] == 'A')) now = now->next; else { if(expandCnt * 2 + n1 >= n2) { printf("NO\n"); return 0; } if(now->ch == 'a') { Link *l1 = allocLink('b'), *l2 = allocLink('a'); l1->next = l2, l2->next = now->next; now = l1; expandCnt ++; } else { Link *l1 = allocLink('a'), *l2 = allocLink('b'); l1->next = l2, l2->next = now->next; now = l1; expandCnt ++; } } } if(expandCnt * 2 + n1 == n2) printf("YES\n"); else printf("NO\n"); }
void dtNavMesh::connectIntLinks(dtMeshTile* tile) { if (!tile) return; dtPolyRef base = getPolyRefBase(tile); for (int i = 0; i < tile->header->polyCount; ++i) { dtPoly* poly = &tile->polys[i]; poly->firstLink = DT_NULL_LINK; if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) continue; // Build edge links backwards so that the links will be // in the linked list from lowest index to highest. for (int j = poly->vertCount-1; j >= 0; --j) { // Skip hard and non-internal edges. if (poly->neis[j] == 0 || (poly->neis[j] & DT_EXT_LINK)) continue; unsigned int idx = allocLink(tile); if (idx != DT_NULL_LINK) { dtLink* link = &tile->links[idx]; link->ref = base | (dtPolyRef)(poly->neis[j]-1); link->edge = (unsigned char)j; link->side = 0xff; link->bmin = link->bmax = 0; // Add to linked list. link->next = poly->firstLink; poly->firstLink = idx; } } } }
void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side) { if (!tile) return; // Connect off-mesh links. // We are interested on links which land from target tile to this tile. const unsigned char oppositeSide = (side == -1) ? 0xff : (unsigned char)dtOppositeTile(side); for (int i = 0; i < target->header->offMeshConCount; ++i) { dtOffMeshConnection* targetCon = &target->offMeshCons[i]; if (targetCon->side != oppositeSide) continue; dtPoly* targetPoly = &target->polys[targetCon->poly]; // Skip off-mesh connections which start location could not be connected at all. if (targetPoly->firstLink == DT_NULL_LINK) continue; const float ext[3] = { targetCon->rad, target->header->walkableClimb, targetCon->rad }; // Find polygon to connect to. const float* p = &targetCon->pos[3]; float nearestPt[3]; dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt); if (!ref) continue; // findNearestPoly may return too optimistic results, further check to make sure. if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(targetCon->rad)) continue; // Make sure the location is on current mesh. float* v = &target->verts[targetPoly->verts[1]*3]; dtVcopy(v, nearestPt); // Link off-mesh connection to target poly. unsigned int idx = allocLink(target); if (idx != DT_NULL_LINK) { dtLink* link = &target->links[idx]; link->ref = ref; link->edge = (unsigned char)1; link->side = oppositeSide; link->bmin = link->bmax = 0; // Add to linked list. link->next = targetPoly->firstLink; targetPoly->firstLink = idx; } // Link target poly to off-mesh connection. if (targetCon->flags & DT_OFFMESH_CON_BIDIR) { unsigned int tidx = allocLink(tile); if (tidx != DT_NULL_LINK) { const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); dtPoly* landPoly = &tile->polys[landPolyIdx]; dtLink* link = &tile->links[tidx]; link->ref = getPolyRefBase(target) | (dtPolyRef)(targetCon->poly); link->edge = 0xff; link->side = (unsigned char)(side == -1 ? 0xff : side); link->bmin = link->bmax = 0; // Add to linked list. link->next = landPoly->firstLink; landPoly->firstLink = tidx; } } } }
void dtNavMesh::connectIntOffMeshLinks(dtMeshTile* tile) { if (!tile) return; dtPolyRef base = getPolyRefBase(tile); // Find Off-mesh connection end points. for (int i = 0; i < tile->header->offMeshConCount; ++i) { dtOffMeshConnection* con = &tile->offMeshCons[i]; dtPoly* poly = &tile->polys[con->poly]; const float ext[3] = { con->rad, tile->header->walkableClimb, con->rad }; for (int j = 0; j < 2; ++j) { unsigned char side = j == 0 ? 0xff : con->side; if (side == 0xff) { // Find polygon to connect to. const float* p = &con->pos[j*3]; float nearestPt[3]; dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt); if (!ref) continue; // findNearestPoly may return too optimistic results, further check to make sure. if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(con->rad)) continue; // Make sure the location is on current mesh. float* v = &tile->verts[poly->verts[j]*3]; dtVcopy(v, nearestPt); // Link off-mesh connection to target poly. unsigned int idx = allocLink(tile); if (idx != DT_NULL_LINK) { dtLink* link = &tile->links[idx]; link->ref = ref; link->edge = (unsigned char)j; link->side = 0xff; link->bmin = link->bmax = 0; // Add to linked list. link->next = poly->firstLink; poly->firstLink = idx; } // Start end-point is always connect back to off-mesh connection, // Destination end-point only if it is bidirectional link. if (j == 0 || (j == 1 && (con->flags & DT_OFFMESH_CON_BIDIR))) { // Link target poly to off-mesh connection. unsigned int idx = allocLink(tile); if (idx != DT_NULL_LINK) { const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); dtPoly* landPoly = &tile->polys[landPolyIdx]; dtLink* link = &tile->links[idx]; link->ref = base | (unsigned int)(con->poly); link->edge = 0xff; link->side = 0xff; link->bmin = link->bmax = 0; // Add to linked list. link->next = landPoly->firstLink; landPoly->firstLink = idx; } } } } } }