Tuesday, May 11, 2021

Reflecting on CS222 Advanced Programming, Spring 2021

It was good to teach CS222 in person, although I have had enough of rotational attendance, face masks, and physical distancing. All of these things significantly inhibit learning, and I'll be glad to see the back of them.

One of the most significant challenges this semester was not apparent when we started. There are always some students who feel that they are not proficient with Java, but I assure them that the prerequisite courses build in enough Java for us to make sense of the readings. Transfer students often come in without Java experience at all, but I point them toward The Java Tutorials, and that's enough for them to be able to read Clean Code. As the weeks went on, though, it became clear that this cohort was different. It became clear that they had done very little programming of any merit in the prerequisite course, that it had really not prepared them for CS222. This put me in a bad situation: I am still beholden to the learning objectives of my course, even if those teaching the prerequisite course did not hold up their part of the curriculum. 

I tried using the existing achievements system to address the deficiency. I introduced a new one based on in-class examples that was really about practicing Java along with CS222 course concepts: namely, Optimas, which was to use TDD to develop a Roman numeral converter. Only a handful of students attempted this, which was good for them. It was not clear to me that other students were willing to put in the effort to make up for their deficiencies. Indeed, while there are usually some obvious slackers on teams, I feel like there was a lot more dead weight on teams this semester, people who, from looking through git logs, didn't seem to do anything significant on the projects.

It was in the last few weeks of the semester that I felt like I could see all the issues more clearly. Just before the third iteration of the semester project, I put up a required video about project planning. The video was under ten minutes long, and it was designed to help them understand how quality can be maintained only by managing scope. Two weeks after posting this required bit of instruction, I happened to be on my YouTube Studio page, which showed me that this video had only three views. There were 28 students enrolled in the class.

This became fodder for our last-day discussion, which had a tumultuous design. To summarize the major talking points, I mentioned that a student had referred to my feedback as "brutal," so I asked them to reflect on how honesty is mistaken for brutality. I showed them the CS121 learning objectives, and I told them that I had looked up their grades for that course, which were all A-B grades. My question for them was, "Who is brutal? The one who gives you honest feedback so that you can meet the objectives, or the one who gives you an A grade when you have not met them?" Then I pulled the rug out from them, pointing out the low viewership on the exact video that was designed to help them do their best in the final iteration: the blame is not external to them! In this way, I tried to show them that, like all of us, they are victims of their environment, but also like all of us, they have the opportunity to overcome it—but many did not take that opportunity.

All that is to say that there were a lot of ups and downs. The grades were, overall, very low, since many students never resubmitted anything from early in the semester, most teams only met some of the final project requirements, and many students did not engage with the achievements. One could blame pandemic malaise, but the fact remains that this cohort of students will struggle to move forward through the curriculum. I put together an optional summer enrichment program for them, consisting of a series of exercises designed to reinforce CS121 data structures knowledge while strengthening their CS222 skills as well. Given their low engagement, I honestly do not expect many to pursue it, but at least I feel like I offered something to them in the face of a systemic failure.

One of the things this made me reflect upon, though, is potential holes in my grading scheme. I had a student who seemed to be willing to do anything for credit except work on the project. This student completed achievements, wrote essays, praised teammates, but never seemed to write a single line of code. Indeed, to be honest, I am not certain that this student can write code at all. Yet, the student could have earned a C- and moved forward in the curriculum. It makes me realize that, after many years of having basically the same grading scheme in CS222, perhaps I should revisit it, perhaps in light of some of my work on checklist-based specifications grading, as I use is Game Programming.

Two other items are high on my list of changes to consider for the future. One is that analysis of git logs makes it obvious that many teams—the poorly performing ones, not coincidentally—have inconsistent progress throughout the iteration. Reflecting on this, I think it is in part due to the institutional brainwashing and the anti-thinking promoted by tools like Canvas. To wit, if I have an iteration deadline three weeks away, Canvas shows it behind anything else that is due sooner. It gives students the illusion that the work is distal, when it is in fact supposed to be consistent throughout. Put another way, Canvas makes it look like the increment has a deadline rather than that there is consistent work to be done. One way around this is to abandon Canvas altogether for this kind of work, but I would still have to put grades there somehow. Another way is to institute something like weekly labor logs, as I did in game design last semester, so that students see something due each week. That sounds like the tail wagging the dog, but I wanted to mention it here for the next time I prep for CS222.

