Changeset 100 for trunk/UGame.pas
- Timestamp:
- Dec 26, 2014, 8:10:40 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/UGame.pas
r96 r100 26 26 TCells = class; 27 27 TMap = class; 28 TCellLinks = class; 29 TMapArea = class; 28 30 29 31 TFloatPoint = record … … 39 41 TCell = class 40 42 private 43 FArea: TMapArea; 41 44 FMap: TMap; 42 45 FPower: Integer; 46 procedure SetArea(AValue: TMapArea); 43 47 procedure SetPower(AValue: Integer); 44 48 public … … 54 58 Neighbors: TCells; 55 59 Mark: Boolean; 60 procedure AreaExtend; 56 61 procedure FixRefId; 57 62 procedure LoadFromNode(Node: TDOMNode); … … 66 71 property Power: Integer read FPower write SetPower; 67 72 property Map: TMap read FMap write FMap; 73 property Area: TMapArea read FArea write SetArea; 68 74 end; 69 75 … … 78 84 procedure LoadFromNode(Node: TDOMNode); 79 85 procedure SaveToNode(Node: TDOMNode); 86 procedure ClearMark; 87 end; 88 89 TCellLink = class 90 Points: array of TPoint; 91 Cell1: TCell; 92 Cell2: TCell; 93 end; 94 95 TCellLinks = class(TObjectList) 96 80 97 end; 81 98 … … 116 133 TMapShape = (msRectangle, msImage); 117 134 135 { TMapArea } 136 137 TMapArea = class 138 Id: Integer; 139 Map: TMap; 140 BridgeCount: Integer; 141 Cells: TCells; 142 procedure GetBorderCells(List: TCells); 143 constructor Create; 144 destructor Destroy; override; 145 end; 146 147 TMapAreas = class(TObjectList) 148 149 end; 150 118 151 { TMap } 119 152 … … 136 169 Shape: TMapShape; 137 170 Image: TImage; 171 CellLinks: TCellLinks; 172 Areas: TMapAreas; 138 173 function IsOutsideShape(Coord: TPoint): Boolean; virtual; 139 174 function IsCellsNeighbor(Cell1, Cell2: TCell): Boolean; virtual; … … 357 392 procedure UpdateRepeatMoves(Player: TPlayer); 358 393 procedure CheckCounterMove(Move: TUnitMove); 394 function SearchDifferentCellArea(List: TCells; SourceArea, DestArea: TMapArea): TCell; 395 procedure BuildTerrain; 396 procedure BuildBridges; 397 procedure BuildMapAreas; 359 398 public 360 399 Players: TPlayers; … … 377 416 FileName: string; 378 417 FogOfWar: Boolean; 418 BridgeEnabled: Boolean; 379 419 function AttackProbability(AttackCount, DefendCount: Integer): Double; 380 420 procedure LoadConfig(Config: TXmlConfig; Path: string); … … 499 539 end; 500 540 541 { TMapArea } 542 543 procedure TMapArea.GetBorderCells(List: TCells); 544 var 545 I: Integer; 546 J: Integer; 547 NeighVoidCount: Integer; 548 begin 549 List.Clear; 550 551 // Unset mark for all cells 552 for I := 0 to Map.Cells.Count - 1 do 553 TCell(Map.Cells[I]).Mark := False; 554 555 for I := 0 to Cells.Count - 1 do 556 with TCell(Cells[I]) do begin 557 NeighVoidCount := 0; 558 for J := 0 to Neighbors.Count - 1 do 559 with TCell(Neighbors[J]) do 560 if (Terrain = ttVoid) then Inc(NeighVoidCount); 561 562 if (NeighVoidCount > 0) and (Area = Self) and (not Mark) then begin 563 List.Add(TCell(Self.Cells[I])); 564 Mark := True; 565 end; 566 end; 567 end; 568 569 constructor TMapArea.Create; 570 begin 571 Cells := TCells.Create; 572 Cells.OwnsObjects := False; 573 end; 574 575 destructor TMapArea.Destroy; 576 begin 577 Cells.Free; 578 inherited Destroy; 579 end; 580 501 581 { TPlayerCell } 502 582 … … 641 721 try 642 722 Lock; 723 // Draw cell links 724 Pen.Color := clBlack; 725 Pen.Style := psSolid; 726 Pen.Width := 3; 727 for C := 0 to Player.Game.Map.CellLinks.Count - 1 do 728 with TCellLink(Player.Game.Map.CellLinks[C]) do begin 729 if Length(Points) >= 2 then begin 730 MoveTo(View.CellToCanvasPos(Points[0])); 731 for I := 1 to Length(Points) - 1 do 732 LineTo(View.CellToCanvasPos(Points[I])); 733 end; 734 end; 735 736 // Draw cells 643 737 for C := 0 to Cells.Count - 1 do begin 644 738 Cell := TPlayerCell(Cells[C]); … … 769 863 end; 770 864 865 procedure TCells.ClearMark; 866 var 867 I: Integer; 868 begin 869 for I := 0 to Count - 1 do 870 TCell(Items[I]).Mark := False; 871 end; 872 771 873 { TPlayers } 772 874 … … 957 1059 958 1060 // Generate neighbours 959 for Y := 0 to self.FSize.Y - 1 do1061 for Y := 0 to Self.FSize.Y - 1 do 960 1062 for X := 0 to FSize.X - 1 do 961 1063 with TCell(Cells[Y * FSize.X + X]) do begin … … 1288 1390 I: Integer; 1289 1391 NewCell: TCell; 1290 NeighCells: TCellArray;1291 1392 begin 1292 1393 // Free previous … … 1313 1414 Size := Point(0, 0); 1314 1415 Image := TImage.Create(nil); 1416 CellLinks := TCellLinks.Create; 1417 Areas := TMapAreas.Create; 1315 1418 end; 1316 1419 1317 1420 destructor TMap.Destroy; 1318 1421 begin 1422 Areas.Free; 1423 CellLinks.Free; 1319 1424 Image.Free; 1320 1425 Size := Point(0, 0); … … 1467 1572 raise Exception.Create('Not allowed to substract power under zero do negative value'); 1468 1573 FPower := AValue; 1574 end; 1575 1576 procedure TCell.SetArea(AValue: TMapArea); 1577 begin 1578 if FArea = AValue then Exit; 1579 if Assigned(FArea) then FArea.Cells.Remove(Self); 1580 FArea := AValue; 1581 if Assigned(FArea) then FArea.Cells.Add(Self); 1582 end; 1583 1584 procedure TCell.AreaExtend; 1585 var 1586 I: Integer; 1587 begin 1588 for I := 0 to Neighbors.Count - 1 do 1589 with TCell(Neighbors[I]) do 1590 if (Terrain <> ttVoid) and (not Assigned(Area)) then begin 1591 Area := Self.Area; 1592 AreaExtend; 1593 end; 1469 1594 end; 1470 1595 … … 2385 2510 end; 2386 2511 2512 function TGame.SearchDifferentCellArea(List: TCells; SourceArea, DestArea: TMapArea): TCell; 2513 var 2514 NewList: TCells; 2515 NewListVoid: TCells; 2516 I: Integer; 2517 C: Integer; 2518 begin 2519 Result := nil; 2520 NewList := TCells.Create; 2521 NewList.OwnsObjects := False; 2522 NewListVoid := TCells.Create; 2523 NewListVoid.OwnsObjects := False; 2524 2525 for C := 0 to List.Count - 1 do 2526 with TCell(List[C]) do begin 2527 for I := 0 to Neighbors.Count - 1 do 2528 with TCell(Neighbors[I]) do 2529 if (not Mark) and (Terrain <> ttVoid) and (Area <> SourceArea) and ((DestArea = nil) or (DestArea = Area)) then begin 2530 NewList.Add(TCell(TCell(List[C]).Neighbors[I])); 2531 Mark := True; 2532 end else 2533 if (not Mark) and (Terrain = ttVoid) then begin 2534 NewListVoid.Add(TCell(TCell(List[C]).Neighbors[I])); 2535 Mark := True; 2536 end; 2537 end; 2538 2539 if NewList.Count > 0 then begin 2540 // We found cell with different area 2541 Result := TCell(NewList[Random(NewList.Count)]); 2542 end else 2543 if NewListVoid.Count > 0 then begin 2544 // Cell was not found but we have more void cells to check 2545 Result := SearchDifferentCellArea(NewListVoid, SourceArea, DestArea); 2546 end; 2547 2548 NewListVoid.Free; 2549 NewList.Free; 2550 end; 2551 2552 procedure TGame.BuildTerrain; 2553 var 2554 C: Integer; 2555 begin 2556 if (Map.Shape = msImage) and FileExists(MapImageFileName) and 2557 (LoadedImageFileName <> MapImageFileName) then begin 2558 LoadedImageFileName := MapImageFileName; 2559 Map.Image.Picture.LoadFromFile(MapImageFileName); 2560 end; 2561 2562 // Randomize map terrain 2563 for C := 0 to Map.Cells.Count - 1 do 2564 with TCell(Map.Cells[C]) do begin 2565 if (VoidEnabled and (Random < VoidPercentage / 100)) or 2566 (Map.IsOutsideShape(PosPx)) then Terrain := ttVoid 2567 else begin 2568 if CityEnabled and (Random < CityPercentage / 100) then Terrain := ttCity 2569 else Terrain := ttNormal; 2570 end; 2571 Power := Random(MaxNeutralUnits + 1); 2572 Player := nil; 2573 end; 2574 end; 2575 2576 procedure TGame.BuildBridges; 2577 var 2578 List: TCells; 2579 Cell: TCell; 2580 FoundCell1: TCell; 2581 FoundCell2: TCell; 2582 I: Integer; 2583 J: Integer; 2584 NewLink: TCellLink; 2585 begin 2586 // Build area bridges 2587 if Map.Areas.Count > 1 then 2588 for I := 0 to Map.Areas.Count - 1 do 2589 with TMapArea(Map.Areas[I]) do begin 2590 List := TCells.Create; 2591 List.OwnsObjects := False; 2592 GetBorderCells(List); 2593 Cell := TCell(List[Random(List.Count)]); 2594 List.Clear; 2595 List.Add(Cell); 2596 2597 Map.Cells.ClearMark; 2598 2599 // Find nearest cell with different area 2600 FoundCell1 := SearchDifferentCellArea(List, TMapArea(Map.Areas[I]), nil); 2601 if Assigned(FoundCell1) then begin 2602 // Again find back nearest cell with different area. 2603 // This will ensure that both cells are closest ones 2604 2605 Map.Cells.ClearMark; 2606 List[0] := FoundCell1; 2607 FoundCell2 := SearchDifferentCellArea(List, FoundCell1.Area, TMapArea(Map.Areas[I])); 2608 if Assigned(FoundCell2) then begin 2609 FoundCell1.Neighbors.Add(FoundCell2); 2610 FoundCell2.Neighbors.Add(FoundCell1); 2611 NewLink := TCellLink.Create; 2612 SetLength(NewLink.Points, 2); 2613 NewLink.Cell1 := FoundCell2; 2614 NewLink.Points[0] := FoundCell2.PosPx; 2615 NewLink.Cell2 := FoundCell1; 2616 NewLink.Points[1] := FoundCell1.PosPx; 2617 Map.CellLinks.Add(NewLink); 2618 Inc(BridgeCount); 2619 end; 2620 end; 2621 2622 List.Free; 2623 end; 2624 end; 2625 2626 procedure TGame.BuildMapAreas; 2627 var 2628 C: Integer; 2629 NewArea: TMapArea; 2630 begin 2631 for C := 0 to Map.Cells.Count - 1 do 2632 with TCell(Map.Cells[C]) do 2633 Area := nil; 2634 Map.Areas.Clear; 2635 for C := 0 to Map.Cells.Count - 1 do 2636 with TCell(Map.Cells[C]) do 2637 if (Terrain <> ttVoid) and (not Assigned(Area)) then begin 2638 NewArea := TMapArea(Map.Areas[Map.Areas.Add(TMapArea.Create)]); 2639 NewArea.Id := Map.Areas.Count; 2640 NewArea.Map := Map; 2641 Area := NewArea; 2642 AreaExtend; 2643 end; 2644 end; 2645 2387 2646 procedure TGame.SaveConfig(Config: TXmlConfig; Path: string); 2388 2647 begin … … 2399 2658 SetValue(Path + '/CityEnabled', CityEnabled); 2400 2659 SetValue(Path + '/CityPercentage', CityPercentage); 2660 SetValue(Path + '/BridgeEnabled', BridgeEnabled); 2401 2661 SetValue(Path + '/GrowAmount', Integer(GrowAmount)); 2402 2662 SetValue(Path + '/GrowCells', Integer(GrowCells)); … … 2421 2681 CityEnabled := GetValue(Path + '/CityEnabled', False); 2422 2682 CityPercentage := GetValue(Path + '/CityPercentage', 10); 2683 BridgeEnabled := GetValue(Path + '/BridgeEnabled', True); 2423 2684 GrowAmount := TGrowAmount(GetValue(Path + '/GrowAmount', Integer(gaBySquareRoot))); 2424 2685 GrowCells := TGrowCells(GetValue(Path + '/GrowCells', Integer(gcPlayerAll))); … … 2450 2711 CityEnabled := ReadBoolean(RootNode, 'CityEnabled', False); 2451 2712 CityPercentage := ReadInteger(RootNode, 'CityPercentage', 0); 2713 BridgeEnabled := ReadBoolean(RootNode, 'BridgeEnabled', False); 2452 2714 TurnCounter := ReadInteger(RootNode, 'TurnCounter', 0); 2453 2715 WinObjective := TWinObjective(ReadInteger(RootNode, 'WinObjective', Integer(woDefeatAllOponents))); … … 2503 2765 WriteBoolean(RootNode, 'CityEnabled', CityEnabled); 2504 2766 WriteInteger(RootNode, 'CityPercentage', CityPercentage); 2767 WriteBoolean(RootNode, 'BridgeEnabled', BridgeEnabled); 2505 2768 WriteInteger(RootNode, 'TurnCounter', TurnCounter); 2506 2769 WriteInteger(RootNode, 'WinObjective', Integer(WinObjective)); … … 2655 2918 Counter: Integer; 2656 2919 C: Integer; 2920 LastAreaCount: Integer; 2657 2921 begin 2658 2922 FileName := SNewGameFile; 2659 2923 TurnCounter := 1; 2660 2924 Moves.Clear; 2661 if (Map.Shape = msImage) and FileExists(MapImageFileName) and 2662 (LoadedImageFileName <> MapImageFileName) then begin 2663 LoadedImageFileName := MapImageFileName; 2664 Map.Image.Picture.LoadFromFile(MapImageFileName); 2665 end; 2666 for C := 0 to Map.Cells.Count - 1 do 2667 with TCell(Map.Cells[C]) do begin 2668 if (VoidEnabled and (Random < VoidPercentage / 100)) or 2669 (Map.IsOutsideShape(PosPx)) then Terrain := ttVoid 2670 else begin 2671 if CityEnabled and (Random < CityPercentage / 100) then Terrain := ttCity 2672 else Terrain := ttNormal; 2673 end; 2674 Power := Random(MaxNeutralUnits + 1); 2675 Player := nil; 2925 2926 BuildTerrain; 2927 if BridgeEnabled then begin 2928 // Connect all areas to all cells be accessible 2929 for I := 0 to Map.CellLinks.Count - 1 do 2930 with TCellLink(Map.CellLinks[I]) do begin 2931 Cell1.Neighbors.Remove(Cell2); 2932 Cell2.Neighbors.Remove(Cell1); 2933 end; 2934 Map.CellLinks.Clear; 2935 BuildMapAreas; 2936 LastAreaCount := -1; 2937 while (Map.Areas.Count > 1) and (Map.Areas.Count <> LastAreaCount) do begin 2938 LastAreaCount := Map.Areas.Count; 2939 BuildBridges; 2940 BuildMapAreas; 2941 end; 2676 2942 end; 2677 2943 … … 2819 3085 try 2820 3086 Lock; 3087 3088 // Draw cell links 3089 Pen.Color := clBlack; 3090 Pen.Style := psSolid; 3091 Pen.Width := 3; 3092 for C := 0 to CellLinks.Count - 1 do 3093 with TCellLink(CellLinks[C]) do begin 3094 if Length(Points) >= 2 then begin 3095 MoveTo(Points[0]); 3096 for I := 1 to Length(Points) - 1 do 3097 LineTo(Points[I]); 3098 end; 3099 end; 3100 3101 // Draw cells 2821 3102 for C := 0 to Cells.Count - 1 do begin 2822 3103 Cell := TCell(Cells[C]);
Note:
See TracChangeset
for help on using the changeset viewer.