(* Content-type: application/mathematica *) (*** Wolfram Notebook File ***) (* http://www.wolfram.com/nb *) (* CreatedBy='Mathematica 6.0' *) (*CacheID: 234*) (* Internal cache information: NotebookFileLineBreakTest NotebookFileLineBreakTest NotebookDataPosition[ 145, 7] NotebookDataLength[ 35830, 912] NotebookOptionsPosition[ 33252, 825] NotebookOutlinePosition[ 33873, 849] CellTagsIndexPosition[ 33830, 846] WindowFrame->Normal*) (* Beginning of Notebook Content *) Notebook[{ Cell[TextData[{ "Creating networked games in ", StyleBox["Mathematica", FontSlant->"Italic"], " - Server Code" }], "Title", CellChangeTimes->{{3.3907458272729015`*^9, 3.390745835374874*^9}, { 3.390746922311163*^9, 3.3907469286805754`*^9}, {3.390747109577908*^9, 3.390747121535579*^9}, {3.3949919891510243`*^9, 3.3949920025093*^9}, { 3.395346125984375*^9, 3.39534614046875*^9}, {3.3954160997502937`*^9, 3.3954160998804817`*^9}, {3.3954170292761545`*^9, 3.3954170434566865`*^9}, { 3.3954987906173086`*^9, 3.395498815643794*^9}, {3.3954996494493756`*^9, 3.3954996553680043`*^9}, {3.395509069172121*^9, 3.3955090844243565`*^9}, { 3.39986821878125*^9, 3.3998682313125*^9}, {3.4631581023894196`*^9, 3.4631581125300446`*^9}}], Cell["\<\ Comp 160 Course Module 9 \ \>", "Subtitle", CellChangeTimes->{{3.390745838950158*^9, 3.3907458395911055`*^9}, 3.3907469187659235`*^9, {3.394991909622219*^9, 3.394991911955411*^9}, 3.3949920154269733`*^9, {3.395346122265625*^9, 3.395346122453125*^9}, 3.3954170235578747`*^9, {3.3954987841378627`*^9, 3.3954987842880816`*^9}, 3.399868213875*^9, {3.427130383844424*^9, 3.42713038402469*^9}, { 3.462107976734375*^9, 3.462107979484375*^9}}], Cell[CellGroupData[{ Cell["An example of a server/client game", "Section", CellChangeTimes->{{3.399870132265625*^9, 3.399870140078125*^9}}], Cell[TextData[{ "This game is based on one of the earliest networked games built called ", StyleBox["NetMaze", FontSlant->"Italic"], ". In ", StyleBox["NetMaze", FontSlant->"Italic"], ", users move around in a 2D grid/maze by going either forward/back one unit \ or turning 90 degrees left/right. To interact with other users, a user may \ fire a weapon that instantaneously destroys another user visible in a \ straight line in front of them. Destroyed users are respawned at a random \ location." }], "Text", CellChangeTimes->{{3.39987014496875*^9, 3.399870262765625*^9}, { 3.399870330890625*^9, 3.399870360984375*^9}, {3.399870758890625*^9, 3.39987101046875*^9}, {3.462115084890625*^9, 3.46211509990625*^9}, { 3.462116760671875*^9, 3.462116763390625*^9}, {3.46211680190625*^9, 3.4621168023125*^9}, 3.463223879046875*^9}], Cell[TextData[{ "This is a very bare bones version of ", StyleBox["NetMaze", FontSlant->"Italic"], " in ", StyleBox["Mathematica", FontSlant->"Italic"], " using links. First, run the server code, as it allows a single computer \ to control all the players. Then coordinate with your neighbors to use three \ computers (a server and two clients) to run this version of ", StyleBox["NetMaze", FontSlant->"Italic"], ". Finally, do the exercises to extend the code." }], "Text", CellChangeTimes->{{3.39987014496875*^9, 3.399870262765625*^9}, { 3.399870330890625*^9, 3.399870360984375*^9}, 3.399870758890625*^9, { 3.399871015453125*^9, 3.399871034921875*^9}, {3.4621168269375*^9, 3.4621168610625*^9}, 3.463223892078125*^9}], Cell[TextData[{ StyleBox["Each time you restart the game code, be sure to first quit the ", FontWeight->"Bold", FontColor->RGBColor[1, 0, 0]], StyleBox["Mathematica", FontWeight->"Bold", FontSlant->"Italic", FontColor->RGBColor[1, 0, 0]], StyleBox[" kernel.", FontWeight->"Bold", FontColor->RGBColor[1, 0, 0]] }], "Text", CellChangeTimes->{{3.463224625375*^9, 3.463224685796875*^9}}], Cell[CellGroupData[{ Cell[TextData[{ StyleBox["NetMaze", FontSlant->"Italic"], " - Game representation" }], "Subsection", CellChangeTimes->{{3.39986383609375*^9, 3.399863841734375*^9}, 3.399870506515625*^9, {3.4631579073425446`*^9, 3.4631579101394196`*^9}}], Cell[CellGroupData[{ Cell["Basic game state", "Subsubsection", CellChangeTimes->{{3.399866830203125*^9, 3.399866854203125*^9}, { 3.46322537609375*^9, 3.46322537684375*^9}}], Cell[TextData[{ "Specify the number of players. ", StyleBox["Change this as necessary.", FontColor->RGBColor[1, 0, 0]] }], "Text", CellChangeTimes->{{3.399858453828125*^9, 3.399858501671875*^9}, { 3.399861398046875*^9, 3.39986140134375*^9}, {3.462117167890625*^9, 3.462117177765625*^9}, {3.46322413525*^9, 3.463224136*^9}, { 3.463224803859375*^9, 3.4632248375*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"n", "=", "1"}]], "Input", CellChangeTimes->{{3.399858442296875*^9, 3.39985846671875*^9}, { 3.39986140515625*^9, 3.399861407265625*^9}, 3.46211713409375*^9, { 3.4631564369206696`*^9, 3.4631564370612946`*^9}, {3.4631569638894196`*^9, 3.4631569640144196`*^9}, {3.4631593833581696`*^9, 3.4631593834675446`*^9}, {3.4631602880612946`*^9, 3.4631602881550446`*^9}, {3.4631605209206696`*^9, 3.4631605210769196`*^9}, {3.4631608949206696`*^9, 3.4631608950769196`*^9}}], Cell[BoxData["1"], "Output", CellChangeTimes->{ 3.46211714628125*^9, 3.4631564377487946`*^9, 3.4631566160144196`*^9, 3.4631569687019196`*^9, 3.4631581264362946`*^9, 3.4631588429519196`*^9, 3.4631590877487946`*^9, 3.4631593842800446`*^9, 3.4631596099675446`*^9, 3.4631602918425446`*^9, 3.4631606034675446`*^9, {3.4631607746237946`*^9, 3.4631607855456696`*^9}, 3.46322391471875*^9}] }, Open ]], Cell[TextData[{ "Define a maze for the game that will be given to each client. Each ", Cell[BoxData["0"]], " is a solid block, and ", Cell[BoxData["1"]], " is an empty space. Note that coordinates in this ", Cell[BoxData["MatrixForm"]], " are transposed in the graphics displayed below, since matrices are indexed \ from the upper left and graphics coordinates are indexed from the lower left." }], "Text", CellChangeTimes->{{3.399861418625*^9, 3.399861424125*^9}, { 3.39987107396875*^9, 3.399871155625*^9}, {3.462117041296875*^9, 3.46211704165625*^9}, {3.4621173163125*^9, 3.462117316609375*^9}, { 3.462118147359375*^9, 3.462118186359375*^9}, {3.463223943109375*^9, 3.46322404175*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"maze", "=", RowBox[{"(", GridBox[{ {"0", "0", "0", "0", "0", "0", "0", "0", "0", "0"}, {"0", "1", "1", "1", "1", "1", "1", "1", "1", "0"}, {"0", "1", "0", "0", "0", "0", "0", "0", "1", "0"}, {"0", "1", "1", "1", "1", "1", "1", "1", "1", "0"}, {"0", "1", "0", "0", "0", "0", "0", "0", "1", "0"}, {"0", "1", "0", "0", "0", "0", "0", "0", "1", "0"}, {"0", "1", "0", "0", "0", "0", "0", "0", "1", "0"}, {"0", "1", "1", "1", "1", "1", "1", "1", "1", "0"}, {"0", "0", "0", "0", "0", "0", "0", "0", "0", "0"} }], ")"}]}], ";"}]], "Input", CellChangeTimes->{{3.3998614385*^9, 3.39986155175*^9}, {3.39986252925*^9, 3.399862599265625*^9}, {3.39986303046875*^9, 3.39986303359375*^9}, { 3.399863068828125*^9, 3.3998630976875*^9}}], Cell["\<\ Define the initial state for all players. Each state is a pair of position \ and orientation. The positions must be empty cells in the maze. The \ orientations are integers 0 through 3 (0=right, 1=up, 2=left, 3=down).\ \>", "Text", CellChangeTimes->{{3.399861582734375*^9, 3.399861588890625*^9}, { 3.3998638975625*^9, 3.399863905*^9}, {3.3998640115625*^9, 3.399864021890625*^9}, 3.46211706084375*^9, {3.46211723575*^9, 3.462117267140625*^9}, {3.462117337328125*^9, 3.462117387296875*^9}, { 3.46211748303125*^9, 3.462117497328125*^9}, {3.462117534640625*^9, 3.462117541625*^9}, {3.462117812*^9, 3.46211781665625*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"state", "=", RowBox[{"Table", "[", RowBox[{ RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"2", ",", "2"}], "}"}], ",", "1"}], "}"}], ",", RowBox[{"{", "n", "}"}]}], "]"}]}], ";"}]], "Input", CellChangeTimes->{{3.399858737171875*^9, 3.39985878690625*^9}, { 3.399858821125*^9, 3.399858860421875*^9}, {3.3998593001875*^9, 3.39985762928125*^9}, {3.39985805090625*^9, 3.399858054890625*^9}, 3.39985833075*^9, {3.399861737171875*^9, 3.39986173740625*^9}, { 3.399862666453125*^9, 3.39986266809375*^9}, 3.4000075296413436`*^9, { 3.462117839734375*^9, 3.462117848734375*^9}}] }, Open ]], Cell[CellGroupData[{ Cell["GUI for game state", "Subsubsection", CellChangeTimes->{{3.399866830203125*^9, 3.399866854203125*^9}, { 3.46322537609375*^9, 3.46322537684375*^9}, {3.4632254094375*^9, 3.463225418046875*^9}}], Cell["\<\ A helper function for positioning each player's icon, a distinctly colored \ triangle:\ \>", "Text", CellChangeTimes->{{3.39987116984375*^9, 3.399871180609375*^9}, 3.4621865889375*^9, {3.463150259828125*^9, 3.46315030271875*^9}, { 3.4632241768125*^9, 3.463224178171875*^9}, {3.463225529515625*^9, 3.46322553075*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"player", "[", RowBox[{"i_", ",", RowBox[{"{", RowBox[{"pos_", ",", "orient_"}], "}"}]}], "]"}], ":=", "\[IndentingNewLine]", RowBox[{"{", RowBox[{ RowBox[{"Hue", "[", FractionBox["i", "n"], "]"}], ",", RowBox[{"Translate", "[", RowBox[{ RowBox[{"Rotate", "[", RowBox[{ RowBox[{"Polygon", "[", RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{ FractionBox[ RowBox[{"-", "5"}], "6"], ",", FractionBox[ RowBox[{"-", "2"}], "3"]}], "}"}], ",", RowBox[{"{", RowBox[{ FractionBox[ RowBox[{"-", "5"}], "6"], ",", FractionBox[ RowBox[{"-", "1"}], "3"]}], "}"}], ",", RowBox[{"{", RowBox[{ FractionBox[ RowBox[{"-", "1"}], "6"], ",", FractionBox[ RowBox[{"-", "1"}], "2"]}], "}"}]}], "}"}], "]"}], ",", FractionBox[ RowBox[{"orient", " ", "\[Pi]"}], "2"]}], "]"}], ",", "pos"}], "]"}]}], "}"}]}]], "Input", CellChangeTimes->{{3.399860268875*^9, 3.399858314875*^9}, 3.39986032025*^9, { 3.399861696734375*^9, 3.399861715046875*^9}, {3.399861826328125*^9, 3.399861855703125*^9}, {3.399862258734375*^9, 3.399862283328125*^9}, 3.399862317328125*^9, {3.4631592327175446`*^9, 3.4631592523894196`*^9}}], Cell["\<\ The game state viewer for the server. This is basically the same as the \ client's user interface.\ \>", "Text", CellChangeTimes->{{3.399144616324111*^9, 3.3991446181533127`*^9}, { 3.399860479453125*^9, 3.399860485*^9}, {3.39986066803125*^9, 3.39986067175*^9}, {3.462186609765625*^9, 3.462186633390625*^9}, { 3.463150324359375*^9, 3.4631503250625*^9}, {3.46322418603125*^9, 3.4632241874375*^9}, {3.4632242184375*^9, 3.463224222953125*^9}}], Cell[CellGroupData[{ Cell[BoxData[{ RowBox[{"Dynamic", "[", "state", "]"}], "\[IndentingNewLine]", RowBox[{"Graphics", "[", RowBox[{ RowBox[{"{", "\[IndentingNewLine]", RowBox[{"Gray", ",", RowBox[{"Raster", "[", RowBox[{"Transpose", "[", "maze", "]"}], "]"}], ",", "\[IndentingNewLine]", RowBox[{"Dynamic", "[", RowBox[{"Table", "[", RowBox[{ RowBox[{"player", "[", RowBox[{"i", ",", RowBox[{ "state", "\[LeftDoubleBracket]", "i", "\[RightDoubleBracket]"}]}], "]"}], ",", RowBox[{"{", RowBox[{"i", ",", "n"}], "}"}]}], "]"}], "]"}]}], "}"}], ",", RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}]}], "Input", CellChangeTimes->{{3.399859975390625*^9, 3.399859984375*^9}, { 3.39986004421875*^9, 3.39986025215625*^9}, {3.3998603833125*^9, 3.399860426984375*^9}, {3.3998606551875*^9, 3.399858347125*^9}, { 3.399861631875*^9, 3.39986163746875*^9}, {3.399861786015625*^9, 3.39986178746875*^9}, {3.3998618193125*^9, 3.39986181996875*^9}, { 3.399861879609375*^9, 3.3998619356875*^9}, {3.399862240734375*^9, 3.399862247578125*^9}, {3.399863105046875*^9, 3.399863109625*^9}, { 3.3998632110625*^9, 3.399863230796875*^9}, {3.399906982052294*^9, 3.399906984989813*^9}, {3.4631595112644196`*^9, 3.4631595297800446`*^9}, { 3.4631596333894196`*^9, 3.4631596336237946`*^9}}], Cell[BoxData[ GraphicsBox[ {GrayLevel[0.5], RasterBox[{{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 1, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}}], DynamicBox[Typeset`ToBoxes[ Table[ $CellContext`player[$CellContext`i, Part[$CellContext`state, $CellContext`i]], {$CellContext`i, \ $CellContext`n}], StandardForm, Graphics], ImageSizeCache->{{0., 0.}, {0., 0.}}]}, Frame->True]], "Output", CellChangeTimes->{ 3.399858091234375*^9, 3.399858347984375*^9, 3.399858642703125*^9, 3.399858845203125*^9, {3.399859095671875*^9, 3.399859138796875*^9}, 3.399859233421875*^9, 3.399859355625*^9, 3.399859453078125*^9, 3.39985955221875*^9, 3.39985978025*^9, 3.39986043471875*^9, 3.39986051825*^9, 3.3998607371875*^9, 3.399860771234375*^9, 3.39986090696875*^9, 3.39986098215625*^9, 3.39986103728125*^9, 3.399861151421875*^9, {3.39986119784375*^9, 3.39986120253125*^9}, { 3.399861725609375*^9, 3.39986175196875*^9}, 3.399861800515625*^9, { 3.39986184746875*^9, 3.399861923046875*^9}, 3.399862091546875*^9, { 3.399862298875*^9, 3.399862321390625*^9}, 3.3998626510625*^9, 3.3998626834375*^9, 3.3998630393125*^9, 3.399863128921875*^9, 3.399863247171875*^9, 3.399864193859375*^9, 3.399864366921875*^9, 3.4631565005612946`*^9, 3.4631566527487946`*^9, 3.4631569882644196`*^9, 3.4631580350612946`*^9, 3.4631581371081696`*^9, 3.4631588505456696`*^9, 3.4631590957175446`*^9, 3.4631593963269196`*^9, {3.4631595161862946`*^9, 3.4631595301706696`*^9}, {3.4631596221081696`*^9, 3.4631596344987946`*^9}, 3.4631596697956696`*^9, 3.4631603021706696`*^9, 3.4631606139362946`*^9, 3.4631607908737946`*^9}] }, Open ]] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[TextData[{ StyleBox["NetMaze", FontSlant->"Italic"], " - Game state update" }], "Subsection", CellChangeTimes->{{3.39986383609375*^9, 3.399863841734375*^9}, 3.399870506515625*^9, {3.4631579073425446`*^9, 3.4631579101394196`*^9}, { 3.4631582899519196`*^9, 3.4631582929206696`*^9}}], Cell[TextData[{ "Each client will transmit updates to the server using ", Cell[BoxData[ FormBox[ StyleBox["LinkWrite", FontFamily->"Courier New"], TraditionalForm]]], " commands. Actions are encoded as integers 0 through 4 (0=Forward, 1=Back, \ 2=Clockwise, 3=CounterClockwise, 4=Fire). The function ", StyleBox["updateState", FontFamily->"Courier New"], " modfies the state accordingly. The firing action is only a stub for you \ to complete later." }], "Text", CellChangeTimes->{{3.39986412896875*^9, 3.399864160203125*^9}, { 3.39987119096875*^9, 3.39987120846875*^9}, {3.462186403578125*^9, 3.462186467421875*^9}, {3.4631583197487946`*^9, 3.4631583480456696`*^9}, { 3.4631583957175446`*^9, 3.4631584928737946`*^9}, {3.463224253625*^9, 3.463224314875*^9}, {3.46322438259375*^9, 3.463224389984375*^9}, { 3.463225628828125*^9, 3.46322570825*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"updateState", "[", RowBox[{"state_", ",", "i_", ",", "action_"}], "]"}], ":=", "\[IndentingNewLine]", RowBox[{"Module", "[", RowBox[{ RowBox[{"{", RowBox[{"newState", "=", "state"}], "}"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"Switch", "[", RowBox[{"action", ",", "\[IndentingNewLine]", "0", ",", RowBox[{"With", "[", RowBox[{ RowBox[{"{", RowBox[{"newPos", "=", RowBox[{ RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "1"}], "\[RightDoubleBracket]"}], "+", RowBox[{"{", RowBox[{ RowBox[{"Cos", "[", RowBox[{ RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "2"}], "\[RightDoubleBracket]"}], " ", FractionBox["\[Pi]", "2"]}], "]"}], ",", RowBox[{"Sin", "[", RowBox[{ RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "2"}], "\[RightDoubleBracket]"}], " ", FractionBox["\[Pi]", "2"]}], "]"}]}], "}"}]}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"If", "[", RowBox[{ RowBox[{ RowBox[{"maze", "\[LeftDoubleBracket]", RowBox[{ RowBox[{ "newPos", "\[LeftDoubleBracket]", "1", "\[RightDoubleBracket]"}], ",", RowBox[{ "newPos", "\[LeftDoubleBracket]", "2", "\[RightDoubleBracket]"}]}], "\[RightDoubleBracket]"}], "\[Equal]", "1"}], ",", RowBox[{ RowBox[{ "newState", "\[LeftDoubleBracket]", "i", "\[RightDoubleBracket]"}], "=", RowBox[{"{", RowBox[{"newPos", ",", RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "2"}], "\[RightDoubleBracket]"}]}], "}"}]}]}], "]"}]}], "]"}], ",", "\[IndentingNewLine]", "1", ",", RowBox[{"With", "[", RowBox[{ RowBox[{"{", RowBox[{"newPos", "=", RowBox[{ RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "1"}], "\[RightDoubleBracket]"}], "-", RowBox[{"{", RowBox[{ RowBox[{"Cos", "[", RowBox[{ RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "2"}], "\[RightDoubleBracket]"}], " ", FractionBox["\[Pi]", "2"]}], "]"}], ",", RowBox[{"Sin", "[", RowBox[{ RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "2"}], "\[RightDoubleBracket]"}], " ", FractionBox["\[Pi]", "2"]}], "]"}]}], "}"}]}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"If", "[", RowBox[{ RowBox[{ RowBox[{"maze", "\[LeftDoubleBracket]", RowBox[{ RowBox[{ "newPos", "\[LeftDoubleBracket]", "1", "\[RightDoubleBracket]"}], ",", RowBox[{ "newPos", "\[LeftDoubleBracket]", "2", "\[RightDoubleBracket]"}]}], "\[RightDoubleBracket]"}], "\[Equal]", "1"}], ",", RowBox[{ RowBox[{ "newState", "\[LeftDoubleBracket]", "i", "\[RightDoubleBracket]"}], "=", RowBox[{"{", RowBox[{"newPos", ",", RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "2"}], "\[RightDoubleBracket]"}]}], "}"}]}]}], "]"}]}], "]"}], ",", "\[IndentingNewLine]", "2", ",", RowBox[{ RowBox[{ "newState", "\[LeftDoubleBracket]", "i", "\[RightDoubleBracket]"}], "=", RowBox[{"{", RowBox[{ RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "1"}], "\[RightDoubleBracket]"}], ",", RowBox[{"Mod", "[", RowBox[{ RowBox[{ RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "2"}], "\[RightDoubleBracket]"}], "-", "1"}], ",", "4"}], "]"}]}], "}"}]}], ",", "\[IndentingNewLine]", "3", ",", RowBox[{ RowBox[{ "newState", "\[LeftDoubleBracket]", "i", "\[RightDoubleBracket]"}], "=", RowBox[{"{", RowBox[{ RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "1"}], "\[RightDoubleBracket]"}], ",", RowBox[{"Mod", "[", RowBox[{ RowBox[{ RowBox[{"state", "\[LeftDoubleBracket]", RowBox[{"i", ",", "2"}], "\[RightDoubleBracket]"}], "+", "1"}], ",", "4"}], "]"}]}], "}"}]}], ",", "\[IndentingNewLine]", "4", ",", "True"}], "]"}], ";", "\[IndentingNewLine]", "newState"}]}], "]"}]}]], "Input", CellChangeTimes->{{3.39986013153125*^9, 3.399860283515625*^9}, { 3.399860331421875*^9, 3.399860407*^9}, {3.399860503078125*^9, 3.399860504171875*^9}, {3.399862396984375*^9, 3.399862505*^9}}], Cell["\<\ The following control panel allows the server to control the every players' \ state. This allows a single-person version of the game without networking. \ This panel is unnecessary when you have clients running. (You can copy the \ buttons below up to the Dynamic graphic to get them both on the screen at \ once.) \ \>", "Text", CellChangeTimes->{{3.4631586469519196`*^9, 3.4631586745300446`*^9}, { 3.4631596782331696`*^9, 3.4631597030144196`*^9}, {3.463224401953125*^9, 3.463224603171875*^9}, {3.463224733515625*^9, 3.463224772171875*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"DynamicModule", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{"{", RowBox[{"i", "=", "1"}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"Panel", "[", "\[IndentingNewLine]", RowBox[{"Row", "[", RowBox[{"{", "\[IndentingNewLine]", RowBox[{ RowBox[{"SetterBar", "[", RowBox[{ RowBox[{"Dynamic", "[", "i", "]"}], ",", RowBox[{"Range", "[", "n", "]"}]}], "]"}], ",", "\[IndentingNewLine]", RowBox[{"Button", "[", RowBox[{"\"\\"", ",", RowBox[{"state", "=", RowBox[{"updateState", "[", RowBox[{"state", ",", "i", ",", "0"}], "]"}]}]}], "]"}], ",", "\[IndentingNewLine]", RowBox[{"Button", "[", RowBox[{"\"\\"", ",", RowBox[{"state", "=", RowBox[{"updateState", "[", RowBox[{"state", ",", "i", ",", "1"}], "]"}]}]}], "]"}], ",", "\[IndentingNewLine]", RowBox[{"Button", "[", RowBox[{"\"\\"", ",", RowBox[{"state", "=", RowBox[{"updateState", "[", RowBox[{"state", ",", "i", ",", "2"}], "]"}]}]}], "]"}], ",", "\[IndentingNewLine]", RowBox[{"Button", "[", RowBox[{"\"\\"", ",", " ", RowBox[{"state", "=", RowBox[{"updateState", "[", RowBox[{"state", ",", "i", ",", "3"}], "]"}]}]}], "]"}], ",", "\[IndentingNewLine]", RowBox[{"Button", "[", RowBox[{"\"\\"", ",", " ", RowBox[{"state", "=", RowBox[{"updateState", "[", RowBox[{"state", ",", "i", ",", "4"}], "]"}]}]}], "]"}]}], "}"}], "]"}], "]"}]}], "]"}]], "Input", CellChangeTimes->CompressedData[" 1:eJxTTMoPSmViYGCQBWIQzdDw5sH2kJeODAw8jyB0+0sI3cq8A0y/EgbTDfGS EDpwNkR8PpQuWAehL+yD0La8O8HqLPnANMNMdQj/K5QuM4LQaWYQWtoOQndC aIYbMRD+9FgIHVAMoXPLIfJlJyB88zMQeu0DCO3yEELfeQpRp/wKQqe/h7rn I4QW/A8Rb4TSp1l2gcXrWcE0g0M+hF9WCKEn10PoFVD6LsdusLqznCCab23I tXNA2kh3NZgW1tvg+B9Ip677CKYVyrxLi8+CaIcyCM1XA6a/JbdA+Et6IDRL P4TWmQyhBRdC6C8bIOoVNkJovT0QceW9EL7UeQif/zKIBgA3WNYa "]], Cell[BoxData[ DynamicModuleBox[{$CellContext`i$$ = 1}, PanelBox[ TemplateBox[{InterpretationBox[ StyleBox[ GridBox[{{ SetterBox[ Dynamic[$CellContext`i$$], {1}, "1"]}}, BaselinePosition -> {1, 1}, GridBoxSpacings -> {"Columns" -> { Offset[0.27999999999999997`], { Offset[0.]}, Offset[0.27999999999999997`]}, "ColumnsIndexed" -> {}, "Rows" -> { Offset[0.2], { Offset[0.4]}, Offset[0.2]}, "RowsIndexed" -> {}}], Deployed -> True], SetterBar[ Dynamic[$CellContext`i$$], {1}]],ButtonBox[ "\"Forward\"", Appearance -> Automatic, ButtonFunction :> ($CellContext`state = \ $CellContext`updateState[$CellContext`state, $CellContext`i$$, 0]), Evaluator -> Automatic, Method -> "Preemptive"],ButtonBox[ "\"Back\"", Appearance -> Automatic, ButtonFunction :> ($CellContext`state = \ $CellContext`updateState[$CellContext`state, $CellContext`i$$, 1]), Evaluator -> Automatic, Method -> "Preemptive"],ButtonBox[ "\"Turn CW\"", Appearance -> Automatic, ButtonFunction :> ($CellContext`state = \ $CellContext`updateState[$CellContext`state, $CellContext`i$$, 2]), Evaluator -> Automatic, Method -> "Preemptive"],ButtonBox[ "\"Turn CC\"", Appearance -> Automatic, ButtonFunction :> ($CellContext`state = \ $CellContext`updateState[$CellContext`state, $CellContext`i$$, 3]), Evaluator -> Automatic, Method -> "Preemptive"],ButtonBox[ "\"Fire\"", Appearance -> Automatic, ButtonFunction :> ($CellContext`state = \ $CellContext`updateState[$CellContext`state, $CellContext`i$$, 4]), Evaluator -> Automatic, Method -> "Preemptive"]}, "Row", DisplayFunction->( RowBox[{#, "\[InvisibleSpace]", #2, "\[InvisibleSpace]", #3, "\[InvisibleSpace]", #4, "\[InvisibleSpace]", #5, "\[InvisibleSpace]", #6}]& ), InterpretationFunction->(RowBox[{"Row", "[", RowBox[{"{", RowBox[{#, ",", #2, ",", #3, ",", #4, ",", #5, ",", #6}], "}"}], "]"}]& )]], DynamicModuleValues:>{}]], "Output", CellChangeTimes->{{3.4631589509987946`*^9, 3.4631590063112946`*^9}, { 3.4631590409987946`*^9, 3.4631590491237946`*^9}, 3.4631591084206696`*^9, 3.4631591780925446`*^9, {3.4631592664206696`*^9, 3.4631592739675446`*^9}, 3.4631594489987946`*^9, 3.4631597064675446`*^9, 3.4631603075456696`*^9, 3.4631606196706696`*^9, 3.4631607966862946`*^9, 3.463224782234375*^9}] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[TextData[{ StyleBox["NetMaze", FontSlant->"Italic"], " - Server code" }], "Subsection", CellChangeTimes->{{3.39986383609375*^9, 3.399863841734375*^9}, 3.399870506515625*^9}], Cell["\<\ First, run the following code on the server. Do this before starting a \ client.\ \>", "Text", CellChangeTimes->{{3.3998644765625*^9, 3.399864487578125*^9}, { 3.462116951390625*^9, 3.462117035453125*^9}}], Cell[CellGroupData[{ Cell["Initialization code", "Subsubsection", CellChangeTimes->{{3.399863912953125*^9, 3.399863916*^9}}], Cell[TextData[{ "Get the IP address for server, which will be needed by the clients' ", Cell[BoxData["LinkConnect"]], "." }], "Text", CellChangeTimes->{{3.3991448347174373`*^9, 3.399144838265493*^9}, { 3.39986385178125*^9, 3.399863868546875*^9}, {3.399871053703125*^9, 3.399871069515625*^9}, {3.462117072875*^9, 3.4621170979375*^9}, { 3.46314970153125*^9, 3.463149761078125*^9}}], Cell[CellGroupData[{ Cell[BoxData["$MachineAddresses"], "Input", CellChangeTimes->{{3.3991448403912*^9, 3.3991448443925314`*^9}}], Cell[BoxData[ RowBox[{"{", "\<\"10.94.20.225\"\>", "}"}]], "Output", CellChangeTimes->{ 3.39985759471875*^9, 3.39985765303125*^9, 3.399857899625*^9, 3.399858081125*^9, {3.399859095296875*^9, 3.39985913865625*^9}, 3.39985923328125*^9, 3.39985935534375*^9, 3.399859452921875*^9, 3.399859551546875*^9, 3.39985978009375*^9, 3.399860434578125*^9, 3.399860518109375*^9, 3.399860736609375*^9, 3.399860771078125*^9, 3.3998609068125*^9, 3.399860982*^9, 3.399861037140625*^9, 3.399861151265625*^9, 3.399861202359375*^9, {3.39986172509375*^9, 3.39986175165625*^9}, 3.399861800234375*^9, {3.3998618471875*^9, 3.39986192271875*^9}, 3.39986209125*^9, {3.399862298546875*^9, 3.399862321046875*^9}, 3.3998626508125*^9, 3.399862683125*^9, 3.399863039*^9, 3.399863128546875*^9, 3.399863246828125*^9, 3.3998641936875*^9, 3.39986435525*^9, 3.4631554644831696`*^9, 3.4631564313425446`*^9, 3.4631566157800446`*^9, 3.4631569665144196`*^9, 3.4631603243581696`*^9, 3.4631606257800446`*^9, 3.4631608078581696`*^9}] }, Open ]], Cell[TextData[{ "Open links all to ", Cell[BoxData[Cell["n"]]], " players." }], "Text", CellChangeTimes->{{3.399144722633273*^9, 3.399144743249507*^9}, { 3.399858719703125*^9, 3.39985872540625*^9}, {3.399864042734375*^9, 3.3998640433125*^9}, {3.46314976715625*^9, 3.4631498361875*^9}, 3.463149882703125*^9, {3.46322488428125*^9, 3.46322488859375*^9}}], Cell[BoxData[ RowBox[{"Do", "[", RowBox[{ RowBox[{ RowBox[{"player", "[", "i", "]"}], "=", RowBox[{"LinkCreate", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{"StringJoin", "[", RowBox[{"\"\<800\>\"", ",", RowBox[{"FromCharacterCode", "[", RowBox[{ RowBox[{"ToCharacterCode", "[", "\"\<0\>\"", "]"}], "+", "i"}], "]"}]}], "]"}], ",", RowBox[{"LinkProtocol", "\[Rule]", "\"\\""}]}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{"{", RowBox[{"i", ",", "n"}], "}"}]}], "]"}]], "Input", CellChangeTimes->{{3.3991445734238663`*^9, 3.3991445932480316`*^9}, { 3.39985855109375*^9, 3.399858618203125*^9}, {3.39985870315625*^9, 3.39985871684375*^9}, {3.399858797171875*^9, 3.39985879871875*^9}}], Cell[TextData[{ "If the server had multiple IP addresses in the first initialization step, \ look at the value of ", StyleBox["LinkCreate[1]", FontFamily->"Courier New"], ", and see which IP address was used." }], "Text", CellChangeTimes->{{3.46314986440625*^9, 3.4631499231875*^9}}], Cell[TextData[StyleBox["You can start the clients at any point after this.", FontWeight->"Bold", FontColor->RGBColor[1, 0, 0]]], "Text", CellChangeTimes->{{3.46315002978125*^9, 3.463150043984375*^9}}] }, Open ]], Cell[CellGroupData[{ Cell["Server networking", "Subsubsection", CellChangeTimes->{{3.399863912953125*^9, 3.399863916*^9}, { 3.463225464984375*^9, 3.463225467640625*^9}}], Cell[TextData[{ "Send the initial state for all ", Cell[BoxData["n"]], " players - each player's state is an ordered pair of position and \ orientation." }], "Text", CellChangeTimes->{{3.399858515953125*^9, 3.3998585290625*^9}, { 3.399859329*^9, 3.399859349953125*^9}, {3.46211719746875*^9, 3.462117197734375*^9}, 3.4621865846875*^9}], Cell[BoxData[ RowBox[{"Do", "[", RowBox[{ RowBox[{"LinkWrite", "[", RowBox[{ RowBox[{"player", "[", "i", "]"}], ",", RowBox[{"{", RowBox[{"maze", ",", "state"}], "}"}]}], "]"}], ",", RowBox[{"{", RowBox[{"i", ",", "n"}], "}"}]}], "]"}]], "Input", CellChangeTimes->{{3.399858737171875*^9, 3.39985878690625*^9}, { 3.399858821125*^9, 3.399858860421875*^9}, {3.3998593001875*^9, 3.39985762928125*^9}, {3.39985805090625*^9, 3.399858054890625*^9}, 3.39985833075*^9, {3.39985880390625*^9, 3.3998588166875*^9}, { 3.399859056140625*^9, 3.3998590870625*^9}, 3.399859312109375*^9, { 3.399860082265625*^9, 3.399860107484375*^9}, {3.399860747109375*^9, 3.39986075765625*^9}, {3.39986160728125*^9, 3.399861615046875*^9}, 3.399863949734375*^9}], Cell["\<\ Main loop: Poll all clients for state changes, update state appropriately, \ and broadcast to all clients.\ \>", "Text", CellChangeTimes->{{3.399864049171875*^9, 3.399864071921875*^9}, { 3.46211786825*^9, 3.4621178845*^9}}], Cell[BoxData[ RowBox[{"While", "[", RowBox[{"True", ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"updated", "=", "False"}], ";", "\[IndentingNewLine]", RowBox[{"Do", "[", RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{"LinkReadyQ", "[", RowBox[{"player", "[", "i", "]"}], "]"}], ",", RowBox[{ RowBox[{"updated", "=", "True"}], ";", RowBox[{"state", "=", RowBox[{"updateState", "[", RowBox[{"state", ",", "i", ",", RowBox[{"LinkRead", "[", RowBox[{"player", "[", "i", "]"}], "]"}]}], "]"}]}]}]}], "]"}], ",", RowBox[{"{", RowBox[{"i", ",", "n"}], "}"}]}], "]"}], ";", "\[IndentingNewLine]", RowBox[{"(*", " ", RowBox[{"Update", " ", "state"}], " ", "*)"}], "\[IndentingNewLine]", RowBox[{"If", "[", RowBox[{"updated", ",", RowBox[{"Do", "[", RowBox[{ RowBox[{"LinkWrite", "[", RowBox[{ RowBox[{"player", "[", "i", "]"}], ",", "state"}], "]"}], ",", RowBox[{"{", RowBox[{"i", ",", "n"}], "}"}]}], "]"}]}], "]"}]}]}], "]"}]], "Input", CellChangeTimes->{{3.399858737171875*^9, 3.39985878690625*^9}, { 3.399858821125*^9, 3.399858860421875*^9}, {3.3998593001875*^9, 3.39985762928125*^9}, {3.39985805090625*^9, 3.399858054890625*^9}, 3.39985833075*^9, {3.39985880390625*^9, 3.3998588166875*^9}, { 3.399859056140625*^9, 3.3998590870625*^9}, 3.399859312109375*^9, { 3.399860082265625*^9, 3.399860107484375*^9}, {3.399860747109375*^9, 3.39986075765625*^9}, {3.39986160728125*^9, 3.399861615046875*^9}, 3.399863949734375*^9, 3.39986404715625*^9}] }, Open ]] }, Open ]] }, Open ]] }, WindowToolbars->{}, WindowSize->{1590, 1022}, WindowMargins->{{0, Automatic}, {Automatic, 0}}, PrintingCopies->1, PrintingPageRange->{1, Automatic}, PrintingOptions->{"PrintCellBrackets"->False, "PrintMultipleHorizontalPages"->False, "PrintRegistrationMarks"->True, "PrintingMargins"->{{54, 54}, {72, 72}}}, ShowSelection->True, Magnification->1.5, FrontEndVersion->"7.0 for Microsoft Windows (32-bit) (November 10, 2008)", StyleDefinitions->"Classroom.nb" ] (* End of Notebook Content *) (* Internal cache information *) (*CellTagsOutline CellTagsIndex->{} *) (*CellTagsIndex CellTagsIndex->{} *) (*NotebookFileOutline Notebook[{ Cell[545, 20, 744, 14, 82, "Title"], Cell[1292, 36, 466, 9, 93, "Subtitle"], Cell[CellGroupData[{ Cell[1783, 49, 119, 1, 81, "Section"], Cell[1905, 52, 853, 17, 60, "Text"], Cell[2761, 71, 745, 17, 60, "Text"], Cell[3509, 90, 401, 12, 36, "Text"], Cell[CellGroupData[{ Cell[3935, 106, 245, 6, 66, "Subsection"], Cell[CellGroupData[{ Cell[4205, 116, 154, 2, 53, "Subsubsection"], Cell[4362, 120, 378, 8, 35, "Text"], Cell[CellGroupData[{ Cell[4765, 132, 504, 8, 69, "Input"], Cell[5272, 142, 399, 6, 68, "Output"] }, Open ]], Cell[5686, 151, 706, 14, 61, "Text"], Cell[6395, 167, 822, 16, 241, "Input"], Cell[7220, 185, 648, 10, 35, "Text"], Cell[7871, 197, 659, 15, 69, "Input"] }, Open ]], Cell[CellGroupData[{ Cell[8567, 217, 203, 3, 53, "Subsubsection"], Cell[8773, 222, 338, 7, 35, "Text"], Cell[9114, 231, 1478, 42, 124, "Input"], Cell[10595, 275, 461, 8, 35, "Text"], Cell[CellGroupData[{ Cell[11081, 287, 1382, 29, 151, "Input"], Cell[12466, 318, 1893, 33, 640, "Output"] }, Open ]] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[14420, 358, 297, 7, 66, "Subsection"], Cell[14720, 367, 878, 18, 62, "Text"], Cell[15601, 387, 5246, 127, 455, "Input"], Cell[20850, 516, 561, 9, 60, "Text"], Cell[CellGroupData[{ Cell[21436, 529, 2139, 51, 313, "Input"], Cell[23578, 582, 2524, 51, 115, "Output"] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[26151, 639, 187, 6, 66, "Subsection"], Cell[26341, 647, 218, 5, 35, "Text"], Cell[CellGroupData[{ Cell[26584, 656, 104, 1, 53, "Subsubsection"], Cell[26691, 659, 390, 8, 36, "Text"], Cell[CellGroupData[{ Cell[27106, 671, 109, 1, 69, "Input"], Cell[27218, 674, 1044, 16, 68, "Output"] }, Open ]], Cell[28277, 693, 366, 8, 36, "Text"], Cell[28646, 703, 794, 19, 124, "Input"], Cell[29443, 724, 289, 7, 36, "Text"], Cell[29735, 733, 203, 3, 35, "Text"] }, Open ]], Cell[CellGroupData[{ Cell[29975, 741, 151, 2, 53, "Subsubsection"], Cell[30129, 745, 345, 8, 36, "Text"], Cell[30477, 755, 794, 17, 69, "Input"], Cell[31274, 774, 237, 5, 35, "Text"], Cell[31514, 781, 1698, 39, 178, "Input"] }, Open ]] }, Open ]] }, Open ]] } ] *) (* End of internal cache information *)