4 public enum BlokusColor : byte { none, blue, yellow, red, green };
6 public enum PlayerColor : byte
8 blue, yellow, red, green;
11 // TOFIX: get { return (BlokusColor)((int)this+1); }
12 get { return (BlokusColor)*(int *)&this+1; }
16 static Color colors[2][BlokusColor] =
18 // TOFIX: (omitting Color { })
19 { 0, Color { 64, 64, 96 }, Color { 141, 114, 48 }, Color { 96, 32, 32 }, Color { 64, 96, 64 } },
20 { 0, blue, goldenrod, red, green }
22 Point corners[PlayerColor] =
30 define numPieces = 21;
32 define squareWidth = 28;
33 define boardStartX = 20;
34 define boardStartY = 30;
43 Piece pieces[numPieces] =
213 struct BlokusGameState
215 byte playerPieces[PlayerColor][numPieces];
216 bool firstPiece[PlayerColor];
217 BlokusColor board[bs * bs];
218 PlayerColor colorTurn;
219 PlayerColor rotatingColor;
221 bool validPieces[numPieces];
232 // TOFIX: for(p = 0; p < PlayerColor::enumSize; p++)
233 for(p = blue; p <= green; p++)
235 for(i = 0; i < numPieces; i++)
236 playerPieces[p][i] = 1;
237 firstPiece[p] = true;
241 for(i = 0; i < bs * bs; i++)
246 rotatingColor = blue;
248 validMove = CheckValidMoves(colorTurn, validPieces);
251 bool ValidMove(PlayerColor playerColor, int selectedPiece, int direction, bool flip, int boardX, int boardY)
253 Piece * piece = &pieces[selectedPiece];
256 bool touchCorner = false;
257 int w = (direction & 1) ? piece->h : piece->w;
258 int h = (direction & 1) ? piece->w : piece->h;
260 if(!playerPieces[playerColor][selectedPiece]) return false;
262 if(boardX < 0 || boardY < 0 || boardX + w > bs || boardY + h > bs) return false;
264 for(y = 0; y < 5; y++)
265 for(x = 0; x < 5; x++)
266 if(PieceBlock(selectedPiece, x, y, direction, flip))
268 int bx = x + boardX, by = y + boardY;
269 if(board[by * bs + bx] ||
270 (by > 0 && board[(by-1) * bs + bx] == playerColor) ||
271 (by < bs-1 && board[(by+1) * bs + bx] == playerColor) ||
272 (bx > 0 && board[by * bs + bx - 1] == playerColor) ||
273 (bx < bs-1 && board[by * bs + bx + 1] == playerColor))
278 if((by > 0 && bx > 0 && board[(by-1) * bs + (bx-1)] == playerColor) ||
279 (by > 0 && bx < bs-1 && board[(by-1) * bs + (bx+1)] == playerColor) ||
280 (by < bs-1 && bx > 0 && board[(by+1) * bs + (bx-1)] == playerColor) ||
281 (by < bs-1 && bx < bs-1 && board[(by+1) * bs + (bx+1)] == playerColor))
284 if(valid && firstPiece[playerColor])
286 for(y = 0; y < 5; y++)
287 for(x = 0; x < 5; x++)
288 if(PieceBlock(selectedPiece, x, y, direction, flip))
290 int bx = x + boardX, by = y + boardY;
291 if(bx == corners[playerColor].x && by == corners[playerColor].y)
299 return valid && touchCorner;
302 bool CheckValidMoves(PlayerColor playerColor, bool validPieces[21])
306 for(p = 0; p < numPieces; p++)
308 bool validMove = false;
309 if(playerPieces[playerColor][p])
312 for(y = 0; y < bs && !validMove; y++)
314 for(x = 0; x < bs && !validMove; x++)
318 for(direction = 0; direction < 4 && !validMove; direction++)
320 for(flip = 0; flip <=1 && !validMove; flip++)
322 if(ValidMove(playerColor, p, direction, flip, x, y))
323 result = validMove = true;
329 if(validPieces) validPieces[p] = validMove;
334 void PlayMove(int pieceType, int direction, bool flip, int boardX, int boardY)
338 for(y = 0; y < 5; y++)
339 for(x = 0; x < 5; x++)
340 if(PieceBlock(pieceType, x, y, direction, flip))
341 board[(y + boardY) * bs + x + boardX] = colorTurn;
342 playerPieces[colorTurn][pieceType] = 0;
343 scores[colorTurn] = 0;
344 for(p = 0; p < numPieces; p++)
346 if(playerPieces[colorTurn][p])
348 Piece * piece = &pieces[p];
350 for(y = 0; y < piece->h; y++)
351 for(x = 0; x < piece->w; x++)
352 if(piece->blocks[y * piece->w + x])
356 if(scores[colorTurn] == 0)
357 bonus[colorTurn] = (pieceType == 0) ? 20 : 15;
359 firstPiece[colorTurn] = false;
360 if(numPlayers == 3 && colorTurn == green)
362 if(++rotatingColor == green) rotatingColor = 0;
364 if(++colorTurn > green) colorTurn = 0;
366 validMove = CheckValidMoves(colorTurn, validPieces);
373 if(numPlayers == 3 && colorTurn == green)
375 if(++rotatingColor == green) rotatingColor = 0;
377 if(++colorTurn > green) colorTurn = 0;
379 validMove = CheckValidMoves(colorTurn, validPieces);
386 PlayerColor turn = colorTurn;
388 for(c = 0; c < 3; c++)
390 if(++turn > green) turn = 0;
391 if(CheckValidMoves(turn, null))
399 int PieceBlock(int p, int x, int y, int direction, bool flip)
401 Piece * piece = &pieces[p];
402 int w = piece->w, h = piece->h;
406 case 0: rx = x; ry = y; break;
407 case 1: ry = h-1 - x; rx = y; break;
408 case 2: ry = h-1 - y; rx = w -1- x; break;
409 case 3: ry = x; rx = w-1-y; break;
411 if(rx < w && ry < h && rx >= 0 && ry >= 0)
412 return piece->blocks[ry * w + (flip ? (w-1-rx) : rx)];
416 class Blokus : Window
420 borderStyle = sizable;
421 minClientSize = { 1068 /*800*/, 700 };
425 size = { 1280, 728 };
426 nativeDecorations = true;
427 font = { "Arial", 12, bold = true };
428 FontResource yourTurnFont { "Arial", 12, bold = true, italic = true, window = this };
431 PlayerColor firstColor;
432 char *playerNames[MaxPlayers];
434 // Current game state
435 BlokusGameState gameState;
438 PlayerColor colorPlayed; // Color currently (or next) being played
440 bool dragging, onBoard;
448 void NextColorPlayed()
450 if(gameState.numPlayers == 1)
452 if(++colorPlayed > green) colorPlayed = 0;
454 else if(gameState.numPlayers == 2)
456 if((colorPlayed+=2) > green) colorPlayed = firstColor;
458 else if(gameState.numPlayers == 3)
460 colorPlayed = (colorPlayed == firstColor && gameState.rotatingColor == firstColor) ? green : firstColor;
464 void UpdatePlayerNames()
467 if(gameState.numPlayers == 1)
469 for(c = 0; c < 4; c++)
470 playerNames[c] = panel.playerNames[0];
472 else if(gameState.numPlayers == 2)
474 for(c = 0; c < 2; c++)
476 playerNames[c] = panel.playerNames[c];
477 playerNames[c+2] = panel.playerNames[c];
480 else if(gameState.numPlayers == 3)
482 for(c = 0; c < 3; c++)
483 playerNames[c] = panel.playerNames[c];
484 playerNames[3] = panel.playerNames[gameState.rotatingColor];
486 else if(gameState.numPlayers == 4)
488 for(c = 0; c < 4; c++)
489 playerNames[c] = panel.playerNames[c];
493 void DrawSquare(Surface surface, int x, int y, BlokusColor color, int shade)
495 surface.background = colors[shade][color];
496 surface.Area(x+1, y+1, x + squareWidth-1, y + squareWidth-1);
497 surface.foreground = lightGray;
498 surface.VLine(y+5, y + 15, x + 5);
499 surface.HLine(x+5, x + 18, y + 5);
500 surface.foreground = white;
501 surface.Rectangle(x + 2,y+2, x + squareWidth-2, y + squareWidth - 2);
507 scoresPanel.Destroy(0);
510 bool OnMouseMove(int mx, int my, Modifiers mods)
514 Piece * piece = &pieces[selectedPiece];
515 int w = (direction & 1) ? piece->h : piece->w;
516 int h = (direction & 1) ? piece->w : piece->h;
517 drag = { offset.x + mx, offset.y + my };
519 if(mx - squareDragged.x * squareWidth >= boardStartX - 10 && mx - squareDragged.x * squareWidth < boardStartX + ((bs-w)+1) * squareWidth + 10 &&
520 my - squareDragged.y * squareWidth >= boardStartY - 10 && my - squareDragged.y * squareWidth < boardStartY + ((bs-h)+1) * squareWidth + 10)
523 x = Max(0,mx - squareDragged.x * squareWidth - boardStartX) / squareWidth;
524 y = Max(0,my - squareDragged.y * squareWidth - boardStartY) / squareWidth;
527 drag.x = boardStartX + x * squareWidth;
528 drag.y = boardStartY + y * squareWidth;
539 bool OnLeftButtonUp(int mx, int my, Modifiers mods)
545 if(gameStarted && colorPlayed == gameState.colorTurn)
547 Piece * piece = &pieces[selectedPiece];
548 if(gameState.ValidMove(gameState.colorTurn, selectedPiece, direction, flip, boardPos.x, boardPos.y))
549 panel.server.PlayPiece(selectedPiece, direction, flip, boardPos.x, boardPos.y);
559 bool OnRightButtonDown(int mx, int my, Modifiers mods)
561 Piece * piece = &pieces[selectedPiece];
562 int x = squareDragged.x, y = squareDragged.y;
565 w = (direction & 1) ? piece->h : piece->w;
566 h = (direction & 1) ? piece->w : piece->h;
568 offset.x += squareDragged.x * squareWidth;
569 offset.y += squareDragged.y * squareWidth;
570 squareDragged = (direction & 1) ? { x, h-1-y } : { w-1-x, y };
572 offset.x -= squareDragged.x * squareWidth;
573 offset.y -= squareDragged.y * squareWidth;
575 OnMouseMove(mx,my,mods);
581 bool OnKeyHit(Key key, unichar ch)
583 if(key == wheelDown || key == wheelUp)
585 Piece * piece = &pieces[selectedPiece];
586 int mx = drag.x - offset.x, my = drag.y - offset.y;
589 int x = squareDragged.x, y = squareDragged.y;
594 if(++direction == 4) direction = 0;
598 if(--direction == -1) direction = 3;
600 w = (direction & 1) ? piece->h : piece->w;
601 h = (direction & 1) ? piece->w : piece->h;
603 offset.x += squareDragged.x * squareWidth;
604 offset.y += squareDragged.y * squareWidth;
606 squareDragged = { w-1-y, x };
608 squareDragged = { y, h-1-x };
610 offset.x -= squareDragged.x * squareWidth;
611 offset.y -= squareDragged.y * squareWidth;
613 OnMouseMove(mx,my,0);
620 bool OnLeftButtonDown(int mx, int my, Modifiers mods)
622 if( mx > squareWidth * bs + 40)
625 bool selected = false;
630 // Draw Player Pieces
631 bx = squareWidth * bs + 40;
633 for(c = 0; c < numPieces; c++)
635 if(gameState.playerPieces[colorPlayed][c])
637 int w = pieces[c].w, h = pieces[c].h;
639 for(y = 0; y < 5; y++)
642 for(x = 0; x < 5; x++)
644 if(PieceBlock(c, x, y, 0, false))
646 int dx = bx + x * squareWidth;
647 int dy = by + y * squareWidth;
648 if(mx >= dx && mx < dx + squareWidth &&
649 my >= dy && my < dy + squareWidth)
653 offset = { bx - mx, by - my };
654 squareDragged = { x, y };
663 bx += w * squareWidth + squareWidth;
665 if(bx + 5 * squareWidth > clientSize.w)
667 bx = squareWidth * bs + 40;
668 by += (rh+1) * squareWidth;
678 selectedPiece = pieceNum;
679 this.offset = offset;
681 OnMouseMove(mx, my, mods);
688 float lightValue, lightDir;
697 lightValue += lightDir;
698 if(lightValue < 0) { lightValue = 0; lightDir = .1f; }
699 if(lightValue > 1) { lightValue = 1; lightDir =-.1f; }
705 void OnRedraw(Surface surface)
708 int bx = boardStartX;
709 int by = boardStartY;
713 Color turnLight = white;
714 if(gameStarted && !gameState.over)
716 ColorRGB empty = colors[1][gameState.colorTurn] /*gray*/, full = white;
719 empty.r + lightValue * (full.r - empty.r),
720 empty.g + lightValue * (full.g - empty.g),
721 empty.b + lightValue * (full.b - empty.b)
725 surface.foreground = aqua;
726 for(c = 0; c <= bs; c++)
728 surface.HLine(bx,bx+squareWidth*bs, by + c * squareWidth);
729 surface.VLine(by,by+squareWidth*bs, bx + c * squareWidth);
732 surface.background = colors[blokus.gameStarted][blue];
735 surface.Area(x - 10, y - 10, x + 10, y-1);
736 surface.Area(x - 10, y - 10, x - 1, y+10);
738 s = playerNames[PlayerColor::blue];
742 surface.foreground = (gameState.colorTurn == blue) ? turnLight : white;
743 surface.WriteText(x + 15, y - 20, s, len);
746 surface.background = colors[blokus.gameStarted][yellow];
747 x = bx + bs*squareWidth;
749 surface.Area(x + 10, y - 10, x - 10, y-1);
750 surface.Area(x + 10, y - 10, x + 1, y+10);
752 s = playerNames[PlayerColor::yellow];
756 surface.TextExtent(s, len, &tw, null);
757 surface.foreground = (gameState.colorTurn == yellow) ? turnLight : white;
758 surface.WriteText(x - 15 - tw, y - 20, s, len);
761 surface.background = colors[blokus.gameStarted][red];
762 x = bx + bs*squareWidth;
763 y = by + bs*squareWidth;
764 surface.Area(x + 10, y + 1, x - 10, y+10);
765 surface.Area(x + 10, y - 10, x + 1, y+10);
766 s = playerNames[PlayerColor::red];
770 surface.TextExtent(s, len, &tw, null);
771 surface.foreground = (gameState.colorTurn == red) ? turnLight : white;
772 surface.WriteText(x - 15 - tw, y, s, len);
775 surface.background = colors[blokus.gameStarted][green];
777 y = by + bs*squareWidth;
778 surface.Area(x - 10, y + 1, x + 10, y+10);
779 surface.Area(x - 10, y - 10, x - 1, y+10);
780 s = playerNames[PlayerColor::green];
784 surface.foreground = (gameState.colorTurn == green) ? turnLight : white;
785 surface.WriteText(x + 15, y, s, len);
790 surface.font = yourTurnFont.font;
791 surface.foreground = crimson;
792 surface.CenterTextf(x + bs*squareWidth/2, y + 3, "Game Over");
794 else if(gameState.numPlayers > 1 && gameStarted && colorPlayed == gameState.colorTurn)
796 surface.font = yourTurnFont.font;
797 surface.foreground = tomato;
798 surface.CenterTextf(x + bs*squareWidth/2, y + 3, "Your turn");
801 for(y = 0; y < bs; y++)
803 for(x = 0; x < bs; x++)
805 BlokusColor color = gameState.board[y * bs + x];
808 DrawSquare(surface, bx + x * squareWidth, by + y * squareWidth, color, blokus.gameStarted);
815 // Draw Player Pieces
816 bx = squareWidth * bs + 40;
818 for(c = 0; c < numPieces; c++)
820 if(gameState.playerPieces[colorPlayed][c])
822 int w = pieces[c].w, h = pieces[c].h;
823 for(y = 0; y < 5; y++)
825 for(x = 0; x < 5; x++)
827 if(PieceBlock(c, x, y, 0, false))
829 if(!dragging || selectedPiece != c)
830 DrawSquare(surface, bx + x * squareWidth, by + y * squareWidth, colorPlayed, gameStarted && (gameState.colorTurn != colorPlayed || gameState.validPieces[c]));
835 bx += w * squareWidth + squareWidth;
836 if(bx + 5 * squareWidth > clientSize.w)
838 bx = squareWidth * bs + 40;
839 by += rh * squareWidth + squareWidth;
844 // Draw Dragged piece
847 for(y = 0; y < 5; y++)
848 for(x = 0; x < 5; x++)
850 if(PieceBlock(selectedPiece, x, y, direction, flip))
852 DrawSquare(surface, drag.x + x * squareWidth, drag.y + y * squareWidth, colorPlayed, gameStarted && gameState.colorTurn == colorPlayed);
854 if(x == 0 || !PieceBlock(selectedPiece, x-1, y, direction, flip))
856 surface.foreground = white;
857 surface.VLine(drag.y + y * squareWidth-1, drag.y + (y+1) * squareWidth+1, drag.x + x * squareWidth - 1);
858 surface.foreground = lime;
859 surface.VLine(drag.y + y * squareWidth-2, drag.y + (y+1) * squareWidth+2, drag.x + x * squareWidth - 2);
862 if(y == 0 || !PieceBlock(selectedPiece, x, y-1, direction, flip))
864 surface.foreground = white;
865 surface.HLine(drag.x + x * squareWidth-1, drag.x + (x+1) * squareWidth+1, drag.y + y * squareWidth - 1);
866 surface.foreground = lime;
867 surface.HLine(drag.x + x * squareWidth-2, drag.x + (x+1) * squareWidth+2, drag.y + y * squareWidth - 2);
870 if(x == 4 || !PieceBlock(selectedPiece, x+1, y, direction, flip))
872 surface.foreground = white;
873 surface.VLine(drag.y + y * squareWidth-1, drag.y + (y+1) * squareWidth+1, drag.x + (x+1) * squareWidth + 1);
874 surface.foreground = lime;
875 surface.VLine(drag.y + y * squareWidth-2, drag.y + (y+1) * squareWidth+2, drag.x + (x+1) * squareWidth + 2);
878 if(y == 4 || !PieceBlock(selectedPiece, x, y+1, direction, flip))
880 surface.foreground = white;
881 surface.HLine(drag.x + x * squareWidth-1, drag.x + (x+1) * squareWidth+1, drag.y + (y+1) * squareWidth + 1);
882 surface.foreground = lime;
883 surface.HLine(drag.x + x * squareWidth-2, drag.x + (x+1) * squareWidth+2, drag.y + (y+1) * squareWidth + 2);
893 this, size = { bs*squareWidth }, anchor = { left = boardStartX, top = boardStartY + bs*squareWidth + 20, bottom = 5 };
894 font = { "Arial", 11, bold = true };
895 editTextColor = white;
896 logTextColor = white;
898 log.hasVertScroll = bool::true;
901 bool ProcessCommand(char * command)
903 panel.server.SendMessage(command);
910 this, text = "No Move Available! Pass...", anchor = { right = 5, bottom = 5 };
914 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
916 btnPass.visible = false;
917 blokus.passed[blokus.gameState.colorTurn] = true;
925 class BlokusScores : Window
931 text = "Blokus Final Scores";
932 clientSize = { 580, 210 };
933 font = { "Arial", 12, bold = true };
935 void OnRedraw(Surface surface)
942 BlokusGameState * state = &blokus.gameState;
943 surface.foreground = white;
944 s = "Score"; len = strlen(s);
945 surface.WriteText(10, 40, s, len);
947 s = "Bonus"; len = strlen(s);
948 surface.WriteText(10, 60, s, len);
950 s = "Total"; len = strlen(s);
951 surface.WriteText(10, 100, s, len);
953 if(state->numPlayers < 3)
955 s = "Grand Total"; len = strlen(s);
956 surface.WriteText(10, 160, s, len);
959 for(p = blue; p <= green; p++)
961 // TOFIX: bug here, why is -1 required?
962 int x = 80 + (p-1) * 120;
963 surface.foreground = colors[1][p];
964 /* // GCC internal compiler error with -O2, MinGW GCC 4.4.0
965 s = (state->numPlayers == 3 && p == green) ? "* Green *" : blokus.playerNames[p];
967 surface.WriteText(x, 20, s, len);
969 if(state->numPlayers == 3 && p == green)
973 surface.WriteText(x, 20, s, len);
975 else if(blokus.playerNames[p])
977 s = blokus.playerNames[p];
979 surface.WriteText(x, 20, s, len);
982 s = temp; sprintf(temp, "%d", state->scores[p]);
984 surface.WriteText(x + 30, 40, s, len);
988 s = temp; sprintf(temp, "%d", state->bonus[p]);
990 surface.WriteText(x + 30, 60, s, len);
993 if(state->numPlayers > 2)
994 grandTotals[p] = state->scores[p] + state->bonus[p];
995 s = temp; sprintf(temp, "%d", state->scores[p] + state->bonus[p]);
997 surface.WriteText(x + 30, 100, s, len);
999 if((state->numPlayers == 2 && p <= yellow) ||
1000 (state->numPlayers == 1 && p == blue))
1002 // TOFIX: Annoying +2 conversion issue
1003 if(state->numPlayers == 2)
1004 grandTotals[p] = state->scores[p] + state->bonus[p] +
1005 state->scores[p+red /*2*/] + state->bonus[p+red /*2*/];
1007 grandTotals[p] = state->scores[0] + state->bonus[0] +
1008 state->scores[1] + state->bonus[1] +
1009 state->scores[2] + state->bonus[2] +
1010 state->scores[3] + state->bonus[3];
1012 if(blokus.playerNames[p])
1014 s = blokus.playerNames[p];
1016 surface.WriteText(x, 140, s, len);
1019 s = temp; sprintf(temp, "%d", grandTotals[p]);
1021 surface.WriteText(x + 30, 160, s, len);
1024 if(state->numPlayers > 1)
1027 int c, greatest = -MAXINT;
1028 int numTies = 0, ties[3], winner;
1031 for(c = 0; c < state->numPlayers; c++)
1033 if(grandTotals[c] > greatest)
1035 greatest = grandTotals[c];
1039 else if(grandTotals[c] == greatest)
1046 ties[numTies++] = c;
1051 for(c = 0; c < numTies; c++)
1053 strcat(string, blokus.playerNames[c]);
1055 strcat(string, ", ");
1056 else if(c < numTies-1)
1057 strcat(string, " and ");
1059 surface.foreground = white;
1060 strcat(string, " tied!");
1064 surface.foreground = colors[1][(PlayerColor)winner];
1065 sprintf(string, "%s won!", blokus.playerNames[winner]);
1068 len = strlen(string);
1069 surface.WriteText(100, 180, string, strlen(string));
1074 BlokusScores scoresPanel { visible = false };
1078 class BlokusApp : GuiApplication
1087 bool Cycle(bool idle)
1089 // This is here because it hangs in MovePlayed() (Why?)
1090 scoresPanel.visible = blokus.gameStarted && blokus.gameState.over;
1096 blokusService.Stop();
1100 import remote "BlokusServer"
1102 define app = ((BlokusApp)__thisModule.application);
1104 define BLOKUS_PORT = 1495;
1105 static bool hosting;
1106 define MaxPlayers = 4;
1108 class CommunicationPanel : Window
1110 text = "Blokus Communication Panel";
1111 background = lightSlateGray;
1112 borderStyle = fixed;
1115 size = { 400, 300 };
1116 anchor = { horz = -3, vert = -7 };
1117 nativeDecorations = true;
1119 ServerConnection server;
1121 // Other player info
1122 char playerNames[MaxPlayers][256];
1124 DataField fldName { header = "Name", width = 100 };
1125 DataField fldAddr { header = "Address" };
1131 blokusService.Stop();
1135 panel.server.Disconnect(0);
1139 CommunicationPanel()
1141 listPlayers.AddField(fldName);
1142 listPlayers.AddField(fldAddr);
1145 ~CommunicationPanel()
1153 listPlayers.Clear();
1154 fldAddr.header = hosting ? "Address" : "";
1155 for(c = 0; c<MaxPlayers; c++)
1159 if(serverPlayers[c])
1161 DataRow row = listPlayers.AddRow();
1162 DCOMServerObject object = (DCOMServerObject)serverPlayers[c].connection._vTbl[-1];
1164 row.tag = serverPlayers[c].id;
1165 row.SetData(fldName, serverPlayers[c].name);
1166 row.SetData(fldAddr, object.serverSocket.inetAddress);
1169 else if(playerNames[c][0])
1171 DataRow row = listPlayers.AddRow();
1172 row.SetData(fldName, playerNames[c]);
1177 void UpdateControlsStates()
1180 if(hosting && !serverGameStarted)
1183 for(c = 0; c<MaxPlayers; c++)
1184 if(serverPlayers[c])
1187 lblServerAddress.disabled = serverAddress.disabled = server ? true : false;
1188 lblPlayerName.disabled = playerName.disabled = server ? true : false;
1189 lblServerAddress.Update(null);
1190 lblPlayerName.Update(null);
1191 btnConnect.visible = server ? false : true;
1192 btnDisconnect.visible = server ? true : false;
1193 blokus.chat.visible = server ? true : false;
1195 btnHost.visible = !hosting && !server;
1196 btnStopHosting.visible = hosting;
1197 btnStart.visible = hosting && !serverGameStarted && numPlayers > 0;
1198 btnStopGame.visible = hosting && serverGameStarted;
1199 listPlayers.visible = (hosting && (serverGameStarted || numPlayers > 0)) || (!hosting && server && blokus.gameStarted);
1200 btnKick.visible = hosting && !serverGameStarted && numPlayers > 0;
1201 btnKick.disabled = listPlayers.currentRow ? false : true;
1203 EditBox serverAddress
1205 this, text = "Server Address:", altA, font = { "Tahoma", 10, bold = true }, size = { 220, 24 }, position = { 16, 64 }, contents = "localhost"
1207 Label lblServerAddress { this, font = { "Tahoma", 8.25f, bold = true }, position = { 16, 40 }, labeledWindow = serverAddress };
1210 this, text = "Connect", altC, isDefault = true, font = { "Arial", 16, bold = true }, size = { 126, 32 }, position = { 256, 64 };
1212 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1216 server = ServerConnection
1218 void OnDisconnect(int code)
1223 delete panel.server;
1224 blokus.gameStarted = false;
1225 blokus.turnLightTimer.Stop();
1226 blokus.lightValue = 1;
1227 blokus.lightDir = -.1f;
1228 blokus.Update(null);
1229 panel.UpdateControlsStates();
1230 panel.ListPlayers();
1232 DCOMClientObject::OnDisconnect(code);
1236 void GameStarted(GameInfo gameInfo)
1241 blokus.gameState.numPlayers = gameInfo.numPlayers;
1242 blokus.firstColor = gameInfo.firstColor;
1243 blokus.colorPlayed = blokus.firstColor;
1245 for(c = 0; c<MaxPlayers; c++)
1247 if(gameInfo.players[c][0])
1248 strcpy(panel.playerNames[np++], gameInfo.players[c]);
1251 blokus.btnPass.visible = false;
1252 blokus.gameState.NewGame();
1253 blokus.passed[0] = false;
1254 blokus.passed[1] = false;
1255 blokus.passed[2] = false;
1256 blokus.passed[3] = false;
1257 blokus.gameStarted = true;
1258 blokus.lightValue = 1;
1259 blokus.lightDir = -.1f;
1260 blokus.turnLightTimer.Start();
1261 blokus.UpdatePlayerNames();
1263 blokus.Update(null);
1265 panel.UpdateControlsStates();
1266 panel.ListPlayers();
1273 panel.ListPlayers();
1275 blokus.gameStarted = false;
1276 blokus.Update(null);
1279 void MovePlayed(PlayerColor color, int pieceType, int direction, bool flip, int boardX, int boardY)
1281 blokus.gameState.PlayMove(pieceType, direction, flip, boardX, boardY);
1282 if(color == blokus.colorPlayed)
1283 blokus.NextColorPlayed();
1285 if(blokus.colorPlayed == blokus.gameState.colorTurn &&
1286 !blokus.gameState.validMove && !blokus.gameState.over)
1288 if(!blokus.passed[blokus.gameState.colorTurn])
1289 blokus.btnPass.visible = true;
1291 panel.server.Pass();
1294 // This hangs here, why?
1295 /*if(blokus.gameState.over)
1296 scoresPanel.visible = true;*/
1299 blokus.UpdatePlayerNames();
1300 blokus.Update(null);
1304 void Passed(PlayerColor color)
1306 blokus.gameState.Pass();
1307 if(color == blokus.colorPlayed)
1308 blokus.NextColorPlayed();
1310 if(blokus.colorPlayed == blokus.gameState.colorTurn &&
1311 !blokus.gameState.validMove && !blokus.gameState.over)
1313 if(!blokus.passed[blokus.gameState.colorTurn])
1314 blokus.btnPass.visible = true;
1316 panel.server.Pass();
1321 blokus.UpdatePlayerNames();
1322 blokus.Update(null);
1326 void NotifyMessage(String name, String msg)
1328 EditBox log = blokus.chat.log;
1329 char * format = (log.numLines > 1 || log.line.count) ?
1330 "\n%s: %s" : "%s: %s";
1331 blokus.chat.Log(format, name, msg);
1334 incref panel.server;
1335 if(panel.server.Connect(serverAddress.contents, BLOKUS_PORT))
1337 int playerID = panel.server.Join();
1338 if(panel.server && playerID != -1)
1339 panel.server.SetName(playerName.contents);
1341 panel.server.Disconnect(0);
1342 UpdateControlsStates();
1345 delete panel.server;
1350 Button btnDisconnect
1352 this, text = "Disconnect", altD, font = { "Arial", 16, bold = true }, size = { 126, 32 }, position = { 256, 64 }, visible = false;
1354 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1357 panel.server.Disconnect(0);
1363 this, text = "Host", altH, font = { "Arial", 16, bold = true }, size = { 90, 32 }, position = { 16, 112 };
1365 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1367 if(!blokus.gameStarted)
1369 if(blokusService.Start())
1373 UpdateControlsStates();
1379 Button btnStopHosting
1381 this, text = "Stop Hosting", altP, font = { "Arial", 16, bold = true }, position = { 16, 112 }, visible = false;
1383 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1386 blokusService.Stop();
1390 UpdateControlsStates();
1396 this, text = "Start Game", altS, font = { "Arial", 16, bold = true }, size = { 124, 32 }, position = { 256, 112 }, visible = false;
1398 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1403 UpdateControlsStates();
1410 this, text = "Stop Game", altG, font = { "Arial", 16, bold = true }, position = { 256, 112 }, visible = false;
1412 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1415 UpdateControlsStates();
1421 this, text = "Players Connected", altD, size = { 236, 84 }, position = { 16, 176 }, visible = false, hasHeader = true;
1423 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
1425 UpdateControlsStates();
1429 Label lblListPlayers { this, font = { "Tahoma", 8.25f, bold = true }, position = { 16, 152 }, visible = false, labeledWindow = listPlayers };
1432 this, text = "Kick", altK, font = { "Arial", 16, bold = true }, size = { 80, 32 }, position = { 264, 224 }, visible = false;
1434 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1436 DataRow row = listPlayers.currentRow;
1438 KickPlayer(row.tag);
1444 this, text = "Player Name:", altN, font = { "Arial", 12 }, size = { 132, 24 }, position = { 104, 8 }, contents = "BlokusPlayer"
1446 Label lblPlayerName { this, font = { "Tahoma", 8.25f, bold = true }, position = { 16, 16 }, labeledWindow = playerName };
1449 CommunicationPanel panel { };
1451 DCOMService blokusService { port = BLOKUS_PORT };