10 enum Kind : byte { clubs, diamonds, hearts, spades, none = 0xFF };
11 enum Number : byte { _5, _7, _8, _9, _10, jack, queen, king, ace };
13 struct Card // class Card : uint16
19 static String cardsNames[] =
21 ":ac.png", ":ad.png", ":ah.png", ":as.png", ":2c.png", ":2d.png", ":2h.png", ":2s.png", ":3c.png", ":3d.png", ":3h.png", ":3s.png",
22 ":4c.png", ":4d.png", ":4h.png", ":4s.png", ":5c.png", ":5d.png", ":5h.png", ":5s.png", ":6c.png", ":6d.png", ":6h.png", ":6s.png",
23 ":7c.png", ":7d.png", ":7h.png", ":7s.png", ":8c.png", ":8d.png", ":8h.png", ":8s.png", ":9c.png", ":9d.png", ":9h.png", ":9s.png",
24 ":10c.png", ":10d.png", ":10h.png", ":10s.png",":jc.png", ":jd.png", ":jh.png", ":js.png", ":qc.png", ":qd.png", ":qh.png", ":qs.png",
25 ":kc.png", ":kd.png", ":kh.png", ":ks.png", ":rb.png", ":rr.png"
28 static define CARD_WIDTH = 111;
29 static define CARD_HEIGHT = 150;
31 static define GAP = 38;
33 enum PlayerPosition : byte { bottom, left, top, right, none = 0xFF };
40 enum PlayerType { local = 1, remotePlayer, ai };
44 PlayerPosition player;
45 // Range: 40-100, 0xFF: "ruff"
52 PlayerPosition shuffle;
76 define MAXROUNDS = 256;
78 define LT_RED = Color { 255, 85, 85 };
79 define LT_BLUE = Color { 85, 85, 255 };
85 Round rounds[MAXROUNDS];
87 int cardSet; // Which of the 9 cards we're at in this round
88 PlayerPosition turn; // Which player whose turn it is to play
89 PlayerPosition start; // Which player put the first card out of 4
98 int RUFF_FirstValidCard(RuffGame * game, Player * player)
102 if(RUFF_Legal(game, player, c))
107 enum MessageType : byte
136 // SERVER TO CLIENT ( ** SETUP ** )
137 struct S2CWelcome : Message
142 struct S2CPlayerInfo : Message
148 struct S2CCardPlayed : Message
155 struct S2CBet : Message
161 struct S2CTrump : Message
166 struct S2CEndOfRound : Message
171 struct S2CReqAck : Message
174 int scores0, scores1;
177 struct S2CNewRound : Message
184 struct S2CStartHand : Message
190 // CLIENT TO SERVER ( ** SETUP ** )
192 struct C2SPlayerName : Message
197 struct C2SPlaceBet : Message
202 struct C2SChoseTrump : Message
207 struct C2SPlayCard : Message
214 void Player_PlaceBet(Player player, int bet)
218 C2SPlaceBet placeBet { sizeof(C2SPlaceBet), C2S_PLACEBET, bet };
219 player.socket.Send(placeBet, sizeof(placeBet));
222 Server_PlaceBet(player.game, player, bet);
225 void Player_ChoseTrump(Player player, Kind trump)
229 C2SChoseTrump choseTrump { sizeof(C2SChoseTrump), C2S_CHOSETRUMP, trump };
230 player.socket.Send(choseTrump, sizeof(choseTrump));
233 Server_ChoseTrump(player.game, player, trump);
236 void Player_PlayCard(Player player, int card)
238 Ruff ruff = player.ruff;
240 ruff.selectedCard = None;
243 C2SPlayCard playCard { sizeof(C2SPlayCard), C2S_PLAYCARD, card };
244 player.socket.Send(playCard, sizeof(playCard));
246 player.cards[card].kind = none;
249 Server_PlayCard(player.game, player, card);
252 void Player_Ack4Cards(Player player, PlayerPosition winner, int scores0, int scores1)
254 Ruff ruff = player.ruff;
255 RuffGame * game = &ruff.game;
257 // ruff.waitingAck = false;
259 ruff.lastWinner = winner;
260 ruff.lastStart = game->start;
261 if(game->played[0].kind != none)
263 CopyBytes(ruff.lastPlayed,game->played, sizeof(Card) * 4);
264 FillBytes(game->played, None, sizeof(Card) * 4);
269 // Message msg { sizeof(Message), C2S_ACK4CARDS };
270 // player.socket.Send(, &msg, sizeof(msg));
272 game->rounds[game->round].scores[0] = scores0;
273 game->rounds[game->round].scores[1] = scores1;
275 ruff.scores.Update(null);
279 void Player_SetName(Player player, char * name)
281 Ruff ruff = player.ruff;
284 C2SPlayerName * playerName = (C2SPlayerName *)new byte[sizeof(C2SPlayerName) + strlen(name)];
285 playerName->type = C2S_PLAYERNAME;
286 playerName->size = sizeof(C2SPlayerName) + strlen(name);
287 strcpy(playerName->name, name);
288 player.socket.Send(playerName, playerName->size);
292 Server_SetName(player.game, player, name);
295 // SERVER TO CLIENT : Informations
296 void Player_InformPlayerInfo(Player player, PlayerPosition who, char *name)
298 Ruff ruff = player.ruff;
299 RuffGame * game = &ruff.game;
301 strcpy(game->players[who].name, name);
303 ruff.scores.Update(null);
311 S2CPlayerInfo * playerInfo = (S2CPlayerInfo *)new byte[sizeof(S2CPlayerInfo) + strlen(name)];
312 playerInfo->type = S2C_PLAYERINFO;
313 playerInfo->size = sizeof(S2CPlayerInfo) + strlen(name);
314 playerInfo->id = who;
315 strcpy(playerInfo->name, name);
316 player.socket.Send(playerInfo, playerInfo->size);
324 void Player_InformStartGame(Player player)
326 Ruff ruff = player.ruff;
327 RuffGame * game = &ruff.game;
330 for(c = 0; c<11; c++)
331 player.cards[c].kind = none;
333 game->played[c].kind = none;
335 ruff.lastWinner = none;
336 ruff.lastStart = none;
337 ruff.lastPlayed[0].kind = ruff.lastPlayed[1].kind =
338 ruff.lastPlayed[2].kind = ruff.lastPlayed[3].kind = none;
339 game->gameStarted = true;
341 ruff.setup.EnableButtons();
343 ruff.scores.Update(null);
345 ruff.selectedCard = None;
352 ruff.playedPlayer = player.id;
357 Message startGame { sizeof(Message), S2C_STARTGAME };
358 player.socket.Send(startGame, sizeof(startGame));
365 void Player_InformStopGame(Player player)
367 Ruff ruff = player.ruff;
368 RuffGame * game = &ruff.game;
370 game->gameStarted = false;
371 ruff.trump.Destroy(0);
374 ruff.setup.EnableButtons();
376 ruff.scores.Update(null);
384 Message stopGame { sizeof(Message), S2C_STOPGAME };
385 player.socket.Send(stopGame, sizeof(stopGame));
392 void Player_InformNewRound(Player player, int r, PlayerPosition shuffle, Card * cards)
394 Ruff ruff = player.ruff;
395 RuffGame * game = &ruff.game;
400 player.cards[c] = cards[c];
402 game->betting = true;
404 round = &game->rounds[game->round];
405 round->bet.howMuch = 0;
406 round->bet.trump = none;
407 round->bet.player = none;
408 round->shuffle = shuffle;
409 round->scores[0] = round->scores[1] = 0;
416 ruff.scores.Update(null);
421 AI_InformNewRound(player, r, shuffle, cards);
426 S2CNewRound newRound { sizeof(S2CNewRound), S2C_NEWROUND, r, shuffle };
427 CopyBytes(newRound.cards, cards, sizeof(newRound.cards));
428 player.socket.Send(newRound, sizeof(newRound));
434 void Player_InformBet(Player player, PlayerPosition who, int howMuch)
436 Ruff ruff = player.ruff;
437 RuffGame * game = &ruff.game;
438 Round * round = &game->rounds[game->round];
446 round->bet.player = who;
447 round->bet.howMuch = howMuch;
450 ruff.scores.Update(null);
455 AI_InformBet(player, who, howMuch);
460 S2CBet bet { sizeof(S2CBet), S2C_BET, who, howMuch };
461 player.socket.Send(bet, sizeof(bet));
467 void Player_InformTrump(Player player, Kind trump)
469 Ruff ruff = player.ruff;
470 RuffGame * game = &ruff.game;
471 Round * round = &game->rounds[game->round];
472 game->betting = false;
477 round->bet.trump = trump;
479 ruff.scores.Update(null);
484 AI_InformTrump(player, trump);
489 S2CTrump informTrump { sizeof(S2CTrump), S2C_TRUMP, trump };
490 player.socket.Send(informTrump, sizeof(informTrump));
496 void Player_InformStartHand(Player player, PlayerPosition start)
498 Ruff ruff = player.ruff;
499 RuffGame * game = &ruff.game;
506 ruff.scores.Update(null);
512 S2CStartHand startHand { sizeof(S2CStartHand), S2C_STARTHAND, start };
513 player.socket.Send(startHand, sizeof(startHand));
519 void Player_InformCardPlayed(Player player, int who, Kind kind, Number number)
521 Ruff ruff = player.ruff;
522 RuffGame * game = &ruff.game;
528 game->played[who].kind = kind;
529 game->played[who].number = number;
531 ruff.scores.Update(null);
536 AI_InformCardPlayed(player, who, kind, number);
541 S2CCardPlayed cardPlayed { sizeof(S2CCardPlayed), S2C_CARDPLAYED, who, kind, number };
542 player.socket.Send(cardPlayed, sizeof(cardPlayed));
548 void Player_InformEndOfRound(Player player, int score0, int score1)
550 Ruff ruff = player.ruff;
551 RuffGame * game = &ruff.game;
556 Round * round = &game->rounds[game->round];
557 round->scores[0] = score0;
558 round->scores[1] = score1;
563 AI_InformEndOfRound(player, score0, score1);
568 S2CEndOfRound endOfRound { sizeof(S2CEndOfRound), S2C_ENDOFROUND, score0, score1 };
569 player.socket.Send(endOfRound, sizeof(endOfRound));
574 ruff.scores.Update(null);
577 // SERVER TO CLIENT : Requests
578 void Player_RequestBet(Player player)
580 Ruff ruff = player.ruff;
581 RuffGame * game = &ruff.game;
589 game->turn = player.id;
590 ruff.playedPlayer = player.id;
591 ruff.selectedCard = None;
593 sprintf(temp, "Your bet, %s?", player.name);
594 ruff.bet.text = temp;
595 ruff.bet.visible = true;
598 ruff.scores.Update(null);
603 AI_RequestBet(player);
608 Message reqBet { sizeof(Message), S2C_REQBET };
609 player.socket.Send(reqBet, sizeof(reqBet));
615 void Player_RequestTrump(Player player)
617 Ruff ruff = player.ruff;
625 ruff.playedPlayer = player.id;
626 ruff.selectedCard = None;
628 sprintf(temp, "Chose your trump, %s?", player.name);
629 ruff.trump.text = temp;
632 ruff.scores.Update(null);
636 AI_RequestTrump(player);
640 Message reqTrump { sizeof(Message), S2C_REQTRUMP };
641 player.socket.Send(reqTrump, sizeof(reqTrump));
647 void Player_RequestCard(Player player)
649 Ruff ruff = player.ruff;
650 RuffGame * game = &ruff.game;
655 ruff.playedPlayer = player.id;
656 game->turn = player.id;
657 ruff.selectedCard = RUFF_FirstValidCard(game, player);
659 ruff.scores.Update(null);
662 AI_RequestCard(player);
666 Message reqCard { sizeof(Message), S2C_REQCARD };
667 player.socket.Send(reqCard, sizeof(reqCard));
673 void Player_Request4CardsAck(Player player, PlayerPosition winner, int scores0, int scores1)
675 Ruff ruff = player.ruff;
676 RuffGame * game = &ruff.game;
681 // ruff.waitingAck = true;
682 Player_Ack4Cards(player, winner, scores0, scores1);
685 // ruff.waitingAck = true;
689 S2CReqAck reqAck { sizeof(S2CReqAck), S2C_REQACK, winner, scores0, scores1 };
690 player.socket.Send(reqAck, sizeof(reqAck));
699 text = "The Ruff Card Game";
700 borderStyle = sizable;
701 hasMaximize = true, hasMinimize = true, hasClose = true;
702 anchor = { horz = -0.1, vert = -0.1 };
703 clientSize = { 926, 688 };
704 background = { 0, 128, 0 };
722 font = FontResource { "Tahoma", 8.25f },
723 anchor = Anchor { horz = 25, vert = 55 },
725 void NotifyDestroyed(Window window, DialogResult result)
727 Player * player = &game.players[playedPlayer];
729 Player_PlaceBet(player, (int)result);
736 font = FontResource { "Tahoma", 8.25f },
738 anchor = Anchor { horz = 25, vert = 55 };
739 void NotifyDestroyed(Window window, DialogResult result)
741 Player * player = &game.players[playedPlayer];
743 Player_ChoseTrump(player, (Kind)result);
748 Bitmap bitmapCards[52];
750 font = FontResource { "Comic Sans MS Bold", 16 };
754 PlayerPosition playedPlayer;
755 PlayerPosition lastWinner;
756 PlayerPosition lastStart;
761 void OnRedraw(Surface surface)
763 Player * player = (playedPlayer != none) ? &game.players[playedPlayer] : null;
764 Round * round = &game.rounds[game.round];
766 static const Point playedPos[] = { { 461, 528 }, { 268, 372 }, { 461, 215 }, { 652, 372 } };
767 static const Point lastPlayedPos[] = { { 430, 497 }, { 238, 340 }, { 430, 184 }, { 621, 340 } };
768 static const Point namePos[] = { { 313, 585 }, { 156, 422 }, { 688, 254 }, { 844, 422 } };
778 if(player->cards[c].kind != none)
780 if(c != selectedCard)
781 RUFF_DrawCard(surface, c * GAP + player->cards[c].kind * CARD_WIDTH, 20, &player->cards[c]);
786 if(selectedCard != None && player->cards[selectedCard].kind != none)
787 RUFF_DrawCard(surface,
788 selectedCard * GAP + player->cards[selectedCard].kind * CARD_WIDTH, 0,
789 &player->cards[selectedCard]);
792 // This round's bet and trump
793 if(round->bet.howMuch)
795 surface.SetForeground((round->bet.player == playedPlayer) ? LT_RED : black);
796 surface.CenterTextf(868, 164, "%d",round->bet.howMuch);
797 if(round->bet.trump != none)
800 card.kind = round->bet.trump;
802 RUFF_DrawCard(surface, 813, 0, &card);
804 surface.CenterTextf(868, 200, game.players[round->bet.player].name);
810 if(lastPlayed[c].kind != none)
811 RUFF_DrawCard(surface, lastPlayedPos[c].x, lastPlayedPos[c].y, &lastPlayed[c]);
813 if(game.played[c].kind != none)
814 RUFF_DrawCard(surface, playedPos[c].x, playedPos[c].y, &game.played[c]);
816 RUFF_DrawCard(surface, playedPos[c].x, playedPos[c].y, null);
818 if(!game.betting && c == game.start)
820 surface.SetForeground(LT_RED);
821 surface.CenterTextf(playedPos[c].x + 10, playedPos[c].y + 50, "S");
825 surface.SetForeground(LT_BLUE);
826 surface.CenterTextf(lastPlayedPos[c].x + 10, lastPlayedPos[c].y + 70, "W");
830 surface.SetForeground(LT_RED);
831 surface.CenterTextf(lastPlayedPos[c].x + 10, lastPlayedPos[c].y + 50, "S");
838 surface.SetForeground((playedPlayer == c) ? LT_RED : black);
839 surface.CenterTextf(namePos[c].x, namePos[c].y,game.players[c].name);
843 bool OnLeftButtonDown(int x, int y, Modifiers mods)
845 if(selectedCard != None && playedPlayer != none)
847 Player * player = &game.players[playedPlayer];
852 int start = c * GAP + player->cards[c].kind * CARD_WIDTH;
853 if(y>=0 && y<CARD_HEIGHT+GAP && x>=start && x<start+CARD_WIDTH)
855 if(RUFF_Legal(game, player,c))
864 Player * player = &game.players[game.turn];
865 // Player_Ack4Cards(player);
870 bool OnLeftDoubleClick(int x, int y, Modifiers mods)
872 if(selectedCard != None && playedPlayer != none)
874 Player * player = &game.players[playedPlayer];
879 int start = c * GAP + player->cards[c].kind * CARD_WIDTH;
880 if(y>=0 && y<CARD_HEIGHT+GAP && x>=start && x<start+CARD_WIDTH)
882 if(RUFF_Legal(game, player,c))
885 Player_PlayCard(player, c);
895 bool OnKeyHit(Key key, unichar ch)
897 if(selectedCard != None && playedPlayer != none)
899 Player * player = &game.players[playedPlayer];
900 switch((SmartKey)key)
903 Player_PlayCard(player, selectedCard);
912 if(selectedCard==9) selectedCard=0;
913 if(RUFF_Legal(game, player, selectedCard))
927 if(selectedCard==-1) selectedCard=8;
928 if(RUFF_Legal(game, player,selectedCard))
938 else if(waitingAck && (SmartKey)key == enter)
940 Player * player = &game.players[game.turn];
941 // Player_Ack4Cards(player);
953 bool OnLoadGraphics()
956 cardBack.LoadT(":back.png", null, displaySystem);
959 bitmapCards[i] = Bitmap {};
960 bitmapCards[i].LoadT(cardsNames[i], null, displaySystem);
965 void OnUnloadGraphics()
969 delete bitmapCards[i];
973 void RUFF_DrawCard(Surface surface, int x, int y, Card card)
976 static const int cardNo[9]=
978 // 5, 7, 8, 9,10, J, Q, K, A
979 4, 6, 7, 8, 9, 10, 11, 12, 0
983 bitmap = bitmapCards[cardNo[card.number] * 4 + card.kind];
987 surface.Blit(bitmap, x, y, 0,0, bitmap.width,bitmap.height);
993 class RuffApp : GuiApplication
1001 ruff.setup.Activate();