The other thing that really has to change is my articulation of a "critical component" in the increment presentations. I have used this terminology for years, and despite how much time I spend reminding students and describing the requirements in text, there are always people who get it wrong. I think this is in part a naming problem. I think I will change the name of that aspect to "Teach Us Something." It is a bit cumbersome to talk about "the Teach Us Something requirement," but I think that will resonate better in more students' minds.

Friday, May 7, 2021

Reflecting on CS490 Software Development Studio, Spring 2021

It was an interesting experience teaching CS490 Software Development Studio this past semester. This was the second year of my experiment in letting students pursue their passion projects. The first year was intended as a one-off, but with the pandemic, it seemed a bad time to try to bring back the element of community engagement. However, next year (Spring 2022), we are already approved and funded to do another community-engaged project with Minnetrista, and I'm really looking forward to that. It means, though, that any breadcrumbs I leave for myself here may not be followed for some time.

We started the semester by having each student participate in two rounds of pitches, we spent some time building prototypes from a subset of these, and by the middle of February had set on three projects to pursue. All three were completed and published to itch.io:

The students followed the distributed methodology that I put together early in the semester. The only major edit I can remember from the semester was removing Trello as an option, since it didn't support the rest of the process as clearly as HacknPlan. At the end of each iteration, each student had to submit a statement that they had met the nine-hours-per-week labor commitment and that they had followed the methodology to the best of their understanding and ability. I thought about having them keep labor logs, as I did in game design last semester, but I decided to go with the more lightweight periodic self-reports instead. This kind of self-reporting is always open to dishonesty, given that grades were connected, but I did not have any sense of this as an endemic problem during the semester. Most students reported that they met all the goals all the time, although some admitted to cases where they were not on point. 

Last Spring, the teams started up in person and then had to move online, and I felt like we had a good working relationship throughout. This semester, we technically had a room that we could use, but that would have been extremely awkward for presentations, conversations, and collaboration. We ended up moving almost everything online, including pitches, work days, planning meetings, and presentations. Given the constraints of the alternative, it was better in all ways. We only met face-to-face a few times during the semester for whole studio meetings. 

A result of this is that I felt very much "outside" the group, and there was not a real sense of community between the teams. The most surprising way that this manifested was on Slack. Originally, different teams used different communication channels, but this was hard for me to manage and prevented people from reaching out for help across teams. I brought everyone together into one Slack instance, but people, by and large, ended up staying in their team's channels anyway. I used the #general channel to share thoughts, ideas, reminders, and the like, but I am not sure that anyone else ever really used it for general studio chat. Put another way, there was no general studio chat. A few people posted links on #random, but even that was really quiet, devoid of any good memes. It makes me wonder, if I were to run a course this way again, should more effort be spent on building up a sense of commonality, or should more effort be spent helping teams become self-sufficient and independent.

Early in the semester, I required that each team come up with a vision statement, explaining to the students that the main value of this is to be able to say "no" to good ideas. The rest of the semester was essentially just a series of sprints, then, in terms of what students were required to do. I advised the teams toward good practices of early playtesting and setting a feature freeze date, but I did not require either of these. Conversations with the teams, including our whole-studio semester retrospective meeting, make me wonder if it would be better to frontload some deadlines around these. For example, part of the methodology could give a date by which the first playtesting is expected, so that teams can move toward this.

Now, in some ways, I see this as inherently dysfunctional. I explained to all the teams—more than once—that "done" meant tested, and so for gameplay issues, "done" meant playtested. I talked about the relative merits of internal vs external playtesting, but I got a real sense that this was falling on deaf ears. When mentoring one, large team, I am active in the regular maintenance of the task board and discussion of "done", and the students get this; without this, I think the teams fell into a conventional undergraduate perspective about it, that "done" meant something much less rigorous. It is possible, then, that this another case where one method might work well for whole-studio projects and another one for small-team projects.

