src/pathfind.cpp
branchnoai
changeset 9732 f8eb3e208514
parent 9724 b39bc69bb2f2
child 9826 9707ad4c9b60
equal deleted inserted replaced
9731:9b1552d0fd9b 9732:f8eb3e208514
   138 	0x2A,
   138 	0x2A,
   139 };
   139 };
   140 
   140 
   141 static void TPFMode2(TrackPathFinder* tpf, TileIndex tile, DiagDirection direction)
   141 static void TPFMode2(TrackPathFinder* tpf, TileIndex tile, DiagDirection direction)
   142 {
   142 {
   143 	uint bits;
       
   144 	RememberData rd;
   143 	RememberData rd;
   145 
   144 
   146 	assert(tpf->tracktype == TRANSPORT_WATER);
   145 	assert(tpf->tracktype == TRANSPORT_WATER);
   147 
   146 
   148 	/* This addition will sometimes overflow by a single tile.
   147 	/* This addition will sometimes overflow by a single tile.
   151 	tile = TILE_MASK(tile + TileOffsByDiagDir(direction));
   150 	tile = TILE_MASK(tile + TileOffsByDiagDir(direction));
   152 
   151 
   153 	if (++tpf->rd.cur_length > 50)
   152 	if (++tpf->rd.cur_length > 50)
   154 		return;
   153 		return;
   155 
   154 
   156 	bits = GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type);
   155 	TrackStatus ts = GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type);
   157 	bits = (byte)((bits | (bits >> 8)) & _bits_mask[direction]);
   156 	TrackBits bits = (TrackBits)(TrackStatusToTrackBits(ts) & _bits_mask[direction]);
   158 	if (bits == 0)
   157 	if (bits == TRACK_BIT_NONE) return;
   159 		return;
       
   160 
   158 
   161 	assert(TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY());
   159 	assert(TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY());
   162 
   160 
   163 	uint i = 0;
   161 	bool only_one_track = true;
   164 	/* only one direction */
   162 	do {
   165 	if (KillFirstBit(bits) == 0) {
   163 		Track track = RemoveFirstTrack(&bits);
   166 		i = FindFirstBit(bits);
   164 		if (bits != TRACK_BIT_NONE) only_one_track = false;
   167 		rd = tpf->rd;
   165 		rd = tpf->rd;
   168 		goto continue_here;
       
   169 	}
       
   170 	/* several directions */
       
   171 	do {
       
   172 		i = FindFirstBit(bits);
       
   173 		rd = tpf->rd;
       
   174 
   166 
   175 		/* Change direction 4 times only */
   167 		/* Change direction 4 times only */
   176 		if ((byte)i != tpf->rd.pft_var6) {
   168 		if (!only_one_track && track != tpf->rd.last_choosen_track) {
   177 			if (++tpf->rd.depth > 4) {
   169 			if (++tpf->rd.depth > 4) {
   178 				tpf->rd = rd;
   170 				tpf->rd = rd;
   179 				return;
   171 				return;
   180 			}
   172 			}
   181 			tpf->rd.pft_var6 = (byte)i;
   173 			tpf->rd.last_choosen_track = track;
   182 		}
   174 		}
   183 
   175 
   184 continue_here:
   176 		tpf->the_dir = (Trackdir)(track + (HasBit(_otherdir_mask[direction], track) ? 8 : 0));
   185 		tpf->the_dir = (Trackdir)(i + (HasBit(_otherdir_mask[direction], i) ? 8 : 0));
   177 
   186 
   178 		if (!tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length)) {
   187 		if (!tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length, NULL)) {
       
   188 			TPFMode2(tpf, tile, _tpf_new_direction[tpf->the_dir]);
   179 			TPFMode2(tpf, tile, _tpf_new_direction[tpf->the_dir]);
   189 		}
   180 		}
   190 
   181 
   191 		tpf->rd = rd;
   182 		tpf->rd = rd;
   192 	} while (ClrBit(bits, i) != 0);
   183 	} while (bits != TRACK_BIT_NONE);
   193 
   184 
   194 }
   185 }
   195 
   186 
   196 /**
   187 /**
   197  * Checks if any vehicle can enter/leave tile in given diagdir
   188  * Checks if any vehicle can enter/leave tile in given diagdir
   259 				GetTunnelBridgeTransportType(tile) != tpf->tracktype) {
   250 				GetTunnelBridgeTransportType(tile) != tpf->tracktype) {
   260 			return;
   251 			return;
   261 		}
   252 		}
   262 	}
   253 	}
   263 
   254 
   264 	uint32 bits = GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type);
   255 	uint32 bits = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type));
   265 
   256 
   266 	/* Check in case of rail if the owner is the same */
   257 	/* Check in case of rail if the owner is the same */
   267 	if (tpf->tracktype == TRANSPORT_RAIL) {
   258 	if (tpf->tracktype == TRANSPORT_RAIL) {
   268 		if (bits != 0 && GetTileTrackStatus(tile_org, TRANSPORT_RAIL, 0) != 0) {
   259 		if (bits != 0 && TrackStatusToTrackdirBits(GetTileTrackStatus(tile_org, TRANSPORT_RAIL, 0)) != TRACKDIR_BIT_NONE) {
   269 			if (GetTileOwner(tile_org) != GetTileOwner(tile)) return;
   260 			if (GetTileOwner(tile_org) != GetTileOwner(tile)) return;
   270 		}
   261 		}
   271 	}
   262 	}
   272 
   263 
   273 	tpf->rd.cur_length++;
   264 	tpf->rd.cur_length++;
   285 				bits = KillFirstBit(bits);
   276 				bits = KillFirstBit(bits);
   286 
   277 
   287 				tpf->the_dir = (Trackdir)((_otherdir_mask[direction] & (byte)(1 << i)) ? (i + 8) : i);
   278 				tpf->the_dir = (Trackdir)((_otherdir_mask[direction] & (byte)(1 << i)) ? (i + 8) : i);
   288 				RememberData rd = tpf->rd;
   279 				RememberData rd = tpf->rd;
   289 
   280 
   290 				if (TPFSetTileBit(tpf, tile, tpf->the_dir) &&
   281 				/* make sure we are not leaving from invalid side */
   291 						!tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length, &tpf->rd.pft_var6) ) {
   282 				if (TPFSetTileBit(tpf, tile, tpf->the_dir) && CanAccessTileInDir(tile, TrackdirToExitdir(tpf->the_dir), tpf->tracktype) &&
       
   283 						!tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length) ) {
   292 					TPFMode1(tpf, tile, _tpf_new_direction[tpf->the_dir]);
   284 					TPFMode1(tpf, tile, _tpf_new_direction[tpf->the_dir]);
   293 				}
   285 				}
   294 				tpf->rd = rd;
   286 				tpf->rd = rd;
   295 			} while (bits != 0);
   287 			} while (bits != 0);
   296 		}
   288 		}
   309 	tpf.new_link = tpf.links;
   301 	tpf.new_link = tpf.links;
   310 	tpf.num_links_left = lengthof(tpf.links);
   302 	tpf.num_links_left = lengthof(tpf.links);
   311 
   303 
   312 	tpf.rd.cur_length = 0;
   304 	tpf.rd.cur_length = 0;
   313 	tpf.rd.depth = 0;
   305 	tpf.rd.depth = 0;
   314 	tpf.rd.pft_var6 = 0;
   306 	tpf.rd.last_choosen_track = INVALID_TRACK;
   315 
   307 
   316 	tpf.var2 = HasBit(flags, 15) ? 0x43 : 0xFF; // 0x8000
   308 	tpf.var2 = HasBit(flags, 15) ? 0x43 : 0xFF; // 0x8000
   317 
   309 
   318 	tpf.disable_tile_hash = HasBit(flags, 12);  // 0x1000
   310 	tpf.disable_tile_hash = HasBit(flags, 12);  // 0x1000
   319 
   311 
   320 
   312 
   321 	tpf.tracktype = (TransportType)(flags & 0xFF);
   313 	tpf.tracktype = (TransportType)(flags & 0xFF);
   322 	tpf.sub_type = sub_type;
   314 	tpf.sub_type = sub_type;
   323 
   315 
   324 	if (HasBit(flags, 11)) {
   316 	if (HasBit(flags, 11)) {
   325 		tpf.rd.pft_var6 = 0xFF;
   317 		tpf.enum_proc(tile, data, INVALID_TRACKDIR, 0);
   326 		tpf.enum_proc(tile, data, INVALID_TRACKDIR, 0, 0);
       
   327 		TPFMode2(&tpf, tile, direction);
   318 		TPFMode2(&tpf, tile, direction);
   328 	} else {
   319 	} else {
   329 		/* clear the hash_heads */
   320 		/* clear the hash_heads */
   330 		memset(tpf.hash_head, 0, sizeof(tpf.hash_head));
   321 		memset(tpf.hash_head, 0, sizeof(tpf.hash_head));
   331 		TPFMode1(&tpf, tile, direction);
   322 		TPFMode1(&tpf, tile, direction);
   689 			/* Not a regular rail tile?
   680 			/* Not a regular rail tile?
   690 			 * Then we can't use the code below, but revert to more general code. */
   681 			 * Then we can't use the code below, but revert to more general code. */
   691 			if (!IsTileType(tile, MP_RAILWAY) || !IsPlainRailTile(tile)) {
   682 			if (!IsTileType(tile, MP_RAILWAY) || !IsPlainRailTile(tile)) {
   692 				/* We found a tile which is not a normal railway tile.
   683 				/* We found a tile which is not a normal railway tile.
   693 				 * Determine which tracks that exist on this tile. */
   684 				 * Determine which tracks that exist on this tile. */
   694 				uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _tpfmode1_and[direction];
   685 				TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _tpfmode1_and[direction];
   695 				bits = TrackdirBitsToTrackBits((TrackdirBits)(ts & TRACKDIR_BIT_MASK));
   686 				bits = TrackStatusToTrackBits(ts);
   696 
   687 
   697 				/* Check that the tile contains exactly one track */
   688 				/* Check that the tile contains exactly one track */
   698 				if (bits == 0 || KillFirstBit(bits) != 0) break;
   689 				if (bits == 0 || KillFirstBit(bits) != 0) break;
   699 
   690 
   700 				if (!HasBit(tpf->railtypes, GetRailType(tile))) {
   691 				if (!HasBit(tpf->railtypes, GetRailType(tile))) {