From f8074f5e0228dde3e34f495ce63351286c5165cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Teuli=C3=A8re?= Date: Sat, 7 Aug 2004 18:25:03 +0000 Subject: [PATCH] Forgot these files --- game/player.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++ game/player.h | 117 ++++++++++++++++++++++++ 2 files changed, 365 insertions(+) create mode 100644 game/player.c create mode 100644 game/player.h diff --git a/game/player.c b/game/player.c new file mode 100644 index 0000000..aac7b90 --- /dev/null +++ b/game/player.c @@ -0,0 +1,248 @@ +/* Eliot */ +/* Copyright (C) 2004 Eliot */ +/* Olivier Teuliere */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* $Id: player.c,v 1.1 2004/08/07 18:25:03 ipkiss Exp $ */ + +#include +#include + +#include "dic.h" +#include "tiles.h" +#include "rack.h" +#include "pldrack.h" +#include "round.h" +#include "results.h" +#include "board.h" +#include "player.h" + +#include "debug.h" + +struct tplayer { + int human; + int score; + play_status status; /* Only used for duplicate mode currently */ + + /* History of the racks and rounds for the player */ + int nracks; + Playedrack racks[PLAYEDRACK_MAX]; + Round rounds[PLAYEDRACK_MAX]; + int turns[PLAYEDRACK_MAX]; + + /* Results of a search with the current rack */ + Results searchresults; +}; + + +Player +Player_create(void) +{ + int i; + Player p; + p = (Player) malloc(sizeof(struct tplayer)); + if (p == NULL) + return NULL; + + for (i = 0; i < PLAYEDRACK_MAX; i++) + { + p->racks[i] = Playedrack_create(); + p->rounds[i] = Round_create(); + } + p->searchresults = Results_create(); + + return p; +} + + +static void +Player_init(Player p, int human) +{ + int i; + + p->score = 0; + p->human = human; + p->status = TO_PLAY; + p->nracks = 0; + for (i = 0; i < PLAYEDRACK_MAX; i++) + { + Playedrack_init(p->racks[i]); + Round_init(p->rounds[i]); + } + Results_init(p->searchresults); +} + + +void +Player_inithuman(Player p) +{ + Player_init(p, 1); +} + + +void +Player_initai(Player p) +{ + Player_init(p, 0); +} + + +void +Player_destroy(Player p) +{ + int i; + if (p) + { + for (i = 0; i < PLAYEDRACK_MAX; i++) + { + Playedrack_destroy(p->racks[i]); + Round_destroy(p->rounds[i]); + } + Results_destroy(p->searchresults); + free(p); + } +} + + +Playedrack +Player_getplayedrack(Player p) +{ + return p->racks[p->nracks]; +} + + +Playedrack +Player_getlastrack(Player p) +{ + return p->racks[p->nracks - 1]; +} + + +Round +Player_getlastround(Player p) +{ + return p->rounds[p->nracks - 1]; +} + + +int +Player_getpoints(Player p) +{ + return p->score; +} + + +void +Player_addpoints(Player p, int s) +{ + p->score += s; +} + + +void +Player_setstatus(Player p, play_status stat) +{ + p->status = stat; +} + + +play_status +Player_getstatus(Player p) +{ + return p->status; +} + + +/* + * This function increments the number of racks, and fills the new rack + * with the unplayed tiles from the previous one. + * 03 sept 2000 : We have to sort the tiles according to the new rules + */ +void +Player_endturn(Player p, Round round, int turn) +{ + tile_t i; + Rack rack; + + p->turns[p->nracks] = turn; + Round_copy(p->rounds[p->nracks], round); + + /* Increment the number of racks + * We are now going to deal with p->racks[p->nracks - 1] and + * p->racks[p->nracks] */ + p->nracks++; + + rack = Rack_create(); + Playedrack_getrack(p->racks[p->nracks - 1], rack); + + /* We remove the played tiles from the rack */ + for (i = 0; i < Round_wordlen(round); i++) + { + if (Round_playedfromrack(round, i)) + { + if (Round_joker(round,i)) + Rack_remove(rack, (tile_t)JOKER_TILE); + else + Rack_remove(rack, Round_gettile(round, i)); + } + } + + Playedrack_init(p->racks[p->nracks]); + Playedrack_setold(p->racks[p->nracks], rack); + Rack_destroy(rack); +} + + +int +Player_ai(Player p) +{ + return ! p->human; +} + + +int +Player_ai_search(Player p, Dictionary dic, Board board, int turn) +{ + Rack rack; + if (dic == NULL) + return 1; + + Results_init(p->searchresults); + + rack = Rack_create(); + Playedrack_getrack(p->racks[p->nracks], rack); + if (turn == 0) + Board_search_first(dic, board, rack, p->searchresults); + else + Board_search(dic, board, rack, p->searchresults); + Rack_destroy(rack); + return 0; +} + + +Round +Player_ai_bestround(Player p) +{ + return Results_get(p->searchresults, 0); +} + + +Results +Player_ai_getresults(Player p) +{ + return p->searchresults; +} + diff --git a/game/player.h b/game/player.h new file mode 100644 index 0000000..ee8c953 --- /dev/null +++ b/game/player.h @@ -0,0 +1,117 @@ +/* Eliot */ +/* Copyright (C) 2004 Eliot */ +/* Olivier Teuliere */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* $Id: player.h,v 1.1 2004/08/07 18:25:03 ipkiss Exp $ */ + +#ifndef _PLAYER_H_ +#define _PLAYER_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Number of played words. + * There are only 102 tiles, so we should be safe even if only one tile is + * played at each turn... */ +#define PLAYEDRACK_MAX 102 + + /************************* + * A player can be a human player, or a computer player (AI) + *************************/ + +typedef struct tplayer *Player; + + /************************* + * Player general routines + *************************/ + +Player Player_create (void); +void Player_inithuman (Player); +void Player_initai (Player); +void Player_destroy (Player); + + /************************** + * General getters + **************************/ + +Playedrack Player_getplayedrack (Player); +Playedrack Player_getlastrack (Player); +Round Player_getlastround (Player); + + /************************** + * + **************************/ + +void Player_endturn (Player,Round,int); + + /************************** + * Add (or remove, if the given value is negative) points + * to the player's score. + **************************/ + +void Player_addpoints (Player,int); +int Player_getpoints (Player); + + /************************** + * + **************************/ + +typedef enum {PLAYED, TO_PLAY} play_status; +void Player_setstatus (Player,play_status); +play_status Player_getstatus (Player); + + /************************** + * AI (Artificial Intelligence) handling + * The int argument of Player_ai_search() is the 'turn' number + * (starting from 0) + * Note: we could implement various strategies: + * - best: play the word with the best score (current implementation) + * - second: play the word with the second best score (strictly lower than + * the best one) + * - random: randomly choose one of the possible words + * - handicap(p): in the array of the n possible words (sorted by + * decreasing scores), play the word number i, where i/n is nearest + * from a predefined percentage p. + * So 'handicap(0)' should be equivalent to 'best'. + * This strategy makes an interesting opponent, because you can adapt + * it to your level, with a careful choice of the p value. + * + * In fact, instead of working on the score of the words, these strategies + * could work on any other value. In particular, some heuristics could + * modulate the score with a value indicating the openings offered by the + * word (if a word makes accessible a "word counts triple" square, it is less + * interesting than another word with the same score or even with a slightly + * lower score, but which does not offer such a square). + * + * More evolved heuristics could even take into account the remaining letters + * in the bag to guess the 'statistical rack' of the opponent, and play a + * word both maximizing the score and minimizing the opponent's score... + * Hmmm... i don't think this one will be implemented in a near future :) + **************************/ + +int Player_ai (Player); +int Player_ai_search (Player,Dictionary,Board,int); +Round Player_ai_bestround (Player); // XXX: useful? +Results Player_ai_getresults (Player); + +#if defined(__cplusplus) + } +#endif +#endif + +