Along with vision statement articulation, external playtesting, and feature freeze dates, another item I have contemplated including is a style guide. Many of my teams have gone without these, but I have been inspired most recently by Ben Humphrey's talks and blog to think about the UX problems my students face. When there is one team, with good fortune, we have an artist who sets up a palette, fonts, and visual style, but even that is not guaranteed. Still, I think students understand that releasing a game using the engine's default styles is a faux pas. I do not want to push every team toward design bibles, but I think there might be some value in at least articulating a basic style guide early in the process.

I am proud of the work these students did, and honestly, their reliability and hard work enabled me to redirect efforts toward the unexpected picking up of CS431 these past few weeks. I hope they do not feel abandoned, but I consider myself fortunate that I had a CS490 group so consistent that I could trust them to wrap things up on their own.

In closing, I would like to share a final thought about the semester. Due to scheduling constraints and all the chaos of the pandemic, the CS490 class this semester was overloaded with technical people, mostly CS majors. I also had some of the most motivated and talented technical teams I have ever seen, and I actually think that's a separate issue from the first. That is, I had more technical people, but I also had better technical people. It was great to see these students deploy lifetime learning skills to teach themselves how to move forward on these different projects. The only downer for me, then, is that I didn't have these people together to work on a community-engaged project! I cannot help but think of what we could have accomplished if we had been able to all be together, in RB368, with coffee and donuts, meeting up for game nights, working with a community partner. 

Wednesday, May 5, 2021

What We Learned in CS222, Spring 2021

Each of my two sections of CS222 were split into two attendance groups. In the final meetings last week, after something of a sermon on professionalism and responsibility, I led them through a reflective exercise. I prefer to do this during a final exam, with everyone present and the wall papered in giant sticky notes, but alas, the pandemic makes this impossible. I set a timer for eight minutes and invited each student to make a list of what they learned. Then, I opened Google Docs and wrote down any item that the students shouted out.

After doing this for each attendance group, I collated the lists to form a master list of 173 items. These were put into a form, through which I invited the students to vote on the eight that they thought were most important. Unfortunately, only 14 of my 28 students responded, but of those who responded, these were the top items along with their vote counts:
  • Clean Code (10)
  • DRY (6)
  • GitHub (5)
  • Red-Green-Refactor (5)
  • SRP (5)
  • TDD (9)
Clearly, some of these overlap. SRP is a part of Clean Code, and Red-Green-Refactor is a core practice of TDD. The overlaps do not bother me because different articulations have different meanings and connotations to the students. In their final exam, they will be able to choose one of these items and write an essay about how they learned it. These essays are always fun to read, providing me a little window into how students are engaging with the course material.

In the list this year were two items that I do not remember seeing before. One of them was "A professor who teaches differently doesn't make him bad." I was momentarily dumbstruck by the comment, and then I wrote it down and told the student that I would take it as a compliment. It's an interesting comment. It shows that the initial reaction that this student had was that because I teach differently, therefore I must be bad. By extension, then, people who teach "regular" must be good. I assume here that the student meant quality of teaching and not moral quality. Continuing the analysis, the student experienced a change of perspective: somehow, during the semester, something internally changed in the student that made them recognize that their original idea was false. To be clear, the student didn't say that I was doing a good job, only that I was not doing a bad job, but I think it's implied here that my good just looks different from what they considered "conventional good." I am left wondering what was the event or what was the catalyst that allowed the student to change their thinking and whether there are long-term gains from this shift in perspective. If there are, will the student be able to remember CS222 as a turning point?

When I put together the survey, I originally had all the elements in alphabetical order. However, this left that previous item as the first one in the list, and I got to feeling self-conscious about it. Of course there would be items on the list that a student had not seen before because no one is in all attendance groups besides me. However, it felt like I was fishing by putting this one first. I ended up rewording it to "Just because a professor teaches differently doesn't make him bad," which got no votes.

