Tutorial Project. Release 3
From wiki.visual-prolog.com
Revision as of 14:47, 20 October 2009 by Victor Yukhtenko (talk | contribs) (New page: This program is part of the Tutorial Project Evolutions article. {{PolyLine Game Rules}} {{note|content= The size of the playing field in the code set 6x6<br/>It is not recommended t...)
This program is part of the Tutorial Project Evolutions article.
Game description
- The game is played on an M x N board.
Game rules
- Each player on his turn adds a new point. The point must prolong the existing Polyline (or start the Polyline, if it doesn't exist).
- The resulting Polyline must be non-interrupted and each move can be taken in any of end of the line.
- The player, which locks the line (the point is set on the polyline), wins.
The size of the playing field in the code set 6x6 It is not recommended to set the size of the field more than 36 points (say 6 x 6) due to the non efficient algorithm used |
The strategy of the computer behaviour adopted from the Tutorial Project. Release 1 (written by Elena Efimova).
Differences (relative to version 2):
- It can be more then 2 players;
- The type of each player (computer or human) is by choice
To run the game please make the steps as follows:
- Create the new project with the User Interface strategy Console
- In the created project replace the entire content of the file "main.pro" by the code shown below (VIP 7.2 only)
- While building the project answer "Add All", when any dialog with proposals to include any packages to the project appears
/***************************************************************************** Copyright (c) 2007-2008 Prolog Development Center SPb SpbSolutions/Examples/Polyline Written by: Victor Yukhtenko Predicates, which represent the strategy neighbour_nd, neighbourOutOfPolyLine_nd, resolveStep, successfulStep, stepCandidate based on solutions proposed by Elena Efimova ********************************************/ goal mainExe::run(main::run). /************ Class Main ************/ implement main open core constants className = "main". classVersion = "1.0". clauses classInfo(className, classVersion). clauses run():- console::init(), game::run(). end implement main class game open core predicates classInfo : core::classInfo. predicates run:(). end class game implement game open core constants className = "game". classVersion = "1.0". clauses classInfo(className, classVersion). class facts playerNo_V:positive:=1. clauses run():- humanInterface::announceStartUp(), PlayerType=humanInterface::getInput(humanInterface::playerType_S,toString(playerNo_V)), not(PlayerType=""), try Player=createPlayerObject(toTerm(PlayerType)), seniourJudge::addPlayer(Player), playerNo_V:=playerNo_V+1 catch _TraceID do humanInterface::announceManagerError(humanInterface::errorPlayerType_S) end try, !, run(). run():- startingPlayer(). class predicates playListMember:()->string nondeterm. clauses playListMember()=PlayersListMember:- I = std::fromTo(1, list::length(seniourJudge::players_V)), Player=list::nth(I-1,seniourJudge::players_V), PlayersListMember=string::format("\n% - %",I,Player:name). class predicates startingPlayer:(). clauses startingPlayer():- not(seniourJudge::players_V=[]) and not(seniourJudge::players_V=[_SiglePlayer]), findAll(PlayListMember,PlayListMember=playListMember(),PlayList), PlayListStr=string::concatList(PlayList), StartingPlayerStr=humanInterface::getInput(humanInterface::startingPlayer_S,PlayListStr), not(StartingPlayerStr=""), try StartingPlayer=toTerm(StartingPlayerStr), !, startGame(StartingPlayer) catch _TraceID1 do humanInterface::announceManagerError(humanInterface::errorMustBeNumber_S), !, startingPlayer() end try. startingPlayer(). class predicates startGame:(positive). clauses startGame(StartingPlayer):- try Player=list::nth(StartingPlayer-1,seniourJudge::players_V), % list::nth(...) needs unsigned !, seniourJudge::play(Player) catch _Trace_D do humanInterface::announceManagerError(humanInterface::errorStartingPlayer_S), ! end try, !, startingPlayer(). class predicates createPlayerObject:(positive)->player. clauses createPlayerObject(1)=Player:- !, Player=human::new(). createPlayerObject(2)=Player:- !, Player=computer::new(). createPlayerObject(_)=_Player:- exception::raise(classInfo,wrongInputException,[]). class predicates wrongInputException:exception. clauses wrongInputException ( classInfo, predicate_Name(), "" ). end implement game /************************ Class seniorJudge ************************/ class seniourJudge open core properties players_V:player*. inProgress_V:boolean. predicates play:(player CurrentPlayer). addPlayer:(player NextPlayer). end class seniourJudge implement seniourJudge open core, humanInterface class facts players_V:player*:=[]. inProgress_V:boolean:=false. clauses play(Player):- inProgress_V=false, humanInterface::showStage(), inProgress_V:=true, Player:move(), humanInterface::announceStarter(Player:name), play(Player), !. play(Player):- juniourJudge::isGameOver(), !, Player:announceWin(), foreach (Participant=list::getMember_nd(players_V) and not(Participant=Player)) do Participant:announceLoss() end foreach, inProgress_V:=false, juniourJudge::reset(). play(Player):- NextPlayer=nextPlayer(Player), NextPlayer:move(), !, play(NextPlayer). clauses addPlayer(NextPlayer):- players_V:=list::append(players_V,[NextPlayer]). class predicates nextPlayer:(player CurrentPlayer)->player NextPlayer. clauses nextPlayer(Player)=NextPlayer:- Index=list::tryGetIndex(Player,players_V), NextPlayer=list::tryGetNth(Index+1,players_V), !. nextPlayer(_Player)=list::nth(0,players_V). end implement seniourJudge /************************ Class juniourJudge ************************/ class juniourJudge open core predicates classInfo : core::classInfo. domains cell = c(positive,positive). stepType_D= ordinary_S; winner_S. properties maxRow_P:positive. maxColumn_P:positive. polyline_P:cell*. predicates neighbour_nd: (cell,cell) nondeterm (i,o) (i,i). neighbourOutOfPolyLine_nd:(cell,cell)->cell nondeterm. set: (string ). isGameOver:() determ. reset:(). end class juniourJudge implement juniourJudge open core, humanInterface constants className = "JuniourJudge". classVersion = "1.0". clauses classInfo(className, classVersion). class facts maxRow_P:positive:=6. maxColumn_P:positive:=6. polyline_P:cell*:=[]. endOfGame_V:boolean:=false. clauses isGameOver():- endOfGame_V=true. clauses set(InputString):- Cell=toTerm(InputString), handleInput (Cell). clauses reset():- juniourJudge:: polyline_P:=[], juniourJudge::endOfGame_V:=false. class predicates handleInput:(juniourJudge::cell). clauses handleInput(Cell):- list::isMember(Cell,polyline_P), try _=makePolyLine(Cell,polyline_P) % it will be an exception if wrong Cell, but we ignore it by failing catch _TraceID do fail end try, !, endOfGame_V:=true, humanInterface::showStep(Cell,winner_S). handleInput (Cell):- polyline_P:=makePolyLine(Cell,polyline_P), !, humanInterface::showStep(Cell,ordinary_S). class predicates makePolyLine: (cell,cell*)-> cell* multi. clauses makePolyLine(c(X,Y),[])=[c(X,Y)]:- X>0,X<=maxColumn_P, Y>0,Y<=maxRow_P, !. makePolyLine(NewCell,[SingleCell])=[NewCell,SingleCell]:- neighbour_nd(SingleCell, NewCell), !. makePolyLine(NewCell,[Left, RestrictingCell | PolyLineTail])=[NewCell, Left, RestrictingCell | PolyLineTail]:- NewCell=neighbourOutOfPolyLine_nd(Left,RestrictingCell). makePolyLine(NewCell,PolyLine)=list::reverse([NewCell,Left, RestrictingCell | PolyLineTail]):- [Left, RestrictingCell | PolyLineTail]= list::reverse(PolyLine), NewCell=neighbourOutOfPolyLine_nd(Left,RestrictingCell). makePolyLine(NewCell,_PolyLine)= _PolyLine1:- exception::raise(classInfo,wrongStepException,[namedValue("data",string(toString(NewCell)))]). class predicates wrongStepException:exception. clauses wrongStepException ( classInfo, predicate_Name(), "the point % can not prolong the polyline!" ). clauses neighbourOutOfPolyLine_nd(Cell,RestrictingCell)=NewCell:- neighbour_nd(Cell,NewCell), not(NewCell = RestrictingCell). clauses neighbour_nd(c(X, Y), c(X + 1, Y)):- X < maxColumn_P. neighbour_nd(c(X, Y), c(X, Y + 1)):- Y < maxrow_P. neighbour_nd(c(X, Y), c(X - 1, Y)):- X > 1. neighbour_nd(c(X, Y), c(X, Y - 1)):- Y > 1. end implement juniourJudge /****************************************** Interface Player ******************************************/ interface player predicates move:(). announceWin:(). announceLoss:(). properties name:string. end interface player /****************************************** Class human ******************************************/ class human:player open core end class human implement human open core facts name:string:=string::format("Hum_%",toString(This)). clauses new():- Name=humanInterface::getInput(humanInterface::playerName_S,name), if not(Name="") then name:=Name end if. clauses move():- InputString=humanInterface::getInput(humanInterface::playerStep_S), try juniourJudge::set(InputString) catch TraceID do handleException(TraceID), fail end try, !. move():- move(). clauses announceWin():- humanInterface::announceWin(name). announceLoss():- humanInterface::announceLoss(name). class predicates handleException:(exception::traceId TraceID). clauses handleException(TraceID):- foreach Descriptor=exception::getDescriptor_nd(TraceID) do Descriptor = exception::descriptor( _ClassInfo1, exception::exceptionDescriptor(_ClassInfo2,_PredicateName,Description), _Kind, ExtraInfo, _GMTTime, _ExceptionDescription, _ThreadId), if ExtraInfo=[namedValue("data",string(CellPointer))] then ErrorMsg=string::format(Description,CellPointer), humanInterface::announceError(ErrorMsg) else humanInterface::announceError("") end if end foreach. end implement human /****************************************** Class computer ******************************************/ class computer:player open core end class computer implement computer open core facts name:string:=string::format("Cmp_%",toString(This)). clauses new():- Name=humanInterface::getInput(humanInterface::playerName_S,name), if not(Name="") then name:=Name end if. clauses move():- humanInterface::announceThinker(name), Cell=resolveStep(), juniourJudge::set(toString(Cell)). predicates resolveStep:()->juniourJudge::cell. clauses resolveStep()=Cell:- Cell=successfulStep(juniourJudge::polyline_P), !. resolveStep()=Cell:- stepCandidate(juniourJudge::polyline_P,_PolyLine,Cell), !. resolveStep()=juniourJudge::c(X+1,Y+1):- X=math::random(juniourJudge::maxColumn_P-1), Y=math::random(juniourJudge::maxRow_P-1). class predicates successfulStep: (juniourJudge::cell*)->juniourJudge::cell nondeterm. clauses successfulStep(PolyLine)=Cell:- stepCandidate(PolyLine,_PolyLine1,Cell), list::isMember(Cell, PolyLine), !. successfulStep(PolyLine)=Cell:- stepCandidate(PolyLine, PolyLine1, Cell), not(_=successfulStep(PolyLine1)). class predicates stepCandidate: (juniourJudge::cell*,juniourJudge::cell* [out],juniourJudge::cell [out]) nondeterm. clauses stepCandidate([Cell],[Cell,NewCell], NewCell):- juniourJudge::neighbour_nd(Cell, NewCell). stepCandidate([Left, RestrictingCell | PolyLine],[NewCell,Left, RestrictingCell| PolyLine], NewCell):- NewCell=juniourJudge::neighbourOutOfPolyLine_nd(Left,RestrictingCell). stepCandidate(PolyLine,list::reverse([NewCell,Left, RestrictingCell |PolyLineTail]),NewCell):- [Left, RestrictingCell |PolyLineTail] = list::reverse(PolyLine), NewCell=juniourJudge::neighbourOutOfPolyLine_nd(Left,RestrictingCell). clauses announceWin():- humanInterface::announceWin(name). clauses announceLoss():- humanInterface::announceLoss(name). end implement computer /****************************************** Class HumanInterface ******************************************/ class humanInterface open core predicates announceStartUp:(). predicates showStage:(). showStep:(juniourJudge::cell,juniourJudge::stepType_D). getInput:(inputType_D,string StringParameter)->string InputString. getInput:(inputType_D)->string InputString. predicates announceManagerError:(choiceError_D). predicates announceStarter:(string Name). announceThinker:(string Name). announceWin:(string Name). announceLoss:(string Name). announceError:(string Description). announceError:(). domains choiceError_D= errorPlayerType_S; errorMustBeNumber_S; errorstartingPlayer_S. domains inputType_D= playerStep_S; playerType_S; playerName_S; startingPlayer_S. end class humanInterface implement humanInterface open core constants cellMarkedOrdinary_C="*". cellMarkedWinner_C="O". constants % messages thinker_C="% is thinking ...". beginner_C="First move done by: %". error_C="Error, % ". congratulation_C="Player % won!". sorryLoss_C="%, Sorry, you loss :-(". playerStep_C="Please enter your move as c(X,Y): ". playerType_C="\nPlayer #%s. Please enter the player type (1-human, 2-computer, Enter - end of choice):". playerName_C="\nPlease assign the name to the player (% proposed):". startingPlayer_C="\nWho moves the first (PlayerNo or Enter - end of the game)?:". errorPlayerType_C="\nNo such player type exists! Enter - repeat input:". errorMustBeNumber_C="\nMust be number! Please repeat input:". errorstartingPlayer_C="\nNo such Player exiasts! Please repeat input:". constants verticalSpace_C=2. horizontalSpace_C=3. emptyLineLenght_C=80. constants % Position of Line starterLine_C=1. announceLine_C=starterLine_C+1. actionLine_C=announceLine_C+1. polylineLine_C=actionLine_C+1. clauses getInput(InputType)=Input:- Input=getInput(InputType,""). getInput(InputType,StringParameter)=Input:- inputInvitation(InputType,StringParameter), Input = console::readLine(), console::clearInput(). class predicates inputInvitation:(inputType_D,string StringParameter). clauses inputInvitation(playerStep_S,_StringParameter):- clearMessageArea(actionLine_C), writeMessage(actionLine_C,"%",playerStep_C). inputInvitation(playerName_S,StringParameter):- console::writef(playerName_C,StringParameter). inputInvitation(playerType_S,StringParameter):- console::writef(playerType_C,StringParameter). inputInvitation(startingPlayer_S,StringParameter):- console::write(StringParameter,startingPlayer_C). clauses showStage():- console::clearOutput(), foreach I = std::fromTo(1, juniourJudge::maxColumn_P) do console::setLocation(console_native::coord(horizontalSpace_C*I, 0)), console::write(I) end foreach, foreach J = std::fromTo(1, juniourJudge::maxRow_P) do console::setLocation(console_native::coord(0, verticalSpace_C*J)), console::write(J) end foreach. clauses showStep(juniourJudge::c(X,Y),_Type):- console::setLocation(console_native::coord(horizontalSpace_C*X, verticalSpace_C*Y)), fail. showStep(_Cell,juniourJudge::ordinary_S):- console::write(cellMarkedOrdinary_C). showStep(_Cell,juniourJudge::winner_S):- console::write(cellMarkedWinner_C). clauses announceStartUp():- console::clearOutput(). clauses announceStarter(Name):- clearMessageArea(starterLine_C), writeMessage(starterLine_C,beginner_C,Name). clauses announceManagerError(errorPlayerType_S):- console::write(errorPlayerType_C), _=console::readLine(). announceManagerError(errorMustBeNumber_S):- console::write(errorMustBeNumber_C). announceManagerError(errorstartingPlayer_S):- console::write(errorstartingPlayer_C). clauses announceError():- announceError(""). announceError(ErrorText):- clearMessageArea(announceLine_C), writeMessage(announceLine_C,error_C,ErrorText). clauses announceWin(Name):- clearMessageArea(announceLine_C), writeMessage(announceLine_C,congratulation_C,Name), showPolyLine(), _ = console::readLine(). announceLoss(Name):- clearMessageArea(announceLine_C), writeMessage(announceLine_C,sorryLoss_C,Name), showPolyLine(), _ = console::readLine(). clauses announceThinker(Name):- clearMessageArea(announceLine_C), clearMessageArea(actionLine_C), writeMessage(actionLine_C,thinker_C,Name). class predicates showPolyLine:(). clauses showPolyLine():- clearMessageArea(actionLine_C), writeMessage(polylineLine_C,"%",toString(juniourJudge::polyline_P)). class predicates clearMessageArea:(positive AreaID). clauses clearMessageArea(AreaID):- console::setLocation(console_native::coord(0,juniourJudge::maxRow_P*verticalSpace_C+AreaID)), console::write(string::create(emptyLineLenght_C," ")). class predicates writeMessage:(positive AreaID,string FormatString,string ParameterString). clauses writeMessage(AreaID,FormatString,ParameterString):- console::setLocation(console_native::coord(0, juniourJudge::maxRow_P*verticalSpace_C+AreaID)), console::writef(FormatString,ParameterString). end implement humanInterface