Changeset 548
- Timestamp:
- Apr 21, 2024, 10:57:18 AM (7 months ago)
- Location:
- trunk
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/AI/StdAI/AI.pas
r531 r548 231 231 else 232 232 begin 233 Quality := trunc(100 * (ln(mi.Attack) + ln(mi.Defense) +234 ln(mi.Speed / 150) * 1.7 - ln(mi.Cost)));233 Quality := Trunc(100 * (Ln(mi.Attack) + Ln(mi.Defense) + 234 Ln(mi.Speed / 150) * 1.7 - Ln(mi.Cost))); 235 235 if mi.Cap and (1 shl (mcFanatic - mcFirstNonCap)) <> 0 then 236 Inc(Quality, trunc(100 * ln(1.5)));236 Inc(Quality, Trunc(100 * Ln(1.5))); 237 237 if mi.Cap and (1 shl (mcLongRange - mcFirstNonCap)) <> 0 then 238 Inc(Quality, trunc(100 * ln(1.5)));238 Inc(Quality, Trunc(100 * Ln(1.5))); 239 239 end; 240 240 end … … 242 242 begin 243 243 Category := mctGroundDefender; 244 Quality := trunc(100 * (ln(mi.Defense) - ln(mi.Cost) * 0.6));244 Quality := Trunc(100 * (Ln(mi.Defense) - Ln(mi.Cost) * 0.6)); 245 245 if mi.Cap and (1 shl (mcFanatic - mcFirstNonCap)) <> 0 then 246 Inc(Quality, trunc(100 * ln(1.5)));246 Inc(Quality, Trunc(100 * Ln(1.5))); 247 247 end; 248 248 dSea: … … 257 257 if EffectiveTransport > 4 then 258 258 EffectiveTransport := 4; // rarely used more 259 Quality := 100 + trunc(100 * (ln(EffectiveTransport) +260 ln(mi.Speed / 150) + ln(mi.Defense) - ln(mi.Cost)));259 Quality := 100 + Trunc(100 * (Ln(EffectiveTransport) + 260 Ln(mi.Speed / 150) + Ln(mi.Defense) - Ln(mi.Cost))); 261 261 if mi.Cap and (1 shl (mcNav - mcFirstNonCap)) <> 0 then 262 Inc(Quality, trunc(100 * ln(1.5)));262 Inc(Quality, Trunc(100 * Ln(1.5))); 263 263 if mi.Cap and (1 shl (mcAirDef - mcFirstNonCap)) <> 0 then 264 Inc(Quality, trunc(100 * ln(1.3)));264 Inc(Quality, Trunc(100 * Ln(1.3))); 265 265 end; 266 266 end … … 272 272 else 273 273 begin 274 Quality := trunc(100 * (ln(mi.Attack) + ln(mi.Defense) * 0.6 - ln(mi.Cost)));274 Quality := Trunc(100 * (Ln(mi.Attack) + Ln(mi.Defense) * 0.6 - Ln(mi.Cost))); 275 275 if mi.Cap and (1 shl (mcNav - mcFirstNonCap)) <> 0 then 276 Inc(Quality, trunc(100 * ln(1.4)));276 Inc(Quality, Trunc(100 * Ln(1.4))); 277 277 if mi.Cap and (1 shl (mcAirDef - mcFirstNonCap)) <> 0 then 278 Inc(Quality, trunc(100 * ln(1.3)));278 Inc(Quality, Trunc(100 * Ln(1.3))); 279 279 if mi.Cap and (1 shl (mcLongRange - mcFirstNonCap)) <> 0 then 280 Inc(Quality, trunc(100 * ln(2.0)));280 Inc(Quality, Trunc(100 * Ln(2.0))); 281 281 if mi.Cap and (1 shl (mcRadar - mcFirstNonCap)) <> 0 then 282 Inc(Quality, trunc(100 * ln(1.5)));282 Inc(Quality, Trunc(100 * Ln(1.5))); 283 283 end; 284 284 end; -
trunk/AI/StdAI/ToolAI.pas
r531 r548 197 197 X := Loc - Y * G.lx; 198 198 Inc(sy, Y); 199 A := 2 * pi * X / G.lx;200 su := su + cos(A);201 sv := sv + sin(A);199 A := 2 * Pi * X / G.lx; 200 su := su + Cos(A); 201 sv := sv + Sin(A); 202 202 Inc(N); 203 203 end; 204 204 end; 205 A := arctan2(sv, su);206 X := round(G.lx * A / (2 * pi));205 A := ArcTan2(sv, su); 206 X := Round(G.lx * A / (2 * Pi)); 207 207 while X >= G.lx do 208 208 Dec(X, G.lx); -
trunk/CityProcessing.pas
r522 r548 223 223 RelCorr := Dist / MaxDist; 224 224 if CorrLevel[RW[P].Government] > 1 then 225 RelCorr := Exp( ln(RelCorr) / CorrLevel[RW[P].Government]);225 RelCorr := Exp(Ln(RelCorr) / CorrLevel[RW[P].Government]); 226 226 if Built[imCourt] = 1 then 227 227 RelCorr := RelCorr / 2; … … 1628 1628 begin 1629 1629 if Value > 0 then 1630 Value := ln(Value) + 123;1630 Value := Ln(Value) + 123; 1631 1631 for I := oFood to oScience do 1632 1632 if ValueFormula_Multiply[I] and (Output[I] > 0) then 1633 1633 Value := Value + ValueFormula_Weight[I] * 1634 ( ln(Output[I]) + 123);1634 (Ln(Output[I]) + 123); 1635 1635 end; 1636 1636 -
trunk/Database.pas
r531 r548 262 262 begin 263 263 c0 := TechFormula_M[diff] * (nTech + 4) * 264 exp((nTech + 4) / TechFormula_D[diff]);264 Exp((nTech + 4) / TechFormula_D[diff]); 265 265 if c0 >= $10000000 then 266 266 Result := $10000000 267 267 else 268 Result := trunc(c0);268 Result := Trunc(c0); 269 269 end; 270 270 … … 652 652 Result := 0; 653 653 for I := 1 to D do 654 Result := Result + sin(f1[I] * ((X * 2 + Y and 1) * sa[I] + Y * 1.5 *654 Result := Result + Sin(f1[I] * ((X * 2 + Y and 1) * sa[I] + Y * 1.5 * 655 655 ca[I])) * f2[I]; 656 656 { x values effectively multiplied with 2 to get 2 horizantal periods … … 662 662 begin 663 663 {$IFNDEF SCR} if X = 1 then 664 V := pi / 2 { first wave goes horizontal }665 else {$ENDIF} V := DelphiRandom * 2 * pi;666 sa[X] := sin(V) / lx;667 ca[X] := cos(V) / ly;668 f1[X] := 2 * pi * exp(Detail * (X - 1));669 f2[X] := exp(-X * Smooth);664 V := Pi / 2 { first wave goes horizontal } 665 else {$ENDIF} V := DelphiRandom * 2 * Pi; 666 sa[X] := Sin(V) / lx; 667 ca[X] := Cos(V) / ly; 668 f1[X] := 2 * Pi * Exp(Detail * (X - 1)); 669 f2[X] := Exp(-X * Smooth); 670 670 end; 671 671 … … 679 679 if X * 2 < imerge then 680 680 V := (X * 2 * V + (imerge - X * 2) * Value(X + lx, Y)) / imerge; 681 V := V - sqr(sqr(2 * Y / ly - 1)); { soft cut at poles }681 V := V - Sqr(Sqr(2 * Y / ly - 1)); { soft cut at poles } 682 682 if V > maxv then 683 683 maxv := V; … … 705 705 I := A; 706 706 A := B; 707 B := I 707 B := I; 708 708 end; 709 709 if A > B then … … 763 763 // must be done after FindContinents 764 764 var 765 I, J, Cnt, X, Y, dx, dy, Loc0, Loc1, xworst, yworst, totalrare, RareMaxWater,765 I, J, Cnt, X, Y, dx, dy, Loc0, Loc1, xworst, yworst, TotalRare, RareMaxWater, 766 766 RareType, iBest, jbest, MinDist, xBlock, yBlock, V8: Integer; 767 767 AreaCount, RareByArea, RareAdjacent: array [0 .. 7, 0 .. 4] of Integer; … … 804 804 end; 805 805 end; 806 totalrare := 0;806 TotalRare := 0; 807 807 for X := 0 to 7 do 808 808 for Y := 0 to 4 do 809 809 if AreaCount[X, Y] > 0 then 810 Inc( totalrare);810 Inc(TotalRare); 811 811 Inc(RareMaxWater); 812 until totalrare >= 12;813 814 while totalrare > 12 do812 until TotalRare >= 12; 813 814 while TotalRare > 12 do 815 815 begin // remove rarebyarea resources too close to each other 816 816 FillChar(RareAdjacent, SizeOf(RareAdjacent), 0); … … 876 876 end; 877 877 AreaCount[xworst, yworst] := 0; 878 Dec( totalrare);878 Dec(TotalRare); 879 879 end; 880 880 -
trunk/LocalPlayer/Battle.pas
r505 r548 169 169 170 170 IsoMap.SetOutput(Buffer); 171 BitBltCanvas(Buffer.Canvas, 0, 0, 66, 48, ca, xm + 8 + 4,172 171 UnshareBitmap(Buffer); 172 BitBltCanvas(Buffer.Canvas, 0, 0, 66, 48, ca, xm + 8 + 4, ym - 8 - 12 - 48); 173 173 { if TerrType<fForest then 174 174 Sprite(Buffer,HGrTerrain,0,16,66,32,1+TerrType*(xxt*2+1),1+yyt) … … 181 181 end; } 182 182 IsoMap.PaintUnit(1, 0, UnitInfo, 0); 183 BitBltCanvas(ca, xm + 8 + 4, ym - 8 - 12 - 48, 66, 48, Buffer.Canvas, 184 0, 0); 185 186 BitBltCanvas(Buffer.Canvas, 0, 0, 66, 48, ca, xm - 8 - 4 - 66, 187 ym + 8 + 12); 183 BitBltCanvas(ca, xm + 8 + 4, ym - 8 - 12 - 48, 66, 48, Buffer.Canvas, 0, 0); 184 185 UnshareBitmap(Buffer); 186 BitBltCanvas(Buffer.Canvas, 0, 0, 66, 48, ca, xm - 8 - 4 - 66, ym + 8 + 12); 188 187 MakeUnitInfo(Me, MyUn[uix], UnitInfo); 189 188 UnitInfo.Flags := UnitInfo.Flags and not unFortified; -
trunk/LocalPlayer/CityScreen.pas
r536 r548 1366 1366 and (Y >= ymOpt - 32) and (Y < ymOpt + 32) then 1367 1367 begin 1368 I := sqr(X - xmOpt) + sqr(Y - ymOpt); // click radius1368 I := Sqr(X - xmOpt) + Sqr(Y - ymOpt); // click radius 1369 1369 if I <= 32 * 32 then 1370 1370 begin … … 1375 1375 I := 3 // rwGrowth 1376 1376 else 1377 case trunc(arctan2(X - xmOpt, ymOpt - Y) * 180 / pi) of1377 case Trunc(ArcTan2(X - xmOpt, ymOpt - Y) * 180 / Pi) of 1378 1378 - 25 - 52 * 2 .. -26 - 52: 1379 1379 I := 1; -
trunk/LocalPlayer/IsoEngine.pas
r538 r548 36 36 Diry: array [0..7] of Integer = (-1, 0, 1, 2, 1, 0, -1, -2); 37 37 procedure CityGrid(xm, ym: Integer; CityAllowClick: Boolean); 38 procedure ClippedLine(X, Y, dx0, dy0: Integer; Mirror: Boolean); 38 39 function IsShoreTile(Loc: Integer): Boolean; 39 40 procedure MakeDark(Line: PPixelPointer; Length: Integer); … … 1053 1054 CityInfo: TCityInfo; 1054 1055 UnitInfo: TUnitInfo; 1055 fog: Boolean;1056 Fog: Boolean; 1056 1057 SpecialRow: Integer; 1057 1058 SpecialCol: Integer; … … 1192 1193 1193 1194 if moEditMode in MapOptions then 1194 fog := (Loc < 0) or (Loc >= G.lx * G.ly)1195 // else if CityLoc >=0 then1196 // fog:= (Loc<0) or (Loc>=G.lx*G.ly) or (Distance(Loc,CityLoc)>5)1195 Fog := (Loc < 0) or (Loc >= G.lx * G.ly) 1196 // else if CityLoc >= 0 then 1197 // Fog:= (Loc < 0) or (Loc >= G.lx * G.ly) or (Distance(Loc, CityLoc) > 5) 1197 1198 else if ShowGrWall then 1198 fog := Tile and fGrWall = 01199 Fog := Tile and fGrWall = 0 1199 1200 else 1200 fog := FoW and (Tile and fObserved = 0);1201 if fog and ShowObjects then1201 Fog := FoW and (Tile and fObserved = 0); 1202 if Fog and ShowObjects then 1202 1203 if Loc < -G.lx then 1203 1204 Sprite(HGrTerrain, X, Y + yyt, xxt * 2, yyt, 1 + 6 * (xxt * 2 + 1), … … 1298 1299 end; 1299 1300 1301 procedure TIsoMap.ClippedLine(X, Y, dx0, dy0: Integer; Mirror: Boolean); 1302 var 1303 x0, x1, dxmin, dymin, dxmax, dymax, N: Integer; 1304 begin 1305 with FOutput.Canvas do 1306 begin 1307 dxmin := (FLeft - X) div xxt; 1308 dymin := (RealTop - Y) div yyt; 1309 dxmax := (FRight - X - 1) div xxt + 1; 1310 dymax := (RealBottom - Y - 1) div yyt + 1; 1311 N := dymax - dy0; 1312 if Mirror then 1313 begin 1314 if dx0 - dxmin < N then 1315 N := dx0 - dxmin; 1316 if dx0 > dxmax then 1317 begin 1318 N := N - (dx0 - dxmax); 1319 dy0 := dy0 + (dx0 - dxmax); 1320 dx0 := dxmax; 1321 end; 1322 if dy0 < dymin then 1323 begin 1324 N := N - (dymin - dy0); 1325 dx0 := dx0 - (dymin - dy0); 1326 dy0 := dymin; 1327 end; 1328 end 1329 else 1330 begin 1331 if dxmax - dx0 < N then 1332 N := dxmax - dx0; 1333 if dx0 < dxmin then 1334 begin 1335 N := N - (dxmin - dx0); 1336 dy0 := dy0 + (dxmin - dx0); 1337 dx0 := dxmin; 1338 end; 1339 if dy0 < dymin then 1340 begin 1341 N := N - (dymin - dy0); 1342 dx0 := dx0 + (dymin - dy0); 1343 dy0 := dymin; 1344 end; 1345 end; 1346 if N <= 0 then 1347 Exit; 1348 if Mirror then 1349 begin 1350 x0 := X + dx0 * xxt - 1; 1351 x1 := X + (dx0 - N) * xxt - 1; 1352 end 1353 else 1354 begin 1355 x0 := X + dx0 * xxt; 1356 x1 := X + (dx0 + N) * xxt; 1357 end; 1358 MoveTo(x0, Y + dy0 * yyt); 1359 LineTo(x1, Y + (dy0 + N) * yyt); 1360 end; 1361 end; 1362 1300 1363 procedure TIsoMap.PaintGrid(X, Y, nx, ny: Integer); 1301 1302 procedure ClippedLine(dx0, dy0: Integer; Mirror: Boolean);1303 var1304 x0, x1, dxmin, dymin, dxmax, dymax, N: Integer;1305 begin1306 with FOutput.Canvas do1307 begin1308 dxmin := (FLeft - X) div xxt;1309 dymin := (RealTop - Y) div yyt;1310 dxmax := (FRight - X - 1) div xxt + 1;1311 dymax := (RealBottom - Y - 1) div yyt + 1;1312 N := dymax - dy0;1313 if Mirror then1314 begin1315 if dx0 - dxmin < N then1316 N := dx0 - dxmin;1317 if dx0 > dxmax then1318 begin1319 N := N - (dx0 - dxmax);1320 dy0 := dy0 + (dx0 - dxmax);1321 dx0 := dxmax;1322 end;1323 if dy0 < dymin then1324 begin1325 N := N - (dymin - dy0);1326 dx0 := dx0 - (dymin - dy0);1327 dy0 := dymin;1328 end;1329 end1330 else1331 begin1332 if dxmax - dx0 < N then1333 N := dxmax - dx0;1334 if dx0 < dxmin then1335 begin1336 N := N - (dxmin - dx0);1337 dy0 := dy0 + (dxmin - dx0);1338 dx0 := dxmin;1339 end;1340 if dy0 < dymin then1341 begin1342 N := N - (dymin - dy0);1343 dx0 := dx0 + (dymin - dy0);1344 dy0 := dymin;1345 end;1346 end;1347 if N <= 0 then1348 Exit;1349 if Mirror then1350 begin1351 x0 := X + dx0 * xxt - 1;1352 x1 := X + (dx0 - N) * xxt - 1;1353 end1354 else1355 begin1356 x0 := X + dx0 * xxt;1357 x1 := X + (dx0 + N) * xxt;1358 end;1359 MoveTo(x0, Y + dy0 * yyt);1360 LineTo(x1, Y + (dy0 + N) * yyt);1361 end;1362 end;1363 1364 1364 var 1365 1365 I: Integer; 1366 1366 begin 1367 FOutput.Canvas. pen.Color := $000000; // $FF shl (8 * Random(3));1367 FOutput.Canvas.Pen.Color := $000000; // $FF shl (8 * Random(3)); 1368 1368 for I := 0 to nx div 2 do 1369 ClippedLine( I * 2, 0, False);1369 ClippedLine(X, Y, I * 2, 0, False); 1370 1370 for I := 1 to (nx + 1) div 2 do 1371 ClippedLine( I * 2, 0, True);1371 ClippedLine(X, Y, I * 2, 0, True); 1372 1372 for I := 0 to ny div 2 do 1373 1373 begin 1374 ClippedLine( 0, 2 * I + 2, False);1375 ClippedLine( nx + 1, 2 * I + 1 + nx and 1, True);1374 ClippedLine(X, Y, 0, 2 * I + 2, False); 1375 ClippedLine(X, Y, nx + 1, 2 * I + 1 + nx and 1, True); 1376 1376 end; 1377 1377 end; … … 1425 1425 if Abs(y_n) < rShade then begin 1426 1426 // Darken left and right parts of elipsis 1427 w_n := sqrt(sqr(rShade) - sqr(y_n));1428 wBright := trunc(w_n * xxt + 0.5);1427 w_n := Sqrt(Sqr(rShade) - Sqr(y_n)); 1428 wBright := Trunc(w_n * xxt + 0.5); 1429 1429 Line.SetX(0); 1430 1430 MakeDark(@Line, ScaleToNative(xm - wBright)); -
trunk/LocalPlayer/Wonders.pas
r530 r548 88 88 const 89 89 Darken = 24; 90 // space =pi/120;90 // space = Pi / 120; 91 91 amax0 = 15734; // 1 shl 16*tan(pi/12-space); 92 92 amin1 = 19413; // 1 shl 16*tan(pi/12+space); -
trunk/NoTerm.pas
r531 r548 359 359 if TotalStatTime > 0 then 360 360 begin 361 TimeShare := trunc(TimeStat[I] / TotalStatTime * 100 + 0.5);361 TimeShare := Trunc(TimeStat[I] / TotalStatTime * 100 + 0.5); 362 362 RisedTextOut(Canvas, xBrain[I] + 34 + 16, yBrain[I] + 51 + 16, 363 363 IntToStr(TimeShare) + '%'); -
trunk/Packages/CevoComponents/ButtonA.pas
r531 r548 12 12 private 13 13 FCaption: string; 14 procedure SetCaption(Text: string); 14 procedure SetCaption(Text: string); override; 15 15 procedure SetFont(const Font: TFont); 16 16 protected -
trunk/Packages/CevoComponents/CevoComponents.lpk
r468 r548 31 31 <Other> 32 32 <CompilerMessages> 33 <IgnoredMessages idx 5024="True"/>33 <IgnoredMessages idx6058="True" idx5024="True"/> 34 34 </CompilerMessages> 35 35 </Other> -
trunk/Packages/CevoComponents/ScreenTools.pas
r538 r548 542 542 OriginalColor := DataPixel.PixelARGB and $FFFFFF; 543 543 if (OriginalColor = TransparentColor1) or (OriginalColor = TransparentColor2) then begin 544 MaskPixel.PixelR := $FF; 545 MaskPixel.PixelG := $FF; 546 MaskPixel.PixelB := $FF; 547 DataPixel.PixelR := 0; 548 DataPixel.PixelG := 0; 549 DataPixel.PixelB := 0; 544 MaskPixel.PixelRGB := $ffffff; 545 DataPixel.PixelRGB := 0; 550 546 end else begin 551 MaskPixel.PixelR := 0; 552 MaskPixel.PixelG := 0; 553 MaskPixel.PixelB := 0; 547 MaskPixel.PixelRGB := 0; 554 548 end; 555 549 DataPixel.NextPixel; … … 1023 1017 if X < 0 then 1024 1018 if Y < 0 then 1025 R := round(sqrt(sqr(X) + sqr(Y)))1019 R := Round(Sqrt(Sqr(X) + Sqr(Y))) 1026 1020 else if Y >= Height then 1027 R := round(sqrt(sqr(X) + sqr(Y - (Height - 1))))1021 R := Round(Sqrt(Sqr(X) + Sqr(Y - (Height - 1)))) 1028 1022 else 1029 1023 R := -X 1030 1024 else if X >= Width then 1031 1025 if Y < 0 then 1032 R := round(sqrt(sqr(X - (Width - 1)) + sqr(Y)))1026 R := Round(sqrt(Sqr(X - (Width - 1)) + Sqr(Y))) 1033 1027 else if Y >= Height then 1034 R := round(sqrt(sqr(X - (Width - 1)) + sqr(Y - (Height - 1))))1028 R := Round(Sqrt(Sqr(X - (Width - 1)) + Sqr(Y - (Height - 1)))) 1035 1029 else 1036 1030 R := X - (Width - 1) … … 1631 1625 TexWidth, TexHeight: Integer; 1632 1626 begin 1633 // texturize background1627 // Texturize background 1634 1628 Dest.BeginUpdate; 1635 1629 TexWidth := Texture.Width; … … 1639 1633 for Y := 0 to ScaleToNative(Dest.Height) - 1 do begin 1640 1634 for X := 0 to ScaleToNative(Dest.Width) - 1 do begin 1641 if (DstPixel.PixelARGB and $FFFFFF)= TransparentColor then begin1635 if DstPixel.PixelRGB = TransparentColor then begin 1642 1636 SrcPixel.SetXY(X mod TexWidth, Y mod TexHeight); 1643 DstPixel.PixelB := SrcPixel.PixelB; 1644 DstPixel.PixelG := SrcPixel.PixelG; 1645 DstPixel.PixelR := SrcPixel.PixelR; 1637 DstPixel.PixelRGB := SrcPixel.PixelRGB; 1646 1638 end; 1647 1639 DstPixel.NextPixel; -
trunk/Packages/DpiControls/Dpi.Graphics.pas
r546 r548 290 290 public 291 291 NativeBitmap: Graphics.TBitmap; 292 procedure BeginUpdate;293 procedure EndUpdate;294 292 constructor Create; override; 295 293 destructor Destroy; override; … … 337 335 published 338 336 procedure LoadFromFile(FileName: string); 339 property Bitm pa: TBitmap read FBitmap write SetBitmap;337 property Bitmap: TBitmap read FBitmap write SetBitmap; 340 338 end; 341 339 … … 713 711 DstPixelWidth := ScaleToNative(XX + 1) - ScaleToNative(XX); 714 712 for DstPixelX := 0 to DstPixelWidth - 1 do begin 715 DstPtr.PixelB := SrcPtr.PixelB; 716 DstPtr.PixelG := SrcPtr.PixelG; 717 DstPtr.PixelR := SrcPtr.PixelR; 713 DstPtr.PixelRGB := SrcPtr.PixelRGB; 718 714 DstPtr.NextPixel; 719 715 end; … … 819 815 end; 820 816 821 procedure TBitmap.BeginUpdate;822 begin823 GetNativeBitmap.BeginUpdate;824 end;825 826 procedure TBitmap.EndUpdate;827 begin828 GetNativeBitmap.EndUpdate;829 end;830 831 817 constructor TBitmap.Create; 832 818 begin -
trunk/Packages/DpiControls/DpiControls.lpk
r482 r548 30 30 <Other> 31 31 <CompilerMessages> 32 <IgnoredMessages idx 3123="True"/>32 <IgnoredMessages idx6058="True" idx3123="True"/> 33 33 </CompilerMessages> 34 34 </Other>
Note:
See TracChangeset
for help on using the changeset viewer.