The other item that I do not remember seeing before is "About some of the people who wrote the Agile Manifesto." One of the underlying themes of the class is that software development is for and by people. During the semester, we talk about the Agile Manifesto, and we also separately talk about Robert Martin, Alistair Cockburn, Kent Beck, Ken Schwaber, and Jeff Sutherland. I'm sure I mention that these men were original signatories of the Agile Manifesto in these discussions, but the point is their other work. I am pleased to see that a student recognized that these people are part of the theme of the course. They are not just a bundle of names and facts, which I think is a common way for undergraduates to consider such things, but real people whose work made a difference.


Thursday, April 22, 2021

An unexpected teaching adventure: wrapping up a programming languages course

At the start of the semester, each course in the department had to have a "back-up instructor" designated, just in case the primary instructor fell ill. Usually such cases are handled on an ad hoc basis, but given the global pandemic, the college wanted us to be prepared. Turns out, I was the back-up for Programming Languages, and that professor was rendered unable to finish the course. So, as of last week Thursday, I have taken over two sections of CS431: Programming Languages. 

I am happy to help, although it has taken significant overtime to get stabilized. I now have more than twice as many students than I did before taking over the course, and the original instructor did not leave any plans for moving forward. I taught Programming Languages a few times in grad school, but not since. Naturally, the approach I would have taken, to lead to particular conclusions at the end of the semester, is not the path they took. It feels more like putting together a two-week workshop on the topic rather than wrapping up a semester, except that I am also suddenly in charge of their final exam and final grades.

All that said, over the past week, I have been able to meet my design goals. I put up exercises for Weeks 14 and 15 of the semester, and I designed the final exam. For Week 14, I decided to look at object-orientation, which is covered some in the prerequisite courses but had not yet been revisited in the PL course. In particular, I decided to look at one of the SOLID principles that we don't get to in CS222: Dependency Inversion. The department syllabus includes some objectives dealing with declarative languages and knowledge representation, and so for Week 15, I created an introduction to Prolog. I have always loved Prolog, and it was a treat to get back into it after over a decade away from it.

I decided to release these two weeks of lesson plans under CC BY-SA 4.0, as I have done for my other courses this semester. You can find them at https://github.com/doctor-g/cs431. The final exam is a secret, of course, but it emphasizes the core ideas of these two weeks of activity. Whereas I generally leave my lesson plans on my CS department Web site as an archive, I haven't decided yet if I will keep that repository up indefinitely, migrate it to csweb, or delete it once the semester is over. If you try to follow that link and it's gone, you'll know which route I chose.

Monday, April 12, 2021

The difference a decade makes: Revisiting Morgan's Raid

In summer 2011, my team released Morgan's Raid, an educational game about Indiana's Civil War history. I wrote about it in the early days of this blog, and my post about our use of entity component system architecture remains one of the most visited pages here. The game won the Indiana Historical Society's Outstanding Project Award the year it released, and my collaborator Ronald Morris featured the game in teacher in-service trainings. We wrote papers and a book chapter about it, gave several internal and external presentations, and even adapted it to be playable in Indiana's juvenile detention facility. 

Unfortunately, it has been unplayable for several years. We built the game atop Java Web Start technology, which was deprecated with the release of Java 9 in 2017. Once it became clear that it was beyond the scope of teachers and IT staff to configure machines that would run the game, we took the Web site down, as we did not want to mislead teachers.

Recently, I have been investigating sources of funding to revitalize Morgan's Raid, and I have a few grant proposals currently under review. My evaluation is that the work is beyond the scope of what I can do in an existing course. In fact, I did once have a small section of CS315 many years ago in which the students tried to rewrite the project in Unity, but it was too great a task for them to learn a new engine and understand enough of the original implementation to do the port.

I have spent some time reviewing the original implementation and piecing together how it might be implemented in Godot Engine. I approached it as I did Canning Heroes: Special Edition, but Morgan's Raid is a much more complicated game than Canning Heroes. Also, it was from much longer ago, and I myself don't even have a version of it that I can run, which means I am working from a combination of screenshots, memory, and the original implementation. 

