18 |
18 |
19 {$INCLUDE "options.inc"} |
19 {$INCLUDE "options.inc"} |
20 |
20 |
21 unit uLand; |
21 unit uLand; |
22 interface |
22 interface |
23 uses SDLh, uLandTemplates, uFloat, uConsts, GLunit; |
23 uses SDLh, uLandTemplates, uFloat, uConsts, GLunit, uTypes; |
24 |
|
25 type |
|
26 TLandArray = packed array of array of LongWord; |
|
27 TCollisionArray = packed array of array of Word; |
|
28 TPreview = packed array[0..127, 0..31] of byte; |
|
29 TDirtyTag = packed array of array of byte; |
|
30 |
|
31 var Land: TCollisionArray; |
|
32 LandPixels: TLandArray; |
|
33 LandDirty: TDirtyTag; |
|
34 hasBorder: boolean; |
|
35 hasGirders: boolean; |
|
36 isMap: boolean; |
|
37 playHeight, playWidth, leftX, rightX, topY, MaxHedgehogs: Longword; // idea is that a template can specify height/width. Or, a map, a height/width by the dimensions of the image. If the map has pixels near top of image, it triggers border. |
|
38 LandBackSurface: PSDL_Surface; |
|
39 digest: shortstring; |
|
40 |
24 |
41 type direction = record x, y: LongInt; end; |
25 type direction = record x, y: LongInt; end; |
42 const DIR_N: direction = (x: 0; y: -1); |
26 const DIR_N: direction = (x: 0; y: -1); |
43 DIR_E: direction = (x: 1; y: 0); |
27 DIR_E: direction = (x: 1; y: 0); |
44 DIR_S: direction = (x: 0; y: 1); |
28 DIR_S: direction = (x: 0; y: 1); |
46 |
30 |
47 procedure initModule; |
31 procedure initModule; |
48 procedure freeModule; |
32 procedure freeModule; |
49 procedure GenMap; |
33 procedure GenMap; |
50 function GenPreview: TPreview; |
34 function GenPreview: TPreview; |
51 procedure CheckLandDigest(s: shortstring); |
|
52 function LandBackPixel(x, y: LongInt): LongWord; |
|
53 |
35 |
54 implementation |
36 implementation |
55 uses uConsole, uStore, uMisc, uRandom, uTeams, uLandObjects, Adler32, uIO, uLandTexture, sysutils; |
37 uses uConsole, uStore, uRandom, uLandObjects, uIO, uLandTexture, sysutils, |
|
38 uVariables, uUtils, uCommands, Adler32, uDebug, uLandPainted; |
56 |
39 |
57 operator=(const a, b: direction) c: Boolean; |
40 operator=(const a, b: direction) c: Boolean; |
58 begin |
41 begin |
59 c := (a.x = b.x) and (a.y = b.y); |
42 c := (a.x = b.x) and (a.y = b.y); |
60 end; |
43 end; |
61 |
44 |
62 type TPixAr = record |
45 type TPixAr = record |
63 Count: Longword; |
46 Count: Longword; |
64 ar: array[0..Pred(cMaxEdgePoints)] of TPoint; |
47 ar: array[0..Pred(cMaxEdgePoints)] of TPoint; |
65 end; |
48 end; |
66 |
|
67 procedure LogLandDigest; |
|
68 var s: shortstring; |
|
69 adler, i: LongInt; |
|
70 begin |
|
71 adler:= 1; |
|
72 for i:= 0 to LAND_HEIGHT-1 do |
|
73 Adler32Update(adler, @Land[i,0], LAND_WIDTH); |
|
74 s:= 'M'+inttostr(adler); |
|
75 |
|
76 CheckLandDigest(s); |
|
77 SendIPCRaw(@s[0], Length(s) + 1) |
|
78 end; |
|
79 |
|
80 procedure CheckLandDigest(s: shortstring); |
|
81 begin |
|
82 {$IFDEF DEBUGFILE} |
|
83 AddFileLog('CheckLandDigest: ' + s + ' digest : ' + digest); |
|
84 {$ENDIF} |
|
85 if digest = '' then |
|
86 digest:= s |
|
87 else |
|
88 TryDo(s = digest, 'Different maps generated, sorry', true); |
|
89 end; |
|
90 |
49 |
91 procedure DrawLine(X1, Y1, X2, Y2: LongInt; Color: Longword); |
50 procedure DrawLine(X1, Y1, X2, Y2: LongInt; Color: Longword); |
92 var |
51 var |
93 eX, eY, dX, dY: LongInt; |
52 eX, eY, dX, dY: LongInt; |
94 i, sX, sY, x, y, d: LongInt; |
53 i, sX, sY, x, y, d: LongInt; |
546 procedure GenBlank(var Template: TEdgeTemplate); |
494 procedure GenBlank(var Template: TEdgeTemplate); |
547 var pa: TPixAr; |
495 var pa: TPixAr; |
548 i: Longword; |
496 i: Longword; |
549 y, x: Longword; |
497 y, x: Longword; |
550 begin |
498 begin |
551 for y:= 0 to LAND_HEIGHT - 1 do |
|
552 for x:= 0 to LAND_WIDTH - 1 do |
|
553 Land[y, x]:= lfBasic; |
|
554 |
|
555 {$HINTS OFF} |
|
556 SetPoints(Template, pa); |
|
557 {$HINTS ON} |
|
558 for i:= 1 to Template.BezierizeCount do |
|
559 begin |
|
560 BezierizeEdge(pa, _0_5); |
|
561 RandomizePoints(pa); |
|
562 RandomizePoints(pa) |
|
563 end; |
|
564 for i:= 1 to Template.RandPassesCount do RandomizePoints(pa); |
|
565 BezierizeEdge(pa, _0_1); |
|
566 |
|
567 DrawEdge(pa, 0); |
|
568 |
|
569 with Template do |
|
570 for i:= 0 to pred(FillPointsCount) do |
|
571 with FillPoints^[i] do |
|
572 FillLand(x, y); |
|
573 |
|
574 DrawEdge(pa, lfBasic); |
|
575 |
|
576 MaxHedgehogs:= Template.MaxHedgehogs; |
|
577 hasGirders:= Template.hasGirders; |
|
578 playHeight:= Template.TemplateHeight; |
|
579 playWidth:= Template.TemplateWidth; |
|
580 leftX:= ((LAND_WIDTH - playWidth) div 2); |
|
581 rightX:= (playWidth + ((LAND_WIDTH - playWidth) div 2)) - 1; |
|
582 topY:= LAND_HEIGHT - playHeight; |
|
583 |
|
584 // force to only cavern even if a cavern map is invertable if cTemplateFilter = 4 ? |
|
585 if (cTemplateFilter = 4) or |
|
586 (Template.canInvert and (getrandom(2) = 0)) or |
|
587 (not Template.canInvert and Template.isNegative) then |
|
588 begin |
|
589 hasBorder:= true; |
|
590 for y:= 0 to LAND_HEIGHT - 1 do |
499 for y:= 0 to LAND_HEIGHT - 1 do |
591 for x:= 0 to LAND_WIDTH - 1 do |
500 for x:= 0 to LAND_WIDTH - 1 do |
592 if (y < topY) or (x < leftX) or (x > rightX) then |
501 Land[y, x]:= lfBasic; |
593 Land[y, x]:= 0 |
502 {$HINTS OFF} |
594 else |
503 SetPoints(Template, pa); |
595 begin |
504 {$HINTS ON} |
596 if Land[y, x] = 0 then |
505 for i:= 1 to Template.BezierizeCount do |
597 Land[y, x]:= lfBasic |
506 begin |
598 else if Land[y, x] = lfBasic then |
507 BezierizeEdge(pa, _0_5); |
599 Land[y, x]:= 0; |
508 RandomizePoints(pa); |
600 end; |
509 RandomizePoints(pa) |
601 end; |
510 end; |
|
511 for i:= 1 to Template.RandPassesCount do RandomizePoints(pa); |
|
512 BezierizeEdge(pa, _0_1); |
|
513 |
|
514 |
|
515 DrawEdge(pa, 0); |
|
516 |
|
517 with Template do |
|
518 for i:= 0 to pred(FillPointsCount) do |
|
519 with FillPoints^[i] do |
|
520 FillLand(x, y); |
|
521 |
|
522 DrawEdge(pa, lfBasic); |
|
523 |
|
524 MaxHedgehogs:= Template.MaxHedgehogs; |
|
525 hasGirders:= Template.hasGirders; |
|
526 playHeight:= Template.TemplateHeight; |
|
527 playWidth:= Template.TemplateWidth; |
|
528 leftX:= ((LAND_WIDTH - playWidth) div 2); |
|
529 rightX:= (playWidth + ((LAND_WIDTH - playWidth) div 2)) - 1; |
|
530 topY:= LAND_HEIGHT - playHeight; |
|
531 |
|
532 // HACK: force to only cavern even if a cavern map is invertable if cTemplateFilter = 4 ? |
|
533 if (cTemplateFilter = 4) or |
|
534 (Template.canInvert and (getrandom(2) = 0)) or |
|
535 (not Template.canInvert and Template.isNegative) then |
|
536 begin |
|
537 hasBorder:= true; |
|
538 for y:= 0 to LAND_HEIGHT - 1 do |
|
539 for x:= 0 to LAND_WIDTH - 1 do |
|
540 if (y < topY) or (x < leftX) or (x > rightX) then |
|
541 Land[y, x]:= 0 |
|
542 else |
|
543 begin |
|
544 if Land[y, x] = 0 then |
|
545 Land[y, x]:= lfBasic |
|
546 else if Land[y, x] = lfBasic then |
|
547 Land[y, x]:= 0; |
|
548 end; |
|
549 end; |
|
550 end; |
|
551 |
|
552 procedure GenDrawnMap; |
|
553 begin |
|
554 uLandPainted.Draw; |
|
555 |
|
556 MaxHedgehogs:= 48; |
|
557 hasGirders:= true; |
|
558 playHeight:= 2048; |
|
559 playWidth:= 4096; |
|
560 leftX:= ((LAND_WIDTH - playWidth) div 2); |
|
561 rightX:= (playWidth + ((LAND_WIDTH - playWidth) div 2)) - 1; |
|
562 topY:= LAND_HEIGHT - playHeight; |
602 end; |
563 end; |
603 |
564 |
604 function SelectTemplate: LongInt; |
565 function SelectTemplate: LongInt; |
605 begin |
566 begin |
606 if (cReducedQuality and rqLowRes) <> 0 then |
567 if (cReducedQuality and rqLowRes) <> 0 then |
1346 end; |
1311 end; |
1347 |
1312 |
1348 GenPreview:= Preview |
1313 GenPreview:= Preview |
1349 end; |
1314 end; |
1350 |
1315 |
|
1316 |
|
1317 procedure chLandCheck(var s: shortstring); |
|
1318 begin |
|
1319 {$IFDEF DEBUGFILE} |
|
1320 AddFileLog('CheckLandDigest: ' + s + ' digest : ' + digest); |
|
1321 {$ENDIF} |
|
1322 if digest = '' then |
|
1323 digest:= s |
|
1324 else |
|
1325 TryDo(s = digest, 'Different maps generated, sorry', true); |
|
1326 end; |
|
1327 |
|
1328 procedure chSendLandDigest(var s: shortstring); |
|
1329 var adler, i: LongInt; |
|
1330 begin |
|
1331 adler:= 1; |
|
1332 for i:= 0 to LAND_HEIGHT-1 do |
|
1333 Adler32Update(adler, @Land[i,0], LAND_WIDTH); |
|
1334 s:= 'M' + IntToStr(adler); |
|
1335 |
|
1336 chLandCheck(s); |
|
1337 SendIPCRaw(@s[0], Length(s) + 1) |
|
1338 end; |
|
1339 |
1351 procedure initModule; |
1340 procedure initModule; |
1352 begin |
1341 begin |
|
1342 RegisterVariable('landcheck', vtCommand, @chLandCheck, false); |
|
1343 RegisterVariable('sendlanddigest', vtCommand, @chSendLandDigest, false); |
|
1344 |
1353 LandBackSurface:= nil; |
1345 LandBackSurface:= nil; |
1354 digest:= ''; |
1346 digest:= ''; |
1355 |
1347 |
1356 if (cReducedQuality and rqBlurryLand) = 0 then |
1348 if (cReducedQuality and rqBlurryLand) = 0 then |
1357 SetLength(LandPixels, LAND_HEIGHT, LAND_WIDTH) |
1349 SetLength(LandPixels, LAND_HEIGHT, LAND_WIDTH) |