$CASE/06f522/SetGame06f/setGameSetup.c - RJL 061125 (adapted from 03f522); 1. game description 2. defining the SetgameFacet SF State Model 3. 03f522 Take-home Problem: (revised 061125-RJL) 1. game description ---------------------- This was a take-home problem for the second hour exam in 03f522. The handout paper from javareport Sept 2001 explains the game and shows its trivial specialized solutions. Our goal is to reuse LCP architecture and its OPclass StateModel to design a more generic game controller SG and card facet evaluator SF for a set of 3 cards (oUt of 12 that are dealt). This evalauation is done whenever an Operator (OP instance) sends a set selection message on behalf of its human user. Any number of persons can play the game, and each one gets an OP class instance. The OP sends an event to a shared Game Controller; this event instance or EI has three integer arguments (range [0..11]); each one identifies a particular card by number. Each of the 12 cards in the tableau or layout (a 3 by 4 card array) has 4 integer values representing a tuple of facet dimension values. (These dimensions are color, shape, number, and fill pattern, and each one has three variations represented by 0, 1, and 2.) [Fill pattern was wrongly called dimension in some solution notes). SG is the SetGame controller which evaluates the validity of a 3-card set selected by a player from a 12-card array or tableau that is dealt to start the game; this array shrinks as a valid set is removed and is then restored to 12 cards as long as unused cards remain in the deck. SG is not the complete game controller. Network aspects like player connection and registration and arbitration among nar-simultaneous Player actions are out of scope, and located elsewhere in the game simulator or DSGServer. Each time a set is selected SG returns a verdict to the DSGServer which decides whether and how to restore the 12-card layout. DSGServer sends new card selection and array location events to the DSGClient players. Then play continues until no more valid sets are found; the game ends after at most 81/3 iterations. 2. defining the SetgameFacet SF State Model ------------------------------------ I have declared below what I think is a valid set of ST, TR and ET rows, for the SF Facet Evaluator State Model below, according to the logsim and test_architecture.c examples in $CASE. Doing the same for the SG controller is left as an exercise. /* GameOfSet.c - RJL 031109 * Ref: www.javareport.com, jave Reprt Sep 2001 (25-29) * www.setgame.com/set/brain.htm * Create the ST,ET, and TR elements; auto-generate the EN association. * for a state machine SF that accepts a sequence of three event types * that correspond to the three values of a facet from three cards, * and returns PASS = 1 if all three cards agree or all three have * different facet values. Otherwise (two agree and the third one * differs) returns FAIL = 0. * The SG controller machine can call one AI four times (once for each facet), * or send a different facet value to each of four concurrent AI * instances running independently. (SG is not sp3cified here.) * There is one OP class instance per DSGClient (person playing the game). * If co-located, they can watch a shared display, or from remote locations * via DBDE or other network arrangement they can watch synchronized copies. */ static EventTYpeList SGEventType[] = { { "SF00", "facetvalue is 0"}, { "SF01", "facetvalue is 1"}, { "SF02", "facetvalue is 2"}, { "SG03", "PASS: goto S0"}, { "SG04", "FAIL: goto S0"} }; /* SG is game controller; SF is facet evaluator.*/ static StateList SFStates[] = { /* StateName, ActName, ActFunc */ { "S0", "SFAction0", SFAction0}, { "S1", "SFAction1", SFAction1}, { "S2", "SFAction2", SFAction2}, { "S3", "SFAction3", SFAction3}, { "S4", "SFAction4", SFAction4}, { "S5", "SFAction5", SFAction5}, { "S6", "SFAction6", SFAction6}, }; static StateTransitionList SFTransitions[] = { /*source, destin, eventtype*/ {"S0", "S1", "SF00"}, {"S0", "S2", "SF01"}, {"S0", "S3", "SF02"}, {"S1", "S4", "SF00"}, {"S1", "S8", "SF01"}, {"S1", "S6", "SF02"}, {"S2", "S5", "SF00"}, {"S2", "S6", "SF01"}, {"S2", "S4", "SF02"}, {"S3", "S6", "SF00"}, {"S3", "S4", "SF01"}, {"S3", "S5", "SF02"}, {"S4", "S7", "SF00"}, {"S4", "S8", "SF01"}, {"S4", "S8", "SF02"}, {"S5", "S8", "SF00"}, {"S5", "S8", "SF01"}, {"S5", "S7", "SF02"}, {"S6", "S8", "SF00"}, {"S6", "S7", "SF01"}, {"S6", "S8", "SF02"}, {"S7", "S0", "SF00"}, {"S7", "S0", "SF01"}, {"S7", "S0", "SF02"}, {"S8", "S0", "SF00"}, {"S8", "S0", "SF01"}, {"S8", "S0", "SF02"} }; SFSMid = StateModelCreateCompletely("SetGameMachine", "SF"); // SM for Facet Eval. SFACid = ActiveClassCreate("SetGameActiveClass", SFSMid); //fkey to SM SFAIid = ActiveInstanceCreate("SF1", SFACid, "S0"); //init state is S0 pr_init("SetGame.vdf", ""); // Don't search for pre-allocated pkeys in other files. /* State Actions: No-OP for all states except S7 and S8. * S7 sends a reply EI whose ET is SG04 = PASS to client SGAIid * S8 sends a reply EI whose ET is SG05 = FAIL to client SGAIid; */ /* The SG State Model is a chain of four states S9 thru S12. * Each state sends 3 EI's to machine SF, one for each card's value * of the facet dimension that corresponds to SG's state number. * If the PASS reply event is received, transition is to the next * state; otherwise SG returns FAIL to its client (the set selector). * If state S12 is reached, then SG returns PASS to its client. * A diagram illustrated this SM. It is not declared here. * * As in lcp04s, another procedure makeHead() should be called during * SFsetup and SGsetup. Its purposee is to provide the * Action Rouine ptr array FuncTbl[] by which the run phase program * LCPmain.exe jumps to each State's action routine. */ 3. 03f522 Take-home Problem: (revised 061125-RJL) ------------------------------------------ Define the SG state-model as for SF above, and write the SGaction and SFaction routines for each state of SG and SF. Place the action methods in SFsetup.c and SGsetup.c, and the State Models in SFsetup.c and SGsetup.c. Imitate the architecture of $CASE/04s522/lcp04s/lechner/lcp/src/*.c, where LCPmain.c is the run phase main LCPsetup.c is the setup phase main program; PAssigner.c is the master-mind of Hominid (adapt it for the DSGServer mastermind of SetGame). HDaction.c and HLaction.c are the run phase state model action routines; HDsetup.c and HLsetup.c are the state model declarations for the setup phase. Combine all table declarations into SetGame06f.sch. Run 'chgen13 -log -metafile SetGame06f.sch' to generate t pr_*.c and schema.h. (You can adapt CASE//04s522/lcp04s/{aajalopez,lechner}/LCPgen for this.) Be sure setgameschema.sch declares all the table types you need. Then try compiling your SFsetup.c, SGsetup.c and OPsetup.c with pr_*.c files and run LCPsetup.exe. You can adapt LCPsetuprun for this - it runs both make -f Makesetup and make -f Makerun. Similarly compile SGaction.c, SFaction.c, OPaction.c with DSGClient.c and DSGSserver.c and link them with LCP and the OP class. #include the proper .h files and the LCP interpreter source code (cpy -r $CASE/04s522/lcp04s/lechner/lcp/olc) This should be application-independent. You can adapt LCPsetuprun for this - it runs both make -f Makesetup and make -f Makerun. Note: The actions of SG and SF are trivial, except for generating events. They do NOT need to change AIcurr->Sstate; the LCP dispatcher does that. Some states need to generate events. In particular, the OPerator as tester needs to accept the player's selectiion of (or a script file containing) a set-selection triple (some that make sense and ought to be a 'winner', and some 'losers')) from the 12-card layout, and send it to the DSGServer as an event instance with 3 card numbers as arguments. The DSGServer SG machine reads one facet dimension from each card in the selected triple, and sends it to the SF facet evaluator. Four facets are evaluated sequentially by four iterations of one facet evaluator (SF) ActiveInstance (or by sending four events to four AI's for evaluation concurrently, if desired). After four facet value triples from three cards have been sent, SG waits for a SF reply that enables its own transition: from state S9 to S12 if all four facets are valid, or to a FAIL exit if at least one facet is invalid. SG needs to exit after each set of 3 cards is evaluated. The DSGServer has the tasks of notifying the OPerator interface to a human player with a reply event type that can be PASS/FAIL; howwever, an error message number or string can also be sent as an EI parameter, to identify the first facet that is invalid. (Each SF-state's FAIL exit to SG should have a different error message.) A set selection iterator could provide exhaustive testing of all binomial(12,3) = 220 triples on the 12-card array. An array or table of 220 PASS/FAIL values can be generated for every possible triple of cards on one test 12-card array. The human operator who tentatively selects a set of 3 cards in effect causes the DSGServer to restart a new SG-simulation each time. Arbitrating among simultaneous 'I_see_a_set' claims is out of the scope of these two StateModels. Perhaps a third SM for the DSGServer as GameController could model more of the network setup and multi-player aspects. When playing the set game, each triple that PASSes is removed so 3 new cards must be added. A replacement triple is rendomly selected one card at a time from the remaining unused cards in the deck; THis should be repeated after each set is removed from the layout. The new triple should never contain a previously used card. Alternately, a permutation can save a random sequence of the numbers 0..80 to simulate a shuffled deck, from which the cards are sequentially removed to replenish the card layout or game board. This does not require any list maintenance (item marking or deletion).