One of first things I noticed from the original implementation is the mess of manually-managed dependencies. The game was programmed using Slick, which was itself built on LWJGL. These required both portable and platform-dependent native dependencies. We also used numerous third-party libraries, particularly from the Apache Commons but also including Guava, EasyMock, and JodaTime. All of these were handled manually within a hand-rolled ant build script. While Maven existed at the time, none of us knew about it; I would not learn about Maven until later projects using PlayN, which required it. These days, my Java projects are all powered by Gradle. This means that if I want to add a dependency, it's a simple matter of tweaking a value in a build script. Looking back at Morgan's Raid reminded me of the reality of "dependency hell" and how good my students have it these days.

The map in Morgan's Raid was represented by 63 512x512 tiles arranged in a 9x7 rectangle. At the time, we had to write the logic to dynamically load only those tiles that were visible so that we would not blow out the client's memory. In my Godot experimentation, I took those original tiles and just loaded them all into the editor at once with no problems. It may also be worth noting that the original implementation was pretty naive. Someone made the whole map in Photoshop by using a paper texture background, and then chopping the large map into these 63 pieces. Much of the map is actually empty aside from this texture. Now, I know it would make a lot more sense to just do that background texturing in-engine with a repeating texture, but we didn't know that at the time. Put another way, it's not just the technology that changed, but my own knowledge and ability to mentor students.

The original implementation used configuration files to specify the locations of the various cities. They are not rendered into the map background but rather overlaid as sprites. All the paths were similarly specified through configuration files, whose data were manually entered based on historic maps and contemporary GPS coordinates. In my demo Godot build, I instead instanced a City scene for each city and just dropped it into the editor. This would have blown the minds of the original Morgan's Raid team, who spent an enormous amount of time transferring data between different representations: if they could just drop a city or draw a path in-editor, our turnaround time would have been much greater.

I remember being very proud of the version control and continuous integration system we set up for Morgan's Raid. The systems administrators got local servers running Mercurial and... something for CI that I cannot remember now. It was my first foray into this kind of devops, and I learned a lot from it. It took a lot of effort from the systems administrators and myself to get this up and running, but now, we can do all of this immediately and for free on GitHub. Like Maven, GitHub also predates our project, but none of us was using it at the time, and it certainly didn't have the de facto standard status that it does now. Indeed, this was back before git had improved its command-line, and I was deep into the Mercurial camp anyway. These days, I can get everyone in a junior-level CS course using continuous integration via GitHub Actions by the second or third week of the semester. 

One of the shortcomings that our research found in the original game is that too many of the mechanics are hidden from the player. There is little feedback to the player about how a choice they are making will impact the future, or how past choices impacted the present. These were intentional decisions made under the reasoning of "fog of war," but our analysis of the game (published in GLS in 2013) showed that this was probably a mistake. I hope that we get a chance not only to re-engineer this game for modern audiences, but also to revisit some of those design decisions. As I recall, we were on the verge of adding the Copperheads and other historically-inspired narrative elements to the game when we had to freeze our features. 

I may continue to tinker with my initial Godot implementation when I find some time during this semester, in hopes that I can then work with a larger team and with dedicated time to complete the effort. This code can be found on GitHub in case anyone wants to take a look, but keep in mind that it's not really set up as a community project, with Issues or any kind of reasonable documentation. 

Saturday, April 10, 2021

Painting Thunderstone Quest Barricades

The Barricades expansion to Thunderstone Quest was released in 2019, and I got my copy from backing the "Back to the Dungeon" Kickstarter campaign. I still remember my surprise at opening the box and finding two miniatures in it. I actually felt a tinge of disappointment: I didn't really want any more minis for this game. They just serve as tokens, but because they are so stylized, it introduces a bit of ludonarrative dissonance that there is no connection between this token and the game. Anyway, I primed these two figures, and then they sat on my painting table for over a year, soaking up positive vibes whenever I looked at them. 

