- Timestamp:
- Dec 12, 2020, 11:09:33 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Games/UClovece.pas
r2 r3 14 14 15 15 TTileKind = (tkNone, tkHome, tkYard); 16 TTileKindSet = set of TTileKind; 16 17 17 18 { TToken } … … 22 23 procedure SetTile(AValue: TTile); 23 24 public 25 MoveCount: Integer; 24 26 Player: TPlayer; 25 27 property Tile: TTile read FTile write SetTile; … … 30 32 TTokens = class(TFPGObjectList<TToken>) 31 33 function AddNew(Player: TPlayer): TToken; 32 function GetCountByTileKind(Kind: TTileKind): Integer; 33 function GetSingleByTileKind(Kind: TTileKind): TToken; 34 function GetCountByTileKind(Kind: TTileKindSet): Integer; 35 function GetSingleByTileKind(Kind: TTileKindSet): TToken; 36 procedure GetByTileKind(Kind: TTileKindSet; const Tiles: TTokens); 34 37 end; 35 38 … … 137 140 UGeometric; 138 141 139 const140 Directions: array[0..3] of TPoint = ((X: 1; Y: 1), (X: -1; Y: 1),141 (X: -1; Y: -1), (X: 1; Y: -1));142 Directions2: array[0..3] of TPoint = ((X: 1; Y: 0), (X: 0; Y: 1),143 (X: -1; Y: 0), (X: 0; Y: -1));144 Directions3: array[0..3] of TPoint = ((X: 0; Y: 1), (X: 1; Y: 0),145 (X: 0; Y: -1), (X: 1; Y: 0));146 147 142 { TToken } 148 143 … … 278 273 end; 279 274 280 function TTokens.GetCountByTileKind(Kind: TTileKind ): Integer;275 function TTokens.GetCountByTileKind(Kind: TTileKindSet): Integer; 281 276 var 282 277 I: Integer; … … 284 279 Result := 0; 285 280 for I := 0 to Count - 1 do 286 if Items[I].Tile.Kind =Kind then Inc(Result);287 end; 288 289 function TTokens.GetSingleByTileKind(Kind: TTileKind ): TToken;281 if Items[I].Tile.Kind in Kind then Inc(Result); 282 end; 283 284 function TTokens.GetSingleByTileKind(Kind: TTileKindSet): TToken; 290 285 var 291 286 I: Integer; 292 287 begin 293 288 I := 0; 294 while (I < Count) and ( Items[I].Tile.Kind <> Kind) do Inc(I);289 while (I < Count) and (not (Items[I].Tile.Kind in Kind)) do Inc(I); 295 290 if I < Count then Result := Items[I] 296 291 else Result := nil; 292 end; 293 294 procedure TTokens.GetByTileKind(Kind: TTileKindSet; const Tiles: TTokens); 295 var 296 I: Integer; 297 begin 298 Tiles.Clear; 299 for I := 0 to Count - 1 do 300 if Items[I].Tile.Kind in Kind then Tiles.Add(Items[I]); 297 301 end; 298 302 … … 320 324 function TPlayer.CanPlay: Boolean; 321 325 begin 322 Result := (Tokens.GetCountByTileKind(tkYard) > 0) or 323 (Tokens.GetCountByTileKind(tkNone) > 0); 326 Result := Tokens.GetCountByTileKind([tkYard, tkNone]) > 0; 324 327 end; 325 328 … … 359 362 P: TPoint; 360 363 P1, P2: TPoint; 361 Tile: TTile;362 364 R: Integer; 363 365 Between: Boolean; … … 434 436 P := Point(Trunc(Center.X + R + TokenCount * TileDistance * 1.35), Center.Y); 435 437 P := RotatePoint(Center, P, Angle); 436 Tile := Tiles.AddNew(RotatePoint(P, Point(P.X + Trunc(0.7 * TileDistance), P.Y), I / TokenCount * 2 * Pi + Pi / 4), tkYard, Players[J]);438 Tiles.AddNew(RotatePoint(P, Point(P.X + Trunc(0.7 * TileDistance), P.Y), I / TokenCount * 2 * Pi + Pi / 4), tkYard, Players[J]); 437 439 end; 438 440 end; … … 474 476 begin 475 477 Steps := TTiles.Create(False); 476 Token.Tile.GetNextSteps(DiceValue, CurrentPlayer, Steps); 477 Token.Tile := nil; 478 for I := 0 to Steps.Count - 1 do begin 479 Steps[I].AnimateToken := Token; 480 Repaint; 481 Application.ProcessMessages; 482 Sleep(200); 483 Steps[I].AnimateToken := nil; 484 end; 485 Steps.Free; 478 try 479 Token.Tile.GetNextSteps(DiceValue, CurrentPlayer, Steps); 480 Token.Tile := nil; 481 for I := 0 to Steps.Count - 1 do begin 482 Steps[I].AnimateToken := Token; 483 Repaint; 484 Application.ProcessMessages; 485 Sleep(200); 486 Steps[I].AnimateToken := nil; 487 end; 488 finally 489 Steps.Free; 490 end; 486 491 Token.Tile := NewTile; 492 Token.MoveCount := Token.MoveCount + DiceValue; 493 end; 494 495 function CompareTokenMoveCount(const Item1, Item2: TToken): Integer; 496 begin 497 if Item1.MoveCount < Item2.MoveCount then Result := 1 498 else if Item1.MoveCount > Item2.MoveCount then Result := -1 499 else Result := 0; 487 500 end; 488 501 … … 493 506 TurnDone: Boolean; 494 507 I: Integer; 508 SortedTokens: TTokens; 495 509 begin 496 510 TurnDone := False; … … 498 512 LastDiceValue := DiceValue; 499 513 if DiceValue = 6 then begin 500 if CurrentPlayer.Tokens.GetCountByTileKind( tkYard) > 0 then begin514 if CurrentPlayer.Tokens.GetCountByTileKind([tkYard]) > 0 then begin 501 515 if (not Assigned(CurrentPlayer.StartTile.Token)) or ( 502 516 Assigned(CurrentPlayer.StartTile.Token) and (CurrentPlayer.StartTile.Token.Player <> CurrentPlayer)) then begin … … 506 520 end; 507 521 // Move one token from yard to start 508 CurrentPlayer.StartTile.Token := CurrentPlayer.Tokens.GetSingleByTileKind(tkYard); 522 Token := CurrentPlayer.Tokens.GetSingleByTileKind([tkYard]); 523 Token.MoveCount := 0; 524 CurrentPlayer.StartTile.Token := Token; 509 525 TurnDone := True; 510 526 end; 511 527 end; 512 528 end; 513 if not TurnDone and (CurrentPlayer.Tokens.GetCountByTileKind( tkNone) > 0) then begin514 for I := 0 to CurrentPlayer.Tokens.Count - 1 do515 if CurrentPlayer.Tokens[I].Tile.Kind in [tkHome, tkNone] then begin516 Token := CurrentPlayer. Tokens[I];529 if not TurnDone and (CurrentPlayer.Tokens.GetCountByTileKind([tkNone, tkHome]) > 0) then begin 530 if Assigned(CurrentPlayer.StartTile.Token) and (CurrentPlayer.StartTile.Token.Player = CurrentPlayer) then begin 531 // Own token is on start position, move it away 532 Token := CurrentPlayer.StartTile.Token; 517 533 NewTile := Token.Tile.GetNext(DiceValue, CurrentPlayer); 518 if not Assigned(NewTile) then Continue; 519 if Assigned(NewTile.Token) then begin 520 if NewTile.Token.Player = Token.Player then begin 521 // Another own token is blocking way, use another one if possible 522 Continue; 523 end else begin 524 // Move opponents token back to its yard 525 NewTile.Token.Tile := NewTile.Token.Player.YardTiles.GetTileWithoutToken; 526 AnimateTokenMovement(Token, NewTile); 527 TurnDone := True; 528 Break; 529 end; 530 end else begin 531 // Normal token move 534 if not Assigned(NewTile.Token) or (NewTile.Token.Player <> CurrentPlayer) then begin 532 535 AnimateTokenMovement(Token, NewTile); 533 536 TurnDone := True; 534 Break;535 537 end; 536 538 end; 539 if not TurnDone then begin 540 SortedTokens := TTokens.Create(False); 541 try 542 CurrentPlayer.Tokens.GetByTileKind([tkNone, tkHome], SortedTokens); 543 SortedTokens.Sort(CompareTokenMoveCount); 544 for I := 0 to SortedTokens.Count - 1 do begin 545 Token := SortedTokens[I]; 546 NewTile := Token.Tile.GetNext(DiceValue, CurrentPlayer); 547 if not Assigned(NewTile) then Continue; 548 if Assigned(NewTile.Token) then begin 549 if NewTile.Token.Player = Token.Player then begin 550 // Another own token is blocking way, use another one if possible 551 Continue; 552 end else begin 553 // Move opponents token back to its yard 554 NewTile.Token.Tile := NewTile.Token.Player.YardTiles.GetTileWithoutToken; 555 AnimateTokenMovement(Token, NewTile); 556 TurnDone := True; 557 Break; 558 end; 559 end else begin 560 // Normal token move 561 AnimateTokenMovement(Token, NewTile); 562 TurnDone := True; 563 Break; 564 end; 565 end; 566 finally 567 SortedTokens.Free; 568 end; 569 end; 537 570 end; 538 571 Inc(DiceThrow); 539 if ((CurrentPlayer.Tokens.GetCountByTileKind(tkNone) = 0) and (DiceThrow >= 3)) or 540 ((CurrentPlayer.Tokens.GetCountByTileKind(tkNone) > 0) and (DiceValue <> 6)) then begin 572 if ((CurrentPlayer.Tokens.GetCountByTileKind([tkNone]) = 0) and (DiceThrow >= 3)) or 573 ((CurrentPlayer.Tokens.GetCountByTileKind([tkNone]) > 0) and (DiceValue <> 6)) or 574 (CurrentPlayer.Tokens.GetCountByTileKind([tkHome]) = TokenCount) then begin 541 575 repeat 542 576 CurrentPlayer := Players[(Players.IndexOf(CurrentPlayer) + 1) mod Players.Count];
Note:
See TracChangeset
for help on using the changeset viewer.