// created on 23/11/2005 at 22:25
using System;
using System.Text;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using RedCorona.Net;
using RedCorona.Net.Games;
using RedCorona.Components;
namespace RedCorona.GameClient.GameTypes.Bridge.UI {
public class TrickPanel : Panel {
BridgeGame game;
internal Trick[] Tricks = new Trick[13];
internal int currentTrick;
internal TrickPanel(BridgeGame game){
this.game = game;
}
internal void Clear(){
currentTrick = 0;
game.TricksWon[0] = game.TricksWon[1] = 0;
Tricks[0] = new Trick((game.declarer + 1) % 4);
if(nextPhase != null) Controls.Remove(nextPhase);
}
internal int NextToPlay {
get {
if((currentTrick < 0) || (currentTrick > 12)) return -1;
if(Tricks[currentTrick].played >= 4) return -1;
return (Tricks[currentTrick].leader + Tricks[currentTrick].played) % 4;
}
}
internal void NextPlay(){
// Do the next action (only called if we own the game)
ByteBuilder b = new ByteBuilder();
Invalidate();
if(currentTrick >= 13) {
return;
} else if(Tricks[currentTrick].played >= 4){
BumpTrick();
Pauser.RunAfterPause(this, new MethodInvoker(NextPlay), 250);
return;
}
BridgePlayer player = game.Players[NextToPlay], actor;
if(player.isDummy) actor = player.opposite;
else actor = player;
if(actor.Player == null){
// Computer
int card;
try {
Card c = actor.GetCard(Tricks[currentTrick], player);
Console.WriteLine("Chose "+BridgePlayer.formatCard(c.Value)+" because "+c.Message);
card = c.Value;
} catch(Exception e) {
card = 0;
Console.WriteLine("wtf ... "+e);
}
SubmitCard(Tricks[currentTrick].played, card);
return;
} else if(actor.Player.ID == game.Lobby.MyID){
// It's me, so don't be silly and go off the server
Invalidate();
} else {
b.AddParameter(ClientInfo.UintToBytes(BridgeCommands.RequestCard), ParameterType.Int);
b.AddParameter(ClientInfo.IntToBytes(player.Player.ID), ParameterType.Int);
b.AddParameter(ClientInfo.IntToBytes(game.Game.ID), ParameterType.Int);
game.Lobby.SendMessage(ReservedCodes.PassToMember, b.Read(0, b.Length), 0);
}
}
void SubmitCard(int posn, int card){
Console.WriteLine("Submitted card "+card+" at "+posn);
ByteBuilder b = new ByteBuilder();
b.AddParameter(ClientInfo.UintToBytes(BridgeCommands.PlayCard), ParameterType.Int);
b.AddParameter(ClientInfo.IntToBytes(game.Game.ID), ParameterType.Int);
b.AddParameter(ClientInfo.IntToBytes(posn), ParameterType.Int);
b.AddParameter(ClientInfo.IntToBytes(card), ParameterType.Int);
game.Lobby.SendMessage(ReservedCodes.GameBroadcast, b.Read(0, b.Length), 0);
}
internal void DoCard(int posn, int card){
if(posn != Tricks[currentTrick].played)
game.DoWarning("OOS (DoCard): posn("+posn+") != tpos("+Tricks[currentTrick].played+")");
int pp = (Tricks[currentTrick].leader + posn) % 4;
if(!game.Players[pp].cards[card]){
game.DoWarning("Attempt to play bad card! ("+posn+"/"+BridgePlayer.formatCard(card)+")");
return;
}
if(Tricks[currentTrick].cards[posn] >= 0){
game.DoWarning("Error (DoCard): card already played by this player");
return;
}
game.Players[pp].remove(card);
for(int i = 0; i < 4; i++) game.Players[i].cardsgone[card] = true;
Tricks[currentTrick].cards[posn] = card;
if(posn == 0){
Tricks[currentTrick].suit = card / 13;
if(currentTrick == 0) game.dummy = game.Players[(game.declarer + 2) % 4];
} else {
int winningcard = Tricks[currentTrick].WinningCard;
if((((card / 13) == (winningcard / 13)) && (card > winningcard)) || (((card / 13) == game.trumps) && ((winningcard / 13) != game.trumps))){
Console.WriteLine("-- New winner "+BridgePlayer.formatCard(card)+" over "+BridgePlayer.formatCard(winningcard));
Tricks[currentTrick].winning = (Tricks[currentTrick].leader + posn) % 4;
}
if(Tricks[currentTrick].suit != card / 13) game.Players[pp].voids[Tricks[currentTrick].suit] = true;
}
Tricks[currentTrick].played = posn + 1;
UpdateText();
Invalidate();
if((posn == 3) && !game.OwnsGame){
Pauser.RunAfterPause(this, new MethodInvoker(BumpTrick), 500);
}
//Thread.Sleep(300);
}
void BumpTrick(){
game.TricksWon[Tricks[currentTrick].winning % 2]++;
currentTrick++;
if(currentTrick < 13) Tricks[currentTrick] = new Trick(Tricks[currentTrick - 1].winning);
else Finish((int)GameState.Debrief, "Go to the debriefing for this round");
UpdateText();
}
String cardMsg = "";
internal void UpdateText(){
// We should always run GetCard because if a player then
// leaves, the computer has all the right information set
// to carry on (who's shown which suit etc)
if(NextToPlay < 0) return;
BridgePlayer pl = game.Players[NextToPlay], actor;
if(pl.isDummy) actor = pl.opposite;
else actor = pl;
Card card = actor.GetCard(Tricks[currentTrick], pl);
if(actor.Player == null){
// Computer
cardMsg = "AI playing from "+Constants.seats[NextToPlay];
} else if(actor.Player.ID == game.Lobby.MyID){
Console.WriteLine(cardMsg = "AI Hint � " + BridgePlayer.formatCard(card.Value) + ": " + card.Message);
} else {
cardMsg = "Waiting for " + actor.Player.DisplayName + "...";
}
if((currentTrick < 13) && (Tricks[currentTrick].played == 4)){
currentTrick++;
}
if((currentTrick >= 13)){
Finish((int)GameState.Debrief, "Click here to continue");
return;
}
}
// UI
Font f = new Font("Arial", 8.5F);
Font fbold = new Font("Arial", 8.5F, FontStyle.Bold);
Font fbig = new Font("Arial", 14);
Brush blackBrush = new SolidBrush(Color.Black);
float[] cardx = new float[4], cardy = new float[4];
protected override void OnPaint(PaintEventArgs e){
Graphics g = e.Graphics;
int suit = -1;
if((currentTrick < 13) && (currentTrick >= 0)) suit = Tricks[currentTrick].suit;
if(game.CanSee(0)) game.Players[0].PaintHand(g, (ClientSize.Width / 2) - 50, 20, game.IsControlled(0) && (NextToPlay == 0), suit);
if(game.CanSee(1)) game.Players[1].PaintHand(g, ClientSize.Width - 100, (ClientSize.Height / 2) - 30, game.IsControlled(1) && (NextToPlay == 1), suit);
if(game.CanSee(2)) game.Players[2].PaintHand(g, (ClientSize.Width / 2) - 50, ClientSize.Height - 70, game.IsControlled(2) && (NextToPlay == 2), suit);
if(game.CanSee(3)) game.Players[3].PaintHand(g, 10, (ClientSize.Height / 2) - 30, game.IsControlled(3) && (NextToPlay == 3), suit);
cardx[0] = cardx[2] = (ClientSize.Width / 2) - 15;
cardx[3] = 110; cardx[1] = ClientSize.Width - 140;
cardy[1] = cardy[3] = (ClientSize.Height / 2) - 8;
cardy[0] = 85; cardy[2] = ClientSize.Height - 100;
g.DrawString("Declarer: ", fbold, blackBrush, ClientSize.Width - 100, 10);
g.DrawString(game.Players[game.declarer].ToString(), f, blackBrush, ClientSize.Width - 100, 20);
g.DrawString("Contract: ", fbold, blackBrush, ClientSize.Width - 100, 33);
PaintContract(g, game.contract, ClientSize.Width - 100, 43);
g.DrawString("Tricks won: ", fbold, blackBrush, 10, 10);
g.DrawString("N/S: "+game.TricksWon[0]+"; E/W: "+game.TricksWon[1], f, blackBrush, 10, 20);
g.DrawString(cardMsg, f, blackBrush, 5, ClientSize.Height - 15);
if((currentTrick < 13) && (currentTrick >= 0))
for(int i = 0; i < Tricks[currentTrick].played; i++){
int inx = (i + Tricks[currentTrick].leader) % 4;
int card = Tricks[currentTrick].cards[i];
g.DrawImage(Constants.suitimages[card / 13], cardx[inx], cardy[inx]);
g.DrawString(Constants.cardnames[card % 13], fbig, blackBrush, cardx[inx] + 15, cardy[inx]);
}
}
Button nextPhase;
void Finish(int buttonState, String caption){
nextPhase = new Button();
nextPhase.Text = caption;
nextPhase.Font = f;
nextPhase.Left = 0; nextPhase.Top = ClientSize.Height - 20;
nextPhase.Width = ClientSize.Width; nextPhase.Height = 20;
nextPhase.Tag = buttonState;
nextPhase.Click += new EventHandler(nextPhaseClick);
nextPhase.Enabled = game.OwnsGame;
Controls.Add(nextPhase);
}
void nextPhaseClick(object sender, EventArgs e){
game.SetData("state", (int)(sender as Control).Tag, false, 1);
(sender as Control).Enabled = false;
}
internal void PaintContract(Graphics g, Contract c, float x, float y){
//g.DrawString(BidPanel.getLevel(c.bid).ToString(), f, blackBrush, x, y);
//g.DrawImage(Constants.suitimagessmall[BidPanel.getSuit(c.bid)], x + 8, y - 1);
String s = BidPanel.getLevel(c.bid) + Constants.suits_short[BidPanel.getSuit(c.bid)];
switch(c.doublestate){
case 0: break;
case 1:
s += " doubled";//, f, blackBrush, x + 20, y);
break;
case 2:
s += " redoubled";//, f, blackBrush, x + 20, y);
break;
}
g.DrawString(s, f, blackBrush, x, y);
}
protected override void OnMouseDown(MouseEventArgs e){
base.OnMouseDown(e);
if(NextToPlay < 0) return;
for(int i = 0; i < 13; i++){
ActiveRegion ar = game.Players[NextToPlay].regions[i];
if(ar == null) continue;
if((e.X >= ar.Left) && (e.X <= ar.Left + ar.Width) && (e.Y >= ar.Top) && (e.Y <= ar.Top + ar.Height)){
SubmitCard(Tricks[currentTrick].played, ar.card);
break;
}
}
}
}
}