I was going to say that I started them after finishing the Shadowed Paths expansion back in December, but now that I think about it, I think I actually started them before receiving that set. Anyway, the point is that these guys needed to be done, so did finally finish painting them... around December. And then, they sat on my table until today, when I varnished and flocked them. I look forward to putting them into my massive Thunderstone Quest box. (I wrote in my previous painting post about why there's been a big delay in posting any painted minis.)

Enough story—on with the figures!



This is the first one of the two that I painted. Looking over it (you know, for months), I decided it would be fun to try to accent the long robe by doing a warm gradient, and I am happy with how it turned out. The flesh and the pants are similar in tone, and I chose a neutral light grey for the wrappings and scarf so that attention would be drawn to the warm colors. The gold trim and accents I think also help tie it all together. 

Although my other Thunderstone Quest figures are more creatively based, I wasn't very creative with this nor the other one. I just used some basing paste, the mix of flock I used on my Journeys in Middle Earth characters, and some static grass. In retrospect, she would have looked a lot better on something like a desert base: the natural brown and green is an unintended contrast against the rest of the figure.



Here is the other figure, preparing for a heroic downward strike in a manner that I can't help but think this armor could not possibly support. Oh well. I do think the blue, silver, and steel work well together, coupled with the natural brown leather accessories. The color of the satchels pick up his hair and boot colors in a nice way.

A lot of my miniature-painting involves matching colors from game illustrations, but I had to choose my own palettes for these two. I am happy with how both turned out. They were both a bit too small for me to put in the eyes, though, so I decided to leave them with just the shadow of a face rather than dotting in miniscule pupils. 

We played Barricades Mode of Thunderstone Quest just a few times, but we have never desired to go back to it. We always end up either playing a scenario out of the books until the books are done, and then we switch back to Epic mode.

Also, over the past few weeks I have made some improvements and additions to my Thunderstone Quest Randomizer app. Feel free to check it out and let me know what you think. There's a thread about it over on BoardGameGeek, and it's free and open source, so you can check out the repository as well if you're interested.

Painting Runebound: Fall of the Dark Star

When I first saw the Fall of the Dark Star scenario pack for Runebound, I was not impressed. I honestly cannot remember my hesitation, but suffice it to say I did not buy it. Fast forward through the other expansions, dozens of plays with my boys, and rumors that the game will never be reprinted nor receive other expansions, and I ended up buying Fall of the Dark Star on the secondary market. Now, my Runebound Third Edition collection is complete.

Does it matter? Well, not really, but my boys and I played this PvP scenario once so far and really enjoyed it. The other competitive PvE scenarios often end up with an anticlimax, where no one is able to defeat the Big Bad and everyone loses. With Fall of the Dark Star, there will always be a winner. It suffers from the kingmaker problem, where a player who cannot win the game can fairly easily affect who does win, but that's with us: it felt like a big battle royal, which is all we really wanted.

Here is Zyla, the hero (?) from the scenario pack.


I started painting her in November or December, and then she sat on my desk half-completed until today. I had not even picked up my brushes since then. Part of the reason was that the three almost-completed figures on the table were uninspiring. Zyla's sculpt is OK, but I'm finding myself tired of painting the FFG-boardgame-scale miniatures. They look good within the game, but the scale doesn't fit well with other games. When I used Elder Mok as my apprentice in a Frostgrave campaign last Fall, he just looked tiny compared to everyone else, especially the oversized Ajax sorcerer from Massive Darkness, which was my wizard. 

The other reason you haven't seen any painting updates from me is my teaching schedule this semester. My MWF class meets 4-6PM. This means that I get up, make a cup of tea, and am "at work" from around 7:30AM. 4PM feels like quitting time, and in a normal semester, it might be when I'd pull out the paints for an hour's painting before dinner. We're just a few weeks from the end of the semester, and I feel like I still haven't figured out how to manage my work and free time this semester. Maybe it's pandemic fatigue, or maybe I just need to ask not to be assigned such late classes in the future.

Anyway, after a long delay, there's a finished figure. She's very blue and purple. The card art has her holding a green ball of magical energy, which provides some much-needed contrast. The sculpt does not include this, which is sensible, and I did not feel like trying to mold one myself. It leaves her a bit monochromatic, but at least there's some good differences in depth between the near-black, the deep purple, and lighter periwinkle wings. Incidentally, the card art does have her as eyeless with some kind of face mask or helmet on. She's a weird one.

Next painting post should be up soon...