5 // FOR COMMUNICATION //////////////////////////////////////////
12 void OnSerialize(SerialBuffer buffer)
16 buffer.Serialize(letter);
17 buffer.Serialize(blankValue);
20 void OnUnserialize(SerialBuffer buffer)
22 buffer.Unserialize(x);
23 buffer.Unserialize(y);
24 buffer.Unserialize(letter);
25 buffer.Unserialize(blankValue);
36 void OnSerialize(SerialBuffer buffer)
39 buffer.Serialize(numTiles);
41 buffer.Serialize(tiles[c]);
42 buffer.Serialize(player);
43 buffer.Serialize(score);
46 void OnUnserialize(SerialBuffer buffer)
49 buffer.Unserialize(numTiles);
51 buffer.Unserialize(tiles[c]);
52 buffer.Unserialize(player);
53 buffer.Unserialize(score);
62 void OnSerialize(SerialBuffer buffer)
64 buffer.Serialize(language);
65 buffer.Serialize((StaticString)players[0]);
66 buffer.Serialize((StaticString)players[1]);
67 buffer.Serialize((StaticString)players[2]);
68 buffer.Serialize((StaticString)players[3]);
71 void OnUnserialize(SerialBuffer buffer)
73 buffer.Unserialize(language);
74 buffer.Unserialize((StaticString)players[0]);
75 buffer.Unserialize((StaticString)players[1]);
76 buffer.Unserialize((StaticString)players[2]);
77 buffer.Unserialize((StaticString)players[3]);
81 //////////////////////////////////////////
91 ServerConnection connection;
99 static char * dicos[Languages] = { ":englishWords.txt", ":frenchWords.txt" };
103 int lettersAvailable[Letters];
104 int numLettersAvailable;
105 AVLTree<String> dictionary { };
107 Player players[MaxPlayers];
110 property Languages language
115 LoadWords(dicos[value]);
119 Letters board[15][15];
120 Letters blankValues[15][15];
128 for(c = 0; c<MaxPlayers; c++)
137 void GetTiles(int tilesPlayer, PlayedMove move)
139 Player player = players[tilesPlayer];
143 while(player.numLetters < 7 && numLettersAvailable)
146 int r = (Letters)GetRandom(0, numLettersAvailable-1);
149 for(letter = 0; letter<Letters::empty; letter++)
151 a += lettersAvailable[letter];
155 numLettersAvailable--;
156 lettersAvailable[letter]--;
158 player.letters[player.numLetters] = letter;
161 move.tiles[move.numTiles++].letter = letter;
170 for(c = 0; c<MaxPlayers; c++)
179 PlayedMove tiles { };
181 numLettersAvailable = 0;
183 for(l = 0; l<Letters::empty; l++)
185 numLettersAvailable += lettersCount[language][l];
186 lettersAvailable[l] = lettersCount[language][l];
189 seed = (uint)(GetTime() * 1000);
192 //Logf("Seeded with %d\n", seed);
194 for(y = 0; y<15; y++)
195 for(x = 0; x<15; x++)
196 board[y][x] = blankValues[y][x] = empty;
199 for(c = 0; c<MaxPlayers; c++)
208 strcpy(list.players[0], crossWordsGame.players[0] ? crossWordsGame.players[0].name : "");
209 strcpy(list.players[1], crossWordsGame.players[1] ? crossWordsGame.players[1].name : "");
210 strcpy(list.players[2], crossWordsGame.players[2] ? crossWordsGame.players[2].name : "");
211 strcpy(list.players[3], crossWordsGame.players[3] ? crossWordsGame.players[3].name : "");
212 list.language = crossWordsGame.language;
214 for(c = 0; c<MaxPlayers; c++)
217 crossWordsGame.GetTiles(c, tiles);
218 crossWordsGame.players[c].connection.GameStarted(list, tiles);
223 void LoadWords(char * fileName)
225 File f = FileOpen(fileName, read);
232 f.GetLine(word, sizeof(word));
235 String s = CopyString(word);
236 if(!dictionary.Add(CopyString(word)))
244 IteratorPointer test1, test2;
245 test1 = dictionary.Find("gewurztraminer");
246 test2 = dictionary.Find("gewurstraminer");
251 bool CheckWord(Letters newBoard[15][15], Direction direction, int where, int start, int end, int * score)
257 int wordMultiplier = 1;
259 for(c = start; c<= end; c++)
261 int y = direction ? c : where;
262 int x = direction ? where : c;
263 Letters letter = newBoard[y][x];
266 if(board[y][x] == empty)
268 if(squareValues[y][x] == doubleLetter) multiplier = 2;
269 else if(squareValues[y][x] == tripleLetter) multiplier = 3;
272 wordScore += lettersValue[language][letter] * multiplier;
274 if(board[y][x] == empty)
276 if(squareValues[y][x] == doubleWord) wordMultiplier *= 2;
277 else if(squareValues[y][x] == tripleWord) wordMultiplier *= 3;
281 letter = blankValues[y][x];
282 word[len++] = (char)letter + 'a';
285 found = dictionary.Find(word) != null;
286 Logf("%s: %s\n", word, found ? "found :)" : "not found :(");
288 *score += wordScore * wordMultiplier;
292 bool VerifyMove(Letters newBoard[15][15], int * score)
297 Direction direction = horizontal;
301 int firstX = MAXINT, lastX = MININT;
302 int firstY = MAXINT, lastY = MININT;
303 int first, last, where;
304 int wordStart, wordEnd;
305 bool anchored = false;
309 for(y = 0; y<15; y++)
311 for(x = 0; x<15; x++)
313 if(board[y][x] == empty && newBoard[y][x] != empty)
317 if(x < firstX) firstX = x;
318 if(y < firstY) firstY = y;
319 if(x > lastX) lastX = x;
320 if(y > lastY) lastY = y;
325 if(!numLetters) return false;
326 if(lastY - firstY > 0)
328 if(lastX - firstX > 1) return false;
329 direction = vertical;
331 else if(lastX - firstX == 0)
333 if(((firstY > 0 && newBoard[firstY-1][firstX] != empty) ||
334 (firstY < 14 && newBoard[firstY+1][firstX] != empty)) &&
335 ((firstX == 0 || newBoard[firstY][firstX-1] == empty) &&
336 (firstX == 14 || newBoard[firstY][firstX+1] == empty)))
337 direction = vertical;
340 first = direction ? firstY : firstX;
341 last = direction ? lastY : lastX;
343 where = direction ? firstX : firstY;
345 for(c = first; c <= last; c++)
347 Letters letter = direction ? newBoard[c][where] : newBoard[where][c];
348 if(letter == empty) return false;
351 for(c = first; c>=0; c--)
353 Letters letter = direction ? newBoard[c][where] : newBoard[where][c];
354 if(letter == empty) break;
359 for(c = last; c<15; c++)
361 Letters letter = direction ? newBoard[c][where] : newBoard[where][c];
362 if(letter == empty) break;
367 if(!CheckWord(newBoard, direction, where, wordStart, wordEnd, score))
370 for(c = first; c <= last; c++)
372 if((direction ? board[c][where] : board[where][c]) == empty)
374 int wordStart, wordEnd;
377 for(a = where; a>=0; a--)
379 Letters letter = direction ? newBoard[c][a] : newBoard[a][c];
380 if(letter == empty) break;
385 for(a = where; a<15; a++)
387 Letters letter = direction ? newBoard[c][a] : newBoard[a][c];
388 if(letter == empty) break;
393 if(wordEnd > wordStart)
394 if(!CheckWord(newBoard, direction^1, c, wordStart, wordEnd, score))
400 if(newBoard[7][7] != empty && board[7][7] == empty) anchored = true;
401 if(!anchored) return false;
402 if(numLetters == 7) *score += 50;
411 for(c = 0; c<MaxPlayers; c++)
413 delete crossWordsGame.players[c];
420 CrossWordsGame crossWordsGame;
422 remote class ServerConnection
432 //crossWordsGame.players[player.id] = null;
433 delete crossWordsGame.players[player.id];
435 crossWordsGame.EndGame();
442 if(!crossWordsGame.gameStarted)
445 for(c = 0; c<MaxPlayers; c++)
447 if(!crossWordsGame.players[c])
452 player = crossWordsGame.players[c] = Player { id = c };
453 player.connection = this;
455 incref crossWordsGame.players[c];
462 bool SetName(const String name)
466 player.name = CopyString(name);
467 if(!crossWords.scoreFields[player.id])
469 crossWords.scoreFields[player.id] = DataField { dataType = class(int), header = name, width = 40 };
470 //incref crossWords.scoreFields[player.id];
471 crossWords.scores.AddField(crossWords.scoreFields[player.id]);
473 crossWords.scoreFields[player.id].header = name;
478 bool PlayTiles(PlayedMove move)
480 if(player && crossWordsGame.players[crossWordsGame.curPlayer] == player)
482 Letters newBoard[15][15];
486 memcpy(newBoard, crossWordsGame.board, 15*15*sizeof(Letters));
487 for(c = 0; c<move.numTiles; c++)
489 if(newBoard[move.tiles[c].y][move.tiles[c].x] == empty)
491 newBoard[move.tiles[c].y][move.tiles[c].x] = move.tiles[c].letter;
492 crossWordsGame.blankValues[move.tiles[c].y][move.tiles[c].x] = move.tiles[c].blankValue;
497 if(crossWordsGame.VerifyMove(newBoard, &score))
499 for(c = 0; c<move.numTiles; c++)
503 for(d = 0; d<player.numLetters; d++)
504 if(player.letters[d] == move.tiles[c].letter)
506 memmove(player.letters + d, player.letters + d + 1, sizeof(int) * (player.numLetters - d - 1));
513 Logf("Letter not found!\n");
518 player.totalScore += score;
519 memcpy(crossWordsGame.board, newBoard, 15*15*sizeof(Letters));
521 crossWordsGame.curMove = move;
522 crossWordsGame.curMove.player = crossWordsGame.curPlayer;
523 crossWordsGame.curMove.score = score;
526 crossWordsGame.GetTiles(crossWordsGame.curPlayer, move);
528 for(c = 0; c<MaxPlayers; c++)
529 if(crossWordsGame.players[c])
530 crossWordsGame.players[c].connection.MovePlayed(crossWordsGame.curMove);
532 do { if(++crossWordsGame.curPlayer == MaxPlayers) crossWordsGame.curPlayer = 0; } while(!crossWordsGame.players[crossWordsGame.curPlayer]);
539 bool DiscardTiles(PlayedMove move)
541 if(player && crossWordsGame.numLettersAvailable >= move.numTiles && crossWordsGame.players[crossWordsGame.curPlayer] == player)
544 PlayedMove newTiles { };
546 for(c = 0; c<move.numTiles; c++)
549 for(d = 0; d<player.numLetters; d++)
550 if(player.letters[d] == move.tiles[c].letter)
552 memmove(player.letters + d, player.letters + d + 1, sizeof(int) * (player.numLetters - d - 1));
558 crossWordsGame.GetTiles(crossWordsGame.curPlayer, newTiles);
560 for(c = 0; c<move.numTiles; c++)
562 crossWordsGame.lettersAvailable[move.tiles[c].letter]++;
563 crossWordsGame.numLettersAvailable++;
566 crossWordsGame.curMove = { }; // TODO: Add informing other players of number of exchanged letters when passing...
567 crossWordsGame.curMove.player = crossWordsGame.curPlayer;
571 for(c = 0; c<MaxPlayers; c++)
572 if(crossWordsGame.players[c])
573 crossWordsGame.players[c].connection.MovePlayed(crossWordsGame.curMove);
575 do { if(++crossWordsGame.curPlayer == MaxPlayers) crossWordsGame.curPlayer = 0; } while(!crossWordsGame.players[crossWordsGame.curPlayer]);
582 virtual void MovePlayed(PlayedMove move);
583 virtual void GameStarted(PlayerList list, PlayedMove tiles);